Merge remote-tracking branch 'origin/ovs-dev' into bsd-port
[sliver-openvswitch.git] / lib / meta-flow.c
index b3a4bff..8e7d4fc 100644 (file)
@@ -54,7 +54,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         MFP_NONE,
         true,
         NXM_NX_TUN_ID, "NXM_NX_TUN_ID",
-        0, NULL,
+        NXM_NX_TUN_ID, "NXM_NX_TUN_ID",
+    }, {
+        MFF_METADATA, "metadata", NULL,
+        MF_FIELD_SIZES(be64),
+        MFM_FULLY, 0,
+        MFS_HEXADECIMAL,
+        MFP_NONE,
+        true,
+        OXM_OF_METADATA, "OXM_OF_METADATA",
+        OXM_OF_METADATA, "OXM_OF_METADATA",
     }, {
         MFF_IN_PORT, "in_port", NULL,
         MF_FIELD_SIZES(be16),
@@ -74,9 +83,8 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         MFS_HEXADECIMAL,                        \
         MFP_NONE,                               \
         true,                                   \
-        NXM_NX_REG(IDX),                        \
-        "NXM_NX_REG" #IDX,                      \
-        0, NULL,                                \
+        NXM_NX_REG(IDX), "NXM_NX_REG" #IDX,     \
+        NXM_NX_REG(IDX), "NXM_NX_REG" #IDX,     \
     }
 #if FLOW_N_REGS > 0
     REGISTER(0),
@@ -147,7 +155,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         MFP_NONE,
         true,
         NXM_OF_VLAN_TCI, "NXM_OF_VLAN_TCI",
-        0, NULL,
+        NXM_OF_VLAN_TCI, "NXM_OF_VLAN_TCI",
     }, {
         MFF_VLAN_VID, "dl_vlan", NULL,
         sizeof(ovs_be16), 12,
@@ -155,7 +163,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         MFS_DECIMAL,
         MFP_NONE,
         true,
-        0, NULL,
+        OXM_OF_VLAN_VID, "OXM_OF_VLAN_VID",
         OXM_OF_VLAN_VID, "OXM_OF_VLAN_VID",
     }, {
         MFF_VLAN_PCP, "dl_vlan_pcp", NULL,
@@ -164,7 +172,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         MFS_DECIMAL,
         MFP_NONE,
         true,
-        0, NULL,
+        OXM_OF_VLAN_PCP, "OXM_OF_VLAN_PCP",
         OXM_OF_VLAN_PCP, "OXM_OF_VLAN_PCP",
     },
 
@@ -257,7 +265,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         MFP_IP_ANY,
         true,
         NXM_NX_IP_TTL, "NXM_NX_IP_TTL",
-        0, NULL,
+        NXM_NX_IP_TTL, "NXM_NX_IP_TTL",
     }, {
         MFF_IP_FRAG, "ip_frag", NULL,
         1, 2,
@@ -266,7 +274,7 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
         MFP_IP_ANY,
         false,
         NXM_NX_IP_FRAG, "NXM_NX_IP_FRAG",
-        0, NULL,
+        NXM_NX_IP_FRAG, "NXM_NX_IP_FRAG",
     },
 
     {
@@ -434,19 +442,22 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
     }
 };
 
+/* Maps an NXM or OXM header value to an mf_field. */
 struct nxm_field {
-    struct hmap_node hmap_node;
-    uint32_t nxm_header;
+    struct hmap_node hmap_node; /* In 'all_fields' hmap. */
+    uint32_t header;            /* NXM or OXM header value. */
     const struct mf_field *mf;
 };
 
-static struct hmap all_nxm_fields = HMAP_INITIALIZER(&all_nxm_fields);
-static struct hmap all_oxm_fields = HMAP_INITIALIZER(&all_oxm_fields);
+/* Contains 'struct nxm_field's. */
+static struct hmap all_fields = HMAP_INITIALIZER(&all_fields);
 
 /* Rate limit for parse errors.  These always indicate a bug in an OpenFlow
  * controller and so there's not much point in showing a lot of them. */
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
+const struct mf_field *mf_from_nxm_header__(uint32_t header);
+
 /* Returns the field with the given 'id'. */
 const struct mf_field *
 mf_from_id(enum mf_field_id id)
@@ -477,54 +488,27 @@ mf_from_name(const char *name)
 }
 
 static void
-add_nxm_field(struct hmap *all_fields, uint32_t nxm_header,
-              const struct mf_field *mf)
+add_nxm_field(uint32_t header, const struct mf_field *mf)
 {
     struct nxm_field *f;
 
     f = xmalloc(sizeof *f);
-    hmap_insert(all_fields, &f->hmap_node, hash_int(nxm_header, 0));
-    f->nxm_header = nxm_header;
+    hmap_insert(&all_fields, &f->hmap_node, hash_int(header, 0));
+    f->header = header;
     f->mf = mf;
 }
 
-static struct hmap *
-get_all_fields(uint32_t header)
-{
-        return IS_OXM_HEADER(header) ? &all_oxm_fields : &all_nxm_fields;
-}
-
 static void
 nxm_init_add_field(const struct mf_field *mf, uint32_t header)
 {
-    struct hmap *all_fields = get_all_fields(header);
-
-    if (!header) {
-        return;
-    }
-    add_nxm_field(all_fields, header, mf);
-    if (mf->maskable == MFM_NONE) {
-        return;
-    }
-    add_nxm_field(all_fields, NXM_MAKE_WILD_HEADER(header), mf);
-}
-
-#ifndef NDEBUG
-static void
-nxm_init_verify_field(const struct mf_field *mf, uint32_t header)
-{
-    if (!header) {
-        return;
-    }
-    assert(mf_from_nxm_header(header) == mf);
-    /* Some OXM fields are not maskable while their NXM
-     * counterparts are, just skip this check for now */
-    if (mf->maskable == MFM_NONE || IS_OXM_HEADER(header)) {
-        return;
+    if (header) {
+        assert(!mf_from_nxm_header__(header));
+        add_nxm_field(header, mf);
+        if (mf->maskable != MFM_NONE) {
+            add_nxm_field(NXM_MAKE_WILD_HEADER(header), mf);
+        }
     }
-    assert(mf_from_nxm_header(NXM_MAKE_WILD_HEADER(mf->nxm_header)) == mf);
 }
-#endif
 
 static void
 nxm_init(void)
@@ -533,30 +517,28 @@ nxm_init(void)
 
     for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) {
         nxm_init_add_field(mf, mf->nxm_header);
-        nxm_init_add_field(mf, mf->oxm_header);
-    }
-
-#ifndef NDEBUG
-    /* Verify that the header values are unique. */
-    for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) {
-        nxm_init_verify_field(mf, mf->nxm_header);
-        nxm_init_verify_field(mf, mf->oxm_header);
+        if (mf->oxm_header != mf->nxm_header) {
+            nxm_init_add_field(mf, mf->oxm_header);
+        }
     }
-#endif
 }
 
 const struct mf_field *
 mf_from_nxm_header(uint32_t header)
 {
-    const struct nxm_field *f;
-    struct hmap *all_fields = get_all_fields(header);
-
-    if (hmap_is_empty(all_fields)) {
+    if (hmap_is_empty(&all_fields)) {
         nxm_init();
     }
+    return mf_from_nxm_header__(header);
+}
 
-    HMAP_FOR_EACH_IN_BUCKET (f, hmap_node, hash_int(header, 0), all_fields) {
-        if (f->nxm_header == header) {
+const struct mf_field *
+mf_from_nxm_header__(uint32_t header)
+{
+    const struct nxm_field *f;
+
+    HMAP_FOR_EACH_IN_BUCKET (f, hmap_node, hash_int(header, 0), &all_fields) {
+        if (f->header == header) {
             return f->mf;
         }
     }
@@ -590,34 +572,10 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
 
     case MFF_TUN_ID:
         return !wc->tun_id_mask;
+    case MFF_METADATA:
+        return !wc->metadata_mask;
 
-#if FLOW_N_REGS > 0
-    case MFF_REG0:
-#endif
-#if FLOW_N_REGS > 1
-    case MFF_REG1:
-#endif
-#if FLOW_N_REGS > 2
-    case MFF_REG2:
-#endif
-#if FLOW_N_REGS > 3
-    case MFF_REG3:
-#endif
-#if FLOW_N_REGS > 4
-    case MFF_REG4:
-#endif
-#if FLOW_N_REGS > 5
-    case MFF_REG5:
-#endif
-#if FLOW_N_REGS > 6
-    case MFF_REG6:
-#endif
-#if FLOW_N_REGS > 7
-    case MFF_REG7:
-#endif
-#if FLOW_N_REGS > 8
-#error
-#endif
+    CASE_MFF_REGS:
         return !wc->reg_masks[mf->id - MFF_REG0];
 
     case MFF_ETH_SRC:
@@ -700,34 +658,11 @@ mf_get_mask(const struct mf_field *mf, const struct flow_wildcards *wc,
     case MFF_TUN_ID:
         mask->be64 = wc->tun_id_mask;
         break;
+    case MFF_METADATA:
+        mask->be64 = wc->metadata_mask;
+        break;
 
-#if FLOW_N_REGS > 0
-    case MFF_REG0:
-#endif
-#if FLOW_N_REGS > 1
-    case MFF_REG1:
-#endif
-#if FLOW_N_REGS > 2
-    case MFF_REG2:
-#endif
-#if FLOW_N_REGS > 3
-    case MFF_REG3:
-#endif
-#if FLOW_N_REGS > 4
-    case MFF_REG4:
-#endif
-#if FLOW_N_REGS > 5
-    case MFF_REG5:
-#endif
-#if FLOW_N_REGS > 6
-    case MFF_REG6:
-#endif
-#if FLOW_N_REGS > 7
-    case MFF_REG7:
-#endif
-#if FLOW_N_REGS > 8
-#error
-#endif
+    CASE_MFF_REGS:
         mask->be32 = htonl(wc->reg_masks[mf->id - MFF_REG0]);
         break;
 
@@ -899,34 +834,9 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
 {
     switch (mf->id) {
     case MFF_TUN_ID:
+    case MFF_METADATA:
     case MFF_IN_PORT:
-#if FLOW_N_REGS > 0
-    case MFF_REG0:
-#endif
-#if FLOW_N_REGS > 1
-    case MFF_REG1:
-#endif
-#if FLOW_N_REGS > 2
-    case MFF_REG2:
-#endif
-#if FLOW_N_REGS > 3
-    case MFF_REG3:
-#endif
-#if FLOW_N_REGS > 4
-    case MFF_REG4:
-#endif
-#if FLOW_N_REGS > 5
-    case MFF_REG5:
-#endif
-#if FLOW_N_REGS > 6
-    case MFF_REG6:
-#endif
-#if FLOW_N_REGS > 7
-    case MFF_REG7:
-#endif
-#if FLOW_N_REGS > 8
-#error
-#endif
+    CASE_MFF_REGS:
     case MFF_ETH_SRC:
     case MFF_ETH_DST:
     case MFF_ETH_TYPE:
@@ -968,7 +878,7 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
         return !(value->be16 & htons(VLAN_CFI | VLAN_PCP_MASK));
 
     case MFF_VLAN_PCP:
-        return !(value->u8 & ~7);
+        return !(value->u8 & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT));
 
     case MFF_IPV6_LABEL:
         return !(value->be32 & ~htonl(IPV6_LABEL_MASK));
@@ -989,38 +899,15 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
     case MFF_TUN_ID:
         value->be64 = flow->tun_id;
         break;
+    case MFF_METADATA:
+        value->be64 = flow->metadata;
+        break;
 
     case MFF_IN_PORT:
         value->be16 = htons(flow->in_port);
         break;
 
-#if FLOW_N_REGS > 0
-    case MFF_REG0:
-#endif
-#if FLOW_N_REGS > 1
-    case MFF_REG1:
-#endif
-#if FLOW_N_REGS > 2
-    case MFF_REG2:
-#endif
-#if FLOW_N_REGS > 3
-    case MFF_REG3:
-#endif
-#if FLOW_N_REGS > 4
-    case MFF_REG4:
-#endif
-#if FLOW_N_REGS > 5
-    case MFF_REG5:
-#endif
-#if FLOW_N_REGS > 6
-    case MFF_REG6:
-#endif
-#if FLOW_N_REGS > 7
-    case MFF_REG7:
-#endif
-#if FLOW_N_REGS > 8
-#error
-#endif
+    CASE_MFF_REGS:
         value->be32 = htonl(flow->regs[mf->id - MFF_REG0]);
         break;
 
@@ -1157,42 +1044,17 @@ mf_set_value(const struct mf_field *mf,
     case MFF_TUN_ID:
         cls_rule_set_tun_id(rule, value->be64);
         break;
+    case MFF_METADATA:
+        cls_rule_set_metadata(rule, value->be64);
+        break;
 
     case MFF_IN_PORT:
         cls_rule_set_in_port(rule, ntohs(value->be16));
         break;
 
-#if FLOW_N_REGS > 0
-    case MFF_REG0:
-#endif
-#if FLOW_N_REGS > 1
-    case MFF_REG1:
-#endif
-#if FLOW_N_REGS > 2
-    case MFF_REG2:
-#endif
-#if FLOW_N_REGS > 3
-    case MFF_REG3:
-#endif
-#if FLOW_N_REGS > 4
-    case MFF_REG4:
-#endif
-#if FLOW_N_REGS > 5
-    case MFF_REG5:
-#endif
-#if FLOW_N_REGS > 6
-    case MFF_REG6:
-#endif
-#if FLOW_N_REGS > 7
-    case MFF_REG7:
-#endif
-#if FLOW_N_REGS > 8
-#error
-#endif
-#if FLOW_N_REGS > 0
+    CASE_MFF_REGS:
         cls_rule_set_reg(rule, mf->id - MFF_REG0, ntohl(value->be32));
         break;
-#endif
 
     case MFF_ETH_SRC:
         cls_rule_set_dl_src(rule, value->mac);
@@ -1327,42 +1189,17 @@ mf_set_flow_value(const struct mf_field *mf,
     case MFF_TUN_ID:
         flow->tun_id = value->be64;
         break;
+    case MFF_METADATA:
+        flow->metadata = value->be64;
+        break;
 
     case MFF_IN_PORT:
         flow->in_port = ntohs(value->be16);
         break;
 
-#if FLOW_N_REGS > 0
-    case MFF_REG0:
-#endif
-#if FLOW_N_REGS > 1
-    case MFF_REG1:
-#endif
-#if FLOW_N_REGS > 2
-    case MFF_REG2:
-#endif
-#if FLOW_N_REGS > 3
-    case MFF_REG3:
-#endif
-#if FLOW_N_REGS > 4
-    case MFF_REG4:
-#endif
-#if FLOW_N_REGS > 5
-    case MFF_REG5:
-#endif
-#if FLOW_N_REGS > 6
-    case MFF_REG6:
-#endif
-#if FLOW_N_REGS > 7
-    case MFF_REG7:
-#endif
-#if FLOW_N_REGS > 8
-#error
-#endif
-#if FLOW_N_REGS > 0
+    CASE_MFF_REGS:
         flow->regs[mf->id - MFF_REG0] = ntohl(value->be32);
         break;
-#endif
 
     case MFF_ETH_SRC:
         memcpy(flow->dl_src, value->mac, ETH_ADDR_LEN);
@@ -1506,55 +1343,17 @@ mf_set_wild(const struct mf_field *mf, struct cls_rule *rule)
     case MFF_TUN_ID:
         cls_rule_set_tun_id_masked(rule, htonll(0), htonll(0));
         break;
+    case MFF_METADATA:
+        cls_rule_set_metadata_masked(rule, htonll(0), htonll(0));
 
     case MFF_IN_PORT:
         rule->wc.wildcards |= FWW_IN_PORT;
         rule->flow.in_port = 0;
         break;
 
-#if FLOW_N_REGS > 0
-    case MFF_REG0:
-        cls_rule_set_reg_masked(rule, 0, 0, 0);
-        break;
-#endif
-#if FLOW_N_REGS > 1
-    case MFF_REG1:
-        cls_rule_set_reg_masked(rule, 1, 0, 0);
-        break;
-#endif
-#if FLOW_N_REGS > 2
-    case MFF_REG2:
-        cls_rule_set_reg_masked(rule, 2, 0, 0);
-        break;
-#endif
-#if FLOW_N_REGS > 3
-    case MFF_REG3:
-        cls_rule_set_reg_masked(rule, 3, 0, 0);
+    CASE_MFF_REGS:
+        cls_rule_set_reg_masked(rule, mf->id - MFF_REG0, 0, 0);
         break;
-#endif
-#if FLOW_N_REGS > 4
-    case MFF_REG4:
-        cls_rule_set_reg_masked(rule, 4, 0, 0);
-        break;
-#endif
-#if FLOW_N_REGS > 5
-    case MFF_REG5:
-        cls_rule_set_reg_masked(rule, 5, 0, 0);
-        break;
-#endif
-#if FLOW_N_REGS > 6
-    case MFF_REG6:
-        cls_rule_set_reg_masked(rule, 6, 0, 0);
-        break;
-#endif
-#if FLOW_N_REGS > 7
-    case MFF_REG7:
-        cls_rule_set_reg_masked(rule, 7, 0, 0);
-        break;
-#endif
-#if FLOW_N_REGS > 8
-#error
-#endif
 
     case MFF_ETH_SRC:
         memset(rule->flow.dl_src, 0, ETH_ADDR_LEN);
@@ -1725,34 +1524,11 @@ mf_set(const struct mf_field *mf,
     case MFF_TUN_ID:
         cls_rule_set_tun_id_masked(rule, value->be64, mask->be64);
         break;
+    case MFF_METADATA:
+        cls_rule_set_metadata_masked(rule, value->be64, mask->be64);
+        break;
 
-#if FLOW_N_REGS > 0
-    case MFF_REG0:
-#endif
-#if FLOW_N_REGS > 1
-    case MFF_REG1:
-#endif
-#if FLOW_N_REGS > 2
-    case MFF_REG2:
-#endif
-#if FLOW_N_REGS > 3
-    case MFF_REG3:
-#endif
-#if FLOW_N_REGS > 4
-    case MFF_REG4:
-#endif
-#if FLOW_N_REGS > 5
-    case MFF_REG5:
-#endif
-#if FLOW_N_REGS > 6
-    case MFF_REG6:
-#endif
-#if FLOW_N_REGS > 7
-    case MFF_REG7:
-#endif
-#if FLOW_N_REGS > 8
-#error
-#endif
+    CASE_MFF_REGS:
         cls_rule_set_reg_masked(rule, mf->id - MFF_REG0,
                                 ntohl(value->be32), ntohl(mask->be32));
         break;
@@ -1884,34 +1660,9 @@ mf_random_value(const struct mf_field *mf, union mf_value *value)
 
     switch (mf->id) {
     case MFF_TUN_ID:
+    case MFF_METADATA:
     case MFF_IN_PORT:
-#if FLOW_N_REGS > 0
-    case MFF_REG0:
-#endif
-#if FLOW_N_REGS > 1
-    case MFF_REG1:
-#endif
-#if FLOW_N_REGS > 2
-    case MFF_REG2:
-#endif
-#if FLOW_N_REGS > 3
-    case MFF_REG3:
-#endif
-#if FLOW_N_REGS > 4
-    case MFF_REG4:
-#endif
-#if FLOW_N_REGS > 5
-    case MFF_REG5:
-#endif
-#if FLOW_N_REGS > 6
-    case MFF_REG6:
-#endif
-#if FLOW_N_REGS > 7
-    case MFF_REG7:
-#endif
-#if FLOW_N_REGS > 8
-#error
-#endif
+    CASE_MFF_REGS:
     case MFF_ETH_SRC:
     case MFF_ETH_DST:
     case MFF_ETH_TYPE:
@@ -2490,6 +2241,11 @@ mf_parse_subfield_name(const char *name, int name_len, bool *wild)
             && mf->nxm_name[name_len] == '\0') {
             return mf;
         }
+        if (mf->oxm_name
+            && !strncmp(mf->oxm_name, name, name_len)
+            && mf->oxm_name[name_len] == '\0') {
+            return mf;
+        }
     }
 
     return NULL;