OXM: Allow masking of IPv6 Flow Label
[openvswitch] / lib / meta-flow.c
index 8e7d4fc8ae50d698d5f28d07340296bacb120f1b..8bc3d1a59e89d6bc057ee5a74c99e5fa72b0a4cd 100644 (file)
@@ -222,7 +222,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
     {
         MFF_IPV6_LABEL, "ipv6_label", NULL,
         4, 20,
-        MFM_NONE, FWW_IPV6_LABEL,
+        MFM_FULLY, 0,
         MFS_HEXADECIMAL,
         MFP_IPV6,
         false,
@@ -561,7 +561,6 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
     case MFF_IP_DSCP:
     case MFF_IP_ECN:
     case MFF_IP_TTL:
-    case MFF_IPV6_LABEL:
     case MFF_ARP_OP:
     case MFF_ARP_SHA:
     case MFF_ARP_THA:
@@ -600,6 +599,9 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
     case MFF_IPV6_DST:
         return ipv6_mask_is_any(&wc->ipv6_dst_mask);
 
+    case MFF_IPV6_LABEL:
+        return !wc->ipv6_label_mask;
+
     case MFF_ND_TARGET:
         return ipv6_mask_is_any(&wc->nd_target_mask);
 
@@ -998,17 +1000,11 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
         break;
 
     case MFF_TCP_SRC:
-        value->be16 = flow->tp_src;
-        break;
-
-    case MFF_TCP_DST:
-        value->be16 = flow->tp_dst;
-        break;
-
     case MFF_UDP_SRC:
         value->be16 = flow->tp_src;
         break;
 
+    case MFF_TCP_DST:
     case MFF_UDP_DST:
         value->be16 = flow->tp_dst;
         break;
@@ -1143,17 +1139,11 @@ mf_set_value(const struct mf_field *mf,
         break;
 
     case MFF_TCP_SRC:
-        cls_rule_set_tp_src(rule, value->be16);
-        break;
-
-    case MFF_TCP_DST:
-        cls_rule_set_tp_dst(rule, value->be16);
-        break;
-
     case MFF_UDP_SRC:
         cls_rule_set_tp_src(rule, value->be16);
         break;
 
+    case MFF_TCP_DST:
     case MFF_UDP_DST:
         cls_rule_set_tp_dst(rule, value->be16);
         break;
@@ -1403,7 +1393,7 @@ mf_set_wild(const struct mf_field *mf, struct cls_rule *rule)
         break;
 
     case MFF_IPV6_LABEL:
-        rule->wc.wildcards |= FWW_IPV6_LABEL;
+        rule->wc.ipv6_label_mask = 0;
         rule->flow.ipv6_label = 0;
         break;
 
@@ -1505,7 +1495,6 @@ mf_set(const struct mf_field *mf,
     case MFF_ETH_TYPE:
     case MFF_VLAN_VID:
     case MFF_VLAN_PCP:
-    case MFF_IPV6_LABEL:
     case MFF_IP_PROTO:
     case MFF_IP_TTL:
     case MFF_IP_DSCP:
@@ -1561,6 +1550,14 @@ mf_set(const struct mf_field *mf,
         cls_rule_set_ipv6_dst_masked(rule, &value->ipv6, &mask->ipv6);
         break;
 
+    case MFF_IPV6_LABEL:
+        if ((mask->be32 & htonl(IPV6_LABEL_MASK)) == htonl(IPV6_LABEL_MASK)) {
+            mf_set_value(mf, value, rule);
+        } else {
+            cls_rule_set_ipv6_label_masked(rule, value->be32, mask->be32);
+        }
+        break;
+
     case MFF_ND_TARGET:
         cls_rule_set_nd_target_masked(rule, &value->ipv6, &mask->ipv6);
         break;
@@ -2075,13 +2072,7 @@ mf_format(const struct mf_field *mf,
 \f
 /* Makes subfield 'sf' within 'rule' exactly match the 'sf->n_bits'
  * least-significant bits in 'x'.
- *
- * See mf_set_subfield() for an example.
- *
- * The difference between this function and mf_set_subfield() is that the
- * latter function can only handle subfields up to 64 bits wide, whereas this
- * one handles the general case.  On the other hand, mf_set_subfield() is
- * arguably easier to use. */
+ */
 void
 mf_write_subfield(const struct mf_subfield *sf, const union mf_subvalue *x,
                   struct cls_rule *rule)
@@ -2095,80 +2086,6 @@ mf_write_subfield(const struct mf_subfield *sf, const union mf_subvalue *x,
     mf_set(field, &value, &mask, rule);
 }
 
-/* Makes subfield 'sf' within 'rule' exactly match the 'sf->n_bits'
- * least-significant bits of 'x'.
- *
- * Example: suppose that 'sf->field' is originally the following 2-byte field
- * in 'rule':
- *
- *     value == 0xe00a == 2#1110000000001010
- *      mask == 0xfc3f == 2#1111110000111111
- *
- * The call mf_set_subfield(sf, 0x55, 8, 7, rule), where sf->ofs == 8 and
- * sf->n_bits == 7 would have the following effect (note that 0x55 is
- * 2#1010101):
- *
- *     value == 0xd50a == 2#1101010100001010
- *      mask == 0xff3f == 2#1111111100111111
- *                           ^^^^^^^ affected bits
- *
- * The caller is responsible for ensuring that the result will be a valid
- * wildcard pattern for 'sf->field'.  The caller is responsible for ensuring
- * that 'rule' meets 'sf->field''s prerequisites. */
-void
-mf_set_subfield(const struct mf_subfield *sf, uint64_t x,
-                struct cls_rule *rule)
-{
-    const struct mf_field *field = sf->field;
-    unsigned int n_bits = sf->n_bits;
-    unsigned int ofs = sf->ofs;
-
-    if (ofs == 0 && field->n_bytes * 8 == n_bits) {
-        union mf_value value;
-        int i;
-
-        for (i = field->n_bytes - 1; i >= 0; i--) {
-            ((uint8_t *) &value)[i] = x;
-            x >>= 8;
-        }
-        mf_set_value(field, &value, rule);
-    } else {
-        union mf_value value, mask;
-        uint8_t *vp = (uint8_t *) &value;
-        uint8_t *mp = (uint8_t *) &mask;
-
-        mf_get(field, rule, &value, &mask);
-        bitwise_put(x,          vp, field->n_bytes, ofs, n_bits);
-        bitwise_put(UINT64_MAX, mp, field->n_bytes, ofs, n_bits);
-        mf_set(field, &value, &mask, rule);
-    }
-}
-
-/* Similar to mf_set_subfield() but modifies only a flow, not a cls_rule. */
-void
-mf_set_subfield_value(const struct mf_subfield *sf, uint64_t x,
-                      struct flow *flow)
-{
-    const struct mf_field *field = sf->field;
-    unsigned int n_bits = sf->n_bits;
-    unsigned int ofs = sf->ofs;
-    union mf_value value;
-
-    if (ofs == 0 && field->n_bytes * 8 == n_bits) {
-        int i;
-
-        for (i = field->n_bytes - 1; i >= 0; i--) {
-            ((uint8_t *) &value)[i] = x;
-            x >>= 8;
-        }
-        mf_set_flow_value(field, &value, flow);
-    } else {
-        mf_get_value(field, flow, &value);
-        bitwise_put(x, &value, field->n_bytes, ofs, n_bits);
-        mf_set_flow_value(field, &value, flow);
-    }
-}
-
 /* Initializes 'x' to the value of 'sf' within 'flow'.  'sf' must be valid for
  * reading 'flow', e.g. as checked by mf_check_src(). */
 void