Implement hash fields select group
[cascardo/ovs.git] / lib / meta-flow.c
index 7871545..124b525 100644 (file)
@@ -34,7 +34,8 @@
 #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);
 
@@ -107,6 +108,8 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
         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:
@@ -116,6 +119,10 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
     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:
@@ -129,6 +136,8 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
         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);
@@ -272,11 +281,14 @@ mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow)
         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:
@@ -322,6 +334,7 @@ mf_mask_field_and_prereqs(const struct mf_field *mf, struct flow *mask)
     case MFP_SCTP:
     case MFP_ICMPV4:
     case MFP_ICMPV6:
+        /* nw_frag always unwildcarded. */
         mask->nw_proto = 0xff;
         /* Fall through. */
     case MFP_ARP:
@@ -339,6 +352,41 @@ mf_mask_field_and_prereqs(const struct mf_field *mf, struct flow *mask)
     }
 }
 
+/* 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.
@@ -356,12 +404,15 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
     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:
@@ -397,7 +448,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
     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);
     }
@@ -456,6 +508,9 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
     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;
@@ -468,6 +523,12 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
     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;
@@ -485,6 +546,9 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
     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);
@@ -658,6 +722,9 @@ mf_set_value(const struct mf_field *mf,
     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;
@@ -670,6 +737,12 @@ mf_set_value(const struct mf_field *mf,
     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;
@@ -691,6 +764,12 @@ mf_set_value(const struct mf_field *mf,
         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));
@@ -881,6 +960,9 @@ mf_set_flow_value(const struct mf_field *mf,
     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;
@@ -893,6 +975,12 @@ mf_set_flow_value(const struct mf_field *mf,
     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;
@@ -908,12 +996,12 @@ mf_set_flow_value(const struct mf_field *mf,
         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);
@@ -988,7 +1076,7 @@ mf_set_flow_value(const struct mf_field *mf,
         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:
@@ -1135,6 +1223,10 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
         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;
@@ -1147,6 +1239,12 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
     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;
@@ -1163,6 +1261,10 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
         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;
@@ -1352,8 +1454,10 @@ mf_set(const struct mf_field *mf,
 
     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:
@@ -1389,6 +1493,12 @@ mf_set(const struct mf_field *mf,
     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;
@@ -1648,13 +1758,10 @@ mf_from_ipv4_string(const struct mf_field *mf, const char *s,
         /* 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 {
@@ -2206,3 +2313,12 @@ mf_format_subvalue(const union mf_subvalue *subvalue, struct ds *s)
     }
     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;
+}