[ovs-dev] [PATCH v2 1/2] nx-match: Add support for multiple OXM field assignments for one field.

Jarno Rajahalme jrajahalme at nicira.com
Thu Oct 30 23:05:11 UTC 2014


Acked-by: Jarno Rajahalme <jrajahalme at nicira.com>

On Oct 9, 2014, at 11:10 PM, Ben Pfaff <blp at nicira.com> wrote:

> actset_output, to be added in an upcoming commit, has one OXM assignment
> in OpenFlow 1.3 and another one in OpenFlow 1.5.  This commit allows both
> of them to be supported in appropriate OpenFlow versions.
> 
> This feature is difficult to test on its own, so the same commit that adds
> actset_output support also tests this feature.
> 
> Signed-off-by: Ben Pfaff <blp at nicira.com>
> ---
> build-aux/extract-ofp-fields | 30 +++++++----------
> lib/meta-flow.h              |  5 +++
> lib/nx-match.c               | 78 +++++++++++++++-----------------------------
> 3 files changed, 44 insertions(+), 69 deletions(-)
> 
> diff --git a/build-aux/extract-ofp-fields b/build-aux/extract-ofp-fields
> index 95714ee..bdbba75 100755
> --- a/build-aux/extract-ofp-fields
> +++ b/build-aux/extract-ofp-fields
> @@ -122,10 +122,13 @@ def make_sizeof(s):
>     else:
>         return "sizeof(%s)" % s
> 
> -def parse_oxm(s, prefix, n_bytes):
> +def parse_oxms(s, prefix, n_bytes):
>     if s == 'none':
> -        return None
> +        return ()
> +
> +    return tuple(parse_oxm(s2.strip(), prefix, n_bytes) for s2 in s.split(','))
> 
> +def parse_oxm(s, prefix, n_bytes):
>     m = re.match('([A-Z0-9_]+)\(([0-9]+)\) since(?: OF(1\.[0-9]+) and)? v([12]\.[0-9]+)$', s)
>     if not m:
>         fatal("%s: syntax error parsing %s" % (s, prefix))
> @@ -247,8 +250,8 @@ def parse_field(mff, comment):
>     if not d['OF1.1'] in (None, 'exact match', 'bitwise mask'):
>         fatal("%s: unknown OF1.1 match type %s" % (mff, d['OF1.1']))
> 
> -    f['OXM'] = parse_oxm(d['OXM'], 'OXM', f['n_bytes'])
> -    f['NXM'] = parse_oxm(d['NXM'], 'NXM', f['n_bytes'])
> +    f['OXM'] = (parse_oxms(d['OXM'], 'OXM', f['n_bytes']) +
> +                parse_oxms(d['NXM'], 'NXM', f['n_bytes']))
> 
>     f['prefix'] = d["Prefix lookup member"]
> 
> @@ -284,13 +287,7 @@ def make_meta_flow(fields):
>         output += ["    %s, %s, %s, %s,"
>                    % (f['mask'], f['string'], f['prereqs'], rw)]
> 
> -        nxm = f['NXM']
>         oxm = f['OXM']
> -        if not nxm:
> -            nxm = oxm
> -        elif not oxm:
> -            oxm = nxm
> -
>         of10 = f['OF1.0']
>         of11 = f['OF1.1']
>         if f['mff'] in ('MFF_DL_VLAN', 'MFF_DL_VLAN_PCP'):
> @@ -305,7 +302,7 @@ def make_meta_flow(fields):
>                 protocols |= set(["of10"])
>             if of11:
>                 protocols |= set(["of11"])
> -            if nxm or oxm:
> +            if oxm:
>                 protocols |= set(["oxm"])
> 
>         if f['mask'] == 'MFM_FULLY':
> @@ -342,17 +339,14 @@ def make_meta_flow(fields):
>         output += ["},"]
>     return output
> 
> -def print_oxm_field(oxm, mff):
> -    if oxm:
> -        print """{ .nf = { %s, %d, "%s", %s } },""" % (
> -            oxm[0], oxm[2], oxm[1], mff)
> -
> def make_nx_match(fields):
>     output = []
>     print "static struct nxm_field_index all_nxm_fields[] = {";
>     for f in fields:
> -        print_oxm_field(f['NXM'], f['mff'])
> -        print_oxm_field(f['OXM'], f['mff'])
> +        # Sort by OpenFlow version number (nx-match.c depends on this).
> +        for oxm in sorted(f['OXM'], key=lambda x: x[2]):
> +            print """{ .nf = { %s, %d, "%s", %s } },""" % (
> +                oxm[0], oxm[2], oxm[1], f['mff'])
>     print "};"
>     return output
> 
> diff --git a/lib/meta-flow.h b/lib/meta-flow.h
> index 4607c7f..9518ba0 100644
> --- a/lib/meta-flow.h
> +++ b/lib/meta-flow.h
> @@ -215,6 +215,11 @@ struct match;
>  *     OXM (e.g. "since OF1.3 and v1.10" if it was introduced in OpenFlow 1.3
>  *     and first supported by Open vSwitch in version 1.10).
>  *
> + *     Some fields have more than one OXM field assignment.  For example,
> + *     actset_output has an experimenter OXM assignment in OpenFlow 1.3 and a
> + *     standard OXM assignment in OpenFlow 1.5.  In such a case, specify both,
> + *     separated by commas.
> + *
>  *     OVS uses the start of the OXM field name to determine the correct OXM
>  *     class.  To support a new OXM class, edit the mapping table in
>  *     build-aux/extract-ofp-fields.
> diff --git a/lib/nx-match.c b/lib/nx-match.c
> index 82b472c..04e0791 100644
> --- a/lib/nx-match.c
> +++ b/lib/nx-match.c
> @@ -140,14 +140,6 @@ nxm_header_len(uint64_t header)
>     return 4 + nxm_experimenter_len(header);
> }
> 
> -/* Returns true if 'header' is a legacy NXM header, false if it is an OXM
> - * header.*/
> -static bool
> -is_nxm_header(uint64_t header)
> -{
> -    return nxm_class(header) <= 1;
> -}
> -
> #define NXM_HEADER(VENDOR, CLASS, FIELD, HASMASK, LENGTH)       \
>     (((uint64_t) (CLASS) << 48) |                               \
>      ((uint64_t) (FIELD) << 41) |                               \
> @@ -197,8 +189,8 @@ struct nxm_field {
> 
> static const struct nxm_field *nxm_field_by_header(uint64_t header);
> static const struct nxm_field *nxm_field_by_name(const char *name, size_t len);
> -static const struct nxm_field *nxm_field_by_mf_id(enum mf_field_id);
> -static const struct nxm_field *oxm_field_by_mf_id(enum mf_field_id);
> +static const struct nxm_field *nxm_field_by_mf_id(enum mf_field_id,
> +                                                  enum ofp_version);
> 
> static void nx_put_header__(struct ofpbuf *, uint64_t header, bool masked);
> 
> @@ -209,14 +201,6 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> static const struct nxm_field *
> mf_parse_subfield_name(const char *name, int name_len, bool *wild);
> 
> -static const struct nxm_field *
> -nxm_field_from_mf_field(enum mf_field_id id, enum ofp_version version)
> -{
> -    const struct nxm_field *oxm = oxm_field_by_mf_id(id);
> -    const struct nxm_field *nxm = nxm_field_by_mf_id(id);
> -    return oxm && (version >= oxm->version || !nxm) ? oxm : nxm;
> -}
> -
> /* Returns the preferred OXM header to use for field 'id' in OpenFlow version
>  * 'version'.  Specify 0 for 'version' if an NXM legacy header should be
>  * preferred over any standardized OXM header.  Returns 0 if field 'id' cannot
> @@ -224,7 +208,7 @@ nxm_field_from_mf_field(enum mf_field_id id, enum ofp_version version)
> static uint64_t
> mf_oxm_header(enum mf_field_id id, enum ofp_version version)
> {
> -    const struct nxm_field *f = nxm_field_from_mf_field(id, version);
> +    const struct nxm_field *f = nxm_field_by_mf_id(id, version);
>     return f ? f->header : 0;
> }
> 
> @@ -264,16 +248,7 @@ nxm_field_bytes(uint64_t header)
>     unsigned int length = nxm_payload_len(header);
>     return nxm_hasmask(header) ? length / 2 : length;
> }
> -
> -/* Returns the earliest version of OpenFlow that standardized an OXM header for
> - * field 'id', or UINT8_MAX if no version of OpenFlow does. */
> -static enum ofp_version
> -mf_oxm_version(enum mf_field_id id)
> -{
> -    const struct nxm_field *oxm = oxm_field_by_mf_id(id);
> -    return oxm ? oxm->version : UINT8_MAX;
> -}
> - 
> +
> /* nx_pull_match() and helpers. */
> 
> /* Given NXM/OXM value 'value' and mask 'mask' associated with 'header', checks
> @@ -1541,7 +1516,7 @@ mf_format_subfield(const struct mf_subfield *sf, struct ds *s)
>     if (!sf->field) {
>         ds_put_cstr(s, "<unknown>");
>     } else {
> -        const struct nxm_field *f = nxm_field_from_mf_field(sf->field->id, 0);
> +        const struct nxm_field *f = nxm_field_by_mf_id(sf->field->id, 0);
>         ds_put_cstr(s, f ? f->name : sf->field->name);
>     }
> 
> @@ -1685,8 +1660,8 @@ oxm_bitmap_to_mf_bitmap(ovs_be64 oxm_bitmap, enum ofp_version version)
>     struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
> 
>     for (enum mf_field_id id = 0; id < MFF_N_IDS; id++) {
> -        if (version >= mf_oxm_version(id)) {
> -            uint64_t oxm = mf_oxm_header(id, version);
> +        uint64_t oxm = mf_oxm_header(id, version);
> +        if (oxm && version >= nxm_field_by_header(oxm)->version) {
>             uint32_t class = nxm_class(oxm);
>             int field = nxm_field(oxm);
> 
> @@ -1749,17 +1724,17 @@ oxm_maskable_fields(void)
> }
> 
> struct nxm_field_index {
> -    struct hmap_node header_node;
> -    struct hmap_node name_node;
> -    struct nxm_field nf;
> +    struct hmap_node header_node; /* In nxm_header_map. */
> +    struct hmap_node name_node;   /* In nxm_name_map. */
> +    struct list mf_node;          /* In mf_mf_map[nf.id]. */
> +    const struct nxm_field nf;
> };
> 
> #include "nx-match.inc"
> 
> static struct hmap nxm_header_map;
> static struct hmap nxm_name_map;
> -static struct nxm_field *nxm_fields[MFF_N_IDS];
> -static struct nxm_field *oxm_fields[MFF_N_IDS];
> +static struct list nxm_mf_map[MFF_N_IDS];
> 
> static void
> nxm_init(void)
> @@ -1768,17 +1743,16 @@ nxm_init(void)
>     if (ovsthread_once_start(&once)) {
>         hmap_init(&nxm_header_map);
>         hmap_init(&nxm_name_map);
> +        for (int i = 0; i < MFF_N_IDS; i++) {
> +            list_init(&nxm_mf_map[i]);
> +        }
>         for (struct nxm_field_index *nfi = all_nxm_fields;
>              nfi < &all_nxm_fields[ARRAY_SIZE(all_nxm_fields)]; nfi++) {
>             hmap_insert(&nxm_header_map, &nfi->header_node,
>                         hash_int(nfi->nf.header, 0));
>             hmap_insert(&nxm_name_map, &nfi->name_node,
>                         hash_string(nfi->nf.name, 0));
> -            if (is_nxm_header(nfi->nf.header)) {
> -                nxm_fields[nfi->nf.id] = &nfi->nf;
> -            } else {
> -                oxm_fields[nfi->nf.id] = &nfi->nf;
> -            }
> +            list_push_back(&nxm_mf_map[nfi->nf.id], &nfi->mf_node);
>         }
>         ovsthread_once_done(&once);
>     }
> @@ -1819,16 +1793,18 @@ nxm_field_by_name(const char *name, size_t len)
> }
> 
> static const struct nxm_field *
> -nxm_field_by_mf_id(enum mf_field_id id)
> +nxm_field_by_mf_id(enum mf_field_id id, enum ofp_version version)
> {
> -    nxm_init();
> -    return nxm_fields[id];
> -}
> +    const struct nxm_field_index *nfi;
> +    const struct nxm_field *f;
> 
> -static const struct nxm_field *
> -oxm_field_by_mf_id(enum mf_field_id id)
> -{
>     nxm_init();
> -    return oxm_fields[id];
> -}
> 
> +    f = NULL;
> +    LIST_FOR_EACH (nfi, mf_node, &nxm_mf_map[id]) {
> +        if (!f || version >= nfi->nf.version) {
> +            f = &nfi->nf;
> +        }
> +    }
> +    return f;
> +}
> -- 
> 2.1.0
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev




More information about the dev mailing list