#include "shash.h"
#include "socket-util.h"
#include "unaligned.h"
-#include "vlog.h"
+#include "util.h"
+#include "openvswitch/vlog.h"
VLOG_DEFINE_THIS_MODULE(meta_flow);
return !wc->masks.dp_hash;
case MFF_RECIRC_ID:
return !wc->masks.recirc_id;
+ case MFF_CONJ_ID:
+ return !wc->masks.conj_id;
case MFF_TUN_SRC:
return !wc->masks.tunnel.ip_src;
case MFF_TUN_DST:
case MFF_TUN_TTL:
case MFF_TUN_FLAGS:
return !wc->masks.tunnel.tun_id;
+ case MFF_TUN_GBP_ID:
+ return !wc->masks.tunnel.gbp_id;
+ case MFF_TUN_GBP_FLAGS:
+ return !wc->masks.tunnel.gbp_flags;
case MFF_METADATA:
return !wc->masks.metadata;
case MFF_IN_PORT:
return !wc->masks.regs[mf->id - MFF_REG0];
CASE_MFF_XREGS:
return !flow_get_xreg(&wc->masks, mf->id - MFF_XREG0);
+ case MFF_ACTSET_OUTPUT:
+ return !wc->masks.actset_output;
case MFF_ETH_SRC:
return eth_addr_is_zero(wc->masks.dl_src);
return is_ip_any(flow);
case MFP_TCP:
- return is_ip_any(flow) && flow->nw_proto == IPPROTO_TCP;
+ return is_ip_any(flow) && flow->nw_proto == IPPROTO_TCP
+ && !(flow->nw_frag & FLOW_NW_FRAG_LATER);
case MFP_UDP:
- return is_ip_any(flow) && flow->nw_proto == IPPROTO_UDP;
+ return is_ip_any(flow) && flow->nw_proto == IPPROTO_UDP
+ && !(flow->nw_frag & FLOW_NW_FRAG_LATER);
case MFP_SCTP:
- return is_ip_any(flow) && flow->nw_proto == IPPROTO_SCTP;
+ return is_ip_any(flow) && flow->nw_proto == IPPROTO_SCTP
+ && !(flow->nw_frag & FLOW_NW_FRAG_LATER);
case MFP_ICMPV4:
return is_icmpv4(flow);
case MFP_ICMPV6:
case MFP_SCTP:
case MFP_ICMPV4:
case MFP_ICMPV6:
+ /* nw_frag always unwildcarded. */
mask->nw_proto = 0xff;
/* Fall through. */
case MFP_ARP:
}
}
+/* Set bits of 'bm' corresponding to the field 'mf' and it's prerequisities. */
+void
+mf_bitmap_set_field_and_prereqs(const struct mf_field *mf, struct mf_bitmap *bm)
+{
+ bitmap_set1(bm->bm, mf->id);
+
+ switch (mf->prereqs) {
+ case MFP_ND:
+ case MFP_ND_SOLICIT:
+ case MFP_ND_ADVERT:
+ bitmap_set1(bm->bm, MFF_TCP_SRC);
+ bitmap_set1(bm->bm, MFF_TCP_DST);
+ /* Fall through. */
+ case MFP_TCP:
+ case MFP_UDP:
+ case MFP_SCTP:
+ case MFP_ICMPV4:
+ case MFP_ICMPV6:
+ /* nw_frag always unwildcarded. */
+ bitmap_set1(bm->bm, MFF_IP_PROTO);
+ /* Fall through. */
+ case MFP_ARP:
+ case MFP_IPV4:
+ case MFP_IPV6:
+ case MFP_MPLS:
+ case MFP_IP_ANY:
+ bitmap_set1(bm->bm, MFF_ETH_TYPE);
+ break;
+ case MFP_VLAN_VID:
+ bitmap_set1(bm->bm, MFF_VLAN_TCI);
+ break;
+ case MFP_NONE:
+ break;
+ }
+}
/* Returns true if 'value' may be a valid value *as part of a masked match*,
* false otherwise.
switch (mf->id) {
case MFF_DP_HASH:
case MFF_RECIRC_ID:
+ case MFF_CONJ_ID:
case MFF_TUN_ID:
case MFF_TUN_SRC:
case MFF_TUN_DST:
case MFF_TUN_TOS:
case MFF_TUN_TTL:
case MFF_TUN_FLAGS:
+ case MFF_TUN_GBP_ID:
+ case MFF_TUN_GBP_FLAGS:
case MFF_METADATA:
case MFF_IN_PORT:
case MFF_SKB_PRIORITY:
case MFF_ND_TLL:
return true;
- case MFF_IN_PORT_OXM: {
+ case MFF_IN_PORT_OXM:
+ case MFF_ACTSET_OUTPUT: {
ofp_port_t port;
return !ofputil_port_from_ofp11(value->be32, &port);
}
case MFF_RECIRC_ID:
value->be32 = htonl(flow->recirc_id);
break;
+ case MFF_CONJ_ID:
+ value->be32 = htonl(flow->conj_id);
+ break;
case MFF_TUN_ID:
value->be64 = flow->tunnel.tun_id;
break;
case MFF_TUN_FLAGS:
value->be16 = htons(flow->tunnel.flags);
break;
+ case MFF_TUN_GBP_ID:
+ value->be16 = flow->tunnel.gbp_id;
+ break;
+ case MFF_TUN_GBP_FLAGS:
+ value->u8 = flow->tunnel.gbp_flags;
+ break;
case MFF_TUN_TTL:
value->u8 = flow->tunnel.ip_ttl;
break;
case MFF_IN_PORT_OXM:
value->be32 = ofputil_port_to_ofp11(flow->in_port.ofp_port);
break;
+ case MFF_ACTSET_OUTPUT:
+ value->be32 = ofputil_port_to_ofp11(flow->actset_output);
+ break;
case MFF_SKB_PRIORITY:
value->be32 = htonl(flow->skb_priority);
case MFF_RECIRC_ID:
match_set_recirc_id(match, ntohl(value->be32));
break;
+ case MFF_CONJ_ID:
+ match_set_conj_id(match, ntohl(value->be32));
+ break;
case MFF_TUN_ID:
match_set_tun_id(match, value->be64);
break;
case MFF_TUN_FLAGS:
match_set_tun_flags(match, ntohs(value->be16));
break;
+ case MFF_TUN_GBP_ID:
+ match_set_tun_gbp_id(match, value->be16);
+ break;
+ case MFF_TUN_GBP_FLAGS:
+ match_set_tun_gbp_flags(match, value->u8);
+ break;
case MFF_TUN_TOS:
match_set_tun_tos(match, value->u8);
break;
match_set_in_port(match, port);
break;
}
+ case MFF_ACTSET_OUTPUT: {
+ ofp_port_t port;
+ ofputil_port_from_ofp11(value->be32, &port);
+ match_set_actset_output(match, port);
+ break;
+ }
case MFF_SKB_PRIORITY:
match_set_skb_priority(match, ntohl(value->be32));
case MFF_RECIRC_ID:
flow->recirc_id = ntohl(value->be32);
break;
+ case MFF_CONJ_ID:
+ flow->conj_id = ntohl(value->be32);
+ break;
case MFF_TUN_ID:
flow->tunnel.tun_id = value->be64;
break;
case MFF_TUN_FLAGS:
flow->tunnel.flags = ntohs(value->be16);
break;
+ case MFF_TUN_GBP_ID:
+ flow->tunnel.gbp_id = value->be16;
+ break;
+ case MFF_TUN_GBP_FLAGS:
+ flow->tunnel.gbp_flags = value->u8;
+ break;
case MFF_TUN_TOS:
flow->tunnel.ip_tos = value->u8;
break;
flow->in_port.ofp_port = u16_to_ofp(ntohs(value->be16));
break;
- case MFF_IN_PORT_OXM: {
- ofp_port_t port;
- ofputil_port_from_ofp11(value->be32, &port);
- flow->in_port.ofp_port = port;
+ case MFF_IN_PORT_OXM:
+ ofputil_port_from_ofp11(value->be32, &flow->in_port.ofp_port);
+ break;
+ case MFF_ACTSET_OUTPUT:
+ ofputil_port_from_ofp11(value->be32, &flow->actset_output);
break;
- }
case MFF_SKB_PRIORITY:
flow->skb_priority = ntohl(value->be32);
break;
case MFF_IPV6_LABEL:
- flow->ipv6_label = value->be32 & ~htonl(IPV6_LABEL_MASK);
+ flow->ipv6_label = value->be32 & htonl(IPV6_LABEL_MASK);
break;
case MFF_IP_PROTO:
match->flow.recirc_id = 0;
match->wc.masks.recirc_id = 0;
break;
+ case MFF_CONJ_ID:
+ match->flow.conj_id = 0;
+ match->wc.masks.conj_id = 0;
+ break;
case MFF_TUN_ID:
match_set_tun_id_masked(match, htonll(0), htonll(0));
break;
case MFF_TUN_FLAGS:
match_set_tun_flags_masked(match, 0, 0);
break;
+ case MFF_TUN_GBP_ID:
+ match_set_tun_gbp_id_masked(match, 0, 0);
+ break;
+ case MFF_TUN_GBP_FLAGS:
+ match_set_tun_gbp_flags_masked(match, 0, 0);
+ break;
case MFF_TUN_TOS:
match_set_tun_tos_masked(match, 0, 0);
break;
match->flow.in_port.ofp_port = 0;
match->wc.masks.in_port.ofp_port = 0;
break;
+ case MFF_ACTSET_OUTPUT:
+ match->flow.actset_output = 0;
+ match->wc.masks.actset_output = 0;
+ break;
case MFF_SKB_PRIORITY:
match->flow.skb_priority = 0;
switch (mf->id) {
case MFF_RECIRC_ID:
+ case MFF_CONJ_ID:
case MFF_IN_PORT:
case MFF_IN_PORT_OXM:
+ case MFF_ACTSET_OUTPUT:
case MFF_SKB_PRIORITY:
case MFF_ETH_TYPE:
case MFF_DL_VLAN:
case MFF_TUN_FLAGS:
match_set_tun_flags_masked(match, ntohs(value->be16), ntohs(mask->be16));
break;
+ case MFF_TUN_GBP_ID:
+ match_set_tun_gbp_id_masked(match, value->be16, mask->be16);
+ break;
+ case MFF_TUN_GBP_FLAGS:
+ match_set_tun_gbp_flags_masked(match, value->u8, mask->u8);
+ break;
case MFF_TUN_TTL:
match_set_tun_ttl_masked(match, value->u8, mask->u8);
break;
/* OK. */
} else if (ovs_scan(s, IP_SCAN_FMT"/%d", IP_SCAN_ARGS(ip), &prefix)) {
if (prefix <= 0 || prefix > 32) {
- return xasprintf("%s: network prefix bits not between 1 and "
+ return xasprintf("%s: network prefix bits not between 0 and "
"32", s);
- } else if (prefix == 32) {
- *mask = OVS_BE32_MAX;
- } else {
- *mask = htonl(((1u << prefix) - 1) << (32 - prefix));
}
+ *mask = be32_prefix_mask(prefix);
} else if (ovs_scan(s, IP_SCAN_FMT, IP_SCAN_ARGS(ip))) {
*mask = OVS_BE32_MAX;
} else {
}
ds_put_char(s, '0');
}
+
+void
+field_array_set(enum mf_field_id id, const union mf_value *value,
+ struct field_array *fa)
+{
+ ovs_assert(id < MFF_N_IDS);
+ bitmap_set1(fa->used.bm, id);
+ fa->value[id] = *value;
+}