Beispiel #1
0
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 action_id classes for OF 1.3
    for wire_version, ordered_classes in of_g.ordered_classes.items():
        if not wire_version in [of_g.VERSION_1_3]:
            continue
        classes = versions[of_g.of_version_wire2name[wire_version]]['classes']
        for cls in ordered_classes:
            if not loxi_utils.class_is_action(cls):
                continue
            action = cls[10:]
            if action == '' or action == 'header':
                continue
            name = "of_action_id_" + action
            members = classes["of_action"][:]
            of_g.ordered_classes[wire_version].append(name)
            if type_maps.action_id_is_extension(name, wire_version):
                # Copy the base action classes thru subtype
                members = classes["of_action_" + action][:4]
            classes[name] = members

    # @fixme If we support extended actions in OF 1.3, need to add IDs
    # for them here

    for wire_version in of_g.wire_ver_map.keys():
        version_name = of_g.of_version_wire2name[wire_version]
        calculate_offsets_and_lengths(
            of_g.ordered_classes[wire_version],
            versions[version_name]['classes'],
            wire_version)
Beispiel #2
0
def get_type_values(cls, version):
    """
    Returns a map from the name of the type member to its value.
    """
    type_values = {}

    # Primary wire type
    if utils.class_is_message(cls):
        type_values['version'] = 'const.OFP_VERSION'
        type_values['type'] = util.constant_for_value(version, "ofp_type", util.primary_wire_type(cls, version))
        if cls in type_maps.flow_mod_list:
            type_values['_command'] = util.constant_for_value(version, "ofp_flow_mod_command",
                                                              type_maps.flow_mod_types[version][cls[8:]])
        if cls in type_maps.stats_request_list:
            type_values['stats_type'] = util.constant_for_value(version, "ofp_stats_types",
                                                                type_maps.stats_types[version][cls[3:-14]])
        if cls in type_maps.stats_reply_list:
            type_values['stats_type'] = util.constant_for_value(version, "ofp_stats_types",
                                                                type_maps.stats_types[version][cls[3:-12]])
        if type_maps.message_is_extension(cls, version):
            type_values['experimenter'] = '%#x' % type_maps.extension_to_experimenter_id(cls)
            type_values['subtype'] = type_maps.extension_message_to_subtype(cls, version)
    elif utils.class_is_action(cls):
        type_values['type'] = util.constant_for_value(version, "ofp_action_type", util.primary_wire_type(cls, version))
        if type_maps.action_is_extension(cls, version):
            type_values['experimenter'] = '%#x' % type_maps.extension_to_experimenter_id(cls)
            type_values['subtype'] = type_maps.extension_action_to_subtype(cls, version)
    elif utils.class_is_queue_prop(cls):
        type_values['type'] = util.constant_for_value(version, "ofp_queue_properties", util.primary_wire_type(cls, version))

    return type_values
Beispiel #3
0
def build_ofclasses(version):
    blacklist = ["of_action", "of_action_header", "of_header", "of_queue_prop",
                 "of_queue_prop_header", "of_experimenter", "of_action_experimenter",
                 "of_oxm", "of_oxm_header", "of_oxm_experimenter_header",
                 "of_hello_elem", "of_hello_elem_header"]
    ofclasses = []
    for cls in of_g.standard_class_order:
        if version not in of_g.unified[cls] or cls in blacklist:
            continue
        unified_class = util.lookup_unified_class(cls, version)

        # Name for the generated Python class
        if utils.class_is_action(cls):
            pyname = cls[10:]
        elif utils.class_is_oxm(cls):
            pyname = cls[7:]
        else:
            pyname = cls[3:]

        type_values = get_type_values(cls, version)
        members = []

        length_member = None
        type_members = []
        pad_count = 0

        for member in unified_class['members']:
            if member['name'] in ['length', 'len']:
                length_member = LengthMember(name=member['name'],
                                             offset=member['offset'],
                                             oftype=oftype.OFType(member['m_type'], version))
            elif member['name'] in type_values:
                type_members.append(TypeMember(name=member['name'],
                                               offset=member['offset'],
                                               oftype=oftype.OFType(member['m_type'], version),
                                               value=type_values[member['name']]))
            else:
                # HACK ensure member names are unique
                if member['name'].startswith("pad"):
                    if pad_count == 0:
                        m_name = 'pad'
                    else:
                        m_name = "pad%d" % pad_count
                    pad_count += 1
                else:
                    m_name = member['name']
                members.append(Member(name=m_name,
                                      oftype=oftype.OFType(member['m_type'], version),
                                      offset=member['offset'],
                                      skip=member['name'] in of_g.skip_members))

        ofclasses.append(
            OFClass(name=cls,
                    pyname=pyname,
                    members=members,
                    length_member=length_member,
                    type_members=type_members,
                    min_length=of_g.base_length[(cls, version)],
                    is_fixed_length=(cls, version) in of_g.is_fixed_length))
    return ofclasses
Beispiel #4
0
def generate_common(out, name, version):
    ofclasses = [x for x in build_ofclasses(version)
                 if not utils.class_is_message(x.name)
                    and not utils.class_is_action(x.name)
                    and not utils.class_is_oxm(x.name)
                    and not utils.class_is_list(x.name)]
    util.render_template(out, 'common.py', ofclasses=ofclasses, version=version)
Beispiel #5
0
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 action_id classes for OF 1.3
    for wire_version, ordered_classes in of_g.ordered_classes.items():
        if not wire_version in [of_g.VERSION_1_3]:
            continue
        classes = versions[of_g.of_version_wire2name[wire_version]]['classes']
        for cls in ordered_classes:
            if not loxi_utils.class_is_action(cls):
                continue
            action = cls[10:]
            if action == '' or action == 'header':
                continue
            name = "of_action_id_" + action
            members = classes["of_action"][:]
            of_g.ordered_classes[wire_version].append(name)
            if type_maps.action_id_is_extension(name, wire_version):
                # Copy the base action classes thru subtype
                members = classes["of_action_" + action][:4]
            classes[name] = members

    # @fixme If we support extended actions in OF 1.3, need to add IDs
    # for them here

    for wire_version in of_g.wire_ver_map.keys():
        version_name = of_g.of_version_wire2name[wire_version]
        calculate_offsets_and_lengths(of_g.ordered_classes[wire_version],
                                      versions[version_name]['classes'],
                                      wire_version)
Beispiel #6
0
def generate_action(out, name, version):
    ofclasses = [
        x for x in build_ofclasses(version) if utils.class_is_action(x.name)
    ]
    util.render_template(out,
                         'action.py',
                         ofclasses=ofclasses,
                         version=version)
Beispiel #7
0
 def class_info(self):
     """ return tuple of (package_prefix, parent_class) for the current JavaOFInterface"""
     # FIXME: This duplicates inheritance information that is now available in the loxi_ir
     # model (note, that the loxi model is on versioned classes). Should check/infer the
     # inheritance information from the versioned lox_ir classes.
     if re.match(r'OFStatsRequest$', self.name):
         return ("", "OFMessage", "T extends OFStatsReply")
     elif re.match(r'OF.+StatsRequest$', self.name):
         return ("", "OFStatsRequest<{}>".format(re.sub(r'Request$', 'Reply', self.name)), None)
     elif re.match(r'OF.+StatsReply$', self.name):
         return ("", "OFStatsReply", None)
     elif re.match(r'OF.+ErrorMsg$', self.name):
         return ("", "OFErrorMsg", None)
     elif re.match(r'OFFlow(Add|Modify(Strict)?|Delete(Strict)?)$', self.name):
         return ("", "OFFlowMod", None)
     elif loxi_utils.class_is_message(self.c_name) and re.match(r'OFBsn.+$', self.name) and self.name != "OFBsnHeader":
         return ("", "OFBsnHeader", None)
     elif loxi_utils.class_is_message(self.c_name) and re.match(r'OFNicira.+$', self.name) and self.name != "OFNiciraHeader":
         return ("", "OFNiciraHeader", None)
     elif self.name == "OFBsnHeader" or self.name =="OFNiciraHeader":
         return ("", "OFExperimenter", None)
     elif re.match(r'OFMatch.*', self.name):
         return ("", "Match", None)
     elif loxi_utils.class_is_message(self.c_name):
         return ("", "OFMessage", None)
     elif loxi_utils.class_is_action(self.c_name):
         if re.match(r'OFActionBsn.+', self.name):
             return ("action", "OFActionBsn", None)
         elif re.match(r'OFActionNicira.+', self.name):
             return ("action", "OFActionNicira", None)
         elif self.name == "OFActionBsn" or self.name == "OFActionNicira":
             return ("action", "OFActionExperimenter", None)
         else:
             return ("action", "OFAction", None)
     elif re.match(r'OFBsnVport.+$', self.name):
         return ("", "OFBsnVport", None)
     elif self.name == "OFOxm":
         return ("oxm", None, "T extends OFValueType<T>")
     elif loxi_utils.class_is_oxm(self.c_name):
         if self.name in model.oxm_map:
             return ("oxm", "OFOxm<%s>" % model.oxm_map[self.name].type_name, None)
         else:
             return ("oxm", "OFOxm", None)
     elif loxi_utils.class_is_instruction(self.c_name):
         return ("instruction", "OFInstruction", None)
     elif loxi_utils.class_is_meter_band(self.c_name):
         return ("meterband", "OFMeterBand", None)
     elif loxi_utils.class_is_queue_prop(self.c_name):
         return ("queueprop", "OFQueueProp", None)
     elif loxi_utils.class_is_hello_elem(self.c_name):
         return ("", "OFHelloElem", None)
     elif loxi_utils.class_is_table_feature_prop(self.c_name):
         return ("", "OFTableFeatureProp", None)
     else:
         return ("", None, None)
Beispiel #8
0
def gen_all_java(out, name):
    """ Generate all of the java files

    @param out is an open file handle to a file called README
    @param name should be 'README' and is ignored for the java
        driver
    """
    messages = list()
    actions = list()
    instructions = list()
    matches = list()
    stat_types = list()
    queue_prop = list()
    lists = list()
    for cls in of_g.unified:
        print "! Classifying %s" % cls
        if cls in ["of_stats_reply", "of_flow_mod", "of_stats_request"]:
            continue  # doesn't work?!
        if loxi_utils.class_is_stats_message(cls):
            stat_types.append(cls)
        elif loxi_utils.class_is_message(cls):
            messages.append(cls)
        elif loxi_utils.class_is_action(cls):
            actions.append(cls)
        elif loxi_utils.class_is_instruction(cls):
            instructions.append(cls)
        elif loxi_utils.class_is_oxm(cls):
            matches.append(cls)
        elif loxi_utils.class_is_queue_prop(cls):
            queue_prop.append(cls)
        elif loxi_utils.class_is_list(cls):
            lists.append(cls)
        else:
            print "Skipping Unknown class object %s" % str(cls)
    print "Parsed "
    print "  Messages: %d" % len(messages)
    print "  Actions: %d" % len(actions)
    print "  Instructions: %d" % len(instructions)
    print "  OXM matches: %d" % len(matches)
    print "  Stat types: %d" % len(stat_types)
    print "  Queue properties: %d" % len(queue_prop)
    print "  Lists: %d" % len(lists)
    target_dir = "loxi_output/openflowj"
    basedir = "%s/%s/" % (target_dir, lang_java.file_to_subdir_map["base_java"])
    srcdir = "%s/src/main/java/org/openflow/protocol" % basedir
    print "Outputting to %s" % basedir
    if not os.path.exists(basedir):
        os.makedirs(basedir)
    java_utils.copy_prewrite_tree(basedir)
    msgs.create_message_interfaces(messages, srcdir)
    msgs.create_message_by_version(messages, srcdir)
    msgs.create_of_type_enum(messages, srcdir)
    with open("README.java-lang") as readme_src:
        out.writelines(readme_src.readlines())
    out.close()
Beispiel #9
0
def generate_pyname(cls):
    if utils.class_is_action(cls):
        return cls[10:]
    elif utils.class_is_oxm(cls):
        return cls[7:]
    elif utils.class_is_meter_band(cls):
        return cls[14:]
    elif utils.class_is_instruction(cls):
        return cls[15:]
    else:
        return cls[3:]
Beispiel #10
0
def generate_pyname(cls):
    if utils.class_is_action(cls):
        return cls[10:]
    elif utils.class_is_oxm(cls):
        return cls[7:]
    elif utils.class_is_meter_band(cls):
        return cls[14:]
    elif utils.class_is_instruction(cls):
        return cls[15:]
    else:
        return cls[3:]
Beispiel #11
0
def generate_common(out, name, version):
    ofclasses = [
        x for x in build_ofclasses(version)
        if not utils.class_is_message(x.name) and not utils.class_is_action(
            x.name) and not utils.class_is_instruction(x.name)
        and not utils.class_is_meter_band(x.name)
        and not utils.class_is_oxm(x.name) and not utils.class_is_list(x.name)
    ]
    util.render_template(out,
                         'common.py',
                         ofclasses=ofclasses,
                         version=version)
Beispiel #12
0
def get_type_values(cls, version):
    """
    Returns a map from the name of the type member to its value.
    """
    type_values = {}

    # Primary wire type
    if utils.class_is_message(cls):
        type_values['version'] = 'const.OFP_VERSION'
        type_values['type'] = util.constant_for_value(version, "ofp_type", util.primary_wire_type(cls, version))
        if cls in type_maps.flow_mod_list:
            type_values['_command'] = util.constant_for_value(version, "ofp_flow_mod_command",
                                                              type_maps.flow_mod_types[version][cls[8:]])
        if cls in type_maps.stats_request_list:
            type_values['stats_type'] = util.constant_for_value(version, "ofp_stats_types",
                                                                type_maps.stats_types[version][cls[3:-14]])
        if cls in type_maps.stats_reply_list:
            type_values['stats_type'] = util.constant_for_value(version, "ofp_stats_types",
                                                                type_maps.stats_types[version][cls[3:-12]])
        if type_maps.message_is_extension(cls, version):
            type_values['experimenter'] = '%#x' % type_maps.extension_to_experimenter_id(cls)
            type_values['subtype'] = type_maps.extension_message_to_subtype(cls, version)
    elif utils.class_is_action(cls):
        type_values['type'] = util.constant_for_value(version, "ofp_action_type", util.primary_wire_type(cls, version))
        if type_maps.action_is_extension(cls, version):
            type_values['experimenter'] = '%#x' % type_maps.extension_to_experimenter_id(cls)
            type_values['subtype'] = type_maps.extension_action_to_subtype(cls, version)
    elif utils.class_is_queue_prop(cls):
        type_values['type'] = util.constant_for_value(version, "ofp_queue_properties", util.primary_wire_type(cls, version))
    elif utils.class_is_hello_elem(cls):
        type_values['type'] = util.constant_for_value(version, "ofp_hello_elem_type", util.primary_wire_type(cls, version))
    elif utils.class_is_oxm(cls):
        oxm_class = 0x8000
        oxm_type = util.primary_wire_type(cls, version)
        oxm_masked = cls.find('masked') != -1 and 1 or 0
        oxm_len = of_g.base_length[(cls, version)] - 4
        type_values['type_len'] = '%#x' % (oxm_class << 16 | oxm_type << 8 | \
                                           oxm_masked << 8 | oxm_len)
    elif cls == "of_match_v2":
        type_values['type'] = 0
    elif cls == "of_match_v3":
        type_values['type'] = 1
    elif utils.class_is_meter_band(cls):
        type_values['type'] = util.constant_for_value(version, "ofp_meter_band_type", util.primary_wire_type(cls, version))
    elif utils.class_is_instruction(cls):
        type_values['type'] = util.constant_for_value(version, "ofp_instruction_type", util.primary_wire_type(cls, version))

    return type_values
Beispiel #13
0
 def generate_class(self, clazz):
     """ return wether or not to generate implementation class clazz.
         Now true for everything except OFTableModVer10.
         @param clazz JavaOFClass instance
     """
     if clazz.interface.name.startswith("OFMatchV"):
         return True
     elif clazz.name == "OFTableModVer10":
         # tablemod ver 10 is a hack and has no oftype defined
         return False
     if loxi_utils.class_is_message(clazz.interface.c_name):
         return True
     if loxi_utils.class_is_oxm(clazz.interface.c_name):
         return True
     if loxi_utils.class_is_action(clazz.interface.c_name):
         return True
     if loxi_utils.class_is_instruction(clazz.interface.c_name):
         return True
     else:
         return True
Beispiel #14
0
def build_ofclasses(version):
    blacklist = [
        "of_action",
        "of_action_header",
        "of_header",
        "of_queue_prop",
        "of_queue_prop_header",
        "of_experimenter",
        "of_action_experimenter",
    ]
    ofclasses = []
    for cls in of_g.standard_class_order:
        if version not in of_g.unified[cls] or cls in blacklist:
            continue
        unified_class = util.lookup_unified_class(cls, version)

        # Name for the generated Python class
        if utils.class_is_action(cls):
            pyname = cls[10:]
        else:
            pyname = cls[3:]

        type_values = get_type_values(cls, version)
        members = []

        length_member = None
        type_members = []

        for member in unified_class["members"]:
            if member["name"] in ["length", "len"]:
                length_member = LengthMember(
                    name=member["name"], offset=member["offset"], oftype=oftype.OFType(member["m_type"], version)
                )
            elif member["name"] in type_values:
                type_members.append(
                    TypeMember(
                        name=member["name"],
                        offset=member["offset"],
                        oftype=oftype.OFType(member["m_type"], version),
                        value=type_values[member["name"]],
                    )
                )
            else:
                # HACK ensure member names are unique
                if member["name"] == "pad" and [x for x in members if x.name == "pad"]:
                    m_name = "pad2"
                else:
                    m_name = member["name"]
                members.append(
                    Member(
                        name=m_name,
                        oftype=oftype.OFType(member["m_type"], version),
                        offset=member["offset"],
                        skip=member["name"] in of_g.skip_members,
                    )
                )

        ofclasses.append(
            OFClass(
                name=cls,
                pyname=pyname,
                members=members,
                length_member=length_member,
                type_members=type_members,
                min_length=of_g.base_length[(cls, version)],
                is_fixed_length=(cls, version) in of_g.is_fixed_length,
            )
        )
    return ofclasses
def gen_list_validator(out, cls, version):
    ver_name = loxi_utils.version_to_name(version)
    e_cls = loxi_utils.list_to_entry_type(cls)
    fixed_len = of_g.base_length[(e_cls, version)]
    out.write("""
static inline int
%(cls)s_%(ver_name)s_validate(uint8_t *buf, int len)
{
""" % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), e_cls=e_cls))

    # TLV16
    if loxi_utils.class_is_tlv16(e_cls):
        subclasses = type_maps.inheritance_map[e_cls]
        out.write("""\
    while (len >= %(fixed_len)s) {
        of_object_id_t e_id;
        uint16_t e_type, e_len;
        buf_u16_get(buf, &e_type);
        buf_u16_get(buf+2, &e_len);
        e_id = %(e_cls)s_to_object_id(e_type, %(ver_name)s);
        switch (e_id) {
""" % dict(fixed_len=fixed_len, ver_name=ver_name, e_cls=e_cls))
        for subcls in subclasses:
            subcls = e_cls + '_' + subcls
            if not loxi_utils.class_in_version(subcls, version):
                continue
            out.write("""\
        case %(subcls_enum)s:
            if (%(subcls)s_%(ver_name)s_validate(buf, e_len) < 0) {
                return -1;
            }
            break;
""" % dict(ver_name=ver_name,
            subcls=subcls,
            subcls_enum=loxi_utils.enum_name(subcls)))
        out.write("""\
        default:
            return -1;
        }
        buf += e_len;
        len -= e_len;
    }
    if (len != 0) {
        return -1;
    }
""" % dict(e_cls=e_cls, ver_name=ver_name))

    # U16 len
    elif loxi_utils.class_is_u16_len(e_cls) or loxi_utils.class_is_action(
            e_cls):
        out.write("""\
    /* TODO verify U16 len elements */
""" % dict())

    # OXM
    elif loxi_utils.class_is_oxm(e_cls):
        out.write("""\
    /* TODO verify OXM elements */
""" % dict())

    # Fixed length
    elif not loxi_utils.class_is_var_len(e_cls, version):
        out.write("""\
    if ((len / %(fixed_len)s) * %(fixed_len)s != len) {
        return -1;
    }
""" % dict(fixed_len=fixed_len))

    # ???
    else:
        out.write("""\
    /* XXX unknown element format */
""" % dict())

    out.write("""
    return 0;
}
""")
Beispiel #16
0
def generate_action(out, name, version):
    ofclasses = [x for x in build_ofclasses(version)
                 if utils.class_is_action(x.name)]
    util.render_template(out, 'action.py', ofclasses=ofclasses, version=version)
Beispiel #17
0
def build_ofclasses(version):
    blacklist = ["of_action", "of_action_header", "of_header", "of_queue_prop",
                 "of_queue_prop_header", "of_experimenter", "of_action_experimenter",
                 "of_oxm", "of_oxm_header", "of_oxm_experimenter_header",
                 "of_hello_elem", "of_hello_elem_header"]
    ofclasses = []
    for cls in of_g.standard_class_order:
        if type_maps.class_is_virtual(cls):
            continue
        if version not in of_g.unified[cls] or cls in blacklist:
            continue
        unified_class = util.lookup_unified_class(cls, version)

        # Name for the generated Python class
        if utils.class_is_action(cls):
            pyname = cls[10:]
        elif utils.class_is_oxm(cls):
            pyname = cls[7:]
        elif utils.class_is_meter_band(cls):
            pyname = cls[14:]
        elif utils.class_is_instruction(cls):
            pyname = cls[15:]
        else:
            pyname = cls[3:]

        type_values = get_type_values(cls, version)
        members = []
        type_members = []

        pad_count = 0

        for member in unified_class['members']:
            if member['name'] in ['length', 'len']:
                members.append(LengthMember(name=member['name'],
                                            oftype=oftype.OFType(member['m_type'], version)))
            elif (cls, version, member['name']) in field_length_members:
                field_name = field_length_members[(cls, version, member['name'])]
                members.append(FieldLengthMember(name=member['name'],
                                                 oftype=oftype.OFType(member['m_type'], version),
                                                 field_name=field_name))
            elif member['name'] in type_values:
                members.append(TypeMember(name=member['name'],
                                          oftype=oftype.OFType(member['m_type'], version),
                                          value=type_values[member['name']]))
                type_members.append(members[-1])
            elif member['name'].startswith("pad"):
                # HACK this should be moved to the frontend
                pad_oftype = oftype.OFType(member['m_type'], version)
                length = struct.calcsize("!" + pad_oftype._pack_fmt())
                if pad_oftype.is_array: length *= pad_oftype.array_length
                members.append(PadMember(length=length))
            else:
                members.append(Member(name=member['name'],
                                      oftype=oftype.OFType(member['m_type'], version)))

        ofclasses.append(
            OFClass(name=cls,
                    pyname=pyname,
                    members=members,
                    type_members=type_members,
                    min_length=of_g.base_length[(cls, version)],
                    is_fixed_length=(cls, version) in of_g.is_fixed_length))
    return ofclasses
Beispiel #18
0
def gen_list_validator(out, cls, version):
    ver_name = loxi_utils.version_to_name(version)
    e_cls = loxi_utils.list_to_entry_type(cls)
    fixed_len = of_g.base_length[(e_cls, version)];
    out.write("""
static inline int
%(cls)s_%(ver_name)s_validate(uint8_t *buf, int len)
{
""" % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), e_cls=e_cls))

    # TLV16
    if loxi_utils.class_is_tlv16(e_cls):
        subclasses = type_maps.inheritance_map[e_cls]
        out.write("""\
    while (len >= %(fixed_len)s) {
        of_object_id_t e_id;
        uint16_t e_type, e_len;
        buf_u16_get(buf, &e_type);
        buf_u16_get(buf+2, &e_len);
        e_id = %(e_cls)s_to_object_id(e_type, %(ver_name)s);
        switch (e_id) {
""" % dict(fixed_len=fixed_len, ver_name=ver_name, e_cls=e_cls))
        for subcls in subclasses:
            subcls = e_cls + '_' + subcls
            if not loxi_utils.class_in_version(subcls, version):
                continue
            out.write("""\
        case %(subcls_enum)s:
            if (%(subcls)s_%(ver_name)s_validate(buf, e_len) < 0) {
                return -1;
            }
            break;
""" % dict(ver_name=ver_name, subcls=subcls, subcls_enum=loxi_utils.enum_name(subcls)))
        out.write("""\
        default:
            return -1;
        }
        buf += e_len;
        len -= e_len;
    }
    if (len != 0) {
        return -1;
    }
""" % dict(e_cls=e_cls, ver_name=ver_name))

    # U16 len
    elif loxi_utils.class_is_u16_len(e_cls) or loxi_utils.class_is_action(e_cls):
        out.write("""\
    /* TODO verify U16 len elements */
""" % dict())

    # OXM
    elif loxi_utils.class_is_oxm(e_cls):
        out.write("""\
    /* TODO verify OXM elements */
""" % dict())

    # Fixed length
    elif not loxi_utils.class_is_var_len(e_cls, version):
        out.write("""\
    if ((len / %(fixed_len)s) * %(fixed_len)s != len) {
        return -1;
    }
""" % dict(fixed_len=fixed_len))

    # ???
    else:
        out.write("""\
    /* XXX unknown element format */
""" % dict())

    out.write("""
    return 0;
}
""")