def gen_validator(out, cls, version): fixed_len = of_g.base_length[(cls, version)] ver_name = loxi_utils.version_to_name(version) out.write(""" static inline int %(cls)s_%(ver_name)s_validate(uint8_t *buf, int len) { if (len < %(fixed_len)s) { VALIDATOR_LOG("Class %(cls)s. Len %%d too small, < %%d", len, %(fixed_len)s); return -1; } """ % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), fixed_len=fixed_len)) members, member_types = loxi_utils.all_member_types_get(cls, version) for member in members: m_type = member["m_type"] m_name = member["name"] m_offset = member['offset'] m_cls = m_type[:-2] # Trim _t if loxi_utils.skip_member_name(m_name): continue if not loxi_utils.type_is_of_object(m_type): continue if not loxi_utils.class_is_var_len(m_cls, version): continue if cls == "of_packet_out" and m_name == "actions": # See _PACKET_OUT_ACTION_LEN out.write(""" { uint16_t %(m_name)s_len; buf_u16_get(buf + %(m_offset)s - 2, &%(m_name)s_len); if (%(m_name)s_len + %(m_offset)s > len) { VALIDATOR_LOG("Class %(cls)s, member %(m_name)s. " "Len %%d and offset %%d too big for %%d", %(m_name)s_len, %(m_offset)s, len); return -1; } """ % dict(m_name=m_name, m_offset=m_offset, cls=cls)) else: out.write(""" { int %(m_name)s_len = len - %(m_offset)s; """ % dict(m_name=m_name, m_offset=m_offset)) out.write(""" if (%(m_cls)s_%(ver_name)s_validate(buf + %(m_offset)s, %(m_name)s_len) < 0) { return -1; } } """ % dict(m_name=m_name, m_cls=m_cls, ver_name=ver_name, m_offset=m_offset)) out.write(""" return 0; } """)
def gen_validator(out, cls, version): fixed_len = of_g.base_length[(cls, version)]; ver_name = loxi_utils.version_to_name(version) out.write(""" static inline int %(cls)s_%(ver_name)s_validate(uint8_t *buf, int len) { if (len < %(fixed_len)s) { VALIDATOR_LOG("Class %(cls)s. Len %%d too small, < %%d", len, %(fixed_len)s); return -1; } """ % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), fixed_len=fixed_len)) members, member_types = loxi_utils.all_member_types_get(cls, version) for member in members: m_type = member["m_type"] m_name = member["name"] m_offset = member['offset'] m_cls = m_type[:-2] # Trim _t if loxi_utils.skip_member_name(m_name): continue if not loxi_utils.type_is_of_object(m_type): continue if not loxi_utils.class_is_var_len(m_cls, version): continue if cls == "of_packet_out" and m_name == "actions": # See _PACKET_OUT_ACTION_LEN out.write(""" { uint16_t %(m_name)s_len; buf_u16_get(buf + %(m_offset)s - 2, &%(m_name)s_len); if (%(m_name)s_len + %(m_offset)s > len) { VALIDATOR_LOG("Class %(cls)s, member %(m_name)s. " "Len %%d and offset %%d too big for %%d", %(m_name)s_len, %(m_offset)s, len); return -1; } """ % dict(m_name=m_name, m_offset=m_offset, cls=cls)) else: out.write(""" { int %(m_name)s_len = len - %(m_offset)s; """ % dict(m_name=m_name, m_offset=m_offset)) out.write(""" if (%(m_cls)s_%(ver_name)s_validate(buf + %(m_offset)s, %(m_name)s_len) < 0) { return -1; } } """ % dict(m_name=m_name, m_cls=m_cls, ver_name=ver_name, m_offset=m_offset)) out.write(""" return 0; } """)
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 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; } """)
def gen_validator(out, cls, version): fixed_len = of_g.base_length[(cls, version)] ver_name = loxi_utils.version_to_name(version) out.write(""" static inline int %(cls)s_%(ver_name)s_validate(uint8_t *buf, int len) { if (len < %(fixed_len)s) { VALIDATOR_LOG("Class %(cls)s. Len %%d too small, < %%d", len, %(fixed_len)s); return -1; } """ % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), fixed_len=fixed_len)) members, member_types = loxi_utils.all_member_types_get(cls, version) for member in members: m_type = member["m_type"] m_name = member["name"] m_offset = member['offset'] m_cls = m_type[:-2] # Trim _t if loxi_utils.skip_member_name(m_name): continue if not loxi_utils.type_is_of_object(m_type): continue if not loxi_utils.class_is_var_len(m_cls, version): continue if cls == "of_packet_out" and m_name == "actions": # See _PACKET_OUT_ACTION_LEN out.write(""" { uint16_t %(m_name)s_len; buf_u16_get(buf + %(m_offset)s - 2, &%(m_name)s_len); if (%(m_name)s_len + %(m_offset)s > len) { VALIDATOR_LOG("Class %(cls)s, member %(m_name)s. " "Len %%d and offset %%d too big for %%d", %(m_name)s_len, %(m_offset)s, len); return -1; } """ % dict(m_name=m_name, m_offset=m_offset, cls=cls)) elif version >= of_g.VERSION_1_2 and loxi_utils.cls_is_flow_mod( cls) and m_name == "instructions": # See _FLOW_MOD_INSTRUCTIONS_OFFSET match_offset = v3_match_offset_get(cls) m_offset = '%s_offset' % m_name out.write(""" { uint16_t %(m_name)s_len, %(m_name)s_offset; uint16_t match_len; buf_u16_get(buf + %(match_offset)s + 2, &match_len); %(m_name)s_offset = %(match_offset)s + OF_MATCH_BYTES(match_len); %(m_name)s_len = len - %(m_name)s_offset; """ % dict(m_name=m_name, cls=cls, match_offset=match_offset)) elif cls == "of_bsn_gentable_entry_add" and m_name == "value": continue elif cls == "of_bsn_gentable_entry_desc_stats_entry" and m_name == "value": continue elif cls == "of_bsn_gentable_entry_stats_entry" and m_name == "stats": continue else: out.write(""" { int %(m_name)s_len = len - %(m_offset)s; """ % dict(m_name=m_name, m_offset=m_offset)) out.write(""" if (%(m_cls)s_%(ver_name)s_validate(buf + %(m_offset)s, %(m_name)s_len) < 0) { return -1; } } """ % dict(m_name=m_name, m_cls=m_cls, ver_name=ver_name, m_offset=m_offset)) out.write(""" return 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; } """)
def gen_validator(out, cls, version): fixed_len = of_g.base_length[(cls, version)]; ver_name = loxi_utils.version_to_name(version) out.write(""" static inline int %(cls)s_%(ver_name)s_validate(uint8_t *buf, int len) { if (len < %(fixed_len)s) { VALIDATOR_LOG("Class %(cls)s. Len %%d too small, < %%d", len, %(fixed_len)s); return -1; } """ % dict(cls=cls, ver_name=ver_name, cls_id=cls.upper(), fixed_len=fixed_len)) members, member_types = loxi_utils.all_member_types_get(cls, version) for member in members: m_type = member["m_type"] m_name = member["name"] m_offset = member['offset'] m_cls = m_type[:-2] # Trim _t if loxi_utils.skip_member_name(m_name): continue if not loxi_utils.type_is_of_object(m_type): continue if not loxi_utils.class_is_var_len(m_cls, version): continue if cls == "of_packet_out" and m_name == "actions": # See _PACKET_OUT_ACTION_LEN out.write(""" { uint16_t %(m_name)s_len; buf_u16_get(buf + %(m_offset)s - 2, &%(m_name)s_len); if (%(m_name)s_len + %(m_offset)s > len) { VALIDATOR_LOG("Class %(cls)s, member %(m_name)s. " "Len %%d and offset %%d too big for %%d", %(m_name)s_len, %(m_offset)s, len); return -1; } """ % dict(m_name=m_name, m_offset=m_offset, cls=cls)) elif version >= of_g.VERSION_1_2 and loxi_utils.cls_is_flow_mod(cls) and m_name == "instructions": # See _FLOW_MOD_INSTRUCTIONS_OFFSET match_offset = v3_match_offset_get(cls) m_offset = '%s_offset' % m_name out.write(""" { uint16_t %(m_name)s_len, %(m_name)s_offset; uint16_t match_len; buf_u16_get(buf + %(match_offset)s + 2, &match_len); %(m_name)s_offset = %(match_offset)s + OF_MATCH_BYTES(match_len); %(m_name)s_len = len - %(m_name)s_offset; """ % dict(m_name=m_name, cls=cls, match_offset=match_offset)) elif cls == "of_bsn_gentable_entry_add" and m_name == "value": continue; elif cls == "of_bsn_gentable_entry_desc_stats_entry" and m_name == "value": continue; elif cls == "of_bsn_gentable_entry_stats_entry" and m_name == "stats": continue; else: out.write(""" { int %(m_name)s_len = len - %(m_offset)s; """ % dict(m_name=m_name, m_offset=m_offset)) out.write(""" if (%(m_cls)s_%(ver_name)s_validate(buf + %(m_offset)s, %(m_name)s_len) < 0) { return -1; } } """ % dict(m_name=m_name, m_cls=m_cls, ver_name=ver_name, m_offset=m_offset)) out.write(""" return 0; } """)