Skip to content

Commit

Permalink
nx-match: Move all knowledge of OXM/NXM here.
Browse files Browse the repository at this point in the history
This improves the general abstraction of OXM/NXM by eliminating direct
knowledge of it from the meta-flow code and other places.

Some function renaming might be called for; for example, mf_oxm_header()
may not be the best name now that the function is implemented within
nx-match.  However, these renamings would make this commit larger and
harder to review, so I'm postponing them.

Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: YAMAMOTO Takashi <[email protected]>
  • Loading branch information
blp committed Oct 7, 2014
1 parent ba5cc06 commit 178742f
Show file tree
Hide file tree
Showing 14 changed files with 968 additions and 765 deletions.
206 changes: 113 additions & 93 deletions build-aux/extract-ofp-fields
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ def usage():
argv0 = os.path.basename(sys.argv[0])
print '''\
%(argv0)s, for extracting OpenFlow field properties from meta-flow.h
usage: %(argv0)s INPUT
usage: %(argv0)s INPUT [--meta-flow | --nx-match]
where INPUT points to lib/meta-flow.h in the source directory.
The output written to stdout is intended to be saved as lib/meta-flow.inc,
which lib/meta-flow.c \"#include\"s.\
Depending on the option given, the output written to stdout is intended to be
saved either as lib/meta-flow.inc or lib/nx-match.inc for the respective C
file to #include.\
''' % {"argv0": argv0}
sys.exit(0)

Expand All @@ -122,7 +123,7 @@ def parse_oxm(s, prefix, n_bytes):
class_ = oxm_name_to_class(name)
if class_ is None:
fatal("unknown OXM class for %s" % name)
header = ("NXM_HEADER(0x%04x, %s, %d)" % (class_, code, n_bytes))
header = ("NXM_HEADER(0x%04x,%s,0,%d)" % (class_, code, n_bytes))

if of_version:
if of_version not in VERSION:
Expand Down Expand Up @@ -244,7 +245,97 @@ def protocols_to_c(protocols):
else:
assert False

def extract_ofp_fields():
def make_meta_flow(fields):
output = []
for f in fields:
output += ["{"]
output += [" %s," % f['mff']]
if f['extra_name']:
output += [" \"%s\", \"%s\"," % (f['name'], f['extra_name'])]
else:
output += [" \"%s\", NULL," % f['name']]
output += [" %d, %d," % (f['n_bytes'], f['n_bits'])]

if f['writable']:
rw = 'true'
else:
rw = 'false'
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'):
# MFF_DL_VLAN and MFF_DL_VLAN_PCP don't exactly correspond to
# OF1.1, nor do they have NXM or OXM assignments, but their
# meanings can be expressed in every protocol, which is the goal of
# this member.
protocols = set(["of10", "of11", "oxm"])
else:
protocols = set([])
if of10:
protocols |= set(["of10"])
if of11:
protocols |= set(["of11"])
if nxm or oxm:
protocols |= set(["oxm"])

if f['mask'] == 'MFM_FULLY':
cidr_protocols = protocols.copy()
bitwise_protocols = protocols.copy()

if of10 == 'exact match':
bitwise_protocols -= set(['of10'])
cidr_protocols -= set(['of10'])
elif of10 == 'CIDR mask':
bitwise_protocols -= set(['of10'])
else:
assert of10 is None

if of11 == 'exact match':
bitwise_protocols -= set(['of11'])
cidr_protocols -= set(['of11'])
else:
assert of11 in (None, 'bitwise mask')
else:
assert f['mask'] == 'MFM_NONE'
cidr_protocols = set([])
bitwise_protocols = set([])

output += [" %s," % protocols_to_c(protocols)]
output += [" %s," % protocols_to_c(cidr_protocols)]
output += [" %s," % protocols_to_c(bitwise_protocols)]

if f['prefix']:
output += [" FLOW_U32OFS(%s)," % f['prefix']]
else:
output += [" -1, /* not usable for prefix lookup */"]

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'])
print "};"
return output

def extract_ofp_fields(mode):
global line

fields = []
Expand Down Expand Up @@ -349,110 +440,39 @@ def extract_ofp_fields():
if n_errors:
sys.exit(1)

output = []
output += ["/* Generated automatically; do not modify! "
"-*- buffer-read-only: t -*- */"]
output += [""]

for f in fields:
output += ["{"]
output += [" %s," % f['mff']]
if f['extra_name']:
output += [" \"%s\", \"%s\"," % (f['name'], f['extra_name'])]
else:
output += [" \"%s\", NULL," % f['name']]
output += [" %d, %d," % (f['n_bytes'], f['n_bits'])]

if f['writable']:
rw = 'true'
else:
rw = 'false'
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
if nxm:
output += [" %s, \"%s\"," % (nxm[0], nxm[1])]
output += [" %s, \"%s\", %s," % (oxm[0], oxm[1], oxm[2])]
else:
output += [" 0, NULL, 0, NULL, 0, /* no NXM or OXM */"]

of10 = f['OF1.0']
of11 = f['OF1.1']
if f['mff'] in ('MFF_DL_VLAN', 'MFF_DL_VLAN_PCP'):
# MFF_DL_VLAN and MFF_DL_VLAN_PCP don't exactly correspond to
# OF1.1, nor do they have NXM or OXM assignments, but their
# meanings can be expressed in every protocol, which is the goal of
# this member.
protocols = set(["of10", "of11", "oxm"])
else:
protocols = set([])
if of10:
protocols |= set(["of10"])
if of11:
protocols |= set(["of11"])
if nxm or oxm:
protocols |= set(["oxm"])
print """\
/* Generated automatically; do not modify! "-*- buffer-read-only: t -*- */
"""

if f['mask'] == 'MFM_FULLY':
cidr_protocols = protocols.copy()
bitwise_protocols = protocols.copy()

if of10 == 'exact match':
bitwise_protocols -= set(['of10'])
cidr_protocols -= set(['of10'])
elif of10 == 'CIDR mask':
bitwise_protocols -= set(['of10'])
else:
assert of10 is None

if of11 == 'exact match':
bitwise_protocols -= set(['of11'])
cidr_protocols -= set(['of11'])
else:
assert of11 in (None, 'bitwise mask')
else:
assert f['mask'] == 'MFM_NONE'
cidr_protocols = set([])
bitwise_protocols = set([])

output += [" %s," % protocols_to_c(protocols)]
output += [" %s," % protocols_to_c(cidr_protocols)]
output += [" %s," % protocols_to_c(bitwise_protocols)]

if f['prefix']:
output += [" FLOW_U32OFS(%s)," % f['prefix']]
else:
output += [" -1, /* not usable for prefix lookup */"]

output += ["},"]

if n_errors:
sys.exit(1)
if mode == '--meta-flow':
output = make_meta_flow(fields)
elif mode == '--nx-match':
output = make_nx_match(fields)
else:
assert False

return output


if __name__ == '__main__':
if '--help' in sys.argv:
usage()
elif len(sys.argv) != 2:
sys.stderr.write("exactly one non-option argument required; "
elif len(sys.argv) != 3:
sys.stderr.write("exactly two arguments required; "
"use --help for help\n")
sys.exit(1)
else:
elif sys.argv[2] in ('--meta-flow', '--nx-match'):
global file_name
global input_file
global line_number
file_name = sys.argv[1]
input_file = open(file_name)
line_number = 0

for oline in extract_ofp_fields():
for oline in extract_ofp_fields(sys.argv[2]):
print oline
else:
sys.stderr.write("invalid arguments; use --help for help\n")
sys.exit(1)


32 changes: 0 additions & 32 deletions include/openflow/nicira-ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,45 +467,13 @@ OFP_ASSERT(sizeof(struct nx_async_config) == 24);
* nx_match error.
*/

#define NXM_HEADER__(VENDOR, FIELD, HASMASK, LENGTH) \
(((VENDOR) << 16) | ((FIELD) << 9) | ((HASMASK) << 8) | (LENGTH))
#define NXM_HEADER(VENDOR, FIELD, LENGTH) \
NXM_HEADER__(VENDOR, FIELD, 0, LENGTH)
#define NXM_HEADER_W(VENDOR, FIELD, LENGTH) \
NXM_HEADER__(VENDOR, FIELD, 1, (LENGTH) * 2)
#define NXM_VENDOR(HEADER) ((HEADER) >> 16)
#define NXM_FIELD(HEADER) (((HEADER) >> 9) & 0x7f)
#define NXM_TYPE(HEADER) (((HEADER) >> 9) & 0x7fffff)
#define NXM_HASMASK(HEADER) (((HEADER) >> 8) & 1)
#define NXM_LENGTH(HEADER) ((HEADER) & 0xff)

#define NXM_MAKE_WILD_HEADER(HEADER) \
NXM_HEADER_W(NXM_VENDOR(HEADER), NXM_FIELD(HEADER), NXM_LENGTH(HEADER))

/* Number of registers allocated NXM field IDs. */
#define NXM_NX_MAX_REGS 16

/* Bits in the value of NXM_NX_IP_FRAG. */
#define NX_IP_FRAG_ANY (1 << 0) /* Is this a fragment? */
#define NX_IP_FRAG_LATER (1 << 1) /* Is this a fragment with nonzero offset? */

/* Flow cookie.
*
* This may be used to gain the OpenFlow 1.1-like ability to restrict
* certain NXM-based Flow Mod and Flow Stats Request messages to flows
* with specific cookies. See the "nx_flow_mod" and "nx_flow_stats_request"
* structure definitions for more details. This match is otherwise not
* allowed.
*
* Prereqs: None.
*
* Format: 64-bit integer in network byte order.
*
* Masking: Arbitrary masks. */
#define NXM_NX_COOKIE NXM_HEADER (0x0001, 30, 8)
#define NXM_NX_COOKIE_W NXM_HEADER_W(0x0001, 30, 8)


/* ## --------------------- ## */
/* ## Requests and replies. ## */
/* ## --------------------- ## */
Expand Down
16 changes: 0 additions & 16 deletions include/openflow/openflow-1.2.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,6 @@
/* Error type for experimenter error messages. */
#define OFPET12_EXPERIMENTER 0xffff

/*
* OXM Class IDs.
* The high order bit differentiate reserved classes from member classes.
* Classes 0x0000 to 0x7FFF are member classes, allocated by ONF.
* Classes 0x8000 to 0xFFFE are reserved classes, reserved for standardisation.
*/
enum ofp12_oxm_class {
OFPXMC12_NXM_0 = 0x0000, /* Backward compatibility with NXM */
OFPXMC12_NXM_1 = 0x0001, /* Backward compatibility with NXM */
OFPXMC12_OPENFLOW_BASIC = 0x8000, /* Basic class for OpenFlow */
OFPXMC15_PACKET_REGS = 0x8001, /* Packet registers (pipeline fields). */
OFPXMC12_EXPERIMENTER = 0xffff, /* Experimenter class */
};

#define IS_OXM_HEADER(header) (NXM_VENDOR(header) == OFPXMC12_OPENFLOW_BASIC)

/* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate
* special conditions.
*/
Expand Down
7 changes: 5 additions & 2 deletions lib/automake.mk
Original file line number Diff line number Diff line change
Expand Up @@ -444,9 +444,12 @@ lib/dirs.c: lib/dirs.c.in Makefile
mv lib/dirs.c.tmp lib/dirs.c

lib/meta-flow.inc: $(srcdir)/build-aux/extract-ofp-fields lib/meta-flow.h
$(AM_V_GEN)$(run_python) $^ > $@.tmp && mv $@.tmp $@
$(AM_V_GEN)$(run_python) $^ --meta-flow > $@.tmp && mv $@.tmp $@
lib/meta-flow.lo: lib/meta-flow.inc
CLEANFILES += lib/meta-flow.inc
lib/nx-match.inc: $(srcdir)/build-aux/extract-ofp-fields lib/meta-flow.h
$(AM_V_GEN)$(run_python) $^ --nx-match > $@.tmp && mv $@.tmp $@
lib/nx-match.lo: lib/nx-match.inc
CLEANFILES += lib/meta-flow.inc lib/nx-match.inc
EXTRA_DIST += build-aux/extract-ofp-fields

lib/ofp-actions.inc1: $(srcdir)/build-aux/extract-ofp-actions lib/ofp-actions.c
Expand Down
Loading

0 comments on commit 178742f

Please sign in to comment.