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))
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"]
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'):
protocols |= set(["of10"])
if of11:
protocols |= set(["of11"])
- if nxm or oxm:
+ if oxm:
protocols |= set(["oxm"])
if f['mask'] == 'MFM_FULLY':
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
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) | \
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);
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
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;
}
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;
-}
- \f
+\f
/* nx_pull_match() and helpers. */
/* Given NXM/OXM value 'value' and mask 'mask' associated with 'header', checks
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);
}
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);
}
\f
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)
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);
}
}
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;
+}