Merge remote-tracking branch 'upstream/master'
Conflicts:
c_gen/c_test_gen.py
java_gen/java_type.py
java_gen/pre-written/pom.xml
java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
loxi_ir/ir_offset.py
diff --git a/.build/push-artifacts.sh b/.build/push-artifacts.sh
index 8c7b60b..ec81d62 100755
--- a/.build/push-artifacts.sh
+++ b/.build/push-artifacts.sh
@@ -9,9 +9,11 @@
exit 1
fi
+ARTIFACT_REPO_BRANCH=${2-master}
+
ARTIFACT_REPO=$(mktemp -d --tmpdir "push-artifacts-repo.XXXXXXX")
-git clone ${ARTIFACT_REPO_URL} ${ARTIFACT_REPO}
+git clone ${ARTIFACT_REPO_URL} ${ARTIFACT_REPO} -b ${ARTIFACT_REPO_BRANCH}
find ${ARTIFACT_REPO} -mindepth 1 -maxdepth 1 -type d \! -name '.*' -print0 | xargs -0 rm -r
make LOXI_OUTPUT_DIR=${ARTIFACT_REPO} clean all
@@ -55,7 +57,7 @@
git tag -a -f "loxi/${loxi_head}" -m "Tag Loxigen Revision ${loxi_head}"
git push --tags
- git push
+ git push origin HEAD
)
rm -rf ${ARTIFACT_REPO}
diff --git a/Makefile b/Makefile
index 018db0b..5f3d8e5 100644
--- a/Makefile
+++ b/Makefile
@@ -131,6 +131,7 @@
PYTHONPATH=${LOXI_OUTPUT_DIR}/pyloxi:. python py_gen/tests/of11.py
PYTHONPATH=${LOXI_OUTPUT_DIR}/pyloxi:. python py_gen/tests/of12.py
PYTHONPATH=${LOXI_OUTPUT_DIR}/pyloxi:. python py_gen/tests/of13.py
+ PYTHONPATH=${LOXI_OUTPUT_DIR}/pyloxi:. python py_gen/tests/of14.py
check-c: c
make -j4 -C ${LOXI_OUTPUT_DIR}/locitest
diff --git a/c_gen/build_of_g.py b/c_gen/build_of_g.py
index 9b19af6..ace386d 100755
--- a/c_gen/build_of_g.py
+++ b/c_gen/build_of_g.py
@@ -119,135 +119,6 @@
if not m_name in of_g.ordered_members[cls]:
of_g.ordered_members[cls].append(m_name)
-def update_offset(cls, wire_version, name, offset, m_type):
- """
- Update (and return) the offset based on type.
- @param cls The parent class
- @param wire_version The wire version being processed
- @param name The name of the data member
- @param offset The current offset
- @param m_type The type declaration being processed
- @returns A pair (next_offset, len_update) next_offset is the new offset
- of the next object or -1 if this is a var-length object. len_update
- is the increment that should be added to the length. Note that (for
- of_match_v3) it is variable length, but it adds 8 bytes to the fixed
- length of the object
- If offset is already -1, do not update
- Otherwise map to base type and count and update (if possible)
- """
- if offset < 0: # Don't update offset once set to -1
- return offset, 0
-
- count, base_type = loxi_utils.type_dec_to_count_base(m_type)
-
- len_update = 0
- if base_type in of_g.of_mixed_types:
- base_type = of_g.of_mixed_types[base_type][wire_version]
-
- base_class = base_type[:-2]
- if (base_class, wire_version) in of_g.is_fixed_length:
- bytes = of_g.base_length[(base_class, wire_version)]
- else:
- if base_type == "of_match_v3_t":
- # This is a special case: it has non-zero min length
- # but is variable length
- bytes = -1
- len_update = 8
- elif base_type == "of_oxm_header_t":
- # This is a special case: it has non-zero min length
- # but is variable length
- bytes = -1
- len_update = 4
- elif base_type == "of_bsn_vport_header_t":
- # This is a special case: it has non-zero min length
- # but is variable length
- bytes = -1
- len_update = 4
- elif base_type in of_g.of_base_types:
- bytes = of_g.of_base_types[base_type]["bytes"]
- else:
- print "UNKNOWN TYPE for %s %s: %s" % (cls, name, base_type)
- log("UNKNOWN TYPE for %s %s: %s" % (cls, name, base_type))
- bytes = -1
-
- # If bytes
- if bytes > 0:
- len_update = count * bytes
-
- if bytes == -1:
- return -1, len_update
-
- return offset + (count * bytes), len_update
-
-def calculate_offsets_and_lengths(ordered_classes, classes, wire_version):
- """
- Generate the offsets for fixed offset class members
- Also calculate the class_sizes when possible.
-
- @param classes The classes to process
- @param wire_version The wire version for this set of classes
-
- Updates global variables
- """
-
- lists = set()
-
- # Generate offsets
- for cls in ordered_classes:
- fixed_offset = 0 # The last "good" offset seen
- offset = 0
- last_offset = 0
- last_name = "-"
- for member in classes[cls]:
- m_type = member["m_type"]
- name = member["name"]
- if last_offset == -1:
- if name == "pad":
- log("Skipping pad for special offset for %s" % cls)
- else:
- log("SPECIAL OFS: Member %s (prev %s), class %s ver %d" %
- (name, last_name, cls, wire_version))
- if (((cls, name) in of_g.special_offsets) and
- (of_g.special_offsets[(cls, name)] != last_name)):
- debug("ERROR: special offset prev name changed")
- debug(" cls %s. name %s. version %d. was %s. now %s" %
- cls, name, wire_version,
- of_g.special_offsets[(cls, name)], last_name)
- sys.exit(1)
- of_g.special_offsets[(cls, name)] = last_name
-
- member["offset"] = offset
- if m_type.find("list(") == 0:
- (list_name, base_type) = loxi_utils.list_name_extract(m_type)
- lists.add(list_name)
- member["m_type"] = list_name + "_t"
- offset = -1
- elif m_type.find("struct") == 0:
- debug("ERROR found struct: %s.%s " % (cls, name))
- sys.exit(1)
- elif m_type == "octets":
- log("offset gen skipping octets: %s.%s " % (cls, name))
- offset = -1
- else:
- offset, len_update = update_offset(cls, wire_version, name,
- offset, m_type)
- if offset != -1:
- fixed_offset = offset
- else:
- fixed_offset += len_update
- log("offset is -1 for %s.%s version %d " %
- (cls, name, wire_version))
- last_offset = offset
- last_name = name
- of_g.base_length[(cls, wire_version)] = fixed_offset
- if (offset != -1):
- of_g.is_fixed_length.add((cls, wire_version))
-
- for list_type in lists:
- classes[list_type] = []
- of_g.ordered_classes[wire_version].append(list_type)
- of_g.base_length[(list_type, wire_version)] = 0
-
def order_and_assign_object_ids():
"""
Order all classes and assign object ids to all classes.
@@ -329,27 +200,30 @@
pad_count = 0
for m in ofclass.members:
if type(m) == OFPadMember:
- m_name = 'pad%d' % pad_count
- if m_name == 'pad0': m_name = 'pad'
- legacy_members.append(dict(m_type='uint8_t[%d]' % m.length,
- name=m_name))
- pad_count += 1
+ continue
else:
- # HACK the C backend does not yet support of_oxm_t
- if m.oftype == 'of_oxm_t':
- m_type = 'of_oxm_header_t'
- # HACK the C backend does not yet support of_bsn_vport_t
- elif m.oftype == 'of_bsn_vport_t':
- m_type = 'of_bsn_vport_header_t'
+ if m.oftype.find("list(") == 0:
+ (list_name, base_type) = loxi_utils.list_name_extract(m.oftype)
+ m_type = list_name + "_t"
else:
enum = find(lambda e: e.name == m.oftype, protocol.enums)
if enum and "wire_type" in enum.params:
m_type = enum.params["wire_type"]
else:
m_type = m.oftype
- legacy_members.append(dict(m_type=m_type, name=m.name))
+
+ if m.offset is None:
+ m_offset = -1
+ else:
+ m_offset = m.offset
+
+ legacy_members.append(dict(m_type=m_type, name=m.name, offset=m_offset))
versions[version_name]['classes'][ofclass.name] = legacy_members
+ of_g.base_length[(ofclass.name, version.wire_version)] = ofclass.base_length
+ if ofclass.is_fixed_length:
+ of_g.is_fixed_length.add((ofclass.name, version.wire_version))
+
for enum in protocol.enums:
for entry in enum.entries:
identifiers.add_identifier(
@@ -361,81 +235,6 @@
"""
Use the type members in the IR to fill out the legacy type_maps.
"""
-
- def split_inherited_cls(cls):
- if cls == 'of_meter_band_stats': # HACK not a subtype of of_meter_band
- return None, None
- for parent in sorted(type_maps.inheritance_data.keys(), reverse=True):
- if cls.startswith(parent):
- return (parent, cls[len(parent)+1:])
- return None, None
-
- def find_experimenter(parent, cls):
- for experimenter in sorted(of_g.experimenter_name_to_id.keys(), reverse=True):
- prefix = parent + '_' + experimenter
- if cls.startswith(prefix) and cls != prefix:
- return experimenter
- return None
-
- def find_type_value(ofclass, m_name):
- for m in ofclass.members:
- if isinstance(m, OFTypeMember) and m.name == m_name:
- return m.value
- raise KeyError("ver=%d, cls=%s, m_name=%s" % (wire_version, cls, m_name))
-
- # Most inheritance classes: actions, instructions, etc
- for version, protocol in loxi_globals.ir.items():
- wire_version = version.wire_version
- for ofclass in protocol.classes:
- cls = ofclass.name
- parent, subcls = split_inherited_cls(cls)
- if not (parent and subcls):
- continue
- if parent == 'of_oxm':
- type_len = find_type_value(ofclass, 'type_len')
- oxm_class = (type_len >> 16) & 0xffff
- if oxm_class != 0x8000:
- # Do not include experimenter OXMs in the main table
- val = type_maps.invalid_type
- else:
- val = (type_len >> 8) & 0xff
- else:
- val = find_type_value(ofclass, 'type')
- type_maps.inheritance_data[parent][wire_version][subcls] = val
-
- # Extensions (only actions for now)
- experimenter = find_experimenter(parent, cls)
- if parent == 'of_action' and experimenter:
- val = find_type_value(ofclass, 'subtype')
- type_maps.extension_action_subtype[wire_version][experimenter][cls] = val
- if wire_version >= of_g.VERSION_1_3:
- cls2 = parent + "_id" + cls[len(parent):]
- type_maps.extension_action_id_subtype[wire_version][experimenter][cls2] = val
- elif parent == 'of_instruction' and experimenter:
- val = find_type_value(ofclass, 'subtype')
- type_maps.extension_instruction_subtype[wire_version][experimenter][cls] = val
-
- # Messages
- for version, protocol in loxi_globals.ir.items():
- wire_version = version.wire_version
- for ofclass in protocol.classes:
- cls = ofclass.name
- # HACK (though this is what loxi_utils.class_is_message() does)
- if not [x for x in ofclass.members if isinstance(x, OFDataMember) and x.name == 'xid']:
- continue
- if type_maps.class_is_virtual(cls):
- continue
- subcls = cls[3:]
- val = find_type_value(ofclass, 'type')
- if not val in type_maps.message_types[wire_version].values():
- type_maps.message_types[wire_version][subcls] = val
-
- # Extensions
- experimenter = find_experimenter('of', cls)
- if experimenter and ofclass.is_subclassof("of_experimenter"):
- val = find_type_value(ofclass, 'subtype')
- type_maps.extension_message_subtype[wire_version][experimenter][cls] = val
-
type_maps.generate_maps()
def analyze_input():
@@ -443,22 +242,38 @@
Add information computed from the input, including offsets and
lengths of struct members and the set of list and action_id types.
"""
+ # Create lists
+ for version, protocol in loxi_globals.ir.items():
+ lists = set()
+ classes = versions[of_g.of_version_wire2name[version.wire_version]]['classes']
- # Generate header classes for inheritance parents
- for wire_version, ordered_classes in of_g.ordered_classes.items():
- classes = versions[of_g.of_version_wire2name[wire_version]]['classes']
- for cls in ordered_classes:
- if cls in type_maps.inheritance_map:
- new_cls = cls + '_header'
- of_g.ordered_classes[wire_version].append(new_cls)
- classes[new_cls] = classes[cls]
+ for ofclass in protocol.classes:
+ for m in ofclass.members:
+ if isinstance(m, OFDataMember) and m.oftype.find("list(") == 0:
+ (list_name, base_type) = loxi_utils.list_name_extract(m.oftype)
+ lists.add(list_name)
- for wire_version in of_g.wire_ver_map.keys():
- version_name = of_g.of_version_wire2name[wire_version]
- calculate_offsets_and_lengths(
- of_g.ordered_classes[wire_version],
- versions[version_name]['classes'],
- wire_version)
+ for list_type in lists:
+ classes[list_type] = []
+ of_g.ordered_classes[version.wire_version].append(list_type)
+ of_g.base_length[(list_type, version.wire_version)] = 0
+
+ # Find special offsets
+ # These are defined as members (except padding) that don't have a fixed
+ # offset. The special_offsets map stores the name of the previous member.
+ for version, protocol in loxi_globals.ir.items():
+ for ofclass in protocol.classes:
+ prev_member = None
+ for m in ofclass.members:
+ if isinstance(m, OFPadMember):
+ continue
+ if m.offset == None:
+ old = of_g.special_offsets.get((ofclass.name, m.name))
+ if old and old != prev_member.name:
+ raise Exception("Error: special offset changed: version=%s cls=%s member=%s old=%s new=%s" %
+ (version, ofclass.name, m.name, old, prev_member.name))
+ of_g.special_offsets[(ofclass.name, m.name)] = prev_member.name
+ prev_member = m
def unify_input():
"""
diff --git a/c_gen/c_code_gen.py b/c_gen/c_code_gen.py
index 484e941..896e9ad 100644
--- a/c_gen/c_code_gen.py
+++ b/c_gen/c_code_gen.py
@@ -403,7 +403,6 @@
int of_object_wire_init(of_object_t *obj, of_object_id_t base_object_id, int max_len);
extern const int *const of_object_fixed_len[OF_VERSION_ARRAY_MAX];
-extern const int *const of_object_extra_len[OF_VERSION_ARRAY_MAX];
""")
c_type_maps.gen_type_data_header(out)
c_match.gen_declarations(out)
@@ -530,7 +529,7 @@
/**
* Check if a version is supported
*/
-#define OF_VERSION_OKAY(v) ((v) >= OF_VERSION_1_0 && (v) <= OF_VERSION_1_3)
+#define OF_VERSION_OKAY(v) ((v) >= OF_VERSION_1_0 && (v) <= OF_VERSION_1_4)
""")
gen_version_enum(out)
@@ -617,19 +616,26 @@
uint8_t addr[OF_IPV6_BYTES];
} of_ipv6_t;
+typedef struct of_bitmap_512_s {
+ uint64_t words[8];
+} of_bitmap_512_t;
+
extern const of_mac_addr_t of_mac_addr_all_ones;
extern const of_mac_addr_t of_mac_addr_all_zeros;
extern const of_ipv6_t of_ipv6_all_ones;
extern const of_ipv6_t of_ipv6_all_zeros;
+extern const of_bitmap_512_t of_bitmap_512_all_ones;
+extern const of_bitmap_512_t of_bitmap_512_all_zeroes;
+
/**
* Generic zero and all-ones values of size 16 bytes.
*
- * IPv6 is longest data type we worry about for comparisons
+ * bitmap_512 is longest data type we worry about for comparisons
*/
-#define of_all_zero_value of_ipv6_all_zeros
-#define of_all_ones_value of_ipv6_all_ones
+#define of_all_zero_value of_bitmap_512_all_zeroes
+#define of_all_ones_value of_bitmap_512_all_ones
/**
* Non-zero/all ones check for arbitrary type of size <= 16 bytes
@@ -726,24 +732,6 @@
#define U64_HTON(val) U64_NTOH(val)
#define IPV6_HTON(dst, src) /* NOTE different syntax; currently no-op */
#endif
-
-/****************************************************************
- *
- * The following are internal definitions used by the automatically
- * generated code. Users should not reference these definitions
- * as they may change between versions of this code
- *
- ****************************************************************/
-
-#define OF_MESSAGE_IN_MATCH_POINTER(obj) \\
- (WIRE_BUF_POINTER(&((obj)->wire_buffer), OF_MESSAGE_IN_MATCH_OFFSET))
-#define OF_MESSAGE_IN_MATCH_LEN(ptr) BUF_U16_GET(&ptr[2])
-#define OF_MESSAGE_IN_DATA_OFFSET(obj) \\
- (FIXED_LEN + OF_MESSAGE_IN_MATCH_LEN(OF_MESSAGE_IN_MATCH_POINTER(obj)) + 2)
-
-#define OF_MESSAGE_OUT_DATA_OFFSET(obj) \\
- (FIXED_LEN + of_message_out_actions_len_get(obj))
-
""")
def external_h_top_matter(out, name):
@@ -773,7 +761,6 @@
* Per-class static delete functions
* Per-class, per-member accessor declarations
* Per-class structure definitions
- * Generic union (inheritance) definitions
* Pointer set function declarations
* Some special case macros
*
@@ -875,61 +862,6 @@
#define OF_MESSAGE_OBJECT_COUNT %d
""" % ((last + 1), msg_count))
- # Generate object type range checking for inheritance classes
-
- # @fixme These should be determined algorithmicly
- out.write("""
-/*
- * Macros to check if an object ID is within an inheritance class range
- */
-""")
- # Alphabetical order for 'last'
- last_ids = dict(of_action="OF_ACTION_STRIP_VLAN",
- of_oxm="OF_OXM_VLAN_VID_MASKED",
- of_instruction="OF_INSTRUCTION_WRITE_METADATA",
- of_queue_prop="OF_QUEUE_PROP_MIN_RATE",
- of_table_feature_prop="OF_TABLE_FEATURE_PROP_WRITE_SETFIELD_MISS",
- # @FIXME add meter_band ?
- )
- for cls, last in last_ids.items():
- out.write("""
-#define %(enum)s_FIRST_ID (%(enum)s + 1)
-#define %(enum)s_LAST_ID %(last)s
-#define %(enum)s_VALID_ID(id) \\
- ((id) >= %(enum)s_FIRST_ID && \\
- (id) <= %(enum)s_LAST_ID)
-""" % dict(enum=enum_name(cls), last=last))
- out.write("""
-/**
- * Function to check a wire ID
- * @param object_id The ID to check
- * @param base_object_id The inheritance parent, if applicable
- * @returns boolean: If base_object_id is an inheritance class, check if
- * object_id is valid as a subclass. Otherwise return 1.
- *
- * Note: Could check that object_id == base_object_id in the
- * second case.
- */
-static inline int
-of_wire_id_valid(int object_id, int base_object_id) {
- switch (base_object_id) {
- case OF_ACTION:
- return OF_ACTION_VALID_ID(object_id);
- case OF_OXM:
- return OF_OXM_VALID_ID(object_id);
- case OF_QUEUE_PROP:
- return OF_QUEUE_PROP_VALID_ID(object_id);
- case OF_TABLE_FEATURE_PROP:
- return OF_TABLE_FEATURE_PROP_VALID_ID(object_id);
- case OF_INSTRUCTION:
- return OF_INSTRUCTION_VALID_ID(object_id);
- default:
- break;
- }
- return 1;
-}
-""")
-
################################################################
#
# Internal Utility Functions
@@ -1041,37 +973,14 @@
#
################################################################
-def gen_generics(out):
- for (cls, subclasses) in type_maps.inheritance_map.items():
- out.write("""
-/**
- * Inheritance super class for %(cls)s
- *
- * This class is the union of %(cls)s classes. You can refer
- * to it untyped by refering to the member 'header' whose structure
- * is common across all sub-classes.
- */
-
-union %(cls)s_u {
- %(cls)s_header_t header; /* Generic instance */
-""" % dict(cls=cls))
- for subcls in sorted(subclasses):
- out.write(" %s_%s_t %s;\n" % (cls, subcls, subcls))
- out.write("};\n")
-
def gen_struct_typedefs(out):
"""
Generate typedefs for all struct objects
@param out The file for output, already open
"""
- out.write("\n/* LOCI inheritance parent typedefs */\n")
- for cls in type_maps.inheritance_map:
- out.write("typedef union %(cls)s_u %(cls)s_t;\n" % dict(cls=cls))
out.write("\n/* LOCI object typedefs */\n")
for cls in of_g.standard_class_order:
- if cls in type_maps.inheritance_map:
- continue
template = "typedef of_object_t %(cls)s_t;\n"
out.write(template % dict(cls=cls))
@@ -1110,7 +1019,7 @@
****************************************************************/
""")
for cls in of_g.standard_class_order:
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls) and not loxi_utils.class_is_list(cls):
continue
out.write("\n/* Unified accessor functions for %s */\n" % cls)
for m_name in of_g.ordered_members[cls]:
@@ -1150,13 +1059,13 @@
e_type = loxi_utils.list_to_entry_type(cls)
out.write("""
extern int %(cls)s_first(
- %(cls)s_t *list, %(e_type)s_t *obj);
+ %(cls)s_t *list, of_object_t *iter);
extern int %(cls)s_next(
- %(cls)s_t *list, %(e_type)s_t *obj);
+ %(cls)s_t *list, of_object_t *iter);
extern int %(cls)s_append_bind(
- %(cls)s_t *list, %(e_type)s_t *obj);
+ %(cls)s_t *list, of_object_t *iter);
extern int %(cls)s_append(
- %(cls)s_t *list, %(e_type)s_t *obj);
+ %(cls)s_t *list, of_object_t *iter);
/**
* Iteration macro for list of type %(cls)s
@@ -1298,7 +1207,7 @@
LOCI_ASSERT(cur_len + abs_offset <= WBUF_CURRENT_BYTES(wbuf));
OF_TRY(of_match_deserialize(ver, %(m_name)s, obj, offset, cur_len));
""" % dict(m_name=m_name))
- elif m_type == "of_oxm_header_t":
+ elif m_type == "of_oxm_t":
out.write("""
/* Initialize child */
%(m_type)s_init(%(m_name)s, obj->version, 0, 1);
@@ -1306,7 +1215,7 @@
of_object_attach(obj, %(m_name)s, offset, cur_len);
of_object_wire_init(%(m_name)s, OF_OXM, 0);
""" % dict(m_type=m_type[:-2], m_name=m_name))
- elif m_type == "of_bsn_vport_header_t":
+ elif m_type == "of_bsn_vport_t":
out.write("""
/* Initialize child */
%(m_type)s_init(%(m_name)s, obj->version, 0, 1);
@@ -1630,10 +1539,6 @@
@param cls The class name for the function
@param out The file to which to write
"""
- if cls in type_maps.inheritance_map:
- param = "obj_p"
- else:
- param = "obj"
out.write("""
/**
@@ -1654,33 +1559,20 @@
*/
void
-%(cls)s_init(%(cls)s_t *%(param)s,
+%(cls)s_init(of_object_t *obj,
of_version_t version, int bytes, int clean_wire)
{
-""" % dict(cls=cls, param=param))
-
- # Use an extra pointer to deal with inheritance classes
- if cls in type_maps.inheritance_map:
- out.write("""\
- %s_header_t *obj;
-
- obj = &obj_p->header; /* Need instantiable subclass */
-""" % cls)
-
- out.write("""
LOCI_ASSERT(of_object_fixed_len[version][%(enum)s] >= 0);
if (clean_wire) {
MEMSET(obj, 0, sizeof(*obj));
}
if (bytes < 0) {
- bytes = of_object_fixed_len[version][%(enum)s] + of_object_extra_len[version][%(enum)s];
+ bytes = of_object_fixed_len[version][%(enum)s];
}
obj->version = version;
obj->length = bytes;
obj->object_id = %(enum)s;
-""" % dict(cls=cls, enum=enum_name(cls)))
- out.write("""
/* Grow the wire buffer */
if (obj->wbuf != NULL) {
int tot_bytes;
@@ -1689,66 +1581,7 @@
of_wire_buffer_grow(obj->wbuf, tot_bytes);
}
}
-
-""")
-
-## @fixme This should also be updated once there is a map from
-# class instance to wire length/type accessors
-def gen_wire_push_fn(cls, out):
- """
- Generate the calls to push values into the wire buffer
- """
- if type_maps.class_is_virtual(cls):
- print "Push fn gen called for virtual class " + cls
- return
-
- out.write("""
-/**
- * Helper function to push values into the wire buffer
- */
-static inline int
-%(cls)s_push_wire_values(%(cls)s_t *obj)
-{
-""" % dict(cls=cls))
-
- import loxi_globals
- uclass = loxi_globals.unified.class_by_name(cls)
- if uclass and not uclass.virtual and uclass.has_type_members:
- out.write("""
- %(cls)s_push_wire_types(obj);
-""" % dict(cls=cls))
-
- if loxi_utils.class_is_message(cls):
- out.write("""
- /* Message obj; set length */
- of_message_t msg;
-
- if ((msg = OF_OBJECT_TO_MESSAGE(obj)) != NULL) {
- of_message_length_set(msg, obj->length);
- }
-""" % dict(name = enum_name(cls)))
-
- else: # Not a message
- if loxi_utils.class_is_tlv16(cls):
- out.write("""
- /* TLV obj; set length */
- of_tlv16_wire_length_set((of_object_t *)obj, obj->length);
-""" % dict(enum=enum_name(cls)))
-
- if loxi_utils.class_is_u16_len(cls) or cls == "of_packet_queue":
- out.write("""
- of_object_wire_length_set((of_object_t *)obj, obj->length);
-""")
-
- if cls == "of_meter_stats":
- out.write("""
- of_meter_stats_wire_length_set((of_object_t *)obj, obj->length);
-""" % dict(enum=enum_name(cls)))
-
- out.write("""
- return OF_ERROR_NONE;
-}
-""")
+""" % dict(cls=cls, enum=enum_name(cls)))
def gen_new_fn_body(cls, out):
"""
@@ -1763,9 +1596,6 @@
*/
""" % dict(cls=cls))
- if not type_maps.class_is_virtual(cls):
- gen_wire_push_fn(cls, out)
-
uclass = loxi_globals.unified.class_by_name(cls)
is_fixed_length = uclass and uclass.is_fixed_length
max_length = is_fixed_length and "bytes" or "OF_WIRE_BUFFER_MAX_LENGTH"
@@ -1783,35 +1613,40 @@
* \\ingroup %(cls)s
*/
-%(cls)s_t *
+of_object_t *
%(cls)s_new(of_version_t version)
{
- %(cls)s_t *obj;
+ of_object_t *obj;
int bytes;
- bytes = of_object_fixed_len[version][%(enum)s] + of_object_extra_len[version][%(enum)s];
+ bytes = of_object_fixed_len[version][%(enum)s];
- if ((obj = (%(cls)s_t *)of_object_new(%(max_length)s)) == NULL) {
+ if ((obj = of_object_new(%(max_length)s)) == NULL) {
return NULL;
}
%(cls)s_init(obj, version, bytes, 0);
""" % dict(cls=cls, enum=enum_name(cls), max_length=max_length))
if not type_maps.class_is_virtual(cls):
- out.write("""
- if (%(cls)s_push_wire_values(obj) < 0) {
- FREE(obj);
- return NULL;
- }
-""" % dict(cls=cls))
+ from codegen import class_metadata_dict
+ metadata = class_metadata_dict[cls]
+
+ if metadata.wire_type_set != 'NULL':
+ out.write("""\
+ %s(obj);
+""" % metadata.wire_type_set)
+
+ if metadata.wire_length_set != 'NULL':
+ out.write("""\
+ %s(obj, obj->length);
+""" % metadata.wire_length_set)
match_offset = v3_match_offset_get(cls)
if match_offset >= 0:
# Init length field for match object
out.write("""
/* Initialize match TLV for 1.2 */
- /* FIXME: Check 1.3 below */
- if ((version == OF_VERSION_1_2) || (version == OF_VERSION_1_3)) {
+ if ((version >= OF_VERSION_1_2)) {
of_object_u16_set((of_object_t *)obj, %(match_offset)d + 2, 4);
}
""" % dict(match_offset=match_offset))
@@ -1847,11 +1682,11 @@
for cls in of_g.standard_class_order:
out.write("""
-extern %(cls)s_t *
+extern of_object_t *
%(cls)s_new(of_version_t version);
""" % dict(cls=cls))
out.write("""extern void %(cls)s_init(
- %(cls)s_t *obj, of_version_t version, int bytes, int clean_wire);
+ of_object_t *obj, of_version_t version, int bytes, int clean_wire);
""" % dict(cls=cls))
out.write("""
@@ -1863,8 +1698,6 @@
****************************************************************/
""")
for cls in of_g.standard_class_order:
-# if cls in type_maps.inheritance_map:
-# continue
out.write("""
/**
* Delete an object of type %(cls)s_t
@@ -1873,8 +1706,8 @@
* \ingroup %(cls)s
*/
static inline void
-%(cls)s_delete(%(cls)s_t *obj) {
- of_object_delete((of_object_t *)(obj));
+%(cls)s_delete(of_object_t *obj) {
+ of_object_delete(obj);
}
""" % dict(cls=cls))
@@ -1922,8 +1755,8 @@
out.write("/* DOCUMENTATION ONLY */\n")
for cls in of_g.standard_class_order:
- if cls in type_maps.inheritance_map:
- pass # Check this
+ if type_maps.class_is_virtual(cls):
+ pass
out.write("""
/**
diff --git a/c_gen/c_dump_gen.py b/c_gen/c_dump_gen.py
index d4a016c..799dc09 100644
--- a/c_gen/c_dump_gen.py
+++ b/c_gen/c_dump_gen.py
@@ -90,10 +90,10 @@
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls):
continue
out.write("""\
-int %(cls)s_%(ver_name)s_dump(loci_writer_f writer, void* cookie, %(cls)s_t *obj);
+int %(cls)s_%(ver_name)s_dump(loci_writer_f writer, void* cookie, of_object_t *obj);
""" % dict(cls=cls, ver_name=loxi_utils.version_to_name(version)))
out.write("""
@@ -129,11 +129,11 @@
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls):
continue
out.write("""
int
-%(cls)s_%(ver_name)s_dump(loci_writer_f writer, void* cookie, %(cls)s_t *obj)
+%(cls)s_%(ver_name)s_dump(loci_writer_f writer, void* cookie, of_object_t *obj)
{
int out = 0;
""" % dict(cls=cls, ver_name=ver_name))
@@ -150,7 +150,7 @@
""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
if loxi_utils.class_is_list(m_type):
base_type = loxi_utils.list_to_entry_type(m_type)
- out.write(" %s elt;\n int rv;\n" % base_type)
+ out.write(" of_object_t elt;\n int rv;\n")
out.write("""
out += writer(cookie, "Object of type %(cls)s\\n");
""" % dict(cls=cls))
@@ -184,7 +184,7 @@
sub_cls = m_type[:-2] # Trim _t
out.write("""
%(cls)s_%(m_name)s_bind(obj, &%(v_name)s);
- out += %(sub_cls)s_%(ver_name)s_dump(writer, cookie, &%(v_name)s);
+ out += of_object_dump(writer, cookie, &%(v_name)s);
""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name,
v_name=var_name_map(m_type), ver_name=ver_name))
@@ -234,7 +234,7 @@
comma = ","
if (not loxi_utils.class_in_version(cls, version) or
- cls in type_maps.inheritance_map):
+ type_maps.class_is_virtual(cls)):
out.write(" unknown_dump%s\n" % comma);
else:
out.write(" %s_%s_dump%s\n" %
@@ -242,20 +242,20 @@
out.write("};\n\n")
out.write("""
-static const loci_obj_dump_f *const dump_funs[5] = {
- NULL,
- dump_funs_v1,
- dump_funs_v2,
- dump_funs_v3,
- dump_funs_v4
+static const loci_obj_dump_f *const dump_funs[] = {
+""")
+
+ for version in of_g.of_version_range:
+ out.write(" [%(v)d] = dump_funs_v%(v)d,\n" % dict(v=version))
+
+ out.write("""\
};
int
of_object_dump(loci_writer_f writer, void* cookie, of_object_t *obj)
{
if ((obj->object_id > 0) && (obj->object_id < OF_OBJECT_COUNT)) {
- if (((obj)->version > 0) && ((obj)->version <= OF_VERSION_1_3)) {
- /* @fixme VERSION */
+ if (OF_VERSION_OKAY(obj->version)) {
return dump_funs[obj->version][obj->object_id](writer, cookie, (of_object_t *)obj);
} else {
return writer(cookie, "Bad version %d\\n", obj->version);
diff --git a/c_gen/c_match.py b/c_gen/c_match.py
index 3afc99c..ccc503d 100644
--- a/c_gen/c_match.py
+++ b/c_gen/c_match.py
@@ -104,6 +104,13 @@
#define of_match_v4_to_match of_match_v3_to_match
#define of_match_to_wire_match_v4 of_match_to_wire_match_v3
#define of_match_v4_delete of_match_v3_delete
+
+#define of_match_v5_t of_match_v3_t
+#define of_match_v5_init of_match_v3_init
+#define of_match_v5_new of_match_v3_new
+#define of_match_v5_to_match of_match_v3_to_match
+#define of_match_to_wire_match_v5 of_match_to_wire_match_v3
+#define of_match_v5_delete of_match_v3_delete
""")
def gen_match_macros(out):
@@ -451,7 +458,7 @@
static int
populate_oxm_list(of_match_t *src, of_list_oxm_t *oxm_list)
{
- of_oxm_t oxm_entry;
+ of_object_t elt;
/* For each active member, add an OXM entry to the list */
""")
@@ -459,23 +466,18 @@
out.write("""\
if (OF_MATCH_MASK_%(ku)s_ACTIVE_TEST(src)) {
if (!OF_MATCH_MASK_%(ku)s_EXACT_TEST(src)) {
- of_oxm_%(key)s_masked_t *elt;
- elt = &oxm_entry.%(key)s_masked;
-
- of_oxm_%(key)s_masked_init(elt,
+ of_oxm_%(key)s_masked_init(&elt,
oxm_list->version, -1, 1);
- of_list_oxm_append_bind(oxm_list, &oxm_entry);
- of_oxm_%(key)s_masked_value_set(elt,
+ of_list_oxm_append_bind(oxm_list, &elt);
+ of_oxm_%(key)s_masked_value_set(&elt,
src->fields.%(key)s);
- of_oxm_%(key)s_masked_value_mask_set(elt,
+ of_oxm_%(key)s_masked_value_mask_set(&elt,
src->masks.%(key)s);
} else { /* Active, but not masked */
- of_oxm_%(key)s_t *elt;
- elt = &oxm_entry.%(key)s;
- of_oxm_%(key)s_init(elt,
+ of_oxm_%(key)s_init(&elt,
oxm_list->version, -1, 1);
- of_list_oxm_append_bind(oxm_list, &oxm_entry);
- of_oxm_%(key)s_value_set(elt, src->fields.%(key)s);
+ of_list_oxm_append_bind(oxm_list, &elt);
+ of_oxm_%(key)s_value_set(&elt, src->fields.%(key)s);
}
}
""" % dict(key=key, ku=key.upper()))
@@ -622,7 +624,7 @@
{
int rv;
of_list_oxm_t oxm_list;
- of_oxm_t oxm_entry;
+ of_object_t oxm_entry;
""")
# for key in match.of_match_members:
# out.write(" of_oxm_%s_t *%s;\n" % (key, key))
@@ -636,23 +638,23 @@
rv = of_list_oxm_first(&oxm_list, &oxm_entry);
while (rv == OF_ERROR_NONE) {
- switch (oxm_entry.header.object_id) { /* What kind of entry is this */
+ switch (oxm_entry.object_id) { /* What kind of entry is this */
""")
for key in match.of_match_members:
out.write("""
case OF_OXM_%(ku)s_MASKED:
of_oxm_%(key)s_masked_value_mask_get(
- &oxm_entry.%(key)s_masked,
+ &oxm_entry,
&dst->masks.%(key)s);
of_oxm_%(key)s_masked_value_get(
- &oxm_entry.%(key)s,
+ &oxm_entry,
&dst->fields.%(key)s);
of_memmask(&dst->fields.%(key)s, &dst->masks.%(key)s, sizeof(&dst->fields.%(key)s));
break;
case OF_OXM_%(ku)s:
OF_MATCH_MASK_%(ku)s_EXACT_SET(dst);
of_oxm_%(key)s_value_get(
- &oxm_entry.%(key)s,
+ &oxm_entry,
&dst->fields.%(key)s);
break;
""" % (dict(ku=key.upper(), key=key)))
@@ -961,55 +963,31 @@
*/
static inline int
-of_match_more_specific(of_match_t *entry, of_match_t *query)
+of_match_more_specific(const of_match_t *entry, const of_match_t *query)
{
- of_match_fields_t *q_m, *e_m; /* Short hand for masks, fields */
- of_match_fields_t *q_f, *e_f;
+ LOCI_ASSERT(sizeof(of_match_fields_t) % sizeof(uint8_t) == 0);
- q_m = &query->masks;
- e_m = &entry->masks;
- q_f = &query->fields;
- e_f = &entry->fields;
-""")
- for key, entry in match.of_match_members.items():
- q_m = "&q_m->%s" % key
- e_m = "&e_m->%s" % key
- q_f = "&q_f->%s" % key
- e_f = "&e_f->%s" % key
- if entry["m_type"] == "of_ipv6_t":
- comp = "OF_MORE_SPECIFIC_IPV6"
- match_type = "OF_RESTRICTED_MATCH_IPV6"
- elif entry["m_type"] == "of_mac_addr_t":
- comp = "OF_MORE_SPECIFIC_MAC_ADDR"
- match_type = "OF_RESTRICTED_MATCH_MAC_ADDR"
- elif entry["m_type"] == "of_bitmap_128_t":
- comp = "OF_MORE_SPECIFIC_BITMAP_128"
- match_type = "OF_RESTRICTED_MATCH_BITMAP_128"
- else: # Integer
- comp = "OF_MORE_SPECIFIC_INT"
- match_type = "OF_RESTRICTED_MATCH_INT"
- q_m = "q_m->%s" % key
- e_m = "e_m->%s" % key
- q_f = "q_f->%s" % key
- e_f = "e_f->%s" % key
- out.write("""
- /* Mask and values for %(key)s */
- if (!%(comp)s(%(e_m)s, %(q_m)s)) {
- return 0;
- }
- if (!%(match_type)s(%(e_f)s, %(q_f)s,
- %(q_m)s)) {
- return 0;
- }
-""" % dict(match_type=match_type, comp=comp, q_f=q_f, e_f=e_f,
- q_m=q_m, e_m=e_m, key=key))
+ /* Short hand for masks, fields */
+ const uint8_t *qm = (const uint8_t *)&query->masks;
+ const uint8_t *em = (const uint8_t *)&entry->masks;
+ const uint8_t *qf = (const uint8_t *)&query->fields;
+ const uint8_t *ef = (const uint8_t *)&entry->fields;
- out.write("""
+ int i;
+ for (i = 0; i < sizeof(of_match_fields_t)/sizeof(uint8_t); i++) {
+ if (qm[i] & ~em[i]) {
+ /* Query mask has a bit set that isn't set in the entry mask */
+ return 0;
+ }
+
+ if ((qf[i] ^ ef[i]) & qm[i]) {
+ /* Query and entry disagree on a field bit */
+ return 0;
+ }
+ }
+
return 1;
}
-""")
-
- out.write("""
/**
* Do two entries overlap?
@@ -1020,42 +998,24 @@
*/
static inline int
-of_match_overlap(of_match_t *match1, of_match_t *match2)
+of_match_overlap(const of_match_t *match1, const of_match_t *match2)
{
- of_match_fields_t *m1, *m2; /* Short hand for masks, fields */
- of_match_fields_t *f1, *f2;
+ LOCI_ASSERT(sizeof(of_match_fields_t) % sizeof(uint8_t) == 0);
- m1 = &match1->masks;
- m2 = &match2->masks;
- f1 = &match1->fields;
- f2 = &match2->fields;
-""")
- for key, entry in match.of_match_members.items():
- m1 = "&m1->%s" % key
- m2 = "&m2->%s" % key
- f1 = "&f1->%s" % key
- f2 = "&f2->%s" % key
- if entry["m_type"] == "of_ipv6_t":
- check = "OF_OVERLAP_IPV6"
- elif entry["m_type"] == "of_mac_addr_t":
- check = "OF_OVERLAP_MAC_ADDR"
- elif entry["m_type"] == "of_bitmap_128_t":
- check = "OF_OVERLAP_BITMAP_128"
- else: # Integer
- check = "OF_OVERLAP_INT"
- m1 = "m1->%s" % key
- m2 = "m2->%s" % key
- f1 = "f1->%s" % key
- f2 = "f2->%s" % key
- out.write("""
- /* Check overlap for %(key)s */
- if (!%(check)s(%(f1)s, %(f2)s,
- %(m2)s, %(m1)s)) {
- return 0; /* This field differentiates; all done */
+ /* Short hand for masks, fields */
+ const uint8_t *m1 = (const uint8_t *)&match1->masks;
+ const uint8_t *m2 = (const uint8_t *)&match2->masks;
+ const uint8_t *f1 = (const uint8_t *)&match1->fields;
+ const uint8_t *f2 = (const uint8_t *)&match2->fields;
+
+ int i;
+ for (i = 0; i < sizeof(of_match_fields_t)/sizeof(uint8_t); i++) {
+ if ((f1[i] ^ f2[i]) & (m1[i] & m2[i])) {
+ /* Matches disagree on a field bit they both qualify on */
+ return 0;
+ }
}
-""" % dict(check=check, f1=f1, f2=f2, m1=m1, m2=m2, key=key))
- out.write("""
return 1; /* No field differentiates matches */
}
""")
diff --git a/c_gen/c_show_gen.py b/c_gen/c_show_gen.py
index 9d84477..d1cbbdb 100644
--- a/c_gen/c_show_gen.py
+++ b/c_gen/c_show_gen.py
@@ -43,6 +43,78 @@
import c_gen.identifiers as identifiers
from c_test_gen import var_name_map
+show_override = {
+ ('uint32_t', 'arp_tpa'): 'ipv4',
+ ('uint32_t', 'arp_spa'): 'ipv4',
+ ('uint32_t', 'nw_addr'): 'ipv4',
+ ('uint32_t', 'dst'): 'ipv4',
+}
+
+show_hex = set([
+ ('uint8_t', 'icmpv6_code'),
+ ('uint8_t', 'mpls_tc'),
+ ('uint16_t', 'eth_type'),
+ ('uint8_t', 'ip_dscp'),
+ ('uint64_t', 'metadata'),
+ ('uint16_t', 'ingress_tpid'),
+ ('uint16_t', 'egress_tpid'),
+ ('uint32_t', 'xid'),
+ ('uint16_t', 'flags'),
+ ('uint32_t', 'experimenter'),
+ ('uint32_t', 'mask'),
+ ('uint8_t', 'report_mirror_ports'),
+ ('uint64_t', 'datapath_id'),
+ ('uint32_t', 'capabilities'),
+ ('uint32_t', 'actions'),
+ ('uint64_t', 'cookie'),
+ ('uint8_t', 'reason'),
+ ('uint32_t', 'role'),
+ ('uint32_t', 'config'),
+ ('uint32_t', 'advertise'),
+ ('uint32_t', 'advertised'),
+ ('uint32_t', 'supported'),
+ ('uint32_t', 'peer'),
+ ('uint64_t', 'cookie_mask'),
+ ('uint32_t', 'reserved'),
+ ('uint16_t', 'ethertype'),
+ ('uint64_t', 'metadata_mask'),
+ ('uint32_t', 'instructions'),
+ ('uint32_t', 'write_actions'),
+ ('uint32_t', 'apply_actions'),
+ ('uint32_t', 'types'),
+ ('uint32_t', 'actions_all'),
+ ('uint32_t', 'actions_select'),
+ ('uint32_t', 'actions_indirect'),
+ ('uint32_t', 'actions_ff'),
+ ('uint64_t', 'generation_id'),
+ ('uint16_t', 'value_mask'),
+ ('uint32_t', 'value_mask'),
+ ('uint8_t', 'value_mask'),
+ ('uint64_t', 'value_mask'),
+ ('uint64_t', 'write_setfields'),
+ ('uint64_t', 'apply_setfields'),
+ ('uint64_t', 'metadata_match'),
+ ('uint64_t', 'metadata_write'),
+ ('uint32_t', 'packet_in_mask_equal_master'),
+ ('uint32_t', 'packet_in_mask_slave'),
+ ('uint32_t', 'port_status_mask_equal_master'),
+ ('uint32_t', 'port_status_mask_slave'),
+ ('uint32_t', 'flow_removed_mask_equal_master'),
+ ('uint32_t', 'flow_removed_mask_slave'),
+ ('uint32_t', 'band_types'),
+ ('uint16_t', 'bsn_tcp_flags'),
+ ('uint8_t', 'bsn_l2_cache_hit'),
+])
+
+def gen_emitter(cls, m_name, m_type):
+ if (m_type, m_name) in show_override:
+ short_type = show_override[(m_type, m_name)]
+ elif (m_type, m_name) in show_hex:
+ short_type = loxi_utils.type_to_short_name(m_type).replace('u', 'x')
+ else:
+ short_type = loxi_utils.type_to_short_name(m_type)
+ return "LOCI_SHOW_" + short_type;
+
def gen_obj_show_h(out, name):
loxi_utils.gen_c_copy_license(out)
out.write("""
@@ -91,10 +163,10 @@
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls):
continue
out.write("""\
-int %(cls)s_%(ver_name)s_show(loci_writer_f writer, void* cookie, %(cls)s_t *obj);
+int %(cls)s_%(ver_name)s_show(loci_writer_f writer, void* cookie, of_object_t *obj);
""" % dict(cls=cls, ver_name=loxi_utils.version_to_name(version)))
out.write("""
@@ -130,11 +202,11 @@
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls):
continue
out.write("""
int
-%(cls)s_%(ver_name)s_show(loci_writer_f writer, void* cookie, %(cls)s_t *obj)
+%(cls)s_%(ver_name)s_show(loci_writer_f writer, void* cookie, of_object_t *obj)
{
int out = 0;
""" % dict(cls=cls, ver_name=ver_name))
@@ -150,13 +222,11 @@
%(m_type)s %(v_name)s;
""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
if loxi_utils.class_is_list(m_type):
- base_type = loxi_utils.list_to_entry_type(m_type)
- out.write(" %s elt;\n int rv;\n" % base_type)
+ out.write(" of_object_t elt;\n int rv;\n")
for member in members:
m_type = member["m_type"]
m_name = member["name"]
- #emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type)
- emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type) + "_" + m_name;
+ emitter = gen_emitter(cls, m_name, m_type)
if loxi_utils.skip_member_name(m_name):
continue
if (loxi_utils.type_is_scalar(m_type) or
@@ -184,7 +254,7 @@
sub_cls = m_type[:-2] # Trim _t
out.write("""
%(cls)s_%(m_name)s_bind(obj, &%(v_name)s);
- out += %(sub_cls)s_%(ver_name)s_show(writer, cookie, &%(v_name)s);
+ out += of_object_show(writer, cookie, &%(v_name)s);
""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name,
v_name=var_name_map(m_type), ver_name=ver_name))
@@ -204,8 +274,7 @@
for key, entry in match.of_match_members.items():
m_type = entry["m_type"]
- #emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type)
- emitter = "LOCI_SHOW_" + loxi_utils.type_to_short_name(m_type) + "_" + key;
+ emitter = gen_emitter('of_match', key, m_type)
out.write("""
if (OF_MATCH_MASK_%(ku)s_ACTIVE_TEST(match)) {
out += writer(cookie, "%(key)s active=");
@@ -233,7 +302,7 @@
comma = ","
if (not loxi_utils.class_in_version(cls, version) or
- cls in type_maps.inheritance_map):
+ type_maps.class_is_virtual(cls)):
out.write(" unknown_show%s\n" % comma);
else:
out.write(" %s_%s_show%s\n" %
@@ -241,20 +310,20 @@
out.write("};\n\n")
out.write("""
-static const loci_obj_show_f *const show_funs[5] = {
- NULL,
- show_funs_v1,
- show_funs_v2,
- show_funs_v3,
- show_funs_v4
+static const loci_obj_show_f *const show_funs[] = {
+""")
+
+ for version in of_g.of_version_range:
+ out.write(" [%(v)d] = show_funs_v%(v)d,\n" % dict(v=version))
+
+ out.write("""\
};
int
of_object_show(loci_writer_f writer, void* cookie, of_object_t *obj)
{
if ((obj->object_id > 0) && (obj->object_id < OF_OBJECT_COUNT)) {
- if (((obj)->version > 0) && ((obj)->version <= OF_VERSION_1_2)) {
- /* @fixme VERSION */
+ if (OF_VERSION_OKAY(obj->version)) {
return show_funs[obj->version][obj->object_id](writer, cookie, (of_object_t *)obj);
} else {
return writer(cookie, "Bad version %d\\n", obj->version);
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index 2f93536..05ff8e2 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -99,11 +99,13 @@
of_octets_t="octets",
of_meter_features_t="features",
of_match_t="match",
- of_oxm_header_t="oxm",
- of_bsn_vport_header_t="bsn_vport",
+ of_oxm_t="oxm",
+ of_bsn_vport_t="bsn_vport",
+ of_table_desc_t="table_desc",
# BSN extensions
of_bsn_vport_q_in_q_t="vport",
of_bitmap_128_t="bitmap_128",
+ of_bitmap_512_t="bitmap_512",
of_checksum_128_t="checksum_128",
#Circuit extensions
of_app_code_t="app_code",
@@ -123,10 +125,18 @@
"of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
"of_ipv6_t", "of_bitmap_128_t", "of_checksum_128_t",
"of_str64_t","of_app_code_t"]
+ "of_str64_t", "of_bitmap_512_t"]
scalar_types = integer_types[:]
scalar_types.extend(string_types)
+# When embedding an object inside of another object we have to pick a single
+# subclass to use, unlike lists where we use all subclasses.
+embedded_subclasses = {
+ 'of_oxm_t': 'of_oxm_eth_type',
+ 'of_bsn_vport_t': 'of_bsn_vport_q_in_q',
+}
+
def ignore_member(cls, version, m_name, m_type):
"""
Filter out names or types that either don't have accessors
@@ -375,7 +385,7 @@
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls) and not loxi_utils.class_is_list(cls):
continue
out.write("""
extern int %(cls)s_%(v_name)s_populate(
@@ -388,24 +398,6 @@
%(cls)s_t *obj, int value);
""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
- out.write("""
-/*
- * Declarations for list population and check primitives
- */
-""")
-
- for version in of_g.of_version_range:
- for cls in of_g.ordered_list_objects:
- if version in of_g.unified[cls]:
- out.write("""
-extern int
- list_setup_%(cls)s_%(v_name)s(
- %(cls)s_t *list, int value);
-extern int
- list_check_%(cls)s_%(v_name)s(
- %(cls)s_t *list, int value);
-""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
-
out.write("\n#endif /* _TEST_COMMON_H_ */\n")
def gen_common_test(out, name):
@@ -480,7 +472,6 @@
gen_fill_string(out)
gen_scalar_set_check_funs(out)
- gen_list_set_check_funs(out)
gen_unified_accessor_funs(out)
gen_ident_tests(out)
@@ -510,7 +501,7 @@
*/
""" % v_name)
for cls in of_g.standard_class_order:
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls):
continue
if version in of_g.unified[cls]:
message_scalar_test(out, version, cls)
@@ -523,7 +514,7 @@
for version in of_g.of_version_range:
v_name = loxi_utils.version_to_name(version)
for cls in of_g.standard_class_order:
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls):
continue
if version in of_g.unified[cls]:
test_name = "%s_%s" % (cls, v_name)
@@ -537,7 +528,7 @@
"""
members, member_types = scalar_member_types_get(cls, version)
- length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
+ length = of_g.base_length[(cls, version)]
v_name = loxi_utils.version_to_name(version)
out.write("""
@@ -696,6 +687,8 @@
"""
for version in of_g.of_version_range:
for cls in of_g.standard_class_order:
+ if type_maps.class_is_virtual(cls):
+ continue
(members, member_types) = scalar_member_types_get(cls, version)
scalar_funs_instance(out, cls, version, members, member_types)
@@ -705,8 +698,7 @@
base_type = loxi_utils.list_to_entry_type(cls)
setup_template = """
%(subcls)s_init(%(inst)s, %(v_name)s, -1, 1);
- %(cls)s_append_bind(list,
- (%(base_type)s_t *)%(inst)s);
+ %(cls)s_append_bind(list, %(inst)s);
value = %(subcls)s_%(v_name)s_populate(
%(inst)s, value);
cur_len += %(inst)s->length;
@@ -751,110 +743,6 @@
TEST_OK(%(cls)s_next(list, &elt));
""" % dict(cls=cls))
-def setup_list_fn(out, version, cls):
- """
- Generate a helper function that populates a list with two
- of each type of subclass it supports
- """
- out.write("""
-/**
- * Set up a list of type %(cls)s with two of each type of subclass
- */
-int
-list_setup_%(cls)s_%(v_name)s(
- %(cls)s_t *list, int value)
-{
-""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
- base_type = loxi_utils.list_to_entry_type(cls)
- out.write("""
- %(base_type)s_t elt;
- int cur_len = 0;
-""" % dict(cls=cls, base_type=base_type))
-
- sub_classes = type_maps.sub_class_map(base_type, version)
- sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
- v_name = loxi_utils.version_to_name(version)
-
- if len(sub_classes) == 0:
- out.write(" /* No subclasses for %s */\n"% base_type)
- out.write(" %s_t *elt_p;\n" % base_type)
- out.write("\n elt_p = &elt;\n")
- else:
- out.write(" /* Declare pointers for each subclass */\n")
- for instance, subcls in sub_classes:
- out.write(" %s_t *%s;\n" % (subcls, instance))
- out.write("\n /* Instantiate pointers for each subclass */\n")
- for instance, subcls in sub_classes:
- out.write(" %s = &elt.%s;\n" % (instance, instance))
-
- if len(sub_classes) == 0: # No inheritance case
- setup_instance(out, cls, base_type, "elt_p", v_name, version)
- else:
- for instance, subcls in sub_classes:
- setup_instance(out, cls, subcls, instance, v_name, version)
- out.write("""
-
- return value;
-}
-""")
-
-def check_list_fn(out, version, cls):
- """
- Generate a helper function that checks a list populated by above fn
- """
- out.write("""
-/**
- * Check a list of type %(cls)s generated by
- * list_setup_%(cls)s_%(v_name)s
- */
-int
-list_check_%(cls)s_%(v_name)s(
- %(cls)s_t *list, int value)
-{
-""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
- base_type = loxi_utils.list_to_entry_type(cls)
- out.write("""
- %(base_type)s_t elt;
-""" % dict(cls=cls, base_type=base_type))
-
- sub_classes = type_maps.sub_class_map(base_type, version)
- sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
- v_name = loxi_utils.version_to_name(version)
-
- if len(sub_classes) == 0:
- out.write(" /* No subclasses for %s */\n"% base_type)
- out.write(" %s_t *elt_p;\n" % base_type)
- out.write("\n elt_p = &elt;\n")
- else:
- out.write(" /* Declare pointers for each subclass */\n")
- for instance, subcls in sub_classes:
- out.write(" %s_t *%s;\n" % (subcls, instance))
- out.write("\n /* Instantiate pointers for each subclass */\n")
- for instance, subcls in sub_classes:
- out.write(" %s = &elt.%s;\n" % (instance, instance))
-
- out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
- if len(sub_classes) == 0: # No inheritance case
- check_instance(out, cls, base_type, "elt_p", v_name, version, True)
- else:
- count = 0
- for instance, subcls in sub_classes:
- count += 1
- check_instance(out, cls, subcls, instance, v_name,
- version, count==len(sub_classes))
-
- out.write("""
- return value;
-}
-""" % dict(base_type=base_type))
-
-def gen_list_set_check_funs(out):
- for version in of_g.of_version_range:
- for cls in of_g.ordered_list_objects:
- if version in of_g.unified[cls]:
- setup_list_fn(out, version, cls)
- check_list_fn(out, version, cls)
-
# Maybe: Get a map from list class to parent, mem_name of container
def list_test(out, version, cls):
@@ -877,7 +765,7 @@
TEST_ASSERT(list->parent == NULL);
TEST_ASSERT(list->object_id == %(enum_cls)s);
- value = list_setup_%(cls)s_%(v_name)s(list, value);
+ value = %(cls)s_%(v_name)s_populate(list, value);
TEST_ASSERT(value != 0);
""" % dict(cls=cls, base_type=base_type, v_name=loxi_utils.version_to_name(version),
enum_cls=loxi_utils.enum_name(cls)))
@@ -885,7 +773,7 @@
out.write("""
/* Now check values */
value = 1;
- value = list_check_%(cls)s_%(v_name)s(list, value);
+ value = %(cls)s_%(v_name)s_check(list, value);
TEST_ASSERT(value != 0);
""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
@@ -959,10 +847,12 @@
static int
test_match_1(void)
{
- of_match_v1_t *m_v1;
- of_match_v2_t *m_v2;
- of_match_v3_t *m_v3;
- of_match_v4_t *m_v4;
+""")
+
+ for version in of_g.of_version_range:
+ out.write(" of_match_v%(v)d_t *m_v%(v)d;\n" % dict(v=version))
+
+ out.write("""\
of_match_t match;
int value = 1;
int idx;
@@ -997,10 +887,12 @@
static int
test_match_2(void)
{
- of_match_v1_t *m_v1;
- of_match_v2_t *m_v2;
- of_match_v3_t *m_v3;
- of_match_v3_t *m_v4;
+""")
+
+ for version in of_g.of_version_range:
+ out.write(" of_match_v%(v)d_t *m_v%(v)d;\n" % dict(v=version))
+
+ out.write("""\
of_match_t match1;
of_match_t match2;
int value = 1;
@@ -1084,7 +976,7 @@
continue
if type_maps.class_is_virtual(cls):
continue
- bytes = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
+ bytes = of_g.base_length[(cls, version)]
out.write("""
static int
test_%(cls)s_create_%(v_name)s(void)
@@ -1167,15 +1059,24 @@
""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
base_type = loxi_utils.list_to_entry_type(cls)
out.write("""
- %(base_type)s_t elt;
+ of_object_t elt;
int cur_len = 0;
+ static int recursion;
+ (void) elt;
+ (void) cur_len;
+
+ if (recursion > 0) {
+ return value;
+ }
+
+ recursion++;
""" % dict(cls=cls, base_type=base_type))
sub_classes = type_maps.sub_class_map(base_type, version)
sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
v_name = loxi_utils.version_to_name(version)
- if len(sub_classes) == 0:
+ if not type_maps.class_is_virtual(base_type):
out.write(" /* No subclasses for %s */\n"% base_type)
out.write(" %s_t *elt_p;\n" % base_type)
out.write("\n elt_p = &elt;\n")
@@ -1185,14 +1086,15 @@
out.write(" %s_t *%s;\n" % (subcls, instance))
out.write("\n /* Instantiate pointers for each subclass */\n")
for instance, subcls in sub_classes:
- out.write(" %s = &elt.%s;\n" % (instance, instance))
+ out.write(" %s = &elt;\n" % (instance))
- if len(sub_classes) == 0: # No inheritance case
+ if not type_maps.class_is_virtual(base_type): # No inheritance case
setup_instance(out, cls, base_type, "elt_p", v_name, version)
else:
for instance, subcls in sub_classes:
setup_instance(out, cls, subcls, instance, v_name, version)
out.write("""
+ recursion--;
return value;
}
""")
@@ -1211,9 +1113,16 @@
""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
base_type = loxi_utils.list_to_entry_type(cls)
out.write("""
- %(base_type)s_t elt;
+ of_object_t elt;
int count = 0;
int rv;
+ static int recursion;
+
+ if (recursion > 0) {
+ return value;
+ }
+
+ recursion++;
""" % dict(cls=cls, base_type=base_type))
@@ -1221,7 +1130,7 @@
sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
v_name = loxi_utils.version_to_name(version)
- if len(sub_classes) == 0:
+ if not type_maps.class_is_virtual(base_type):
entry_count = 2
out.write(" /* No subclasses for %s */\n"% base_type)
out.write(" %s_t *elt_p;\n" % base_type)
@@ -1233,10 +1142,12 @@
out.write(" %s_t *%s;\n" % (subcls, instance))
out.write("\n /* Instantiate pointers for each subclass */\n")
for instance, subcls in sub_classes:
- out.write(" %s = &elt.%s;\n" % (instance, instance))
+ out.write(" %s = &elt;\n" % (instance))
- out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
- if len(sub_classes) == 0: # No inheritance case
+ if not type_maps.class_is_virtual(base_type) or sub_classes:
+ out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
+
+ if not type_maps.class_is_virtual(base_type): # No inheritance case
check_instance(out, cls, base_type, "elt_p", v_name,
version, True)
else:
@@ -1280,6 +1191,7 @@
of_object_delete((of_object_t *)dup);
}
+ recursion--;
return value;
}
""" % dict(cls=cls, u_cls=cls.upper(), entry_count=entry_count))
@@ -1304,8 +1216,9 @@
for m_type in member_types:
if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
- elif m_type == "of_bsn_vport_header_t":
- out.write(" of_bsn_vport_q_in_q_t *%s;\n" % var_name_map(m_type))
+ elif m_type in embedded_subclasses:
+ subcls = embedded_subclasses[m_type]
+ out.write(" %s_t *%s;\n" % (subcls, var_name_map(m_type)))
else:
out.write(" %s *%s;\n" % (m_type, var_name_map(m_type)))
out.write("""
@@ -1316,7 +1229,7 @@
m_name = member["name"]
if loxi_utils.skip_member_name(m_name):
continue
- if m_type == "of_bsn_vport_header_t":
+ if m_type in embedded_subclasses:
continue
if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
out.write("""\
@@ -1366,8 +1279,8 @@
FREE(octets.data);
}
""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
- elif m_type == "of_bsn_vport_header_t": # test q_in_q
- sub_cls = "of_bsn_vport_q_in_q"
+ elif m_type in embedded_subclasses:
+ sub_cls = embedded_subclasses[m_type]
out.write("""\
%(var_name)s = %(sub_cls)s_new(%(v_name)s);
TEST_ASSERT(%(var_name)s != NULL);
@@ -1446,8 +1359,8 @@
value = of_octets_check(&%(var_name)s, value);
""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
v_name=loxi_utils.version_to_name(version)))
- elif m_type == "of_bsn_vport_header_t": # tests only q_in_q
- sub_cls = "of_bsn_vport_q_in_q"
+ elif m_type in embedded_subclasses:
+ sub_cls = embedded_subclasses[m_type]
out.write("""
{ /* Use get/delete to access on check */
%(sub_cls)s_t *%(m_name)s_ptr;
@@ -1513,7 +1426,7 @@
"""
members, member_types = scalar_member_types_get(cls, version)
- length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
+ length = of_g.base_length[(cls, version)]
v_name = loxi_utils.version_to_name(version)
out.write("""
@@ -1568,11 +1481,9 @@
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
- continue
elif loxi_utils.class_is_list(cls):
gen_list_setup_check(out, cls, version)
- else:
+ elif not type_maps.class_is_virtual(cls):
gen_class_setup_check(out, cls, version)
def gen_unified_accessor_tests(out, name):
@@ -1591,7 +1502,7 @@
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls):
continue
unified_accessor_test_case(out, cls, version)
@@ -1605,7 +1516,7 @@
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls):
continue
test_name = "%s_%s" % (cls, v_name)
out.write(" RUN_TEST(%s);\n" % test_name)
@@ -1642,8 +1553,8 @@
%(cls)s_%(ver_name)s_dup(
%(cls)s_t *src)
{
- %(elt_type)s_t src_elt;
- %(elt_type)s_t *dst_elt;
+ of_object_t src_elt;
+ of_object_t *dst_elt;
int rv;
%(cls)s_t *dst;
@@ -1678,20 +1589,21 @@
*
* The caller is responsible for deleting the returned value
*/
-%(cls)s_t *
+of_object_t *
%(cls)s_%(ver_name)s_dup(
- %(cls)s_t *src)
+ of_object_t *src)
{
""" % dict(cls=cls, ver_name=ver_name))
# For each subclass, check if this is an instance of that subclass
- version_classes = type_maps.inheritance_data[cls][version]
- for sub_cls in version_classes:
- sub_enum = (cls + "_" + sub_cls).upper()
+ sub_classes = type_maps.sub_class_map(cls, version)
+ for (_, sub_cls) in sub_classes:
+ sub_enum = sub_cls.upper()
+ if type_maps.class_is_virtual(sub_cls):
+ continue
out.write("""
- if (src->header.object_id == %(sub_enum)s) {
- return (%(cls)s_t *)%(cls)s_%(sub_cls)s_%(ver_name)s_dup(
- &src->%(sub_cls)s);
+ if (src->object_id == %(sub_enum)s) {
+ return %(sub_cls)s_%(ver_name)s_dup(src);
}
""" % dict(sub_cls=sub_cls, ver_name=ver_name, sub_enum=sub_enum, cls=cls))
@@ -1731,11 +1643,12 @@
if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
# Declare instance of these
out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
- elif m_type == "of_bsn_vport_header_t": # test q_in_q
+ elif m_type in embedded_subclasses:
+ sub_cls = embedded_subclasses[m_type]
out.write("""
- of_bsn_vport_q_in_q_t src_%(v_name)s;
- of_bsn_vport_q_in_q_t *dst_%(v_name)s;
-""" % dict(v_name=var_name_map(m_type)))
+ %(sub_cls)s_t src_%(v_name)s;
+ %(sub_cls)s_t *dst_%(v_name)s;
+""" % dict(v_name=var_name_map(m_type), sub_cls=sub_cls))
else:
out.write("""
%(m_type)s src_%(v_name)s;
@@ -1763,8 +1676,8 @@
%(cls)s_%(m_name)s_get(src, &%(v_name)s);
%(cls)s_%(m_name)s_set(dst, &%(v_name)s);
""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
- elif m_type == "of_bsn_vport_header_t": # test q_in_q
- sub_cls = "of_bsn_vport_q_in_q"
+ elif m_type in embedded_subclasses:
+ sub_cls = embedded_subclasses[m_type]
out.write("""
%(cls)s_%(m_name)s_bind(
src, &src_%(v_name)s);
@@ -1817,11 +1730,11 @@
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_inheritance_root(cls):
gen_dup_inheritance(out, cls, version)
elif loxi_utils.class_is_list(cls):
gen_dup_list(out, cls, version)
- else:
+ elif not type_maps.class_is_virtual(cls):
gen_dup_cls(out, cls, version)
def gen_dup(out=sys.stdout):
@@ -1831,22 +1744,26 @@
for cls in of_g.standard_class_order:
out.write("""
-%(cls)s_t *
+of_object_t *
%(cls)s_dup(
- %(cls)s_t *src)
+ of_object_t *src)
{
""" % dict(cls=cls))
for version in of_g.of_version_range:
if not loxi_utils.class_in_version(cls, version):
continue
- hdr = "header." if cls in type_maps.inheritance_map else ""
-
+ elif type_maps.class_is_inheritance_root(cls):
+ pass
+ elif loxi_utils.class_is_list(cls):
+ pass
+ elif type_maps.class_is_virtual(cls):
+ continue
ver_name = loxi_utils.version_to_name(version)
out.write("""
- if (src->%(hdr)sversion == %(ver_name)s) {
+ if (src->version == %(ver_name)s) {
return %(cls)s_%(ver_name)s_dup(src);
}
-""" % dict(cls=cls, ver_name=ver_name, hdr=hdr))
+""" % dict(cls=cls, ver_name=ver_name))
out.write("""
/* Class not supported in given version */
@@ -1900,20 +1817,26 @@
for cls in of_g.standard_class_order:
out.write("""
-extern %(cls)s_t *
+extern of_object_t *
%(cls)s_dup(
- %(cls)s_t *src);
+ of_object_t *src);
""" % dict(cls=cls))
for version in of_g.of_version_range:
for cls in of_g.standard_class_order:
if not loxi_utils.class_in_version(cls, version):
continue
+ elif type_maps.class_is_inheritance_root(cls):
+ pass
+ elif loxi_utils.class_is_list(cls):
+ pass
+ elif type_maps.class_is_virtual(cls):
+ continue
ver_name = loxi_utils.version_to_name(version)
out.write("""
-extern %(cls)s_t *
+extern of_object_t *
%(cls)s_%(ver_name)s_dup(
- %(cls)s_t *src);
+ of_object_t *src);
""" % dict(cls=cls, ver_name=ver_name))
out.write("\n#endif /* _OF_DUP_H_ */\n")
@@ -1943,7 +1866,7 @@
for j, cls in enumerate(of_g.all_class_order):
if not loxi_utils.class_in_version(cls, version):
continue
- if cls in type_maps.inheritance_map:
+ if type_maps.class_is_virtual(cls):
continue
if cls == "of_bsn_virtual_port_create_request": # test q_in_q
out.write("""
diff --git a/c_gen/c_type_maps.py b/c_gen/c_type_maps.py
index 6c45d4d..36ad5f6 100644
--- a/c_gen/c_type_maps.py
+++ b/c_gen/c_type_maps.py
@@ -64,6 +64,18 @@
extern void of_meter_stats_wire_length_get(of_object_t *obj, int *bytes);
extern void of_meter_stats_wire_length_set(of_object_t *obj, int bytes);
+extern void of_port_desc_wire_length_get(of_object_t *obj, int *bytes);
+extern void of_port_desc_wire_length_set(of_object_t *obj, int bytes);
+
+extern void of_port_stats_entry_wire_length_get(of_object_t *obj, int *bytes);
+extern void of_port_stats_entry_wire_length_set(of_object_t *obj, int bytes);
+
+extern void of_queue_stats_entry_wire_length_get(of_object_t *obj, int *bytes);
+extern void of_queue_stats_entry_wire_length_set(of_object_t *obj, int bytes);
+
+extern void of_queue_desc_wire_length_get(of_object_t *obj, int *bytes);
+extern void of_queue_desc_wire_length_set(of_object_t *obj, int bytes);
+
""")
@@ -106,44 +118,3 @@
out.write("""
};
""")
-
-
-def gen_extra_length_array(out):
- """
- Generate an array giving the extra lengths of all objects/versions
- @param out The file handle to which to write
- """
- out.write("""
-/**
- * An array with the number of bytes in the extra length part
- * of each OF object
- */
-""")
-
- for version in of_g.of_version_range:
- out.write("""
-static const int\nof_object_extra_len_v%d[OF_OBJECT_COUNT] = {
- -1, /* of_object is not instantiable */
-""" % version)
- for i, cls in enumerate(of_g.all_class_order):
- comma = ","
- if i == len(of_g.all_class_order) - 1:
- comma = ""
- val = "-1" + comma
- if (cls, version) in of_g.base_length:
- val = str(of_g.extra_length.get((cls, version), 0)) + comma
- out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
- out.write("};\n")
-
- out.write("""
-/**
- * Unified map of extra length part of each object
- */
-const int *const of_object_extra_len[OF_VERSION_ARRAY_MAX] = {
- NULL,
-""")
- for version in of_g.of_version_range:
- out.write(" of_object_extra_len_v%d,\n" % version)
- out.write("""
-};
-""")
diff --git a/c_gen/codegen.py b/c_gen/codegen.py
index ea05826..f052950 100644
--- a/c_gen/codegen.py
+++ b/c_gen/codegen.py
@@ -121,26 +121,12 @@
c_code_gen.gen_new_function_definitions(out, uclass.name)
c_code_gen.gen_accessor_definitions(out, uclass.name)
-# TODO remove header classes and use the corresponding class instead
-def generate_header_classes(install_dir):
- for cls in of_g.standard_class_order:
- if cls.find("_header") < 0 or cls in ["of_header", "of_bsn_header", "of_nicira_header"]:
- continue
- with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out:
- util.render_template(out, "class.c",
- push_wire_types_data=None,
- parse_wire_types_data=None)
- # Append legacy generated code
- c_code_gen.gen_new_function_definitions(out, cls)
- c_code_gen.gen_accessor_definitions(out, cls)
-
def generate_classes_header(install_dir):
# Collect legacy code
tmp = StringIO()
c_code_gen.gen_struct_typedefs(tmp)
c_code_gen.gen_new_function_declarations(tmp)
c_code_gen.gen_accessor_declarations(tmp)
- c_code_gen.gen_generics(tmp)
with template_utils.open_output(install_dir, "loci/inc/loci/loci_classes.h") as out:
util.render_template(out, "loci_classes.h",
@@ -186,7 +172,6 @@
# Collect legacy code
tmp = StringIO()
c_type_maps.gen_length_array(tmp)
- c_type_maps.gen_extra_length_array(tmp)
with template_utils.open_output(install_dir, "loci/src/of_type_maps.c") as out:
util.render_template(out, "of_type_maps.c", legacy_code=tmp.getvalue())
@@ -197,6 +182,14 @@
class_metadata = []
class_metadata_dict = {}
+# These classes have handwritten C code to get/set their length fields
+# See templates/of_type_maps.c
+special_length_classes = set([
+ 'of_packet_queue', 'of_meter_stats', 'of_port_desc',
+ 'of_port_stats_entry', 'of_queue_stats_entry',
+ 'of_queue_desc',
+])
+
def build_class_metadata():
for uclass in loxi_globals.unified.classes:
wire_length_get = 'NULL'
@@ -207,69 +200,24 @@
if uclass and not uclass.virtual and uclass.has_type_members:
wire_type_set = '%s_push_wire_types' % uclass.name
+ root = uclass.inheritance_root()
+ if root and root.name != 'of_header':
+ wire_type_get = root.name + '_wire_object_id_get'
+
if uclass.is_message:
wire_length_get = 'of_object_message_wire_length_get'
wire_length_set = 'of_object_message_wire_length_set'
- elif uclass.is_action:
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_action_wire_object_id_get'
- elif uclass.is_instanceof('of_bsn_vport'):
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_bsn_vport_wire_object_id_get'
- elif uclass.is_action_id:
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_action_id_wire_object_id_get'
- elif uclass.is_instruction:
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_instruction_wire_object_id_get'
- elif uclass.is_instanceof('of_instruction_id'):
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_instruction_id_wire_object_id_get'
- elif uclass.is_instanceof('of_queue_prop'):
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_queue_prop_wire_object_id_get'
- elif uclass.is_instanceof('of_table_feature_prop'):
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_table_feature_prop_wire_object_id_get'
- elif uclass.is_instanceof('of_meter_band'):
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_meter_band_wire_object_id_get'
- elif uclass.is_instanceof('of_hello_elem'):
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_hello_elem_wire_object_id_get'
- elif uclass.is_instanceof('of_bsn_tlv'):
- wire_length_set = 'of_tlv16_wire_length_set'
- wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_get = 'of_bsn_tlv_wire_object_id_get'
elif uclass.is_oxm:
wire_length_get = 'of_oxm_wire_length_get'
- wire_type_get = 'of_oxm_wire_object_id_get'
- elif uclass.name == "of_packet_queue":
- wire_length_get = 'of_packet_queue_wire_length_get'
- wire_length_set = 'of_packet_queue_wire_length_set'
- elif uclass.name == "of_meter_stats":
- wire_length_get = 'of_meter_stats_wire_length_get'
- wire_length_set = 'of_meter_stats_wire_length_set'
- elif uclass.name in ["of_group_desc_stats_entry", "of_group_stats_entry",
- "of_flow_stats_entry", "of_bucket", "of_table_features",
- "of_bsn_port_counter_stats_entry", "of_bsn_vlan_counter_stats_entry",
- "of_bsn_gentable_entry_desc_stats_entry", "of_bsn_gentable_entry_stats_entry",
- "of_bsn_gentable_desc_stats_entry", "of_bsn_vrf_counter_stats_entry"]:
- wire_length_get = "of_u16_len_wire_length_get"
- wire_length_set = "of_u16_len_wire_length_set"
- elif uclass.name == 'of_match_v3':
+ elif uclass.name in special_length_classes:
+ wire_length_get = '%s_wire_length_get' % uclass.name
+ wire_length_set = '%s_wire_length_set' % uclass.name
+ elif loxi_utils_legacy.class_is_tlv16(uclass.name):
wire_length_set = 'of_tlv16_wire_length_set'
wire_length_get = 'of_tlv16_wire_length_get'
- wire_type_set = 'of_match_v3_push_wire_types'
+ elif loxi_utils_legacy.class_is_u16_len(uclass.name):
+ wire_length_get = "of_u16_len_wire_length_get"
+ wire_length_set = "of_u16_len_wire_length_set"
class_metadata.append(ClassMetadata(
name=uclass.name,
@@ -278,75 +226,6 @@
wire_type_get=wire_type_get,
wire_type_set=wire_type_set))
- class_metadata.extend([
- ClassMetadata(
- name="of_action_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_action_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_action_id_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_action_id_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_bsn_vport_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_bsn_vport_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_instruction_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_instruction_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_instruction_id_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_instruction_id_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_queue_prop_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_queue_prop_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_table_feature_prop_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_table_feature_prop_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_meter_band_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_meter_band_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_hello_elem_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_hello_elem_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_bsn_tlv_header",
- wire_length_set='of_tlv16_wire_length_set',
- wire_length_get='of_tlv16_wire_length_get',
- wire_type_get='of_bsn_tlv_wire_object_id_get',
- wire_type_set='NULL'),
- ClassMetadata(
- name="of_oxm_header",
- wire_length_set='NULL',
- wire_length_get='of_oxm_wire_length_get',
- wire_type_get='of_oxm_wire_object_id_get',
- wire_type_set='NULL'),
- ])
-
for metadata in class_metadata:
class_metadata_dict[metadata.name] = metadata
diff --git a/c_gen/loxi_utils_legacy.py b/c_gen/loxi_utils_legacy.py
index 4472ffa..0399638 100644
--- a/c_gen/loxi_utils_legacy.py
+++ b/c_gen/loxi_utils_legacy.py
@@ -37,6 +37,8 @@
import c_gen.of_g_legacy as of_g
import tenjin
from generic_utils import find, memoize
+import loxi_globals
+from loxi_ir import ir
def class_signature(members):
"""
@@ -99,40 +101,49 @@
"""
Return True if cls_name is an object which uses uint16 for type and length
"""
- if cls.find("of_action") == 0: # Includes of_action_id classes
- return True
- if cls.find("of_instruction") == 0:
- return True
- if cls.find("of_queue_prop") == 0:
- return True
- if cls.find("of_table_feature_prop") == 0:
- return True
- # *sigh*
- if cls.find("of_meter_band_stats") == 0: # NOT A TLV
+
+ ofclass = loxi_globals.unified.class_by_name(cls)
+ if not ofclass:
return False
- if cls.find("of_meter_band") == 0:
- return True
- if cls.find("of_hello_elem") == 0:
- return True
- if cls == "of_match_v3":
- return True
- if cls == "of_match_v4":
- return True
- if cls.find("of_bsn_tlv") == 0:
- return True
- if cls.find("of_bsn_vport") == 0:
- return True
- return False
+
+ if len(ofclass.members) < 2:
+ return False
+
+ m1 = ofclass.members[0]
+ m2 = ofclass.members[1]
+
+ if not (isinstance(m1, ir.OFTypeMember) or isinstance(m1, ir.OFDiscriminatorMember)):
+ return False
+
+ if not isinstance(m2, ir.OFLengthMember):
+ return False
+
+ if m1.oftype != "uint16_t" or m2.oftype != "uint16_t":
+ return False
+
+ return True
def class_is_u16_len(cls):
"""
Return True if cls_name is an object which uses initial uint16 length
"""
- return cls in ["of_group_desc_stats_entry", "of_group_stats_entry",
- "of_flow_stats_entry", "of_bucket", "of_table_features",
- "of_bsn_port_counter_stats_entry", "of_bsn_vlan_counter_stats_entry",
- "of_bsn_gentable_entry_desc_stats_entry", "of_bsn_gentable_entry_stats_entry",
- "of_bsn_gentable_desc_stats_entry", "of_bsn_vrf_counter_stats_entry"]
+
+ ofclass = loxi_globals.unified.class_by_name(cls)
+ if not ofclass:
+ return False
+
+ if len(ofclass.members) < 1:
+ return False
+
+ m = ofclass.members[0]
+
+ if not isinstance(m, ir.OFLengthMember):
+ return False
+
+ if m.oftype != "uint16_t":
+ return False
+
+ return True
def class_is_list(cls):
"""
@@ -219,6 +230,10 @@
"""
return parent + "_" + instance
+def class_to_instance(cls, base_cls):
+ assert cls.startswith(base_cls + '_')
+ return cls[len(base_cls)+1:]
+
def class_is_var_len(cls, version):
# Match is special case. Only version 1.2 (wire version 3) is var
if cls == "of_match":
@@ -283,7 +298,7 @@
"""
Convert an integer version to the C macro name
"""
- return "OF_" + of_g.version_names[version]
+ return of_g.of_version_wire2name[version]
def gen_c_copy_license(out):
"""
diff --git a/c_gen/match.py b/c_gen/match.py
index 7b7dcce..c6459d4 100644
--- a/c_gen/match.py
+++ b/c_gen/match.py
@@ -131,6 +131,7 @@
2: of_v2_keys,
3: [],
4: [],
+ 5: [],
}
# Complete list of match keys, sorted by the standard order
@@ -196,8 +197,7 @@
# Generate list of OXM names from the unified classes
oxm_names = [x[7:] for x in of_g.unified.keys() if
x.startswith('of_oxm_') and
- x.find('masked') < 0 and
- x.find('header') < 0]
+ x.find('masked') < 0]
# Check that all OXMs are in the match members
for key in oxm_names:
diff --git a/c_gen/of_g_legacy.py b/c_gen/of_g_legacy.py
index 0c48edd..caabc1a 100644
--- a/c_gen/of_g_legacy.py
+++ b/c_gen/of_g_legacy.py
@@ -31,8 +31,7 @@
# @fixme This needs to be refactored and brought into the 21st century.
#
-import sys
-# @fixme Replace with argparse
+import loxi_globals
################################################################
#
@@ -114,6 +113,7 @@
2: "uint32_t",
3: "uint32_t",
4: "uint32_t",
+ 5: "uint32_t",
"short_name":"port_no"
},
of_port_desc_t = {
@@ -121,6 +121,7 @@
2: "of_port_desc_t",
3: "of_port_desc_t",
4: "of_port_desc_t",
+ 5: "of_port_desc_t",
"short_name":"port_desc"
},
of_bsn_vport_t = {
@@ -128,6 +129,7 @@
2: "of_bsn_vport_t",
3: "of_bsn_vport_t",
4: "of_bsn_vport_t",
+ 5: "of_bsn_vport_t",
"short_name":"bsn_vport"
},
of_fm_cmd_t = { # Flow mod command went from u16 to u8
@@ -135,6 +137,7 @@
2: "uint8_t",
3: "uint8_t",
4: "uint8_t",
+ 5: "uint8_t",
"short_name":"fm_cmd"
},
of_wc_bmap_t = { # Wildcard bitmap
@@ -142,6 +145,7 @@
2: "uint32_t",
3: "uint64_t",
4: "uint64_t",
+ 5: "uint64_t",
"short_name":"wc_bmap"
},
of_match_bmap_t = { # Match bitmap
@@ -149,6 +153,7 @@
2: "uint32_t",
3: "uint64_t",
4: "uint64_t",
+ 5: "uint64_t",
"short_name":"match_bmap"
},
of_match_t = { # Match object
@@ -156,6 +161,7 @@
2: "of_match_v2_t",
3: "of_match_v3_t",
4: "of_match_v3_t", # Currently uses same match as 1.2 (v3).
+ 5: "of_match_v3_t", # Currently uses same match as 1.2 (v3).
"short_name":"match"
},
)
@@ -209,6 +215,7 @@
# short_name="match_v4"),
of_octets_t = dict(bytes=-1, short_name="octets"),
of_bitmap_128_t = dict(bytes=16, short_name="bitmap_128"),
+ of_bitmap_512_t = dict(bytes=64, short_name="bitmap_512"),
of_checksum_128_t = dict(bytes=16, short_name="checksum_128"),
of_app_code_t = dict(bytes=ofp_constants["OF_APP_CODE_LEN"],
short_name="app_code"),
@@ -221,7 +228,7 @@
"of_match_bmap_t", "of_port_name_t", "of_table_name_t",
"of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
"of_ipv6_t", "of_ipv4_t", "of_bitmap_128_t", "of_checksum_128_t",
- "of_str64_t"]
+ "of_str64_t", "of_bitmap_512_t"]
##
# LOXI identifiers
@@ -273,12 +280,6 @@
## Map from class, wire_version to size of fixed part of class
base_length = {}
-## Map from class, wire_version to size of variable-offset, fixed length part of class
-extra_length = {
- ("of_packet_in", 3): 2,
- ("of_packet_in", 4): 2,
-}
-
## Boolean indication of variable length, per class, wire_version,
is_fixed_length = set()
@@ -292,25 +293,21 @@
# Indexed by (cls, version, member-name) and value is prev-member-name
special_offsets = {}
-## Define Python variables with integer wire version values
-VERSION_1_0 = 1
-VERSION_1_1 = 2
-VERSION_1_2 = 3
-VERSION_1_3 = 4
-
-version_names = {1:"VERSION_1_0", 2:"VERSION_1_1", 3:"VERSION_1_2",
- 4:"VERSION_1_3"}
-short_version_names = {1:"OF_1_0", 2:"OF_1_1", 3:"OF_1_2", 4:"OF_1_3"}
+# Map from wire version to OF_1_x
+short_version_names = {}
# The iteration object that gives the wire versions supported
-of_version_range = [VERSION_1_0, VERSION_1_1, VERSION_1_2, VERSION_1_3]
+of_version_range = []
-of_version_wire2name = {
- VERSION_1_0:"OF_VERSION_1_0",
- VERSION_1_1:"OF_VERSION_1_1",
- VERSION_1_2:"OF_VERSION_1_2",
- VERSION_1_3:"OF_VERSION_1_3"
- }
+# Map from wire version to OF_VERSION_1_x
+of_version_wire2name = {}
+
+for version in loxi_globals.OFVersions.all_supported:
+ v = version.version.replace('.', '_')
+ short_version_names[version.wire_version] = 'OF_' + v
+ of_version_range.append(version.wire_version)
+ of_version_wire2name[version.wire_version] = 'OF_VERSION_' + v
+ globals()['VERSION_' + v] = version.wire_version
################################################################
diff --git a/c_gen/templates/README b/c_gen/templates/README
index 71c4a48..44eedab 100644
--- a/c_gen/templates/README
+++ b/c_gen/templates/README
@@ -60,7 +60,7 @@
for (i = 1; i <= 4; i++) {
of_action_output_t action;
of_action_output_init(&action, flow_add->version, -1, 1);
- of_list_action_append_bind(&actions, (of_action_t *)&action);
+ of_list_action_append_bind(&actions, &action);
of_action_output_port_set(&action, i);
}
diff --git a/c_gen/templates/list.c b/c_gen/templates/list.c
index 9ff6e42..5eb45c6 100644
--- a/c_gen/templates/list.c
+++ b/c_gen/templates/list.c
@@ -42,12 +42,11 @@
*/
int
-${cls}_first(${cls}_t *list, ${e_cls}_t *_obj)
+${cls}_first(${cls}_t *list, of_object_t *obj)
{
int rv;
- of_object_t *obj = (of_object_t *)_obj;
- ${e_cls}_init(_obj, list->version, -1, 1);
+ ${e_cls}_init(obj, list->version, -1, 1);
if ((rv = of_list_first(list, obj)) < 0) {
return rv;
@@ -73,10 +72,9 @@
*/
int
-${cls}_next(${cls}_t *list, ${e_cls}_t *_obj)
+${cls}_next(${cls}_t *list, of_object_t *obj)
{
int rv;
- of_object_t *obj = (of_object_t *)_obj;
if ((rv = of_list_next(list, obj)) < 0) {
return rv;
@@ -105,9 +103,9 @@
*/
int
-${cls}_append_bind(${cls}_t *list, ${e_cls}_t *obj)
+${cls}_append_bind(${cls}_t *list, of_object_t *obj)
{
- return of_list_append_bind(list, (of_object_t *)obj);
+ return of_list_append_bind(list, obj);
}
/**
@@ -119,7 +117,7 @@
*/
int
-${cls}_append(${cls}_t *list, ${e_cls}_t *obj)
+${cls}_append(${cls}_t *list, of_object_t *obj)
{
- return of_list_append(list, (of_object_t *)obj);
+ return of_list_append(list, obj);
}
diff --git a/c_gen/templates/loci_dump.h b/c_gen/templates/loci_dump.h
index 1344565..89c5f2a 100644
--- a/c_gen/templates/loci_dump.h
+++ b/c_gen/templates/loci_dump.h
@@ -99,6 +99,8 @@
#define LOCI_DUMP_checksum_128(writer, cookie, val) writer(cookie, "%016" PRIx64 "%016" PRIx64, (val).hi, (val).lo)
+#define LOCI_DUMP_bitmap_512(writer, cookie, val) writer(cookie, "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64, (val).words[7], (val).words[6], (val).words[5], (val).words[4], (val).words[3], (val).words[2], (val).words[1], (val).words[0])
+
/**
* Generic version for any object
*/
diff --git a/c_gen/templates/loci_int.h b/c_gen/templates/loci_int.h
index 1ea9eeb..eb1c923 100644
--- a/c_gen/templates/loci_int.h
+++ b/c_gen/templates/loci_int.h
@@ -30,6 +30,8 @@
:: flow_mod = of_g.base_length[("of_flow_modify",of_g.VERSION_1_2)]
:: packet_in = of_g.base_length[("of_packet_in",of_g.VERSION_1_2)]
:: packet_in_1_3 = of_g.base_length[("of_packet_in",of_g.VERSION_1_3)]
+:: packet_in_1_4 = of_g.base_length[("of_packet_in",of_g.VERSION_1_4)]
+:: assert packet_in_1_3 == packet_in_1_4
:: flow_stats = of_g.base_length[("of_flow_stats_entry", of_g.VERSION_1_2)]
:: match1 = of_g.base_length[("of_match_v1",of_g.VERSION_1_0)]
:: match2 = of_g.base_length[("of_match_v2",of_g.VERSION_1_1)]
@@ -239,13 +241,16 @@
* @param obj An object of type of_packet_in_t
*
* Get length of preceding match object and add to fixed length
- * Applies only to version 1.2 and 1.3
- * The +2 comes from the 2 bytes of padding between the match and packet data.
+ * Applies only to version 1.2+
+ * There are 2 bytes of padding between the match and data. The
+ * _OFFSET_FOLLOWING_MATCH_V3 macro assumes the match is at the end of the
+ * fixed length, so we need to subtract 2 from the fixed length we pass and
+ * then add 2 to the resulting offset.
*/
#define _PACKET_IN_DATA_OFFSET(obj) \
(_OFFSET_FOLLOWING_MATCH_V3((obj), (obj)->version == OF_VERSION_1_2 ? \
-${packet_in} : ${packet_in_1_3}) + 2)
+(${packet_in} - 2) : (${packet_in_1_3} - 2)) + 2)
/**
* Macro to calculate variable offset of data (packet) member in packet_out
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index 3624bcd..dc35959 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -67,61 +67,6 @@
#define LOCI_SHOW_d32(writer, cookie, val) LOCI_SHOW_D_INT(cookie, PRId32, val)
#define LOCI_SHOW_d64(writer, cookie, val) LOCI_SHOW_D_INT(cookie, PRId64, val)
-
-
-/**
- * Field-specific show macros.
- */
-#define LOCI_SHOW_u32_ipv6_flabel(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_vlan_pcp(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_src(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv6_ipv6_dst(writer, cookie, val) LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_u32_arp_tpa(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_icmpv6_type(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_mac_arp_sha(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_ipv6_ipv6_src(writer, cookie, val) LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_u16_sctp_src(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u8_icmpv6_code(writer, cookie, val) LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_mac_eth_dst(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_mac_ipv6_nd_sll(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u8_mpls_tc(writer, cookie, val) LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_u64_tunnel_id(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u16_arp_op(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_eth_type(writer, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_ipv6_ipv6_nd_target(writer, cookie, val) LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_u16_vlan_vid(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_arp_tha(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_port_no_in_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_u8_ip_dscp(writer, cookie, val) LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_u16_sctp_dst(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u8_icmpv4_code(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_tcp_src(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_arp_spa(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_ip_ecn(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_udp_dst(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_port_no_in_phy_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_dst(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_mac_eth_src(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u16_udp_src(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_ipv6_nd_tll(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u8_icmpv4_type(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_mpls_label(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_tcp_dst(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u8_ip_proto(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u64_metadata(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u8_enabled(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_vport_no(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_port_no(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_ingress_tpid(writer, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u16_egress_tpid(writer, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u16_ingress_vlan_id(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_egress_vlan_id(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_enabled(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_enable(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-
-
-
-
/* @todo Add checks for special port numbers */
#define LOCI_SHOW_port_no(writer, cookie, val) writer(cookie, "%d", val)
#define LOCI_SHOW_fm_cmd(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
@@ -168,253 +113,11 @@
#define LOCI_SHOW_checksum_128(writer, cookie, val) writer(cookie, "%016" PRIx64 "%016" PRIx64, (val).hi, (val).lo)
+#define LOCI_SHOW_bitmap_512(writer, cookie, val) writer(cookie, "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64, (val).words[7], (val).words[6], (val).words[5], (val).words[4], (val).words[3], (val).words[2], (val).words[1], (val).words[0])
+
/**
* Generic version for any object
*/
int of_object_show(loci_writer_f writer, void *cookie, of_object_t *obj);
-
-
-
-/**
- * Choose a representation for each field that
- * makes the most sense for display to the user.
- */
-#define LOCI_SHOW_u32_xid(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u16_flags(writer, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u64_packet_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_byte_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u32_flow_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_match_match(writer, cookie, val) LOCI_SHOW_match(writer, cookie, val)
-#define LOCI_SHOW_u8_table_id(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_port_no_out_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_u32_experimenter(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_subtype(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_index(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_mask(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u8_report_mirror_ports(writer, cookie, val) LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_desc_str_mfr_desc(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_desc_str_hw_desc(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_desc_str_sw_desc(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_ser_num_serial_num(writer, cookie, val) LOCI_SHOW_ser_num(writer, cookie, val)
-#define LOCI_SHOW_desc_str_dp_desc(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_desc_str_pipeline(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_octets_data(writer, cookie, val) LOCI_SHOW_octets(writer, cookie, val)
-#define LOCI_SHOW_octets_value(writer, cookie, val) LOCI_SHOW_octets(writer, cookie, val)
-#define LOCI_SHOW_u16_err_type(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_code(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u64_datapath_id(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u32_n_buffers(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_n_tables(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_capabilities(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u64_cookie(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u16_idle_timeout(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_hard_timeout(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_buffer_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_reason(writer, cookie, val) LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_u32_duration_sec(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_duration_nsec(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_miss_send_len(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_role(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u16_total_len(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_port_no_port_no(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_port_no_loopback_port_no(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_mac_hw_addr(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u32_config(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_advertise(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_port_no_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_u32_queue_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_dest_port(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_vlan_tag(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_copy_stage(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_max_len(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_dl_addr(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u32_nw_addr(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_nw_tos(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_tp_port(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_wc_bmap_wildcards(writer, cookie, val) LOCI_SHOW_wc_bmap(writer, cookie, val)
-#define LOCI_SHOW_port_name_name(writer, cookie, val) LOCI_SHOW_port_name(writer, cookie, val)
-#define LOCI_SHOW_u32_state(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_curr(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_advertised(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_supported(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_peer(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_packets(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_packets_unicast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_packets_multicast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_packets_broadcast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_uint64_value(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_packets(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_packets_unicast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_packets_multicast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_packets_broadcast(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_bytes(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_bytes(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_dropped(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_dropped(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_errors(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_tx_errors(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_frame_err(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_over_err(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_rx_crc_err(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_collisions(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u16_rate(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_tab_name_name(writer, cookie, val) LOCI_SHOW_tab_name(writer, cookie, val)
-#define LOCI_SHOW_u32_max_entries(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_active_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_lookup_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_matched_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u32_out_group(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_cookie_mask(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u32_reserved(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u16_command(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u8_group_type(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_group_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_ethertype(writer, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u8_mpls_ttl(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_nw_ecn(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_nw_ttl(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_weight(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_port_no_watch_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_u32_watch_group(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_ref_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_metadata_mask(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_mac_eth_src_mask(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_mac_eth_dst_mask(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_src_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_dst_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u32_curr_speed(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_speed(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_match_bmap_match(writer, cookie, val) LOCI_SHOW_match_bmap(writer, cookie, val)
-#define LOCI_SHOW_u32_instructions(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_write_actions(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_apply_actions(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_types(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_groups_all(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_groups_select(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_groups_indirect(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_max_groups_ff(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions_all(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions_select(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions_indirect(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_actions_ff(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u64_generation_id(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_octets_field(writer, cookie, val) LOCI_SHOW_octets(writer, cookie, val)
-#define LOCI_SHOW_u16_value(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_value_mask(writer, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_mac_value(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_mac_value_mask(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u32_value(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_value_mask(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_oxm_header(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u8_value(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_value_mask(writer, cookie, val) LOCI_SHOW_x8(writer, cookie, val)
-#define LOCI_SHOW_port_no_value(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_port_no_value_mask(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_ipv6_value(writer, cookie, val) LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_ipv6_value_mask(writer, cookie, val) LOCI_SHOW_ipv6(writer, cookie, val)
-#define LOCI_SHOW_u64_value(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_value_mask(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u64_write_setfields(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u64_apply_setfields(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u64_metadata_match(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u64_metadata_write(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
-#define LOCI_SHOW_u32_packet_in_mask_equal_master(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_packet_in_mask_slave(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_port_status_mask_equal_master(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_port_status_mask_slave(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_flow_removed_mask_equal_master(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u32_flow_removed_mask_slave(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u8_auxiliary_id(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_meter_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_rate(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_burst_size(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_prec_level(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u64_packet_band_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_byte_band_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u32_max_meter(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_band_types(writer, cookie, val) LOCI_SHOW_x32(writer, cookie, val)
-#define LOCI_SHOW_u8_max_bands(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_max_color(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u64_packet_in_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u64_byte_in_count(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_octets_experimenter_data(writer, cookie, val) LOCI_SHOW_octets(writer, cookie, val)
-#define LOCI_SHOW_u32_dst(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u32_service(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_status(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u16_subtype(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_addr(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv4_ipv4_netmask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_l2_table_enable(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_l2_table_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_ipv4_value(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv4_value_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_hybrid_enable(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_hybrid_version(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_bitmap_128_value(writer, cookie, val) LOCI_SHOW_bitmap_128(writer, cookie, val)
-#define LOCI_SHOW_bitmap_128_value_mask(writer, cookie, val) LOCI_SHOW_bitmap_128(writer, cookie, val)
-#define LOCI_SHOW_bitmap_128_bsn_in_ports_128(writer, cookie, val) LOCI_SHOW_bitmap_128(writer, cookie, val)
-#define LOCI_SHOW_u32_timeout_ms(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_tx_interval_ms(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_slot_num(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_lag_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_vrf(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_bsn_global_vrf_allowed(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_l3_interface_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_l3_src_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_l3_dst_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u8_convergence_status(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_actor_sys_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_actor_sys_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u16_actor_port_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_actor_port_num(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_actor_key(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_partner_sys_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_mac_partner_sys_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u16_partner_port_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_partner_port_num(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u16_partner_key(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u64_time_ms(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_desc_str_uri(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_u8_state(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u16_table_id(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_deleted_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_error_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_checksum_128_checksum(writer, cookie, val) LOCI_SHOW_checksum_128(writer, cookie, val)
-#define LOCI_SHOW_checksum_128_checksum_mask(writer, cookie, val) LOCI_SHOW_checksum_128(writer, cookie, val)
-#define LOCI_SHOW_u32_buckets_size(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_entry_count(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_num_aux(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_checksum(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_egr_port_group_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf0(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf1(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf2(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf3(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf4(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf5(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf6(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_udf7(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u64_counter_id(writer, cookie, val) LOCI_SHOW_u64(writer, cookie, val)
-#define LOCI_SHOW_desc_str_description(writer, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_str64_name(writer, cookie, val) LOCI_SHOW_str64(writer, cookie, val)
-#define LOCI_SHOW_mac_local_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_mac_nh_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_ipv4_src_ip(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_ipv4_dst_ip(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u8_dscp_mode(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_dscp(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u8_ttl(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_vpn(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_rate_limit(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_flags(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_desc_str_image_checksum(write, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_desc_str_startup_config_checksum(write, cookie, val) LOCI_SHOW_desc_str(writer, cookie, val)
-#define LOCI_SHOW_u16_bsn_tcp_flags(write, cookie, val) LOCI_SHOW_x16(writer, cookie, val)
-#define LOCI_SHOW_u8_loglevel(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_vrf(write, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-#define LOCI_SHOW_u32_bsn_vlan_xlate_port_group_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
-
#endif /* _LOCI_SHOW_H_ */
diff --git a/c_gen/templates/loci_strings.c b/c_gen/templates/loci_strings.c
index f546e12..165bf56 100644
--- a/c_gen/templates/loci_strings.c
+++ b/c_gen/templates/loci_strings.c
@@ -69,6 +69,12 @@
}
};
+const of_bitmap_512_t of_bitmap_512_all_ones = {
+ { -1, -1, -1, -1, -1, -1, -1, -1, }
+};
+
+const of_bitmap_512_t of_bitmap_512_all_zeroes;
+
/** @var of_error_strings
* The error string map; use abs value to index
*/
diff --git a/c_gen/templates/loci_validator.c b/c_gen/templates/loci_validator.c
index 1f98b21..c4e8b5c 100644
--- a/c_gen/templates/loci_validator.c
+++ b/c_gen/templates/loci_validator.c
@@ -199,7 +199,7 @@
return ${validator_name(proto.class_by_name('of_header'))}(msg, len, &out_len);
:: #endfor
default:
- VALIDATOR_LOG("Bad version %d", OF_VERSION_1_3);
+ VALIDATOR_LOG("Bad version %d", version);
return -1;
}
}
diff --git a/c_gen/templates/locitest/test_utils.c b/c_gen/templates/locitest/test_utils.c
index 10a6b3d..d078a59 100644
--- a/c_gen/templates/locitest/test_utils.c
+++ b/c_gen/templates/locitest/test_utils.c
@@ -43,12 +43,8 @@
test_has_outport(void)
{
of_list_action_t *list;
- of_action_t elt;
- of_action_set_dl_src_t *set_dl_src;
- of_action_output_t *output;
-
- set_dl_src = &elt.set_dl_src;
- output = &elt.output;
+ of_object_t set_dl_src;
+ of_object_t output;
list = of_list_action_new(OF_VERSION_1_0);
TEST_ASSERT(list != NULL);
@@ -57,25 +53,25 @@
TEST_ASSERT(!of_action_list_has_out_port(list, 1));
/* Add some other action */
- of_action_set_dl_src_init(set_dl_src, OF_VERSION_1_0, -1, 1);
- TEST_OK(of_list_action_append_bind(list, (of_action_t *)set_dl_src));
+ of_action_set_dl_src_init(&set_dl_src, OF_VERSION_1_0, -1, 1);
+ TEST_OK(of_list_action_append_bind(list, &set_dl_src));
TEST_ASSERT(of_action_list_has_out_port(list, OF_PORT_DEST_WILDCARD));
TEST_ASSERT(!of_action_list_has_out_port(list, 1));
/* Add port 2 */
- of_action_output_init(output, OF_VERSION_1_0, -1, 1);
- TEST_OK(of_list_action_append_bind(list, (of_action_t *)output));
- of_action_output_port_set(output, 2);
+ of_action_output_init(&output, OF_VERSION_1_0, -1, 1);
+ TEST_OK(of_list_action_append_bind(list, &output));
+ of_action_output_port_set(&output, 2);
TEST_ASSERT(of_action_list_has_out_port(list, OF_PORT_DEST_WILDCARD));
TEST_ASSERT(!of_action_list_has_out_port(list, 1));
TEST_ASSERT(of_action_list_has_out_port(list, 2));
/* Add port 1 */
- of_action_output_init(output, OF_VERSION_1_0, -1, 1);
- TEST_OK(of_list_action_append_bind(list, (of_action_t *)output));
- of_action_output_port_set(output, 1);
+ of_action_output_init(&output, OF_VERSION_1_0, -1, 1);
+ TEST_OK(of_list_action_append_bind(list, &output));
+ of_action_output_port_set(&output, 1);
TEST_ASSERT(of_action_list_has_out_port(list, OF_PORT_DEST_WILDCARD));
TEST_ASSERT(of_action_list_has_out_port(list, 1));
@@ -88,26 +84,26 @@
TEST_ASSERT(list != NULL);
/* Add port 2 */
- of_action_output_init(output, OF_VERSION_1_0, -1, 1);
- TEST_OK(of_list_action_append_bind(list, (of_action_t *)output));
- of_action_output_port_set(output, 2);
+ of_action_output_init(&output, OF_VERSION_1_0, -1, 1);
+ TEST_OK(of_list_action_append_bind(list, &output));
+ of_action_output_port_set(&output, 2);
TEST_ASSERT(of_action_list_has_out_port(list, OF_PORT_DEST_WILDCARD));
TEST_ASSERT(!of_action_list_has_out_port(list, 1));
TEST_ASSERT(of_action_list_has_out_port(list, 2));
/* Add some other action */
- of_action_set_dl_src_init(set_dl_src, OF_VERSION_1_0, -1, 1);
- TEST_OK(of_list_action_append_bind(list, (of_action_t *)set_dl_src));
+ of_action_set_dl_src_init(&set_dl_src, OF_VERSION_1_0, -1, 1);
+ TEST_OK(of_list_action_append_bind(list, &set_dl_src));
TEST_ASSERT(of_action_list_has_out_port(list, OF_PORT_DEST_WILDCARD));
TEST_ASSERT(!of_action_list_has_out_port(list, 1));
TEST_ASSERT(of_action_list_has_out_port(list, 2));
/* Add port 1 */
- of_action_output_init(output, OF_VERSION_1_0, -1, 1);
- TEST_OK(of_list_action_append_bind(list, (of_action_t *)output));
- of_action_output_port_set(output, 1);
+ of_action_output_init(&output, OF_VERSION_1_0, -1, 1);
+ TEST_OK(of_list_action_append_bind(list, &output));
+ of_action_output_port_set(&output, 1);
TEST_ASSERT(of_action_list_has_out_port(list, OF_PORT_DEST_WILDCARD));
TEST_ASSERT(of_action_list_has_out_port(list, 1));
diff --git a/c_gen/templates/locitest/test_validator.c b/c_gen/templates/locitest/test_validator.c
index a4b55eb..fde5cba 100644
--- a/c_gen/templates/locitest/test_validator.c
+++ b/c_gen/templates/locitest/test_validator.c
@@ -88,9 +88,9 @@
of_message_t msg;
of_flow_modify_actions_bind(obj, &list);
of_action_set_tp_dst_init(&element1, OF_VERSION_1_0, -1, 1);
- of_list_action_append_bind(&list, (of_action_t *)&element1);
+ of_list_action_append_bind(&list, &element1);
of_action_output_init(&element2, OF_VERSION_1_0, -1, 1);
- of_list_action_append_bind(&list, (of_action_t *)&element2);
+ of_list_action_append_bind(&list, &element2);
msg = OF_OBJECT_TO_MESSAGE(obj);
TEST_ASSERT(of_validate_message(msg, of_message_length_get(msg)) == 0);
diff --git a/c_gen/templates/of_object.c b/c_gen/templates/of_object.c
index 5647d81..574db27 100644
--- a/c_gen/templates/of_object.c
+++ b/c_gen/templates/of_object.c
@@ -521,7 +521,7 @@
obj->wbuf = NULL;
}
-#define _MAX_PARENT_ITERATIONS 4
+#define _MAX_PARENT_ITERATIONS 8
/**
* Iteratively update parent lengths thru hierarchy
* @param obj The object whose length is being updated
@@ -581,9 +581,6 @@
if (loci_class_metadata[obj->object_id].wire_type_get != NULL) {
of_object_id_t id;
loci_class_metadata[obj->object_id].wire_type_get(obj, &id);
- if (!of_wire_id_valid(id, base_object_id)) {
- return OF_ERROR_PARSE;
- }
obj->object_id = id;
/* Call the init function for this object type; do not push to wire */
of_object_init_map[id]((of_object_t *)(obj), obj->version, -1, 0);
diff --git a/c_gen/templates/of_type_maps.c b/c_gen/templates/of_type_maps.c
index 9fa59e0..3fcf024 100644
--- a/c_gen/templates/of_type_maps.c
+++ b/c_gen/templates/of_type_maps.c
@@ -305,3 +305,173 @@
of_wire_buffer_u16_set(wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(obj, OF_METER_STATS_LENGTH_OFFSET), bytes);
}
+
+/**
+ * Get the wire length for a port desc object
+ * @param obj The object being referenced
+ * @param bytes Pointer to location to store length
+ *
+ * The length is only present for OF 1.4+.
+ */
+void
+of_port_desc_wire_length_get(of_object_t *obj, int *bytes)
+{
+ of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
+ uint16_t u16;
+
+ LOCI_ASSERT(wbuf != NULL);
+
+ if (obj->version >= OF_VERSION_1_4) {
+ of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, 4),
+ &u16);
+ *bytes = u16;
+ } else {
+ *bytes = OF_OBJECT_FIXED_LENGTH(obj);
+ }
+}
+
+/**
+ * Set the wire length for a port desc object
+ * @param obj The object being referenced
+ * @param bytes The length of the object
+ *
+ * The length is only present for OF 1.4+.
+ */
+
+void
+of_port_desc_wire_length_set(of_object_t *obj, int bytes)
+{
+ of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
+ LOCI_ASSERT(wbuf != NULL);
+
+ if (obj->version >= OF_VERSION_1_4) {
+ of_wire_buffer_u16_set(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, 4),
+ bytes);
+ } else {
+ LOCI_ASSERT(obj->length == OF_OBJECT_FIXED_LENGTH(obj));
+ }
+}
+
+/**
+ * Get the wire length for a port stats_entry object
+ * @param obj The object being referenced
+ * @param bytes Pointer to location to store length
+ *
+ * The length is only present for OF 1.4+.
+ */
+void
+of_port_stats_entry_wire_length_get(of_object_t *obj, int *bytes)
+{
+ of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
+ uint16_t u16;
+
+ LOCI_ASSERT(wbuf != NULL);
+
+ if (obj->version >= OF_VERSION_1_4) {
+ of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, 0),
+ &u16);
+ *bytes = u16;
+ } else {
+ *bytes = OF_OBJECT_FIXED_LENGTH(obj);
+ }
+}
+
+/**
+ * Set the wire length for a port stats_entry object
+ * @param obj The object being referenced
+ * @param bytes The length of the object
+ *
+ * The length is only present for OF 1.4+.
+ */
+
+void
+of_port_stats_entry_wire_length_set(of_object_t *obj, int bytes)
+{
+ of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
+ LOCI_ASSERT(wbuf != NULL);
+
+ if (obj->version >= OF_VERSION_1_4) {
+ of_wire_buffer_u16_set(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, 0),
+ bytes);
+ } else {
+ LOCI_ASSERT(obj->length == OF_OBJECT_FIXED_LENGTH(obj));
+ }
+}
+
+/**
+ * Get the wire length for a queue stats_entry object
+ * @param obj The object being referenced
+ * @param bytes Pointer to location to store length
+ *
+ * The length is only present for OF 1.4+.
+ */
+void
+of_queue_stats_entry_wire_length_get(of_object_t *obj, int *bytes)
+{
+ of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
+ uint16_t u16;
+
+ LOCI_ASSERT(wbuf != NULL);
+
+ if (obj->version >= OF_VERSION_1_4) {
+ of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, 0),
+ &u16);
+ *bytes = u16;
+ } else {
+ *bytes = OF_OBJECT_FIXED_LENGTH(obj);
+ }
+}
+
+/**
+ * Set the wire length for a queue stats_entry object
+ * @param obj The object being referenced
+ * @param bytes The length of the object
+ *
+ * The length is only present for OF 1.4+.
+ */
+
+void
+of_queue_stats_entry_wire_length_set(of_object_t *obj, int bytes)
+{
+ of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
+ LOCI_ASSERT(wbuf != NULL);
+
+ if (obj->version >= OF_VERSION_1_4) {
+ of_wire_buffer_u16_set(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, 0),
+ bytes);
+ } else {
+ LOCI_ASSERT(obj->length == OF_OBJECT_FIXED_LENGTH(obj));
+ }
+}
+
+/**
+ * Get the wire length for a queue_desc object
+ * @param obj The object being referenced
+ * @param bytes Pointer to location to store length
+ */
+void
+of_queue_desc_wire_length_get(of_object_t *obj, int *bytes)
+{
+ of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
+ uint16_t u16;
+
+ LOCI_ASSERT(wbuf != NULL);
+
+ of_wire_buffer_u16_get(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, 8), &u16);
+ *bytes = u16;
+}
+
+/**
+ * Set the wire length for a queue_desc object
+ * @param obj The object being referenced
+ * @param bytes The length of the object
+ */
+
+void
+of_queue_desc_wire_length_set(of_object_t *obj, int bytes)
+{
+ of_wire_buffer_t *wbuf = OF_OBJECT_TO_WBUF(obj);
+ LOCI_ASSERT(wbuf != NULL);
+
+ of_wire_buffer_u16_set(wbuf, OF_OBJECT_ABSOLUTE_OFFSET(obj, 8), bytes);
+}
diff --git a/c_gen/templates/of_utils.c b/c_gen/templates/of_utils.c
index 373ad59..bddbc8d 100644
--- a/c_gen/templates/of_utils.c
+++ b/c_gen/templates/of_utils.c
@@ -54,7 +54,7 @@
int
of_action_list_has_out_port(of_list_action_t *actions, of_port_no_t outport)
{
- of_action_t elt;
+ of_object_t elt;
of_action_output_t *output;
int loop_rv;
of_port_no_t port_no;
@@ -64,7 +64,7 @@
return 1;
}
- output = &elt.output;
+ output = &elt;
OF_LIST_ACTION_ITER(actions, &elt, loop_rv) {
if (output->object_id == OF_ACTION_OUTPUT) {
of_action_output_port_get(output, &port_no);
diff --git a/c_gen/templates/of_wire_buf.h b/c_gen/templates/of_wire_buf.h
index 0922a69..9ade2c4 100644
--- a/c_gen/templates/of_wire_buf.h
+++ b/c_gen/templates/of_wire_buf.h
@@ -469,14 +469,10 @@
of_wire_buffer_u16_get(wbuf, offset, &v16);
*value = v16;
break;
- case OF_VERSION_1_1:
- case OF_VERSION_1_2:
- case OF_VERSION_1_3:
+ default:
of_wire_buffer_u32_get(wbuf, offset, &v32);
*value = v32;
break;
- default:
- LOCI_ASSERT(0);
}
}
@@ -498,13 +494,9 @@
case OF_VERSION_1_0:
of_wire_buffer_u16_set(wbuf, offset, (uint16_t)value);
break;
- case OF_VERSION_1_1:
- case OF_VERSION_1_2:
- case OF_VERSION_1_3:
+ default:
of_wire_buffer_u32_set(wbuf, offset, (uint32_t)value);
break;
- default:
- LOCI_ASSERT(0);
}
}
@@ -527,14 +519,10 @@
of_wire_buffer_u16_get(wbuf, offset, &v16);
*value = v16;
break;
- case OF_VERSION_1_1:
- case OF_VERSION_1_2:
- case OF_VERSION_1_3:
+ default:
of_wire_buffer_u8_get(wbuf, offset, &v8);
*value = v8;
break;
- default:
- LOCI_ASSERT(0);
}
}
@@ -553,13 +541,9 @@
case OF_VERSION_1_0:
of_wire_buffer_u16_set(wbuf, offset, (uint16_t)value);
break;
- case OF_VERSION_1_1:
- case OF_VERSION_1_2:
- case OF_VERSION_1_3:
+ default:
of_wire_buffer_u8_set(wbuf, offset, (uint8_t)value);
break;
- default:
- LOCI_ASSERT(0);
}
}
@@ -583,13 +567,10 @@
of_wire_buffer_u32_get(wbuf, offset, &v32);
*value = v32;
break;
- case OF_VERSION_1_2:
- case OF_VERSION_1_3:
+ default:
of_wire_buffer_u64_get(wbuf, offset, &v64);
*value = v64;
break;
- default:
- LOCI_ASSERT(0);
}
}
@@ -609,12 +590,9 @@
case OF_VERSION_1_1:
of_wire_buffer_u32_set(wbuf, offset, (uint32_t)value);
break;
- case OF_VERSION_1_2:
- case OF_VERSION_1_3:
+ default:
of_wire_buffer_u64_set(wbuf, offset, (uint64_t)value);
break;
- default:
- LOCI_ASSERT(0);
}
}
@@ -910,6 +888,45 @@
#define of_wire_buffer_checksum_128_set(buf, offset, checksum) \
(of_wire_buffer_u64_set(buf, offset, checksum.hi), of_wire_buffer_u64_set(buf, offset+8, checksum.lo))
+
+/**
+ * Get a bitmap_512 from a wire buffer
+ * @param wbuf The pointer to the wire buffer structure
+ * @param offset Offset in the wire buffer
+ * @param value Pointer to where to put value
+ *
+ * The underlying buffer accessor funtions handle endian and alignment.
+ */
+
+static inline void
+of_wire_buffer_bitmap_512_get(of_wire_buffer_t *wbuf, int offset, of_bitmap_512_t *value)
+{
+ OF_WIRE_BUFFER_ACCESS_CHECK(wbuf, offset + (int) sizeof(of_bitmap_512_t));
+ int i;
+ for (i = 0; i < 8; i++) {
+ buf_u64_get(OF_WIRE_BUFFER_INDEX(wbuf, offset+i*8), &value->words[i]);
+ }
+}
+
+/**
+ * Set a bitmap_512 in a wire buffer
+ * @param wbuf The pointer to the wire buffer structure
+ * @param offset Offset in the wire buffer
+ * @param value The value to store
+ *
+ * The underlying buffer accessor funtions handle endian and alignment.
+ */
+
+static inline void
+of_wire_buffer_bitmap_512_set(of_wire_buffer_t *wbuf, int offset, of_bitmap_512_t value)
+{
+ OF_WIRE_BUFFER_ACCESS_CHECK(wbuf, offset + (int) sizeof(of_bitmap_512_t));
+ int i;
+ for (i = 0; i < 8; i++) {
+ buf_u64_set(OF_WIRE_BUFFER_INDEX(wbuf, offset+i*8), value.words[i]);
+ }
+}
+
/* Relocate data from start offset to the end of the buffer to a new position */
static inline void
of_wire_buffer_move_end(of_wire_buffer_t *wbuf, int start_offset, int new_offset)
diff --git a/c_gen/type_maps.py b/c_gen/type_maps.py
index 7b745a6..607814c 100644
--- a/c_gen/type_maps.py
+++ b/c_gen/type_maps.py
@@ -25,432 +25,37 @@
# EPL for the specific language governing permissions and limitations
# under the EPL.
-#
-# Miscellaneous type information
-#
-# Define the map between sub-class types and wire values. In each
-# case, an array indexed by wire version gives a hash from identifier
-# to wire value.
-#
-
-import c_gen.of_g_legacy as of_g
-import sys
from generic_utils import *
-import loxi_utils.loxi_utils as loxi_utils
import c_gen.loxi_utils_legacy as loxi_utils
import loxi_globals
-invalid_type = "invalid_type"
-
-################################################################
-#
-# Define type data for inheritance classes:
-# instructions, actions, queue properties and OXM
-#
-# Messages are not in this group; they're treated specially for now
-#
-# These are indexed by wire protocol number
-#
-################################################################
-
-instruction_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict()
- }
-
-instruction_id_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict()
- }
-
-action_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict(),
- }
-
-action_id_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict(),
- }
-
-queue_prop_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict()
- }
-
-bsn_vport_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict(),
- }
-
-oxm_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict(),
- }
-
-hello_elem_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict(),
- }
-
-table_feature_prop_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict(),
- }
-
-meter_band_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict(),
- }
-
-bsn_tlv_types = {
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict(),
- }
-
-# All inheritance data for non-messages
-inheritance_data = dict(
- of_instruction = instruction_types,
- of_instruction_id = instruction_id_types,
- of_action = action_types,
- of_action_id = action_id_types,
- of_oxm = oxm_types,
- of_queue_prop = queue_prop_types,
- of_hello_elem = hello_elem_types,
- of_table_feature_prop = table_feature_prop_types,
- of_meter_band = meter_band_types,
- # BSN specific inheritance extensions
- of_bsn_vport = bsn_vport_types,
- of_bsn_tlv = bsn_tlv_types,
- )
+# map from inheritance root class name to set of subclass names
+inheritance_map = {}
def class_is_virtual(cls):
"""
Returns True if cls is a virtual class
"""
- if cls.find("header") > 0:
- return True
if loxi_utils.class_is_list(cls):
return True
return loxi_globals.unified.class_by_name(cls).virtual
-################################################################
-#
-# These are message types
-#
-################################################################
-
-# The hardcoded message types are for inheritance parents
-message_types = {
- # version 1.0
- of_g.VERSION_1_0:dict(
- error_msg = 1,
- experimenter = 4,
- flow_mod = 14,
- stats_request = 16,
- stats_reply = 17,
- ),
-
- # version 1.1
- of_g.VERSION_1_1:dict(
- error_msg = 1,
- experimenter = 4,
- flow_mod = 14,
- group_mod = 15,
- stats_request = 18,
- stats_reply = 19,
- ),
-
- # version 1.2
- of_g.VERSION_1_2:dict(
- error_msg = 1,
- experimenter = 4,
- flow_mod = 14,
- group_mod = 15,
- stats_request = 18,
- stats_reply = 19,
- ),
-
- # version 1.3
- of_g.VERSION_1_3:dict(
- error_msg = 1,
- experimenter = 4,
- flow_mod = 14,
- group_mod = 15,
- stats_request = 18, # FIXME Multipart
- stats_reply = 19,
- )
- }
-
-################################################################
-#
-# These are other objects that have a notion of type but are
-# not (yet) promoted to objects with inheritance
-#
-################################################################
-
-stats_types = {
- # version 1.0
- of_g.VERSION_1_0:dict(
- desc = 0,
- flow = 1,
- aggregate = 2,
- table = 3,
- port = 4,
- queue = 5,
- experimenter = 0xffff
- ),
-
- # version 1.1
- of_g.VERSION_1_1:dict(
- desc = 0,
- flow = 1,
- aggregate = 2,
- table = 3,
- port = 4,
- queue = 5,
- group = 6,
- group_desc = 7,
- experimenter = 0xffff
- ),
-
- # version 1.2
- of_g.VERSION_1_2:dict(
- desc = 0,
- flow = 1,
- aggregate = 2,
- table = 3,
- port = 4,
- queue = 5,
- group = 6,
- group_desc = 7,
- group_features = 8,
- experimenter = 0xffff
- ),
-
- # version 1.3
- of_g.VERSION_1_3:dict(
- desc = 0,
- flow = 1,
- aggregate = 2,
- table = 3,
- port = 4,
- queue = 5,
- group = 6,
- group_desc = 7,
- group_features = 8,
- meter = 9,
- meter_config = 10,
- meter_features = 11,
- table_features = 12,
- port_desc = 13,
- experimenter = 0xffff,
- bsn_lacp = 0xffff,
- bsn_switch_pipeline = 0xffff,
- bsn_port_counter = 0xffff,
- bsn_vlan_counter = 0xffff
- )
- }
-
-common_flow_mod_types = dict(
- add = 0,
- modify = 1,
- modify_strict = 2,
- delete = 3,
- delete_strict = 4
- )
-
-flow_mod_types = {
- # version 1.0
- of_g.VERSION_1_0:common_flow_mod_types,
- of_g.VERSION_1_1:common_flow_mod_types,
- of_g.VERSION_1_2:common_flow_mod_types,
- of_g.VERSION_1_3:common_flow_mod_types
- }
-
-# These do not translate to objects (yet)
-error_types = {
- # version 1.0
- of_g.VERSION_1_0:dict(
- hello_failed = 0,
- bad_request = 1,
- bad_action = 2,
- flow_mod_failed = 3,
- port_mod_failed = 4,
- queue_op_failed = 5
- ),
-
- # version 1.1
- of_g.VERSION_1_1:dict(
- hello_failed = 0,
- bad_request = 1,
- bad_action = 2,
- bad_instruction = 3,
- bad_match = 4,
- flow_mod_failed = 5,
- group_mod_failed = 6,
- port_mod_failed = 7,
- table_mod_failed = 8,
- queue_op_failed = 9,
- switch_config_failed = 10
- ),
-
- # version 1.2
- of_g.VERSION_1_2:dict(
- hello_failed = 0,
- bad_request = 1,
- bad_action = 2,
- bad_instruction = 3,
- bad_match = 4,
- flow_mod_failed = 5,
- group_mod_failed = 6,
- port_mod_failed = 7,
- table_mod_failed = 8,
- queue_op_failed = 9,
- switch_config_failed = 10,
- role_request_failed = 11,
- experimenter = 0xffff
- ),
-
- # version 1.3
- of_g.VERSION_1_3:dict(
- hello_failed = 0,
- bad_request = 1,
- bad_action = 2,
- bad_instruction = 3,
- bad_match = 4,
- flow_mod_failed = 5,
- group_mod_failed = 6,
- port_mod_failed = 7,
- table_mod_failed = 8,
- queue_op_failed = 9,
- switch_config_failed = 10,
- role_request_failed = 11,
- meter_mod_failed = 12,
- table_features_failed= 13,
- experimenter = 0xffff
- )
- }
-
-group_mod_types = {
- # version 1.0
- of_g.VERSION_1_0:dict(),
-
- # version 1.1
- of_g.VERSION_1_1:dict(
- add = 0,
- modify = 1,
- delete = 2
- ),
-
- # version 1.2
- of_g.VERSION_1_2:dict(
- add = 0,
- modify = 1,
- delete = 2
- ),
-
- # version 1.3
- of_g.VERSION_1_3:dict(
- add = 0,
- modify = 1,
- delete = 2
- )
- }
-
-################################################################
-#
-# type_val is the primary data structure that maps an
-# (class_name, version) pair to the wire data type value
-#
-################################################################
-
-type_val = dict()
-inheritance_map = dict()
+def class_is_inheritance_root(cls):
+ return cls in inheritance_map
def generate_maps():
- for parent, versioned in inheritance_data.items():
- inheritance_map[parent] = set()
- for ver, subclasses in versioned.items():
- for subcls in subclasses:
- inheritance_map[parent].add(subcls)
+ for ofclass in loxi_globals.unified.classes:
+ if ofclass.virtual and not ofclass.superclass:
+ inheritance_map[ofclass.name] = set()
- for version, classes in message_types.items():
- for cls in classes:
- name = "of_" + cls
- type_val[(name, version)] = classes[cls]
+ for version, protocol in loxi_globals.ir.items():
+ wire_version = version.wire_version
+ for ofclass in protocol.classes:
+ root = ofclass.inheritance_root()
+ if not root or root == ofclass or root.name == "of_header":
+ continue
- for parent, versioned in inheritance_data.items():
- for version, subclasses in versioned.items():
- for subcls, value in subclasses.items():
- name = parent + "_" + subcls
- type_val[(name, version)] = value
-
- # Special case OF-1.2 match type
- type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
- type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
-
-# Utility function
-def dict_to_array(d, m_val, def_val=-1):
- """
- Given a dictionary, d, with each value a small integer,
- produce an array indexed by the integer whose value is the key.
- @param d The dictionary
- @param m_val Ignore values greater than m_val
- @param def_val The default value (for indices not in range of d)
- """
-
- # Get the max value in range for hash
- max_val = 0
- for key in d:
- if (d[key] > max_val) and (d[key] < m_val):
- max_val = d[key]
- ar = []
- for x in range(0, max_val + 1):
- ar.append(def_val)
- for key in d:
- if (d[key] < m_val):
- ar[d[key]] = key
- return ar
-
-def type_array_len(version_indexed, max_val):
- """
- Given versioned information about a type, calculate how long
- the unified array should be.
-
- @param version_indexed A dict indexed by version. Each value is a
- dict indexed by a name and whose value is an integer
- @param max_val Ignore values greater than this for length calcs
- """
- # First, find the max length of all arrays
- arr_len = 0
- for version, val_dict in version_indexed.items():
- ar = dict_to_array(val_dict, max_val, invalid_type)
- if arr_len < len(ar):
- arr_len = len(ar)
- return arr_len
+ inheritance_map[root.name].add(ofclass.name)
def sub_class_map(base_type, version):
"""
@@ -461,99 +66,10 @@
if base_type not in inheritance_map:
return rv
- for instance in inheritance_map[base_type]:
- subcls = loxi_utils.instance_to_class(instance, base_type)
+ for subcls in inheritance_map[base_type]:
if not loxi_utils.class_in_version(subcls, version):
continue
+ instance = loxi_utils.class_to_instance(subcls, base_type)
rv.append((instance, subcls))
return rv
-
-################################################################
-#
-# Extension related data and functions
-#
-################################################################
-
-# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
-# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
-extension_message_subtype = {
- # version 1.0
- of_g.VERSION_1_0:dict( # Version 1.0 extensions
- bsn = { # BSN extensions; indexed by class name, value is subtype
- },
- nicira = { # Nicira extensions, value is subtype
- },
- ),
- of_g.VERSION_1_1:dict( # Version 1.0 extensions
- bsn = { # BSN extensions; indexed by class name, value is subtype
- },
- ),
- of_g.VERSION_1_2:dict( # Version 1.0 extensions
- bsn = { # BSN extensions; indexed by class name, value is subtype
- },
- ),
- of_g.VERSION_1_3:dict( # Version 1.0 extensions
- bsn = { # BSN extensions; indexed by class name, value is subtype
- },
- ),
-}
-
-# Set to empty dict if no extension actions defined
-# Per OF Version, per experimenter, map actions to subtype
-extension_action_subtype = {
- # version 1.0
- of_g.VERSION_1_0:dict( # Version 1.0 extensions
- bsn = { # of_action_bsn_
- },
- nicira = { # of_action_nicira_
- }
- ),
- of_g.VERSION_1_1:dict( # Version 1.0 extensions
- bsn = { # of_action_bsn_
- },
- nicira = { # of_action_nicira_
- }
- ),
- of_g.VERSION_1_2:dict( # Version 1.0 extensions
- bsn = { # of_action_bsn_
- },
- nicira = { # of_action_nicira_
- }
- ),
- of_g.VERSION_1_3:dict( # Version 1.0 extensions
- bsn = { # of_action_bsn_
- },
- nicira = { # of_action_nicira_
- }
- ),
-}
-
-# Set to empty dict if no extension actions defined
-# Per OF Version, per experimenter, map actions to subtype
-extension_action_id_subtype = {
- # version 1.0
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict( # Version 1.3 extensions
- bsn = { # of_action_bsn_
- },
- nicira = { # of_action_nicira_
- }
- ),
-}
-
-# Set to empty dict if no extension instructions defined
-extension_instruction_subtype = {
- # version 1.0
- of_g.VERSION_1_0:dict(),
- of_g.VERSION_1_1:dict(),
- of_g.VERSION_1_2:dict(),
- of_g.VERSION_1_3:dict(
- bsn = { # of_instruction_bsn_
- },
- nicira = { # of_instruction_nicira_
- }
- ),
-}
diff --git a/cmdline.py b/cmdline.py
index 6395fff..de7070a 100644
--- a/cmdline.py
+++ b/cmdline.py
@@ -33,7 +33,7 @@
# The default configuration dictionary for LOXI code generation
options_default = {
"lang" : "c",
- "version-list" : "1.0 1.1 1.2 1.3",
+ "version-list" : "1.0 1.1 1.2 1.3 1.4",
"install-dir" : "loxi_output",
}
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 8726632..c8f70e6 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -184,14 +184,25 @@
@memoize
def enums(self):
name_version_enum_map = OrderedDefaultDict(lambda: OrderedDict())
+ name_stable_map = {}
for version in self.versions:
- logger.info("version: {}".format(version.ir_version))
+ logger.debug("version: {}".format(version.ir_version))
of_protocol = loxi_globals.ir[version.ir_version]
for enum in of_protocol.enums:
name_version_enum_map[enum.name][version] = enum
+ stable = (enum.params.get('stable') == 'True')
- enums = [ JavaEnum(name, version_enum_map) for name, version_enum_map,
+ logger.debug("Enum: %s stable: %s", enum.name, stable)
+
+ if not enum.name in name_stable_map:
+ name_stable_map[enum.name] = stable
+ else:
+ if name_stable_map[enum.name] != stable:
+ raise Exception("Inconsistent enum stability (should be caught " +\
+ " by IR)")
+
+ enums = [ JavaEnum(name, name_stable_map[name], version_enum_map) for name, version_enum_map,
in name_version_enum_map.items() ]
# inelegant - need java name here
@@ -402,6 +413,9 @@
reply_name = m.group(1) + "Reply"
if model.interface_by_name(reply_name):
return ["OFRequest<%s>" % reply_name ]
+ elif self.name == "OFBundleCtrlMsg":
+ reply_name = "OFBundleCtrlMsg"
+ return ["OFRequest<%s>" % reply_name ]
return []
@@ -573,6 +587,8 @@
if not find(lambda x: x.name == "mask", self.ir_model_members):
virtual_members.append(
JavaVirtualMember(self, "mask", find(lambda x: x.name == "value", self.ir_model_members).java_type))
+ elif self.name =="OFErrorMsg":
+ virtual_members += [ JavaVirtualMember(self, "data", java_type.error_cause_data) ]
if not find(lambda m: m.name == "version", self.ir_model_members):
virtual_members.append(JavaVirtualMember(self, "version", java_type.of_version))
@@ -815,7 +831,7 @@
entry = enum.entry_by_version_value(self.msg.version, self.value)
return "%s.%s" % ( enum.name, entry.name)
except KeyError, e:
- logger.debug("No enum found", e)
+ logger.debug("No enum found for type %s version %s value %s", java_type, self.msg.version, self.value)
return self.value
@property
@@ -1041,8 +1057,9 @@
#######################################################################
class JavaEnum(object):
- def __init__(self, c_name, version_enum_map):
+ def __init__(self, c_name, stable, version_enum_map):
self.c_name = c_name
+ self.stable = stable
self.name = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
@@ -1062,7 +1079,23 @@
self.entries = [ e for e in self.entries if e.name not in model.enum_entry_blacklist[self.name] ]
self.package = "org.projectfloodlight.openflow.protocol"
- self.metadata = model.enum_metadata_map[self.name]
+ static_metadata = model.enum_metadata_map[self.name]
+ if self.stable:
+ # need this to look up wire_type, which does not matter
+ any_version = version_enum_map.keys()[0]
+ # if this is a 'stable' enum, i.e., its value won't change, add
+ # a "Metadata" (virtual) field "StableValue" to it that returns
+ # its wirevalue.
+ stable_value = JavaModel.OFEnumPropertyMetadata("StableValue",
+ self.wire_type(any_version),
+ value = lambda entry: entry.stable_value)
+
+ self.metadata = JavaModel.OFEnumMetadata(
+ properties=static_metadata.properties + (stable_value, ),
+ to_string=static_metadata.to_string
+ )
+ else:
+ self.metadata = static_metadata
def wire_type(self, version):
ir_enum = self.version_enums[version]
@@ -1113,7 +1146,7 @@
@property
def constructor_params(self):
- return [ m.value(self) for m in self.enum.metadata.properties ]
+ return [ (m.type, m.value(self)) for m in self.enum.metadata.properties ]
def has_value(self, version):
return version in self.values
@@ -1129,6 +1162,13 @@
return [ self.values[version] if version in self.values else not_present for version in versions ]
@property
+ def stable_value(self):
+ if self.enum.stable:
+ return self.values.values()[0]
+ else:
+ raise Exception("Enum {} not stable".format(self.enum.name))
+
+ @property
@memoize
def masked_enum_group(self):
group = find(lambda g: self.name in g.members, model.masked_enum_groups[self.enum.name])
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 5ff987d..900aa6d 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -53,9 +53,12 @@
signed-craziness
"""
signed, bits, cast_needed = java_primitives_info[t]
+ if t == 'boolean':
+ return "true" if bool(value) and value not in("False", "false") else "false"
+
max = (1 << bits)-1
if value > max:
- raise Exception("Value %d to large for type %s" % (value, t))
+ raise Exception("Value %s to large for type %s" % (value, t))
if signed:
max_pos = (1 << (bits-1)) - 1
@@ -361,10 +364,20 @@
.op(read="IPv4Address.read4Bytes(bb)", \
write="$name.write4Bytes(bb)",
default='IPv4Address.NONE')
+ipv4_list = JType('List<IPv4Address>') \
+ .op(read='ChannelUtils.readList(bb, $length, IPv4Address.READER)',
+ write='ChannelUtils.writeList(bb, $name)',
+ default='ImmutableList.<IPv4Address>of()',
+ funnel="FunnelUtils.putList($name, sink)")
ipv6 = JType("IPv6Address") \
.op(read="IPv6Address.read16Bytes(bb)", \
write="$name.write16Bytes(bb)",
default='IPv6Address.NONE')
+ipv6_list = JType('List<IPv46ddress>') \
+ .op(read='ChannelUtils.readList(bb, $length, IPv6Address.READER)',
+ write='ChannelUtils.writeList(bb, $name)',
+ default='ImmutableList.<IPv6Address>of()',
+ funnel="FunnelUtils.putList($name, sink)")
packetin_reason = gen_enum_jtype("OFPacketInReason")
transport_port = JType("TransportPort")\
.op(read="TransportPort.read2Bytes(bb)",
@@ -437,10 +450,14 @@
table_stats_wildcards = JType("int") \
.op(read='bb.readInt()',
write='bb.writeInt($name)')
-port_bitmap = JType('OFBitMask128') \
+port_bitmap_128 = JType('OFBitMask128') \
.op(read='OFBitMask128.read16Bytes(bb)',
write='$name.write16Bytes(bb)',
default='OFBitMask128.NONE')
+port_bitmap_512 = JType('OFBitMask512') \
+ .op(read='OFBitMask512.read64Bytes(bb)',
+ write='$name.write64Bytes(bb)',
+ default='OFBitMask512.NONE')
table_id = JType("TableId") \
.op(read='TableId.readByte(bb)',
write='$name.writeByte(bb)',
@@ -458,6 +475,10 @@
port_speed = JType("PortSpeed")
error_type = JType("OFErrorType")
+of_message = JType("OFMessage")\
+ .op(read="OFMessageVer$version.READER.readFrom(bb)",
+ write="$name.writeTo(bb)")
+
of_type = JType("OFType", 'byte') \
.op(read='bb.readByte()', write='bb.writeByte($name)')
action_type= gen_enum_jtype("OFActionType")\
@@ -505,6 +526,10 @@
.op(read='GenTableId.read2Bytes(bb)',
write='$name.write2Bytes(bb)',
)
+bundle_id = JType("BundleId") \
+ .op(read='BundleId.read4Bytes(bb)',
+ write='$name.write4Bytes(bb)',
+ )
udf = JType("UDF") \
.op(version=ANY, read="UDF.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="UDF.ZERO")
error_cause_data = JType("OFErrorCauseData") \
@@ -519,6 +544,10 @@
generic_t = JType("T")
+table_desc = JType('OFTableDesc') \
+ .op(read='OFTableDescVer$version.READER.readFrom(bb)', \
+ write='$name.writeTo(bb)')
+
default_mtype_to_jtype_convert_map = {
'uint8_t' : u8,
@@ -535,6 +564,8 @@
'list(of_uint32_t)' : u32_list,
'list(of_uint8_t)' : u8_list,
'list(of_oxm_t)' : oxm_list,
+ 'list(of_ipv4_t)' : ipv4_list,
+ 'list(of_ipv6_t)' : ipv6_list,
'of_octets_t' : octets,
'of_match_t': of_match,
'of_fm_cmd_t': flow_mod_cmd,
@@ -550,11 +581,13 @@
'of_wc_bmap_t': flow_wildcards,
'of_oxm_t': oxm,
'of_meter_features_t': meter_features,
- 'of_bitmap_128_t': port_bitmap,
+ 'of_bitmap_128_t': port_bitmap_128,
+ 'of_bitmap_512_t': port_bitmap_512,
'of_checksum_128_t': u128,
'of_bsn_vport_t': bsn_vport,
'of_app_code_t': app_code,
'of_sig_id_t': sig_id,
+ 'of_table_desc_t': table_desc,
}
## Map that defines exceptions from the standard loxi->java mapping scheme
@@ -608,9 +641,18 @@
'of_oxm_mpls_label_masked' : { 'value' : u32obj, 'value_mask' : u32obj },
'of_oxm_mpls_tc' : { 'value' : u8obj },
'of_oxm_mpls_tc_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
+ 'of_oxm_mpls_bos' : { 'value' : boolean_value },
+ 'of_oxm_mpls_bos_masked' : { 'value' : boolean_value, 'value_mask' : boolean_value },
+ 'of_oxm_ipv6_exthdr' : { 'value' : u16obj },
+ 'of_oxm_ipv6_exthdr_masked' : { 'value' : u16obj, 'value_mask' : u16obj },
+ 'of_oxm_pbb_uca' : { 'value' : boolean_value },
+ 'of_oxm_pbb_uca_masked' : { 'value' : boolean_value, 'value_mask' : boolean_value },
- 'of_oxm_bsn_in_ports_128' : { 'value': port_bitmap },
- 'of_oxm_bsn_in_ports_128_masked' : { 'value': port_bitmap, 'value_mask': port_bitmap },
+ 'of_oxm_bsn_in_ports_128' : { 'value': port_bitmap_128 },
+ 'of_oxm_bsn_in_ports_128_masked' : { 'value': port_bitmap_128, 'value_mask': port_bitmap_128 },
+
+ 'of_oxm_bsn_in_ports_512' : { 'value': port_bitmap_512 },
+ 'of_oxm_bsn_in_ports_512_masked' : { 'value': port_bitmap_512, 'value_mask': port_bitmap_512 },
'of_oxm_bsn_lag_id' : { 'value' : lag_id },
'of_oxm_bsn_lag_id_masked' : { 'value' : lag_id, 'value_mask' : lag_id },
@@ -663,6 +705,9 @@
'of_oxm_bsn_vlan_xlate_port_group_id' : { 'value' : class_id },
'of_oxm_bsn_vlan_xlate_port_group_id_masked' : { 'value' : class_id, 'value_mask' : class_id },
+ 'of_oxm_bsn_l2_cache_hit' : { 'value' : boolean_value },
+ 'of_oxm_bsn_l2_cache_hit_masked' : { 'value' : boolean_value, 'value_mask' : boolean_value },
+
'of_table_stats_entry': { 'wildcards': table_stats_wildcards },
'of_match_v1': { 'vlan_vid' : vlan_vid_match, 'vlan_pcp': vlan_pcp,
'eth_type': eth_type, 'ip_dscp': ip_dscp, 'ip_proto': ip_proto,
@@ -704,8 +749,10 @@
'of_features_reply' : { 'auxiliary_id' : of_aux_id},
'of_oxm_och_sigtype' : { 'value' : u8obj },
'of_oxm_och_sigtype_basic' : { 'value' : u8obj },
- 'of_oxm_och_sigid' : {'value' : sig_id},
- 'of_oxm_och_sigid_basic' : {'value' : sig_id},
+ 'of_oxm_och_sigid' : {'value' : sig_id},
+ 'of_oxm_och_sigid_basic' : {'value' : sig_id},
+
+ 'of_bundle_add_msg' : { 'data' : of_message },
}
@@ -770,6 +817,8 @@
return action_type_set
elif field_name == "table_id" and re.match(r'of_bsn_gentable.*', obj_name):
return gen_table_id
+ elif field_name == "bundle_id" and re.match(r'of_bundle_.*', obj_name):
+ return bundle_id
elif c_type in default_mtype_to_jtype_convert_map:
return default_mtype_to_jtype_convert_map[c_type]
elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type):
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/BundleIdGenerator.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/BundleIdGenerator.java
new file mode 100644
index 0000000..2cb3583
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/BundleIdGenerator.java
@@ -0,0 +1,7 @@
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.types.BundleId;
+
+public interface BundleIdGenerator {
+ BundleId nextBundleId();
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/BundleIdGenerators.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/BundleIdGenerators.java
new file mode 100644
index 0000000..997e0cd
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/BundleIdGenerators.java
@@ -0,0 +1,28 @@
+package org.projectfloodlight.openflow.protocol;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.projectfloodlight.openflow.types.BundleId;
+
+public class BundleIdGenerators {
+ private static final BundleIdGenerator GLOBAL_BUNDLE_ID_GENERATOR = create();
+
+ public static BundleIdGenerator create() {
+ return new StandardBundleIdGenerator();
+ }
+
+ public static BundleIdGenerator global() {
+ return GLOBAL_BUNDLE_ID_GENERATOR;
+ }
+}
+
+class StandardBundleIdGenerator implements BundleIdGenerator {
+
+ private final AtomicInteger idGen = new AtomicInteger();
+
+ @Override
+ public BundleId nextBundleId() {
+ return BundleId.of(idGen.incrementAndGet());
+ }
+
+}
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFVersion.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFVersion.java
index 6f54e5f..0c54fdc 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFVersion.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFVersion.java
@@ -1,7 +1,7 @@
package org.projectfloodlight.openflow.protocol;
public enum OFVersion {
- OF_10(1), OF_11(2), OF_12(3), OF_13(4);
+ OF_10(1), OF_11(2), OF_12(3), OF_13(4), OF_14(5);
public final int wireVersion;
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
index 9fb3fd4..e2f172b 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
@@ -14,6 +14,7 @@
import org.projectfloodlight.openflow.types.LagId;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBitMask128;
+import org.projectfloodlight.openflow.types.OFBitMask512;
import org.projectfloodlight.openflow.types.OFBooleanValue;
import org.projectfloodlight.openflow.types.OFMetadata;
import org.projectfloodlight.openflow.types.OFPort;
@@ -179,12 +180,33 @@
new MatchField<U8>("mpls_tc", MatchFields.MPLS_TC,
new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.MPLS_UNICAST, EthType.MPLS_MULTICAST));
- public final static MatchField<U64> TUNNEL_ID =
+ public final static MatchField<OFBooleanValue> MPLS_BOS =
+ new MatchField<OFBooleanValue>("mpls_bos", MatchFields.MPLS_BOS,
+ new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.MPLS_UNICAST, EthType.MPLS_MULTICAST));
+
+ public final static MatchField<U64> TUNNEL_ID =
new MatchField<U64>("tunnel_id", MatchFields.TUNNEL_ID);
+ public final static MatchField<U16> IPV6_EXTHDR =
+ new MatchField<U16>("ipv6_exthdr", MatchFields.IPV6_EXTHDR);
+
+ public final static MatchField<OFBooleanValue> PBB_UCA =
+ new MatchField<OFBooleanValue>("pbb_uca", MatchFields.PBB_UCA);
+
+ public final static MatchField<IPv4Address> TUNNEL_IPV4_SRC =
+ new MatchField<IPv4Address>("tunnel_ipv4_src", MatchFields.TUNNEL_IPV4_SRC,
+ new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv4));
+
+ public final static MatchField<IPv4Address> TUNNEL_IPV4_DST =
+ new MatchField<IPv4Address>("tunnel_ipv4_dst", MatchFields.TUNNEL_IPV4_DST,
+ new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv4));
+
public final static MatchField<OFBitMask128> BSN_IN_PORTS_128 =
new MatchField<OFBitMask128>("bsn_in_ports_128", MatchFields.BSN_IN_PORTS_128);
+ public final static MatchField<OFBitMask512> BSN_IN_PORTS_512 =
+ new MatchField<OFBitMask512>("bsn_in_ports_512", MatchFields.BSN_IN_PORTS_512);
+
public final static MatchField<LagId> BSN_LAG_ID =
new MatchField<LagId>("bsn_lag_id", MatchFields.BSN_LAG_ID);
@@ -236,7 +258,6 @@
public final static MatchField<ClassId> BSN_VLAN_XLATE_PORT_GROUP_ID =
new MatchField<ClassId>("bsn_vlan_xlate_port_group_id", MatchFields.BSN_VLAN_XLATE_PORT_GROUP_ID);
-
public final static MatchField<U8> OCH_SIGTYPE =
new MatchField<U8>("och_sigtype",
MatchFields.OCH_SIGTYPE);
@@ -245,7 +266,6 @@
new MatchField<U8>("och_sigtype_basic",
MatchFields.OCH_SIGTYPE_BASIC);
-
public final static MatchField<CircuitSignalID> OCH_SIGID =
new MatchField<CircuitSignalID>("och_sigid",
MatchFields.OCH_SIGID);
@@ -254,6 +274,9 @@
new MatchField<CircuitSignalID>("och_sigid_basic",
MatchFields.OCH_SIGID);
+ public final static MatchField<OFBooleanValue> BSN_L2_CACHE_HIT =
+ new MatchField<OFBooleanValue>("bsn_l2_cache_hit", MatchFields.BSN_L2_CACHE_HIT);
+
public String getName() {
return name;
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
index 3bf717b..12e2b20 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
@@ -38,8 +38,14 @@
IPV6_ND_TLL,
MPLS_LABEL,
MPLS_TC,
+ MPLS_BOS,
TUNNEL_ID,
+ IPV6_EXTHDR,
+ PBB_UCA,
+ TUNNEL_IPV4_SRC,
+ TUNNEL_IPV4_DST,
BSN_IN_PORTS_128,
+ BSN_IN_PORTS_512,
BSN_LAG_ID,
BSN_VRF,
BSN_GLOBAL_VRF_ALLOWED,
@@ -57,8 +63,9 @@
BSN_UDF7,
BSN_TCP_FLAGS,
BSN_VLAN_XLATE_PORT_GROUP_ID,
+ BSN_L2_CACHE_HIT,
OCH_SIGTYPE,
OCH_SIGTYPE_BASIC,
OCH_SIGID,
- OCH_SIGID_BASIC,;
+ OCH_SIGID_BASIC,
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver14/ChannelUtilsVer14.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver14/ChannelUtilsVer14.java
new file mode 100644
index 0000000..c893cab
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver14/ChannelUtilsVer14.java
@@ -0,0 +1,26 @@
+package org.projectfloodlight.openflow.protocol.ver14;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+import org.projectfloodlight.openflow.protocol.OFMatchBmap;
+import org.projectfloodlight.openflow.protocol.match.Match;
+
+/**
+ * Collection of helper functions for reading and writing into ChannelBuffers
+ *
+ * @author capveg
+ */
+
+public class ChannelUtilsVer14 {
+ public static Match readOFMatch(final ChannelBuffer bb) throws OFParseError {
+ return OFMatchV3Ver14.READER.readFrom(bb);
+ }
+
+ public static OFMatchBmap readOFMatchBmap(ChannelBuffer bb) {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public static void writeOFMatchBmap(ChannelBuffer bb, OFMatchBmap match) {
+ throw new UnsupportedOperationException("not implemented");
+ }
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/BundleId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/BundleId.java
new file mode 100644
index 0000000..cccf67e
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/BundleId.java
@@ -0,0 +1,92 @@
+package org.projectfloodlight.openflow.types;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.UnsignedInts;
+
+@Immutable
+public class BundleId implements OFValueType<BundleId> {
+ static final int LENGTH = 4;
+
+ private final static int NONE_VAL = 0;
+ public final static BundleId NONE = new BundleId(NONE_VAL);
+
+ private final static int NO_MASK_VAL = 0xFFFFFFFF;
+ public final static BundleId NO_MASK = new BundleId(NO_MASK_VAL);
+ public final static BundleId FULL_MASK = NONE;
+
+ private final int rawValue;
+
+ private BundleId(final int rawValue) {
+ this.rawValue = rawValue;
+ }
+
+ public static BundleId of(final int raw) {
+ if(raw == NONE_VAL)
+ return NONE;
+ else if(raw == NO_MASK_VAL)
+ return NO_MASK;
+ return new BundleId(raw);
+ }
+
+ public int getInt() {
+ return rawValue;
+ }
+
+ @Override
+ public int getLength() {
+ return LENGTH;
+ }
+
+ @Override
+ public String toString() {
+ return UnsignedInts.toString(rawValue);
+ }
+
+ @Override
+ public BundleId applyMask(BundleId mask) {
+ return BundleId.of(rawValue & mask.rawValue); }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + rawValue;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BundleId other = (BundleId) obj;
+ if (rawValue != other.rawValue)
+ return false;
+ return true;
+ }
+
+ public void write4Bytes(ChannelBuffer c) {
+ c.writeInt(rawValue);
+ }
+
+ public static BundleId read4Bytes(ChannelBuffer c) {
+ return BundleId.of(c.readInt());
+ }
+
+ @Override
+ public int compareTo(BundleId o) {
+ return UnsignedInts.compare(rawValue, rawValue);
+ }
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(rawValue);
+ }
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
index 7d7c38e..98c1253 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
@@ -43,7 +43,7 @@
@Override
public String toString() {
- return Integer.toString(rawValue);
+ return UnsignedInts.toString(rawValue);
}
@Override
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
index 3a1b15e..eb37a20 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
@@ -12,14 +12,16 @@
import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
-
+import org.projectfloodlight.openflow.protocol.Writeable;
+import org.projectfloodlight.openflow.protocol.OFMessageReader;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
/**
* Wrapper around an IPv4Address address
*
* @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
*/
-public class IPv4Address extends IPAddress<IPv4Address> {
+public class IPv4Address extends IPAddress<IPv4Address> implements Writeable {
static final int LENGTH = 4;
private final int rawValue;
@@ -38,6 +40,15 @@
this.rawValue = rawValue;
}
+ public final static Reader READER = new Reader();
+
+ private static class Reader implements OFMessageReader<IPv4Address> {
+ @Override
+ public IPv4Address readFrom(ChannelBuffer bb) throws OFParseError {
+ return new IPv4Address(bb.readInt());
+ }
+ }
+
@Override
public IPVersion getIpVersion() {
return IPVersion.IPv4;
@@ -345,4 +356,8 @@
sink.putInt(rawValue);
}
+ @Override
+ public void writeTo(ChannelBuffer bb) {
+ bb.writeInt(rawValue);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
index 471d0fb..9d6fa4d 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
@@ -8,19 +8,22 @@
import javax.annotation.Nonnull;
import org.jboss.netty.buffer.ChannelBuffer;
-import org.projectfloodlight.openflow.exceptions.OFParseError;
import com.google.common.base.Preconditions;
import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Longs;
+import org.projectfloodlight.openflow.protocol.Writeable;
+import org.projectfloodlight.openflow.protocol.OFMessageReader;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+
/**
* IPv6 address object. Instance controlled, immutable. Internal representation:
* two 64 bit longs (not that you'd have to know).
*
* @author Andreas Wundsam <andreas.wundsam@teleteach.de>
*/
-public class IPv6Address extends IPAddress<IPv6Address> {
+public class IPv6Address extends IPAddress<IPv6Address> implements Writeable {
static final int LENGTH = 16;
private final long raw1;
private final long raw2;
@@ -43,6 +46,15 @@
this.raw2 = raw2;
}
+ public final static Reader READER = new Reader();
+
+ private static class Reader implements OFMessageReader<IPv6Address> {
+ @Override
+ public IPv6Address readFrom(ChannelBuffer bb) throws OFParseError {
+ return new IPv6Address(bb.readLong(), bb.readLong());
+ }
+ }
+
@Override
public IPVersion getIpVersion() {
return IPVersion.IPv6;
@@ -213,8 +225,17 @@
public static IPv6Address of(@Nonnull final String string) throws IllegalArgumentException {
Preconditions.checkNotNull(string, "string must not be null");
+ // remove the zone id
+ int zoneDelimIndex = string.indexOf("%");
+ String substring;
+ if (zoneDelimIndex != -1) {
+ substring = string.substring(0, zoneDelimIndex);
+ } else {
+ substring = string;
+ }
+
IPv6Builder builder = new IPv6Builder();
- String[] parts = colonPattern.split(string, -1);
+ String[] parts = colonPattern.split(substring, -1);
int leftWord = 0;
int leftIndex = 0;
@@ -538,4 +559,10 @@
sink.putLong(raw1);
sink.putLong(raw2);
}
+
+ @Override
+ public void writeTo(ChannelBuffer bb) {
+ bb.writeLong(raw1);
+ bb.writeLong(raw2);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask512.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask512.java
new file mode 100644
index 0000000..3fe9b88
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask512.java
@@ -0,0 +1,205 @@
+package org.projectfloodlight.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+import com.google.common.hash.PrimitiveSink;
+
+public class OFBitMask512 implements OFValueType<OFBitMask512> {
+
+ static final int LENGTH = 64;
+
+ private final long raw1;
+ private final long raw2;
+ private final long raw3;
+ private final long raw4;
+ private final long raw5;
+ private final long raw6;
+ private final long raw7;
+ private final long raw8;
+
+ public static final OFBitMask512 ALL = new OFBitMask512(-1, -1, -1, -1,
+ -1, -1, -1, -1);
+ public static final OFBitMask512 NONE = new OFBitMask512(0, 0, 0, 0,
+ 0, 0, 0, 0);
+
+ public static final OFBitMask512 NO_MASK = ALL;
+ public static final OFBitMask512 FULL_MASK = NONE;
+
+ private OFBitMask512(long raw1, long raw2, long raw3, long raw4,
+ long raw5, long raw6, long raw7, long raw8) {
+ this.raw1 = raw1;
+ this.raw2 = raw2;
+ this.raw3 = raw3;
+ this.raw4 = raw4;
+ this.raw5 = raw5;
+ this.raw6 = raw6;
+ this.raw7 = raw7;
+ this.raw8 = raw8;
+ }
+
+ public static OFBitMask512 of(long raw1, long raw2, long raw3, long raw4,
+ long raw5, long raw6, long raw7, long raw8) {
+ if (raw1 == -1 && raw2 == -1 && raw3 == -1 && raw4 == -1
+ && raw5 == -1 && raw6 == -1 && raw7 == -1 && raw8 == -1)
+ return ALL;
+ if (raw1 == 0 && raw2 == 0 && raw3 == 0 && raw4 == 0
+ && raw5 == 0 && raw6 == 0 && raw7 == 0 && raw8 == 0)
+ return NONE;
+ return new OFBitMask512(raw1, raw2, raw3, raw4, raw5, raw6, raw7, raw8);
+ }
+
+ @Override
+ public int getLength() {
+ return LENGTH;
+ }
+
+ @Override
+ public OFBitMask512 applyMask(OFBitMask512 mask) {
+ return of(this.raw1 & mask.raw1, this.raw2 & mask.raw2,
+ this.raw3 & mask.raw3, this.raw4 & mask.raw4,
+ this.raw5 & mask.raw5, this.raw6 & mask.raw6,
+ this.raw7 & mask.raw7, this.raw8 & mask.raw8);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (raw1 ^ (raw1 >>> 32));
+ result = prime * result + (int) (raw2 ^ (raw2 >>> 32));
+ result = prime * result + (int) (raw3 ^ (raw3 >>> 32));
+ result = prime * result + (int) (raw4 ^ (raw4 >>> 32));
+ result = prime * result + (int) (raw5 ^ (raw5 >>> 32));
+ result = prime * result + (int) (raw6 ^ (raw6 >>> 32));
+ result = prime * result + (int) (raw7 ^ (raw7 >>> 32));
+ result = prime * result + (int) (raw8 ^ (raw8 >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ OFBitMask512 other = (OFBitMask512) obj;
+ if (raw1 != other.raw1) return false;
+ if (raw2 != other.raw2) return false;
+ if (raw3 != other.raw3) return false;
+ if (raw4 != other.raw4) return false;
+ if (raw5 != other.raw5) return false;
+ if (raw6 != other.raw6) return false;
+ if (raw7 != other.raw7) return false;
+ if (raw8 != other.raw8) return false;
+ return true;
+ }
+
+ protected static boolean isBitOn(long raw1, long raw2, long raw3, long raw4,
+ long raw5, long raw6, long raw7, long raw8, int bit) {
+ if (bit < 0 || bit >= 512)
+ throw new IndexOutOfBoundsException();
+ long word;
+ if (bit < 64) {
+ word = raw8;
+ } else if (bit < 128) {
+ word = raw7;
+ bit -= 64;
+ } else if (bit < 128) {
+ word = raw6;
+ bit -= 128;
+ } else if (bit < 128) {
+ word = raw5;
+ bit -= 192;
+ } else if (bit < 128) {
+ word = raw4;
+ bit -= 256;
+ } else if (bit < 128) {
+ word = raw3;
+ bit -= 320;
+ } else if (bit < 128) {
+ word = raw2;
+ bit -= 384;
+ } else {
+ word = raw1;
+ bit -= 448;
+ }
+ return (word & ((long)1 << bit)) != 0;
+ }
+
+ public void write64Bytes(ChannelBuffer cb) {
+ cb.writeLong(raw1);
+ cb.writeLong(raw2);
+ cb.writeLong(raw3);
+ cb.writeLong(raw4);
+ cb.writeLong(raw5);
+ cb.writeLong(raw6);
+ cb.writeLong(raw7);
+ cb.writeLong(raw8);
+ }
+
+ public static OFBitMask512 read64Bytes(ChannelBuffer cb) {
+ long raw1 = cb.readLong();
+ long raw2 = cb.readLong();
+ long raw3 = cb.readLong();
+ long raw4 = cb.readLong();
+ long raw5 = cb.readLong();
+ long raw6 = cb.readLong();
+ long raw7 = cb.readLong();
+ long raw8 = cb.readLong();
+ return of(raw1, raw2, raw3, raw4, raw5, raw6, raw7, raw8);
+ }
+
+ public boolean isOn(int bit) {
+ return isBitOn(raw1, raw2, raw3, raw4, raw5, raw6, raw7, raw8, bit);
+ }
+
+ @Override
+ public String toString() {
+ return (String.format("%64s", Long.toBinaryString(raw8))
+ + String.format("%64s", Long.toBinaryString(raw7))
+ + String.format("%64s", Long.toBinaryString(raw6))
+ + String.format("%64s", Long.toBinaryString(raw5))
+ + String.format("%64s", Long.toBinaryString(raw4))
+ + String.format("%64s", Long.toBinaryString(raw3))
+ + String.format("%64s", Long.toBinaryString(raw2))
+ + String.format("%64s", Long.toBinaryString(raw1))).replaceAll(" ", "0");
+ }
+
+ @Override
+ public int compareTo(OFBitMask512 o) {
+ long c = this.raw1 - o.raw1;
+ if (c != 0)
+ return Long.signum(c);
+ c = this.raw2 - o.raw2;
+ if (c != 0)
+ return Long.signum(c);
+ c = this.raw3 - o.raw3;
+ if (c != 0)
+ return Long.signum(c);
+ c = this.raw4 - o.raw4;
+ if (c != 0)
+ return Long.signum(c);
+ c = this.raw5 - o.raw5;
+ if (c != 0)
+ return Long.signum(c);
+ c = this.raw6 - o.raw6;
+ if (c != 0)
+ return Long.signum(c);
+ c = this.raw7 - o.raw7;
+ if (c != 0)
+ return Long.signum(c);
+ return Long.signum(this.raw8 - o.raw8);
+ }
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putLong(raw1);
+ sink.putLong(raw2);
+ sink.putLong(raw3);
+ sink.putLong(raw4);
+ sink.putLong(raw5);
+ sink.putLong(raw6);
+ sink.putLong(raw7);
+ sink.putLong(raw8);
+ }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/MultiplePktInReasonUtil.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/MultiplePktInReasonUtil.java
index a919f62..3ee588f 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/MultiplePktInReasonUtil.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/MultiplePktInReasonUtil.java
@@ -22,10 +22,10 @@
* reasons in Match.MetaData field.
* */
public static Set<OFBsnPktinFlag> getOFBsnPktinFlags(OFPacketIn pktIn) {
- if(pktIn.getVersion() != OFVersion.OF_13) {
+ if(pktIn.getVersion().compareTo(OFVersion.OF_13) < 0) {
throw new IllegalArgumentException("multiple pkt in reasons are "
+ "only supported by BVS using "
- + "openflow 1.3");
+ + "openflow version >= 1.3");
}
Match match = pktIn.getMatch();
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
index a397c2a..fd26856 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
@@ -399,4 +399,10 @@
assertNotNull(e.getMessage());
}
}
+
+ @Test
+ public void testZoneId() throws OFParseError {
+ assertEquals("::", IPv6Address.of("::%eth0").toString(true, false));
+ assertEquals("1:0:0:4::8", IPv6Address.of("1:0:0:4:0:0:0:8%2").toString(true, false));
+ }
}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/protocol/OFPortDescTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/protocol/OFPortDescTest.java
new file mode 100644
index 0000000..965e314
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/protocol/OFPortDescTest.java
@@ -0,0 +1,53 @@
+package org.projectfloodlight.protocol;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFPortConfig;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortState;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+import static org.hamcrest.Matchers.is;
+
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests auxiliary OFPortDesc methods for all versions of OpenFlow
+ *
+ * @author Jason Parraga <jason.parraga@bigswitch.com>
+ */
+public class OFPortDescTest {
+
+ @Test
+ public void testIsEnabled() {
+ testIsEnabledForFactory(OFFactories.getFactory(OFVersion.OF_10));
+ testIsEnabledForFactory(OFFactories.getFactory(OFVersion.OF_11));
+ testIsEnabledForFactory(OFFactories.getFactory(OFVersion.OF_12));
+ testIsEnabledForFactory(OFFactories.getFactory(OFVersion.OF_13));
+ testIsEnabledForFactory(OFFactories.getFactory(OFVersion.OF_14));
+ }
+
+ public void testIsEnabledForFactory(OFFactory factory) {
+ // Default
+ OFPortDesc desc = factory.buildPortDesc()
+ .build();
+ assertThat(desc.isEnabled(), is(true));
+
+ // Partially disabled
+ desc = factory.buildPortDesc()
+ .setConfig(new HashSet<OFPortConfig>(Arrays.asList(OFPortConfig.PORT_DOWN)))
+ .build();
+ assertThat(desc.isEnabled(), is(false));
+
+ // Fully disabled
+ desc = factory.buildPortDesc()
+ .setConfig(new HashSet<OFPortConfig>(Arrays.asList(OFPortConfig.PORT_DOWN)))
+ .setState(new HashSet<OFPortState>(Arrays.asList(OFPortState.LINK_DOWN)))
+ .build();
+ assertThat(desc.isEnabled(), is(false));
+ }
+}
diff --git a/java_gen/templates/const.java b/java_gen/templates/const.java
index a7786f4..1828bac 100644
--- a/java_gen/templates/const.java
+++ b/java_gen/templates/const.java
@@ -37,7 +37,7 @@
public enum ${class_name} {
//:: for i, entry in enumerate(enum.entries):
//:: if enum.metadata.properties:
-//:: params = "({})".format(", ".join(entry.constructor_params))
+//:: params = "({})".format(", ".join(type.format_value(value) for (type, value) in entry.constructor_params))
//:: else:
//:: params = ""
//:: #endif
diff --git a/java_gen/templates/custom/OFMatchV3.Builder.java b/java_gen/templates/custom/OFMatchV3.Builder.java
new file mode 100644
index 0000000..54b35ba
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3.Builder.java
@@ -0,0 +1,106 @@
+
+ private OFOxmList.Builder oxmListBuilder;
+
+ private void initBuilder() {
+ if (oxmListBuilder != null)
+ return;
+ oxmListBuilder = new OFOxmList.Builder();
+ }
+
+ private void updateOxmList() {
+ this.oxmList = this.oxmListBuilder.build();
+ this.oxmListSet = true;
+ }
+
+ private <F extends OFValueType<F>> OFOxm<F> getOxm(MatchField<F> field) {
+//:: if has_parent:
+ return this.oxmListSet ? this.oxmList.get(field) : parentMessage.oxmList.get(field);
+//:: else:
+ return this.oxmListSet ? this.oxmList.get(field) : null;
+//:: #endif
+ }
+
+ @Override
+ public <F extends OFValueType<F>> F get(MatchField<F> field)
+ throws UnsupportedOperationException {
+ OFOxm<F> value = getOxm(field);
+ if (value == null)
+ return null;
+ return value.getValue();
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+ throws UnsupportedOperationException {
+ OFOxm<F> value = getOxm(field);
+ if (value == null || !value.isMasked())
+ return null;
+ // TODO: If changing OXMs to extend Masked, then use it here
+ return Masked.of(value.getValue(), value.getMask());
+ }
+
+ @Override
+ public boolean supports(MatchField<?> field) {
+ return supportsField(field);
+ }
+
+ @Override
+ public boolean supportsMasked(MatchField<?> field) {
+ return supportsField(field);
+ }
+
+ @Override
+ public boolean isExact(MatchField<?> field) {
+ OFOxm<?> value = getOxm(field);
+ return (value != null && !value.isMasked());
+ }
+
+ @Override
+ public boolean isFullyWildcarded(MatchField<?> field) {
+ OFOxm<?> value = getOxm(field);
+ return (value == null);
+ }
+
+ @Override
+ public boolean isPartiallyMasked(MatchField<?> field) {
+ OFOxm<?> value = getOxm(field);
+ return (value != null && value.isMasked());
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder setExact(
+ MatchField<F> field, F value) {
+ initBuilder();
+ OFOxm<F> oxm = OFFactories.getFactory(OFVersion.${version.constant_version}).oxms().fromValue(value, field);
+ this.oxmListBuilder.set(oxm);
+ updateOxmList();
+ return this;
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder setMasked(
+ MatchField<F> field, F value, F mask) {
+ initBuilder();
+ OFOxm<F> oxm = OFFactories.getFactory(OFVersion.${version.constant_version}).oxms().fromValueAndMask(value, mask, field);
+ this.oxmListBuilder.set(oxm);
+ updateOxmList();
+ return this;
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder setMasked(
+ MatchField<F> field, Masked<F> valueWithMask) {
+ initBuilder();
+ OFOxm<F> oxm = OFFactories.getFactory(OFVersion.${version.constant_version}).oxms().fromMasked(valueWithMask, field);
+ this.oxmListBuilder.set(oxm);
+ updateOxmList();
+ return this;
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+ initBuilder();
+ this.oxmListBuilder.unset(field);
+ updateOxmList();
+ return this;
+ }
diff --git a/java_gen/templates/custom/OFMatchV3.java b/java_gen/templates/custom/OFMatchV3.java
new file mode 100644
index 0000000..799135c
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3.java
@@ -0,0 +1,112 @@
+//:: from generic_utils import OrderedSet
+//:: from java_gen.java_model import model
+ @Override
+ public <F extends OFValueType<F>> F get(MatchField<F> field)
+ throws UnsupportedOperationException {
+ if (!supports(field))
+ throw new UnsupportedOperationException("${msg.name} does not support matching on field " + field.getName());
+
+ OFOxm<F> oxm = this.oxmList.get(field);
+
+ if (oxm == null || !field.arePrerequisitesOK(this))
+ return null;
+
+ return oxm.getValue();
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+ throws UnsupportedOperationException {
+ if (!supportsMasked(field))
+ throw new UnsupportedOperationException("${msg.name} does not support masked matching on field " + field.getName());
+
+ OFOxm<F> oxm = this.oxmList.get(field);
+
+ if (oxm == null || !field.arePrerequisitesOK(this))
+ return null;
+
+ if (oxm.getMask() == null)
+ return null;
+
+ // TODO: Make OfOxm extend Masked and just return the OXM?
+ return Masked.of(oxm.getValue(), oxm.getMask());
+ }
+
+ private static boolean supportsField(MatchField<?> field) {
+ switch (field.id) {
+ //:: for id_constant in sorted(set(id_constant for _, id_constant, _ in model.oxm_map.values())):
+ case ${id_constant}:
+ //:: #endfor
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean supports(MatchField<?> field) {
+ return supportsField(field);
+ }
+
+ @Override
+ public boolean supportsMasked(MatchField<?> field) {
+ return supportsField(field);
+ }
+
+ @Override
+ public boolean isExact(MatchField<?> field) {
+ if (!supports(field))
+ throw new UnsupportedOperationException("${msg.name} does not support matching on field " + field.getName());
+
+ OFOxm<?> oxm = this.oxmList.get(field);
+
+ return oxm != null && !oxm.isMasked();
+ }
+
+ @Override
+ public boolean isFullyWildcarded(MatchField<?> field) {
+ if (!supports(field))
+ throw new UnsupportedOperationException("${msg.name} does not support matching on field " + field.getName());
+
+ OFOxm<?> oxm = this.oxmList.get(field);
+
+ return oxm == null;
+ }
+
+ @Override
+ public boolean isPartiallyMasked(MatchField<?> field) {
+ if (!supports(field))
+ throw new UnsupportedOperationException("${msg.name} does not support matching on field " + field.getName());
+
+ OFOxm<?> oxm = this.oxmList.get(field);
+
+ return oxm != null && oxm.isMasked();
+ }
+
+ private class MatchFieldIterator extends AbstractIterator<MatchField<?>> {
+ private Iterator<OFOxm<?>> oxmIterator;
+
+ MatchFieldIterator() {
+ oxmIterator = oxmList.iterator();
+ }
+
+ @Override
+ protected MatchField<?> computeNext() {
+ while(oxmIterator.hasNext()) {
+ OFOxm<?> oxm = oxmIterator.next();
+ if(oxm.getMatchField().arePrerequisitesOK(${msg.name}.this))
+ return oxm.getMatchField();
+ }
+ endOfData();
+ return null;
+ }
+ }
+
+ @Override
+ public Iterable<MatchField<?>> getMatchFields() {
+ return new Iterable<MatchField<?>>() {
+ public Iterator<MatchField<?>> iterator() {
+ return new MatchFieldIterator();
+ }
+ };
+ }
diff --git a/java_gen/templates/custom/OFMatchV3Ver12.Builder.java b/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
index 3fae367..ae2ecaa 100644
--- a/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
+++ b/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
@@ -1,106 +1 @@
-
- private OFOxmList.Builder oxmListBuilder;
-
- private synchronized void initBuilder() {
- if (oxmListBuilder != null)
- return;
- oxmListBuilder = new OFOxmList.Builder();
- }
-
- private synchronized void updateOxmList() {
- this.oxmList = this.oxmListBuilder.build();
- this.oxmListSet = true;
- }
-
- private <F extends OFValueType<F>> OFOxm<F> getOxm(MatchField<F> field) {
-//:: if has_parent:
- return this.oxmListSet ? this.oxmList.get(field) : parentMessage.oxmList.get(field);
-//:: else:
- return this.oxmListSet ? this.oxmList.get(field) : null;
-//:: #endif
- }
-
- @Override
- public synchronized <F extends OFValueType<F>> F get(MatchField<F> field)
- throws UnsupportedOperationException {
- OFOxm<F> value = getOxm(field);
- if (value == null)
- return null;
- return value.getValue();
- }
-
- @Override
- public synchronized <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
- throws UnsupportedOperationException {
- OFOxm<F> value = getOxm(field);
- if (value == null || !value.isMasked())
- return null;
- // TODO: If changing OXMs to extend Masked, then use it here
- return Masked.of(value.getValue(), value.getMask());
- }
-
- @Override
- public boolean supports(MatchField<?> field) {
- return supportsField(field);
- }
-
- @Override
- public boolean supportsMasked(MatchField<?> field) {
- return supportsField(field);
- }
-
- @Override
- public synchronized boolean isExact(MatchField<?> field) {
- OFOxm<?> value = getOxm(field);
- return (value != null && !value.isMasked());
- }
-
- @Override
- public synchronized boolean isFullyWildcarded(MatchField<?> field) {
- OFOxm<?> value = getOxm(field);
- return (value == null);
- }
-
- @Override
- public synchronized boolean isPartiallyMasked(MatchField<?> field) {
- OFOxm<?> value = getOxm(field);
- return (value != null && value.isMasked());
- }
-
- @Override
- public synchronized <F extends OFValueType<F>> Match.Builder setExact(
- MatchField<F> field, F value) {
- initBuilder();
- OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValue(value, field);
- this.oxmListBuilder.set(oxm);
- updateOxmList();
- return this;
- }
-
- @Override
- public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
- MatchField<F> field, F value, F mask) {
- initBuilder();
- OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValueAndMask(value, mask, field);
- this.oxmListBuilder.set(oxm);
- updateOxmList();
- return this;
- }
-
- @Override
- public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
- MatchField<F> field, Masked<F> valueWithMask) {
- initBuilder();
- OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromMasked(valueWithMask, field);
- this.oxmListBuilder.set(oxm);
- updateOxmList();
- return this;
- }
-
- @Override
- public synchronized <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
- initBuilder();
- this.oxmListBuilder.unset(field);
- updateOxmList();
- return this;
- }
+//:: include("custom/OFMatchV3.Builder.java", msg=msg, version=version, has_parent=False)
diff --git a/java_gen/templates/custom/OFMatchV3Ver12.java b/java_gen/templates/custom/OFMatchV3Ver12.java
index 81092c1..225b0dc 100644
--- a/java_gen/templates/custom/OFMatchV3Ver12.java
+++ b/java_gen/templates/custom/OFMatchV3Ver12.java
@@ -1,114 +1 @@
-
- @Override
- public <F extends OFValueType<F>> F get(MatchField<F> field)
- throws UnsupportedOperationException {
- if (!supports(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
-
- OFOxm<F> oxm = this.oxmList.get(field);
-
- if (oxm == null || !field.arePrerequisitesOK(this))
- return null;
-
- return oxm.getValue();
- }
-
- @Override
- public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
- throws UnsupportedOperationException {
- if (!supportsMasked(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support masked matching on field " + field.getName());
-
- OFOxm<F> oxm = this.oxmList.get(field);
-
- if (oxm == null || !field.arePrerequisitesOK(this))
- return null;
-
- if (oxm.getMask() == null)
- return null;
-
- // TODO: Make OfOxm extend Masked and just return the OXM?
- return Masked.of(oxm.getValue(), oxm.getMask());
- }
-
- private static boolean supportsField(MatchField<?> field) {
- switch (field.id) {
- case IN_PORT:
- case IN_PHY_PORT:
- case METADATA:
- case ETH_DST:
- case ETH_SRC:
- case ETH_TYPE:
- case VLAN_VID:
- case VLAN_PCP:
- case IP_DSCP:
- case IP_ECN:
- case IP_PROTO:
- case IPV4_SRC:
- case IPV4_DST:
- case TCP_SRC:
- case TCP_DST:
- case UDP_SRC:
- case UDP_DST:
- case SCTP_SRC:
- case SCTP_DST:
- case ICMPV4_TYPE:
- case ICMPV4_CODE:
- case ARP_OP:
- case ARP_SPA:
- case ARP_TPA:
- case ARP_SHA:
- case ARP_THA:
- case IPV6_SRC:
- case IPV6_DST:
- case IPV6_FLABEL:
- return true;
- default:
- return false;
- }
- }
-
- @Override
- public boolean supports(MatchField<?> field) {
- return supportsField(field);
- }
-
- @Override
- public boolean supportsMasked(MatchField<?> field) {
- return supportsField(field);
- }
-
- @Override
- public boolean isExact(MatchField<?> field) {
- if (!supports(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
-
- OFOxm<?> oxm = this.oxmList.get(field);
-
- return oxm != null && !oxm.isMasked();
- }
-
- @Override
- public boolean isFullyWildcarded(MatchField<?> field) {
- if (!supports(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
-
- OFOxm<?> oxm = this.oxmList.get(field);
-
- return oxm == null;
- }
-
- @Override
- public boolean isPartiallyMasked(MatchField<?> field) {
- if (!supports(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
-
- OFOxm<?> oxm = this.oxmList.get(field);
-
- return oxm != null && oxm.isMasked();
- }
-
- @Override
- public Iterable<MatchField<?>> getMatchFields() {
- throw new UnsupportedOperationException();
- }
+//:: include("custom/OFMatchV3.java", msg=msg, has_parent=False)
diff --git a/java_gen/templates/custom/OFMatchV3Ver12_toString.java b/java_gen/templates/custom/OFMatchV3Ver12_toString.java
new file mode 100644
index 0000000..3b2783b
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3Ver12_toString.java
@@ -0,0 +1 @@
+//:: include("custom/OFMatch_toString.java", msg=msg, has_parent=False)
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
index 79cbdbc..ae2ecaa 100644
--- a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
+++ b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
@@ -1,107 +1 @@
-
- private OFOxmList.Builder oxmListBuilder;
-
- private void initBuilder() {
- if (oxmListBuilder != null)
- return;
- oxmListBuilder = new OFOxmList.Builder();
- }
-
- private void updateOxmList() {
- this.oxmList = this.oxmListBuilder.build();
- this.oxmListSet = true;
- }
-
- private <F extends OFValueType<F>> OFOxm<F> getOxm(MatchField<F> field) {
-//:: if has_parent:
- return this.oxmListSet ? this.oxmList.get(field) : parentMessage.oxmList.get(field);
-//:: else:
- return this.oxmListSet ? this.oxmList.get(field) : null;
-//:: #endif
- }
-
- @Override
- public <F extends OFValueType<F>> F get(MatchField<F> field)
- throws UnsupportedOperationException {
- OFOxm<F> value = getOxm(field);
- if (value == null)
- return null;
- return value.getValue();
- }
-
- @Override
- public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
- throws UnsupportedOperationException {
- OFOxm<F> value = getOxm(field);
- if (value == null || !value.isMasked())
- return null;
- // TODO: If changing OXMs to extend Masked, then use it here
- return Masked.of(value.getValue(), value.getMask());
- }
-
- @Override
- public boolean supports(MatchField<?> field) {
- return supportsField(field);
- }
-
- @Override
- public boolean supportsMasked(MatchField<?> field) {
- return supportsField(field);
- }
-
- @Override
- public boolean isExact(MatchField<?> field) {
- OFOxm<?> value = getOxm(field);
- return (value != null && !value.isMasked());
- }
-
- @Override
- public boolean isFullyWildcarded(MatchField<?> field) {
- OFOxm<?> value = getOxm(field);
- return (value == null);
- }
-
- @Override
- public boolean isPartiallyMasked(MatchField<?> field) {
- OFOxm<?> value = getOxm(field);
- return (value != null && value.isMasked());
- }
-
- @Override
- public <F extends OFValueType<F>> Match.Builder setExact(
- MatchField<F> field, F value) {
- initBuilder();
- OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValue(value, field);
- this.oxmListBuilder.set(oxm);
- updateOxmList();
- return this;
- }
-
- @Override
- public <F extends OFValueType<F>> Match.Builder setMasked(
- MatchField<F> field, F value, F mask) {
- initBuilder();
- OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValueAndMask(value, mask, field);
- this.oxmListBuilder.set(oxm);
- updateOxmList();
- return this;
- }
-
- @Override
- public <F extends OFValueType<F>> Match.Builder setMasked(
- MatchField<F> field, Masked<F> valueWithMask) {
- initBuilder();
- OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromMasked(valueWithMask, field);
- this.oxmListBuilder.set(oxm);
- updateOxmList();
- return this;
- }
-
- @Override
- public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
- initBuilder();
- this.oxmListBuilder.unset(field);
- updateOxmList();
- return this;
- }
-
+//:: include("custom/OFMatchV3.Builder.java", msg=msg, version=version, has_parent=False)
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.java b/java_gen/templates/custom/OFMatchV3Ver13.java
index dc8e637..225b0dc 100644
--- a/java_gen/templates/custom/OFMatchV3Ver13.java
+++ b/java_gen/templates/custom/OFMatchV3Ver13.java
@@ -1,112 +1 @@
-//:: from generic_utils import OrderedSet
-//:: from java_gen.java_model import model
- @Override
- public <F extends OFValueType<F>> F get(MatchField<F> field)
- throws UnsupportedOperationException {
- if (!supports(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
-
- OFOxm<F> oxm = this.oxmList.get(field);
-
- if (oxm == null || !field.arePrerequisitesOK(this))
- return null;
-
- return oxm.getValue();
- }
-
- @Override
- public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
- throws UnsupportedOperationException {
- if (!supportsMasked(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support masked matching on field " + field.getName());
-
- OFOxm<F> oxm = this.oxmList.get(field);
-
- if (oxm == null || !field.arePrerequisitesOK(this))
- return null;
-
- if (oxm.getMask() == null)
- return null;
-
- // TODO: Make OfOxm extend Masked and just return the OXM?
- return Masked.of(oxm.getValue(), oxm.getMask());
- }
-
- private static boolean supportsField(MatchField<?> field) {
- switch (field.id) {
- //:: for id_constant in sorted(set(id_constant for _, id_constant, _ in model.oxm_map.values())):
- case ${id_constant}:
- //:: #endfor
- return true;
- default:
- return false;
- }
- }
-
- @Override
- public boolean supports(MatchField<?> field) {
- return supportsField(field);
- }
-
- @Override
- public boolean supportsMasked(MatchField<?> field) {
- return supportsField(field);
- }
-
- @Override
- public boolean isExact(MatchField<?> field) {
- if (!supports(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
-
- OFOxm<?> oxm = this.oxmList.get(field);
-
- return oxm != null && !oxm.isMasked();
- }
-
- @Override
- public boolean isFullyWildcarded(MatchField<?> field) {
- if (!supports(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
-
- OFOxm<?> oxm = this.oxmList.get(field);
-
- return oxm == null;
- }
-
- @Override
- public boolean isPartiallyMasked(MatchField<?> field) {
- if (!supports(field))
- throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
-
- OFOxm<?> oxm = this.oxmList.get(field);
-
- return oxm != null && oxm.isMasked();
- }
-
- private class MatchFieldIterator extends AbstractIterator<MatchField<?>> {
- private Iterator<OFOxm<?>> oxmIterator;
-
- MatchFieldIterator() {
- oxmIterator = oxmList.iterator();
- }
-
- @Override
- protected MatchField<?> computeNext() {
- while(oxmIterator.hasNext()) {
- OFOxm<?> oxm = oxmIterator.next();
- if(oxm.getMatchField().arePrerequisitesOK(OFMatchV3Ver13.this))
- return oxm.getMatchField();
- }
- endOfData();
- return null;
- }
- }
-
- @Override
- public Iterable<MatchField<?>> getMatchFields() {
- return new Iterable<MatchField<?>>() {
- public Iterator<MatchField<?>> iterator() {
- return new MatchFieldIterator();
- }
- };
- }
+//:: include("custom/OFMatchV3.java", msg=msg, has_parent=False)
diff --git a/java_gen/templates/custom/OFMatchV3Ver14.Builder.java b/java_gen/templates/custom/OFMatchV3Ver14.Builder.java
new file mode 100644
index 0000000..ae2ecaa
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3Ver14.Builder.java
@@ -0,0 +1 @@
+//:: include("custom/OFMatchV3.Builder.java", msg=msg, version=version, has_parent=False)
diff --git a/java_gen/templates/custom/OFMatchV3Ver14.java b/java_gen/templates/custom/OFMatchV3Ver14.java
new file mode 100644
index 0000000..225b0dc
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3Ver14.java
@@ -0,0 +1 @@
+//:: include("custom/OFMatchV3.java", msg=msg, has_parent=False)
diff --git a/java_gen/templates/custom/OFMatchV3Ver14_toString.java b/java_gen/templates/custom/OFMatchV3Ver14_toString.java
new file mode 100644
index 0000000..3b2783b
--- /dev/null
+++ b/java_gen/templates/custom/OFMatchV3Ver14_toString.java
@@ -0,0 +1 @@
+//:: include("custom/OFMatch_toString.java", msg=msg, has_parent=False)
diff --git a/java_gen/templates/custom/OFPortDesc.java b/java_gen/templates/custom/OFPortDesc.java
new file mode 100644
index 0000000..3be1b70
--- /dev/null
+++ b/java_gen/templates/custom/OFPortDesc.java
@@ -0,0 +1,11 @@
+
+ /**
+ * Returns true if the port is up, i.e., it's neither administratively
+ * down nor link down. It currently does NOT take STP state into
+ * consideration
+ * @return whether the port is up
+ */
+ public boolean isEnabled() {
+ return (!state.contains(OFPortState.LINK_DOWN) && !config.contains(OFPortConfig.PORT_DOWN));
+ }
+
\ No newline at end of file
diff --git a/java_gen/templates/custom/OFPortDescVer10.java b/java_gen/templates/custom/OFPortDescVer10.java
new file mode 100644
index 0000000..782a726
--- /dev/null
+++ b/java_gen/templates/custom/OFPortDescVer10.java
@@ -0,0 +1 @@
+//:: include("custom/OFPortDesc.java", msg=msg, has_parent=False)
\ No newline at end of file
diff --git a/java_gen/templates/custom/OFPortDescVer11.java b/java_gen/templates/custom/OFPortDescVer11.java
new file mode 100644
index 0000000..782a726
--- /dev/null
+++ b/java_gen/templates/custom/OFPortDescVer11.java
@@ -0,0 +1 @@
+//:: include("custom/OFPortDesc.java", msg=msg, has_parent=False)
\ No newline at end of file
diff --git a/java_gen/templates/custom/OFPortDescVer12.java b/java_gen/templates/custom/OFPortDescVer12.java
new file mode 100644
index 0000000..782a726
--- /dev/null
+++ b/java_gen/templates/custom/OFPortDescVer12.java
@@ -0,0 +1 @@
+//:: include("custom/OFPortDesc.java", msg=msg, has_parent=False)
\ No newline at end of file
diff --git a/java_gen/templates/custom/OFPortDescVer13.java b/java_gen/templates/custom/OFPortDescVer13.java
new file mode 100644
index 0000000..782a726
--- /dev/null
+++ b/java_gen/templates/custom/OFPortDescVer13.java
@@ -0,0 +1 @@
+//:: include("custom/OFPortDesc.java", msg=msg, has_parent=False)
\ No newline at end of file
diff --git a/java_gen/templates/custom/OFPortDescVer14.java b/java_gen/templates/custom/OFPortDescVer14.java
new file mode 100644
index 0000000..782a726
--- /dev/null
+++ b/java_gen/templates/custom/OFPortDescVer14.java
@@ -0,0 +1 @@
+//:: include("custom/OFPortDesc.java", msg=msg, has_parent=False)
\ No newline at end of file
diff --git a/java_gen/templates/custom/interface/OFPortDesc.java b/java_gen/templates/custom/interface/OFPortDesc.java
new file mode 100644
index 0000000..ecf39f3
--- /dev/null
+++ b/java_gen/templates/custom/interface/OFPortDesc.java
@@ -0,0 +1,2 @@
+ // Additional method
+ boolean isEnabled();
\ No newline at end of file
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index f1d72b2..0b032ac 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -74,6 +74,13 @@
${impl_class}(${
", ".join("%s %s" %(prop.java_type.public_type, prop.name) for prop in msg.data_members) }) {
//:: for prop in msg.data_members:
+//:: if not prop.java_type.is_primitive and (not prop.default_value or prop.default_value != "null"):
+ if(${prop.name} == null) {
+ throw new NullPointerException("${msg.name}: property ${prop.name} cannot be null");
+ }
+//:: #endif
+//:: #endfor
+//:: for prop in msg.data_members:
this.${prop.name} = ${prop.name};
//:: #endfor
}
@@ -88,7 +95,7 @@
//:: include("_field_accessors.java", msg=msg, generate_setters=False, builder=False, has_parent=False)
//:: if os.path.exists("%s/custom/%s.java" % (template_dir, msg.name)):
- //:: include("custom/%s.java" % msg.name, msg=msg)
+ //:: include("custom/%s.java" % msg.name, msg=msg, version=version)
//:: #endif
//:: if msg.data_members:
@@ -124,7 +131,7 @@
//
//:: if os.path.exists("%s/custom/%s.Builder_normalize_stanza.java" % (template_dir, msg.name)):
- //:: include("custom/%s.Builder_normalize_stanza.java" % msg.name, msg=msg, has_parent=False)
+ //:: include("custom/%s.Builder_normalize_stanza.java" % msg.name, msg=msg, version=version, has_parent=False)
//:: #endif
return new ${impl_class}(
//:: for i, prop in enumerate(msg.data_members):
@@ -134,7 +141,7 @@
);
}
//:: if os.path.exists("%s/custom/%s.Builder.java" % (template_dir, msg.name)):
- //:: include("custom/%s.Builder.java" % msg.name, msg=msg, has_parent=True)
+ //:: include("custom/%s.Builder.java" % msg.name, msg=msg, version=version, has_parent=True)
//:: #endif
}
@@ -164,7 +171,7 @@
//:: #endfor
//:: if os.path.exists("%s/custom/%s.Builder_normalize_stanza.java" % (template_dir, msg.name)):
- //:: include("custom/%s.Builder_normalize_stanza.java" % msg.name, msg=msg, has_parent=False)
+ //:: include("custom/%s.Builder_normalize_stanza.java" % msg.name, msg=msg, version=version, has_parent=False)
//:: #endif
return new ${impl_class}(
@@ -175,7 +182,7 @@
);
}
//:: if os.path.exists("%s/custom/%s.Builder.java" % (template_dir, msg.name)):
- //:: include("custom/%s.Builder.java" % msg.name, msg=msg, has_parent=False)
+ //:: include("custom/%s.Builder.java" % msg.name, msg=msg, version=version, has_parent=False)
//:: #endif
}
@@ -249,7 +256,7 @@
//:: if msg.data_members:
//:: if os.path.exists("%s/custom/%s.Reader_normalize_stanza.java" % (template_dir, msg.name)):
- //:: include("custom/%s.Reader_normalize_stanza.java" % msg.name, msg=msg, has_parent=False)
+ //:: include("custom/%s.Reader_normalize_stanza.java" % msg.name, msg=msg, version=version, has_parent=False)
//:: #endif
${impl_class} ${msg.variable_name} = new ${impl_class}(
${",\n ".join(
@@ -364,7 +371,7 @@
}
//:: if os.path.exists("%s/custom/%s_toString.java" % (template_dir, msg.name)):
- //:: include("custom/%s_toString.java" % msg.name, msg=msg, has_parent=False)
+ //:: include("custom/%s_toString.java" % msg.name, msg=msg, version=version, has_parent=False)
//:: else:
@Override
public String toString() {
diff --git a/java_gen/templates/of_factories.java b/java_gen/templates/of_factories.java
index f9ec015..ba73286 100644
--- a/java_gen/templates/of_factories.java
+++ b/java_gen/templates/of_factories.java
@@ -51,7 +51,9 @@
private static class GenericReader implements OFMessageReader<OFMessage> {
public OFMessage readFrom(ChannelBuffer bb) throws OFParseError {
- short wireVersion = U8.f(bb.getByte(0));
+ if(!bb.readable())
+ return null;
+ short wireVersion = U8.f(bb.getByte(bb.readerIndex()));
OFFactory factory;
switch (wireVersion) {
//:: for v in versions:
diff --git a/java_gen/templates/of_interface.java b/java_gen/templates/of_interface.java
index a515ad1..18e2cf1 100644
--- a/java_gen/templates/of_interface.java
+++ b/java_gen/templates/of_interface.java
@@ -27,6 +27,7 @@
//::
//:: import itertools
//:: import re
+//:: import os
//:: include('_copyright.java')
//:: include('_autogen.java')
@@ -39,6 +40,10 @@
//:: for prop in msg.members:
${prop.java_type.public_type} ${prop.getter_name}()${ "" if prop.is_universal else " throws UnsupportedOperationException"};
//:: #endfor
+//:: if os.path.exists("%s/custom/interface/%s.java" % (template_dir, msg.name)):
+//:: include("custom/interface/%s.java" % msg.name, msg=msg)
+//:: #endif
+
void writeTo(ChannelBuffer channelBuffer);
diff --git a/lang_c.py b/lang_c.py
index c7b68f7..bec4a65 100644
--- a/lang_c.py
+++ b/lang_c.py
@@ -125,7 +125,6 @@
fn(outfile, os.path.basename(name))
c_gen.codegen.build_class_metadata()
c_gen.codegen.generate_classes(install_dir)
- c_gen.codegen.generate_header_classes(install_dir)
c_gen.codegen.generate_classes_header(install_dir)
c_gen.codegen.generate_lists(install_dir)
c_gen.codegen.generate_strings(install_dir)
diff --git a/lang_python.py b/lang_python.py
index 019b62d..18fca27 100644
--- a/lang_python.py
+++ b/lang_python.py
@@ -28,12 +28,6 @@
"""
Python backend for LOXI
-This language specific file defines a dictionary 'targets' that
-defines the generated files and the functions used to generate them.
-
-For each generated file there is a generate_* function in py_gen.codegen
-and a Tenjin template under py_gen/templates.
-
Target directory structure:
pyloxi:
loxi:
@@ -64,51 +58,9 @@
"""
import os
-from loxi_globals import OFVersions
-import loxi_globals
-import loxi_utils.loxi_utils as loxi_utils
-import py_gen
-import py_gen.util
import py_gen.codegen
-import template_utils
-versions = {
- 1: "of10",
- 2: "of11",
- 3: "of12",
- 4: "of13",
-}
-
-prefix = 'pyloxi/loxi'
-
-modules = {
- 1: ["action", "common", "const", "message", "util"],
- 2: ["action", "common", "const", "instruction", "message", "util"],
- 3: ["action", "common", "const", "instruction", "message", "oxm", "util"],
- 4: ["action", "action_id", "common", "const", "instruction", "instruction_id", "message", "meter_band", "oxm", "bsn_tlv", "util"],
-}
-
-def make_gen(name, version):
- fn = getattr(py_gen.codegen, "generate_" + name)
- return lambda out, name: fn(out, name, version)
-
-def static(template_name):
- return lambda out, name: py_gen.util.render_template(out, template_name)
-
-targets = {
- prefix+'/__init__.py': static('toplevel_init.py'),
- prefix+'/pp.py': static('pp.py'),
- prefix+'/generic_util.py': static('generic_util.py'),
-}
-
-for version, subdir in versions.items():
- targets['%s/%s/__init__.py' % (prefix, subdir)] = make_gen('init', version)
- for module in modules[version]:
- filename = '%s/%s/%s.py' % (prefix, subdir, module)
- targets[filename] = make_gen(module, OFVersions.from_wire(version))
+PREFIX = 'pyloxi/loxi'
def generate(install_dir):
- py_gen.codegen.init()
- for (name, fn) in targets.items():
- with template_utils.open_output(install_dir, name) as outfile:
- fn(outfile, os.path.basename(name))
+ py_gen.codegen.codegen(os.path.join(install_dir, PREFIX))
diff --git a/loxi_front_end/parser.py b/loxi_front_end/parser.py
index 4a465f7..fbf476d 100644
--- a/loxi_front_end/parser.py
+++ b/loxi_front_end/parser.py
@@ -68,7 +68,7 @@
s('}') - s(';')
# Enums
-enum_param_name = kw("wire_type") | kw("bitmask") | kw("complete")
+enum_param_name = kw("wire_type") | kw("bitmask") | kw("complete") | kw("stable")
enum_param = P.Group(enum_param_name - s('=') - word)
enum_param_list = P.Forward()
enum_param_list << enum_param + P.Optional(s(',') + P.Optional(enum_param_list))
diff --git a/loxi_globals.py b/loxi_globals.py
index e8b21bd..b4662cb 100644
--- a/loxi_globals.py
+++ b/loxi_globals.py
@@ -37,12 +37,14 @@
VERSION_1_1 = OFVersion("1.1", 2)
VERSION_1_2 = OFVersion("1.2", 3)
VERSION_1_3 = OFVersion("1.3", 4)
+ VERSION_1_4 = OFVersion("1.4", 5)
all_supported = (
VERSION_1_0,
VERSION_1_1,
VERSION_1_2,
VERSION_1_3,
+ VERSION_1_4,
)
wire_version_map = { v.wire_version : v for v in all_supported }
diff --git a/loxi_ir/ir.py b/loxi_ir/ir.py
index 0e95473..7b9a0b6 100644
--- a/loxi_ir/ir.py
+++ b/loxi_ir/ir.py
@@ -145,6 +145,15 @@
def is_subclassof(self, super_class_name):
return self.name != super_class_name and self.is_instanceof(super_class_name)
+ def inheritance_root(self):
+ if not self.superclass:
+ if self.virtual:
+ return self
+ else:
+ return None
+ else:
+ return self.superclass.inheritance_root()
+
@property
def is_message(self):
return self.is_instanceof("of_header")
diff --git a/loxi_ir/ir_offset.py b/loxi_ir/ir_offset.py
index 1d66115..490c6b0 100644
--- a/loxi_ir/ir_offset.py
+++ b/loxi_ir/ir_offset.py
@@ -36,6 +36,7 @@
2: "uint32_t",
3: "uint32_t",
4: "uint32_t",
+ 5: "uint32_t",
"short_name":"port_no"
},
of_port_desc_t = {
@@ -43,6 +44,7 @@
2: "of_port_desc_t",
3: "of_port_desc_t",
4: "of_port_desc_t",
+ 5: "of_port_desc_t",
"short_name":"port_desc"
},
of_bsn_vport_t = {
@@ -50,6 +52,7 @@
2: "of_bsn_vport_t",
3: "of_bsn_vport_t",
4: "of_bsn_vport_t",
+ 5: "of_bsn_vport_t",
"short_name":"bsn_vport"
},
of_fm_cmd_t = { # Flow mod command went from u16 to u8
@@ -57,6 +60,7 @@
2: "uint8_t",
3: "uint8_t",
4: "uint8_t",
+ 5: "uint8_t",
"short_name":"fm_cmd"
},
of_wc_bmap_t = { # Wildcard bitmap
@@ -64,6 +68,7 @@
2: "uint32_t",
3: "uint64_t",
4: "uint64_t",
+ 5: "uint64_t",
"short_name":"wc_bmap"
},
of_match_bmap_t = { # Match bitmap
@@ -71,6 +76,7 @@
2: "uint32_t",
3: "uint64_t",
4: "uint64_t",
+ 5: "uint64_t",
"short_name":"match_bmap"
},
of_match_t = { # Match object
@@ -78,6 +84,7 @@
2: "of_match_v2_t",
3: "of_match_v3_t",
4: "of_match_v3_t", # Currently uses same match as 1.2 (v3).
+ 5: "of_match_v3_t", # Currently uses same match as 1.2 (v3).
"short_name":"match"
},
)
@@ -105,6 +112,7 @@
of_checksum_128_t = (16, True),
of_app_code_t = (15,True),
of_sig_id_t = (6, True),
+ of_bitmap_512_t = (64, True),
)
def type_dec_to_count_base(m_type):
@@ -183,6 +191,8 @@
member_ir_class = existing_classes[base_class]
bytes = member_ir_class.base_length
length_fixed = member_ir_class.is_fixed_length
+ if member_ir_class.has_external_alignment:
+ bytes = (bytes + 7) & ~7
else:
if base_type in existing_enums:
enum = existing_enums[base_type]
diff --git a/loxi_ir/unified.py b/loxi_ir/unified.py
index 41b86dc..fa97c87 100644
--- a/loxi_ir/unified.py
+++ b/loxi_ir/unified.py
@@ -98,6 +98,9 @@
self.entries[e.name] = ir.OFEnumEntry(e.name, e.value, copy.copy(e.params))
else:
entry = self.entries[e.name]
+ if v_enum.params.get('stable') == 'True' and e.value != entry.value:
+ raise Exception("Error unifying stable ir enum {} - adding entry {} version {} value {} <-> {}".format(
+ self.name, e.name, version, entry.value, e.value))
for name, value in e.params.items():
if not name in entry.params:
entry.params[name] = value
diff --git a/openflow_input/bsn-1.3 b/openflow_input/bsn-1.3
index f9340b4..5ad480c 100644
--- a/openflow_input/bsn-1.3
+++ b/openflow_input/bsn-1.3
@@ -26,6 +26,7 @@
// under the EPL.
#version 4
+#version 5
// BSN extension instruction
struct of_instruction_bsn : of_instruction_experimenter {
diff --git a/openflow_input/bsn_acl b/openflow_input/bsn_acl
index 4035904..bcca842 100644
--- a/openflow_input/bsn_acl
+++ b/openflow_input/bsn_acl
@@ -30,6 +30,7 @@
// Copyright (c) 2011, 2012 Open Networking Foundation
#version 4
+#version 5
// Instructions to express control flow in ACL tables
diff --git a/openflow_input/bsn_arp_idle b/openflow_input/bsn_arp_idle
index 26cea92..16a1782 100644
--- a/openflow_input/bsn_arp_idle
+++ b/openflow_input/bsn_arp_idle
@@ -35,6 +35,7 @@
// not remove the table entry on its own.
#version 4
+#version 5
struct of_bsn_arp_idle : of_bsn_header {
uint8_t version;
diff --git a/openflow_input/bsn_arp_offload b/openflow_input/bsn_arp_offload
index 5a229b1..f13f6ac 100644
--- a/openflow_input/bsn_arp_offload
+++ b/openflow_input/bsn_arp_offload
@@ -30,6 +30,7 @@
// Copyright (c) 2011, 2012 Open Networking Foundation
#version 4
+#version 5
struct of_instruction_bsn_arp_offload : of_instruction_bsn {
uint16_t type == 65535;
diff --git a/openflow_input/bsn_auto_negotiation b/openflow_input/bsn_auto_negotiation
new file mode 100644
index 0000000..68116cf
--- /dev/null
+++ b/openflow_input/bsn_auto_negotiation
@@ -0,0 +1,41 @@
+// Copyright 2014, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+// the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may distribute libraries
+// generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+// that copyright and licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i) included in
+// the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+// documentation for the LoxiGen Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2014, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+// a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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
+// EPL for the specific language governing permissions and limitations
+// under the EPL.
+//
+// Also derived from the OpenFlow header files which have these copyrights:
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+
+#version 4
+#version 5
+
+struct of_instruction_bsn_auto_negotiation : of_instruction_bsn {
+ uint16_t type == 65535;
+ uint16_t len;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 11;
+ pad(4);
+};
diff --git a/openflow_input/bsn_aux_cxns b/openflow_input/bsn_aux_cxns
index 247f81b..8ceaa72 100644
--- a/openflow_input/bsn_aux_cxns
+++ b/openflow_input/bsn_aux_cxns
@@ -28,6 +28,8 @@
// Request that the switch spawn and configure auxiliary OF connections.
//
#version 4
+#version 5
+
// Set the number of desired aux connections num_aux=(0-16) accompanying this main connection
// This message is only allowed on the main connection.
struct of_bsn_set_aux_cxns_request : of_bsn_header {
diff --git a/openflow_input/bsn_controller_connections b/openflow_input/bsn_controller_connections
index eae315e..845d3b8 100644
--- a/openflow_input/bsn_controller_connections
+++ b/openflow_input/bsn_controller_connections
@@ -37,6 +37,7 @@
// The URIs are of the form tcp://1.2.3.4:6553
#version 4
+#version 5
enum ofp_bsn_controller_connection_state(wire_type=uint8_t) {
OFP_BSN_CONTROLLER_CONNECTION_STATE_DISCONNECTED = 0,
diff --git a/openflow_input/bsn_debug_counter b/openflow_input/bsn_debug_counter
index 75cafcc..6c28b87 100644
--- a/openflow_input/bsn_debug_counter
+++ b/openflow_input/bsn_debug_counter
@@ -29,6 +29,7 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
// Switches have many non-dataplane counters that are mainly useful for
// debugging. An example is the number of packet-ins dropped due to
diff --git a/openflow_input/bsn_dhcp_offload b/openflow_input/bsn_dhcp_offload
index b21b036..5352754 100644
--- a/openflow_input/bsn_dhcp_offload
+++ b/openflow_input/bsn_dhcp_offload
@@ -30,6 +30,7 @@
// Copyright (c) 2011, 2012 Open Networking Foundation
#version 4
+#version 5
struct of_instruction_bsn_dhcp_offload : of_instruction_bsn {
uint16_t type == 65535;
diff --git a/openflow_input/bsn_disable_src_mac_check b/openflow_input/bsn_disable_src_mac_check
index f75c237..6b095ca 100644
--- a/openflow_input/bsn_disable_src_mac_check
+++ b/openflow_input/bsn_disable_src_mac_check
@@ -30,6 +30,7 @@
// Copyright (c) 2011, 2012 Open Networking Foundation
#version 4
+#version 5
struct of_instruction_bsn_disable_src_mac_check : of_instruction_bsn {
uint16_t type == 65535;
diff --git a/openflow_input/bsn_disable_vlan_counters b/openflow_input/bsn_disable_vlan_counters
index 068db64..e586917 100644
--- a/openflow_input/bsn_disable_vlan_counters
+++ b/openflow_input/bsn_disable_vlan_counters
@@ -30,6 +30,7 @@
// Copyright (c) 2011, 2012 Open Networking Foundation
#version 4
+#version 5
struct of_instruction_bsn_disable_vlan_counters : of_instruction_bsn {
uint16_t type == 65535;
diff --git a/openflow_input/bsn_egr_port_group_id b/openflow_input/bsn_egr_port_group_id
index a237b49..3ba5462 100644
--- a/openflow_input/bsn_egr_port_group_id
+++ b/openflow_input/bsn_egr_port_group_id
@@ -30,6 +30,7 @@
#version 3
#version 4
+#version 5
/*
* Egress port group ID for SwitchLight
diff --git a/openflow_input/bsn_flow_checksum b/openflow_input/bsn_flow_checksum
index bfa5f3c..35b658f 100644
--- a/openflow_input/bsn_flow_checksum
+++ b/openflow_input/bsn_flow_checksum
@@ -29,6 +29,7 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
// Retrieves the checksum for every bucket in a table. The entries are ordered
// by bucket index.
diff --git a/openflow_input/bsn_flow_idle b/openflow_input/bsn_flow_idle
index 40a95d8..e0139e2 100644
--- a/openflow_input/bsn_flow_idle
+++ b/openflow_input/bsn_flow_idle
@@ -29,6 +29,7 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
/*
* Notification of idle flows
diff --git a/openflow_input/bsn_generic_stats b/openflow_input/bsn_generic_stats
new file mode 100644
index 0000000..b67d8e3
--- /dev/null
+++ b/openflow_input/bsn_generic_stats
@@ -0,0 +1,67 @@
+// Copyright 2013, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License,
+// version 1.0 (EPL), with the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may
+// distribute libraries generated by LoxiGen (LoxiGen Libraries)
+// under the terms of your choice, provided that copyright and
+// licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i)
+// included in the LoxiGen Libraries, if distributed in source code
+// form and (ii) included in any documentation for the LoxiGen
+// Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or
+// LOXI Exception. You may obtain a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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 EPL for the specific language
+// governing permissions and limitations under the EPL.
+
+#version 4
+#version 5
+
+// This extension provides flexibility for stats requests like gentable
+// does for table programming.
+
+struct of_bsn_generic_stats_request : of_bsn_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 0xffff;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 16;
+ of_str64_t name;
+ list(of_bsn_tlv_t) tlvs;
+};
+
+struct of_bsn_generic_stats_entry {
+ uint16_t length;
+ list(of_bsn_tlv_t) tlvs;
+};
+
+struct of_bsn_generic_stats_reply : of_bsn_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 0xffff;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 16;
+ list(of_bsn_generic_stats_entry_t) entries;
+};
diff --git a/openflow_input/bsn_gentable b/openflow_input/bsn_gentable
index 1344ef5..556ae0b 100644
--- a/openflow_input/bsn_gentable
+++ b/openflow_input/bsn_gentable
@@ -29,6 +29,7 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
// We have a number of switch agents that need to be configured by the
// controller and report stats. Some of them will have large tables (1000+
@@ -351,3 +352,13 @@
uint32_t subtype == 5;
list(of_bsn_gentable_bucket_stats_entry_t) entries;
};
+
+// Reference a gentable entry from an action list
+struct of_action_bsn_gentable : of_action_bsn {
+ uint16_t type == 65535;
+ uint16_t len;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 5;
+ uint32_t table_id;
+ list(of_bsn_tlv_t) key;
+};
diff --git a/openflow_input/bsn_image b/openflow_input/bsn_image
index 05a1a97..fafe8d8 100644
--- a/openflow_input/bsn_image
+++ b/openflow_input/bsn_image
@@ -29,6 +29,7 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
struct of_bsn_image_desc_stats_request : of_bsn_stats_request {
uint8_t version;
diff --git a/openflow_input/bsn_in_ports b/openflow_input/bsn_in_ports
index b23df63..bb4c030 100644
--- a/openflow_input/bsn_in_ports
+++ b/openflow_input/bsn_in_ports
@@ -30,6 +30,7 @@
#version 3
#version 4
+#version 5
/*
* Bitmap of input ports
@@ -59,3 +60,14 @@
of_bitmap_128_t value;
of_bitmap_128_t value_mask;
};
+
+struct of_oxm_bsn_in_ports_512 : of_oxm {
+ uint32_t type_len == 0x00032640;
+ of_bitmap_512_t value;
+};
+
+struct of_oxm_bsn_in_ports_512_masked : of_oxm {
+ uint32_t type_len == 0x00032780;
+ of_bitmap_512_t value;
+ of_bitmap_512_t value_mask;
+};
diff --git a/openflow_input/bsn_l2_cache_hit b/openflow_input/bsn_l2_cache_hit
new file mode 100644
index 0000000..694bc65
--- /dev/null
+++ b/openflow_input/bsn_l2_cache_hit
@@ -0,0 +1,47 @@
+// Copyright 2014, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License,
+// version 1.0 (EPL), with the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may
+// distribute libraries generated by LoxiGen (LoxiGen Libraries)
+// under the terms of your choice, provided that copyright and
+// licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i)
+// included in the LoxiGen Libraries, if distributed in source code
+// form and (ii) included in any documentation for the LoxiGen
+// Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or
+// LOXI Exception. You may obtain a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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 EPL for the specific language
+// governing permissions and limitations under the EPL.
+
+#version 3
+#version 4
+
+/*
+ * L2 Cache Hit
+ */
+
+struct of_oxm_bsn_l2_cache_hit : of_oxm {
+ uint32_t type_len == 0x00032401;
+ uint8_t value;
+};
+
+struct of_oxm_bsn_l2_cache_hit_masked : of_oxm {
+ uint32_t type_len == 0x00032502;
+ uint8_t value;
+ uint8_t value_mask;
+};
diff --git a/openflow_input/bsn_l3_interface_class_id b/openflow_input/bsn_l3_interface_class_id
index 80d1e37..f16d333 100644
--- a/openflow_input/bsn_l3_interface_class_id
+++ b/openflow_input/bsn_l3_interface_class_id
@@ -30,6 +30,7 @@
#version 3
#version 4
+#version 5
/*
* L3 interface class ID for SwitchLight
diff --git a/openflow_input/bsn_l3_src_class_id b/openflow_input/bsn_l3_src_class_id
index 58f60c6..7e2569e 100644
--- a/openflow_input/bsn_l3_src_class_id
+++ b/openflow_input/bsn_l3_src_class_id
@@ -30,6 +30,7 @@
#version 3
#version 4
+#version 5
/*
* L3 source class ID for SwitchLight
diff --git a/openflow_input/bsn_lacp b/openflow_input/bsn_lacp
index d2e540a..ed36b0d 100644
--- a/openflow_input/bsn_lacp
+++ b/openflow_input/bsn_lacp
@@ -29,9 +29,10 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
// LACP Convergence Status set in of_bsn_lacp_convergence_notif message
-enum of_bsn_lacp_convergence_status_t(wire_type=uint8_t, complete=False) {
+enum of_bsn_lacp_convergence_status(wire_type=uint8_t, complete=False) {
LACP_SUCCESS = 0,
LACP_TIMEDOUT = 1,
LACP_OUT_OF_SYNC = 2,
diff --git a/openflow_input/bsn_lag_id b/openflow_input/bsn_lag_id
index 63645a3..d428933 100644
--- a/openflow_input/bsn_lag_id
+++ b/openflow_input/bsn_lag_id
@@ -30,6 +30,7 @@
#version 3
#version 4
+#version 5
/*
* Ingress LAG ID for SwitchLight
diff --git a/openflow_input/bsn_log b/openflow_input/bsn_log
index b2a9758..e636d6e 100644
--- a/openflow_input/bsn_log
+++ b/openflow_input/bsn_log
@@ -29,6 +29,7 @@
// the receiver's configured loglevel is lower than the message's loglevel.
#version 4
+#version 5
enum ofp_bsn_loglevel(wire_type=uint8_t) {
OFP_BSN_LOGLEVEL_MSG = 0,
diff --git a/openflow_input/bsn_lua b/openflow_input/bsn_lua
new file mode 100644
index 0000000..d941666
--- /dev/null
+++ b/openflow_input/bsn_lua
@@ -0,0 +1,108 @@
+// Copyright 2015, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License,
+// version 1.0 (EPL), with the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may
+// distribute libraries generated by LoxiGen (LoxiGen Libraries)
+// under the terms of your choice, provided that copyright and
+// licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i)
+// included in the LoxiGen Libraries, if distributed in source code
+// form and (ii) included in any documentation for the LoxiGen
+// Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or
+// LOXI Exception. You may obtain a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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 EPL for the specific language
+// governing permissions and limitations under the EPL.
+
+// IVS supports running sandboxed Lua code as the forwarding pipeline.
+// This extension allows the controller to upload the Lua code, send
+// commands to it, and receive async notifications.
+//
+// Most of the data passed between the controller and the Lua code is
+// opaque to the rest of the switch. It's assumed that the controller
+// is tightly coupled to the Lua code it uploaded, so there's no need
+// to version the protocol between them.
+
+#version 4
+#version 5
+
+// Upload chunks of Lua code to the switch
+//
+// If the MORE flag is not set, the old VM will be cleaned up and
+// a new VM will be initialized with the uploaded code. Each chunk
+// of code is executed in the VM in the order it was received.
+//
+// If the FORCE flag is not set, the switch will check to see if the
+// old and new code is identical. If they are identical the message
+// will be ignored.
+//
+// As part of the VM cleanup, all gentables registered by Lua code
+// will be unregistered.
+//
+// Consecutive messages with the same filename are concatenated,
+// to support chunks larger than 64K.
+
+enum ofp_bsn_lua_upload_flags(wire_type=uint16_t, bitmask=True) {
+ OFP_BSN_LUA_UPLOAD_MORE = 0x1,
+ OFP_BSN_LUA_UPLOAD_FORCE = 0x2,
+};
+
+struct of_bsn_lua_upload : of_bsn_header {
+ uint8_t version;
+ uint8_t type == 4;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 64;
+ enum ofp_bsn_lua_upload_flags flags;
+ of_str64_t filename;
+ of_octets_t data;
+};
+
+// Send a command to Lua
+
+struct of_bsn_lua_command_request : of_bsn_header {
+ uint8_t version;
+ uint8_t type == 4;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 65;
+ of_octets_t data;
+};
+
+struct of_bsn_lua_command_reply : of_bsn_header {
+ uint8_t version;
+ uint8_t type == 4;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 66;
+ of_octets_t data;
+};
+
+// Async message from Lua to the controller
+
+struct of_bsn_lua_notification : of_bsn_header {
+ uint8_t version;
+ uint8_t type == 4;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 67;
+ of_octets_t data;
+};
diff --git a/openflow_input/bsn_packet_of_death b/openflow_input/bsn_packet_of_death
index e8679f0..c1ac28d 100644
--- a/openflow_input/bsn_packet_of_death
+++ b/openflow_input/bsn_packet_of_death
@@ -30,6 +30,7 @@
// Copyright (c) 2011, 2012 Open Networking Foundation
#version 4
+#version 5
struct of_instruction_bsn_packet_of_death : of_instruction_bsn {
uint16_t type == 65535;
diff --git a/openflow_input/bsn_pdu b/openflow_input/bsn_pdu
index 66465f3..007365b 100644
--- a/openflow_input/bsn_pdu
+++ b/openflow_input/bsn_pdu
@@ -32,7 +32,7 @@
// When the slot_num field has this value, the message applies
// to all currently used slots on the switch for the given port
-enum of_bsn_pdu_slot_num_t(wire_type=uint8_t, complete=False) {
+enum of_bsn_pdu_slot_num(wire_type=uint8_t, complete=False) {
BSN_PDU_SLOT_NUM_ANY = 0xff
};
diff --git a/openflow_input/bsn_pktin_flag b/openflow_input/bsn_pktin_flag
index fd94a49..b046024 100644
--- a/openflow_input/bsn_pktin_flag
+++ b/openflow_input/bsn_pktin_flag
@@ -26,6 +26,7 @@
// under the EPL.
#version 4
+#version 5
// In a realistic switch pipeline there are multiple reasons a given packet
// should be sent to the controller. The packet-in reason field is only 8 bits,
@@ -43,4 +44,6 @@
OFP_BSN_PKTIN_FLAG_L3_MISS = 0x100,
OFP_BSN_PKTIN_FLAG_L3_CPU = 0x200,
OFP_BSN_PKTIN_FLAG_INGRESS_ACL = 0x400,
+ OFP_BSN_PKTIN_FLAG_SFLOW = 0x800,
+ OFP_BSN_PKTIN_FLAG_ARP_CACHE = 0x1000,
};
diff --git a/openflow_input/bsn_port_counter b/openflow_input/bsn_port_counter
index 73ba80e..6cf5e10 100644
--- a/openflow_input/bsn_port_counter
+++ b/openflow_input/bsn_port_counter
@@ -29,8 +29,9 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
-enum ofp_bsn_port_counter(wire_type=uint8_t, complete=False) {
+enum ofp_bsn_port_counter(wire_type=uint8_t, complete=False, stable=True) {
OFP_BSN_PORT_COUNTER_RX_BYTES = 0,
OFP_BSN_PORT_COUNTER_RX_PACKETS_UNICAST = 1,
OFP_BSN_PORT_COUNTER_RX_PACKETS_BROADCAST = 2,
diff --git a/openflow_input/bsn_prioritize_pdus b/openflow_input/bsn_prioritize_pdus
index fbec0a0..7a179a9 100644
--- a/openflow_input/bsn_prioritize_pdus
+++ b/openflow_input/bsn_prioritize_pdus
@@ -30,6 +30,7 @@
// Copyright (c) 2011, 2012 Open Networking Foundation
#version 4
+#version 5
struct of_instruction_bsn_prioritize_pdus : of_instruction_bsn {
uint16_t type == 65535;
diff --git a/openflow_input/bsn_require_vlan_xlate b/openflow_input/bsn_require_vlan_xlate
index 24cf137..32fc55c 100644
--- a/openflow_input/bsn_require_vlan_xlate
+++ b/openflow_input/bsn_require_vlan_xlate
@@ -30,6 +30,7 @@
// Copyright (c) 2011, 2012 Open Networking Foundation
#version 4
+#version 5
struct of_instruction_bsn_require_vlan_xlate : of_instruction_bsn {
uint16_t type == 65535;
diff --git a/openflow_input/bsn_span_destination b/openflow_input/bsn_span_destination
new file mode 100644
index 0000000..fd4f677
--- /dev/null
+++ b/openflow_input/bsn_span_destination
@@ -0,0 +1,41 @@
+// Copyright 2014, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+// the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may distribute libraries
+// generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+// that copyright and licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i) included in
+// the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+// documentation for the LoxiGen Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2014, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+// a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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
+// EPL for the specific language governing permissions and limitations
+// under the EPL.
+//
+// Also derived from the OpenFlow header files which have these copyrights:
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+
+#version 4
+#version 5
+
+struct of_instruction_bsn_span_destination : of_instruction_bsn {
+ uint16_t type == 65535;
+ uint16_t len;
+ uint32_t experimenter == 0x5c16c7;
+ uint32_t subtype == 10;
+ pad(4);
+};
diff --git a/openflow_input/bsn_switch_pipeline b/openflow_input/bsn_switch_pipeline
index ff2213f..d42532b 100644
--- a/openflow_input/bsn_switch_pipeline
+++ b/openflow_input/bsn_switch_pipeline
@@ -29,6 +29,7 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
struct of_bsn_get_switch_pipeline_request : of_bsn_header {
uint8_t version;
diff --git a/openflow_input/bsn_tcp_flags b/openflow_input/bsn_tcp_flags
index e8ef2e9..1a84a90 100644
--- a/openflow_input/bsn_tcp_flags
+++ b/openflow_input/bsn_tcp_flags
@@ -30,6 +30,7 @@
#version 3
#version 4
+#version 5
/*
* TCP flags
diff --git a/openflow_input/bsn_time b/openflow_input/bsn_time
index 0a955be..d69e538 100644
--- a/openflow_input/bsn_time
+++ b/openflow_input/bsn_time
@@ -33,6 +33,7 @@
// The timestamp must be monotonic (not affected by system time updates).
#version 4
+#version 5
struct of_bsn_time_request : of_bsn_header {
uint8_t version;
diff --git a/openflow_input/bsn_tlv b/openflow_input/bsn_tlv
index 4113759..7e9b376 100644
--- a/openflow_input/bsn_tlv
+++ b/openflow_input/bsn_tlv
@@ -29,6 +29,7 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
struct of_bsn_tlv_port : of_bsn_tlv {
uint16_t type == 0;
@@ -172,3 +173,304 @@
uint16_t length;
uint8_t value;
};
+
+struct of_bsn_tlv_external_ip : of_bsn_tlv {
+ uint16_t type == 23;
+ uint16_t length;
+ of_ipv4_t value;
+};
+
+struct of_bsn_tlv_external_mac : of_bsn_tlv {
+ uint16_t type == 24;
+ uint16_t length;
+ of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_external_netmask : of_bsn_tlv {
+ uint16_t type == 25;
+ uint16_t length;
+ of_ipv4_t value;
+};
+
+struct of_bsn_tlv_external_gateway_ip : of_bsn_tlv {
+ uint16_t type == 26;
+ uint16_t length;
+ of_ipv4_t value;
+};
+
+struct of_bsn_tlv_internal_mac : of_bsn_tlv {
+ uint16_t type == 27;
+ uint16_t length;
+ of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_internal_gateway_mac : of_bsn_tlv {
+ uint16_t type == 28;
+ uint16_t length;
+ of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_external_gateway_mac : of_bsn_tlv {
+ uint16_t type == 29;
+ uint16_t length;
+ of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_sampling_rate : of_bsn_tlv {
+ uint16_t type == 30;
+ uint16_t length;
+ uint32_t value;
+};
+
+struct of_bsn_tlv_header_size : of_bsn_tlv {
+ uint16_t type == 31;
+ uint16_t length;
+ uint32_t value; /* bytes */
+};
+
+struct of_bsn_tlv_eth_src : of_bsn_tlv {
+ uint16_t type == 32;
+ uint16_t length;
+ of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_eth_dst : of_bsn_tlv {
+ uint16_t type == 33;
+ uint16_t length;
+ of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_ipv4_src : of_bsn_tlv {
+ uint16_t type == 34;
+ uint16_t length;
+ of_ipv4_t value;
+};
+
+struct of_bsn_tlv_ipv4_dst : of_bsn_tlv {
+ uint16_t type == 35;
+ uint16_t length;
+ of_ipv4_t value;
+};
+
+struct of_bsn_tlv_udp_src : of_bsn_tlv {
+ uint16_t type == 36;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_udp_dst : of_bsn_tlv {
+ uint16_t type == 37;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_sub_agent_id : of_bsn_tlv {
+ uint16_t type == 38;
+ uint16_t length;
+ uint32_t value;
+};
+
+struct of_bsn_tlv_tx_bytes : of_bsn_tlv {
+ uint16_t type == 39;
+ uint16_t length;
+ uint64_t value;
+};
+
+struct of_bsn_tlv_actor_system_priority: of_bsn_tlv {
+ uint16_t type == 40;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_actor_system_mac: of_bsn_tlv {
+ uint16_t type == 41;
+ uint16_t length;
+ of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_actor_port_priority: of_bsn_tlv {
+ uint16_t type == 42;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_actor_port_num: of_bsn_tlv {
+ uint16_t type == 43;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_actor_key: of_bsn_tlv {
+ uint16_t type == 44;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_convergence_status: of_bsn_tlv {
+ uint16_t type == 45;
+ uint16_t length;
+ uint8_t value;
+};
+
+struct of_bsn_tlv_partner_system_priority: of_bsn_tlv {
+ uint16_t type == 47;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_partner_system_mac: of_bsn_tlv {
+ uint16_t type == 48;
+ uint16_t length;
+ of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_partner_port_priority: of_bsn_tlv {
+ uint16_t type == 49;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_partner_port_num: of_bsn_tlv {
+ uint16_t type == 50;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_partner_key: of_bsn_tlv {
+ uint16_t type == 51;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_name : of_bsn_tlv {
+ uint16_t type == 52;
+ uint16_t length;
+ of_octets_t value; /* UTF-8 encoded. Not null terminated. */
+};
+
+enum ofp_bsn_lacp_state(wire_type=uint8_t, bitmask=True) {
+ OFP_BSN_LACP_STATE_ACTIVITY = 0x01,
+ OFP_BSN_LACP_STATE_TIMEOUT = 0x02,
+ OFP_BSN_LACP_STATE_AGGREGATION = 0x04,
+ OFP_BSN_LACP_STATE_SYNCHRONIZATION = 0x08,
+ OFP_BSN_LACP_STATE_COLLECTING = 0x10,
+ OFP_BSN_LACP_STATE_DISTRIBUTING = 0x20,
+ OFP_BSN_LACP_STATE_DEFAULTED = 0x40,
+ OFP_BSN_LACP_STATE_EXPIRED = 0x80,
+};
+
+struct of_bsn_tlv_actor_state: of_bsn_tlv {
+ uint16_t type == 53;
+ uint16_t length;
+ enum ofp_bsn_lacp_state value;
+};
+
+struct of_bsn_tlv_partner_state: of_bsn_tlv {
+ uint16_t type == 54;
+ uint16_t length;
+ enum ofp_bsn_lacp_state value;
+};
+
+struct of_bsn_tlv_data : of_bsn_tlv {
+ uint16_t type == 55;
+ uint16_t length;
+ of_octets_t value;
+};
+
+struct of_bsn_tlv_mac_mask : of_bsn_tlv {
+ uint16_t type == 56;
+ uint16_t length;
+ of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_priority : of_bsn_tlv {
+ uint16_t type == 57;
+ uint16_t length;
+ uint32_t value;
+};
+
+struct of_bsn_tlv_interval : of_bsn_tlv {
+ uint16_t type == 58;
+ uint16_t length;
+ uint32_t value; /* Milliseconds */
+};
+
+/* A reference to an entry in another gentable */
+struct of_bsn_tlv_reference : of_bsn_tlv {
+ uint16_t type == 59;
+ uint16_t length;
+ uint16_t table_id;
+ list(of_bsn_tlv_t) key;
+};
+
+struct of_bsn_tlv_ipv4_netmask : of_bsn_tlv {
+ uint16_t type == 60;
+ uint16_t length;
+ of_ipv4_t value;
+};
+
+struct of_bsn_tlv_mpls_label : of_bsn_tlv {
+ uint16_t type == 61;
+ uint16_t length;
+ uint32_t value;
+};
+
+struct of_bsn_tlv_mpls_control_word : of_bsn_tlv {
+ uint16_t type == 62;
+ uint16_t length;
+ uint8_t value;
+};
+
+struct of_bsn_tlv_mpls_sequenced : of_bsn_tlv {
+ uint16_t type == 63;
+ uint16_t length;
+ uint8_t value;
+};
+
+struct of_bsn_tlv_bucket : of_bsn_tlv {
+ uint16_t type == 64;
+ uint16_t length;
+ list(of_bsn_tlv_t) value;
+};
+
+struct of_bsn_tlv_tcp_src : of_bsn_tlv {
+ uint16_t type == 65;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_tcp_dst : of_bsn_tlv {
+ uint16_t type == 66;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_ip_proto : of_bsn_tlv {
+ uint16_t type == 67;
+ uint16_t length;
+ uint8_t value;
+};
+
+struct of_bsn_tlv_icmp_type : of_bsn_tlv {
+ uint16_t type == 68;
+ uint16_t length;
+ uint8_t value;
+};
+
+struct of_bsn_tlv_icmp_code : of_bsn_tlv {
+ uint16_t type == 69;
+ uint16_t length;
+ uint8_t value;
+};
+
+struct of_bsn_tlv_icmp_id : of_bsn_tlv {
+ uint16_t type == 70;
+ uint16_t length;
+ uint16_t value;
+};
+
+struct of_bsn_tlv_rx_bytes : of_bsn_tlv {
+ uint16_t type == 71;
+ uint16_t length;
+ uint64_t value;
+};
diff --git a/openflow_input/bsn_udf b/openflow_input/bsn_udf
index f7ce9a6..12ad1cb 100644
--- a/openflow_input/bsn_udf
+++ b/openflow_input/bsn_udf
@@ -30,6 +30,7 @@
#version 3
#version 4
+#version 5
/*
* User Defined Fields
diff --git a/openflow_input/bsn_vlan_counter b/openflow_input/bsn_vlan_counter
index 5d90724..d39d35f 100644
--- a/openflow_input/bsn_vlan_counter
+++ b/openflow_input/bsn_vlan_counter
@@ -29,12 +29,13 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
enum ofp_bsn_vlan_counter_constants {
OFP_BSN_VLAN_ALL = 0xffff,
};
-enum of_bsn_vlan_counter_t(wire_type=uint8_t, complete=False) {
+enum of_bsn_vlan_counter(wire_type=uint8_t, complete=False, stable=True) {
OFP_BSN_VLAN_COUNTER_RX_BYTES = 0,
OFP_BSN_VLAN_COUNTER_RX_PACKETS = 1,
OFP_BSN_VLAN_COUNTER_TX_BYTES = 2,
diff --git a/openflow_input/bsn_vlan_xlate_port_group_id b/openflow_input/bsn_vlan_xlate_port_group_id
index c8e5a25..986dc0e 100644
--- a/openflow_input/bsn_vlan_xlate_port_group_id
+++ b/openflow_input/bsn_vlan_xlate_port_group_id
@@ -30,6 +30,7 @@
#version 3
#version 4
+#version 5
/*
* VLAN xlate port group ID for SwitchLight
diff --git a/openflow_input/bsn_vrf b/openflow_input/bsn_vrf
index 26959bd..c61c313 100644
--- a/openflow_input/bsn_vrf
+++ b/openflow_input/bsn_vrf
@@ -30,6 +30,7 @@
#version 3
#version 4
+#version 5
/*
* Virtual Routing/Forwarding ID for SwitchLight
diff --git a/openflow_input/bsn_vrf_counter b/openflow_input/bsn_vrf_counter
index 7676e69..012d728 100644
--- a/openflow_input/bsn_vrf_counter
+++ b/openflow_input/bsn_vrf_counter
@@ -29,12 +29,13 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
enum ofp_bsn_vrf_counter_constants(wire_type=uint32_t) {
OFP_BSN_VRF_ALL = 0xffffffff,
};
-enum of_bsn_vrf_counter_t(wire_type=uint8_t, complete=False) {
+enum of_bsn_vrf_counter(wire_type=uint8_t, complete=False, stable=True) {
OFP_BSN_VRF_COUNTER_BYTES = 0,
OFP_BSN_VRF_COUNTER_PACKETS = 1,
};
diff --git a/openflow_input/oxm-1.2 b/openflow_input/oxm-1.2
index 5006cff..dd596bd 100644
--- a/openflow_input/oxm-1.2
+++ b/openflow_input/oxm-1.2
@@ -31,6 +31,7 @@
#version 3
#version 4
+#version 5
struct of_oxm {
uint32_t type_len == ?;
diff --git a/openflow_input/oxm-1.3 b/openflow_input/oxm-1.3
index 2dbab42..4bb55a1 100644
--- a/openflow_input/oxm-1.3
+++ b/openflow_input/oxm-1.3
@@ -29,6 +29,7 @@
// governing permissions and limitations under the EPL.
#version 4
+#version 5
struct of_oxm_tunnel_id : of_oxm {
uint32_t type_len == 0x80004c08;
@@ -40,3 +41,27 @@
uint64_t value;
uint64_t value_mask;
};
+
+struct of_oxm_mpls_bos : of_oxm {
+ uint32_t type_len == 0x80004801;
+ uint8_t value;
+};
+
+struct of_oxm_mpls_bos_masked : of_oxm {
+ uint32_t type_len == 0x80004902;
+ uint8_t value;
+ uint8_t value_mask;
+};
+
+/* Not supporting pbb_isid at the moment, requires a 3-byte field */
+
+struct of_oxm_ipv6_exthdr : of_oxm {
+ uint32_t type_len == 0x80004e02;
+ uint16_t value;
+};
+
+struct of_oxm_ipv6_exthdr_masked : of_oxm {
+ uint32_t type_len == 0x80004f04;
+ uint16_t value;
+ uint16_t value_mask;
+};
diff --git a/openflow_input/oxm-1.4 b/openflow_input/oxm-1.4
new file mode 100644
index 0000000..0fd96ec
--- /dev/null
+++ b/openflow_input/oxm-1.4
@@ -0,0 +1,42 @@
+// Copyright 2014, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License,
+// version 1.0 (EPL), with the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may
+// distribute libraries generated by LoxiGen (LoxiGen Libraries)
+// under the terms of your choice, provided that copyright and
+// licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i)
+// included in the LoxiGen Libraries, if distributed in source code
+// form and (ii) included in any documentation for the LoxiGen
+// Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or
+// LOXI Exception. You may obtain a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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 EPL for the specific language
+// governing permissions and limitations under the EPL.
+
+#version 5
+
+struct of_oxm_pbb_uca : of_oxm {
+ uint32_t type_len == 0x80005201;
+ uint8_t value;
+};
+
+struct of_oxm_pbb_uca_masked : of_oxm {
+ uint32_t type_len == 0x80005302;
+ uint8_t value;
+ uint8_t value_mask;
+};
diff --git a/openflow_input/oxm_nicira_tun b/openflow_input/oxm_nicira_tun
new file mode 100644
index 0000000..408f63e
--- /dev/null
+++ b/openflow_input/oxm_nicira_tun
@@ -0,0 +1,54 @@
+// Copyright 2013, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+// the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may distribute libraries
+// generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+// that copyright and licensing notices generated by LoxiGen are not altered or removd
+// from the LoxiGen Libraries and the notice provided below is (i) included in
+// the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+// documentation for the LoxiGen Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by t"
+//
+// You may not use this file except in compliance with the EPL or LOXI Exception. Youn
+// a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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
+// EPL for the specific language governing permissions and limitations
+// under the EPL.
+
+#version 3
+#version 4
+#version 5
+
+// Nicira extension for tun_ipv4_src (31)
+struct of_oxm_tunnel_ipv4_src : of_oxm {
+ uint32_t type_len == 0x00013e04;
+ of_ipv4_t value;
+};
+
+struct of_oxm_tunnel_ipv4_src_masked : of_oxm {
+ uint32_t type_len == 0x00013f08;
+ of_ipv4_t value;
+ of_ipv4_t value_mask;
+};
+
+// Nicira extension for tun_ipv4_dst (32)
+struct of_oxm_tunnel_ipv4_dst : of_oxm {
+ uint32_t type_len == 0x00014004;
+ of_ipv4_t value;
+};
+
+struct of_oxm_tunnel_ipv4_dst_masked : of_oxm {
+ uint32_t type_len == 0x00014108;
+ of_ipv4_t value;
+ of_ipv4_t value_mask;
+};
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index 64a465d..fa1a967 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -160,6 +160,7 @@
OFPPF_AUTONEG = 0x2000,
OFPPF_PAUSE = 0x4000,
OFPPF_PAUSE_ASYM = 0x8000,
+ OFPPF_BSN_BREAKOUT_CAPABLE = 0x80000000,
};
enum ofp_port_reason(wire_type=uint8_t) {
@@ -1700,7 +1701,7 @@
struct of_table_feature_prop_experimenter : of_table_feature_prop {
uint16_t type == 65534;
uint16_t length;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
uint32_t subtype;
of_octets_t experimenter_data;
};
@@ -1708,7 +1709,7 @@
struct of_table_feature_prop_experimenter_miss : of_table_feature_prop {
uint16_t type == 65535;
uint16_t length;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
uint32_t subtype;
of_octets_t experimenter_data;
};
diff --git a/openflow_input/standard-1.4 b/openflow_input/standard-1.4
new file mode 100644
index 0000000..edcc781
--- /dev/null
+++ b/openflow_input/standard-1.4
@@ -0,0 +1,2675 @@
+// Copyright 2013, Big Switch Networks, Inc.
+//
+// LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+// the following special exception:
+//
+// LOXI Exception
+//
+// As a special exception to the terms of the EPL, you may distribute libraries
+// generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+// that copyright and licensing notices generated by LoxiGen are not altered or removed
+// from the LoxiGen Libraries and the notice provided below is (i) included in
+// the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+// documentation for the LoxiGen Libraries, if distributed in binary form.
+//
+// Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//
+// You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+// a copy of the EPL at:
+//
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// 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
+// EPL for the specific language governing permissions and limitations
+// under the EPL.
+//
+// Also derived from the OpenFlow header files which have these copyrights:
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+
+#version 5
+
+enum macro_definitions {
+ OFP_MAX_TABLE_NAME_LEN = 32,
+ OFP_MAX_PORT_NAME_LEN = 16,
+
+ OFP_TCP_PORT = 6653,
+ OFP_SSL_PORT = 6653,
+
+ OFP_ETH_ALEN = 6,
+
+ OFP_DEFAULT_MISS_SEND_LEN = 128,
+
+ OFP_VLAN_NONE = 0,
+
+ OFP_FLOW_PERMANENT = 0,
+
+ OFP_DEFAULT_PRIORITY = 0x8000,
+
+ OFP_NO_BUFFER = 0xffffffff,
+
+ DESC_STR_LEN = 256,
+ SERIAL_NUM_LEN = 32,
+
+ OFPQ_ALL = 0xffffffff,
+ OFPQ_MAX_RATE_UNCFG = 0xffff,
+ OFPQ_MIN_RATE_UNCFG = 0xffff,
+};
+
+enum ofp_port(wire_type=uint32_t) {
+ OFPP_MAX = 0xffffff00,
+ OFPP_IN_PORT = 0xfffffff8,
+ OFPP_TABLE = 0xfffffff9,
+ OFPP_NORMAL = 0xfffffffa,
+ OFPP_FLOOD = 0xfffffffb,
+ OFPP_ALL = 0xfffffffc,
+ OFPP_CONTROLLER = 0xfffffffd,
+ OFPP_LOCAL = 0xfffffffe,
+ OFPP_ANY = 0xffffffff,
+};
+
+enum ofp_type(wire_type=uint8_t) {
+ OFPT_HELLO = 0,
+ OFPT_ERROR = 1,
+ OFPT_ECHO_REQUEST = 2,
+ OFPT_ECHO_REPLY = 3,
+ OFPT_EXPERIMENTER = 4,
+ OFPT_FEATURES_REQUEST = 5,
+ OFPT_FEATURES_REPLY = 6,
+ OFPT_GET_CONFIG_REQUEST = 7,
+ OFPT_GET_CONFIG_REPLY = 8,
+ OFPT_SET_CONFIG = 9,
+ OFPT_PACKET_IN = 10,
+ OFPT_FLOW_REMOVED = 11,
+ OFPT_PORT_STATUS = 12,
+ OFPT_PACKET_OUT = 13,
+ OFPT_FLOW_MOD = 14,
+ OFPT_GROUP_MOD = 15,
+ OFPT_PORT_MOD = 16,
+ OFPT_TABLE_MOD = 17,
+ OFPT_STATS_REQUEST = 18,
+ OFPT_STATS_REPLY = 19,
+ OFPT_BARRIER_REQUEST = 20,
+ OFPT_BARRIER_REPLY = 21,
+ OFPT_ROLE_REQUEST = 24,
+ OFPT_ROLE_REPLY = 25,
+ OFPT_GET_ASYNC_REQUEST = 26,
+ OFPT_GET_ASYNC_REPLY = 27,
+ OFPT_SET_ASYNC = 28,
+ OFPT_METER_MOD = 29,
+ OFPT_ROLE_STATUS = 30,
+ OFPT_TABLE_STATUS = 31,
+ OFPT_REQUESTFORWARD = 32,
+ OFPT_BUNDLE_CONTROL = 33,
+ OFPT_BUNDLE_ADD_MESSAGE = 34,
+};
+
+enum ofp_config_flags(wire_type=uint16_t, bitmask=True) {
+ OFPC_FRAG_NORMAL = 0,
+ OFPC_FRAG_DROP = 1,
+ OFPC_FRAG_REASM = 2,
+ OFPC_FRAG_MASK = 3,
+};
+
+enum ofp_table_config(wire_type=uint32_t, bitmask=True) {
+ OFPTC_DEPRECATED_MASK = 0x3,
+ OFPTC_EVICTION = 0x4,
+ OFPTC_VACANCY_EVENTS = 0x8,
+};
+
+enum ofp_table(wire_type=uint8_t, complete=False) {
+ OFPTT_MAX = 0xfe,
+ OFPTT_ALL = 0xff,
+};
+
+enum ofp_capabilities(wire_type=uint32_t, bitmask=True) {
+ OFPC_FLOW_STATS = 0x1,
+ OFPC_TABLE_STATS = 0x2,
+ OFPC_PORT_STATS = 0x4,
+ OFPC_GROUP_STATS = 0x8,
+ OFPC_IP_REASM = 0x20,
+ OFPC_QUEUE_STATS = 0x40,
+ OFPC_PORT_BLOCKED = 0x100,
+};
+
+enum ofp_port_config(wire_type=uint32_t, bitmask=True) {
+ OFPPC_PORT_DOWN = 0x1,
+ OFPPC_NO_RECV = 0x4,
+ OFPPC_NO_FWD = 0x20,
+ OFPPC_NO_PACKET_IN = 0x40,
+ OFPPC_BSN_MIRROR_DEST = 0x80000000,
+};
+
+enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
+ OFPPS_LINK_DOWN = 0x1,
+ OFPPS_BLOCKED = 0x2,
+ OFPPS_LIVE = 0x4,
+};
+
+enum ofp_port_features(wire_type=uint32_t, bitmask=True) {
+ OFPPF_10MB_HD = 0x1,
+ OFPPF_10MB_FD = 0x2,
+ OFPPF_100MB_HD = 0x4,
+ OFPPF_100MB_FD = 0x8,
+ OFPPF_1GB_HD = 0x10,
+ OFPPF_1GB_FD = 0x20,
+ OFPPF_10GB_FD = 0x40,
+ OFPPF_40GB_FD = 0x80,
+ OFPPF_100GB_FD = 0x100,
+ OFPPF_1TB_FD = 0x200,
+ OFPPF_OTHER = 0x400,
+ OFPPF_COPPER = 0x800,
+ OFPPF_FIBER = 0x1000,
+ OFPPF_AUTONEG = 0x2000,
+ OFPPF_PAUSE = 0x4000,
+ OFPPF_PAUSE_ASYM = 0x8000,
+ OFPPF_BSN_BREAKOUT_CAPABLE = 0x80000000,
+};
+
+enum ofp_port_reason(wire_type=uint8_t) {
+ OFPPR_ADD = 0,
+ OFPPR_DELETE = 1,
+ OFPPR_MODIFY = 2,
+};
+
+enum ofp_match_type(wire_type=uint16_t) {
+ OFPMT_STANDARD = 0,
+ OFPMT_OXM = 1,
+};
+
+enum ofp_oxm_class(wire_type=uint16_t) {
+ OFPXMC_NXM_0 = 0,
+ OFPXMC_NXM_1 = 1,
+ OFPXMC_OPENFLOW_BASIC = 0x8000,
+ OFPXMC_EXPERIMENTER = 0xffff,
+};
+
+enum ofp_vlan_id(wire_type=uint16_t) {
+ OFPVID_NONE = 0,
+ OFPVID_PRESENT = 0x1000,
+};
+
+// FIXME: OF spec specified this as '9' bits, implicitly adding
+// to full byte
+enum ofp_ipv6exthdr_flags(wire_type=uint16_t, bitmask=True) {
+ OFPIEH_NONEXT = 0x1,
+ OFPIEH_ESP = 0x2,
+ OFPIEH_AUTH = 0x4,
+ OFPIEH_DEST = 0x8,
+ OFPIEH_FRAG = 0x10,
+ OFPIEH_ROUTER = 0x20,
+ OFPIEH_HOP = 0x40,
+ OFPIEH_UNREP = 0x80,
+ OFPIEH_UNSEQ = 0x100,
+};
+
+enum ofp_action_type(wire_type=uint16_t) {
+ OFPAT_OUTPUT = 0,
+ OFPAT_COPY_TTL_OUT = 0xb,
+ OFPAT_COPY_TTL_IN = 0xc,
+ OFPAT_SET_MPLS_TTL = 0xf,
+ OFPAT_DEC_MPLS_TTL = 0x10,
+ OFPAT_PUSH_VLAN = 0x11,
+ OFPAT_POP_VLAN = 0x12,
+ OFPAT_PUSH_MPLS = 0x13,
+ OFPAT_POP_MPLS = 0x14,
+ OFPAT_SET_QUEUE = 0x15,
+ OFPAT_GROUP = 0x16,
+ OFPAT_SET_NW_TTL = 0x17,
+ OFPAT_DEC_NW_TTL = 0x18,
+ OFPAT_SET_FIELD = 0x19,
+ OFPAT_PUSH_PBB = 0x1a,
+ OFPAT_POP_PBB = 0x1b,
+ OFPAT_EXPERIMENTER = 0xffff,
+};
+
+enum ofp_controller_max_len(wire_type=uint16_t, complete=False) {
+ OFPCML_MAX = 0xffe5,
+ OFPCML_NO_BUFFER = 0xffff,
+};
+
+enum ofp_instruction_type(wire_type=uint16_t, bitmask=True) {
+ OFPIT_GOTO_TABLE = 0x1,
+ OFPIT_WRITE_METADATA = 0x2,
+ OFPIT_WRITE_ACTIONS = 0x3,
+ OFPIT_APPLY_ACTIONS = 0x4,
+ OFPIT_CLEAR_ACTIONS = 0x5,
+ OFPIT_METER = 0x6,
+ OFPIT_EXPERIMENTER = 0xffff,
+};
+
+enum ofp_flow_mod_command(wire_type=uint8_t) {
+ OFPFC_ADD = 0,
+ OFPFC_MODIFY = 1,
+ OFPFC_MODIFY_STRICT = 2,
+ OFPFC_DELETE = 3,
+ OFPFC_DELETE_STRICT = 4,
+};
+
+enum ofp_flow_mod_flags(wire_type=uint16_t, bitmask=True) {
+ OFPFF_SEND_FLOW_REM = 0x1,
+ OFPFF_CHECK_OVERLAP = 0x2,
+ OFPFF_RESET_COUNTS = 0x4,
+ OFPFF_NO_PKT_COUNTS = 0x8,
+ OFPFF_NO_BYT_COUNTS = 0x10,
+
+ /* Non-standard, enabled by an experimenter message */
+ /* See the bsn_flow_idle input file */
+ OFPFF_BSN_SEND_IDLE = 0x80,
+};
+
+enum ofp_group(wire_type=uint32_t, complete=False) {
+ OFPG_MAX = 0xffffff00,
+ OFPG_ALL = 0xfffffffc,
+ OFPG_ANY = 0xffffffff,
+};
+
+enum ofp_group_mod_command(wire_type=uint16_t) {
+ OFPGC_ADD = 0,
+ OFPGC_MODIFY = 1,
+ OFPGC_DELETE = 2,
+};
+
+enum ofp_group_type(wire_type=uint8_t) {
+ OFPGT_ALL = 0,
+ OFPGT_SELECT = 1,
+ OFPGT_INDIRECT = 2,
+ OFPGT_FF = 3,
+};
+
+enum ofp_packet_in_reason(wire_type=uint8_t) {
+ OFPR_NO_MATCH = 0,
+ OFPR_ACTION = 1,
+ OFPR_INVALID_TTL = 2,
+ OFPR_ACTION_SET = 3,
+ OFPR_GROUP = 4,
+ OFPR_PACKET_OUT = 5,
+
+ // non-standard BSN extensions. OF does not have a standard-conformant
+ // way to extend the set of packet_in reasons
+ OFPR_BSN_NEW_HOST = 128,
+ OFPR_BSN_STATION_MOVE = 129,
+ OFPR_BSN_BAD_VLAN = 130,
+ OFPR_BSN_DESTINATION_LOOKUP_FAILURE = 131,
+ OFPR_BSN_NO_ROUTE = 132,
+ OFPR_BSN_ICMP_ECHO_REQUEST = 133,
+ OFPR_BSN_DEST_NETWORK_UNREACHABLE = 134,
+ OFPR_BSN_DEST_HOST_UNREACHABLE = 135,
+ OFPR_BSN_DEST_PORT_UNREACHABLE = 136,
+ OFPR_BSN_FRAGMENTATION_REQUIRED = 137,
+ OFPR_BSN_ARP = 139,
+ OFPR_BSN_DHCP = 140,
+ OFPR_BSN_DEBUG = 141,
+ OFPR_BSN_PACKET_OF_DEATH = 142,
+};
+
+enum ofp_flow_removed_reason(wire_type=uint8_t) {
+ OFPRR_IDLE_TIMEOUT = 0,
+ OFPRR_HARD_TIMEOUT = 1,
+ OFPRR_DELETE = 2,
+ OFPRR_GROUP_DELETE = 3,
+ OFPRR_METER_DELETE = 4,
+ OFPRR_EVICTION = 5,
+};
+
+enum ofp_meter(wire_type=uint32_t, complete=False) {
+ OFPM_MAX = 0xffff0000,
+ OFPM_SLOWPATH = 0xfffffffd,
+ OFPM_CONTROLLER = 0xfffffffe,
+ OFPM_ALL = 0xffffffff,
+};
+
+enum ofp_meter_band_type(wire_type=uint16_t) {
+ OFPMBT_DROP = 0x1,
+ OFPMBT_DSCP_REMARK = 0x2,
+ OFPMBT_EXPERIMENTER = 0xffff,
+};
+
+enum ofp_meter_mod_command(wire_type=uint16_t) {
+ OFPMC_ADD = 0,
+ OFPMC_MODIFY = 1,
+ OFPMC_DELETE = 2,
+};
+
+enum ofp_meter_flags(wire_type=uint16_t, bitmask=True) {
+ OFPMF_KBPS = 0x1,
+ OFPMF_PKTPS = 0x2,
+ OFPMF_BURST = 0x4,
+ OFPMF_STATS = 0x8,
+};
+
+enum ofp_error_type(wire_type=uint16_t) {
+ OFPET_HELLO_FAILED = 0,
+ OFPET_BAD_REQUEST = 1,
+ OFPET_BAD_ACTION = 2,
+ OFPET_BAD_INSTRUCTION = 3,
+ OFPET_BAD_MATCH = 4,
+ OFPET_FLOW_MOD_FAILED = 5,
+ OFPET_GROUP_MOD_FAILED = 6,
+ OFPET_PORT_MOD_FAILED = 7,
+ OFPET_TABLE_MOD_FAILED = 8,
+ OFPET_QUEUE_OP_FAILED = 9,
+ OFPET_SWITCH_CONFIG_FAILED = 10,
+ OFPET_ROLE_REQUEST_FAILED = 11,
+ OFPET_METER_MOD_FAILED = 12,
+ OFPET_TABLE_FEATURES_FAILED = 13,
+ OFPET_BAD_PROPERTY = 14,
+ OFPET_ASYNC_CONFIG_FAILED = 15,
+ OFPET_FLOW_MONITOR_FAILED = 16,
+ OFPET_BUNDLE_FAILED = 17,
+ OFPET_EXPERIMENTER = 0xffff,
+};
+
+enum ofp_hello_failed_code(wire_type=uint16_t) {
+ OFPHFC_INCOMPATIBLE = 0,
+ OFPHFC_EPERM = 1,
+};
+
+enum ofp_bad_request_code(wire_type=uint16_t) {
+ OFPBRC_BAD_VERSION = 0,
+ OFPBRC_BAD_TYPE = 1,
+ OFPBRC_BAD_STAT = 2,
+ OFPBRC_BAD_EXPERIMENTER = 3,
+ OFPBRC_BAD_EXPERIMENTER_TYPE = 4,
+ OFPBRC_EPERM = 5,
+ OFPBRC_BAD_LEN = 6,
+ OFPBRC_BUFFER_EMPTY = 7,
+ OFPBRC_BUFFER_UNKNOWN = 8,
+ OFPBRC_BAD_TABLE_ID = 9,
+ OFPBRC_IS_SLAVE = 10,
+ OFPBRC_BAD_PORT = 11,
+ OFPBRC_BAD_PACKET = 12,
+ OFPBRC_MULTIPART_BUFFER_OVERFLOW = 13,
+ OFPBRC_MULTIPART_REQUEST_TIMEOUT = 14,
+ OFPBRC_MULTIPART_REPLY_TIMEOUT = 15,
+};
+
+enum ofp_bad_action_code(wire_type=uint16_t) {
+ OFPBAC_BAD_TYPE = 0,
+ OFPBAC_BAD_LEN = 1,
+ OFPBAC_BAD_EXPERIMENTER = 2,
+ OFPBAC_BAD_EXPERIMENTER_TYPE = 3,
+ OFPBAC_BAD_OUT_PORT = 4,
+ OFPBAC_BAD_ARGUMENT = 5,
+ OFPBAC_EPERM = 6,
+ OFPBAC_TOO_MANY = 7,
+ OFPBAC_BAD_QUEUE = 8,
+ OFPBAC_BAD_OUT_GROUP = 9,
+ OFPBAC_MATCH_INCONSISTENT = 10,
+ OFPBAC_UNSUPPORTED_ORDER = 11,
+ OFPBAC_BAD_TAG = 12,
+ OFPBAC_BAD_SET_TYPE = 13,
+ OFPBAC_BAD_SET_LEN = 14,
+ OFPBAC_BAD_SET_ARGUMENT = 15,
+};
+
+enum ofp_bad_instruction_code(wire_type=uint16_t) {
+ OFPBIC_UNKNOWN_INST = 0,
+ OFPBIC_UNSUP_INST = 1,
+ OFPBIC_BAD_TABLE_ID = 2,
+ OFPBIC_UNSUP_METADATA = 3,
+ OFPBIC_UNSUP_METADATA_MASK = 4,
+ OFPBIC_BAD_EXPERIMENTER = 5,
+ OFPBIC_BAD_EXPERIMENTER_TYPE = 6,
+ OFPBIC_BAD_LEN = 7,
+ OFPBIC_EPERM = 8,
+ OFPBIC_DUP_INST = 9,
+};
+
+enum ofp_bad_match_code(wire_type=uint16_t) {
+ OFPBMC_BAD_TYPE = 0,
+ OFPBMC_BAD_LEN = 1,
+ OFPBMC_BAD_TAG = 2,
+ OFPBMC_BAD_DL_ADDR_MASK = 3,
+ OFPBMC_BAD_NW_ADDR_MASK = 4,
+ OFPBMC_BAD_WILDCARDS = 5,
+ OFPBMC_BAD_FIELD = 6,
+ OFPBMC_BAD_VALUE = 7,
+ OFPBMC_BAD_MASK = 8,
+ OFPBMC_BAD_PREREQ = 9,
+ OFPBMC_DUP_FIELD = 10,
+ OFPBMC_EPERM = 11,
+};
+
+enum ofp_flow_mod_failed_code(wire_type=uint16_t) {
+ OFPFMFC_UNKNOWN = 0,
+ OFPFMFC_TABLE_FULL = 1,
+ OFPFMFC_BAD_TABLE_ID = 2,
+ OFPFMFC_OVERLAP = 3,
+ OFPFMFC_EPERM = 4,
+ OFPFMFC_BAD_TIMEOUT = 5,
+ OFPFMFC_BAD_COMMAND = 6,
+ OFPFMFC_BAD_FLAGS = 7,
+ OFPFMFC_CANT_SYNC = 8,
+ OFPFMFC_BAD_PRIORITY = 9,
+};
+
+enum ofp_group_mod_failed_code(wire_type=uint16_t) {
+ OFPGMFC_GROUP_EXISTS = 0,
+ OFPGMFC_INVALID_GROUP = 1,
+ OFPGMFC_WEIGHT_UNSUPPORTED = 2,
+ OFPGMFC_OUT_OF_GROUPS = 3,
+ OFPGMFC_OUT_OF_BUCKETS = 4,
+ OFPGMFC_CHAINING_UNSUPPORTED = 5,
+ OFPGMFC_WATCH_UNSUPPORTED = 6,
+ OFPGMFC_LOOP = 7,
+ OFPGMFC_UNKNOWN_GROUP = 8,
+ OFPGMFC_CHAINED_GROUP = 9,
+ OFPGMFC_BAD_TYPE = 10,
+ OFPGMFC_BAD_COMMAND = 11,
+ OFPGMFC_BAD_BUCKET = 12,
+ OFPGMFC_BAD_WATCH = 13,
+ OFPGMFC_EPERM = 14,
+};
+
+enum ofp_port_mod_failed_code(wire_type=uint16_t) {
+ OFPPMFC_BAD_PORT = 0,
+ OFPPMFC_BAD_HW_ADDR = 1,
+ OFPPMFC_BAD_CONFIG = 2,
+ OFPPMFC_BAD_ADVERTISE = 3,
+ OFPPMFC_EPERM = 4,
+};
+
+enum ofp_table_mod_failed_code(wire_type=uint16_t) {
+ OFPTMFC_BAD_TABLE = 0,
+ OFPTMFC_BAD_CONFIG = 1,
+ OFPTMFC_EPERM = 2,
+};
+
+enum ofp_queue_op_failed_code(wire_type=uint16_t) {
+ OFPQOFC_BAD_PORT = 0,
+ OFPQOFC_BAD_QUEUE = 1,
+ OFPQOFC_EPERM = 2,
+};
+
+enum ofp_switch_config_failed_code(wire_type=uint16_t) {
+ OFPSCFC_BAD_FLAGS = 0,
+ OFPSCFC_BAD_LEN = 1,
+ OFPSCFC_EPERM = 2,
+};
+
+enum ofp_role_request_failed_code(wire_type=uint16_t){
+ OFPRRFC_STALE = 0,
+ OFPRRFC_UNSUP = 1,
+ OFPRRFC_BAD_ROLE = 2,
+};
+
+enum ofp_meter_mod_failed_code(wire_type=uint16_t) {
+ OFPMMFC_UNKNOWN = 0,
+ OFPMMFC_METER_EXISTS = 1,
+ OFPMMFC_INVALID_METER = 2,
+ OFPMMFC_UNKNOWN_METER = 3,
+ OFPMMFC_BAD_COMMAND = 4,
+ OFPMMFC_BAD_FLAGS = 5,
+ OFPMMFC_BAD_RATE = 6,
+ OFPMMFC_BAD_BURST = 7,
+ OFPMMFC_BAD_BAND = 8,
+ OFPMMFC_BAD_BAND_VALUE = 9,
+ OFPMMFC_OUT_OF_METERS = 10,
+ OFPMMFC_OUT_OF_BANDS = 11,
+};
+
+enum ofp_table_features_failed_code(wire_type=uint16_t) {
+ OFPTFFC_BAD_TABLE = 0,
+ OFPTFFC_BAD_METADATA = 1,
+ OFPTFFC_EPERM = 5,
+};
+
+enum ofp_bad_property_code(wire_type=uint16_t) {
+ OFPBPC_BAD_TYPE = 0, /* Unknown property type. */
+ OFPBPC_BAD_LEN = 1, /* Length problem in property. */
+ OFPBPC_BAD_VALUE = 2, /* Unsupported property value. */
+ OFPBPC_TOO_MANY = 3, /* Can’t handle this many properties. */
+ OFPBPC_DUP_TYPE = 4, /* A property type was duplicated. */
+ OFPBPC_BAD_EXPERIMENTER = 5, /* Unknown experimenter id specified. */
+ OFPBPC_BAD_EXP_TYPE = 6, /* Unknown exp_type for experimenter id. */
+ OFPBPC_BAD_EXP_VALUE = 7, /* Unknown value for experimenter id. */
+ OFPBPC_EPERM = 8, /* Permissions error. */
+};
+
+
+enum ofp_async_config_failed_code(wire_type=uint16_t) {
+ OFPACFC_INVALID = 0, /* One mask is invalid. */
+ OFPACFC_UNSUPPORTED = 1, /* Requested configuration not supported. */
+ OFPACFC_EPERM = 2, /* Permissions error. */
+};
+
+enum ofp_flow_monitor_failed_code(wire_type=uint16_t) {
+ OFPMOFC_UNKNOWN = 0, /* Unspecified error. */
+ OFPMOFC_MONITOR_EXISTS = 1, /* Monitor not added because a Monitor ADD
+ * attempted to replace an existing Monitor. */
+ OFPMOFC_INVALID_MONITOR = 2, /* Monitor not added because Monitor specified
+ * is invalid. */
+ OFPMOFC_UNKNOWN_MONITOR = 3, /* Monitor not modified because a Monitor
+ MODIFY attempted to modify a non-existent
+ Monitor. */
+ OFPMOFC_BAD_COMMAND = 4, /* Unsupported or unknown command. */
+ OFPMOFC_BAD_FLAGS = 5, /* Flag configuration unsupported. */
+ OFPMOFC_BAD_TABLE_ID = 6, /* Specified table does not exist. */
+ OFPMOFC_BAD_OUT = 7, /* Error in output port/group. */
+};
+
+enum ofp_bundle_failed_code(wire_type=uint16_t) {
+ OFPBFC_UNKNOWN = 0, /* Unspecified error. */
+ OFPBFC_EPERM = 1, /* Permissions error. */
+ OFPBFC_BAD_ID = 2, /* Bundle ID doesn’t exist. */
+ OFPBFC_BUNDLE_EXIST = 3, /* Bundle ID already exist. */
+ OFPBFC_BUNDLE_CLOSED = 4, /* Bundle ID is closed. */
+ OFPBFC_OUT_OF_BUNDLES = 5, /* Too many bundles IDs. */
+ OFPBFC_BAD_TYPE = 6, /* Unsupported or unknown message control type. */
+ OFPBFC_BAD_FLAGS = 7, /* Unsupported, unknown, or inconsistent flags. */
+ OFPBFC_MSG_BAD_LEN = 8, /* Length problem in included message. */
+ OFPBFC_MSG_BAD_XID = 9, /* Inconsistent or duplicate XID. */
+ OFPBFC_MSG_UNSUP = 10, /* Unsupported message in this bundle. */
+ OFPBFC_MSG_CONFLICT = 11, /* Unsupported message combination in this bundle. */
+ OFPBFC_MSG_TOO_MANY = 12, /* Cant handle this many messages in bundle. */
+ OFPBFC_MSG_FAILED = 13, /* One message in bundle failed. */
+ OFPBFC_TIMEOUT = 14, /* Bundle is taking too long. */
+ OFPBFC_BUNDLE_IN_PROGRESS = 15, /* Bundle is locking the resource. */
+};
+
+/* Port stats property types.
+ */
+enum ofp_port_stats_prop_type(wire_type=uint16_t) {
+ OFPPSPT_ETHERNET = 0, /* Ethernet property. */
+ OFPPSPT_OPTICAL = 1, /* Optical property. */
+ OFPPSPT_EXPERIMENTER = 0xFFFF, /* Experimenter property. */
+};
+
+
+enum ofp_stats_type(wire_type=uint16_t) {
+ OFPST_DESC = 0,
+ OFPST_FLOW = 1,
+ OFPST_AGGREGATE = 2,
+ OFPST_TABLE = 3,
+ OFPST_PORT = 4,
+ OFPST_QUEUE = 5,
+ OFPST_GROUP = 6,
+ OFPST_GROUP_DESC = 7,
+ OFPST_GROUP_FEATURES = 8,
+ OFPST_METER = 9,
+ OFPST_METER_CONFIG = 10,
+ OFPST_METER_FEATURES = 11,
+ OFPST_TABLE_FEATURES = 12,
+ OFPST_PORT_DESC = 13,
+ OFPMP_TABLE_DESC = 14,
+ OFPMP_QUEUE_DESC = 15,
+ OFPMP_FLOW_MONITOR = 16,
+ OFPST_EXPERIMENTER = 0xffff,
+};
+
+enum ofp_stats_request_flags(wire_type=uint16_t, bitmask=True) {
+ OFPSF_REQ_MORE = 0x1,
+};
+
+enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
+ OFPSF_REPLY_MORE = 0x1,
+};
+
+enum ofp_table_feature_prop_type(wire_type=uint16_t) {
+ OFPTFPT_INSTRUCTIONS = 0,
+ OFPTFPT_INSTRUCTIONS_MISS = 1,
+ OFPTFPT_NEXT_TABLES = 2,
+ OFPTFPT_NEXT_TABLES_MISS = 3,
+ OFPTFPT_WRITE_ACTIONS = 4,
+ OFPTFPT_WRITE_ACTIONS_MISS = 5,
+ OFPTFPT_APPLY_ACTIONS = 6,
+ OFPTFPT_APPLY_ACTIONS_MISS = 7,
+ OFPTFPT_MATCH = 8,
+ OFPTFPT_WILDCARDS = 0xa,
+ OFPTFPT_WRITE_SETFIELD = 0xc,
+ OFPTFPT_WRITE_SETFIELD_MISS = 0xd,
+ OFPTFPT_APPLY_SETFIELD = 0xe,
+ OFPTFPT_APPLY_SETFIELD_MISS = 0xf,
+ OFPTFPT_TABLE_SYNC_FROM = 0x10,
+ OFPTFPT_EXPERIMENTER = 0xfffe,
+ OFPTFPT_EXPERIMENTER_MISS = 0xffff,
+};
+
+enum ofp_group_capabilities(wire_type=uint32_t, bitmask=True) {
+ OFPGFC_SELECT_WEIGHT = 0x1,
+ OFPGFC_SELECT_LIVENESS = 0x2,
+ OFPGFC_CHAINING = 0x4,
+ OFPGFC_CHAINING_CHECKS = 0x8,
+};
+
+enum ofp_controller_role(wire_type=uint32_t) {
+ OFPCR_ROLE_NOCHANGE = 0,
+ OFPCR_ROLE_EQUAL = 1,
+ OFPCR_ROLE_MASTER = 2,
+ OFPCR_ROLE_SLAVE = 3,
+};
+
+enum ofp_hello_elem_type(wire_type=uint16_t) {
+ OFPHET_VERSIONBITMAP = 1,
+};
+
+enum ofp_optical_port_features(wire_type=uint32_t, bitmask=True) {
+ OFPOPF_RX_TUNE = 0x1,
+ OFPOPF_TX_TUNE = 0x2,
+ OFPOPF_TX_PWR = 0x4,
+ OFPOPF_USE_FREQ = 0x8,
+};
+
+enum ofp_table_mod_prop_eviction_flag(wire_type=uint32_t, bitmask=True) {
+ OFPTMPEF_OTHER = 0x1,
+ OFPTMPEF_IMPORTANCE = 0x2,
+ OFPTMPEF_LIFETIME = 0x4,
+};
+
+enum ofp_port_stats_optical_flags(wire_type=uint32_t, bitmask=True) {
+ OFPOSF_RX_TUNE = 0x1,
+ OFPOSF_TX_TUNE = 0x2,
+ OFPOSF_TX_PWR = 0x4,
+ OFPOSF_RX_PWR = 0x10,
+ OFPOSF_TX_BIAS = 0x20,
+ OFPOSF_TX_TEMP = 0x40,
+};
+
+enum ofp_bundle_ctrl_type(wire_type=uint16_t) {
+ OFPBCT_OPEN_REQUEST = 0,
+ OFPBCT_OPEN_REPLY = 1,
+ OFPBCT_CLOSE_REQUEST = 2,
+ OFPBCT_CLOSE_REPLY = 3,
+ OFPBCT_COMMIT_REQUEST = 4,
+ OFPBCT_COMMIT_REPLY = 5,
+ OFPBCT_DISCARD_REQUEST = 6,
+ OFPBCT_DISCARD_REPLY = 7,
+};
+
+enum ofp_bundle_flags(wire_type=uint16_t, bitmask=True) {
+ OFPBF_ATOMIC = 1,
+ OFPBF_ORDERED = 2,
+};
+
+enum ofp_controller_role_reason(wire_type=uint8_t) {
+ OFPCRR_MASTER_REQUEST = 0,
+ OFPCRR_CONFIG = 1,
+ OFPCRR_EXPERIMENTER = 2,
+};
+
+enum ofp_table_reason(wire_type=uint8_t) {
+ OFPTR_VACANCY_DOWN = 3,
+ OFPTR_VACANCY_UP = 4,
+};
+
+enum ofp_requestforward_reason {
+ OFPRFR_GROUP_MOD = 0,
+ OFPRFR_METER_MOD = 1,
+};
+
+/* XXX rename to of_message */
+struct of_header {
+ uint8_t version;
+ uint8_t type == ?;
+ uint16_t length;
+ uint32_t xid;
+};
+
+struct of_uint64 {
+ uint64_t value;
+};
+
+// Special structures used for managing scalar list elements
+struct of_uint32 {
+ uint32_t value;
+};
+
+// Special structures used for managing scalar list elements
+struct of_uint8 {
+ uint8_t value;
+};
+
+struct of_hello_elem {
+ uint16_t type == ?;
+ uint16_t length;
+};
+
+struct of_hello_elem_versionbitmap : of_hello_elem {
+ uint16_t type == 1;
+ uint16_t length;
+ list(of_uint32_t) bitmaps;
+};
+
+struct of_hello : of_header {
+ uint8_t version;
+ uint8_t type == 0;
+ uint16_t length;
+ uint32_t xid;
+ list(of_hello_elem_t) elements;
+};
+
+struct of_echo_request : of_header {
+ uint8_t version;
+ uint8_t type == 2;
+ uint16_t length;
+ uint32_t xid;
+ of_octets_t data;
+};
+
+struct of_echo_reply : of_header {
+ uint8_t version;
+ uint8_t type == 3;
+ uint16_t length;
+ uint32_t xid;
+ of_octets_t data;
+};
+
+struct of_experimenter : of_header {
+ uint8_t version;
+ uint8_t type == 4;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t experimenter == ?;
+ uint32_t subtype;
+ of_octets_t data;
+};
+
+struct of_barrier_request : of_header {
+ uint8_t version;
+ uint8_t type == 20;
+ uint16_t length;
+ uint32_t xid;
+};
+
+struct of_barrier_reply : of_header {
+ uint8_t version;
+ uint8_t type == 21;
+ uint16_t length;
+ uint32_t xid;
+};
+
+struct of_get_config_request : of_header {
+ uint8_t version;
+ uint8_t type == 7;
+ uint16_t length;
+ uint32_t xid;
+};
+
+struct of_get_config_reply : of_header {
+ uint8_t version;
+ uint8_t type == 8;
+ uint16_t length;
+ uint32_t xid;
+ enum ofp_config_flags flags;
+ uint16_t miss_send_len;
+};
+
+struct of_set_config : of_header {
+ uint8_t version;
+ uint8_t type == 9;
+ uint16_t length;
+ uint32_t xid;
+ enum ofp_config_flags flags;
+ uint16_t miss_send_len;
+};
+
+struct of_table_mod_prop {
+ uint16_t type == ?; /* One of OFPTMPT_*. */
+ uint16_t length; /* Length in bytes of this property. */
+};
+
+struct of_table_mod_prop_eviction {
+ uint16_t type == 2;
+ uint16_t length;
+ enum ofp_table_mod_prop_eviction_flag flags;
+};
+
+struct of_table_mod_prop_vacancy {
+ uint16_t type == 3;
+ uint16_t length;
+ uint8_t vacancy_down;
+ uint8_t vacancy_up;
+ uint8_t vacancy;
+ pad(1);
+};
+
+struct of_table_mod_prop_experimenter {
+ uint16_t type == 0xffff;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t exp_type;
+};
+
+struct of_table_mod : of_header {
+ uint8_t version;
+ uint8_t type == 17;
+ uint16_t length;
+ uint32_t xid;
+ uint8_t table_id;
+ pad(3);
+ uint32_t config;
+ list(of_table_mod_prop_t) properties;
+};
+
+struct of_port_desc_prop {
+ uint16_t type == ?; /* One of OFPPDPT_*. */
+ uint16_t length; /* Length in bytes of this property. */
+};
+
+struct of_port_desc_prop_ethernet : of_port_desc_prop {
+ uint16_t type == 0;
+ uint16_t length;
+ pad(4);
+ uint32_t curr;
+ uint32_t advertised;
+ uint32_t supported;
+ uint32_t peer;
+ uint32_t curr_speed;
+ uint32_t max_speed;
+};
+
+struct of_port_desc_prop_optical : of_port_desc_prop {
+ uint16_t type == 1;
+ uint16_t length;
+ pad(4);
+ uint32_t supported;
+ uint32_t tx_min_freq_lmda;
+ uint32_t tx_max_freq_lmda;
+ uint32_t tx_grid_freq_lmda;
+ uint32_t rx_min_freq_lmda;
+ uint32_t rx_max_freq_lmda;
+ uint32_t rx_grid_freq_lmda;
+ uint32_t tx_pwr_min;
+ uint32_t tx_pwr_max;
+};
+
+struct of_port_desc_prop_experimenter : of_port_desc_prop {
+ uint16_t type == 0xffff;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t exp_type;
+};
+
+struct of_port_desc {
+ of_port_no_t port_no;
+ uint16_t length;
+ pad(2);
+ of_mac_addr_t hw_addr;
+ pad(2);
+ of_port_name_t name;
+ enum ofp_port_config config; /* Bitmap of OFPPC_* flags. */
+ enum ofp_port_state state; /* Bitmap of OFPPS_* flags. */
+ list(of_port_desc_prop_t) properties;
+};
+
+struct of_features_request : of_header {
+ uint8_t version;
+ uint8_t type == 5;
+ uint16_t length;
+ uint32_t xid;
+};
+
+struct of_features_reply : of_header {
+ uint8_t version;
+ uint8_t type == 6;
+ uint16_t length;
+ uint32_t xid;
+ uint64_t datapath_id;
+ uint32_t n_buffers;
+ uint8_t n_tables;
+ uint8_t auxiliary_id;
+ pad(2);
+ enum ofp_capabilities capabilities;
+ uint32_t reserved;
+};
+
+struct of_port_status : of_header {
+ uint8_t version;
+ uint8_t type == 12;
+ uint16_t length;
+ uint32_t xid;
+ enum ofp_port_reason reason;
+ pad(7);
+ of_port_desc_t desc;
+};
+
+struct of_port_mod_prop {
+ uint16_t type == ?; /* One of OFPPMPT_*. */
+ uint16_t length; /* Length in bytes of this property. */
+};
+
+struct of_port_mod_prop_ethernet : of_port_mod_prop {
+ uint16_t type == 0;
+ uint16_t length;
+ uint32_t advertise;
+};
+
+struct of_port_mod_prop_optical : of_port_mod_prop {
+ uint16_t type == 1;
+ uint16_t length;
+ uint32_t configure;
+ uint32_t freq_ldma;
+ uint32_t fl_offset; /* TODO signed */
+ uint32_t grid_span;
+ uint32_t tx_pwr;
+};
+
+struct of_port_mod_prop_experimenter : of_port_mod_prop {
+ uint16_t type == 0xffff;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t exp_type;
+};
+
+struct of_port_mod : of_header {
+ uint8_t version;
+ uint8_t type == 16;
+ uint16_t length;
+ uint32_t xid;
+ of_port_no_t port_no;
+ pad(4);
+ of_mac_addr_t hw_addr;
+ pad(2);
+ uint32_t config;
+ uint32_t mask;
+ list(of_port_mod_prop_t) properties;
+};
+
+struct of_match_v3(align=8, length_includes_align=False) {
+ uint16_t type == 1;
+ uint16_t length;
+ list(of_oxm_t) oxm_list;
+};
+
+// This looks like an action header, but is standalone. See
+// ofp_table_features_prop_actions
+struct of_action_id {
+ uint16_t type;
+ uint16_t len;
+ of_octets_t exp_data;
+};
+
+struct of_action_output : of_action {
+ uint16_t type == 0;
+ uint16_t len;
+ of_port_no_t port;
+ uint16_t max_len;
+ pad(6);
+};
+
+struct of_action_copy_ttl_out : of_action {
+ uint16_t type == 11;
+ uint16_t len;
+ pad(4);
+};
+
+struct of_action_copy_ttl_in : of_action {
+ uint16_t type == 12;
+ uint16_t len;
+ pad(4);
+};
+
+struct of_action_set_mpls_ttl : of_action {
+ uint16_t type == 15;
+ uint16_t len;
+ uint8_t mpls_ttl;
+ pad(3);
+};
+
+struct of_action_dec_mpls_ttl : of_action {
+ uint16_t type == 16;
+ uint16_t len;
+ pad(4);
+};
+
+struct of_action_push_vlan : of_action {
+ uint16_t type == 17;
+ uint16_t len;
+ uint16_t ethertype;
+ pad(2);
+};
+
+struct of_action_pop_vlan : of_action {
+ uint16_t type == 18;
+ uint16_t len;
+ pad(4);
+};
+
+struct of_action_push_mpls : of_action {
+ uint16_t type == 19;
+ uint16_t len;
+ uint16_t ethertype;
+ pad(2);
+};
+
+struct of_action_pop_mpls : of_action {
+ uint16_t type == 20;
+ uint16_t len;
+ uint16_t ethertype;
+ pad(2);
+};
+
+struct of_action_set_queue : of_action {
+ uint16_t type == 21;
+ uint16_t len;
+ uint32_t queue_id;
+};
+
+struct of_action_group : of_action {
+ uint16_t type == 22;
+ uint16_t len;
+ uint32_t group_id;
+};
+
+struct of_action_set_nw_ttl : of_action {
+ uint16_t type == 23;
+ uint16_t len;
+ uint8_t nw_ttl;
+ pad(3);
+};
+
+struct of_action_dec_nw_ttl : of_action {
+ uint16_t type == 24;
+ uint16_t len;
+ pad(4);
+};
+
+struct of_action_set_field(align=8, length_includes_align=True) : of_action {
+ uint16_t type == 25;
+ uint16_t len;
+ of_oxm_t field;
+};
+
+struct of_action_experimenter(align=8, length_includes_align=True): of_action {
+ uint16_t type == 65535;
+ uint16_t len;
+ uint32_t experimenter == ?;
+ of_octets_t data;
+};
+
+struct of_action_pop_pbb : of_action {
+ uint16_t type == 27;
+ uint16_t len;
+ pad(4);
+};
+
+struct of_action_push_pbb : of_action {
+ uint16_t type == 26;
+ uint16_t len;
+ uint16_t ethertype;
+ pad(2);
+};
+
+struct of_action {
+ uint16_t type == ?;
+ uint16_t len;
+ pad(4);
+};
+
+struct of_instruction_id {
+ uint16_t type;
+ uint16_t len;
+};
+
+struct of_instruction {
+ uint16_t type == ?;
+ uint16_t len;
+};
+
+struct of_instruction_goto_table : of_instruction {
+ uint16_t type == 1;
+ uint16_t len;
+ uint8_t table_id;
+ pad(3);
+};
+
+struct of_instruction_write_metadata : of_instruction {
+ uint16_t type == 2;
+ uint16_t len;
+ pad(4);
+ uint64_t metadata;
+ uint64_t metadata_mask;
+};
+
+struct of_instruction_write_actions : of_instruction {
+ uint16_t type == 3;
+ uint16_t len;
+ pad(4);
+ list(of_action_t) actions;
+};
+
+struct of_instruction_apply_actions : of_instruction {
+ uint16_t type == 4;
+ uint16_t len;
+ pad(4);
+ list(of_action_t) actions;
+};
+
+struct of_instruction_clear_actions : of_instruction {
+ uint16_t type == 5;
+ uint16_t len;
+ pad(4);
+};
+
+struct of_instruction_meter : of_instruction {
+ uint16_t type == 6;
+ uint16_t len;
+ uint32_t meter_id;
+};
+
+struct of_instruction_experimenter : of_instruction {
+ uint16_t type == 65535;
+ uint16_t len;
+ uint32_t experimenter == ?;
+ of_octets_t data;
+};
+
+struct of_flow_mod : of_header {
+ uint8_t version;
+ uint8_t type == 14;
+ uint16_t length;
+ uint32_t xid;
+ uint64_t cookie;
+ uint64_t cookie_mask;
+ uint8_t table_id;
+ of_fm_cmd_t _command == ?;
+ uint16_t idle_timeout;
+ uint16_t hard_timeout;
+ uint16_t priority;
+ uint32_t buffer_id;
+ of_port_no_t out_port;
+ uint32_t out_group;
+ enum ofp_flow_mod_flags flags;
+ pad(2);
+ of_match_t match;
+ list(of_instruction_t) instructions;
+};
+
+struct of_flow_add : of_flow_mod {
+ uint8_t version;
+ uint8_t type == 14;
+ uint16_t length;
+ uint32_t xid;
+ uint64_t cookie;
+ uint64_t cookie_mask;
+ uint8_t table_id;
+ of_fm_cmd_t _command == 0;
+ uint16_t idle_timeout;
+ uint16_t hard_timeout;
+ uint16_t priority;
+ uint32_t buffer_id;
+ of_port_no_t out_port;
+ uint32_t out_group;
+ enum ofp_flow_mod_flags flags;
+ uint16_t importance;
+ of_match_t match;
+ list(of_instruction_t) instructions;
+};
+
+struct of_flow_modify : of_flow_mod {
+ uint8_t version;
+ uint8_t type == 14;
+ uint16_t length;
+ uint32_t xid;
+ uint64_t cookie;
+ uint64_t cookie_mask;
+ uint8_t table_id;
+ of_fm_cmd_t _command == 1;
+ uint16_t idle_timeout;
+ uint16_t hard_timeout;
+ uint16_t priority;
+ uint32_t buffer_id;
+ of_port_no_t out_port;
+ uint32_t out_group;
+ enum ofp_flow_mod_flags flags;
+ uint16_t importance;
+ of_match_t match;
+ list(of_instruction_t) instructions;
+};
+
+struct of_flow_modify_strict : of_flow_mod {
+ uint8_t version;
+ uint8_t type == 14;
+ uint16_t length;
+ uint32_t xid;
+ uint64_t cookie;
+ uint64_t cookie_mask;
+ uint8_t table_id;
+ of_fm_cmd_t _command == 2;
+ uint16_t idle_timeout;
+ uint16_t hard_timeout;
+ uint16_t priority;
+ uint32_t buffer_id;
+ of_port_no_t out_port;
+ uint32_t out_group;
+ enum ofp_flow_mod_flags flags;
+ uint16_t importance;
+ of_match_t match;
+ list(of_instruction_t) instructions;
+};
+
+struct of_flow_delete : of_flow_mod {
+ uint8_t version;
+ uint8_t type == 14;
+ uint16_t length;
+ uint32_t xid;
+ uint64_t cookie;
+ uint64_t cookie_mask;
+ uint8_t table_id;
+ of_fm_cmd_t _command == 3;
+ uint16_t idle_timeout;
+ uint16_t hard_timeout;
+ uint16_t priority;
+ uint32_t buffer_id;
+ of_port_no_t out_port;
+ uint32_t out_group;
+ enum ofp_flow_mod_flags flags;
+ uint16_t importance;
+ of_match_t match;
+ list(of_instruction_t) instructions;
+};
+
+struct of_flow_delete_strict : of_flow_mod {
+ uint8_t version;
+ uint8_t type == 14;
+ uint16_t length;
+ uint32_t xid;
+ uint64_t cookie;
+ uint64_t cookie_mask;
+ uint8_t table_id;
+ of_fm_cmd_t _command == 4;
+ uint16_t idle_timeout;
+ uint16_t hard_timeout;
+ uint16_t priority;
+ uint32_t buffer_id;
+ of_port_no_t out_port;
+ uint32_t out_group;
+ enum ofp_flow_mod_flags flags;
+ uint16_t importance;
+ of_match_t match;
+ list(of_instruction_t) instructions;
+};
+
+struct of_bucket {
+ uint16_t len;
+ uint16_t weight;
+ of_port_no_t watch_port;
+ uint32_t watch_group;
+ pad(4);
+ list(of_action_t) actions;
+};
+
+struct of_group_mod : of_header {
+ uint8_t version;
+ uint8_t type == 15;
+ uint16_t length;
+ uint32_t xid;
+ enum ofp_group_mod_command command == ?;
+ enum ofp_group_type group_type;
+ pad(1);
+ uint32_t group_id;
+ list(of_bucket_t) buckets;
+};
+
+struct of_group_add : of_group_mod {
+ uint8_t version;
+ uint8_t type == 15;
+ uint16_t length;
+ uint32_t xid;
+ enum ofp_group_mod_command command == 0;
+ enum ofp_group_type group_type;
+ pad(1);
+ uint32_t group_id;
+ list(of_bucket_t) buckets;
+};
+
+struct of_group_modify : of_group_mod {
+ uint8_t version;
+ uint8_t type == 15;
+ uint16_t length;
+ uint32_t xid;
+ enum ofp_group_mod_command command == 1;
+ enum ofp_group_type group_type;
+ pad(1);
+ uint32_t group_id;
+ list(of_bucket_t) buckets;
+};
+
+struct of_group_delete : of_group_mod {
+ uint8_t version;
+ uint8_t type == 15;
+ uint16_t length;
+ uint32_t xid;
+ enum ofp_group_mod_command command == 2;
+ enum ofp_group_type group_type;
+ pad(1);
+ uint32_t group_id;
+ list(of_bucket_t) buckets;
+};
+
+struct of_packet_out : of_header {
+ uint8_t version;
+ uint8_t type == 13;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t buffer_id;
+ of_port_no_t in_port;
+ uint16_t actions_len;
+ pad(6);
+ list(of_action_t) actions;
+ of_octets_t data;
+};
+
+struct of_packet_in : of_header {
+ uint8_t version;
+ uint8_t type == 10;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t buffer_id;
+ uint16_t total_len;
+ uint8_t reason;
+ uint8_t table_id;
+ uint64_t cookie;
+ of_match_t match;
+ pad(2);
+ of_octets_t data;
+};
+
+struct of_flow_removed : of_header {
+ uint8_t version;
+ uint8_t type == 11;
+ uint16_t length;
+ uint32_t xid;
+ uint64_t cookie;
+ uint16_t priority;
+ uint8_t reason;
+ uint8_t table_id;
+ uint32_t duration_sec;
+ uint32_t duration_nsec;
+ uint16_t idle_timeout;
+ uint16_t hard_timeout;
+ uint64_t packet_count;
+ uint64_t byte_count;
+ of_match_t match;
+};
+
+struct of_meter_band {
+ uint16_t type == ?;
+ uint16_t len;
+// uint32_t rate; // These are excluded b/c this is the header
+// uint32_t burst_size; // These are excluded b/c this is the header
+};
+
+struct of_meter_band_drop : of_meter_band {
+ uint16_t type == 1;
+ uint16_t len;
+ uint32_t rate;
+ uint32_t burst_size;
+ pad(4);
+};
+
+struct of_meter_band_dscp_remark : of_meter_band {
+ uint16_t type == 2;
+ uint16_t len;
+ uint32_t rate;
+ uint32_t burst_size;
+ uint8_t prec_level;
+ pad(3);
+};
+
+struct of_meter_band_experimenter : of_meter_band {
+ uint16_t type == 65535;
+ uint16_t len;
+ uint32_t rate;
+ uint32_t burst_size;
+ uint32_t experimenter;
+};
+
+struct of_meter_mod : of_header {
+ uint8_t version;
+ uint8_t type == 29;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t command;
+ uint16_t flags;
+ uint32_t meter_id;
+ list(of_meter_band_t) bands;
+};
+
+struct of_error_msg : of_header {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == ?;
+};
+
+struct of_hello_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 0;
+ enum ofp_hello_failed_code code;
+ of_octets_t data;
+};
+
+struct of_bad_request_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 1;
+ enum ofp_bad_request_code code;
+ of_octets_t data;
+};
+
+struct of_bad_action_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 2;
+ enum ofp_bad_action_code code;
+ of_octets_t data;
+};
+
+struct of_bad_instruction_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 3;
+ enum ofp_bad_instruction_code code;
+ of_octets_t data;
+};
+
+struct of_bad_match_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 4;
+ enum ofp_bad_match_code code;
+ of_octets_t data;
+};
+
+struct of_flow_mod_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 5;
+ enum ofp_flow_mod_failed_code code;
+ of_octets_t data;
+};
+
+struct of_group_mod_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 6;
+ enum ofp_group_mod_failed_code code;
+ of_octets_t data;
+};
+
+struct of_port_mod_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 7;
+ enum ofp_port_mod_failed_code code;
+ of_octets_t data;
+};
+
+struct of_table_mod_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 8;
+ enum ofp_table_mod_failed_code code;
+ of_octets_t data;
+};
+
+struct of_queue_op_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 9;
+ enum ofp_queue_op_failed_code code;
+ of_octets_t data;
+};
+
+struct of_switch_config_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 10;
+ enum ofp_switch_config_failed_code code;
+ of_octets_t data;
+};
+
+struct of_role_request_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 11;
+ enum ofp_role_request_failed_code code;
+ of_octets_t data;
+};
+
+struct of_meter_mod_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 12;
+ enum ofp_meter_mod_failed_code code;
+ of_octets_t data;
+};
+
+struct of_table_features_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 13;
+ enum ofp_table_features_failed_code code;
+ of_octets_t data;
+};
+
+struct of_bad_property_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 14;
+ enum ofp_bad_property_code code;
+ of_octets_t data;
+};
+
+struct of_async_config_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 15;
+ enum ofp_async_config_failed_code code;
+ of_octets_t data;
+};
+
+struct of_flow_monitor_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 16;
+ enum ofp_flow_monitor_failed_code code;
+ of_octets_t data;
+};
+
+struct of_bundle_failed_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 17;
+ enum ofp_bundle_failed_code code;
+ of_octets_t data;
+};
+
+struct of_experimenter_error_msg : of_error_msg {
+ uint8_t version;
+ uint8_t type == 1;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t err_type == 0xffff;
+ uint16_t subtype;
+ uint32_t experimenter;
+ of_octets_t data;
+};
+
+// STATS ENTRIES: flow, table, port, queue, group stats, group desc stats
+
+struct of_flow_stats_entry {
+ uint16_t length;
+ uint8_t table_id;
+ pad(1);
+ uint32_t duration_sec;
+ uint32_t duration_nsec;
+ uint16_t priority;
+ uint16_t idle_timeout;
+ uint16_t hard_timeout;
+ enum ofp_flow_mod_flags flags;
+ uint16_t importance;
+ pad(2);
+ uint64_t cookie;
+ uint64_t packet_count;
+ uint64_t byte_count;
+ of_match_t match;
+ list(of_instruction_t) instructions;
+};
+
+
+struct of_table_stats_entry {
+ uint8_t table_id;
+ pad(3);
+ uint32_t active_count;
+ uint64_t lookup_count;
+ uint64_t matched_count;
+};
+
+/* Common header for all port stats properties. */
+struct of_port_stats_prop {
+ uint16_t type == ?; /* One of OFPPSPT_*. */
+ uint16_t length; /* Length in bytes of this property. */
+};
+
+/* Ethernet port stats property. */
+struct of_port_stats_prop_ethernet : of_port_stats_prop {
+ uint16_t type == 0; /* OFPPSPT_ETHERNET. */
+ uint16_t length; /* Length in bytes of this property. */
+ pad(4);
+
+ uint64_t rx_frame_err; /* Number of frame alignment errors. */
+ uint64_t rx_over_err; /* Number of packets with RX overrun. */
+ uint64_t rx_crc_err; /* Number of CRC errors. */
+ uint64_t collisions; /* Number of collisions. */
+};
+
+/* Optical port stats property. */
+struct of_port_stats_prop_optical : of_port_stats_prop {
+ uint16_t type == 1;
+ uint16_t length;
+ pad(4);
+
+ uint32_t flags;
+ uint32_t tx_freq_lmda;
+ uint32_t tx_offset;
+ uint32_t tx_grid_span;
+ uint32_t rx_freq_lmda;
+ uint32_t rx_offset;
+ uint32_t rx_grid_span;
+ uint16_t tx_pwr;
+ uint16_t rx_pwr;
+ uint16_t bias_current;
+ uint16_t temperature;
+};
+
+/* Experimenter port stats property. */
+struct of_port_stats_prop_experimenter : of_port_stats_prop {
+ uint16_t type == 0xffff;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t exp_type;
+ of_octets_t experimenter_data;
+};
+
+struct of_port_stats_entry {
+ uint16_t length;
+ pad(2);
+ of_port_no_t port_no;
+ uint32_t duration_sec;
+ uint32_t duration_nsec;
+ uint64_t rx_packets;
+ uint64_t tx_packets;
+ uint64_t rx_bytes;
+ uint64_t tx_bytes;
+ uint64_t rx_dropped;
+ uint64_t tx_dropped;
+ uint64_t rx_errors;
+ uint64_t tx_errors;
+ list(of_port_stats_prop_t) properties;
+};
+
+struct of_queue_stats_prop {
+ uint16_t type == ?;
+ uint16_t length;
+};
+
+struct of_queue_stats_prop_experimenter : of_queue_stats_prop {
+ uint16_t type == 0xffff;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t exp_type;
+};
+
+struct of_queue_stats_entry {
+ uint16_t length;
+ pad(6);
+ of_port_no_t port_no;
+ uint32_t queue_id;
+ uint64_t tx_bytes;
+ uint64_t tx_packets;
+ uint64_t tx_errors;
+ uint32_t duration_sec;
+ uint32_t duration_nsec;
+ list(of_queue_stats_prop_t) properties;
+};
+
+struct of_bucket_counter {
+ uint64_t packet_count;
+ uint64_t byte_count;
+};
+
+struct of_group_stats_entry {
+ uint16_t length;
+ pad(2);
+ uint32_t group_id;
+ uint32_t ref_count;
+ pad(4);
+ uint64_t packet_count;
+ uint64_t byte_count;
+ uint32_t duration_sec;
+ uint32_t duration_nsec;
+ list(of_bucket_counter_t) bucket_stats;
+};
+
+struct of_group_desc_stats_entry {
+ uint16_t length;
+ enum ofp_group_type group_type;
+ pad(1);
+ uint32_t group_id;
+ list(of_bucket_t) buckets;
+};
+
+// STATS:
+// Desc, flow, agg, table, port, queue, group, group_desc, group_feat, experi
+
+struct of_stats_request : of_header {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == ?;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+};
+
+struct of_stats_reply : of_header {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == ?;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+};
+
+struct of_desc_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 0;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+};
+
+struct of_desc_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 0;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ of_desc_str_t mfr_desc;
+ of_desc_str_t hw_desc;
+ of_desc_str_t sw_desc;
+ of_serial_num_t serial_num;
+ of_desc_str_t dp_desc;
+};
+
+struct of_flow_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 1;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ uint8_t table_id;
+ pad(3);
+ of_port_no_t out_port;
+ uint32_t out_group;
+ pad(4);
+ uint64_t cookie;
+ uint64_t cookie_mask;
+ of_match_t match;
+};
+
+struct of_flow_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 1;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_flow_stats_entry_t) entries;
+};
+
+struct of_aggregate_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 2;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ uint8_t table_id;
+ pad(3);
+ of_port_no_t out_port;
+ uint32_t out_group;
+ pad(4);
+ uint64_t cookie;
+ uint64_t cookie_mask;
+ of_match_t match;
+};
+
+struct of_aggregate_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 2;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ uint64_t packet_count;
+ uint64_t byte_count;
+ uint32_t flow_count;
+ pad(4);
+};
+
+struct of_table_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 3;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+};
+
+struct of_table_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 3;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_table_stats_entry_t) entries;
+};
+
+struct of_experimenter_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 0xffff;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ uint32_t experimenter == ?;
+ uint32_t subtype;
+};
+
+struct of_experimenter_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 0xffff;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ uint32_t experimenter == ?;
+ uint32_t subtype;
+};
+
+// FIXME: These are padded to 8 byte align beyond the length indicated
+
+struct of_table_feature_prop {
+ uint16_t type == ?;
+ uint16_t length;
+};
+
+struct of_table_feature_prop_instructions : of_table_feature_prop {
+ uint16_t type == 0;
+ uint16_t length;
+ // FIXME Check if instruction_t is right for ids here
+ list(of_instruction_id_t) instruction_ids;
+};
+
+struct of_table_feature_prop_instructions_miss : of_table_feature_prop {
+ uint16_t type == 1;
+ uint16_t length;
+ list(of_instruction_id_t) instruction_ids;
+};
+
+struct of_table_feature_prop_next_tables : of_table_feature_prop {
+ uint16_t type == 2;
+ uint16_t length;
+ list(of_uint8_t) next_table_ids;
+};
+
+struct of_table_feature_prop_next_tables_miss : of_table_feature_prop {
+ uint16_t type == 3;
+ uint16_t length;
+ list(of_uint8_t) next_table_ids;
+};
+
+struct of_table_feature_prop_write_actions : of_table_feature_prop {
+ uint16_t type == 4;
+ uint16_t length;
+ list(of_action_id_t) action_ids;
+};
+
+struct of_table_feature_prop_write_actions_miss : of_table_feature_prop {
+ uint16_t type == 5;
+ uint16_t length;
+ list(of_action_id_t) action_ids;
+};
+
+struct of_table_feature_prop_apply_actions : of_table_feature_prop {
+ uint16_t type == 6;
+ uint16_t length;
+ list(of_action_id_t) action_ids;
+};
+
+struct of_table_feature_prop_apply_actions_miss : of_table_feature_prop {
+ uint16_t type == 7;
+ uint16_t length;
+ list(of_action_id_t) action_ids;
+};
+
+struct of_table_feature_prop_match : of_table_feature_prop {
+ uint16_t type == 8;
+ uint16_t length;
+ list(of_uint32_t) oxm_ids;
+};
+
+struct of_table_feature_prop_wildcards : of_table_feature_prop {
+ uint16_t type == 10;
+ uint16_t length;
+ list(of_uint32_t) oxm_ids;
+};
+
+struct of_table_feature_prop_write_setfield : of_table_feature_prop {
+ uint16_t type == 12;
+ uint16_t length;
+ list(of_uint32_t) oxm_ids;
+};
+
+struct of_table_feature_prop_write_setfield_miss : of_table_feature_prop {
+ uint16_t type == 13;
+ uint16_t length;
+ list(of_uint32_t) oxm_ids;
+};
+
+struct of_table_feature_prop_apply_setfield : of_table_feature_prop {
+ uint16_t type == 14;
+ uint16_t length;
+ list(of_uint32_t) oxm_ids;
+};
+
+struct of_table_feature_prop_apply_setfield_miss : of_table_feature_prop {
+ uint16_t type == 15;
+ uint16_t length;
+ list(of_uint32_t) oxm_ids;
+};
+
+struct of_table_feature_prop_table_sync_from : of_table_feature_prop {
+ uint16_t type == 16;
+ uint16_t length;
+ list(of_uint8_t) table_ids;
+};
+
+struct of_table_feature_prop_experimenter : of_table_feature_prop {
+ uint16_t type == 65534;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t subtype;
+ of_octets_t experimenter_data;
+};
+
+struct of_table_feature_prop_experimenter_miss : of_table_feature_prop {
+ uint16_t type == 65535;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t subtype;
+ of_octets_t experimenter_data;
+};
+
+struct of_table_features {
+ uint16_t length;
+ uint8_t table_id;
+ pad(5);
+ of_table_name_t name;
+ uint64_t metadata_match;
+ uint64_t metadata_write;
+ uint32_t config;
+ uint32_t max_entries;
+ list(of_table_feature_prop_t) properties;
+};
+
+struct of_meter_features {
+ uint32_t max_meter;
+ uint32_t band_types;
+ uint32_t capabilities;
+ uint8_t max_bands;
+ uint8_t max_color;
+ pad(2);
+};
+
+struct of_port_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 4;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ of_port_no_t port_no;
+ pad(4);
+};
+
+struct of_port_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 4;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_port_stats_entry_t) entries;
+};
+
+struct of_queue_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 5;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ of_port_no_t port_no;
+ uint32_t queue_id;
+};
+
+struct of_queue_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 5;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_queue_stats_entry_t) entries;
+};
+
+struct of_group_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 6;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ uint32_t group_id;
+ pad(4);
+};
+
+struct of_group_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 6;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_group_stats_entry_t) entries;
+};
+
+struct of_group_desc_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 7;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+};
+
+struct of_group_desc_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 7;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_group_desc_stats_entry_t) entries;
+};
+
+struct of_group_features_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 8;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+};
+
+struct of_group_features_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 8;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ uint32_t types;
+ uint32_t capabilities;
+ uint32_t max_groups_all;
+ uint32_t max_groups_select;
+ uint32_t max_groups_indirect;
+ uint32_t max_groups_ff;
+ uint32_t actions_all;
+ uint32_t actions_select;
+ uint32_t actions_indirect;
+ uint32_t actions_ff;
+};
+
+struct of_meter_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 9;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ uint32_t meter_id;
+ pad(4);
+};
+
+struct of_meter_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 9;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_meter_stats_t) entries;
+};
+
+struct of_meter_config_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 10;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ uint32_t meter_id;
+ pad(4);
+};
+
+struct of_meter_config_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 10;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_meter_band_t) entries;
+};
+
+// FIXME stats added to get things working
+struct of_meter_features_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 11;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+};
+
+// FIXME stats added to get things working
+struct of_meter_features_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 11;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ of_meter_features_t features;
+};
+
+// FIXME stats added to get things working
+struct of_table_features_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 12;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+ list(of_table_features_t) entries;
+};
+
+// FIXME stats added to get things working
+struct of_table_features_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 12;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_table_features_t) entries;
+};
+
+// FIXME stats added to get things working
+struct of_port_desc_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 13;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+};
+
+// FIXME stats added to get things working
+struct of_port_desc_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 13;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_port_desc_t) entries;
+};
+
+struct of_table_desc_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 14;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+};
+
+struct of_table_desc {
+ uint16_t length;
+ uint8_t table_id;
+ pad(1);
+ enum ofp_table_config config;
+};
+
+struct of_table_desc_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 14;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_table_desc_t) entries;
+};
+
+struct of_queue_desc_stats_request : of_stats_request {
+ uint8_t version;
+ uint8_t type == 18;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 15;
+ enum ofp_stats_request_flags flags;
+ pad(4);
+};
+
+struct of_queue_desc_prop {
+ uint16_t type == ?;
+ uint16_t length;
+};
+
+struct of_queue_desc_prop_min_rate : of_queue_desc_prop {
+ uint16_t type == 1;
+ uint16_t length;
+ uint16_t rate;
+ pad(2);
+};
+
+struct of_queue_desc_prop_max_rate : of_queue_desc_prop {
+ uint16_t type == 2;
+ uint16_t length;
+ uint16_t rate;
+ pad(2);
+};
+
+struct of_queue_desc_prop_experimenter : of_queue_desc_prop {
+ uint16_t type == 0xffff;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t exp_type;
+};
+
+struct of_queue_desc {
+ uint32_t port_no;
+ uint32_t queue_id;
+ uint16_t length;
+ pad(6);
+ list(of_queue_desc_prop_t) properties;
+};
+
+struct of_queue_desc_stats_reply : of_stats_reply {
+ uint8_t version;
+ uint8_t type == 19;
+ uint16_t length;
+ uint32_t xid;
+ uint16_t stats_type == 15;
+ enum ofp_stats_reply_flags flags;
+ pad(4);
+ list(of_queue_desc_t) entries;
+};
+
+/*
+ * Not supporting the flow monitor multipart messages. This message is
+ * poorly designed because it includes a variable length match inside a
+ * struct (ofp_flow_monitor_request) with no explicit length member.
+ * I'm not writing the special case code to figure out the total length.
+ */
+
+struct of_meter_band_stats {
+ uint64_t packet_band_count;
+ uint64_t byte_band_count;
+};
+
+struct of_meter_stats {
+ uint32_t meter_id;
+ uint16_t len;
+ pad(6);
+ uint32_t flow_count;
+ uint64_t packet_in_count;
+ uint64_t byte_in_count;
+ uint32_t duration_sec;
+ uint32_t duration_nsec;
+ list(of_meter_band_stats_t) band_stats;
+};
+
+struct of_meter_config {
+ uint16_t length;
+ uint16_t flags;
+ uint32_t meter_id;
+ list(of_meter_band_t) entries;
+};
+
+// END OF STATS OBJECTS
+
+struct of_queue_prop {
+ uint16_t type == ?;
+ uint16_t len;
+ pad(4);
+};
+
+struct of_queue_prop_min_rate : of_queue_prop {
+ uint16_t type == 1;
+ uint16_t len;
+ pad(4);
+ uint16_t rate;
+ pad(6);
+};
+
+struct of_queue_prop_max_rate : of_queue_prop {
+ uint16_t type == 2;
+ uint16_t len;
+ pad(4);
+ uint16_t rate;
+ pad(6);
+};
+
+struct of_queue_prop_experimenter : of_queue_prop {
+ uint16_t type == 65535;
+ uint16_t len;
+ pad(4);
+ uint32_t experimenter == ?;
+ pad(4);
+ of_octets_t data;
+};
+
+struct of_packet_queue {
+ uint32_t queue_id;
+ of_port_no_t port;
+ uint16_t len;
+ pad(6);
+ list(of_queue_prop_t) properties;
+};
+
+struct of_role_request : of_header {
+ uint8_t version;
+ uint8_t type == 24;
+ uint16_t length;
+ uint32_t xid;
+ enum ofp_controller_role role;
+ pad(4);
+ uint64_t generation_id;
+};
+
+struct of_role_reply : of_header {
+ uint8_t version;
+ uint8_t type == 25;
+ uint16_t length;
+ uint32_t xid;
+ enum ofp_controller_role role;
+ pad(4);
+ uint64_t generation_id;
+};
+
+/* Bundle messages */
+
+struct of_bundle_prop {
+ uint16_t type == ?;
+ uint16_t length;
+};
+
+struct of_bundle_prop_experimenter : of_bundle_prop {
+ uint16_t type == 0xffff;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t exp_type;
+};
+
+struct of_bundle_ctrl_msg : of_header {
+ uint8_t version;
+ uint8_t type == 33;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t bundle_id;
+ enum ofp_bundle_ctrl_type bundle_ctrl_type;
+ enum ofp_bundle_flags flags;
+ list(of_bundle_prop_t) properties;
+};
+
+struct of_bundle_add_msg : of_header {
+ uint8_t version;
+ uint8_t type == 34;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t bundle_id;
+ pad(2);
+ enum ofp_bundle_flags flags;
+ // TODO support embedding of_header
+ of_octets_t data;
+ // TODO support trailing properties
+};
+
+/* Async config messages */
+
+struct of_async_config_prop {
+ uint16_t type == ?;
+ uint16_t length;
+};
+
+struct of_async_config_prop_packet_in_slave : of_async_config_prop {
+ uint16_t type == 0;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_packet_in_master : of_async_config_prop {
+ uint16_t type == 1;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_port_status_slave : of_async_config_prop {
+ uint16_t type == 2;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_port_status_master : of_async_config_prop {
+ uint16_t type == 3;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_flow_removed_slave : of_async_config_prop {
+ uint16_t type == 4;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_flow_removed_master : of_async_config_prop {
+ uint16_t type == 5;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_role_status_slave : of_async_config_prop {
+ uint16_t type == 6;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_role_status_master : of_async_config_prop {
+ uint16_t type == 7;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_table_status_slave : of_async_config_prop {
+ uint16_t type == 8;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_table_status_master : of_async_config_prop {
+ uint16_t type == 9;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_requestforward_slave : of_async_config_prop {
+ uint16_t type == 10;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_requestforward_master : of_async_config_prop {
+ uint16_t type == 11;
+ uint16_t length;
+ uint32_t mask;
+};
+
+struct of_async_config_prop_experimenter_slave : of_async_config_prop {
+ uint16_t type == 0xfffe;
+ uint16_t length;
+};
+
+struct of_async_config_prop_experimenter_master : of_async_config_prop {
+ uint16_t type == 0xffff;
+ uint16_t length;
+};
+
+struct of_async_get_request : of_header {
+ uint8_t version;
+ uint8_t type == 26;
+ uint16_t length;
+ uint32_t xid;
+ list(of_async_config_prop_t) properties;
+};
+
+struct of_async_get_reply : of_header {
+ uint8_t version;
+ uint8_t type == 27;
+ uint16_t length;
+ uint32_t xid;
+ list(of_async_config_prop_t) properties;
+};
+
+struct of_async_set : of_header {
+ uint8_t version;
+ uint8_t type == 28;
+ uint16_t length;
+ uint32_t xid;
+ list(of_async_config_prop_t) properties;
+};
+
+/* Role status message */
+
+struct of_role_prop {
+ uint16_t type == ?;
+ uint16_t length;
+};
+
+struct of_role_prop_experimenter : of_role_prop {
+ uint16_t type == 0xffff;
+ uint16_t length;
+ uint32_t experimenter == ?;
+ uint32_t exp_type;
+};
+
+struct of_role_status : of_header {
+ uint8_t version;
+ uint8_t type == 30;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t role;
+ enum ofp_controller_role_reason reason;
+ pad(3);
+ uint64_t generation_id;
+ list(of_role_prop_t) properties;
+};
+
+/* Table status messages */
+
+struct of_table_status : of_header {
+ uint8_t version;
+ uint8_t type == 31;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t role;
+ enum ofp_table_reason reason;
+ pad(7);
+ of_table_desc_t table;
+};
+
+/* Request forward message */
+
+struct of_requestforward : of_header {
+ uint8_t version;
+ uint8_t type == 32;
+ uint16_t length;
+ uint32_t xid;
+ uint32_t role;
+ // TODO support embedding of_header
+ of_octets_t data;
+};
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 9c32e7f..9c741d2 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -26,16 +26,13 @@
# under the EPL.
from collections import defaultdict
+import os
import loxi_globals
-import struct
import template_utils
import loxi_utils.loxi_utils as utils
import util
-import oftype
from loxi_ir import *
-modules_by_version = {}
-
# Map from inheritance root to module name
roots = {
'of_header': 'message',
@@ -46,6 +43,18 @@
'of_instruction_id': 'instruction_id',
'of_meter_band': 'meter_band',
'of_bsn_tlv': 'bsn_tlv',
+ 'of_port_desc_prop': 'port_desc_prop',
+ 'of_port_stats_prop': 'port_stats_prop',
+ 'of_port_mod_prop': 'port_mod_prop',
+ 'of_table_mod_prop': 'table_mod_prop',
+ 'of_queue_desc_prop': 'queue_desc_prop',
+ 'of_queue_stats_prop': 'queue_stats_prop',
+ 'of_async_config_prop': 'async_config_prop',
+ 'of_bundle_prop': 'bundle_prop',
+ #'of_queue_prop': 'queue_prop',
+ 'of_role_prop': 'role_prop',
+ #'of_table_feature_prop': 'table_feature_prop',
+ 'of_table_mod_prop': 'table_mod_prop',
}
# Return the module and class names for the generated Python class
@@ -69,63 +78,36 @@
modules[module_name].append(ofclass)
return modules
-def generate_init(out, name, version):
- util.render_template(out, 'init.py', version=version)
+def codegen(install_dir):
+ def render(name, template_name=None, **ctx):
+ if template_name is None:
+ template_name = os.path.basename(name)
+ with template_utils.open_output(install_dir, name) as out:
+ util.render_template(out, template_name, **ctx)
-def generate_action(out, name, version):
- util.render_template(out, 'module.py',
- ofclasses=modules_by_version[version]['action'],
- version=version)
+ render('__init__.py', template_name='toplevel_init.py')
+ render('pp.py')
+ render('generic_util.py')
-def generate_action_id(out, name, version):
- util.render_template(out, 'module.py',
- ofclasses=modules_by_version[version]['action_id'],
- version=version)
+ for version in loxi_globals.OFVersions.all_supported:
+ subdir = 'of' + version.version.replace('.', '')
+ modules = build_ofclasses(version)
-def generate_oxm(out, name, version):
- util.render_template(out, 'module.py',
- ofclasses=modules_by_version[version]['oxm'],
- version=version)
+ render(os.path.join(subdir, '__init__.py'), template_name='init.py',
+ version=version, modules=modules.keys())
-def generate_common(out, name, version):
- util.render_template(out, 'module.py',
- ofclasses=modules_by_version[version]['common'],
- version=version,
- extra_template='_common_extra.py')
+ render(os.path.join(subdir, 'util.py'), version=version)
-def generate_const(out, name, version):
- util.render_template(out, 'const.py', version=version,
- enums=loxi_globals.ir[version].enums)
+ render(os.path.join(subdir, 'const.py'), version=version,
+ enums=loxi_globals.ir[version].enums)
-def generate_instruction(out, name, version):
- util.render_template(out, 'module.py',
- ofclasses=modules_by_version[version]['instruction'],
- version=version)
+ args_by_module = {
+ 'common': { 'extra_template' : '_common_extra.py' },
+ 'message': { 'extra_template' : '_message_extra.py' },
+ }
-def generate_instruction_id(out, name, version):
- util.render_template(out, 'module.py',
- ofclasses=modules_by_version[version]['instruction_id'],
- version=version)
-
-def generate_message(out, name, version):
- util.render_template(out, 'module.py',
- ofclasses=modules_by_version[version]['message'],
- version=version,
- extra_template='_message_extra.py')
-
-def generate_meter_band(out, name, version):
- util.render_template(out, 'module.py',
- ofclasses=modules_by_version[version]['meter_band'],
- version=version)
-
-def generate_util(out, name, version):
- util.render_template(out, 'util.py', version=version)
-
-def generate_bsn_tlv(out, name, version):
- util.render_template(out, 'module.py',
- ofclasses=modules_by_version[version]['bsn_tlv'],
- version=version)
-
-def init():
- for version in loxi_globals.OFVersions.target_versions:
- modules_by_version[version] = build_ofclasses(version)
+ for name, ofclasses in modules.items():
+ args = args_by_module.get(name, {})
+ render(os.path.join(subdir, name + '.py'), template_name='module.py',
+ version=version, ofclasses=ofclasses, subdir=subdir,
+ **args)
diff --git a/py_gen/oftype.py b/py_gen/oftype.py
index 7bd242e..76eebd0 100644
--- a/py_gen/oftype.py
+++ b/py_gen/oftype.py
@@ -110,12 +110,17 @@
'of_oxm_t': OFTypeData(
init='None',
pack='%s.pack()',
- unpack='oxm.oxm.unpack(%s)'),
+ unpack='ofp.oxm.oxm.unpack(%s)'),
'of_checksum_128_t': OFTypeData(
init='0',
pack='util.pack_checksum_128(%s)',
unpack="util.unpack_checksum_128(%s)"),
+
+ 'of_bitmap_512_t': OFTypeData(
+ init='set()',
+ pack='util.pack_bitmap_512(%s)',
+ unpack="util.unpack_bitmap_512(%s)"),
}
## Fixed length strings
@@ -139,10 +144,11 @@
# Map from class name to Python class name
embedded_structs = {
- 'of_match_t': 'common.match',
- 'of_port_desc_t': 'common.port_desc',
- 'of_meter_features_t': 'common.meter_features',
- 'of_bsn_vport_t': 'common.bsn_vport',
+ 'of_match_t': 'ofp.match',
+ 'of_port_desc_t': 'ofp.port_desc',
+ 'of_meter_features_t': 'ofp.meter_features',
+ 'of_bsn_vport_t': 'ofp.bsn_vport',
+ 'of_table_desc_t': 'ofp.table_desc',
}
for (cls, pyclass) in embedded_structs.items():
@@ -190,8 +196,9 @@
elif oftype_is_list(oftype):
ofproto = loxi_globals.ir[version]
ofclass = ofproto.class_by_name(oftype_list_elem(oftype))
+ assert ofclass, "No class named %r" % oftype_list_elem(oftype)
module_name, class_name = py_gen.codegen.generate_pyname(ofclass)
- return 'loxi.generic_util.unpack_list(%s, %s.%s.unpack)' % \
+ return 'loxi.generic_util.unpack_list(%s, ofp.%s.%s.unpack)' % \
(reader_expr, module_name, class_name)
else:
return "loxi.unimplemented('unpack %s')" % oftype
diff --git a/py_gen/templates/_common_extra.py b/py_gen/templates/_common_extra.py
index 8639dc4..f801965 100644
--- a/py_gen/templates/_common_extra.py
+++ b/py_gen/templates/_common_extra.py
@@ -35,4 +35,7 @@
:: elif version == OFVersions.VERSION_1_3:
:: # HACK
match = match_v3
+:: elif version == OFVersions.VERSION_1_4:
+:: # HACK
+match = match_v3
:: #endif
diff --git a/py_gen/templates/_message_extra.py b/py_gen/templates/_message_extra.py
index 9fc2f5e..adfd0e7 100644
--- a/py_gen/templates/_message_extra.py
+++ b/py_gen/templates/_message_extra.py
@@ -32,8 +32,8 @@
def parse_message(buf):
msg_ver, msg_type, msg_len, msg_xid = parse_header(buf)
- if msg_ver != const.OFP_VERSION and msg_type != const.OFPT_HELLO:
- raise loxi.ProtocolError("wrong OpenFlow version (expected %d, got %d)" % (const.OFP_VERSION, msg_ver))
+ if msg_ver != ofp.OFP_VERSION and msg_type != ofp.OFPT_HELLO:
+ raise loxi.ProtocolError("wrong OpenFlow version (expected %d, got %d)" % (ofp.OFP_VERSION, msg_ver))
if len(buf) != msg_len:
raise loxi.ProtocolError("incorrect message size")
return message.unpack(loxi.generic_util.OFReader(buf))
diff --git a/py_gen/templates/_unpack.py b/py_gen/templates/_unpack.py
index cce9de3..f5c4e34 100644
--- a/py_gen/templates/_unpack.py
+++ b/py_gen/templates/_unpack.py
@@ -35,7 +35,7 @@
:: elif type(m) == OFLengthMember:
_${m.name} = ${gen_unpack_expr(m.oftype, 'reader', version=version)}
orig_reader = reader
- reader = orig_reader.slice(_${m.name} - (${m.offset} + ${m.length}))
+ reader = orig_reader.slice(_${m.name}, ${m.offset + m.length})
:: elif type(m) == OFFieldLengthMember:
:: field_length_members[m.field_name] = m
_${m.name} = ${gen_unpack_expr(m.oftype, 'reader', version=version)}
diff --git a/py_gen/templates/generic_util.py b/py_gen/templates/generic_util.py
index 039d82a..02f1c0e 100644
--- a/py_gen/templates/generic_util.py
+++ b/py_gen/templates/generic_util.py
@@ -105,7 +105,7 @@
self.offset += length
def skip_align(self):
- new_offset = ((self.start + self.offset + 7) / 8 * 8) - self.start
+ new_offset = (self.offset + 7) / 8 * 8
if new_offset > self.length:
raise loxi.ProtocolError("Buffer too short")
self.offset = new_offset
@@ -114,9 +114,10 @@
return self.offset == self.length
# Used when parsing objects that have their own length fields
- def slice(self, length):
- if self.offset + length > self.length:
+ def slice(self, length, rewind=0):
+ if self.offset + length - rewind > self.length:
raise loxi.ProtocolError("Buffer too short")
- reader = OFReader(self.buf, self.start + self.offset, length)
- self.offset += length
+ reader = OFReader(self.buf, self.start + self.offset - rewind, length)
+ reader.skip(rewind)
+ self.offset += length - rewind
return reader
diff --git a/py_gen/templates/init.py b/py_gen/templates/init.py
index 3b73baa..aa968b6 100644
--- a/py_gen/templates/init.py
+++ b/py_gen/templates/init.py
@@ -29,17 +29,10 @@
:: include('_autogen.py')
-import action, common, const, message
-:: if version >= 2:
-import instruction
-:: #endif
-:: if version >= 3:
-import oxm
-:: #endif
-:: if version >= 4:
-import meter_band
-import bsn_tlv
-:: #endif
+import const
+:: for module in modules:
+import ${module}
+:: #endfor
from const import *
from common import *
from loxi import ProtocolError
diff --git a/py_gen/templates/module.py b/py_gen/templates/module.py
index dfe23e8..32baac9 100644
--- a/py_gen/templates/module.py
+++ b/py_gen/templates/module.py
@@ -33,24 +33,12 @@
import struct
import loxi
-import const
-import common
-import action
-:: if version >= OFVersions.VERSION_1_1:
-import instruction
-:: #endif
-:: if version >= OFVersions.VERSION_1_2:
-import oxm
-:: #endif
-:: if version >= OFVersions.VERSION_1_3:
-import action_id
-import instruction_id
-import meter_band
-import bsn_tlv
-:: #endif
import util
import loxi.generic_util
+import sys
+ofp = sys.modules['loxi.${subdir}']
+
:: for ofclass in ofclasses:
:: include('_ofclass.py', ofclass=ofclass)
diff --git a/py_gen/templates/toplevel_init.py b/py_gen/templates/toplevel_init.py
index e5493a5..0393169 100644
--- a/py_gen/templates/toplevel_init.py
+++ b/py_gen/templates/toplevel_init.py
@@ -39,20 +39,13 @@
"""
Import and return the protocol module for the given wire version.
"""
- if ver == 1:
- import of10
- return of10
- elif ver == 2:
- import of11
- return of11
- elif ver == 3:
- import of12
- return of12
- elif ver == 4:
- import of13
- return of13
- else:
- raise ValueError
+:: for v in loxi_globals.OFVersions.all_supported:
+ if ver == ${v.wire_version}:
+ import of${v.version.replace('.', '')}
+ return of${v.version.replace('.', '')}
+
+:: #endfor
+ raise ValueError
class ProtocolError(Exception):
"""
diff --git a/py_gen/templates/util.py b/py_gen/templates/util.py
index 85181dc..7558576 100644
--- a/py_gen/templates/util.py
+++ b/py_gen/templates/util.py
@@ -173,6 +173,28 @@
x >>= 1
return value
+def pack_bitmap_512(value):
+ words = [0] * 8
+ for v in value:
+ assert v < 512
+ words[7-v/64] |= 1 << (v % 64)
+ return struct.pack("!8Q", *words)
+
+def unpack_bitmap_512(reader):
+ words = reader.read("!8Q")
+ x = 0l
+ for word in words:
+ x <<= 64
+ x |= word
+ i = 0
+ value = set()
+ while x != 0:
+ if x & 1 == 1:
+ value.add(i)
+ i += 1
+ x >>= 1
+ return value
+
def pack_checksum_128(value):
return struct.pack("!QQ", (value >> 64) & MASK64, value & MASK64)
diff --git a/py_gen/tests/generic_util.py b/py_gen/tests/generic_util.py
index 03885a2..20a23a4 100644
--- a/py_gen/tests/generic_util.py
+++ b/py_gen/tests/generic_util.py
@@ -102,17 +102,17 @@
self.assertEquals(reader.is_empty(), True)
def test_skip_align(self):
- reader = OFReader("abcd" + "efgh" + "ijkl" + "mnop" + "qr")
+ reader = OFReader("abcd" + "efgh" + "ijkl" + "mnop" + "qrst")
reader.skip_align()
self.assertEquals(reader.peek('2s')[0], 'ab')
self.assertEquals(reader.read('2s')[0], "ab")
reader.skip_align()
self.assertEquals(reader.peek('2s')[0], 'ij')
self.assertEquals(reader.read('2s')[0], 'ij')
- child = reader.slice(8)
- self.assertEquals(child.peek('2s')[0], 'kl')
+ child = reader.slice(10)
+ self.assertEquals(child.read('2s')[0], 'kl')
child.skip_align()
- self.assertEquals(child.peek('2s')[0], 'qr')
+ self.assertEquals(child.peek('2s')[0], 'st')
if __name__ == '__main__':
unittest.main()
diff --git a/py_gen/tests/of13.py b/py_gen/tests/of13.py
index c5a16b2..c99ee34 100644
--- a/py_gen/tests/of13.py
+++ b/py_gen/tests/of13.py
@@ -126,5 +126,18 @@
else:
fn()
+class TestUtils(unittest.TestCase):
+ def check_bitmap_512(self, value, data):
+ self.assertEquals(data, ofp.util.pack_bitmap_512(set(value)))
+ self.assertEquals(ofp.util.unpack_bitmap_512(OFReader(data)), set(value))
+
+ def test_bitmap_512(self):
+ self.check_bitmap_512([0], "\x00" * 63 + "\x01")
+ self.check_bitmap_512([8], "\x00" * 62 + "\x01\x00")
+ self.check_bitmap_512([63], "\x00" * 56 + "\x80" + "\x00" * 7)
+ self.check_bitmap_512([64], "\x00" * 55 + "\x01" + "\x00" * 8)
+ self.check_bitmap_512([511], "\x80" + "\x00" * 63)
+ self.check_bitmap_512([5, 67, 90], "\x00" * 52 + "\x04\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x20")
+
if __name__ == '__main__':
unittest.main()
diff --git a/py_gen/tests/of14.py b/py_gen/tests/of14.py
new file mode 100644
index 0000000..3fdfb8e
--- /dev/null
+++ b/py_gen/tests/of14.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+# Copyright 2014, Big Switch Networks, Inc.
+#
+# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+# the following special exception:
+#
+# LOXI Exception
+#
+# As a special exception to the terms of the EPL, you may distribute libraries
+# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+# that copyright and licensing notices generated by LoxiGen are not altered or removed
+# from the LoxiGen Libraries and the notice provided below is (i) included in
+# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+# documentation for the LoxiGen Libraries, if distributed in binary form.
+#
+# Notice: "Copyright 2014, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+#
+# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+# a copy of the EPL at:
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# 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
+# EPL for the specific language governing permissions and limitations
+# under the EPL.
+import unittest
+from testutil import test_serialization
+from testutil import add_datafiles_tests
+
+try:
+ import loxi
+ import loxi.of14 as ofp
+ from loxi.generic_util import OFReader
+except ImportError:
+ exit("loxi package not found. Try setting PYTHONPATH.")
+
+class TestImports(unittest.TestCase):
+ def test_toplevel(self):
+ import loxi
+ self.assertTrue(hasattr(loxi, "ProtocolError"))
+ self.assertEquals(loxi.version_names[5], "1.4")
+ ofp = loxi.protocol(5)
+ self.assertEquals(ofp.OFP_VERSION, 5)
+ self.assertTrue(hasattr(ofp, "action"))
+ self.assertTrue(hasattr(ofp, "common"))
+ self.assertTrue(hasattr(ofp, "const"))
+ self.assertTrue(hasattr(ofp, "message"))
+ self.assertTrue(hasattr(ofp, "oxm"))
+
+ def test_version(self):
+ import loxi
+ self.assertTrue(hasattr(loxi.of14, "ProtocolError"))
+ self.assertTrue(hasattr(loxi.of14, "OFP_VERSION"))
+ self.assertEquals(loxi.of14.OFP_VERSION, 5)
+ self.assertTrue(hasattr(loxi.of14, "action"))
+ self.assertTrue(hasattr(loxi.of14, "common"))
+ self.assertTrue(hasattr(loxi.of14, "const"))
+ self.assertTrue(hasattr(loxi.of14, "message"))
+ self.assertTrue(hasattr(loxi.of14, "oxm"))
+
+# The majority of the serialization tests are created here using the files in
+# the test_data directory.
+class TestDataFiles(unittest.TestCase):
+ pass
+add_datafiles_tests(TestDataFiles, 'of14/', ofp)
+
+class TestAllof14(unittest.TestCase):
+ """
+ Round-trips every class through serialization/deserialization.
+ Not a replacement for handcoded tests because it only uses the
+ default member values.
+ """
+
+ def setUp(self):
+ mods = [ofp.action,ofp.message,ofp.common,ofp.oxm]
+ self.klasses = [klass for mod in mods
+ for klass in mod.__dict__.values()
+ if isinstance(klass, type) and
+ issubclass(klass, loxi.OFObject) and
+ not hasattr(klass, 'subtypes')]
+ self.klasses.sort(key=lambda x: str(x))
+
+ def test_serialization(self):
+ expected_failures = [
+ ofp.action.set_field, # field defaults to None
+ ]
+ for klass in self.klasses:
+ def fn():
+ obj = klass()
+ if hasattr(obj, "xid"): obj.xid = 42
+ buf = obj.pack()
+ obj2 = klass.unpack(OFReader(buf))
+ self.assertEquals(obj, obj2)
+ if klass in expected_failures:
+ self.assertRaises(Exception, fn)
+ else:
+ fn()
+
+ def test_parse_message(self):
+ expected_failures = [
+ ]
+ for klass in self.klasses:
+ if not issubclass(klass, ofp.message.message):
+ continue
+ def fn():
+ obj = klass(xid=42)
+ buf = obj.pack()
+ obj2 = ofp.message.parse_message(buf)
+ self.assertEquals(obj, obj2)
+ if klass in expected_failures:
+ self.assertRaises(Exception, fn)
+ else:
+ fn()
+
+ def test_show(self):
+ expected_failures = []
+ for klass in self.klasses:
+ def fn():
+ obj = klass()
+ if hasattr(obj, "xid"): obj.xid = 42
+ obj.show()
+ if klass in expected_failures:
+ self.assertRaises(Exception, fn)
+ else:
+ fn()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test_data/of10/flow_add.data b/test_data/of10/flow_add.data
index 60fd780..275a40e 100644
--- a/test_data/of10/flow_add.data
+++ b/test_data/of10/flow_add.data
@@ -117,19 +117,19 @@
of_list_action_t actions;
of_flow_add_actions_bind(obj, &actions);
{
- of_action_t action;
- of_action_output_init(&action.output, OF_VERSION_1_0, -1, 1);
+ of_object_t action;
+ of_action_output_init(&action, OF_VERSION_1_0, -1, 1);
of_list_action_append_bind(&actions, &action);
- of_action_output_port_set(&action.output, OF_PORT_DEST_FLOOD);
+ of_action_output_port_set(&action, OF_PORT_DEST_FLOOD);
}
{
- of_action_t action;
- of_action_nicira_dec_ttl_init(&action.nicira_dec_ttl, OF_VERSION_1_0, -1, 1);
+ of_object_t action;
+ of_action_nicira_dec_ttl_init(&action, OF_VERSION_1_0, -1, 1);
of_list_action_append_bind(&actions, &action);
}
{
- of_action_t action;
- of_action_bsn_set_tunnel_dst_init(&action.bsn_set_tunnel_dst, OF_VERSION_1_0, -1, 1);
+ of_object_t action;
+ of_action_bsn_set_tunnel_dst_init(&action, OF_VERSION_1_0, -1, 1);
of_list_action_append_bind(&actions, &action);
}
}
diff --git a/test_data/of13/oxm_bsn_in_ports_masked_512.data b/test_data/of13/oxm_bsn_in_ports_masked_512.data
new file mode 100644
index 0000000..82cc45c
--- /dev/null
+++ b/test_data/of13/oxm_bsn_in_ports_masked_512.data
@@ -0,0 +1,36 @@
+-- binary
+00 03 # class
+27 # type/masked
+80 # length
+00 00 00 00 00 00 00 00 # value
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+7f ff ff ff ff ff ff ff # mask - Only ports 0, 17, 96, 511 are selected (and thus are zero)
+ff ff ff ff ff ff ff ff # ...
+ff ff ff ff ff ff ff ff # ...
+ff ff ff ff ff ff ff ff # ...
+ff ff ff ff ff ff ff ff # ...
+ff ff ff ff ff ff ff ff # ...
+ff ff ff fe ff ff ff ff # ...
+ff ff ff ff ff fd ff fe # ...
+-- python
+ofp.oxm.bsn_in_ports_512_masked(set(), set(range(0,512)) - set((0, 17, 96, 511)))
+-- c
+obj = of_oxm_bsn_in_ports_512_masked_new(OF_VERSION_1_3);
+{
+ of_bitmap_512_t bmap = { { 0, 0, 0, 0, 0, 0, 0, 0 } };
+ of_oxm_bsn_in_ports_512_masked_value_set(obj, bmap);
+}
+{
+ of_bitmap_512_t bmap = { { 0x7fffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffeffffffff, 0xfffffffffffdfffe } };
+ of_oxm_bsn_in_ports_512_masked_value_mask_set(obj, bmap);
+}
+-- java
+OFPortMap portmap = OFPortMap.ofPorts(OFPort.of(0), OFPort.of(17), OFPort.of(96));
+builder.setValue(portmap.getValue());
+builder.setMask(portmap.getMask());
diff --git a/test_data/of13/oxm_mpls_bos.data b/test_data/of13/oxm_mpls_bos.data
new file mode 100644
index 0000000..8d43f33
--- /dev/null
+++ b/test_data/of13/oxm_mpls_bos.data
@@ -0,0 +1,7 @@
+-- binary
+80 00 # class
+48 # type/masked
+01 # length
+01 # value
+-- python
+ofp.oxm.mpls_bos(value=01)
diff --git a/test_data/of13/port_status.data b/test_data/of13/port_status.data
index 10f7c16..e56705f 100644
--- a/test_data/of13/port_status.data
+++ b/test_data/of13/port_status.data
@@ -34,3 +34,24 @@
peer=ofp.OFPPF_100MB_FD,
curr_speed=10,
max_speed=20))
+-- c
+obj = of_port_status_new(OF_VERSION_1_3);
+of_port_status_xid_set(obj, 0x12345678);
+of_port_status_reason_set(obj, OF_PORT_CHANGE_REASON_MODIFY);
+{
+ of_object_t desc;
+ of_port_status_desc_bind(obj, &desc);
+ of_port_desc_port_no_set(&desc, 4);
+ of_mac_addr_t hw_addr = { { 1, 2, 3, 4, 5, 6 } };
+ of_port_desc_hw_addr_set(&desc, hw_addr);
+ of_port_name_t name = "foo";
+ of_port_desc_name_set(&desc, name);
+ of_port_desc_config_set(&desc, OF_PORT_CONFIG_FLAG_NO_FWD|OF_PORT_CONFIG_FLAG_NO_RECV);
+ of_port_desc_state_set(&desc, OF_PORT_STATE_FLAG_BLOCKED);
+ of_port_desc_curr_set(&desc, OF_PORT_FEATURE_FLAG_10MB_HD);
+ of_port_desc_advertised_set(&desc, OF_PORT_FEATURE_FLAG_10MB_FD);
+ of_port_desc_supported_set(&desc, OF_PORT_FEATURE_FLAG_100MB_HD);
+ of_port_desc_peer_set(&desc, OF_PORT_FEATURE_FLAG_100MB_FD);
+ of_port_desc_curr_speed_set(&desc, 10);
+ of_port_desc_max_speed_set(&desc, 20);
+}
diff --git a/test_data/of14/flow_add.data b/test_data/of14/flow_add.data
new file mode 100644
index 0000000..88cf939
--- /dev/null
+++ b/test_data/of14/flow_add.data
@@ -0,0 +1,104 @@
+-- binary
+05 0e # version, type
+00 80 # length
+12 34 56 78 # xid
+
+fe dc ba 98 76 54 32 10 # cookie
+
+ff 00 ff 00 ff 00 ff 00 # cookie_mask
+
+03 # table_id
+00 # _command
+00 05 # idle_timeout
+00 0a # hard_timeout
+17 70 # priority
+
+00 00 00 32 # buffer_id
+00 00 00 06 # out_port
+
+00 00 00 08 # out_group
+00 00 # flags
+aa bb # importance
+
+00 01 # match.type
+00 3F # match.length # 59 bytes OXMs + 4 bytes match header
+
+80 00 01 08 # match.oxm_list[0].type_len - IN_PORT
+00 00 00 04 # match.oxm_list[0].value
+00 00 00 05 # match.oxm_list[0].mask
+
+80 00 0A 02 # match.oxm_list[1].type_len - ETH_TYPE
+86 DD # match.oxm_list[1].value - ETH_TYPE = IPv6
+
+80 00 14 01 # match.oxm_list[2].type_len - IP Proto
+06 # match.oxm_list[2].value = IP_PROTO = TCP
+
+80 00 35 20 # match.oxm_list[3].type_len - IPV6_SRC
+1C CA FE 1C B1 10 1C 00 00 28 00 00 00 00 00 00 # match.oxm_list[3].value
+FF FF FF FF FF F0 FF FF 1C 2C 3C 00 00 00 00 00 # match.oxm_list[3].mask
+
+00 # match.pad
+
+00 01 # instructions[0].type
+00 08 # instructions[0].length
+04 # instructions[0].table_id
+00 00 00 # pad
+
+00 01 # instructions[1].type
+00 08 # instructions[1].length
+07 # instructions[1].table_id
+00 00 00 # pad
+-- python
+ofp.message.flow_add(
+ xid=0x12345678,
+ cookie=0xFEDCBA9876543210,
+ cookie_mask=0xFF00FF00FF00FF00,
+ table_id=3,
+ idle_timeout=5,
+ hard_timeout=10,
+ priority=6000,
+ buffer_id=50,
+ out_port=6,
+ out_group=8,
+ flags=0,
+ importance=0xaabb,
+ match=ofp.match(oxm_list=[
+ ofp.oxm.in_port_masked(value=4, value_mask=5),
+ ofp.oxm.eth_type(value=0x86dd),
+ ofp.oxm.ip_proto(value=6),
+ ofp.oxm.ipv6_src_masked(
+ value ='\x1C\xCA\xFE\x1C\xB1\x10\x1C\x00\x00\x28\x00\x00\x00\x00\x00\x00',
+ value_mask='\xFF\xFF\xFF\xFF\xFF\xF0\xFF\xFF\x1C\x2C\x3C\x00\x00\x00\x00\x00')
+ ]),
+ instructions=[
+ ofp.instruction.goto_table(table_id=4),
+ ofp.instruction.goto_table(table_id=7)])
+-- java
+builder.setXid(0x12345678)
+ .setCookie(U64.parseHex("FEDCBA9876543210"))
+ .setCookieMask(U64.parseHex("FF00FF00FF00FF00"))
+ .setTableId(TableId.of(3))
+ .setIdleTimeout(5)
+ .setHardTimeout(10)
+ .setPriority(6000)
+ .setBufferId(OFBufferId.of(50))
+ .setOutPort(OFPort.of(6))
+ .setOutGroup(OFGroup.of(8))
+ .setFlags(ImmutableSet.<OFFlowModFlags>of())
+ .setImportance(0xaabb)
+ .setMatch(
+ factory.buildMatch()
+ .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
+ .setExact(MatchField.ETH_TYPE, EthType.IPv6)
+ .setExact(MatchField.IP_PROTO, IpProtocol.TCP)
+ .setMasked(MatchField.IPV6_SRC,
+ IPv6Address.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
+ IPv6Address.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
+ .build()
+ )
+ .setInstructions(
+ ImmutableList.<OFInstruction>of(
+ factory.instructions().gotoTable(TableId.of(4)),
+ factory.instructions().gotoTable(TableId.of(7))
+ )
+ );
diff --git a/test_data/of14/port_desc_stats_reply.data b/test_data/of14/port_desc_stats_reply.data
new file mode 100644
index 0000000..8e38975
--- /dev/null
+++ b/test_data/of14/port_desc_stats_reply.data
@@ -0,0 +1,54 @@
+-- binary
+05 13 # version/type
+00 58 # length
+00 00 00 05 # xid
+00 0d # stats_type
+00 00 # flags
+00 00 00 00 # pad
+00 00 00 01 # entries[0].port_no
+00 48 # entries[0].length
+00 00 # pad
+01 02 03 04 05 06 # entries[0].hw_addr
+00 00 # pad
+69 6e 74 65 72 66 61 63 65 31 32 33 34 35 36 37 # entries[0].name
+00 00 00 60 # entries[0].config
+00 00 00 03 # entries[0].state
+00 00 # entries[0].properties[0].type (ethernet)
+00 20 # entries[0].properties[0].length
+00 00 00 00 # pad
+00 00 00 70 # entries[0].properties[0].curr
+00 00 00 00 # entries[0].properties[0].advertised
+00 00 00 00 # entries[0].properties[0].supported
+00 00 00 00 # entries[0].properties[0].peer
+00 00 00 00 # entries[0].properties[0].curr_speed
+00 00 00 80 # entries[0].properties[0].max_speed
+-- python
+ofp.message.port_desc_stats_reply(
+ xid=5, flags=0, entries=[
+ ofp.port_desc(
+ port_no=1,
+ hw_addr=[1,2,3,4,5,6],
+ name="interface1234567",
+ config=0x60,
+ state=0x03,
+ properties=[
+ ofp.port_desc_prop.ethernet(
+ curr=0x70,
+ max_speed=0x80)])])
+-- java
+builder
+ .setXid(5)
+ .setFlags(ImmutableSet.<OFStatsReplyFlags>of())
+ .setEntries(ImmutableList.of(
+ factory.buildPortDesc()
+ .setPortNo(OFPort.of(1))
+ .setHwAddr(MacAddress.of("01:02:03:04:05:06"))
+ .setName("interface1234567")
+ .setConfig(Sets.immutableEnumSet(OFPortConfig.NO_FWD, OFPortConfig.NO_PACKET_IN))
+ .setState(Sets.immutableEnumSet(OFPortState.LINK_DOWN, OFPortState.BLOCKED))
+ .setProperties(ImmutableList.<OFPortDescProp>of(factory.buildPortDescPropEthernet()
+ .setCurr(0x70)
+ .setMaxSpeed(0x80)
+ .build()))
+ .build())
+ );
diff --git a/test_data/of14/port_stats_reply.data b/test_data/of14/port_stats_reply.data
new file mode 100644
index 0000000..0ff4902
--- /dev/null
+++ b/test_data/of14/port_stats_reply.data
@@ -0,0 +1,104 @@
+-- binary
+05 13 # version/type
+00 d8 # length
+00 00 00 05 # xid
+00 04 # stats_type
+00 00 # flags
+00 00 00 00 # pad
+00 78 # entries[0].length
+00 00 # pad
+00 00 00 01 # entries[0].port_no
+00 00 00 00 # entries[0].duration_sec
+00 00 00 00 # entries[0].duration_nsec
+00 00 00 00 00 00 00 01 # entries[0].rx_packets
+00 00 00 00 00 00 00 00 # entries[0].tx_packets
+00 00 00 00 00 00 00 00 # entries[0].rx_bytes
+00 00 00 00 00 00 00 00 # entries[0].tx_bytes
+00 00 00 00 00 00 00 00 # entries[0].rx_dropped
+00 00 00 00 00 00 00 00 # entries[0].tx_dropped
+00 00 00 00 00 00 00 00 # entries[0].rx_errors
+00 00 00 00 00 00 00 02 # entries[0].tx_errors
+00 00 # entries[0].properties[0].type (ethernet)
+00 28 # entries[0].properties[0].length
+00 00 00 00 # pad
+00 00 00 00 00 00 00 01 # entries[0].properties[0].rx_frame_err
+00 00 00 00 00 00 00 02 # entries[0].properties[0].rx_over_err
+00 00 00 00 00 00 00 03 # entries[0].properties[0].rx_crc_err
+00 00 00 00 00 00 00 04 # entries[0].properties[0].collisions
+00 50 # entries[1].length
+00 00 # pad
+ff ff ff fe # entries[1].port_no
+00 00 00 00 # entries[1].duration_sec
+00 00 00 00 # entries[1].duration_nsec
+00 00 00 00 00 00 00 03 # entries[1].rx_packets
+00 00 00 00 00 00 00 00 # entries[1].tx_packets
+00 00 00 00 00 00 00 00 # entries[1].rx_bytes
+00 00 00 00 00 00 00 00 # entries[1].tx_bytes
+00 00 00 00 00 00 00 00 # entries[1].rx_dropped
+00 00 00 00 00 00 00 00 # entries[1].tx_dropped
+00 00 00 00 00 00 00 00 # entries[1].rx_errors
+00 00 00 00 00 00 00 04 # entries[1].tx_errors
+-- python
+ofp.message.port_stats_reply(
+ xid=5, flags=0, entries=[
+ ofp.port_stats_entry(port_no=1, rx_packets=1, tx_errors=2,
+ properties=[
+ ofp.port_stats_prop.ethernet(
+ rx_frame_err=1,
+ rx_over_err=2,
+ rx_crc_err=3,
+ collisions=4)]),
+ ofp.port_stats_entry(port_no=ofp.OFPP_LOCAL, rx_packets=3, tx_errors=4)])
+-- c
+obj = of_port_stats_reply_new(OF_VERSION_1_4);
+{
+ of_object_t list;
+ of_port_stats_reply_entries_bind(obj, &list);
+ {
+ of_object_t *obj = of_port_stats_entry_new(OF_VERSION_1_4);
+ of_port_stats_entry_port_no_set(obj, 1);
+ of_port_stats_entry_rx_packets_set(obj, 1);
+ of_port_stats_entry_tx_packets_set(obj, 0);
+ of_port_stats_entry_rx_bytes_set(obj, 0);
+ of_port_stats_entry_tx_bytes_set(obj, 0);
+ of_port_stats_entry_rx_dropped_set(obj, 0);
+ of_port_stats_entry_tx_dropped_set(obj, 0);
+ of_port_stats_entry_rx_errors_set(obj, 0);
+ of_port_stats_entry_tx_errors_set(obj, 2);
+
+ /* Append property */
+ {
+ of_object_t list;
+ of_port_stats_entry_properties_bind(obj, &list);
+ {
+ of_object_t *obj = of_port_stats_prop_ethernet_new(OF_VERSION_1_4);
+ of_port_stats_prop_ethernet_rx_frame_err_set(obj, 1);
+ of_port_stats_prop_ethernet_rx_over_err_set(obj, 2);
+ of_port_stats_prop_ethernet_rx_crc_err_set(obj, 3);
+ of_port_stats_prop_ethernet_collisions_set(obj, 4);
+ of_list_append(&list, obj);
+ of_object_delete(obj);
+ }
+ }
+
+
+ of_list_append(&list, obj);
+ of_object_delete(obj);
+ }
+ {
+ of_object_t *obj = of_port_stats_entry_new(OF_VERSION_1_4);
+ of_port_stats_entry_port_no_set(obj, OF_PORT_DEST_LOCAL);
+ of_port_stats_entry_rx_packets_set(obj, 3);
+ of_port_stats_entry_tx_packets_set(obj, 0);
+ of_port_stats_entry_rx_bytes_set(obj, 0);
+ of_port_stats_entry_tx_bytes_set(obj, 0);
+ of_port_stats_entry_rx_dropped_set(obj, 0);
+ of_port_stats_entry_tx_dropped_set(obj, 0);
+ of_port_stats_entry_rx_errors_set(obj, 0);
+ of_port_stats_entry_tx_errors_set(obj, 4);
+ of_list_append(&list, obj);
+ of_object_delete(obj);
+ }
+}
+of_port_stats_reply_flags_set(obj, 0);
+of_port_stats_reply_xid_set(obj, 5);
diff --git a/test_data/of14/port_status.data b/test_data/of14/port_status.data
new file mode 100644
index 0000000..9fb5bde
--- /dev/null
+++ b/test_data/of14/port_status.data
@@ -0,0 +1,72 @@
+-- binary
+05 0c # version, type
+00 58 # length
+12 34 56 78 # xid
+02 # reason
+00 00 00 00 00 00 00 # pad
+00 00 00 04 # port_no
+00 48 # length
+00 00 # pad
+01 02 03 04 05 06 # hw_addr
+00 00 # pad
+66 6f 6f 00 00 00 00 00 # name
+00 00 00 00 00 00 00 00 # ...
+00 00 00 24 # config
+00 00 00 02 # state
+00 00 # properties[0].type (ethernet)
+00 20 # properties[0].length
+00 00 00 00 # pad
+00 00 00 01 # properties[0].curr
+00 00 00 02 # properties[0].advertised
+00 00 00 04 # properties[0].supported
+00 00 00 08 # properties[0].peer
+00 00 00 0a # properties[0].curr_speed
+00 00 00 14 # properties[0].max_speed
+-- python
+ofp.message.port_status(
+ xid=0x12345678,
+ reason=ofp.OFPPR_MODIFY,
+ desc=ofp.port_desc(
+ port_no=4,
+ hw_addr=[1,2,3,4,5,6],
+ name="foo",
+ config=ofp.OFPPC_NO_FWD|ofp.OFPPC_NO_RECV,
+ state=ofp.OFPPS_BLOCKED,
+ properties=[
+ ofp.port_desc_prop.ethernet(
+ curr=ofp.OFPPF_10MB_HD,
+ advertised=ofp.OFPPF_10MB_FD,
+ supported=ofp.OFPPF_100MB_HD,
+ peer=ofp.OFPPF_100MB_FD,
+ curr_speed=10,
+ max_speed=20)]))
+-- c
+obj = of_port_status_new(OF_VERSION_1_4);
+of_port_status_xid_set(obj, 0x12345678);
+of_port_status_reason_set(obj, OF_PORT_CHANGE_REASON_MODIFY);
+{
+ of_object_t desc;
+ of_port_status_desc_bind(obj, &desc);
+ of_port_desc_port_no_set(&desc, 4);
+ of_mac_addr_t hw_addr = { { 1, 2, 3, 4, 5, 6 } };
+ of_port_desc_hw_addr_set(&desc, hw_addr);
+ of_port_name_t name = "foo";
+ of_port_desc_name_set(&desc, name);
+ of_port_desc_config_set(&desc, OF_PORT_CONFIG_FLAG_NO_FWD|OF_PORT_CONFIG_FLAG_NO_RECV);
+ of_port_desc_state_set(&desc, OF_PORT_STATE_FLAG_BLOCKED);
+ {
+ of_list_port_desc_prop_t list;
+ of_port_desc_properties_bind(&desc, &list);
+ {
+ of_object_t *obj = of_port_desc_prop_ethernet_new(OF_VERSION_1_4);
+ of_port_desc_prop_ethernet_curr_set(obj, OF_PORT_FEATURE_FLAG_10MB_HD);
+ of_port_desc_prop_ethernet_advertised_set(obj, OF_PORT_FEATURE_FLAG_10MB_FD);
+ of_port_desc_prop_ethernet_supported_set(obj, OF_PORT_FEATURE_FLAG_100MB_HD);
+ of_port_desc_prop_ethernet_peer_set(obj, OF_PORT_FEATURE_FLAG_100MB_FD);
+ of_port_desc_prop_ethernet_curr_speed_set(obj, 10);
+ of_port_desc_prop_ethernet_max_speed_set(obj, 20);
+ of_list_append(&list, obj);
+ of_object_delete(obj);
+ }
+ }
+}
diff --git a/wireshark_gen/__init__.py b/wireshark_gen/__init__.py
index a610f3f..75918f8 100644
--- a/wireshark_gen/__init__.py
+++ b/wireshark_gen/__init__.py
@@ -38,7 +38,7 @@
DissectorField = namedtuple("DissectorField", ["fullname", "name", "type", "base", "enum_table"])
-proto_names = { 1: 'of10', 2: 'of11', 3: 'of12', 4: 'of13' }
+proto_names = { 1: 'of10', 2: 'of11', 3: 'of12', 4: 'of13', 5: 'of14' }
def make_field_name(version, ofclass_name, member_name):
return "%s.%s.%s" % (proto_names[version.wire_version],
ofclass_name[3:],
diff --git a/wireshark_gen/templates/_oftype_readers.lua b/wireshark_gen/templates/_oftype_readers.lua
index f7eb79c..ad0f0c2 100644
--- a/wireshark_gen/templates/_oftype_readers.lua
+++ b/wireshark_gen/templates/_oftype_readers.lua
@@ -49,6 +49,10 @@
read_scalar(reader, subtree, field_name, 16)
end
+function read_of_bitmap_512_t(reader, version, subtree, field_name)
+ read_scalar(reader, subtree, field_name, 64)
+end
+
function read_of_checksum_128_t(reader, version, subtree, field_name)
read_scalar(reader, subtree, field_name, 16)
end
@@ -68,8 +72,12 @@
dissect_of_match_v1_v1(reader, subtree:add("of_match"))
elseif version == 2 then
dissect_of_match_v2_v2(reader, subtree:add("of_match"))
- elseif version >= 3 then
+ elseif version == 3 then
dissect_of_match_v3_v3(reader, subtree:add("of_match"))
+ elseif version == 4 then
+ dissect_of_match_v3_v4(reader, subtree:add("of_match"))
+ else
+ error("Unsupported match version")
end
end
diff --git a/wireshark_gen/templates/openflow.lua b/wireshark_gen/templates/openflow.lua
index 9ce51d2..f96fccf 100644
--- a/wireshark_gen/templates/openflow.lua
+++ b/wireshark_gen/templates/openflow.lua
@@ -52,7 +52,7 @@
:: for version, ofproto in ir.items():
:: for enum in ofproto.enums:
-local enum_v${version.wire_version}_${enum.name} = {
+enum_v${version.wire_version}_${enum.name} = {
:: for (name, value) in enum.values:
[${value}] = "${name}",
:: #endfor
@@ -159,8 +159,8 @@
local msg_len = buf(offset+2,2):uint()
-- Detect obviously broken messages
- if msg_version == 0 or msg_version > 4 then break end
- if msg_type > 29 then break end
+ if msg_version == 0 or msg_version > 5 then break end
+ if msg_type > 34 then break end
if msg_len < 8 then break end
if offset + msg_len > buf:len() then