Merge into master from pull request #239:
loci: only mask partially wildcarded fields (https://github.com/floodlight/loxigen/pull/239)
diff --git a/.gitignore b/.gitignore
index c0b10be..f4243d4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,5 @@
*.cache
openflowj-loxi
/bin
+*,cover
+/.coverage
diff --git a/Makefile b/Makefile
index 3767fba..018db0b 100644
--- a/Makefile
+++ b/Makefile
@@ -142,4 +142,13 @@
ctags:
ctags ${LOXI_PY_FILES} ${LOXI_TEMPLATE_FILES} ${INPUT_FILES} ${TEST_DATA}
-.PHONY: all clean debug check pylint c python
+coverage:
+ find -name '*,cover' -exec rm {} \;
+ coverage erase
+ coverage run -a ./loxigen.py --lang=c
+ coverage run -a ./loxigen.py --lang=python
+ coverage run -a ./loxigen.py --lang=java
+ coverage run -a ./loxigen.py --lang=wireshark
+ coverage annotate -i --omit tenjin.py,pyparsing.py
+
+.PHONY: all clean debug check pylint c python coverage
diff --git a/c_gen/build_of_g.py b/c_gen/build_of_g.py
index f117bfd..4d37b36 100755
--- a/c_gen/build_of_g.py
+++ b/c_gen/build_of_g.py
@@ -153,6 +153,16 @@
# 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:
@@ -281,10 +291,6 @@
for cls in of_g.ordered_list_objects:
of_g.unified[cls]["object_id"] = of_g.object_id
of_g.object_id += 1
- for cls in of_g.ordered_pseudo_objects:
- of_g.unified[cls] = {}
- of_g.unified[cls]["object_id"] = of_g.object_id
- of_g.object_id += 1
def initialize_versions():
@@ -330,7 +336,10 @@
else:
# HACK the C backend does not yet support of_oxm_t
if m.oftype == 'of_oxm_t':
- m_type = 'of_octets_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'
else:
enum = find(lambda e: e.name == m.oftype, protocol.enums)
if enum and "wire_type" in enum.params:
@@ -466,70 +475,3 @@
classes = versions[version]["classes"]
for cls in of_g.ordered_classes[wire_version]:
add_class(wire_version, cls, classes[cls])
-
-
-def log_all_class_info():
- """
- Log the results of processing the input
-
- Debug function
- """
-
- for cls in of_g.unified:
- for v in of_g.unified[cls]:
- if type(v) == type(0):
- log("cls: %s. ver: %d. base len %d. %s" %
- (str(cls), v, of_g.base_length[(cls, v)],
- loxi_utils.class_is_var_len(cls,v) and "not fixed"
- or "fixed"))
- if "use_version" in of_g.unified[cls][v]:
- log("cls %s: v %d mapped to %d" % (str(cls), v,
- of_g.unified[cls][v]["use_version"]))
- if "members" in of_g.unified[cls][v]:
- for member in of_g.unified[cls][v]["members"]:
- log(" %-20s: type %-20s. offset %3d" %
- (member["name"], member["m_type"],
- member["offset"]))
-
-def generate_all_files():
- """
- Create the files for the language target
- """
- for (name, fn) in lang_module.targets.items():
- path = of_g.options.install_dir + '/' + name
- os.system("mkdir -p %s" % os.path.dirname(path))
- with open(path, "w") as outfile:
- fn(outfile, os.path.basename(name))
- print("Wrote contents for " + name)
-
-if __name__ == '__main__':
- of_g.loxigen_log_file = open("loxigen.log", "w")
- of_g.loxigen_dbg_file = sys.stdout
-
- of_g.process_commandline()
- # @fixme Use command line params to select log
-
- if not config_sanity_check():
- debug("Config sanity check failed\n")
- sys.exit(1)
-
- # Import the language file
- lang_file = "lang_%s" % of_g.options.lang
- lang_module = __import__(lang_file)
-
- # If list files, just list auto-gen files to stdout and exit
- if of_g.options.list_files:
- for name in lang_module.targets:
- print of_g.options.install_dir + '/' + name
- sys.exit(0)
-
- log("\nGenerating files for target language %s\n" % of_g.options.lang)
-
- initialize_versions()
- read_input()
- populate_type_maps()
- analyze_input()
- unify_input()
- order_and_assign_object_ids()
- log_all_class_info()
- generate_all_files()
diff --git a/c_gen/c_code_gen.py b/c_gen/c_code_gen.py
index 81f5a1a..3fa4f3a 100644
--- a/c_gen/c_code_gen.py
+++ b/c_gen/c_code_gen.py
@@ -306,20 +306,6 @@
log("Generated %d identifiers" % (count - 1))
out.write("\n#endif /* Loci identifiers header file */\n")
-def base_h_external(out, filename):
- """
- Copy contents of external file to base header
-
- The contents of the filename are copied literally into the
- out file handler. This allows openflow common defines to
- be entered into the LoxiGen code base. The content of this
- code must depend only on standard C headers.
- """
- infile = open(filename, "r")
- contents = infile.read()
- out.write(contents)
- infile.close()
-
def match_h_gen(out, name):
"""
Generate code for
@@ -330,7 +316,6 @@
c_match.gen_incompat_members(out)
c_match.gen_match_struct(out)
c_match.gen_match_comp(out)
-# c_match.gen_match_accessors(out)
out.write("\n#endif /* Match header file */\n")
def top_h_gen(out, name):
@@ -375,7 +360,7 @@
* Treat as private
*/
#define OF_OBJECT_TO_MESSAGE(obj) \\
- ((of_message_t)(WBUF_BUF((obj)->wire_object.wbuf)))
+ ((of_message_t)(WBUF_BUF((obj)->wbuf)))
/**
* Macro for the fixed length part of an object
@@ -469,8 +454,8 @@
*/
#define OF_LENGTH_CHECK_ASSERT(obj) \\
LOCI_ASSERT(((obj)->parent != NULL) || \\
- ((obj)->wire_object.wbuf == NULL) || \\
- (WBUF_CURRENT_BYTES((obj)->wire_object.wbuf) == (obj)->length))
+ ((obj)->wbuf == NULL) || \\
+ (WBUF_CURRENT_BYTES((obj)->wbuf) == (obj)->length))
#define OF_DEBUG_DUMP
#if defined(OF_DEBUG_DUMP)
@@ -803,6 +788,7 @@
#include <loci/of_match.h>
#include <loci/of_object.h>
#include <loci/loci_classes.h>
+#include <loci/loci_class_metadata.h>
/****************************************************************
*
@@ -908,12 +894,6 @@
of_g.unified[cls]["object_id"]))
last = of_g.unified[cls]["object_id"]
- out.write("\n /* Generic stats request/reply types; pseudo objects */\n")
- for cls in of_g.ordered_pseudo_objects:
- out.write(" %s = %d,\n" % (enum_name(cls),
- of_g.unified[cls]["object_id"]))
- last = of_g.unified[cls]["object_id"]
-
out.write("""
OF_OBJECT_COUNT = %d
} of_object_id_t;
@@ -1037,23 +1017,6 @@
sys.exit(1)
return params
-def typed_function_base(cls, m_name):
- """
- Generate the core name for accessors based on the type
- @param cls The class name
- @param m_name The member name
- """
- (m_type, get_rv) = get_acc_rv(cls, m_name)
- return "%s_%s" % (cls, m_type)
-
-def member_function_base(cls, m_name):
- """
- Generate the core name for accessors based on the member name
- @param cls The class name
- @param m_name The member name
- """
- return "%s_%s" % (cls, m_name)
-
def field_ver_get(cls, m_name):
"""
Generate a dict, indexed by wire version, giving a pair (type, offset)
@@ -1106,13 +1069,6 @@
#
################################################################
-
-def gen_of_object_defs(out):
- """
- Generate low level of_object core operations
- @param out The file for output, already open
- """
-
def gen_generics(out):
for (cls, subclasses) in type_maps.inheritance_map.items():
out.write("""
@@ -1313,58 +1269,6 @@
}
""" % dict(cls=cls, e_type=e_type, u_type=enum_name(e_type), len_str=len_str))
-
-def gen_bind(out, cls, m_name, m_type):
- """
- Generate the body of a bind function
- @param out The file to which to write
- @param cls The class name for which code is being generated
- @param m_name The name of the data member
- @param m_type The type of the data member
- """
-
- bparams = ",\n ".join(param_list(cls, m_name, "bind"))
-
- i_call = init_call(e_type, "child", "parent->version", "0", "1")
-
- out.write("""
-/**
- * Bind the child object to the parent object for read processing
- * @param parent The parent object
- * @param child The child object
- *
- * The child obj instance is completely initialized.
- */
-
-int
-%(cls)s_%(m_name)_bind(%(cls)s_t *parent,
- %(e_type)s_t *child)
-{
- int rv;
-
- %(i_call)s;
-
- /* Derive offset and length of child in parent */
- OF_TRY(of_object_child_attach(parent, child,
- if ((rv = of_list_first((of_object_t *)list, (of_object_t *)obj)) < 0) {
- return rv;
- }
-""" % dict(cls=cls, e_type=e_type, i_call=i_call))
-
- # Special case flow_stats_entry lists
-
- out.write("""
- rv = of_object_wire_init((of_object_t *) obj, %(u_type)s,
- list->length);
- if ((rv == OF_ERROR_NONE) && (%(len_str)s == 0)) {
- return OF_ERROR_PARSE;
- }
-
- return rv;
-}
-""" % dict(cls=cls, e_type=e_type, u_type=enum_name(e_type), len_str=len_str))
-
-
def gen_list_next(out, cls, e_type):
"""
Generate the body of a list_next operation
@@ -1670,15 +1574,36 @@
match_octets.data = OF_OBJECT_BUFFER_INDEX(obj, offset);
OF_TRY(of_match_deserialize(ver, %(m_name)s, &match_octets));
""" % dict(m_name=m_name))
+ elif m_type == "of_oxm_header_t":
+ out.write("""
+ /* Initialize child */
+ %(m_type)s_init(%(m_name)s, obj->version, 0, 1);
+ /* Attach to parent */
+ %(m_name)s->parent = (of_object_t *)obj;
+ %(m_name)s->wbuf = obj->wbuf;
+ %(m_name)s->obj_offset = abs_offset;
+ %(m_name)s->length = 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":
+ out.write("""
+ /* Initialize child */
+ %(m_type)s_init(%(m_name)s, obj->version, 0, 1);
+ /* Attach to parent */
+ %(m_name)s->parent = (of_object_t *)obj;
+ %(m_name)s->wbuf = obj->wbuf;
+ %(m_name)s->obj_offset = abs_offset;
+ %(m_name)s->length = cur_len;
+ of_object_wire_init(%(m_name)s, OF_BSN_VPORT, 0);
+""" % dict(m_type=m_type[:-2], m_name=m_name))
else:
out.write("""
/* Initialize child */
%(m_type)s_init(%(m_name)s, obj->version, 0, 1);
/* Attach to parent */
%(m_name)s->parent = (of_object_t *)obj;
- %(m_name)s->wire_object.wbuf = obj->wire_object.wbuf;
- %(m_name)s->wire_object.obj_offset = abs_offset;
- %(m_name)s->wire_object.owned = 0;
+ %(m_name)s->wbuf = obj->wbuf;
+ %(m_name)s->obj_offset = abs_offset;
%(m_name)s->length = cur_len;
""" % dict(m_type=m_type[:-2], m_name=m_name))
@@ -1720,7 +1645,7 @@
out.write("""
new_len = %(m_name)s->length;
/* If underlying buffer already shared; nothing to do */
- if (obj->wire_object.wbuf == %(m_name)s->wire_object.wbuf) {
+ if (obj->wbuf == %(m_name)s->wbuf) {
of_wire_buffer_grow(wbuf, abs_offset + new_len);
/* Verify that the offsets are correct */
LOCI_ASSERT(abs_offset == OF_OBJECT_ABSOLUTE_OFFSET(%(m_name)s, 0));
@@ -1752,9 +1677,7 @@
elif m_type not in ["of_match_t", "of_octets_t"]:
out.write("""
/* @fixme Shouldn't this precede copying value's data to buffer? */
- if (%(m_name)s->wire_length_set != NULL) {
- %(m_name)s->wire_length_set((of_object_t *)%(m_name)s, %(m_name)s->length);
- }
+ of_object_wire_length_set((of_object_t *)%(m_name)s, %(m_name)s->length);
""" % dict(m_name=m_name))
out.write("""
/* Not scalar, update lengths if needed */
@@ -1985,20 +1908,6 @@
#
################################################################
-
-################################################################
-# First, some utility functions for new/delete
-################################################################
-
-def del_function_proto(cls):
- """
- Return the prototype for the delete operator for the given class
- @param cls The class name
- """
- fn = "void\n"
- return fn
-
-
################################################################
# Routines to generate the body of new/delete functions
################################################################
@@ -2058,15 +1967,14 @@
obj->length = bytes;
obj->object_id = %(enum)s;
""" % dict(cls=cls, enum=enum_name(cls)))
- gen_coerce_ops(out, cls)
out.write("""
/* Grow the wire buffer */
- if (obj->wire_object.wbuf != NULL) {
+ if (obj->wbuf != NULL) {
int tot_bytes;
- tot_bytes = bytes + obj->wire_object.obj_offset;
- of_wire_buffer_grow(obj->wire_object.wbuf, tot_bytes);
+ tot_bytes = bytes + obj->obj_offset;
+ of_wire_buffer_grow(obj->wbuf, tot_bytes);
}
}
@@ -2117,7 +2025,7 @@
if loxi_utils.class_is_u16_len(cls) or cls == "of_packet_queue":
out.write("""
- obj->wire_length_set((of_object_t *)obj, obj->length);
+ of_object_wire_length_set((of_object_t *)obj, obj->length);
""")
if cls == "of_meter_stats":
@@ -2146,6 +2054,10 @@
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"
+
out.write("""
/**
* Create a new %(cls)s object
@@ -2170,13 +2082,12 @@
bytes = of_object_fixed_len[version][%(enum)s] + of_object_extra_len[version][%(enum)s];
- /* Allocate a maximum-length wire buffer assuming we'll be appending to it. */
- if ((obj = (%(cls)s_t *)of_object_new(OF_WIRE_BUFFER_MAX_LENGTH)) == NULL) {
+ if ((obj = (%(cls)s_t *)of_object_new(%(max_length)s)) == NULL) {
return NULL;
}
%(cls)s_init(obj, version, bytes, 0);
-""" % dict(cls=cls, enum=enum_name(cls)))
+""" % 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) {
@@ -2329,99 +2240,6 @@
****************************************************************/
""")
-#
-# @fixme Not clear that these should all be set for virtual fns
-#
-# @fixme Clean up. should have a (language specific) map from class
-# to length and type get/set functions
-#
-
-def gen_coerce_ops(out, cls):
- out.write("""
- /* Set up the object's function pointers */
-""")
-
- uclass = loxi_globals.unified.class_by_name(cls)
- if uclass and not uclass.virtual and uclass.has_type_members:
- out.write("""
- obj->wire_type_set = %(cls)s_push_wire_types;
-""" % dict(cls=cls))
-
- if loxi_utils.class_is_message(cls):
- out.write("""
- obj->wire_length_get = of_object_message_wire_length_get;
- obj->wire_length_set = of_object_message_wire_length_set;
-""")
- else:
- if loxi_utils.class_is_tlv16(cls):
- if not (cls in type_maps.inheritance_map): # Don't set for super
- out.write("""
- obj->wire_length_set = of_tlv16_wire_length_set;
-""")
- out.write("""
- obj->wire_length_get = of_tlv16_wire_length_get;
-""")
- if loxi_utils.class_is_action(cls):
- out.write("""
- obj->wire_type_get = of_action_wire_object_id_get;
-""")
- if loxi_utils.class_is_action_id(cls):
- out.write("""
- obj->wire_type_get = of_action_id_wire_object_id_get;
-""")
- if loxi_utils.class_is_instruction(cls):
- out.write("""
- obj->wire_type_get = of_instruction_wire_object_id_get;
-""")
- if loxi_utils.class_is_instruction_id(cls):
- out.write("""
- obj->wire_type_get = of_instruction_id_wire_object_id_get;
-""")
- if loxi_utils.class_is_queue_prop(cls):
- out.write("""
- obj->wire_type_get = of_queue_prop_wire_object_id_get;
-""")
- if loxi_utils.class_is_table_feature_prop(cls):
- out.write("""
- obj->wire_type_get = of_table_feature_prop_wire_object_id_get;
-""")
- if loxi_utils.class_is_meter_band(cls):
- out.write("""
- obj->wire_type_get = of_meter_band_wire_object_id_get;
-""")
- if loxi_utils.class_is_hello_elem(cls):
- out.write("""
- obj->wire_type_get = of_hello_elem_wire_object_id_get;
-""")
- if loxi_utils.class_is_bsn_tlv(cls):
- out.write("""
- obj->wire_type_get = of_bsn_tlv_wire_object_id_get;
-""")
- if loxi_utils.class_is_oxm(cls):
- out.write("""
- obj->wire_length_get = of_oxm_wire_length_get;
- obj->wire_type_get = of_oxm_wire_object_id_get;
-""")
- if loxi_utils.class_is_u16_len(cls):
- out.write("""
- obj->wire_length_get = of_u16_len_wire_length_get;
- obj->wire_length_set = of_u16_len_wire_length_set;
-""")
- if cls == "of_packet_queue":
- out.write("""
- obj->wire_length_get = of_packet_queue_wire_length_get;
- obj->wire_length_set = of_packet_queue_wire_length_set;
-""")
-# if cls == "of_list_meter_band_stats":
-# out.write("""
-# obj->wire_length_get = of_list_meter_band_stats_wire_length_get;
-#""")
- if cls == "of_meter_stats":
- out.write("""
- obj->wire_length_get = of_meter_stats_wire_length_get;
- obj->wire_length_set = of_meter_stats_wire_length_set;
-""")
-
def gen_new_function_definitions(out, cls):
"""
Generate the new operator for all classes
@@ -2502,201 +2320,3 @@
""" % dict(cls=cls))
out.write("#endif /* _LOCI_DOC_H_ */\n")
-
-################################################################
-#
-# For fun, here are some unified, traditional C structure representation
-#
-################################################################
-
-def gen_cof_to_wire(out):
- pass
-
-def gen_wire_to_cof(out):
- pass
-
-def gen_cof_instance(out, cls):
- out.write("struct c%s_s {\n" % cls)
- for m in of_g.ordered_members[cls]:
- if m in of_g.skip_members:
- continue
- entry = of_g.unified[cls]["union"][m]
- cof_type = type_to_cof_type(entry["m_type"])
- out.write(" %-20s %s;\n" % (cof_type, m))
- out.write("};\n\n");
-
-def gen_cof_structs(out):
- """
- Generate non-version specific (common) representation of structures
-
- @param out The file to which to write the functions
- """
-
- out.write("\n/* Common, unified OpenFlow structure representations */\n")
- for cls in of_g.standard_class_order:
- if cls in type_maps.inheritance_map:
- continue
- gen_cof_instance(out, cls)
-
-################################################################
-#
-# Generate code samples for applications.
-#
-################################################################
-
-def gen_code_samples(out, name):
- out.write("""
-#if 0 /* Do not compile in */
-/**
- * @file %(name)s
- *
- * These are code samples for inclusion in other components
- */
-
-""" % dict(name=name))
-
- gen_jump_table_template(out)
- # These are messages that a switch might expect.
- msg_list = ["of_echo_request",
- "of_hello",
- "of_packet_in",
- "of_packet_out",
- "of_port_mod",
- "of_port_stats_request",
- "of_queue_get_config_request",
- "of_queue_stats_request",
- "of_flow_add",
- "of_flow_modify",
- "of_flow_modify_strict",
- "of_flow_delete",
- "of_flow_delete_strict",
- "of_get_config_request",
- "of_flow_stats_request",
- "of_barrier_request",
- "of_echo_reply",
- "of_aggregate_stats_request",
- "of_desc_stats_request",
- "of_table_stats_request",
- "of_features_request",
- "of_table_mod",
- "of_set_config",
- "of_experimenter",
- "of_experimenter_stats_request",
- "of_group_desc_stats_request",
- "of_group_features_stats_request",
- "of_role_request"]
-
- gen_message_handler_templates(out, msgs=msg_list)
-
- out.write("""
-#endif
-""")
-
-def gen_jump_table_template(out=sys.stdout, all_unhandled=True,
- cxn_type="ls_cxn_handle_t",
- unhandled="unhandled_message"):
- """
- Generate a template for a jump table.
- @param out The file to which to write the functions
- """
- out.write("""
-/*
- * Simple jump table definition for message handling
- */
-typedef int (*msg_handler_f)(%(cxn_type)s cxn, of_object_t *obj);
-typedef msg_handler_f msg_jump_table_t[OF_MESSAGE_OBJECT_COUNT];
-
-/* Jump table template for message objects */
-extern msg_jump_table_t jump_table;
-
-/* C-code template */
-msg_jump_table_t jump_table = {
- %(unhandled)s, /* OF_OBJECT; place holder for generic object */
-""" % dict(unhandled=unhandled, cxn_type=cxn_type))
- count = 0
- fn_name = unhandled
- for cls in of_g.ordered_messages:
- comma = ","
- count += 1
- if count == len(of_g.ordered_messages):
- comma = " "
- if not all_unhandled:
- fn_name = "%s_handler" % cls[3:]
- out.write(" %s%s /* %s */\n" % (fn_name, comma, enum_name(cls)))
-
- out.write("};\n")
-
-def gen_message_switch_stmt_tmeplate(out=sys.stdout, all_unhandled=True,
- cxn_type="ls_cxn_handle_t",
- unhandled="unhandled_message"):
- out.write("""
-/*
- * Simple switch statement for message handling
- */
-
- switch (obj->object_id):
-""")
- fn_name = unhandled
- for cls in of_g.ordered_messages:
- if not all_unhandled:
- fn_name = "%s_handler" % cls[3:]
- out.write("""
- case %(enum)s:
- rv = %(fn_name)s(cxn, obj);
- break;
-""" % dict(fn_name=fn_name, cls=cls, enum=enum_name(cls)))
- out.write("""
- default:
- rv = LS_ERROR_PARAM;
- break;
- }
-
- TRACE("Handled msg %p with rv %d (%s)", obj, rv, ls_error_strings[rv]);
-
- return rv;
-""")
-
-
-def gen_message_handler_templates(out=sys.stdout, cxn_type="ls_cxn_handle_t",
- unhandled="unhandled_message", msgs=None):
- gen_jump_table_template(out, False, cxn_type)
- out.write("""
-/**
- * Function for unhandled message
- */
-static int
-unhandled_message(%(cxn_type)s cxn, of_object_t *obj)
-{
- (void)cxn;
- (void)obj;
- TRACE("Unhandled message %%p. Object id %%d", obj, obj->object_id);
-
- return LS_ERROR_UNAVAIL;
-}
-""" % dict(unhandled=unhandled, cxn_type=cxn_type))
-
- if not msgs:
- msgs = of_g.ordered_messages
- for cls in msgs:
- out.write("""
-/**
- * Handle a %(s_cls)s message
- * @param cxn Connection handler for the owning connection
- * @param _obj Generic type object for the message to be coerced
- * @returns Error code
- */
-
-static int
-%(s_cls)s_handler(%(cxn_type)s cxn, of_object_t *_obj)
-{
- %(cls)s_t *obj;
-
- TRACE("Handling %(cls)s message: %%p.", obj);
- obj = (%(cls)s_t *)_obj;
-
- /* Handle object of type %(cls)s_t */
-
- return LS_ERROR_NONE;
-}
-""" % dict(s_cls=cls[3:], cls=cls, cxn_type=cxn_type))
- gen_message_switch_stmt_tmeplate(out, False, cxn_type)
diff --git a/c_gen/c_dump_gen.py b/c_gen/c_dump_gen.py
index a0af14e..d4a016c 100644
--- a/c_gen/c_dump_gen.py
+++ b/c_gen/c_dump_gen.py
@@ -86,9 +86,6 @@
""")
- type_to_emitter = dict(
-
- )
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):
diff --git a/c_gen/c_match.py b/c_gen/c_match.py
index b5ef80a..7fd6a21 100644
--- a/c_gen/c_match.py
+++ b/c_gen/c_match.py
@@ -622,7 +622,6 @@
/* For each active member, add an OXM entry to the list */
""")
for key in match.match_keys_sorted:
- entry = match.of_match_members[key]
out.write("""\
if (OF_MATCH_MASK_%(ku)s_ACTIVE_TEST(src)) {
if (!OF_MATCH_MASK_%(ku)s_EXACT_TEST(src)) {
@@ -874,7 +873,8 @@
of_match_v%(version)s_delete(wire_match);
return rv;
}
- octets->bytes = OF_MATCH_BYTES(wire_match->length);
+ of_wire_buffer_grow(wire_match->wbuf, OF_MATCH_BYTES(wire_match->length));
+ octets->bytes = wire_match->wbuf->current_bytes;
of_object_wire_buffer_steal((of_object_t *)wire_match,
&octets->data);
of_match_v%(version)s_delete(wire_match);
@@ -929,7 +929,7 @@
/* Free the wire buffer control block without freeing
* octets->bytes. */
- of_wire_buffer_steal(wire_match.wire_object.wbuf, &tmp);
+ of_wire_buffer_steal(wire_match.wbuf, &tmp);
}
break;
""" % dict(version=version, ver_name=of_g.of_version_wire2name[version]))
diff --git a/c_gen/c_show_gen.py b/c_gen/c_show_gen.py
index fc3edb8..9d84477 100644
--- a/c_gen/c_show_gen.py
+++ b/c_gen/c_show_gen.py
@@ -87,9 +87,6 @@
""")
- type_to_emitter = dict(
-
- )
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):
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index 6cc9612..8537f66 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -99,6 +99,8 @@
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",
# BSN extensions
of_bsn_vport_q_in_q_t="vport",
of_bitmap_128_t="bitmap_128",
@@ -348,7 +350,6 @@
extern int run_scalar_acc_tests(void);
extern int run_list_tests(void);
extern int run_message_tests(void);
-extern int run_setup_from_add_tests(void);
extern int run_validator_tests(void);
@@ -384,9 +385,6 @@
for version in of_g.of_version_range:
for cls in of_g.ordered_list_objects:
- if cls in type_maps.inheritance_map:
- continue
-
if version in of_g.unified[cls]:
out.write("""
extern int
@@ -565,10 +563,10 @@
if not type_maps.class_is_virtual(cls):
out.write("""
- if (obj->wire_length_get != NULL) {
+ if (loci_class_metadata[obj->object_id].wire_length_get != NULL) {
int length;
- obj->wire_length_get((of_object_t *)obj, &length);
+ loci_class_metadata[obj->object_id].wire_length_get((of_object_t *)obj, &length);
TEST_ASSERT(length == %(length)d);
}
@@ -692,7 +690,7 @@
# Helper function to set up a subclass instance for a test
-def setup_instance(out, cls, subcls, instance, v_name, inst_len, version):
+def setup_instance(out, cls, subcls, instance, v_name, version):
base_type = loxi_utils.list_to_entry_type(cls)
setup_template = """
%(subcls)s_init(%(inst)s, %(v_name)s, -1, 1);
@@ -709,23 +707,11 @@
for i in range(2):
out.write(setup_template %
dict(inst=instance, subcls=subcls, v_name=v_name,
- base_type=base_type, cls=cls, inst_len=inst_len,
+ base_type=base_type, cls=cls,
version=version))
-def check_instance(out, cls, subcls, instance, v_name, inst_len, version, last):
- check_template = ""
- if inst_len >= 0:
- check_template = """
- TEST_ASSERT(%(inst)s->length == %(inst_len)d);
- if (%(inst)s->wire_length_get != NULL) {
- int length;
-
- %(inst)s->wire_length_get(
- (of_object_t *)&elt, &length);
- TEST_ASSERT(length == %(inst_len)d);
- }
-"""
- check_template += """
+def check_instance(out, cls, subcls, instance, v_name, version, last):
+ check_template = """
TEST_ASSERT(%(inst)s->object_id == %(elt_name)s);
value = %(subcls)s_%(v_name)s_check(
%(inst)s, value);
@@ -734,7 +720,7 @@
out.write("\n /* Check two instances of type %s */" % instance)
out.write(check_template %
- dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
+ dict(elt_name=loxi_utils.enum_name(subcls),
inst=instance, subcls=subcls,
v_name=loxi_utils.version_to_name(version)))
out.write("""\
@@ -742,7 +728,7 @@
""" % dict(cls=cls))
out.write(check_template %
- dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
+ dict(elt_name=loxi_utils.enum_name(subcls),
inst=instance, subcls=subcls,
v_name=loxi_utils.version_to_name(version)))
if last:
@@ -791,12 +777,10 @@
out.write(" %s = &elt.%s;\n" % (instance, instance))
if len(sub_classes) == 0: # No inheritance case
- inst_len = loxi_utils.base_type_to_length(base_type, version)
- setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
+ setup_instance(out, cls, base_type, "elt_p", v_name, version)
else:
for instance, subcls in sub_classes:
- inst_len = of_g.base_length[(subcls, version)]
- setup_instance(out, cls, subcls, instance, v_name, inst_len, version)
+ setup_instance(out, cls, subcls, instance, v_name, version)
out.write("""
return value;
@@ -840,21 +824,12 @@
out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
if len(sub_classes) == 0: # No inheritance case
- if loxi_utils.class_is_var_len(base_type, version):
- inst_len = -1
- else:
- inst_len = loxi_utils.base_type_to_length(base_type, version)
- check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
- version, True)
+ check_instance(out, cls, base_type, "elt_p", v_name, version, True)
else:
count = 0
for instance, subcls in sub_classes:
count += 1
- if loxi_utils.class_is_var_len(subcls, version):
- inst_len = -1
- else:
- inst_len = of_g.base_length[(subcls, version)]
- check_instance(out, cls, subcls, instance, v_name, inst_len,
+ check_instance(out, cls, subcls, instance, v_name,
version, count==len(sub_classes))
out.write("""
@@ -865,9 +840,6 @@
def gen_list_set_check_funs(out):
for version in of_g.of_version_range:
for cls in of_g.ordered_list_objects:
- if cls in type_maps.inheritance_map:
- continue
-
if version in of_g.unified[cls]:
setup_list_fn(out, version, cls)
check_list_fn(out, version, cls)
@@ -939,8 +911,6 @@
*/
""" % v_name)
for cls in of_g.ordered_list_objects:
- if cls in type_maps.inheritance_map:
- continue
if version in of_g.unified[cls]:
list_test(out, version, cls)
@@ -952,8 +922,6 @@
for version in of_g.of_version_range:
v_name = loxi_utils.version_to_name(version)
for cls in of_g.ordered_list_objects:
- if cls in type_maps.inheritance_map:
- continue
if version in of_g.unified[cls]:
test_name = "%s_%s" % (cls, v_name)
out.write(" RUN_TEST(%s);\n" % test_name)
@@ -1221,24 +1189,11 @@
for instance, subcls in sub_classes:
out.write(" %s = &elt.%s;\n" % (instance, instance))
-# if type_maps.class_is_virtual(base_type):
-# out.write("""\
-# TEST_OK(%(base_type)s_header_init(
-# (%(base_type)s_header_t *)&elt, %(v_name)s, -1, 1));
-# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
-# else:
-# out.write("""\
-# TEST_OK(%(base_type)s_init(&elt, %(v_name)s, -1, 1));
-# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
-
if len(sub_classes) == 0: # No inheritance case
- inst_len = loxi_utils.base_type_to_length(base_type, version)
- setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
+ setup_instance(out, cls, base_type, "elt_p", v_name, version)
else:
for instance, subcls in sub_classes:
- inst_len = of_g.base_length[(subcls, version)]
- setup_instance(out, cls, subcls, instance, v_name,
- inst_len, version)
+ setup_instance(out, cls, subcls, instance, v_name, version)
out.write("""
return value;
}
@@ -1284,21 +1239,13 @@
out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
if len(sub_classes) == 0: # No inheritance case
- if loxi_utils.class_is_var_len(base_type, version):
- inst_len = -1
- else:
- inst_len = loxi_utils.base_type_to_length(base_type, version)
- check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
+ check_instance(out, cls, base_type, "elt_p", v_name,
version, True)
else:
count = 0
for instance, subcls in sub_classes:
count += 1
- if loxi_utils.class_is_var_len(subcls, version):
- inst_len = -1
- else:
- inst_len = of_g.base_length[(subcls, version)]
- check_instance(out, cls, subcls, instance, v_name, inst_len,
+ check_instance(out, cls, subcls, instance, v_name,
version, count==len(sub_classes))
out.write("""
""" % dict(base_type=base_type))
@@ -1417,6 +1364,19 @@
FREE(octets.data);
}
""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
+ elif m_type == "of_bsn_vport_t": # FIXME: tests only q_in_q
+ out.write("""\
+ %(var_name)s = %(sub_cls)s_new(%(v_name)s);
+ TEST_ASSERT(%(var_name)s != NULL);
+ value = %(sub_cls)s_q_in_q_%(v_name)s_populate(
+ &%(var_name)s->q_in_q, value);
+ TEST_ASSERT(value != 0);
+ %(cls)s_%(m_name)s_set(
+ obj, %(var_name)s);
+ %(sub_cls)s_delete(%(var_name)s);
+""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
+ var_name=var_name_map(m_type),
+ v_name=loxi_utils.version_to_name(version)))
else:
sub_cls = m_type[:-2] # Trim _t
out.write("""
@@ -1483,6 +1443,22 @@
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_t": # FIXME: tests only q_in_q
+ sub_cls = m_type[:-2] # Trim _t
+ out.write("""
+ { /* Use get/delete to access on check */
+ %(m_type)s *%(m_name)s_ptr;
+
+ %(m_name)s_ptr = %(cls)s_%(m_name)s_get(obj);
+ TEST_ASSERT(%(m_name)s_ptr != NULL);
+ value = %(sub_cls)s_q_in_q_%(v_name)s_check(
+ &%(m_name)s_ptr->q_in_q, value);
+ TEST_ASSERT(value != 0);
+ %(sub_cls)s_delete(%(m_name)s_ptr);
+ }
+""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
+ var_name=var_name_map(m_type),
+ v_name=loxi_utils.version_to_name(version)))
else:
sub_cls = m_type[:-2] # Trim _t
out.write("""
@@ -1552,16 +1528,16 @@
v_name=v_name, length=length, version=version))
if (not type_maps.class_is_virtual(cls)) or loxi_utils.class_is_list(cls):
out.write("""
- if (obj->wire_length_get != NULL) {
+ if (loci_class_metadata[obj->object_id].wire_length_get != NULL) {
int length;
- obj->wire_length_get((of_object_t *)obj, &length);
+ loci_class_metadata[obj->object_id].wire_length_get((of_object_t *)obj, &length);
TEST_ASSERT(length == %(length)d);
}
- if (obj->wire_type_get != NULL) {
+ if (loci_class_metadata[obj->object_id].wire_type_get != NULL) {
of_object_id_t obj_id;
- obj->wire_type_get((of_object_t *)obj, &obj_id);
+ loci_class_metadata[obj->object_id].wire_type_get((of_object_t *)obj, &obj_id);
TEST_ASSERT(obj_id == %(u_cls)s);
}
diff --git a/c_gen/c_type_maps.py b/c_gen/c_type_maps.py
index 2b46932..6e6f3fe 100644
--- a/c_gen/c_type_maps.py
+++ b/c_gen/c_type_maps.py
@@ -367,7 +367,6 @@
/* Do a simple if/else search for the ver, experimenter and subtype */
"""
- first = True
for version, experimenter_lists in type_maps.extension_message_subtype.items():
for exp, subtypes in experimenter_lists.items():
experimenter_function += """
diff --git a/c_gen/codegen.py b/c_gen/codegen.py
index af4dfa4..fe5e2ad 100644
--- a/c_gen/codegen.py
+++ b/c_gen/codegen.py
@@ -180,3 +180,153 @@
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())
+
+ClassMetadata = namedtuple('ClassMetadata',
+ ['name', 'wire_length_get', 'wire_length_set', 'wire_type_get', 'wire_type_set'])
+
+def generate_class_metadata(install_dir):
+ with template_utils.open_output(install_dir, "loci/inc/loci/loci_class_metadata.h") as out:
+ util.render_template(out, "loci_class_metadata.h")
+
+ with template_utils.open_output(install_dir, "loci/src/loci_class_metadata.c") as out:
+ class_metadata = []
+ for uclass in loxi_globals.unified.classes:
+ wire_length_get = 'NULL'
+ wire_length_set = 'NULL'
+ wire_type_get = 'NULL'
+ wire_type_set = 'NULL'
+
+ if uclass and not uclass.virtual and uclass.has_type_members:
+ wire_type_set = '%s_push_wire_types' % uclass.name
+
+ if uclass.is_message and uclass.name != "of_header":
+ 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_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"]:
+ wire_length_get = "of_u16_len_wire_length_get"
+ wire_length_set = "of_u16_len_wire_length_set"
+ elif uclass.name == 'of_match_v3':
+ 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'
+
+ class_metadata.append(ClassMetadata(
+ name=uclass.name,
+ wire_length_get=wire_length_get,
+ wire_length_set=wire_length_set,
+ 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_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'),
+ ])
+
+ util.render_template(out, "loci_class_metadata.c", class_metadata=class_metadata)
diff --git a/c_gen/identifiers.py b/c_gen/identifiers.py
index 5862967..a3304c9 100644
--- a/c_gen/identifiers.py
+++ b/c_gen/identifiers.py
@@ -65,15 +65,6 @@
if name not in idents_by_group[ofp_group]:
idents_by_group[ofp_group].append(name)
-def all_versions_agree(all_idents, version_list, name):
- val_list = all_idents[name]["values_by_version"]
- for version in version_list:
- if not version in val_list:
- return False
- if str(val_list[version]) != str(all_idents[name]["common_value"]):
- return False
- return True
-
def defined_versions_agree(all_idents, version_list, name):
val_list = all_idents[name]["values_by_version"]
for version in version_list:
diff --git a/c_gen/loci_utils.py b/c_gen/loci_utils.py
deleted file mode 100644
index 686fb0f..0000000
--- a/c_gen/loci_utils.py
+++ /dev/null
@@ -1,243 +0,0 @@
-import c_gen.of_g_legacy as of_g
-
-def class_signature(members):
- """
- Generate a signature string for a class in canonical form
-
- @param cls The class whose signature is to be generated
- """
- return ";".join([",".join([x["m_type"], x["name"], str(x["offset"])])
- for x in members])
-
-def type_dec_to_count_base(m_type):
- """
- Resolve a type declaration like uint8_t[4] to a count (4) and base_type
- (uint8_t)
-
- @param m_type The string type declaration to process
- """
- count = 1
- chk_ar = m_type.split('[')
- if len(chk_ar) > 1:
- count_str = chk_ar[1].split(']')[0]
- if count_str in of_g.ofp_constants:
- count = of_g.ofp_constants[count_str]
- else:
- count = int(count_str)
- base_type = chk_ar[0]
- else:
- base_type = m_type
- return count, base_type
-
-def list_to_entry_type(cls):
- """
- Return the entry type for a list
- """
- slen = len("of_list_")
- return "of_" + cls[slen:]
-
-def type_to_short_name(m_type):
- if m_type in of_g.of_base_types:
- tname = of_g.of_base_types[m_type]["short_name"]
- elif m_type in of_g.of_mixed_types:
- tname = of_g.of_mixed_types[m_type]["short_name"]
- else:
- tname = "unknown"
- return tname
-
-def type_to_name_type(cls, member_name):
- """
- Generate the root name of a member for accessor functions, etc
- @param cls The class name
- @param member_name The member name
- """
- members = of_g.unified[cls]["union"]
- if not member_name in members:
- debug("Error: %s is not in class %s for acc_name defn" %
- (member_name, cls))
- os.exit()
-
- mem = members[member_name]
- m_type = mem["m_type"]
- id = mem["memid"]
- tname = type_to_short_name(m_type)
-
- return "o%d_m%d_%s" % (of_g.unified[cls]["object_id"], id, tname)
-
-
-def member_to_index(m_name, members):
- """
- Given a member name, return the index in the members dict
- @param m_name The name of the data member to search for
- @param members The dict of members
- @return Index if found, -1 not found
-
- Note we could generate an index when processing the original input
- """
- count = 0
- for d in members:
- if d["name"] == m_name:
- return count
- count += 1
- return -1
-
-def member_base_type(cls, m_name):
- """
- Map a member to its of_ type
- @param cls The class name
- @param m_name The name of the member being gotten
- @return The of_ type of the member
- """
- rv = of_g.unified[cls]["union"][m_name]["m_type"]
- if rv[-2:] == "_t":
- return rv
- return rv + "_t"
-
-def member_type_is_octets(cls, m_name):
- return member_base_type(cls, m_name) == "of_octets_t"
-
-def h_file_to_define(name):
- """
- Convert a .h file name to the define used for the header
- """
- h_name = name[:-2].upper()
- h_name = "_" + h_name + "_H_"
- return h_name
-
-def type_to_cof_type(m_type):
- if m_type in of_g.of_base_types:
- if "cof_type" in of_g.of_base_types[m_type]:
- return of_g.of_base_types[m_type]["cof_type"]
- return m_type
-
-
-def member_is_scalar(cls, m_name):
- return of_g.unified[cls]["union"][m_name]["m_type"] in of_g.of_scalar_types
-
-def type_is_scalar(m_type):
- return m_type in of_g.of_scalar_types
-
-def skip_member_name(name):
- return name.find("pad") == 0 or name in of_g.skip_members
-
-def enum_name(cls):
- """
- Return the name used for an enum identifier for the given class
- @param cls The class name
- """
- return cls.upper()
-
-def class_in_version(cls, ver):
- """
- Return boolean indicating if cls is defined for wire version ver
- """
-
- return (cls, ver) in of_g.base_length
-
-def instance_to_class(instance, parent):
- """
- Return the name of the class for an instance of inheritance type parent
- """
- return parent + "_" + instance
-
-def sub_class_to_var_name(cls):
- """
- Given a subclass name like of_action_output, generate the
- name of a variable like 'output'
- @param cls The class name
- """
- pass
-
-def class_is_var_len(cls, version):
- # Match is special case. Only version 1.2 (wire version 3) is var
- if cls == "of_match":
- return version == 3
-
- return not (cls, version) in of_g.is_fixed_length
-
-def base_type_to_length(base_type, version):
- if base_type + "_t" in of_g.of_base_types:
- inst_len = of_g.of_base_types[base_type + "_t"]["bytes"]
- else:
- inst_len = of_g.base_length[(base_type, version)]
-
-def version_to_name(version):
- """
- Convert an integer version to the C macro name
- """
- return "OF_" + of_g.version_names[version]
-
-##
-# Is class a flow modify of some sort?
-
-def cls_is_flow_mod(cls):
- return cls in ["of_flow_mod", "of_flow_modify", "of_flow_add", "of_flow_delete",
- "of_flow_modify_strict", "of_flow_delete_strict"]
-
-def all_member_types_get(cls, version):
- """
- Get the members and list of types for members of a given class
- @param cls The class name to process
- @param version The version for the class
- """
- member_types = []
-
- if not version in of_g.unified[cls]:
- return ([], [])
-
- if "use_version" in of_g.unified[cls][version]:
- v = of_g.unified[cls][version]["use_version"]
- members = of_g.unified[cls][v]["members"]
- else:
- members = of_g.unified[cls][version]["members"]
- # Accumulate variables that are supported
- for member in members:
- m_type = member["m_type"]
- m_name = member["name"]
- if skip_member_name(m_name):
- continue
- if not m_type in member_types:
- member_types.append(m_type)
-
- return (members, member_types)
-
-def list_name_extract(list_type):
- """
- Return the base name for a list object of the given type
- @param list_type The type of the list as appears in the input,
- for example list(of_port_desc_t).
- @return A pair, (list-name, base-type) where list-name is the
- base name for the list, for example of_list_port_desc, and base-type
- is the type of list elements like of_port_desc_t
- """
- base_type = list_type[5:-1]
- list_name = base_type
- if list_name.find("of_") == 0:
- list_name = list_name[3:]
- if list_name[-2:] == "_t":
- list_name = list_name[:-2]
- list_name = "of_list_" + list_name
- return (list_name, base_type)
-
-def version_to_name(version):
- """
- Convert an integer version to the C macro name
- """
- return "OF_" + of_g.version_names[version]
-
-def gen_c_copy_license(out):
- """
- Generate the top comments for copyright and license
- """
- import c_gen.util
- c_gen.util.render_template(out, '_copyright.c')
-
-def accessor_returns_error(a_type, m_type):
- is_var_len = (not type_is_scalar(m_type)) and \
- [x for x in of_g.of_version_range if class_is_var_len(m_type[:-2], x)] != []
- if a_type == "set" and is_var_len:
- return True
- elif m_type == "of_match_t":
- return True
- else:
- return False
diff --git a/c_gen/loxi_utils_legacy.py b/c_gen/loxi_utils_legacy.py
index df93c2b..220d043 100644
--- a/c_gen/loxi_utils_legacy.py
+++ b/c_gen/loxi_utils_legacy.py
@@ -120,6 +120,8 @@
return True
if cls.find("of_bsn_tlv") == 0:
return True
+ if cls.find("of_bsn_vport") == 0:
+ return True
return False
def class_is_u16_len(cls):
@@ -161,122 +163,12 @@
return False
-def class_is_action_id(cls):
- """
- Return True if cls_name is an action object
-
- Note that action_id is not an action object, though it has
- the same header. It looks like an action header, but the type
- is used to identify a kind of action, it does not indicate the
- type of the object following.
- """
- if cls.find("of_action_id") == 0:
- return True
-
- # For each vendor, check for vendor specific action
- for exp in of_g.experimenter_name_to_id:
- if cls.find("of_action_id_" + exp) == 0:
- return True
-
- return False
-
-def class_is_instruction(cls):
- """
- Return True if cls_name is an instruction object
- """
- if cls.find("of_instruction_id") == 0:
- return False
- if cls.find("of_instruction") == 0:
- return True
-
- # For each vendor, check for vendor specific action
- for exp in of_g.experimenter_name_to_id:
- if cls.find("of_instruction" + exp) == 0:
- return True
-
- return False
-
-def class_is_instruction_id(cls):
- """
- Return True if cls_name is an action object
-
- Note that instruction_id is not an instruction object, though it has
- the same header. It looks like an instruction header, but the type
- is used to identify a kind of instruction, it does not indicate the
- type of the object following.
- """
- if cls.find("of_instruction_id") == 0:
- return True
-
- # For each vendor, check for vendor specific action
- for exp in of_g.experimenter_name_to_id:
- if cls.find("of_instruction_id_" + exp) == 0:
- return True
-
- return False
-
-def class_is_meter_band(cls):
- """
- Return True if cls_name is an instruction object
- """
- # meter_band_stats is not a member of meter_band class hierarchy
- if cls.find("of_meter_band_stats") == 0:
- return False
- if cls.find("of_meter_band") == 0:
- return True
- return False
-
-def class_is_hello_elem(cls):
- """
- Return True if cls_name is an instruction object
- """
- if cls.find("of_hello_elem") == 0:
- return True
- return False
-
-def class_is_queue_prop(cls):
- """
- Return True if cls_name is a queue_prop object
- """
- if cls.find("of_queue_prop") == 0:
- return True
-
- # For each vendor, check for vendor specific action
- for exp in of_g.experimenter_name_to_id:
- if cls.find("of_queue_prop_" + exp) == 0:
- return True
-
- return False
-
-def class_is_table_feature_prop(cls):
- """
- Return True if cls_name is a queue_prop object
- """
- if cls.find("of_table_feature_prop") == 0:
- return True
- return False
-
-def class_is_stats_message(cls):
- """
- Return True if cls_name is a message object based on info in unified
- """
-
- return "stats_type" in of_g.unified[cls]["union"]
-
def class_is_list(cls):
"""
Return True if cls_name is a list object
"""
return (cls.find("of_list_") == 0)
-def class_is_bsn_tlv(cls):
- """
- Return True if cls_name is a BSN TLV object
- """
- if cls.find("of_bsn_tlv") == 0:
- return True
- return False
-
def type_is_of_object(m_type):
"""
Return True if m_type is an OF object type
@@ -302,26 +194,6 @@
tname = "unknown"
return tname
-def type_to_name_type(cls, member_name):
- """
- Generate the root name of a member for accessor functions, etc
- @param cls The class name
- @param member_name The member name
- """
- members = of_g.unified[cls]["union"]
- if not member_name in members:
- debug("Error: %s is not in class %s for acc_name defn" %
- (member_name, cls))
- os.exit()
-
- mem = members[member_name]
- m_type = mem["m_type"]
- id = mem["memid"]
- tname = type_to_short_name(m_type)
-
- return "o%d_m%d_%s" % (of_g.unified[cls]["object_id"], id, tname)
-
-
def member_to_index(m_name, members):
"""
Given a member name, return the index in the members dict
@@ -350,27 +222,6 @@
return rv
return rv + "_t"
-def member_type_is_octets(cls, m_name):
- return member_base_type(cls, m_name) == "of_octets_t"
-
-def h_file_to_define(name):
- """
- Convert a .h file name to the define used for the header
- """
- h_name = name[:-2].upper()
- h_name = "_" + h_name + "_H_"
- return h_name
-
-def type_to_cof_type(m_type):
- if m_type in of_g.of_base_types:
- if "cof_type" in of_g.of_base_types[m_type]:
- return of_g.of_base_types[m_type]["cof_type"]
- return m_type
-
-
-def member_is_scalar(cls, m_name):
- return of_g.unified[cls]["union"][m_name]["m_type"] in of_g.of_scalar_types
-
def type_is_scalar(m_type):
return m_type in of_g.of_scalar_types
@@ -397,14 +248,6 @@
"""
return parent + "_" + instance
-def sub_class_to_var_name(cls):
- """
- Given a subclass name like of_action_output, generate the
- name of a variable like 'output'
- @param cls The class name
- """
- pass
-
def class_is_var_len(cls, version):
# Match is special case. Only version 1.2 (wire version 3) is var
if cls == "of_match":
@@ -412,18 +255,6 @@
return not (cls, version) in of_g.is_fixed_length
-def base_type_to_length(base_type, version):
- if base_type + "_t" in of_g.of_base_types:
- inst_len = of_g.of_base_types[base_type + "_t"]["bytes"]
- else:
- inst_len = of_g.base_length[(base_type, version)]
-
-def version_to_name(version):
- """
- Convert an integer version to the C macro name
- """
- return "OF_" + of_g.version_names[version]
-
##
# Is class a flow modify of some sort?
@@ -499,31 +330,3 @@
return True
else:
return False
-
-def render_template(out, name, path, context, prefix = None):
- """
- Render a template using tenjin.
- out: a file-like object
- name: name of the template
- path: array of directories to search for the template
- context: dictionary of variables to pass to the template
- prefix: optional prefix to use for embedding (for other languages than python)
- """
- pp = [ tenjin.PrefixedLinePreprocessor(prefix=prefix) if prefix else tenjin.PrefixedLinePreprocessor() ] # support "::" syntax
- template_globals = { "to_str": str, "escape": str } # disable HTML escaping
- engine = TemplateEngine(path=path, pp=pp)
- out.write(engine.render(name, context, template_globals))
-
-def render_static(out, name, path):
- """
- Write out a static template.
- out: a file-like object
- name: name of the template
- path: array of directories to search for the template
- """
- # Reuse the tenjin logic for finding the template
- template_filename = tenjin.FileSystemLoader().find(name, path)
- if not template_filename:
- raise ValueError("template %s not found" % name)
- with open(template_filename) as infile:
- out.write(infile.read())
diff --git a/c_gen/of_g_legacy.py b/c_gen/of_g_legacy.py
index 3311282..b58ca08 100644
--- a/c_gen/of_g_legacy.py
+++ b/c_gen/of_g_legacy.py
@@ -292,47 +292,12 @@
VERSION_1_2 = 3
VERSION_1_3 = 4
-# Ignore version for some functions
-VERSION_ANY = -1
-
-## @var supported_wire_protos
-# The wire protocols this version of LoxiGen supports
-supported_wire_protos = set([1, 2, 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"}
-param_version_names = {1:"1.0", 2:"1.1", 3:"1.2", 4:"1.3"}
-
-##
-# Maps and ranges related to versioning
-
-# For parameter version indications
-of_param_version_map = {
- "1.0":VERSION_1_0,
- "1.1":VERSION_1_1,
- "1.2":VERSION_1_2,
- "1.3":VERSION_1_3
- }
-
-# For parameter version indications
-of_version_map = {
- "1.0":VERSION_1_0,
- "1.1":VERSION_1_1,
- "1.2":VERSION_1_2,
- "1.3":VERSION_1_3
- }
# 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_max = VERSION_1_3
-
-
-of_version_name2wire = dict(
- OF_VERSION_1_0=VERSION_1_0,
- OF_VERSION_1_1=VERSION_1_1,
- OF_VERSION_1_2=VERSION_1_2,
- OF_VERSION_1_3=VERSION_1_3
- )
of_version_wire2name = {
VERSION_1_0:"OF_VERSION_1_0",
@@ -367,21 +332,3 @@
nicira = 0x00002320,
openflow = 0x000026e1
)
-
-def experimenter_name_lookup(experimenter_id):
- """
- Map an experimenter ID to its LOXI recognized name string
- """
- for name, id in of_g.experimenter_name_to_id.items():
- if id == experimenter_id:
- return name
- return None
-
-################################################################
-#
-# Debug
-#
-################################################################
-
-loxigen_dbg_file = sys.stdout
-loxigen_log_file = sys.stdout
diff --git a/c_gen/templates/_push_wire_types.c b/c_gen/templates/_push_wire_types.c
index fd2536c..96a9111 100644
--- a/c_gen/templates/_push_wire_types.c
+++ b/c_gen/templates/_push_wire_types.c
@@ -25,7 +25,7 @@
:: # EPL for the specific language governing permissions and limitations
:: # under the EPL.
::
-static void
+void
${data.class_name}_push_wire_types(of_object_t *obj)
{
unsigned char *buf = OF_OBJECT_BUFFER_INDEX(obj, 0);
diff --git a/c_gen/templates/loci_class_metadata.c b/c_gen/templates/loci_class_metadata.c
new file mode 100644
index 0000000..1aca773
--- /dev/null
+++ b/c_gen/templates/loci_class_metadata.c
@@ -0,0 +1,51 @@
+:: # 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.
+::
+:: include('_copyright.c')
+:: import loxi_globals
+
+/****************************************************************
+ *
+ * loci_class_metadata.c
+ *
+ * Tables with information for each class
+ *
+ ****************************************************************/
+
+#include "loci_log.h"
+#include <loci/loci.h>
+
+struct loci_class_metadata loci_class_metadata[OF_OBJECT_COUNT] = {
+:: for data in class_metadata:
+ [${data.name.upper()}] = {
+ .wire_length_get=${data.wire_length_get},
+ .wire_length_set=${data.wire_length_set},
+ .wire_type_get=${data.wire_type_get},
+ .wire_type_set=${data.wire_type_set},
+ },
+:: #endfor
+};
diff --git a/c_gen/templates/loci_class_metadata.h b/c_gen/templates/loci_class_metadata.h
new file mode 100644
index 0000000..37962e3
--- /dev/null
+++ b/c_gen/templates/loci_class_metadata.h
@@ -0,0 +1,63 @@
+:: # 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.
+::
+:: include('_copyright.c')
+::
+#ifndef __LOCI_CLASS_METADATA_H__
+#define __LOCI_CLASS_METADATA_H__
+
+typedef void (*of_wire_length_get_f)(of_object_t *obj, int *bytes);
+typedef void (*of_wire_length_set_f)(of_object_t *obj, int bytes);
+typedef void (*of_wire_type_get_f)(of_object_t *obj, of_object_id_t *id);
+typedef void (*of_wire_type_set_f)(of_object_t *obj);
+
+struct loci_class_metadata {
+ of_wire_length_get_f wire_length_get;
+ of_wire_length_set_f wire_length_set;
+ of_wire_type_get_f wire_type_get;
+ of_wire_type_set_f wire_type_set;
+};
+
+extern struct loci_class_metadata loci_class_metadata[OF_OBJECT_COUNT];
+
+static inline void
+of_object_wire_length_set(of_object_t *obj, int bytes)
+{
+ if (loci_class_metadata[obj->object_id].wire_length_set) {
+ loci_class_metadata[obj->object_id].wire_length_set(obj, bytes);
+ }
+}
+
+static inline void
+of_object_wire_type_set(of_object_t *obj)
+{
+ if (loci_class_metadata[obj->object_id].wire_type_set) {
+ loci_class_metadata[obj->object_id].wire_type_set(obj);
+ }
+}
+
+#endif
diff --git a/c_gen/templates/loci_classes.h b/c_gen/templates/loci_classes.h
index 12c07d1..c5147cb 100644
--- a/c_gen/templates/loci_classes.h
+++ b/c_gen/templates/loci_classes.h
@@ -33,6 +33,7 @@
:: for uclass in loxi_globals.unified.classes:
void ${uclass.name}_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
+void ${uclass.name}_push_wire_types(of_object_t *obj);
:: #endfor
${legacy_code}
diff --git a/c_gen/templates/loci_int.h b/c_gen/templates/loci_int.h
index c57371a..1ea9eeb 100644
--- a/c_gen/templates/loci_int.h
+++ b/c_gen/templates/loci_int.h
@@ -67,8 +67,8 @@
of_object_u16_get(of_object_t *obj, int offset) {
uint16_t val16;
- of_wire_buffer_u16_get(obj->wire_object.wbuf,
- obj->wire_object.obj_offset + offset, &val16);
+ of_wire_buffer_u16_get(obj->wbuf,
+ obj->obj_offset + offset, &val16);
return (int)val16;
}
@@ -86,8 +86,8 @@
uint16_t val16;
val16 = (uint16_t)value;
- of_wire_buffer_u16_set(obj->wire_object.wbuf,
- obj->wire_object.obj_offset + offset, val16);
+ of_wire_buffer_u16_set(obj->wbuf,
+ obj->obj_offset + offset, val16);
}
/**
diff --git a/c_gen/templates/loci_setup_from_add_fns.c b/c_gen/templates/loci_setup_from_add_fns.c
deleted file mode 100644
index 5f63d29..0000000
--- a/c_gen/templates/loci_setup_from_add_fns.c
+++ /dev/null
@@ -1,250 +0,0 @@
-:: # 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.
-:: include('_copyright.c')
-#include <loci/loci.h>
-#include <loci/of_object.h>
-#include "loci_log.h"
-#include "loci_int.h"
-
-/* Flow stats entry setup for all versions */
-
-static int
-flow_stats_entry_setup_from_flow_add_common(of_flow_stats_entry_t *obj,
- of_flow_add_t *flow_add,
- of_object_t *effects,
- int entry_match_offset,
- int add_match_offset)
-{
- int entry_len, add_len;
- of_wire_buffer_t *wbuf;
- int abs_offset;
- int delta;
- uint16_t val16;
- uint64_t cookie;
- of_octets_t match_octets;
-
- /* Transfer the match underlying object from add to stats entry */
- wbuf = OF_OBJECT_TO_WBUF(obj);
- entry_len = _WIRE_MATCH_PADDED_LEN(obj, entry_match_offset);
- add_len = _WIRE_MATCH_PADDED_LEN(flow_add, add_match_offset);
-
- match_octets.bytes = add_len;
- match_octets.data = OF_OBJECT_BUFFER_INDEX(flow_add, add_match_offset);
-
- /* Copy data into flow entry */
- abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, entry_match_offset);
- of_wire_buffer_replace_data(wbuf, abs_offset, entry_len,
- match_octets.data, add_len);
-
- /* Not scalar, update lengths if needed */
- delta = add_len - entry_len;
- if (delta != 0) {
- /* Update parent(s) */
- of_object_parent_length_update((of_object_t *)obj, delta);
- }
-
- of_flow_add_cookie_get(flow_add, &cookie);
- of_flow_stats_entry_cookie_set(obj, cookie);
-
- of_flow_add_priority_get(flow_add, &val16);
- of_flow_stats_entry_priority_set(obj, val16);
-
- of_flow_add_idle_timeout_get(flow_add, &val16);
- of_flow_stats_entry_idle_timeout_set(obj, val16);
-
- of_flow_add_hard_timeout_get(flow_add, &val16);
- of_flow_stats_entry_hard_timeout_set(obj, val16);
-
- /* Effects may come from different places */
- if (effects != NULL) {
- if (obj->version == OF_VERSION_1_0) {
- OF_TRY(of_flow_stats_entry_actions_set(obj,
- (of_list_action_t *)effects));
- } else {
- OF_TRY(of_flow_stats_entry_instructions_set(obj,
- (of_list_instruction_t *)effects));
- }
- } else {
- if (obj->version == OF_VERSION_1_0) {
- of_list_action_t actions;
- of_flow_add_actions_bind(flow_add, &actions);
- OF_TRY(of_flow_stats_entry_actions_set(obj, &actions));
- } else {
- of_list_instruction_t instructions;
- of_flow_add_instructions_bind(flow_add, &instructions);
- OF_TRY(of_flow_stats_entry_instructions_set(obj, &instructions));
- }
- }
-
- return OF_ERROR_NONE;
-}
-
-/* Flow removed setup for all versions */
-
-static int
-flow_removed_setup_from_flow_add_common(of_flow_removed_t *obj,
- of_flow_add_t *flow_add,
- int removed_match_offset,
- int add_match_offset)
-{
- int add_len, removed_len;
- of_wire_buffer_t *wbuf;
- int abs_offset;
- int delta;
- uint16_t val16;
- uint64_t cookie;
- of_octets_t match_octets;
-
- /* Transfer the match underlying object from add to removed obj */
- wbuf = OF_OBJECT_TO_WBUF(obj);
- removed_len = _WIRE_MATCH_PADDED_LEN(obj, removed_match_offset);
- add_len = _WIRE_MATCH_PADDED_LEN(flow_add, add_match_offset);
-
- match_octets.bytes = add_len;
- match_octets.data = OF_OBJECT_BUFFER_INDEX(flow_add, add_match_offset);
-
- /* Copy data into flow removed */
- abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, removed_match_offset);
- of_wire_buffer_replace_data(wbuf, abs_offset, removed_len,
- match_octets.data, add_len);
-
- /* Not scalar, update lengths if needed */
- delta = add_len - removed_len;
- if (delta != 0) {
- /* Update parent(s) */
- of_object_parent_length_update((of_object_t *)obj, delta);
- }
-
- of_flow_add_cookie_get(flow_add, &cookie);
- of_flow_removed_cookie_set(obj, cookie);
-
- of_flow_add_priority_get(flow_add, &val16);
- of_flow_removed_priority_set(obj, val16);
-
- of_flow_add_idle_timeout_get(flow_add, &val16);
- of_flow_removed_idle_timeout_set(obj, val16);
-
- if (obj->version >= OF_VERSION_1_2) {
- of_flow_add_hard_timeout_get(flow_add, &val16);
- of_flow_removed_hard_timeout_set(obj, val16);
- }
-
- return OF_ERROR_NONE;
-}
-
-/* Set up a flow removed message from the original add */
-
-int
-of_flow_removed_setup_from_flow_add(of_flow_removed_t *obj,
- of_flow_add_t *flow_add)
-{
- switch (obj->version) {
- case OF_VERSION_1_0:
- return flow_removed_setup_from_flow_add_common(obj, flow_add,
- 8, 8);
- break;
- case OF_VERSION_1_1:
- case OF_VERSION_1_2:
- case OF_VERSION_1_3:
- return flow_removed_setup_from_flow_add_common(obj, flow_add,
- 48, 48);
- break;
- default:
- return OF_ERROR_VERSION;
- break;
- }
-
- return OF_ERROR_NONE;
-}
-
-
-/* Set up a packet in message from the original add */
-
-int
-of_packet_in_setup_from_flow_add(of_packet_in_t *obj,
- of_flow_add_t *flow_add)
-{
- int add_len, pkt_in_len;
- of_wire_buffer_t *wbuf;
- int abs_offset;
- int delta;
- const int pkt_in_match_offset = 16;
- const int add_match_offset = 48;
- of_octets_t match_octets;
-
- if (obj->version < OF_VERSION_1_2) {
- /* Nothing to be done before OF 1.2 */
- return OF_ERROR_NONE;
- }
-
- /* Transfer match struct from flow add to packet in object */
- wbuf = OF_OBJECT_TO_WBUF(obj);
- pkt_in_len = _WIRE_MATCH_PADDED_LEN(obj, pkt_in_match_offset);
- add_len = _WIRE_MATCH_PADDED_LEN(flow_add, add_match_offset);
-
- match_octets.bytes = add_len;
- match_octets.data = OF_OBJECT_BUFFER_INDEX(flow_add, add_match_offset);
-
- /* Copy data into pkt_in msg */
- abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, pkt_in_match_offset);
- of_wire_buffer_replace_data(wbuf, abs_offset, pkt_in_len,
- match_octets.data, add_len);
-
- /* Not scalar, update lengths if needed */
- delta = add_len - pkt_in_len;
- if (delta != 0) {
- /* Update parent(s) */
- of_object_parent_length_update((of_object_t *)obj, delta);
- }
-
- return OF_ERROR_NONE;
-}
-
-/* Set up a stats entry from the original add */
-
-int
-of_flow_stats_entry_setup_from_flow_add(of_flow_stats_entry_t *obj,
- of_flow_add_t *flow_add,
- of_object_t *effects)
-{
- switch (obj->version) {
- case OF_VERSION_1_0:
- return flow_stats_entry_setup_from_flow_add_common(obj, flow_add,
- effects, 4, 8);
- break;
- case OF_VERSION_1_1:
- case OF_VERSION_1_2:
- case OF_VERSION_1_3:
- return flow_stats_entry_setup_from_flow_add_common(obj, flow_add,
- effects, 48, 48);
- break;
- default:
- return OF_ERROR_VERSION;
- }
-
- return OF_ERROR_NONE;
-}
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index b210570..88fd029 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -398,5 +398,14 @@
#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_flags(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
#endif /* _LOCI_SHOW_H_ */
diff --git a/c_gen/templates/locitest/main.c b/c_gen/templates/locitest/main.c
index 86f7ae6..36bf60c 100644
--- a/c_gen/templates/locitest/main.c
+++ b/c_gen/templates/locitest/main.c
@@ -33,7 +33,6 @@
TEST_ASSERT(run_scalar_acc_tests() == TEST_PASS);
TEST_ASSERT(run_list_tests() == TEST_PASS);
TEST_ASSERT(run_message_tests() == TEST_PASS);
- TEST_ASSERT(run_setup_from_add_tests() == TEST_PASS);
TEST_ASSERT(run_validator_tests() == TEST_PASS);
diff --git a/c_gen/templates/locitest/test_setup_from_add.c b/c_gen/templates/locitest/test_setup_from_add.c
deleted file mode 100644
index 0b07076..0000000
--- a/c_gen/templates/locitest/test_setup_from_add.c
+++ /dev/null
@@ -1,133 +0,0 @@
-:: # 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.
-::
-:: include('_copyright.c')
-
-/**
- * Test code for setup from flow add routines
- */
-
-#include <locitest/test_common.h>
-
-/* mcheck is a glibc extension */
-#if defined(__linux__)
-#include <mcheck.h>
-#define MCHECK_INIT mcheck(NULL)
-#else
-#define MCHECK_INIT do { } while (0)
-#endif
-
-
-static int
-test_removed_setup_from_add(void)
-{
- of_flow_removed_t *removed;
- of_flow_add_t *add;
- of_match_t m1, m2;
-
- TEST_ASSERT((add = of_flow_add_new(OF_VERSION_1_0)) != NULL);
- TEST_ASSERT((removed = of_flow_removed_new(OF_VERSION_1_0)) != NULL);
-
- TEST_ASSERT(of_flow_add_OF_VERSION_1_0_populate(add, 1) != 0);
- TEST_ASSERT(of_flow_add_match_get(add, &m1) == 0);
-
- TEST_ASSERT(of_flow_removed_setup_from_flow_add(removed, add) == 0);
- TEST_ASSERT(of_flow_removed_match_get(removed, &m2) == 0);
- TEST_ASSERT(memcmp(&m1, &m2, sizeof(m1)) == 0);
-
- of_flow_add_delete(add);
- of_flow_removed_delete(removed);
-
- return TEST_PASS;
-}
-
-
-static int
-test_stats_entry_setup_from_add(void)
-{
- of_flow_add_t *add;
- of_flow_stats_entry_t *entry;
- of_match_t m1, m2;
- of_list_action_t *list;
- of_list_action_t list_out;
-
- TEST_ASSERT((add = of_flow_add_new(OF_VERSION_1_0)) != NULL);
- TEST_ASSERT((entry = of_flow_stats_entry_new(OF_VERSION_1_0)) != NULL);
-
- TEST_ASSERT(of_flow_add_OF_VERSION_1_0_populate(add, 1) != 0);
- TEST_ASSERT(of_flow_add_match_get(add, &m1) == 0);
-
- TEST_ASSERT(of_flow_stats_entry_setup_from_flow_add(entry, add, NULL) == 0);
- TEST_ASSERT(of_flow_stats_entry_match_get(entry, &m2) == 0);
- TEST_ASSERT(memcmp(&m1, &m2, sizeof(m1)) == 0);
-
- of_flow_add_delete(add);
- of_flow_stats_entry_delete(entry);
-
- /* @todo check action lists agree */
-
- /* Same with an external action list */
-
- TEST_ASSERT((add = of_flow_add_new(OF_VERSION_1_0)) != NULL);
- TEST_ASSERT((entry = of_flow_stats_entry_new(OF_VERSION_1_0)) != NULL);
-
- TEST_ASSERT(of_flow_add_OF_VERSION_1_0_populate(add, 1) != 0);
- TEST_ASSERT(of_flow_add_match_get(add, &m1) == 0);
-
- list = of_list_action_new(OF_VERSION_1_0);
- TEST_ASSERT(list != NULL);
- TEST_ASSERT(of_list_action_OF_VERSION_1_0_populate(list, 1) != 0);
-
- /* Verify matches agree */
- TEST_ASSERT(of_flow_stats_entry_setup_from_flow_add(entry, add, list) == 0);
- TEST_ASSERT(of_flow_stats_entry_match_get(entry, &m2) == 0);
- TEST_ASSERT(memcmp(&m1, &m2, sizeof(m1)) == 0);
-
- of_list_action_init(&list_out, OF_VERSION_1_0, 0, 1);
- of_flow_stats_entry_actions_bind(entry, &list_out);
-
- /* Verify lists agree */
- TEST_ASSERT(list->length == list_out.length);
- TEST_ASSERT(memcmp(WBUF_BUF(list->wire_object.wbuf),
- WBUF_BUF(list_out.wire_object.wbuf),
- list->length));
-
- of_flow_add_delete(add);
- of_list_action_delete(list);
- of_flow_stats_entry_delete(entry);
-
- return TEST_PASS;
-}
-
-
-int run_setup_from_add_tests(void)
-{
- RUN_TEST(removed_setup_from_add);
- RUN_TEST(stats_entry_setup_from_add);
-
- return TEST_PASS;
-}
diff --git a/c_gen/templates/of_object.c b/c_gen/templates/of_object.c
index 69bd8d3..39a6790 100644
--- a/c_gen/templates/of_object.c
+++ b/c_gen/templates/of_object.c
@@ -61,11 +61,10 @@
MEMSET(obj, 0, sizeof(*obj));
if (bytes > 0) {
- if ((obj->wire_object.wbuf = of_wire_buffer_new(bytes)) == NULL) {
+ if ((obj->wbuf = of_wire_buffer_new(bytes)) == NULL) {
FREE(obj);
return NULL;
}
- obj->wire_object.owned = 1;
}
return obj;
@@ -87,15 +86,8 @@
return;
}
- /*
- * Make callback if present
- */
- if (obj->track_info.delete_cb != NULL) {
- obj->track_info.delete_cb(obj);
- }
-
- if (obj->wire_object.owned) {
- of_wire_buffer_free(obj->wire_object.wbuf);
+ if (obj->parent == NULL) {
+ of_wire_buffer_free(obj->wbuf);
}
FREE(obj);
@@ -121,13 +113,11 @@
MEMSET(dst, 0, sizeof(*dst));
/* Allocate a minimal wire buffer assuming we will not write to it. */
- if ((dst->wire_object.wbuf = of_wire_buffer_new(src->length)) == NULL) {
+ if ((dst->wbuf = of_wire_buffer_new(src->length)) == NULL) {
FREE(dst);
return NULL;
}
- dst->wire_object.owned = 1;
-
init_fn = of_object_init_map[src->object_id];
init_fn(dst, src->version, src->length, 0);
@@ -211,7 +201,7 @@
}
obj->version = version;
- obj->wire_object.wbuf = wbuf;
+ obj->wbuf = wbuf;
wbuf->buf = msg;
wbuf->alloc_bytes = len;
wbuf->current_bytes = len;
@@ -239,23 +229,18 @@
of_object_buffer_bind(of_object_t *obj, uint8_t *buf, int bytes,
of_buffer_free_f buf_free)
{
- of_wire_object_t *wobj;
of_wire_buffer_t *wbuf;
LOCI_ASSERT(buf != NULL);
LOCI_ASSERT(bytes > 0);
- // LOCI_ASSERT(wobj is not bound);
-
- wobj = &obj->wire_object;
- MEMSET(wobj, 0, sizeof(*wobj));
wbuf = of_wire_buffer_new_bind(buf, bytes, buf_free);
if (wbuf == NULL) {
return OF_ERROR_RESOURCE;
}
- wobj->wbuf = wbuf;
- wobj->owned = 1;
+ obj->wbuf = wbuf;
+ obj->obj_offset = 0;
obj->length = bytes;
return OF_ERROR_NONE;
@@ -291,17 +276,14 @@
object_child_attach(of_object_t *parent, of_object_t *child,
int offset, int bytes)
{
- of_wire_object_t *c_wobj; /* Pointer to child's wire object */
of_wire_buffer_t *wbuf; /* Pointer to common wire buffer manager */
child->parent = parent;
- wbuf = parent->wire_object.wbuf;
+ wbuf = parent->wbuf;
/* Set up the child's wire buf to point to same as parent */
- c_wobj = &child->wire_object;
- c_wobj->wbuf = wbuf;
- c_wobj->obj_offset = parent->wire_object.obj_offset + offset;
- c_wobj->owned = 0;
+ child->wbuf = wbuf;
+ child->obj_offset = parent->obj_offset + offset;
/*
* bytes determines if this is a read or write setup.
@@ -312,7 +294,7 @@
int tot_bytes; /* Total bytes to request for buffer if updated */
/* Set up space for the child in the parent's buffer */
- tot_bytes = parent->wire_object.obj_offset + offset + bytes;
+ tot_bytes = parent->obj_offset + offset + bytes;
of_wire_buffer_grow(wbuf, tot_bytes);
child->length = bytes;
@@ -331,7 +313,7 @@
of_object_can_grow(of_object_t *obj, int new_len)
{
return OF_OBJECT_ABSOLUTE_OFFSET(obj, new_len) <=
- WBUF_ALLOC_BYTES(obj->wire_object.wbuf);
+ WBUF_ALLOC_BYTES(obj->wbuf);
}
/**
@@ -405,7 +387,7 @@
of_list_append_bind(of_object_t *parent, of_object_t *child)
{
if (parent == NULL || child == NULL ||
- parent->wire_object.wbuf == NULL) {
+ parent->wbuf == NULL) {
return OF_ERROR_PARAM;
}
@@ -417,13 +399,8 @@
child->length);
/* Update the wire length and type if needed */
- if (child->wire_length_set) {
- child->wire_length_set(child, child->length);
- }
-
- if (child->wire_type_set) {
- child->wire_type_set(child);
- }
+ of_object_wire_length_set(child, child->length);
+ of_object_wire_type_set(child);
/* Update the parent's length */
of_object_parent_length_update(parent, child->length);
@@ -452,7 +429,7 @@
return OF_ERROR_RESOURCE;
}
- of_wire_buffer_grow(list->wire_object.wbuf,
+ of_wire_buffer_grow(list->wbuf,
OF_OBJECT_ABSOLUTE_OFFSET(list, new_len));
MEMCPY(OF_OBJECT_BUFFER_INDEX(list, list->length),
@@ -503,8 +480,8 @@
static int
of_list_is_last(of_object_t *parent, of_object_t *child)
{
- if (child->wire_object.obj_offset + child->length >=
- parent->wire_object.obj_offset + parent->length) {
+ if (child->obj_offset + child->length >=
+ parent->obj_offset + parent->length) {
return 1;
}
@@ -538,7 +515,7 @@
}
/* Offset is relative to parent start */
- offset = (child->wire_object.obj_offset - parent->wire_object.obj_offset) +
+ offset = (child->obj_offset - parent->obj_offset) +
child->length;
object_child_attach(parent, child, offset, 0);
@@ -549,8 +526,8 @@
of_object_wire_buffer_steal(of_object_t *obj, uint8_t **buffer)
{
LOCI_ASSERT(obj != NULL);
- of_wire_buffer_steal(obj->wire_object.wbuf, buffer);
- obj->wire_object.wbuf = NULL;
+ of_wire_buffer_steal(obj->wbuf, buffer);
+ obj->wbuf = NULL;
}
#define _MAX_PARENT_ITERATIONS 4
@@ -575,18 +552,16 @@
while (obj != NULL) {
LOCI_ASSERT(count++ < _MAX_PARENT_ITERATIONS);
obj->length += delta;
- if (obj->wire_length_set != NULL) {
- obj->wire_length_set(obj, obj->length);
- }
+ of_object_wire_length_set(obj, obj->length);
#ifndef NDEBUG
- wbuf = obj->wire_object.wbuf;
+ wbuf = obj->wbuf;
#endif
/* Asserts for wire length checking */
- LOCI_ASSERT(obj->length + obj->wire_object.obj_offset <=
+ LOCI_ASSERT(obj->length + obj->obj_offset <=
WBUF_CURRENT_BYTES(wbuf));
if (obj->parent == NULL) {
- LOCI_ASSERT(obj->length + obj->wire_object.obj_offset ==
+ LOCI_ASSERT(obj->length + obj->obj_offset ==
WBUF_CURRENT_BYTES(wbuf));
}
@@ -612,9 +587,9 @@
of_object_wire_init(of_object_t *obj, of_object_id_t base_object_id,
int max_len)
{
- if (obj->wire_type_get != NULL) {
+ if (loci_class_metadata[obj->object_id].wire_type_get != NULL) {
of_object_id_t id;
- obj->wire_type_get(obj, &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;
}
@@ -622,9 +597,9 @@
/* 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);
}
- if (obj->wire_length_get != NULL) {
+ if (loci_class_metadata[obj->object_id].wire_length_get != NULL) {
int length;
- obj->wire_length_get(obj, &length);
+ loci_class_metadata[obj->object_id].wire_length_get(obj, &length);
if (length < 0 || (max_len > 0 && length > max_len)) {
return OF_ERROR_PARSE;
}
@@ -665,8 +640,8 @@
d_wbuf = OF_OBJECT_TO_WBUF(dst);
s_wbuf = OF_OBJECT_TO_WBUF(src);
- dst_offset = dst->wire_object.obj_offset + dst_length;
- src_offset = src->wire_object.obj_offset;
+ dst_offset = dst->obj_offset + dst_length;
+ src_offset = src->obj_offset;
OF_WIRE_BUFFER_INIT_CHECK(d_wbuf, dst_offset + src->length);
MEMCPY(OF_WBUF_BUFFER_POINTER(d_wbuf, dst_offset),
OF_WBUF_BUFFER_POINTER(s_wbuf, 0), src->length);
@@ -685,7 +660,7 @@
of_packet_out_actions_length_set(of_packet_t *obj, int len)
{
if (obj == NULL || obj->object_id != OF_PACKET_IN ||
- obj->wire_object.wbuf == NULL) {
+ obj->wbuf == NULL) {
return OF_ERROR_PARAM;
}
@@ -696,7 +671,7 @@
_packet_out_data_offset_get(of_packet_t *obj)
{
if (obj == NULL || obj->object_id != OF_PACKET_IN ||
- obj->wire_object.wbuf == NULL) {
+ obj->wbuf == NULL) {
return -1;
}
diff --git a/c_gen/templates/of_object.h b/c_gen/templates/of_object.h
index 3172ad1..d299537 100644
--- a/c_gen/templates/of_object.h
+++ b/c_gen/templates/of_object.h
@@ -48,30 +48,6 @@
#include <loci/of_message.h>
#include <loci/of_wire_buf.h>
-/**
- * This is the number of bytes reserved for metadata in each
- * of_object_t instance.
- */
-#define OF_OBJECT_METADATA_BYTES 32
-
-/*
- * Generic accessors:
- *
- * Many objects have a length represented in the wire buffer
- * wire_length_get and wire_length_set access these values directly on the
- * wire.
- *
- * Many objects have a length represented in the wire buffer
- * wire_length_get and wire_length_set access these values directly on the
- * wire.
- *
- * FIXME: TBD if wire_length_set and wire_type_set are required.
- */
-typedef void (*of_wire_length_get_f)(of_object_t *obj, int *bytes);
-typedef void (*of_wire_length_set_f)(of_object_t *obj, int bytes);
-typedef void (*of_wire_type_get_f)(of_object_t *obj, of_object_id_t *id);
-typedef void (*of_wire_type_set_f)(of_object_t *obj);
-
/****************************************************************
* General list operations: first, next, append_setup, append_advance
****************************************************************/
@@ -91,16 +67,6 @@
extern of_object_t *of_object_new(int bytes);
extern of_object_t *of_object_dup(of_object_t *src);
-/**
- * Callback function prototype for deleting an object
- */
-typedef void (*of_object_delete_callback_f)(of_object_t *obj);
-
-typedef struct of_object_track_info_s {
- of_object_delete_callback_f delete_cb; /* To be implemented */
- void *delete_cookie;
-} of_object_track_info_t;
-
extern int of_object_xid_set(of_object_t *obj, uint32_t xid);
extern int of_object_xid_get(of_object_t *obj, uint32_t *xid);
@@ -135,8 +101,13 @@
void of_object_parent_length_update(of_object_t *obj, int delta);
struct of_object_s {
- /* The control block for the underlying data buffer */
- of_wire_object_t wire_object;
+ /** A pointer to the underlying buffer's management structure. */
+ of_wire_buffer_t *wbuf;
+
+ /** The start offset for this object relative to the start of the
+ * underlying buffer */
+ int obj_offset;
+
/* The LOCI type enum value of the object */
of_object_id_t object_id;
@@ -154,24 +125,6 @@
*/
int length;
of_version_t version;
-
- /*
- * Many objects have a length and/or type represented in the wire buffer
- * These accessors get and set those value when present. Treat as private.
- */
- of_wire_length_get_f wire_length_get;
- of_wire_length_set_f wire_length_set;
- of_wire_type_get_f wire_type_get;
- of_wire_type_set_f wire_type_set;
-
- of_object_track_info_t track_info;
-
- /*
- * Metadata available for applications. Ensure 8-byte alignment, but
- * that buffer is at least as large as requested. This data is not used
- * or inspected by LOCI.
- */
- uint64_t metadata[(OF_OBJECT_METADATA_BYTES + 7) / 8];
};
struct of_object_storage_s {
diff --git a/c_gen/templates/of_wire_buf.h b/c_gen/templates/of_wire_buf.h
index 0723454..dfec5c3 100644
--- a/c_gen/templates/of_wire_buf.h
+++ b/c_gen/templates/of_wire_buf.h
@@ -62,21 +62,6 @@
of_buffer_free_f free;
} of_wire_buffer_t;
-/**
- * Decouples object from underlying wire buffer
- *
- * Called a 'slice' in some places.
- */
-typedef struct of_wire_object_s {
- /** A pointer to the underlying buffer's management structure. */
- of_wire_buffer_t *wbuf;
- /** The start offset for this object relative to the start of the
- * underlying buffer */
- int obj_offset;
- /* Boolean, whether the object owns the wire buffer. */
- char owned;
-} of_wire_object_t;
-
#define WBUF_BUF(wbuf) (wbuf)->buf
#define WBUF_ALLOC_BYTES(wbuf) (wbuf)->alloc_bytes
#define WBUF_CURRENT_BYTES(wbuf) (wbuf)->current_bytes
@@ -104,15 +89,6 @@
*/
#define OF_WIRE_BUFFER_INDEX(wbuf, offset) (&((WBUF_BUF(wbuf))[offset]))
-/**
- * Return a pointer to a particular offset in the underlying buffer
- * associated with a wire object
- * @param wobj Pointer to an of_wire_object_t structure
- * @param offset The location to reference relative to the start of the object
- */
-#define OF_WIRE_OBJECT_INDEX(wobj, offset) \
- OF_WIRE_BUFFER_INDEX((wobj)->wbuf, (offset) + (wobj)->obj_offset)
-
/****************************************************************
* Object specific macros; of_object_t includes a wire_object
****************************************************************/
@@ -124,7 +100,7 @@
* @param offset The location to reference relative to the start of the object
*/
#define OF_OBJECT_BUFFER_INDEX(obj, offset) \
- OF_WIRE_OBJECT_INDEX(&((obj)->wire_object), offset)
+ OF_WIRE_BUFFER_INDEX((obj)->wbuf, (obj)->obj_offset + offset)
/**
* Return the absolute offset as an integer from a object-relative offset
@@ -132,7 +108,7 @@
* @param offset The location to reference relative to the start of the object
*/
#define OF_OBJECT_ABSOLUTE_OFFSET(obj, offset) \
- ((obj)->wire_object.obj_offset + offset)
+ ((obj)->obj_offset + offset)
/**
@@ -140,7 +116,7 @@
*
* Treat as private
*/
-#define OF_OBJECT_TO_WBUF(obj) ((obj)->wire_object.wbuf)
+#define OF_OBJECT_TO_WBUF(obj) ((obj)->wbuf)
@@ -174,7 +150,6 @@
FREE(wbuf);
return NULL;
}
- MEMSET(wbuf->buf, 0, a_bytes);
wbuf->current_bytes = 0;
wbuf->alloc_bytes = a_bytes;
@@ -245,6 +220,7 @@
LOCI_ASSERT(wbuf != NULL);
LOCI_ASSERT(wbuf->alloc_bytes >= bytes);
if (bytes > wbuf->current_bytes) {
+ MEMSET(wbuf->buf + wbuf->current_bytes, 0, bytes - wbuf->current_bytes);
wbuf->current_bytes = bytes;
}
}
diff --git a/c_gen/type_maps.py b/c_gen/type_maps.py
index ee452fc..7b745a6 100644
--- a/c_gen/type_maps.py
+++ b/c_gen/type_maps.py
@@ -41,7 +41,6 @@
import loxi_globals
invalid_type = "invalid_type"
-invalid_value = "0xeeee" # Note, as a string
################################################################
#
@@ -90,22 +89,10 @@
}
bsn_vport_types = {
- # version 1.0
- of_g.VERSION_1_0:dict(
- q_in_q = 0,
- ),
- # version 1.1
- of_g.VERSION_1_1:dict(
- q_in_q = 0,
- ),
- # version 1.2
- of_g.VERSION_1_2:dict(
- q_in_q = 0,
- ),
- # version 1.3
- of_g.VERSION_1_3:dict(
- q_in_q = 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(),
}
oxm_types = {
@@ -393,18 +380,6 @@
)
}
-##
-# These are the objects whose length is specified by an external
-# reference, specifically another data member in the class.
-#
-#external_length_spec = {
-# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
-# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
-# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
-# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
-#}
-
-
################################################################
#
# type_val is the primary data structure that maps an
@@ -582,236 +557,3 @@
}
),
}
-
-# Set to empty dict if no extension instructions defined
-extension_instruction_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(
- bsn = { # of_instruction_bsn_
- },
- nicira = { # of_instruction_nicira_
- }
- ),
-}
-
-# Set to empty dict if no extension instructions defined
-extension_queue_prop_subtype = {}
-
-# Set to empty dict if no extension instructions defined
-extension_table_feature_prop_subtype = {}
-
-extension_objects = [
- extension_message_subtype,
- extension_action_subtype,
- extension_action_id_subtype,
- extension_instruction_subtype,
- extension_instruction_id_subtype,
- extension_queue_prop_subtype,
- extension_table_feature_prop_subtype
-]
-
-################################################################
-# These are extension type generic (for messages, actions...)
-################################################################
-
-def extension_to_experimenter_name(cls):
- """
- Return the name of the experimenter if class is an
- extension, else None
-
- This is brute force; we search all extension data for a match
- """
-
- for ext_obj in extension_objects:
- for version, exp_list in ext_obj.items():
- for exp_name, classes in exp_list.items():
- if cls in classes:
- return exp_name
- return None
-
-def extension_to_experimenter_id(cls):
- """
- Return the ID of the experimenter if class is an
- extension, else None
- """
- exp_name = extension_to_experimenter_name(cls)
- if exp_name:
- return of_g.experimenter_name_to_id[exp_name]
- return None
-
-def extension_to_experimenter_macro_name(cls):
- """
- Return the "macro name" of the ID of the experimenter if class is an
- extension, else None
- """
- exp_name = extension_to_experimenter_name(cls)
- if exp_name:
- return "OF_EXPERIMENTER_ID_" + exp_name.upper()
- return None
-
-def extension_to_subtype(cls, version):
- """
- Generic across all extension objects, return subtype identifier
- """
- for ext_obj in extension_objects:
- for version, exp_list in ext_obj.items():
- for exp_name, classes in exp_list.items():
- if cls in classes:
- return classes[cls]
-
-def class_is_extension(cls, version):
- """
- Return True if class, version is recognized as an extension
- of any type (message, action....)
-
- Accepts of_g.OF_VERSION_ANY
- """
-
- for ext_obj in extension_objects:
- if cls_is_ext_obj(cls, version, ext_obj):
- return True
-
- return False
-
-# Internal
-def cls_is_ext_obj(cls, version, ext_obj):
- """
- @brief Return True if cls in an extension of type ext_obj
- @param cls The class to check
- @param version The version to check
- @param ext_obj The extension object dictionary (messages, actions...)
-
- Accepts of_g.VERSION_ANY
- """
-
- # Call with each version if "any" is passed
- if version == of_g.VERSION_ANY:
- for v in of_g.of_version_range:
- if cls_is_ext_obj(cls, v, ext_obj):
- return True
- else: # Version specified
- if version in ext_obj:
- for exp, subtype_vals in ext_obj[version].items():
- if cls in subtype_vals:
- return True
-
- return False
-
-################################################################
-# These are extension message specific
-################################################################
-
-def message_is_extension(cls, version):
- """
- Return True if cls, version is recognized as an extension
- This is brute force, searching records for a match
- """
- return cls_is_ext_obj(cls, version, extension_message_subtype)
-
-def extension_message_to_subtype(cls, version):
- """
- Return the subtype of the experimenter message if the class is an
- extension, else None
- """
- if version in extension_message_subtype:
- for exp, classes in extension_message_subtype[version].items():
- for ext_class, subtype in classes.items():
- if cls == ext_class:
- return subtype
- return None
-
-################################################################
-# These are extension action specific
-################################################################
-
-def action_is_extension(cls, version):
- """
- Return True if cls, version is recognized as an action extension
- This is brute force, searching records for a match
- """
- return cls_is_ext_obj(cls, version, extension_action_subtype)
-
-def extension_action_to_subtype(cls, version):
- """
- Return the ID of the action subtype (for its experimenteer)
- if class is an action extension, else None
- """
- if version in extension_action_subtype:
- for exp, classes in extension_action_subtype[version].items():
- if cls in classes:
- return classes[cls]
-
- return None
-
-################################################################
-# These are extension action specific
-################################################################
-
-def action_id_is_extension(cls, version):
- """
- Return True if cls, version is recognized as an action ID extension
- This is brute force, searching records for a match
- """
- if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
- return False
- return cls_is_ext_obj(cls, version, extension_action_id_subtype)
-
-def extension_action_id_to_subtype(cls, version):
- """
- Return the ID of the action ID subtype (for its experimenteer)
- if class is an action ID extension, else None
- """
- if version in extension_action_id_subtype:
- for exp, classes in extension_action_id_subtype[version].items():
- if cls in classes:
- return classes[cls]
-
- return None
-
-################################################################
-# These are extension instruction specific
-################################################################
-
-def instruction_is_extension(cls, version):
- """
- Return True if cls, version is recognized as an instruction extension
- This is brute force, searching records for a match
- """
- return cls_is_ext_obj(cls, version, extension_instruction_subtype)
-
-################################################################
-# These are extension instruction specific
-################################################################
-
-def instruction_id_is_extension(cls, version):
- """
- Return True if cls, version is recognized as an instruction ID extension
- This is brute force, searching records for a match
- """
- return cls_is_ext_obj(cls, version, extension_instruction_id_subtype)
-
-################################################################
-# These are extension queue_prop specific
-################################################################
-
-def queue_prop_is_extension(cls, version):
- """
- Return True if cls, version is recognized as an instruction extension
- This is brute force, searching records for a match
- """
- return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
-
-################################################################
-# These are extension table_feature_prop specific
-################################################################
-
-def table_feature_prop_is_extension(cls, version):
- """
- Return True if cls, version is recognized as an instruction extension
- This is brute force, searching records for a match
- """
- return cls_is_ext_obj(cls, version,
- extension_table_feature_prop_subtype)
diff --git a/c_gen/util.py b/c_gen/util.py
index 54e0f80..58a4355 100644
--- a/c_gen/util.py
+++ b/c_gen/util.py
@@ -37,6 +37,3 @@
def render_template(out, name, **context):
template_utils.render_template(out, name, template_path, context)
-
-def render_static(out, name):
- template_utils.render_static(out, name, template_path)
diff --git a/cmdline.py b/cmdline.py
index aafa019..6395fff 100644
--- a/cmdline.py
+++ b/cmdline.py
@@ -29,14 +29,6 @@
from loxi_globals import OFVersions
-##
-# Command line options
-options = {}
-
-##
-# Command line arguments
-args = []
-
##@var config_default
# The default configuration dictionary for LOXI code generation
options_default = {
@@ -77,10 +69,6 @@
@param cfg_dflt The default configuration dictionary
@return A pair (options, args) as per parser return
"""
- global options
- global args
- global target_version_list
-
parser = OptionParser(version="%prog 0.1")
#@todo Add options via dictionary
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index f55e7d3..452ac58 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -420,8 +420,8 @@
meter_features = JType("OFMeterFeatures")\
.op(read="OFMeterFeaturesVer$version.READER.readFrom(bb)",
write="$name.writeTo(bb)")
-bsn_vport_q_in_q = JType("OFBsnVportQInQ")\
- .op(read="OFBsnVportQInQVer$version.READER.readFrom(bb)",
+bsn_vport = JType("OFBsnVport")\
+ .op(read="OFBsnVportVer$version.READER.readFrom(bb)",
write="$name.writeTo(bb)")
flow_wildcards = JType("int") \
.op(read='bb.readInt()',
@@ -537,7 +537,7 @@
'of_meter_features_t': meter_features,
'of_bitmap_128_t': port_bitmap,
'of_checksum_128_t': checksum,
- 'of_bsn_vport_q_in_q_t': bsn_vport_q_in_q,
+ 'of_bsn_vport_t': bsn_vport,
}
## Map that defines exceptions from the standard loxi->java mapping scheme
@@ -649,6 +649,7 @@
'of_bsn_set_l2_table_request': { 'l2_table_enable': boolean },
'of_bsn_set_l2_table_reply': { 'l2_table_enable': boolean },
'of_bsn_set_pktin_suppression_request': { 'enabled': boolean },
+ 'of_bsn_controller_connection': { 'auxiliary_id' : of_aux_id},
'of_flow_stats_request': { 'out_group': of_group_default_any },
'of_aggregate_stats_request': { 'out_group': of_group_default_any },
diff --git a/java_gen/pre-written/pom.xml b/java_gen/pre-written/pom.xml
index 4f0dc74..b4e81cc 100644
--- a/java_gen/pre-written/pom.xml
+++ b/java_gen/pre-written/pom.xml
@@ -179,7 +179,7 @@
<failOnNoGitDirectory>false</failOnNoGitDirectory>
<gitDescribe>
- <skip>false</skip>
+ <skip>true</skip>
<always>true</always>
<abbrev>7</abbrev>
<dirty>-dirty</dirty>
@@ -211,10 +211,20 @@
<projectName>${project.name}</projectName>
<version>${project.version}</version>
<vcsRevision>${git.commit.id.abbrev}</vcsRevision>
- <vcsBranch>${git.branch}</vcsBranch>
- <vcsDirty>${git.commit.id.describe}</vcsDirty>
+ <!-- note: git.branch does not work in jenkins, because jenkins
+ builds the system in 'detached head' state. Because we mostly
+ about jenkins builds, we instead use the environment variable
+ GIT_BRANCH set by jenkins here -->
+ <vcsBranch>${env.GIT_BRANCH}</vcsBranch>
<buildUser>${user.name}</buildUser>
<buildDate>${git.build.time}</buildDate>
+ <!-- continuous integration information from jenkins env variables:
+ https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project#Buildingasoftwareproject-below -->
+ <ciBuildNumber>${env.BUILD_NUMBER}</ciBuildNumber>
+ <ciBuildId>${env.BUILD_ID}</ciBuildId>
+ <ciBuildTag>${env.BUILD_TAG}</ciBuildTag>
+ <ciJobName>${env.JOB_NAME}</ciJobName>
+i <ciNodeName>${env.NODE_NAME}</ciNodeName>
</manifestEntries>
</manifestSection>
</manifestSections>
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
index 2e675d4..ee605de 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
@@ -33,6 +33,8 @@
}
public static VlanVid ofVlan(int vid) {
+ if (vid == NO_MASK.vid)
+ return NO_MASK;
if ((vid & VALIDATION_MASK) != vid)
throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
return new VlanVid((short) vid);
diff --git a/lang_c.py b/lang_c.py
index 0a881e9..1969a83 100644
--- a/lang_c.py
+++ b/lang_c.py
@@ -84,7 +84,6 @@
'loci/src/of_object.c': static,
'loci/src/of_utils.c': static,
'loci/src/of_wire_buf.c': static,
- 'loci/src/loci_setup_from_add_fns.c': static,
# Static LOCI documentation
'loci/README': static,
@@ -107,7 +106,6 @@
'locitest/src/test_ext.c': static,
'locitest/src/test_list_limits.c': static,
'locitest/src/test_match_utils.c': static,
- 'locitest/src/test_setup_from_add.c': static,
'locitest/src/test_utils.c': static,
'locitest/src/test_validator.c': static,
'locitest/src/main.c': static,
@@ -131,3 +129,4 @@
c_gen.codegen.generate_strings(install_dir)
c_gen.codegen.generate_init_map(install_dir)
c_gen.codegen.generate_type_maps(install_dir)
+ c_gen.codegen.generate_class_metadata(install_dir)
diff --git a/loxi_front_end/frontend.py b/loxi_front_end/frontend.py
index bc79ed9..7b96fe3 100644
--- a/loxi_front_end/frontend.py
+++ b/loxi_front_end/frontend.py
@@ -112,7 +112,6 @@
ofinput.wire_versions.add(int(decl_ast[2]))
else:
raise InputError("Unrecognized wire protocol version %r" % decl_ast[2])
- found_wire_version = True
if not ofinput.wire_versions:
raise InputError("Missing #version metadata")
diff --git a/loxi_ir/ir.py b/loxi_ir/ir.py
index c8ca04d..0e95473 100644
--- a/loxi_ir/ir.py
+++ b/loxi_ir/ir.py
@@ -220,7 +220,7 @@
else:
raise Exception("Not a fixed length member: {}.{} [{}]".format(
self.of_class.name,
- self.name if hasattr("self", name) else "(unnnamed)",
+ self.name if hasattr("self", "name") else "(unnnamed)",
type(self).__name__))
"""
diff --git a/loxi_ir/ir_offset.py b/loxi_ir/ir_offset.py
index 2e6d004..9c6a5c1 100644
--- a/loxi_ir/ir_offset.py
+++ b/loxi_ir/ir_offset.py
@@ -172,7 +172,6 @@
"""
count, base_type = type_dec_to_count_base(fe_member.oftype)
- len_update = 0
if base_type in of_mixed_types:
base_type = of_mixed_types[base_type][version.wire_version]
diff --git a/loxigen.py b/loxigen.py
index 700168a..fcb2788 100755
--- a/loxigen.py
+++ b/loxigen.py
@@ -132,7 +132,6 @@
filenames = [x for x in filenames if not x.endswith('~')]
# Read input files
- all_ofinputs = []
for filename in filenames:
log("Processing struct file: " + filename)
ofinput = process_input_file(filename)
@@ -167,20 +166,9 @@
lang_file = "lang_%s" % options.lang
lang_module = __import__(lang_file)
- if hasattr(lang_module, "config_sanity_check") and not lang_module.config_sanity_check():
- debug("Config sanity check failed\n")
- sys.exit(1)
-
- # If list files, just list auto-gen files to stdout and exit
- if options.list_files:
- for name in lang_module.targets:
- print options.install_dir + '/' + name
- sys.exit(0)
-
log("\nGenerating files for target language %s\n" % options.lang)
loxi_globals.OFVersions.target_versions = target_versions
inputs = read_input()
build_ir(inputs)
- #log_all_class_info()
lang_module.generate(options.install_dir)
diff --git a/openflow_input/bsn_pktin_flag b/openflow_input/bsn_pktin_flag
new file mode 100644
index 0000000..54c942f
--- /dev/null
+++ b/openflow_input/bsn_pktin_flag
@@ -0,0 +1,45 @@
+// 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.
+
+#version 4
+
+// 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,
+// so we use the metadata OXM to carry this information.
+
+enum ofp_bsn_pktin_flag(wire_type=uint64_t, bitmask=True) {
+ OFP_BSN_PKTIN_FLAG_PDU = 0x1,
+ OFP_BSN_PKTIN_FLAG_NEW_HOST = 0x2,
+ OFP_BSN_PKTIN_FLAG_STATION_MOVE = 0x4,
+ OFP_BSN_PKTIN_FLAG_ARP = 0x8,
+ OFP_BSN_PKTIN_FLAG_DHCP = 0x10,
+ OFP_BSN_PKTIN_FLAG_L2_CPU = 0x20,
+ OFP_BSN_PKTIN_FLAG_DEBUG = 0x40,
+ OFP_BSN_PKTIN_FLAG_TTL_EXPIRED = 0x80,
+ OFP_BSN_PKTIN_FLAG_L3_MISS = 0x100,
+ OFP_BSN_PKTIN_FLAG_L3_CPU = 0x200,
+};
diff --git a/openflow_input/bsn_vport b/openflow_input/bsn_vport
index 4eeda8c..82d9d33 100644
--- a/openflow_input/bsn_vport
+++ b/openflow_input/bsn_vport
@@ -42,6 +42,14 @@
OF_BSN_VPORT_Q_IN_Q_UNTAGGED = 0xffff,
};
+enum ofp_bsn_vport_l2gre_flags(wire_type=uint32_t, bitmask=True) {
+ OF_BSN_VPORT_L2GRE_LOCAL_MAC_IS_VALID = 0x1,
+
+ /* DSCP flags are mutually exclusive */
+ OF_BSN_VPORT_L2GRE_DSCP_ASSIGN = 0x2,
+ OF_BSN_VPORT_L2GRE_DSCP_COPY = 0x4,
+};
+
// BSN Virtual port object header
// FIXME For now, inheritance is not exercised. See below.
struct of_bsn_vport {
@@ -55,7 +63,7 @@
struct of_bsn_vport_q_in_q : of_bsn_vport {
uint16_t type == 0;
- uint16_t length; /* 32 */
+ uint16_t length;
uint32_t port_no; /* OF port number of parent; usually phys port */
uint16_t ingress_tpid;
uint16_t ingress_vlan_id;
@@ -64,6 +72,26 @@
of_port_name_t if_name; /* Name to use in create operation */
};
+
+// L2GRE tunnel virtual port specification
+
+struct of_bsn_vport_l2gre : of_bsn_vport {
+ uint16_t type == 1;
+ uint16_t length;
+ enum ofp_bsn_vport_l2gre_flags flags;
+ of_port_no_t port_no; /* OF port number of parent */
+ of_mac_addr_t local_mac; /* Local MAC */
+ of_mac_addr_t nh_mac; /* Next Hop MAC */
+ of_ipv4_t src_ip; /* Source IP */
+ of_ipv4_t dst_ip; /* Destination IP */
+ uint8_t dscp;
+ uint8_t ttl;
+ pad(2);
+ uint32_t vpn; /* VPN ID (for GRE Key) */
+ of_port_name_t if_name; /* Virtual Interface Name */
+};
+
+
// Request from controller to switch to create vport
struct of_bsn_virtual_port_create_request : of_bsn_header {
uint8_t version;
@@ -72,8 +100,7 @@
uint32_t xid;
uint32_t experimenter == 0x5c16c7;
uint32_t subtype == 15;
- // FIXME This should be an instance of the inheritance superclass
- of_bsn_vport_q_in_q_t vport; // Description of vport to create
+ of_bsn_vport_t vport; // Description of vport to create
// Additional data follows depending on header type
};
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 44b4814..9c32e7f 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -118,9 +118,6 @@
ofclasses=modules_by_version[version]['meter_band'],
version=version)
-def generate_pp(out, name, version):
- util.render_template(out, 'pp.py')
-
def generate_util(out, name, version):
util.render_template(out, 'util.py', version=version)
diff --git a/py_gen/oftype.py b/py_gen/oftype.py
index ddde14a..7bd242e 100644
--- a/py_gen/oftype.py
+++ b/py_gen/oftype.py
@@ -142,7 +142,7 @@
'of_match_t': 'common.match',
'of_port_desc_t': 'common.port_desc',
'of_meter_features_t': 'common.meter_features',
- 'of_bsn_vport_q_in_q_t': 'common.bsn_vport_q_in_q',
+ 'of_bsn_vport_t': 'common.bsn_vport',
}
for (cls, pyclass) in embedded_structs.items():
diff --git a/py_gen/tests/generic_util.py b/py_gen/tests/generic_util.py
index 8b2f59f..03885a2 100644
--- a/py_gen/tests/generic_util.py
+++ b/py_gen/tests/generic_util.py
@@ -44,12 +44,6 @@
self.assertEquals(['\x04abc', '\x03de', '\x02f', '\x01'], a)
class TestOFReader(unittest.TestCase):
- def test_empty(self):
- reader = OFReader("")
- self.assertEquals(str(reader.read('')), "")
- with self.assertRaisesRegexp(loxi.ProtocolError, "Buffer too short"):
- reader.read_buf(1)
-
def test_simple(self):
reader = OFReader("abcdefg")
self.assertEquals(reader.read('2s')[0], "ab")
diff --git a/py_gen/util.py b/py_gen/util.py
index 2a0dc54..0d8c43f 100644
--- a/py_gen/util.py
+++ b/py_gen/util.py
@@ -41,18 +41,3 @@
def render_static(out, name):
template_utils.render_static(out, name, [templates_dir])
-
-def constant_for_value(version, group, value):
- enums = loxi_globals.ir[version].enums
- enum = [x for x in enums if x.name == group][0]
- for name, value2 in enum.values:
- if value == value2:
- return "const." + name
- return repr(value)
-
-def ancestors(ofclass):
- r = []
- while ofclass:
- r.append(ofclass)
- ofclass = ofclass.superclass
- return r
diff --git a/test_data/of13/bsn_virtual_port_create_request__l2gre.data b/test_data/of13/bsn_virtual_port_create_request__l2gre.data
new file mode 100644
index 0000000..b5fd5fa
--- /dev/null
+++ b/test_data/of13/bsn_virtual_port_create_request__l2gre.data
@@ -0,0 +1,77 @@
+-- binary
+04 04 # version, type
+00 48 # len
+01 02 03 04 # xid
+00 5c 16 c7 # experimenter
+00 00 00 0f # subtype
+00 01 # vport type
+00 38 # vport len
+00 00 00 03 # vport flags
+00 00 00 01 # vport port no
+0a 0b 0c 0d 0e 0f # local mac
+01 02 03 04 05 06 # next hop mac
+c0 00 00 02 # src ip
+c0 00 10 02 # dst ip
+01 40 00 00 # dscp, ttl, pad(2)
+00 00 be ef # vpn
+66 6f 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 # vport if name
+-- python
+ofp.message.bsn_virtual_port_create_request(
+xid=0x01020304, vport=ofp.bsn_vport_l2gre(
+flags=ofp.OF_BSN_VPORT_L2GRE_LOCAL_MAC_IS_VALID | ofp.OF_BSN_VPORT_L2GRE_DSCP_ASSIGN,
+port_no=1,
+local_mac=[0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f],
+nh_mac=[0x01, 0x02, 0x03, 0x04, 0x05, 0x06],
+src_ip=0xc0000002,
+dst_ip=0xc0001002,
+dscp=1,
+ttl=64,
+vpn=0xbeef,
+if_name="foo"
+))
+-- c
+obj = of_bsn_virtual_port_create_request_new(OF_VERSION_1_3);
+of_bsn_virtual_port_create_request_xid_set(obj, 0x01020304);
+{
+ of_object_t *vport = of_bsn_vport_l2gre_new(OF_VERSION_1_3);
+ {
+ of_port_name_t if_name = "foo";
+ of_mac_addr_t local_mac = { { 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f } };
+ of_mac_addr_t nh_mac = { { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 } };
+ of_bsn_vport_l2gre_flags_set(vport,
+ OF_BSN_VPORT_L2GRE_LOCAL_MAC_IS_VALID |
+ OF_BSN_VPORT_L2GRE_DSCP_ASSIGN);
+ of_bsn_vport_l2gre_port_no_set(vport, 1);
+ of_bsn_vport_l2gre_local_mac_set(vport, local_mac);
+ of_bsn_vport_l2gre_nh_mac_set(vport, nh_mac);
+ of_bsn_vport_l2gre_src_ip_set(vport, 0xc0000002);
+ of_bsn_vport_l2gre_dst_ip_set(vport, 0xc0001002);
+ of_bsn_vport_l2gre_dscp_set(vport, 1);
+ of_bsn_vport_l2gre_ttl_set(vport, 64);
+ of_bsn_vport_l2gre_vpn_set(vport, 0xbeef);
+ of_bsn_vport_l2gre_if_name_set(vport, if_name);
+ }
+ of_bsn_virtual_port_create_request_vport_set(obj, vport);
+ of_object_delete(vport);
+}
+-- java
+builder.setXid(0x01020304)
+ .setVport(
+ factory.buildBsnVportL2Gre()
+ .setFlags(
+ ImmutableSet.<OFBsnVportL2GreFlags>of(
+ OFBsnVportL2GreFlags.BSN_VPORT_L2GRE_LOCAL_MAC_IS_VALID,
+ OFBsnVportL2GreFlags.BSN_VPORT_L2GRE_DSCP_ASSIGN
+ )
+ )
+ .setPortNo(OFPort.of(1))
+ .setLocalMac(MacAddress.of("0a:0b:0c:0d:0e:0f"))
+ .setNhMac(MacAddress.of("01:02:03:04:05:06"))
+ .setSrcIp(IPv4Address.of("192.0.0.2"))
+ .setDstIp(IPv4Address.of("192.0.16.2"))
+ .setDscp((short)1)
+ .setTtl((short)64)
+ .setVpn(0xbeef)
+ .setIfName("foo")
+ .build()
+ );
diff --git a/test_data/of13/bsn_virtual_port_create_request__q_in_q.data b/test_data/of13/bsn_virtual_port_create_request__q_in_q.data
new file mode 100644
index 0000000..ca53fbe
--- /dev/null
+++ b/test_data/of13/bsn_virtual_port_create_request__q_in_q.data
@@ -0,0 +1,53 @@
+-- binary
+04 04 # version, type
+00 30 # len
+01 02 03 04 # xid
+00 5c 16 c7 # experimenter
+00 00 00 0f # subtype
+00 00 # vport type
+00 20 # vport len
+00 00 00 01 # vport port no
+00 02 # vport ingress tpid
+00 03 # vport ingress vlan id
+00 04 # vport egress tpid
+00 05 # vport egress vlan id
+66 6f 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 # vport if name
+-- python
+ofp.message.bsn_virtual_port_create_request(
+xid=0x01020304, vport=ofp.bsn_vport_q_in_q(
+port_no=1,
+ingress_tpid=2,
+ingress_vlan_id=3,
+egress_tpid=4,
+egress_vlan_id=5,
+if_name="foo"
+))
+-- c
+obj = of_bsn_virtual_port_create_request_new(OF_VERSION_1_3);
+of_bsn_virtual_port_create_request_xid_set(obj, 0x01020304);
+{
+ of_object_t *vport = of_bsn_vport_q_in_q_new(OF_VERSION_1_3);
+ {
+ of_port_name_t if_name = "foo";
+ of_bsn_vport_q_in_q_port_no_set(vport, 1);
+ of_bsn_vport_q_in_q_ingress_tpid_set(vport, 2);
+ of_bsn_vport_q_in_q_ingress_vlan_id_set(vport, 3);
+ of_bsn_vport_q_in_q_egress_tpid_set(vport, 4);
+ of_bsn_vport_q_in_q_egress_vlan_id_set(vport, 5);
+ of_bsn_vport_q_in_q_if_name_set(vport, if_name);
+ }
+ of_bsn_virtual_port_create_request_vport_set(obj, vport);
+ of_object_delete(vport);
+}
+-- java
+builder.setXid(0x01020304)
+ .setVport(
+ factory.buildBsnVportQInQ()
+ .setPortNo(1)
+ .setIngressTpid(2)
+ .setIngressVlanId(3)
+ .setEgressTpid(4)
+ .setEgressVlanId(5)
+ .setIfName("foo")
+ .build()
+ );