def gen_obj_show_h(out, name): loxi_utils.gen_c_copy_license(out) out.write(""" /** * * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen. * * Header file for object showing. */ /** * Show object declarations * * Routines that emit a human-readable dump of each object. * */ #if !defined(_LOCI_OBJ_SHOW_H_) #define _LOCI_OBJ_SHOW_H_ #include <loci/loci.h> #include <stdio.h> /* g++ requires this to pick up PRI, etc. * See http://gcc.gnu.org/ml/gcc-help/2006-10/msg00223.html */ #if !defined(__STDC_FORMAT_MACROS) #define __STDC_FORMAT_MACROS #endif #include <inttypes.h> /** * Show any OF object. */ int of_object_show(loci_writer_f writer, void* cookie, of_object_t* obj); """) for version in of_g.of_version_range: for cls in of_g.standard_class_order: if not loxi_utils.class_in_version(cls, version): continue if type_maps.class_is_virtual(cls): continue out.write("""\ int %(cls)s_%(ver_name)s_show(loci_writer_f writer, void* cookie, of_object_t *obj); """ % dict(cls=cls, ver_name=loxi_utils.version_to_name(version))) out.write(""" #endif /* _LOCI_OBJ_SHOW_H_ */ """)
def gen_obj_show_c(out, name): loxi_utils.gen_c_copy_license(out) out.write(""" /** * * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen. * * Source file for object showing. * */ #define DISABLE_WARN_UNUSED_RESULT #include <loci/loci.h> #include <loci/loci_show.h> #include <loci/loci_obj_show.h> static int unknown_show(loci_writer_f writer, void* cookie, of_object_t *obj) { return writer(cookie, "Unable to print object of type %d, version %d\\n", obj->object_id, obj->version); } """) for version in of_g.of_version_range: ver_name = loxi_utils.version_to_name(version) for cls in of_g.standard_class_order: if not loxi_utils.class_in_version(cls, version): continue if type_maps.class_is_virtual(cls): continue out.write(""" int %(cls)s_%(ver_name)s_show(loci_writer_f writer, void* cookie, of_object_t *obj) { int out = 0; """ % dict(cls=cls, ver_name=ver_name)) members, member_types = loxi_utils.all_member_types_get(cls, version) for m_type in member_types: if loxi_utils.type_is_scalar(m_type) or m_type in \ ["of_match_t", "of_octets_t"]: # Declare instance of these out.write(" %s %s;\n" % (m_type, var_name_map(m_type))) else: out.write(""" %(m_type)s %(v_name)s; """ % dict(m_type=m_type, v_name=var_name_map(m_type))) if loxi_utils.class_is_list(m_type): out.write(" of_object_t elt;\n int rv;\n") for member in members: m_type = member["m_type"] m_name = member["name"] emitter = gen_emitter(cls, m_name, m_type) if loxi_utils.skip_member_name(m_name): continue if (loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]): out.write(""" %(cls)s_%(m_name)s_get(obj, &%(v_name)s); out += writer(cookie, "%(m_name)s="); out += %(emitter)s(writer, cookie, %(v_name)s); out += writer(cookie, " "); """ % dict(cls=cls, m_name=m_name, m_type=m_type, v_name=var_name_map(m_type), emitter=emitter)) elif loxi_utils.class_is_list(m_type): sub_cls = m_type[:-2] # Trim _t elt_type = loxi_utils.list_to_entry_type(m_type) out.write(""" out += writer(cookie, "%(elt_type)s={ "); %(cls)s_%(m_name)s_bind(obj, &%(v_name)s); %(u_type)s_ITER(&%(v_name)s, &elt, rv) { of_object_show(writer, cookie, (of_object_t *)&elt); } out += writer(cookie, "} "); """ % dict(sub_cls=sub_cls, u_type=sub_cls.upper(), v_name=var_name_map(m_type), elt_type=elt_type, cls=cls, m_name=m_name, m_type=m_type)) else: sub_cls = m_type[:-2] # Trim _t out.write(""" %(cls)s_%(m_name)s_bind(obj, &%(v_name)s); out += of_object_show(writer, cookie, &%(v_name)s); """ % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, v_name=var_name_map(m_type), ver_name=ver_name)) out.write(""" return out; } """) out.write(""" /** * Log a match entry */ int loci_show_match(loci_writer_f writer, void* cookie, of_match_t *match) { int out = 0; """) for key, entry in match.of_match_members.items(): m_type = entry["m_type"] emitter = gen_emitter('of_match', key, m_type) out.write(""" if (OF_MATCH_MASK_%(ku)s_ACTIVE_TEST(match)) { out += writer(cookie, "%(key)s active="); out += %(emitter)s(writer, cookie, match->fields.%(key)s); out += writer(cookie, "/"); out += %(emitter)s(writer, cookie, match->masks.%(key)s); out += writer(cookie, " "); } """ % dict(key=key, ku=key.upper(), emitter=emitter, m_type=m_type)) out.write(""" return out; } """) # Generate big table indexed by version and object for version in of_g.of_version_range: out.write(""" static const loci_obj_show_f show_funs_v%(version)s[OF_OBJECT_COUNT] = { """ % dict(version=version)) out.write(" unknown_show, /* of_object, not a valid specific type */\n") for j, cls in enumerate(of_g.all_class_order): comma = "" if j < len(of_g.all_class_order) - 1: # Avoid ultimate comma comma = "," if (not loxi_utils.class_in_version(cls, version) or type_maps.class_is_virtual(cls)): out.write(" unknown_show%s\n" % comma); else: out.write(" %s_%s_show%s\n" % (cls, loxi_utils.version_to_name(version), comma)) out.write("};\n\n") out.write(""" static const loci_obj_show_f *const show_funs[] = { """) for version in of_g.of_version_range: out.write(" [%(v)d] = show_funs_v%(v)d,\n" % dict(v=version)) out.write("""\ }; int of_object_show(loci_writer_f writer, void* cookie, of_object_t *obj) { if ((obj->object_id > 0) && (obj->object_id < OF_OBJECT_COUNT)) { if (OF_VERSION_OKAY(obj->version)) { return show_funs[obj->version][obj->object_id](writer, cookie, (of_object_t *)obj); } else { return writer(cookie, "Bad version %d\\n", obj->version); } } return writer(cookie, "Bad object id %d\\n", obj->object_id); } """)
def populate_type_maps(): """ Use the type members in the IR to fill out the legacy type_maps. """ def split_inherited_cls(cls): if cls == 'of_meter_band_stats': # HACK not a subtype of of_meter_band return None, None for parent in sorted(type_maps.inheritance_data.keys(), reverse=True): if cls.startswith(parent): return (parent, cls[len(parent)+1:]) return None, None def find_experimenter(parent, cls): for experimenter in sorted(of_g.experimenter_name_to_id.keys(), reverse=True): prefix = parent + '_' + experimenter if cls.startswith(prefix) and cls != prefix: return experimenter return None def find_type_value(ofclass, m_name): for m in ofclass.members: if isinstance(m, OFTypeMember) and m.name == m_name: return m.value raise KeyError("ver=%d, cls=%s, m_name=%s" % (wire_version, cls, m_name)) # Most inheritance classes: actions, instructions, etc for version, protocol in loxi_globals.ir.items(): wire_version = version.wire_version for ofclass in protocol.classes: cls = ofclass.name parent, subcls = split_inherited_cls(cls) if not (parent and subcls): continue if parent == 'of_oxm': type_len = find_type_value(ofclass, 'type_len') oxm_class = (type_len >> 16) & 0xffff if oxm_class != 0x8000: # Do not include experimenter OXMs in the main table val = type_maps.invalid_type else: val = (type_len >> 8) & 0xff else: val = find_type_value(ofclass, 'type') type_maps.inheritance_data[parent][wire_version][subcls] = val # Extensions (only actions for now) experimenter = find_experimenter(parent, cls) if parent == 'of_action' and experimenter: val = find_type_value(ofclass, 'subtype') type_maps.extension_action_subtype[wire_version][experimenter][cls] = val if wire_version >= of_g.VERSION_1_3: cls2 = parent + "_id" + cls[len(parent):] type_maps.extension_action_id_subtype[wire_version][experimenter][cls2] = val elif parent == 'of_instruction' and experimenter: val = find_type_value(ofclass, 'subtype') type_maps.extension_instruction_subtype[wire_version][experimenter][cls] = val # Messages for version, protocol in loxi_globals.ir.items(): wire_version = version.wire_version for ofclass in protocol.classes: cls = ofclass.name # HACK (though this is what loxi_utils.class_is_message() does) if not [x for x in ofclass.members if isinstance(x, OFDataMember) and x.name == 'xid']: continue if type_maps.class_is_virtual(cls): continue subcls = cls[3:] val = find_type_value(ofclass, 'type') if not val in type_maps.message_types[wire_version].values(): type_maps.message_types[wire_version][subcls] = val # Extensions experimenter = find_experimenter('of', cls) if experimenter and ofclass.is_subclassof("of_experimenter"): val = find_type_value(ofclass, 'subtype') type_maps.extension_message_subtype[wire_version][experimenter][cls] = val type_maps.generate_maps()
def populate_type_maps(): """ Use the type members in the IR to fill out the legacy type_maps. """ def split_inherited_cls(cls): if cls == 'of_meter_band_stats': # HACK not a subtype of of_meter_band return None, None for parent in sorted(type_maps.inheritance_data.keys(), reverse=True): if cls.startswith(parent): return (parent, cls[len(parent) + 1:]) return None, None def find_experimenter(parent, cls): for experimenter in sorted(of_g.experimenter_name_to_id.keys(), reverse=True): prefix = parent + '_' + experimenter if cls.startswith(prefix) and cls != prefix: return experimenter return None def find_type_value(ofclass, m_name): for m in ofclass.members: if isinstance(m, OFTypeMember) and m.name == m_name: return m.value raise KeyError("ver=%d, cls=%s, m_name=%s" % (wire_version, cls, m_name)) # Most inheritance classes: actions, instructions, etc for version, protocol in loxi_globals.ir.items(): wire_version = version.wire_version for ofclass in protocol.classes: cls = ofclass.name parent, subcls = split_inherited_cls(cls) if not (parent and subcls): continue if parent == 'of_oxm': type_len = find_type_value(ofclass, 'type_len') oxm_class = (type_len >> 16) & 0xffff if oxm_class != 0x8000: # Do not include experimenter OXMs in the main table val = type_maps.invalid_type else: val = (type_len >> 8) & 0xff else: val = find_type_value(ofclass, 'type') type_maps.inheritance_data[parent][wire_version][subcls] = val # Extensions (only actions for now) experimenter = find_experimenter(parent, cls) if parent == 'of_action' and experimenter: val = find_type_value(ofclass, 'subtype') type_maps.extension_action_subtype[wire_version][experimenter][ cls] = val if wire_version >= of_g.VERSION_1_3: cls2 = parent + "_id" + cls[len(parent):] type_maps.extension_action_id_subtype[wire_version][ experimenter][cls2] = val elif parent == 'of_instruction' and experimenter: val = find_type_value(ofclass, 'subtype') type_maps.extension_instruction_subtype[wire_version][ experimenter][cls] = val # Messages for version, protocol in loxi_globals.ir.items(): wire_version = version.wire_version for ofclass in protocol.classes: cls = ofclass.name # HACK (though this is what loxi_utils.class_is_message() does) if not [ x for x in ofclass.members if isinstance(x, OFDataMember) and x.name == 'xid' ]: continue if type_maps.class_is_virtual(cls): continue subcls = cls[3:] val = find_type_value(ofclass, 'type') if not val in type_maps.message_types[wire_version].values(): type_maps.message_types[wire_version][subcls] = val # Extensions experimenter = find_experimenter('of', cls) if experimenter and ofclass.is_subclassof("of_experimenter"): val = find_type_value(ofclass, 'subtype') type_maps.extension_message_subtype[wire_version][ experimenter][cls] = val type_maps.generate_maps()