def generate_lists(install_dir): # Collect all the lists in use list_oftypes = set() for uclass in loxi_globals.unified.classes: for ofclass in uclass.version_classes.values(): for m in ofclass.members: if isinstance(m, ir.OFDataMember) and \ loxi_utils.oftype_is_list(m.oftype): list_oftypes.add(m.oftype) for oftype in sorted(list(list_oftypes)): cls, e_cls = loxi_utils_legacy.list_name_extract(oftype) e_cls = e_cls[:-2] e_uclass = loxi_globals.unified.class_by_name(e_cls) with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out: util.render_template( out, "list.c", cls=cls, e_cls=e_cls, e_uclass=e_uclass, wire_length_get=class_metadata_dict[e_cls].wire_length_get) # Append legacy generated code c_code_gen.gen_new_function_definitions(out, cls)
def build_ordered_classes(): """ Read in from files given on command line and update global state @fixme Should select versions to support from command line """ for version, protocol in loxi_globals.ir.items(): wire_version = version.wire_version # Populate global state version_name = of_g.of_version_wire2name[wire_version] for ofclass in protocol.classes: of_g.ordered_classes[wire_version].append(ofclass.name) legacy_members = [] pad_count = 0 for m in ofclass.members: if type(m) == OFPadMember: continue else: # HACK the C backend does not yet support of_oxm_t if m.oftype == 'of_oxm_t': m_type = 'of_oxm_header_t' # HACK the C backend does not yet support of_bsn_vport_t elif m.oftype == 'of_bsn_vport_t': m_type = 'of_bsn_vport_header_t' elif m.oftype.find("list(") == 0: (list_name, base_type) = loxi_utils.list_name_extract(m.oftype) m_type = list_name + "_t" else: enum = find(lambda e: e.name == m.oftype, protocol.enums) if enum and "wire_type" in enum.params: m_type = enum.params["wire_type"] else: m_type = m.oftype if m.offset is None: m_offset = -1 else: m_offset = m.offset legacy_members.append(dict(m_type=m_type, name=m.name, offset=m_offset)) versions[version_name]['classes'][ofclass.name] = legacy_members of_g.base_length[(ofclass.name, version.wire_version)] = ofclass.base_length if ofclass.is_fixed_length: of_g.is_fixed_length.add((ofclass.name, version.wire_version)) for enum in protocol.enums: for entry in enum.entries: identifiers.add_identifier( translation.loxi_name(entry.name), entry.name, enum.name, entry.value, wire_version, of_g.identifiers, of_g.identifiers_by_group)
def build_ordered_classes(): """ Read in from files given on command line and update global state @fixme Should select versions to support from command line """ for version, protocol in loxi_globals.ir.items(): wire_version = version.wire_version # Populate global state version_name = of_g.of_version_wire2name[wire_version] for ofclass in protocol.classes: of_g.ordered_classes[wire_version].append(ofclass.name) legacy_members = [] pad_count = 0 for m in ofclass.members: if type(m) == OFPadMember: continue else: if m.oftype.find("list(") == 0: (list_name, base_type) = loxi_utils.list_name_extract(m.oftype) m_type = list_name + "_t" else: enum = find(lambda e: e.name == m.oftype, protocol.enums) if enum and "wire_type" in enum.params: m_type = enum.params["wire_type"] else: m_type = m.oftype if m.offset is None: m_offset = -1 else: m_offset = m.offset legacy_members.append( dict(m_type=m_type, name=m.name, offset=m_offset)) versions[version_name]['classes'][ofclass.name] = legacy_members of_g.base_length[(ofclass.name, version.wire_version)] = ofclass.base_length if ofclass.is_fixed_length: of_g.is_fixed_length.add((ofclass.name, version.wire_version)) for enum in protocol.enums: for entry in enum.entries: identifiers.add_identifier(translation.loxi_name(entry.name), entry.name, enum.name, entry.value, wire_version, of_g.identifiers, of_g.identifiers_by_group)
def analyze_input(): """ Add information computed from the input, including offsets and lengths of struct members and the set of list and action_id types. """ # Generate header classes for inheritance parents for wire_version, ordered_classes in of_g.ordered_classes.items(): classes = versions[of_g.of_version_wire2name[wire_version]]['classes'] for cls in ordered_classes: if type_maps.class_is_inheritance_root(cls): new_cls = cls + '_header' of_g.ordered_classes[wire_version].append(new_cls) classes[new_cls] = classes[cls] of_g.base_length[(new_cls, wire_version)] = of_g.base_length[(cls, wire_version)] if (cls, wire_version) in of_g.is_fixed_length: of_g.is_fixed_length.add((cls, wire_version)) # Create lists for version, protocol in loxi_globals.ir.items(): lists = set() classes = versions[of_g.of_version_wire2name[version.wire_version]]['classes'] for ofclass in protocol.classes: for m in ofclass.members: if isinstance(m, OFDataMember) and m.oftype.find("list(") == 0: (list_name, base_type) = loxi_utils.list_name_extract(m.oftype) lists.add(list_name) for list_type in lists: classes[list_type] = [] of_g.ordered_classes[version.wire_version].append(list_type) of_g.base_length[(list_type, version.wire_version)] = 0 # Find special offsets # These are defined as members (except padding) that don't have a fixed # offset. The special_offsets map stores the name of the previous member. for version, protocol in loxi_globals.ir.items(): for ofclass in protocol.classes: prev_member = None for m in ofclass.members: if isinstance(m, OFPadMember): continue if m.offset == None: old = of_g.special_offsets.get((ofclass.name, m.name)) if old and old != prev_member.name: raise Exception("Error: special offset changed: version=%s cls=%s member=%s old=%s new=%s" % (version, ofclass.name, m.name, old, prev_member.name)) of_g.special_offsets[(ofclass.name, m.name)] = prev_member.name prev_member = m
def generate_lists(install_dir): # Collect all the lists in use list_oftypes = set() for uclass in loxi_globals.unified.classes: for ofclass in uclass.version_classes.values(): for m in ofclass.members: if isinstance(m, ir.OFDataMember) and \ loxi_utils.oftype_is_list(m.oftype): list_oftypes.add(m.oftype) for oftype in sorted(list(list_oftypes)): cls, e_cls = loxi_utils_legacy.list_name_extract(oftype) e_cls = e_cls[:-2] e_uclass = loxi_globals.unified.class_by_name(e_cls) with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out: util.render_template(out, "list.c", cls=cls, e_cls=e_cls, e_uclass=e_uclass, wire_length_get=class_metadata_dict[e_cls].wire_length_get) # Append legacy generated code c_code_gen.gen_new_function_definitions(out, cls)
def analyze_input(): """ Add information computed from the input, including offsets and lengths of struct members and the set of list and action_id types. """ # Create lists for version, protocol in loxi_globals.ir.items(): lists = set() classes = versions[of_g.of_version_wire2name[ version.wire_version]]['classes'] for ofclass in protocol.classes: for m in ofclass.members: if isinstance(m, OFDataMember) and m.oftype.find("list(") == 0: (list_name, base_type) = loxi_utils.list_name_extract(m.oftype) lists.add(list_name) for list_type in lists: classes[list_type] = [] of_g.ordered_classes[version.wire_version].append(list_type) of_g.base_length[(list_type, version.wire_version)] = 0 # Find special offsets # These are defined as members (except padding) that don't have a fixed # offset. The special_offsets map stores the name of the previous member. for version, protocol in loxi_globals.ir.items(): for ofclass in protocol.classes: prev_member = None for m in ofclass.members: if isinstance(m, OFPadMember): continue if m.offset == None: old = of_g.special_offsets.get((ofclass.name, m.name)) if old and old != prev_member.name: raise Exception( "Error: special offset changed: version=%s cls=%s member=%s old=%s new=%s" % (version, ofclass.name, m.name, old, prev_member.name)) of_g.special_offsets[(ofclass.name, m.name)] = prev_member.name prev_member = m
def calculate_offsets_and_lengths(ordered_classes, classes, wire_version): """ Generate the offsets for fixed offset class members Also calculate the class_sizes when possible. @param classes The classes to process @param wire_version The wire version for this set of classes Updates global variables """ lists = set() # Generate offsets for cls in ordered_classes: fixed_offset = 0 # The last "good" offset seen offset = 0 last_offset = 0 last_name = "-" for member in classes[cls]: m_type = member["m_type"] name = member["name"] if last_offset == -1: if name == "pad": log("Skipping pad for special offset for %s" % cls) else: log("SPECIAL OFS: Member %s (prev %s), class %s ver %d" % (name, last_name, cls, wire_version)) if (((cls, name) in of_g.special_offsets) and (of_g.special_offsets[(cls, name)] != last_name)): debug("ERROR: special offset prev name changed") debug(" cls %s. name %s. version %d. was %s. now %s" % cls, name, wire_version, of_g.special_offsets[(cls, name)], last_name) sys.exit(1) of_g.special_offsets[(cls, name)] = last_name member["offset"] = offset if m_type.find("list(") == 0: (list_name, base_type) = loxi_utils.list_name_extract(m_type) lists.add(list_name) member["m_type"] = list_name + "_t" offset = -1 elif m_type.find("struct") == 0: debug("ERROR found struct: %s.%s " % (cls, name)) sys.exit(1) elif m_type == "octets": log("offset gen skipping octets: %s.%s " % (cls, name)) offset = -1 else: offset, len_update = update_offset(cls, wire_version, name, offset, m_type) if offset != -1: fixed_offset = offset else: fixed_offset += len_update log("offset is -1 for %s.%s version %d " % (cls, name, wire_version)) last_offset = offset last_name = name of_g.base_length[(cls, wire_version)] = fixed_offset if (offset != -1): of_g.is_fixed_length.add((cls, wire_version)) for list_type in lists: classes[list_type] = [] of_g.ordered_classes[wire_version].append(list_type) of_g.base_length[(list_type, wire_version)] = 0
def calculate_offsets_and_lengths(ordered_classes, classes, wire_version): """ Generate the offsets for fixed offset class members Also calculate the class_sizes when possible. @param classes The classes to process @param wire_version The wire version for this set of classes Updates global variables """ lists = set() # Generate offsets for cls in ordered_classes: fixed_offset = 0 # The last "good" offset seen offset = 0 last_offset = 0 last_name = "-" for member in classes[cls]: m_type = member["m_type"] name = member["name"] if last_offset == -1: if name == "pad": log("Skipping pad for special offset for %s" % cls) else: log("SPECIAL OFS: Member %s (prev %s), class %s ver %d" % (name, last_name, cls, wire_version)) if (((cls, name) in of_g.special_offsets) and (of_g.special_offsets[(cls, name)] != last_name)): debug("ERROR: special offset prev name changed") debug( " cls %s. name %s. version %d. was %s. now %s" % cls, name, wire_version, of_g.special_offsets[(cls, name)], last_name) sys.exit(1) of_g.special_offsets[(cls, name)] = last_name member["offset"] = offset if m_type.find("list(") == 0: (list_name, base_type) = loxi_utils.list_name_extract(m_type) lists.add(list_name) member["m_type"] = list_name + "_t" offset = -1 elif m_type.find("struct") == 0: debug("ERROR found struct: %s.%s " % (cls, name)) sys.exit(1) elif m_type == "octets": log("offset gen skipping octets: %s.%s " % (cls, name)) offset = -1 else: offset, len_update = update_offset(cls, wire_version, name, offset, m_type) if offset != -1: fixed_offset = offset else: fixed_offset += len_update log("offset is -1 for %s.%s version %d " % (cls, name, wire_version)) last_offset = offset last_name = name of_g.base_length[(cls, wire_version)] = fixed_offset if (offset != -1): of_g.is_fixed_length.add((cls, wire_version)) for list_type in lists: classes[list_type] = [] of_g.ordered_classes[wire_version].append(list_type) of_g.base_length[(list_type, wire_version)] = 0