[ovs-dev] [metaflow-cleanup 3/3] nx-match: Fold all of its data structures into mf_field.

Ethan Jackson ethan at nicira.com
Mon Nov 14 22:17:01 UTC 2011


This looks good to me.  Definitely seems a lot cleaner.  Especially
the bitwise_copy() function, we've needed something like that for a
while.

Why do we consider mf_fields which don't have a corresponding NXM
field writable?  That wasn't obvious to me from reading the code.

Ethan

On Mon, Nov 7, 2011 at 21:50, Ben Pfaff <blp at nicira.com> wrote:
> This is less redundant.
> ---
>  lib/automake.mk  |    1 -
>  lib/classifier.c |   10 +-
>  lib/learn.c      |   18 +-
>  lib/meta-flow.c  |  310 +++++++++++++++++++++++++++++++----
>  lib/meta-flow.h  |   11 ++
>  lib/nx-match.c   |  475 +++++++++++++++---------------------------------------
>  lib/nx-match.def |   71 --------
>  lib/nx-match.h   |    1 -
>  8 files changed, 430 insertions(+), 467 deletions(-)
>  delete mode 100644 lib/nx-match.def
>
> diff --git a/lib/automake.mk b/lib/automake.mk
> index 6484518..da95acb 100644
> --- a/lib/automake.mk
> +++ b/lib/automake.mk
> @@ -88,7 +88,6 @@ lib_libopenvswitch_a_SOURCES = \
>        lib/netlink.c \
>        lib/netlink.h \
>        lib/nx-match.c \
> -       lib/nx-match.def \
>        lib/nx-match.h \
>        lib/odp-util.c \
>        lib/odp-util.h \
> diff --git a/lib/classifier.c b/lib/classifier.c
> index 8ffc96f..4a4015b 100644
> --- a/lib/classifier.c
> +++ b/lib/classifier.c
> @@ -227,12 +227,10 @@ cls_rule_set_any_vid(struct cls_rule *rule)
>  void
>  cls_rule_set_dl_vlan(struct cls_rule *rule, ovs_be16 dl_vlan)
>  {
> +    flow_set_vlan_vid(&rule->flow, dl_vlan);
>     if (dl_vlan == htons(OFP_VLAN_NONE)) {
> -        cls_rule_set_dl_tci(rule, htons(0));
> +        rule->wc.vlan_tci_mask = htons(UINT16_MAX);
>     } else {
> -        dl_vlan &= htons(VLAN_VID_MASK);
> -        rule->flow.vlan_tci &= ~htons(VLAN_VID_MASK);
> -        rule->flow.vlan_tci |= htons(VLAN_CFI) | dl_vlan;
>         rule->wc.vlan_tci_mask |= htons(VLAN_VID_MASK | VLAN_CFI);
>     }
>  }
> @@ -256,9 +254,7 @@ cls_rule_set_any_pcp(struct cls_rule *rule)
>  void
>  cls_rule_set_dl_vlan_pcp(struct cls_rule *rule, uint8_t dl_vlan_pcp)
>  {
> -    dl_vlan_pcp &= 0x07;
> -    rule->flow.vlan_tci &= ~htons(VLAN_PCP_MASK);
> -    rule->flow.vlan_tci |= htons((dl_vlan_pcp << VLAN_PCP_SHIFT) | VLAN_CFI);
> +    flow_set_vlan_pcp(&rule->flow, dl_vlan_pcp);
>     rule->wc.vlan_tci_mask |= htons(VLAN_CFI | VLAN_PCP_MASK);
>  }
>
> diff --git a/lib/learn.c b/lib/learn.c
> index 9f95a13..19a0e00 100644
> --- a/lib/learn.c
> +++ b/lib/learn.c
> @@ -169,7 +169,7 @@ learn_check(const struct nx_action_learn *learn, const struct flow *flow)
>
>             if (dst_type == NX_LEARN_DST_MATCH
>                 && src_type == NX_LEARN_SRC_IMMEDIATE) {
> -                mf_set_subfield(nxm_field_to_mf_field(ntohl(dst_field)), value,
> +                mf_set_subfield(mf_from_nxm_header(ntohl(dst_field)), value,
>                                 dst_ofs, n_bits, &rule);
>             }
>         }
> @@ -232,7 +232,7 @@ learn_execute(const struct nx_action_learn *learn, const struct flow *flow,
>         case NX_LEARN_DST_MATCH:
>             dst_field = get_be32(&p);
>             dst_ofs = ntohs(get_be16(&p));
> -            mf_set_subfield(nxm_field_to_mf_field(ntohl(dst_field)), value,
> +            mf_set_subfield(mf_from_nxm_header(ntohl(dst_field)), value,
>                             dst_ofs, n_bits, &fm->cr);
>             break;
>
> @@ -346,10 +346,10 @@ learn_parse_spec(const char *orig, char *name, char *value,
>
>         spec->n_bits = n_bits;
>         spec->src_type = NX_LEARN_SRC_FIELD;
> -        spec->src = nxm_field_to_mf_field(src_header);
> +        spec->src = mf_from_nxm_header(src_header);
>         spec->src_ofs = src_ofs;
>         spec->dst_type = NX_LEARN_DST_MATCH;
> -        spec->dst = nxm_field_to_mf_field(dst_header);
> +        spec->dst = mf_from_nxm_header(dst_header);
>         spec->dst_ofs = 0;
>     } else if (!strcmp(name, "load")) {
>         if (value[strcspn(value, "[-")] == '-') {
> @@ -371,7 +371,7 @@ learn_parse_spec(const char *orig, char *name, char *value,
>                 spec->src_imm[i] = imm >> ((imm_bytes - i - 1) * 8);
>             }
>             spec->dst_type = NX_LEARN_DST_LOAD;
> -            spec->dst = nxm_field_to_mf_field(ntohl(load.dst));
> +            spec->dst = mf_from_nxm_header(ntohl(load.dst));
>             spec->dst_ofs = nxm_decode_ofs(load.ofs_nbits);
>         } else {
>             struct nx_action_reg_move move;
> @@ -380,10 +380,10 @@ learn_parse_spec(const char *orig, char *name, char *value,
>
>             spec->n_bits = ntohs(move.n_bits);
>             spec->src_type = NX_LEARN_SRC_FIELD;
> -            spec->src = nxm_field_to_mf_field(ntohl(move.src));
> +            spec->src = mf_from_nxm_header(ntohl(move.src));
>             spec->src_ofs = ntohs(move.src_ofs);
>             spec->dst_type = NX_LEARN_DST_LOAD;
> -            spec->dst = nxm_field_to_mf_field(ntohl(move.dst));
> +            spec->dst = mf_from_nxm_header(ntohl(move.dst));
>             spec->dst_ofs = ntohs(move.dst_ofs);
>         }
>     } else if (!strcmp(name, "output")) {
> @@ -397,7 +397,7 @@ learn_parse_spec(const char *orig, char *name, char *value,
>
>         spec->n_bits = n_bits;
>         spec->src_type = NX_LEARN_SRC_FIELD;
> -        spec->src = nxm_field_to_mf_field(header);
> +        spec->src = mf_from_nxm_header(header);
>         spec->src_ofs = ofs;
>         spec->dst_type = NX_LEARN_DST_OUTPUT;
>         spec->dst = NULL;
> @@ -605,7 +605,7 @@ learn_format(const struct nx_action_learn *learn, struct ds *s)
>         /* Get the destination. */
>         if (dst_type == NX_LEARN_DST_MATCH || dst_type == NX_LEARN_DST_LOAD) {
>             dst_header = ntohl(get_be32(&p));
> -            dst_field = nxm_field_to_mf_field(dst_header);
> +            dst_field = mf_from_nxm_header(dst_header);
>             dst_ofs = ntohs(get_be16(&p));
>         } else {
>             dst_header = 0;
> diff --git a/lib/meta-flow.c b/lib/meta-flow.c
> index 4ab212b..87c7845 100644
> --- a/lib/meta-flow.c
> +++ b/lib/meta-flow.c
> @@ -48,14 +48,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_FULLY, 0,
>         MFS_HEXADECIMAL,
>         MFP_NONE,
> -        NXM_NX_TUN_ID,
> +        true,
> +        NXM_NX_TUN_ID, "NXM_NX_TUN_ID",
>     }, {
>         MFF_IN_PORT, "in_port", NULL,
>         MF_FIELD_SIZES(be16),
>         MFM_NONE, FWW_IN_PORT,
>         MFS_OFP_PORT,
>         MFP_NONE,
> -        NXM_OF_IN_PORT,
> +        false,
> +        NXM_OF_IN_PORT, "NXM_OF_IN_PORT",
>     },
>
>  #define REGISTER(IDX)                           \
> @@ -65,7 +67,9 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_FULLY, 0,                           \
>         MFS_HEXADECIMAL,                        \
>         MFP_NONE,                               \
> +        true,                                   \
>         NXM_NX_REG(IDX),                        \
> +        "NXM_NX_REG" #IDX                       \
>     }
>  #if FLOW_N_REGS > 0
>     REGISTER(0),
> @@ -96,21 +100,24 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_NONE, FWW_DL_SRC,
>         MFS_ETHERNET,
>         MFP_NONE,
> -        NXM_OF_ETH_SRC,
> +        true,
> +        NXM_OF_ETH_SRC, "NXM_OF_ETH_SRC",
>     }, {
>         MFF_ETH_DST, "eth_dst", "dl_dst",
>         MF_FIELD_SIZES(mac),
>         MFM_MCAST, 0,
>         MFS_ETHERNET,
>         MFP_NONE,
> -        NXM_OF_ETH_DST,
> +        true,
> +        NXM_OF_ETH_DST, "NXM_OF_ETH_DST",
>     }, {
>         MFF_ETH_TYPE, "eth_type", "dl_type",
>         MF_FIELD_SIZES(be16),
>         MFM_NONE, FWW_DL_TYPE,
>         MFS_HEXADECIMAL,
>         MFP_NONE,
> -        NXM_OF_ETH_TYPE,
> +        false,
> +        NXM_OF_ETH_TYPE, "NXM_OF_ETH_TYPE",
>     },
>
>     {
> @@ -119,21 +126,24 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_FULLY, 0,
>         MFS_HEXADECIMAL,
>         MFP_NONE,
> -        NXM_OF_VLAN_TCI,
> +        true,
> +        NXM_OF_VLAN_TCI, "NXM_OF_VLAN_TCI",
>     }, {
>         MFF_VLAN_VID, "dl_vlan", NULL,
>         sizeof(ovs_be16), 12,
>         MFM_NONE, 0,
>         MFS_DECIMAL,
>         MFP_NONE,
> -        0,
> +        true,
> +        0, NULL
>     }, {
>         MFF_VLAN_PCP, "dl_vlan_pcp", NULL,
>         1, 3,
>         MFM_NONE, 0,
>         MFS_DECIMAL,
>         MFP_NONE,
> -        0,
> +        true,
> +        0, NULL
>     },
>
>     /* ## -- ## */
> @@ -146,14 +156,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_CIDR, 0,
>         MFS_IPV4,
>         MFP_IPV4,
> -        NXM_OF_IP_SRC,
> +        true,
> +        NXM_OF_IP_SRC, "NXM_OF_IP_SRC",
>     }, {
>         MFF_IPV4_DST, "ip_dst", "nw_dst",
>         MF_FIELD_SIZES(be32),
>         MFM_CIDR, 0,
>         MFS_IPV4,
>         MFP_IPV4,
> -        NXM_OF_IP_DST,
> +        true,
> +        NXM_OF_IP_DST, "NXM_OF_IP_DST",
>     },
>
>     {
> @@ -162,14 +174,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_CIDR, 0,
>         MFS_IPV6,
>         MFP_IPV6,
> -        NXM_NX_IPV6_SRC,
> +        true,
> +        NXM_NX_IPV6_SRC, "NXM_NX_IPV6_SRC",
>     }, {
>         MFF_IPV6_DST, "ipv6_dst", NULL,
>         MF_FIELD_SIZES(ipv6),
>         MFM_CIDR, 0,
>         MFS_IPV6,
>         MFP_IPV6,
> -        NXM_NX_IPV6_DST,
> +        true,
> +        NXM_NX_IPV6_DST, "NXM_NX_IPV6_DST",
>     },
>
>     {
> @@ -178,21 +192,24 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_NONE, FWW_NW_PROTO,
>         MFS_DECIMAL,
>         MFP_IP_ANY,
> -        NXM_OF_IP_PROTO,
> +        false,
> +        NXM_OF_IP_PROTO, "NXM_OF_IP_PROTO",
>     }, {
>         MFF_IP_TOS, "nw_tos", NULL,
>         MF_FIELD_SIZES(u8),
>         MFM_NONE, 0,
>         MFS_DECIMAL,
>         MFP_IP_ANY,
> -        NXM_OF_IP_TOS,
> +        true,
> +        NXM_OF_IP_TOS, "NXM_OF_IP_TOS"
>     }, {
>         MFF_IP_FRAG, "ip_frag", NULL,
>         1, 2,
>         MFM_FULLY, 0,
>         MFS_FRAG,
>         MFP_IP_ANY,
> -        NXM_NX_IP_FRAG,
> +        false,
> +        NXM_NX_IP_FRAG, "NXM_NX_IP_FRAG"
>     },
>
>     {
> @@ -201,35 +218,40 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_NONE, FWW_NW_PROTO,
>         MFS_DECIMAL,
>         MFP_ARP,
> -        NXM_OF_ARP_OP,
> +        false,
> +        NXM_OF_ARP_OP, "NXM_OF_ARP_OP",
>     }, {
>         MFF_ARP_SPA, "arp_spa", NULL,
>         MF_FIELD_SIZES(be32),
>         MFM_CIDR, 0,
>         MFS_IPV4,
>         MFP_ARP,
> -        NXM_OF_ARP_SPA,
> +        false,
> +        NXM_OF_ARP_SPA, "NXM_OF_ARP_SPA",
>     }, {
>         MFF_ARP_TPA, "arp_tpa", NULL,
>         MF_FIELD_SIZES(be32),
>         MFM_CIDR, 0,
>         MFS_IPV4,
>         MFP_ARP,
> -        NXM_OF_ARP_TPA,
> +        false,
> +        NXM_OF_ARP_TPA, "NXM_OF_ARP_TPA",
>     }, {
>         MFF_ARP_SHA, "arp_sha", NULL,
>         MF_FIELD_SIZES(mac),
>         MFM_NONE, FWW_ARP_SHA,
>         MFS_ETHERNET,
>         MFP_ARP,
> -        NXM_NX_ARP_SHA,
> +        false,
> +        NXM_NX_ARP_SHA, "NXM_NX_ARP_SHA",
>     }, {
>         MFF_ARP_THA, "arp_tha", NULL,
>         MF_FIELD_SIZES(mac),
>         MFM_NONE, FWW_ARP_THA,
>         MFS_ETHERNET,
>         MFP_ARP,
> -        NXM_NX_ARP_THA,
> +        false,
> +        NXM_NX_ARP_THA, "NXM_NX_ARP_THA",
>     },
>
>     /* ## -- ## */
> @@ -242,14 +264,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_NONE, FWW_TP_SRC,
>         MFS_DECIMAL,
>         MFP_TCP,
> -        NXM_OF_TCP_SRC,
> +        true,
> +        NXM_OF_TCP_SRC, "NXM_OF_TCP_SRC",
>     }, {
>         MFF_TCP_DST, "tcp_dst", "tp_dst",
>         MF_FIELD_SIZES(be16),
>         MFM_NONE, FWW_TP_DST,
>         MFS_DECIMAL,
>         MFP_TCP,
> -        NXM_OF_TCP_DST,
> +        true,
> +        NXM_OF_TCP_DST, "NXM_OF_TCP_DST",
>     },
>
>     {
> @@ -258,14 +282,16 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_NONE, FWW_TP_SRC,
>         MFS_DECIMAL,
>         MFP_UDP,
> -        NXM_OF_UDP_SRC,
> +        true,
> +        NXM_OF_UDP_SRC, "NXM_OF_UDP_SRC",
>     }, {
>         MFF_UDP_DST, "udp_dst", NULL,
>         MF_FIELD_SIZES(be16),
>         MFM_NONE, FWW_TP_DST,
>         MFS_DECIMAL,
>         MFP_UDP,
> -        NXM_OF_UDP_DST,
> +        true,
> +        NXM_OF_UDP_DST, "NXM_OF_UDP_DST",
>     },
>
>     {
> @@ -274,28 +300,34 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_NONE, FWW_TP_SRC,
>         MFS_DECIMAL,
>         MFP_ICMPV4,
> -        NXM_OF_ICMP_TYPE,
> +        false,
> +        NXM_OF_ICMP_TYPE, "NXM_OF_ICMP_TYPE",
>     }, {
>         MFF_ICMPV4_CODE, "icmp_code", NULL,
>         MF_FIELD_SIZES(u8),
>         MFM_NONE, FWW_TP_DST,
>         MFS_DECIMAL,
>         MFP_ICMPV4,
> -        NXM_OF_ICMP_CODE,
> -    }, {
> +        false,
> +        NXM_OF_ICMP_CODE, "NXM_OF_ICMP_CODE",
> +    },
> +
> +    {
>         MFF_ICMPV6_TYPE, "icmpv6_type", NULL,
>         MF_FIELD_SIZES(u8),
>         MFM_NONE, FWW_TP_SRC,
>         MFS_DECIMAL,
>         MFP_ICMPV6,
> -        NXM_NX_ICMPV6_TYPE,
> +        false,
> +        NXM_NX_ICMPV6_TYPE, "NXM_NX_ICMPV6_TYPE",
>     }, {
>         MFF_ICMPV6_CODE, "icmpv6_code", NULL,
>         MF_FIELD_SIZES(u8),
>         MFM_NONE, FWW_TP_DST,
>         MFS_DECIMAL,
>         MFP_ICMPV6,
> -        NXM_NX_ICMPV6_CODE,
> +        false,
> +        NXM_NX_ICMPV6_CODE, "NXM_NX_ICMPV6_CODE",
>     },
>
>     /* ## ---- ## */
> @@ -308,24 +340,35 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
>         MFM_NONE, FWW_ND_TARGET,
>         MFS_IPV6,
>         MFP_ND,
> -        NXM_NX_ND_TARGET,
> +        false,
> +        NXM_NX_ND_TARGET, "NXM_NX_ND_TARGET",
>     }, {
>         MFF_ND_SLL, "nd_sll", NULL,
>         MF_FIELD_SIZES(mac),
>         MFM_NONE, FWW_ARP_SHA,
>         MFS_ETHERNET,
>         MFP_ND_SOLICIT,
> -        NXM_NX_ND_SLL,
> +        false,
> +        NXM_NX_ND_SLL, "NXM_NX_ND_SLL",
>     }, {
>         MFF_ND_TLL, "nd_tll", NULL,
>         MF_FIELD_SIZES(mac),
>         MFM_NONE, FWW_ARP_THA,
>         MFS_ETHERNET,
>         MFP_ND_ADVERT,
> -        NXM_NX_ND_TLL,
> +        false,
> +        NXM_NX_ND_TLL, "NXM_NX_ND_TLL",
>     }
>  };
>
> +struct nxm_field {
> +    struct hmap_node hmap_node;
> +    uint32_t nxm_header;
> +    const struct mf_field *mf;
> +};
> +
> +static struct hmap all_nxm_fields = HMAP_INITIALIZER(&all_nxm_fields);
> +
>  /* Returns the field with the given 'id'. */
>  const struct mf_field *
>  mf_from_id(enum mf_field_id id)
> @@ -355,6 +398,64 @@ mf_from_name(const char *name)
>     return shash_find_data(&mf_by_name, name);
>  }
>
> +static void
> +add_nxm_field(uint32_t nxm_header, const struct mf_field *mf)
> +{
> +    struct nxm_field *f;
> +
> +    f = xmalloc(sizeof *f);
> +    hmap_insert(&all_nxm_fields, &f->hmap_node, hash_int(nxm_header, 0));
> +    f->nxm_header = nxm_header;
> +    f->mf = mf;
> +}
> +
> +static void
> +nxm_init(void)
> +{
> +    const struct mf_field *mf;
> +
> +    for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) {
> +        if (mf->nxm_header) {
> +            add_nxm_field(mf->nxm_header, mf);
> +            if (mf->maskable != MFM_NONE) {
> +                add_nxm_field(NXM_MAKE_WILD_HEADER(mf->nxm_header), mf);
> +            }
> +        }
> +    }
> +
> +#ifndef NDEBUG
> +    /* Verify that the header values are unique. */
> +    for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) {
> +        if (mf->nxm_header) {
> +            assert(mf_from_nxm_header(mf->nxm_header) == mf);
> +            if (mf->maskable != MFM_NONE) {
> +                assert(mf_from_nxm_header(NXM_MAKE_WILD_HEADER(mf->nxm_header))
> +                       == mf);
> +            }
> +        }
> +    }
> +#endif
> +}
> +
> +const struct mf_field *
> +mf_from_nxm_header(uint32_t header)
> +{
> +    const struct nxm_field *f;
> +
> +    if (hmap_is_empty(&all_nxm_fields)) {
> +        nxm_init();
> +    }
> +
> +    HMAP_FOR_EACH_IN_BUCKET (f, hmap_node, hash_int(header, 0),
> +                             &all_nxm_fields) {
> +        if (f->nxm_header == header) {
> +            return f->mf;
> +        }
> +    }
> +
> +    return NULL;
> +}
> +
>  /* Returns true if 'wc' wildcards all the bits in field 'mf', false if 'wc'
>  * specifies at least one bit in the field.
>  *
> @@ -1017,6 +1118,151 @@ mf_set_value(const struct mf_field *mf,
>     }
>  }
>
> +/* Makes 'rule' match field 'mf' exactly, with the value matched taken from
> + * 'value'.  The caller is responsible for ensuring that 'rule' meets 'mf''s
> + * prerequisites. */
> +void
> +mf_set_flow_value(const struct mf_field *mf,
> +                  const union mf_value *value, struct flow *flow)
> +{
> +    switch (mf->id) {
> +    case MFF_TUN_ID:
> +        flow->tun_id = 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
> +#error
> +#endif
> +#if FLOW_N_REGS > 0
> +        flow->regs[mf->id - MFF_REG0] = ntohl(value->be32);
> +        break;
> +#endif
> +
> +    case MFF_ETH_SRC:
> +        memcpy(flow->dl_src, value->mac, ETH_ADDR_LEN);
> +        break;
> +
> +    case MFF_ETH_DST:
> +        memcpy(flow->dl_src, value->mac, ETH_ADDR_LEN);
> +        break;
> +
> +    case MFF_ETH_TYPE:
> +        flow->dl_type = value->be16;
> +        break;
> +
> +    case MFF_VLAN_TCI:
> +        flow->vlan_tci = value->be16;
> +        break;
> +
> +    case MFF_VLAN_VID:
> +        flow_set_vlan_vid(flow, value->be16);
> +        break;
> +
> +    case MFF_VLAN_PCP:
> +        flow_set_vlan_pcp(flow, value->u8);
> +        break;
> +
> +    case MFF_IPV4_SRC:
> +        flow->nw_src = value->be32;
> +        break;
> +
> +    case MFF_IPV4_DST:
> +        flow->nw_dst = value->be32;
> +        break;
> +
> +    case MFF_IPV6_SRC:
> +        flow->ipv6_src = value->ipv6;
> +        break;
> +
> +    case MFF_IPV6_DST:
> +        flow->ipv6_dst = value->ipv6;
> +        break;
> +
> +    case MFF_IP_PROTO:
> +        flow->nw_proto = value->u8;
> +        break;
> +
> +    case MFF_IP_TOS:
> +        flow->tos_frag &= ~IP_DSCP_MASK;
> +        flow->tos_frag |= value->u8 & IP_DSCP_MASK;
> +        break;
> +
> +    case MFF_IP_FRAG:
> +        flow->tos_frag &= ~FLOW_FRAG_MASK;
> +        flow->tos_frag |= value->u8 & FLOW_FRAG_MASK;
> +        break;
> +
> +    case MFF_ARP_OP:
> +        flow->nw_proto = ntohs(value->be16);
> +        break;
> +
> +    case MFF_ARP_SPA:
> +        flow->nw_src = value->be32;
> +        break;
> +
> +    case MFF_ARP_TPA:
> +        flow->nw_dst = value->be32;
> +        break;
> +
> +    case MFF_ARP_SHA:
> +    case MFF_ND_SLL:
> +        memcpy(flow->arp_sha, value->mac, ETH_ADDR_LEN);
> +        break;
> +
> +    case MFF_ARP_THA:
> +    case MFF_ND_TLL:
> +        memcpy(flow->arp_tha, value->mac, ETH_ADDR_LEN);
> +        break;
> +
> +    case MFF_TCP_SRC:
> +    case MFF_UDP_SRC:
> +        flow->tp_src = value->be16;
> +        break;
> +
> +    case MFF_TCP_DST:
> +    case MFF_UDP_DST:
> +        flow->tp_dst = value->be16;
> +        break;
> +
> +    case MFF_ICMPV4_TYPE:
> +    case MFF_ICMPV6_TYPE:
> +        flow->tp_src = htons(value->u8);
> +        break;
> +
> +    case MFF_ICMPV4_CODE:
> +    case MFF_ICMPV6_CODE:
> +        flow->tp_dst = htons(value->u8);
> +        break;
> +
> +    case MFF_ND_TARGET:
> +        flow->nd_target = value->ipv6;
> +        break;
> +
> +    case MFF_N_IDS:
> +    default:
> +        NOT_REACHED();
> +    }
> +}
> +
>  /* Makes 'rule' wildcard field 'mf'.
>  *
>  * The caller is responsible for ensuring that 'rule' meets 'mf''s
> diff --git a/lib/meta-flow.h b/lib/meta-flow.h
> index ccab1b7..44715c4 100644
> --- a/lib/meta-flow.h
> +++ b/lib/meta-flow.h
> @@ -174,7 +174,14 @@ struct mf_field {
>     flow_wildcards_t fww_bit;   /* Either 0 or exactly one FWW_* bit. */
>     enum mf_string string;
>     enum mf_prereqs prereqs;
> +    bool writable;              /* May be written by actions? */
> +
> +    /* NXM properties.
> +     *
> +     * A few "mf_field"s don't correspond to NXM fields.  Those have 0 and
> +     * NULL for the following members, respectively. */
>     uint32_t nxm_header;        /* An NXM_* constant (a few fields have 0). */
> +    const char *nxm_name;       /* The "NXM_*" constant's name. */
>  };
>
>  /* The representation of a field's value. */
> @@ -190,6 +197,8 @@ union mf_value {
>  /* Finding mf_fields. */
>  const struct mf_field *mf_from_id(enum mf_field_id);
>  const struct mf_field *mf_from_name(const char *name);
> +const struct mf_field *mf_from_nxm_header(uint32_t nxm_header);
> +const struct mf_field *mf_from_nxm_name(const char *nxm_name);
>
>  /* Inspecting wildcarded bits. */
>  bool mf_is_all_wild(const struct mf_field *, const struct flow_wildcards *);
> @@ -209,6 +218,8 @@ void mf_get_value(const struct mf_field *, const struct flow *,
>                   union mf_value *value);
>  void mf_set_value(const struct mf_field *, const union mf_value *value,
>                   struct cls_rule *);
> +void mf_set_flow_value(const struct mf_field *, const union mf_value *value,
> +                       struct flow *);
>
>  void mf_get(const struct mf_field *, const struct cls_rule *,
>             union mf_value *value, union mf_value *mask);
> diff --git a/lib/nx-match.c b/lib/nx-match.c
> index 84a14de..a859bab 100644
> --- a/lib/nx-match.c
> +++ b/lib/nx-match.c
> @@ -46,76 +46,6 @@ enum {
>     BAD_ARGUMENT = OFP_MKERR(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT)
>  };
>
> -/* For each NXM_* field, define NFI_NXM_* as consecutive integers starting from
> - * zero. */
> -enum nxm_field_index {
> -#define DEFINE_FIELD(HEADER, MFF_ID, WRITABLE)  \
> -        NFI_NXM_##HEADER,
> -#include "nx-match.def"
> -    N_NXM_FIELDS
> -};
> -
> -struct nxm_field {
> -    struct hmap_node hmap_node;
> -    enum nxm_field_index index;       /* NFI_* value. */
> -    uint32_t header;                  /* NXM_* value. */
> -    enum mf_field_id mf_id;           /* MFF_* value. */
> -    const struct mf_field *mf;
> -    const char *name;                 /* "NXM_*" string. */
> -    bool writable;                    /* Writable with NXAST_REG_{MOVE,LOAD}? */
> -};
> -
> -/* All the known fields. */
> -static struct nxm_field nxm_fields[N_NXM_FIELDS] = {
> -#define DEFINE_FIELD(HEADER, MFF_ID, WRITABLE)                            \
> -    { HMAP_NODE_NULL_INITIALIZER, NFI_NXM_##HEADER, NXM_##HEADER, \
> -      MFF_ID, NULL, "NXM_" #HEADER, WRITABLE },
> -#include "nx-match.def"
> -};
> -
> -/* Hash table of 'nxm_fields'. */
> -static struct hmap all_nxm_fields = HMAP_INITIALIZER(&all_nxm_fields);
> -
> -static void
> -nxm_init(void)
> -{
> -    if (hmap_is_empty(&all_nxm_fields)) {
> -        int i;
> -
> -        for (i = 0; i < N_NXM_FIELDS; i++) {
> -            struct nxm_field *f = &nxm_fields[i];
> -            hmap_insert(&all_nxm_fields, &f->hmap_node,
> -                        hash_int(f->header, 0));
> -            f->mf = mf_from_id(f->mf_id);
> -        }
> -
> -        /* Verify that the header values are unique (duplicate "case" values
> -         * cause a compile error). */
> -        switch (0) {
> -#define DEFINE_FIELD(HEADER, MFF_ID, WRITABLE)  \
> -        case NXM_##HEADER: break;
> -#include "nx-match.def"
> -        }
> -    }
> -}
> -
> -static const struct nxm_field *
> -nxm_field_lookup(uint32_t header)
> -{
> -    struct nxm_field *f;
> -
> -    nxm_init();
> -
> -    HMAP_FOR_EACH_WITH_HASH (f, hmap_node, hash_int(header, 0),
> -                             &all_nxm_fields) {
> -        if (f->header == header) {
> -            return f;
> -        }
> -    }
> -
> -    return NULL;
> -}
> -
>  /* Returns the width of the data for a field with the given 'header', in
>  * bytes. */
>  int
> @@ -132,13 +62,6 @@ nxm_field_bits(uint32_t header)
>  {
>     return nxm_field_bytes(header) * 8;
>  }
> -
> -const struct mf_field *
> -nxm_field_to_mf_field(uint32_t header)
> -{
> -    const struct nxm_field *f = nxm_field_lookup(header);
> -    return f ? f->mf : NULL;
> -}
>
>  /* nx_pull_match() and helpers. */
>
> @@ -191,46 +114,46 @@ nx_pull_match(struct ofpbuf *b, unsigned int match_len, uint16_t priority,
>     cls_rule_init_catchall(rule, priority);
>     while ((header = nx_entry_ok(p, match_len)) != 0) {
>         unsigned length = NXM_LENGTH(header);
> -        const struct nxm_field *f;
> +        const struct mf_field *mf;
>         int error;
>
> -        f = nxm_field_lookup(header);
> -        if (!f) {
> +        mf = mf_from_nxm_header(header);
> +        if (!mf) {
>             error = NXM_BAD_TYPE;
> -        } else if (!mf_are_prereqs_ok(f->mf, &rule->flow)) {
> +        } else if (!mf_are_prereqs_ok(mf, &rule->flow)) {
>             error = NXM_BAD_PREREQ;
> -        } else if (!mf_is_all_wild(f->mf, &rule->wc)) {
> +        } else if (!mf_is_all_wild(mf, &rule->wc)) {
>             error = NXM_DUP_TYPE;
>         } else {
> -            unsigned int width = f->mf->n_bytes;
> +            unsigned int width = mf->n_bytes;
>             union mf_value value;
>
>             memcpy(&value, p + 4, width);
> -            if (!mf_is_value_valid(f->mf, &value)) {
> +            if (!mf_is_value_valid(mf, &value)) {
>                 error = NXM_BAD_VALUE;
>             } else if (!NXM_HASMASK(header)) {
>                 error = 0;
> -                mf_set_value(f->mf, &value, rule);
> +                mf_set_value(mf, &value, rule);
>             } else {
>                 union mf_value mask;
>
>                 memcpy(&mask, p + 4 + width, width);
> -                if (!mf_is_mask_valid(f->mf, &mask)) {
> +                if (!mf_is_mask_valid(mf, &mask)) {
>                     error = NXM_BAD_MASK;
>                 } else {
>                     error = 0;
> -                    mf_set(f->mf, &value, &mask, rule);
> +                    mf_set(mf, &value, &mask, rule);
>                 }
>             }
>         }
>
>         if (error) {
>             char *msg = ofputil_error_to_string(error);
> -            VLOG_DBG_RL(&rl, "bad nxm_entry with vendor=%"PRIu32", "
> -                        "field=%"PRIu32", hasmask=%"PRIu32", type=%"PRIu32" "
> -                        "(%s)",
> +            VLOG_DBG_RL(&rl, "bad nxm_entry %#08"PRIx32" (vendor=%"PRIu32", "
> +                        "field=%"PRIu32", hasmask=%"PRIu32", len=%"PRIu32"), "
> +                        "(%s)", header,
>                         NXM_VENDOR(header), NXM_FIELD(header),
> -                        NXM_HASMASK(header), NXM_TYPE(header),
> +                        NXM_HASMASK(header), NXM_LENGTH(header),
>                         msg);
>             free(msg);
>
> @@ -673,9 +596,12 @@ nx_match_to_string(const uint8_t *p, unsigned int match_len)
>  static void
>  format_nxm_field_name(struct ds *s, uint32_t header)
>  {
> -    const struct nxm_field *f = nxm_field_lookup(header);
> -    if (f) {
> -        ds_put_cstr(s, f->name);
> +    const struct mf_field *mf = mf_from_nxm_header(header);
> +    if (mf) {
> +        ds_put_cstr(s, mf->nxm_name);
> +        if (NXM_HASMASK(header)) {
> +            ds_put_cstr(s, "_W");
> +        }
>     } else {
>         ds_put_format(s, "%d:%d", NXM_VENDOR(header), NXM_FIELD(header));
>     }
> @@ -684,12 +610,25 @@ format_nxm_field_name(struct ds *s, uint32_t header)
>  static uint32_t
>  parse_nxm_field_name(const char *name, int name_len)
>  {
> -    const struct nxm_field *f;
> +    bool wild;
> +    int i;
>
>     /* Check whether it's a field name. */
> -    for (f = nxm_fields; f < &nxm_fields[ARRAY_SIZE(nxm_fields)]; f++) {
> -        if (!strncmp(f->name, name, name_len) && f->name[name_len] == '\0') {
> -            return f->header;
> +    wild = name_len > 2 && !memcmp(&name[name_len - 2], "_W", 2);
> +    if (wild) {
> +        name_len -= 2;
> +    }
> +    for (i = 0; i < MFF_N_IDS; i++) {
> +        const struct mf_field *mf = mf_from_id(i);
> +
> +        if (mf->nxm_name
> +            && !strncmp(mf->nxm_name, name, name_len)
> +            && mf->nxm_name[name_len] == '\0') {
> +            if (!wild) {
> +                return mf->nxm_header;
> +            } else if (mf->maskable != MFM_NONE) {
> +                return NXM_MAKE_WILD_HEADER(mf->nxm_header);
> +            }
>         }
>     }
>
> @@ -928,12 +867,11 @@ nxm_format_reg_load(const struct nx_action_reg_load *load, struct ds *s)
>  /* nxm_check_reg_move(), nxm_check_reg_load(). */
>
>  static bool
> -field_ok(const struct nxm_field *f, const struct flow *flow, int size)
> +field_ok(const struct mf_field *mf, const struct flow *flow, int size)
>  {
> -    return (f
> -            && !NXM_HASMASK(f->header)
> -            && mf_are_prereqs_ok(f->mf, flow)
> -            && size <= nxm_field_bits(f->header));
> +    return (mf
> +            && mf_are_prereqs_ok(mf, flow)
> +            && size <= nxm_field_bits(mf->nxm_header));
>  }
>
>  int
> @@ -958,14 +896,15 @@ nxm_check_reg_move(const struct nx_action_reg_move *action,
>  /* Given a flow, checks that the source field represented by 'src_header'
>  * in the range ['ofs', 'ofs' + 'n_bits') is valid. */
>  int
> -nxm_src_check(ovs_be32 src_header, unsigned int ofs, unsigned int n_bits,
> +nxm_src_check(ovs_be32 src_header_, unsigned int ofs, unsigned int n_bits,
>               const struct flow *flow)
>  {
> -    const struct nxm_field *src = nxm_field_lookup(ntohl(src_header));
> +    uint32_t src_header = ntohl(src_header_);
> +    const struct mf_field *src = mf_from_nxm_header(src_header);
>
>     if (!n_bits) {
>         VLOG_WARN_RL(&rl, "zero bit source field");
> -    } else if (!field_ok(src, flow, ofs + n_bits)) {
> +    } else if (NXM_HASMASK(src_header) || !field_ok(src, flow, ofs + n_bits)) {
>         VLOG_WARN_RL(&rl, "invalid source field");
>     } else {
>         return 0;
> @@ -977,14 +916,15 @@ nxm_src_check(ovs_be32 src_header, unsigned int ofs, unsigned int n_bits,
>  /* Given a flow, checks that the destination field represented by 'dst_header'
>  * in the range ['ofs', 'ofs' + 'n_bits') is valid. */
>  int
> -nxm_dst_check(ovs_be32 dst_header, unsigned int ofs, unsigned int n_bits,
> +nxm_dst_check(ovs_be32 dst_header_, unsigned int ofs, unsigned int n_bits,
>               const struct flow *flow)
>  {
> -    const struct nxm_field *dst = nxm_field_lookup(ntohl(dst_header));
> +    uint32_t dst_header = ntohl(dst_header_);
> +    const struct mf_field *dst = mf_from_nxm_header(dst_header);
>
>     if (!n_bits) {
>         VLOG_WARN_RL(&rl, "zero bit destination field");
> -    } else if (!field_ok(dst, flow, ofs + n_bits)) {
> +    } else if (NXM_HASMASK(dst_header) || !field_ok(dst, flow, ofs + n_bits)) {
>         VLOG_WARN_RL(&rl, "invalid destination field");
>     } else if (!dst->writable) {
>         VLOG_WARN_RL(&rl, "destination field is not writable");
> @@ -1019,111 +959,57 @@ nxm_check_reg_load(const struct nx_action_reg_load *action,
>
>  /* nxm_execute_reg_move(), nxm_execute_reg_load(). */
>
> -static uint64_t
> -nxm_read_field(const struct nxm_field *src, const struct flow *flow)
> +static void
> +bitwise_copy(const void *src_, unsigned int src_len, unsigned int src_ofs,
> +             void *dst_, unsigned int dst_len, unsigned int dst_ofs,
> +             unsigned int n_bits)
>  {
> -    switch (src->index) {
> -    case NFI_NXM_OF_IN_PORT:
> -        return flow->in_port;
> -
> -    case NFI_NXM_OF_ETH_DST:
> -        return eth_addr_to_uint64(flow->dl_dst);
> -
> -    case NFI_NXM_OF_ETH_SRC:
> -        return eth_addr_to_uint64(flow->dl_src);
> -
> -    case NFI_NXM_OF_ETH_TYPE:
> -        return ntohs(ofputil_dl_type_to_openflow(flow->dl_type));
> -
> -    case NFI_NXM_OF_VLAN_TCI:
> -        return ntohs(flow->vlan_tci);
> -
> -    case NFI_NXM_OF_IP_TOS:
> -        return flow->tos_frag & IP_DSCP_MASK;
> -
> -    case NFI_NXM_NX_IP_FRAG:
> -        return flow->tos_frag & FLOW_FRAG_MASK;
> -
> -    case NFI_NXM_OF_IP_PROTO:
> -    case NFI_NXM_OF_ARP_OP:
> -        return flow->nw_proto;
> -
> -    case NFI_NXM_OF_IP_SRC:
> -    case NFI_NXM_OF_ARP_SPA:
> -        return ntohl(flow->nw_src);
> -
> -    case NFI_NXM_OF_IP_DST:
> -    case NFI_NXM_OF_ARP_TPA:
> -        return ntohl(flow->nw_dst);
> -
> -    case NFI_NXM_OF_TCP_SRC:
> -    case NFI_NXM_OF_UDP_SRC:
> -        return ntohs(flow->tp_src);
> -
> -    case NFI_NXM_OF_TCP_DST:
> -    case NFI_NXM_OF_UDP_DST:
> -        return ntohs(flow->tp_dst);
> -
> -    case NFI_NXM_OF_ICMP_TYPE:
> -    case NFI_NXM_NX_ICMPV6_TYPE:
> -        return ntohs(flow->tp_src) & 0xff;
> -
> -    case NFI_NXM_OF_ICMP_CODE:
> -    case NFI_NXM_NX_ICMPV6_CODE:
> -        return ntohs(flow->tp_dst) & 0xff;
> -
> -    case NFI_NXM_NX_TUN_ID:
> -        return ntohll(flow->tun_id);
> -
> -#define NXM_READ_REGISTER(IDX)                  \
> -    case NFI_NXM_NX_REG##IDX:                   \
> -        return flow->regs[IDX];                 \
> -    case NFI_NXM_NX_REG##IDX##_W:               \
> -        NOT_REACHED();
> -
> -    NXM_READ_REGISTER(0);
> -#if FLOW_N_REGS >= 2
> -    NXM_READ_REGISTER(1);
> -#endif
> -#if FLOW_N_REGS >= 3
> -    NXM_READ_REGISTER(2);
> -#endif
> -#if FLOW_N_REGS >= 4
> -    NXM_READ_REGISTER(3);
> -#endif
> -#if FLOW_N_REGS >= 5
> -    NXM_READ_REGISTER(4);
> -#endif
> -#if FLOW_N_REGS > 5
> -#error
> -#endif
> -
> -    case NFI_NXM_NX_ARP_SHA:
> -    case NFI_NXM_NX_ND_SLL:
> -        return eth_addr_to_uint64(flow->arp_sha);
> -
> -    case NFI_NXM_NX_ARP_THA:
> -    case NFI_NXM_NX_ND_TLL:
> -        return eth_addr_to_uint64(flow->arp_tha);
> -
> -    case NFI_NXM_NX_TUN_ID_W:
> -    case NFI_NXM_OF_ETH_DST_W:
> -    case NFI_NXM_OF_VLAN_TCI_W:
> -    case NFI_NXM_OF_IP_SRC_W:
> -    case NFI_NXM_OF_IP_DST_W:
> -    case NFI_NXM_OF_ARP_SPA_W:
> -    case NFI_NXM_OF_ARP_TPA_W:
> -    case NFI_NXM_NX_IPV6_SRC:
> -    case NFI_NXM_NX_IPV6_SRC_W:
> -    case NFI_NXM_NX_IPV6_DST:
> -    case NFI_NXM_NX_IPV6_DST_W:
> -    case NFI_NXM_NX_IP_FRAG_W:
> -    case NFI_NXM_NX_ND_TARGET:
> -    case N_NXM_FIELDS:
> -        NOT_REACHED();
> -    }
> +    const uint8_t *src = src_;
> +    uint8_t *dst = dst_;
> +
> +    src += src_len - (src_ofs / 8 + 1);
> +    src_ofs %= 8;
> +
> +    dst += dst_len - (dst_ofs / 8 + 1);
> +    dst_ofs %= 8;
>
> -    NOT_REACHED();
> +    if (src_ofs == 0 && dst_ofs == 0) {
> +        unsigned int n_bytes = n_bits / 8;
> +        if (n_bytes) {
> +            dst -= n_bytes - 1;
> +            src -= n_bytes - 1;
> +            memcpy(dst, src, n_bytes);
> +
> +            n_bits %= 8;
> +            src--;
> +            dst--;
> +        }
> +        if (n_bits) {
> +            uint8_t mask = (1 << n_bits) - 1;
> +            *dst = (*dst & ~mask) | (*src & mask);
> +        }
> +    } else {
> +        while (n_bits > 0) {
> +            unsigned int max_copy = 8 - MAX(src_ofs, dst_ofs);
> +            unsigned int chunk = MIN(n_bits, max_copy);
> +            uint8_t mask = ((1 << chunk) - 1) << dst_ofs;
> +
> +            *dst &= ~mask;
> +            *dst |= ((*src >> src_ofs) << dst_ofs) & mask;
> +
> +            src_ofs += chunk;
> +            if (src_ofs == 8) {
> +                src--;
> +                src_ofs = 0;
> +            }
> +            dst_ofs += chunk;
> +            if (dst_ofs == 8) {
> +                dst--;
> +                dst_ofs = 0;
> +            }
> +            n_bits -= chunk;
> +        }
> +    }
>  }
>
>  /* Returns the value of the NXM field corresponding to 'header' at 'ofs_nbits'
> @@ -1132,136 +1018,33 @@ uint64_t
>  nxm_read_field_bits(ovs_be32 header, ovs_be16 ofs_nbits,
>                     const struct flow *flow)
>  {
> -    int n_bits = nxm_decode_n_bits(ofs_nbits);
> -    int ofs = nxm_decode_ofs(ofs_nbits);
> -    uint64_t mask, data;
> -
> -    mask = n_bits == 64 ? UINT64_MAX : (UINT64_C(1) << n_bits) - 1;
> -    data = nxm_read_field(nxm_field_lookup(ntohl(header)), flow);
> -    data = (data >> ofs) & mask;
> -
> -    return data;
> -}
> -
> -static void
> -nxm_write_field(const struct nxm_field *dst, struct flow *flow,
> -                uint64_t new_value)
> -{
> -    switch (dst->index) {
> -    case NFI_NXM_OF_ETH_DST:
> -        eth_addr_from_uint64(new_value, flow->dl_dst);
> -        break;
> -
> -    case NFI_NXM_OF_ETH_SRC:
> -        eth_addr_from_uint64(new_value, flow->dl_src);
> -        break;
> -
> -    case NFI_NXM_OF_VLAN_TCI:
> -        flow->vlan_tci = htons(new_value);
> -        break;
> -
> -    case NFI_NXM_NX_TUN_ID:
> -        flow->tun_id = htonll(new_value);
> -        break;
> -
> -#define NXM_WRITE_REGISTER(IDX)                 \
> -    case NFI_NXM_NX_REG##IDX:                   \
> -        flow->regs[IDX] = new_value;            \
> -        break;                                  \
> -    case NFI_NXM_NX_REG##IDX##_W:               \
> -        NOT_REACHED();
> -
> -    NXM_WRITE_REGISTER(0);
> -#if FLOW_N_REGS >= 2
> -    NXM_WRITE_REGISTER(1);
> -#endif
> -#if FLOW_N_REGS >= 3
> -    NXM_WRITE_REGISTER(2);
> -#endif
> -#if FLOW_N_REGS >= 4
> -    NXM_WRITE_REGISTER(3);
> -#endif
> -#if FLOW_N_REGS >= 5
> -    NXM_WRITE_REGISTER(4);
> -#endif
> -#if FLOW_N_REGS > 5
> -#error
> -#endif
> -
> -    case NFI_NXM_OF_IP_TOS:
> -        flow->tos_frag &= ~IP_DSCP_MASK;
> -        flow->tos_frag |= new_value & IP_DSCP_MASK;
> -        break;
> -
> -    case NFI_NXM_NX_IP_FRAG:
> -        flow->tos_frag &= ~FLOW_FRAG_MASK;
> -        flow->tos_frag |= new_value & FLOW_FRAG_MASK;
> -        break;
> -
> -    case NFI_NXM_OF_IP_SRC:
> -        flow->nw_src = htonl(new_value);
> -        break;
> -
> -    case NFI_NXM_OF_IP_DST:
> -        flow->nw_dst = htonl(new_value);
> -        break;
> -
> -    case NFI_NXM_OF_TCP_SRC:
> -    case NFI_NXM_OF_UDP_SRC:
> -        flow->tp_src = htons(new_value);
> -        break;
> -
> -    case NFI_NXM_OF_TCP_DST:
> -    case NFI_NXM_OF_UDP_DST:
> -        flow->tp_dst = htons(new_value);
> -        break;
> -
> -    case NFI_NXM_OF_IN_PORT:
> -    case NFI_NXM_OF_ETH_TYPE:
> -    case NFI_NXM_OF_IP_PROTO:
> -    case NFI_NXM_OF_ARP_OP:
> -    case NFI_NXM_OF_ARP_SPA:
> -    case NFI_NXM_OF_ARP_TPA:
> -    case NFI_NXM_OF_ICMP_TYPE:
> -    case NFI_NXM_OF_ICMP_CODE:
> -    case NFI_NXM_NX_TUN_ID_W:
> -    case NFI_NXM_OF_ETH_DST_W:
> -    case NFI_NXM_OF_VLAN_TCI_W:
> -    case NFI_NXM_OF_IP_SRC_W:
> -    case NFI_NXM_OF_IP_DST_W:
> -    case NFI_NXM_OF_ARP_SPA_W:
> -    case NFI_NXM_OF_ARP_TPA_W:
> -    case NFI_NXM_NX_ARP_SHA:
> -    case NFI_NXM_NX_ARP_THA:
> -    case NFI_NXM_NX_IPV6_SRC:
> -    case NFI_NXM_NX_IPV6_SRC_W:
> -    case NFI_NXM_NX_IPV6_DST:
> -    case NFI_NXM_NX_IPV6_DST_W:
> -    case NFI_NXM_NX_IP_FRAG_W:
> -    case NFI_NXM_NX_ICMPV6_TYPE:
> -    case NFI_NXM_NX_ICMPV6_CODE:
> -    case NFI_NXM_NX_ND_TARGET:
> -    case NFI_NXM_NX_ND_SLL:
> -    case NFI_NXM_NX_ND_TLL:
> -    case N_NXM_FIELDS:
> -        NOT_REACHED();
> -    }
> +    const struct mf_field *field = mf_from_nxm_header(ntohl(header));
> +    union mf_value value;
> +    union mf_value bits;
> +
> +    mf_get_value(field, flow, &value);
> +    bits.be64 = htonll(0);
> +    bitwise_copy(&value, field->n_bytes, nxm_decode_ofs(ofs_nbits),
> +                 &bits, sizeof bits.be64, 0,
> +                 nxm_decode_n_bits(ofs_nbits));
> +    return ntohll(bits.be64);
>  }
>
>  void
>  nxm_execute_reg_move(const struct nx_action_reg_move *action,
>                      struct flow *flow)
>  {
> -    ovs_be16 src_ofs_nbits, dst_ofs_nbits;
> -    uint64_t src_data;
> -    int n_bits;
> -
> -    n_bits = ntohs(action->n_bits);
> -    src_ofs_nbits = nxm_encode_ofs_nbits(ntohs(action->src_ofs), n_bits);
> -    dst_ofs_nbits = nxm_encode_ofs_nbits(ntohs(action->dst_ofs), n_bits);
> -
> -    src_data = nxm_read_field_bits(action->src, src_ofs_nbits, flow);
> -    nxm_reg_load(action->dst, dst_ofs_nbits, src_data, flow);
> +    const struct mf_field *src = mf_from_nxm_header(ntohl(action->src));
> +    const struct mf_field *dst = mf_from_nxm_header(ntohl(action->dst));
> +    union mf_value src_value;
> +    union mf_value dst_value;
> +
> +    mf_get_value(dst, flow, &dst_value);
> +    mf_get_value(src, flow, &src_value);
> +    bitwise_copy(&src_value, src->n_bytes, ntohs(action->src_ofs),
> +                 &dst_value, dst->n_bytes, ntohs(action->dst_ofs),
> +                 ntohs(action->n_bits));
> +    mf_set_flow_value(dst, &dst_value, flow);
>  }
>
>  void
> @@ -1277,16 +1060,16 @@ void
>  nxm_reg_load(ovs_be32 dst_header, ovs_be16 ofs_nbits, uint64_t src_data,
>              struct flow *flow)
>  {
> +    const struct mf_field *dst = mf_from_nxm_header(ntohl(dst_header));
>     int n_bits = nxm_decode_n_bits(ofs_nbits);
>     int dst_ofs = nxm_decode_ofs(ofs_nbits);
> -    uint64_t mask = n_bits == 64 ? UINT64_MAX : (UINT64_C(1) << n_bits) - 1;
> -
> -    /* Get remaining bits of the destination field. */
> -    const struct nxm_field *dst = nxm_field_lookup(ntohl(dst_header));
> -    uint64_t dst_data = nxm_read_field(dst, flow) & ~(mask << dst_ofs);
> -
> -    /* Get the final value. */
> -    uint64_t new_data = dst_data | (src_data << dst_ofs);
> -
> -    nxm_write_field(dst, flow, new_data);
> +    union mf_value dst_value;
> +    union mf_value src_value;
> +
> +    mf_get_value(dst, flow, &dst_value);
> +    src_value.be64 = htonll(src_data);
> +    bitwise_copy(&src_value, sizeof src_value.be64, 0,
> +                 &dst_value, dst->n_bytes, dst_ofs,
> +                 n_bits);
> +    mf_set_flow_value(dst, &dst_value, flow);
>  }
> diff --git a/lib/nx-match.def b/lib/nx-match.def
> deleted file mode 100644
> index 6b941cb..0000000
> --- a/lib/nx-match.def
> +++ /dev/null
> @@ -1,71 +0,0 @@
> -/*                                                                -*- c -*-
> - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
> - *
> - * Licensed under the Apache License, Version 2.0 (the "License");
> - * you may not use this file except in compliance with the License.
> - * You may obtain a copy of the License at:
> - *
> - *     http://www.apache.org/licenses/LICENSE-2.0
> - *
> - * Unless required by applicable law or agreed to in writing, software
> - * distributed under the License is distributed on an "AS IS" BASIS,
> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> - * See the License for the specific language governing permissions and
> - * limitations under the License.
> - */
> -
> -#define DEFINE_FIELD_M(HEADER, MFF_ID, WRITABLE)  \
> -    DEFINE_FIELD(HEADER,     MFF_ID, WRITABLE)        \
> -    DEFINE_FIELD(HEADER##_W, MFF_ID, false)
> -
> -/*             NXM_ suffix    MFF_ field ID    rw? */
> -/*             ------------   ------------   ----- */
> -DEFINE_FIELD_M(NX_TUN_ID,     MFF_TUN_ID,     true)
> -DEFINE_FIELD  (OF_IN_PORT,    MFF_IN_PORT,   false)
> -DEFINE_FIELD_M(OF_ETH_DST,    MFF_ETH_DST,    true)
> -DEFINE_FIELD  (OF_ETH_SRC,    MFF_ETH_SRC,    true)
> -DEFINE_FIELD  (OF_ETH_TYPE,   MFF_ETH_TYPE,  false)
> -DEFINE_FIELD_M(OF_VLAN_TCI,   MFF_VLAN_TCI,   true)
> -DEFINE_FIELD  (OF_IP_TOS,     MFF_IP_TOS,     true)
> -DEFINE_FIELD  (OF_IP_PROTO,   MFF_IP_PROTO,  false)
> -DEFINE_FIELD_M(OF_IP_SRC,     MFF_IPV4_SRC,   true)
> -DEFINE_FIELD_M(OF_IP_DST,     MFF_IPV4_DST,   true)
> -DEFINE_FIELD_M(NX_IP_FRAG,    MFF_IP_FRAG,   false)
> -DEFINE_FIELD  (OF_TCP_SRC,    MFF_TCP_SRC,    true)
> -DEFINE_FIELD  (OF_TCP_DST,    MFF_TCP_DST,    true)
> -DEFINE_FIELD  (OF_UDP_SRC,    MFF_UDP_SRC,    true)
> -DEFINE_FIELD  (OF_UDP_DST,    MFF_UDP_DST,    true)
> -DEFINE_FIELD  (OF_ICMP_TYPE,  MFF_ICMPV4_TYPE, false)
> -DEFINE_FIELD  (OF_ICMP_CODE,  MFF_ICMPV4_CODE, false)
> -DEFINE_FIELD  (OF_ARP_OP,     MFF_ARP_OP,    false)
> -DEFINE_FIELD_M(OF_ARP_SPA,    MFF_ARP_SPA,   false)
> -DEFINE_FIELD_M(OF_ARP_TPA,    MFF_ARP_TPA,   false)
> -DEFINE_FIELD  (NX_ARP_SHA,    MFF_ARP_SHA,   false)
> -DEFINE_FIELD  (NX_ARP_THA,    MFF_ARP_THA,   false)
> -DEFINE_FIELD_M(NX_IPV6_SRC,   MFF_IPV6_SRC,  false)
> -DEFINE_FIELD_M(NX_IPV6_DST,   MFF_IPV6_DST,  false)
> -/* XXX should we have MFF_ICMPV4_TYPE and MFF_ICMPV6_TYPE? */
> -DEFINE_FIELD  (NX_ICMPV6_TYPE,MFF_ICMPV6_TYPE, false)
> -DEFINE_FIELD  (NX_ICMPV6_CODE,MFF_ICMPV6_CODE, false)
> -DEFINE_FIELD  (NX_ND_TARGET,  MFF_ND_TARGET, false)
> -DEFINE_FIELD  (NX_ND_SLL,     MFF_ND_SLL,    false)
> -DEFINE_FIELD  (NX_ND_TLL,     MFF_ND_TLL,    false)
> -
> -DEFINE_FIELD_M(NX_REG0,       MFF_REG0,       true)
> -#if FLOW_N_REGS >= 2
> -DEFINE_FIELD_M(NX_REG1,       MFF_REG1,       true)
> -#endif
> -#if FLOW_N_REGS >= 3
> -DEFINE_FIELD_M(NX_REG2,       MFF_REG2,       true)
> -#endif
> -#if FLOW_N_REGS >= 4
> -DEFINE_FIELD_M(NX_REG3,       MFF_REG3,       true)
> -#endif
> -#if FLOW_N_REGS >= 5
> -DEFINE_FIELD_M(NX_REG4,       MFF_REG4,       true)
> -#endif
> -#if FLOW_N_REGS > 5
> -#error
> -#endif
> -
> -#undef DEFINE_FIELD
> diff --git a/lib/nx-match.h b/lib/nx-match.h
> index fbb8946..92545ef 100644
> --- a/lib/nx-match.h
> +++ b/lib/nx-match.h
> @@ -64,7 +64,6 @@ void nxm_reg_load(ovs_be32 dst, ovs_be16 ofs_nbits, uint64_t src_data,
>
>  int nxm_field_bytes(uint32_t header);
>  int nxm_field_bits(uint32_t header);
> -const struct mf_field *nxm_field_to_mf_field(uint32_t header);
>
>  const char *nxm_parse_field_bits(const char *s,
>                                  uint32_t *headerp, int *ofsp, int *n_bitsp);
> --
> 1.7.2.5
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>



More information about the dev mailing list