From 75761b933f3e28494bae4b2cf5636a07ffe6ce18 Mon Sep 17 00:00:00 2001 From: Ole Troan Date: Wed, 11 Sep 2019 17:49:08 +0200 Subject: [PATCH] api: split vl_api_prefix into two One type for address with prefix and one type for prefix. Type: fix Signed-off-by: Ole Troan Change-Id: Icfec51d9b7d5cde1d69fbecdd97498688ab7b295 Signed-off-by: Ole Troan Signed-off-by: Klement Sekera Signed-off-by: Ole Troan --- src/plugins/lb/lb.api | 10 +-- src/plugins/lb/lb_types.api | 2 +- src/tools/vppapigen/vppapigen.py | 7 +- src/tools/vppapigen/vppapigen_c.py | 76 ++++++++--------- src/tools/vppapigen/vppapigen_json.py | 3 +- src/vnet/interface.api | 2 +- src/vnet/ip/ip.api | 4 +- src/vnet/ip/ip_format_fns.h | 6 ++ src/vnet/ip/ip_types.api | 17 ++++ src/vnet/mpls/mpls.api | 3 +- .../python/vpp_papi/tests/test_vpp_serializer.py | 94 ++++++++++++++++++++++ src/vpp-api/python/vpp_papi/vpp_format.py | 72 ++++++++++++++++- src/vpp-api/python/vpp_papi/vpp_serializer.py | 20 ++++- src/vpp-api/vapi/vapi_c_gen.py | 4 +- src/vpp-api/vapi/vapi_json_parser.py | 30 ++++--- test/vpp_ip_route.py | 2 +- 16 files changed, 274 insertions(+), 78 deletions(-) diff --git a/src/plugins/lb/lb.api b/src/plugins/lb/lb.api index 867832df966..b9f5c22126a 100644 --- a/src/plugins/lb/lb.api +++ b/src/plugins/lb/lb.api @@ -39,7 +39,7 @@ autoreply manual_print define lb_conf autoreply manual_print define lb_add_del_vip { u32 client_index; u32 context; - vl_api_prefix_t pfx; + vl_api_address_with_prefix_t pfx; u8 protocol [default=255]; u16 port; vl_api_lb_encap_type_t encap; @@ -64,7 +64,7 @@ autoreply manual_print define lb_add_del_vip { autoreply manual_print define lb_add_del_as { u32 client_index; u32 context; - vl_api_prefix_t pfx; + vl_api_address_with_prefix_t pfx; u8 protocol [default=255]; u16 port; vl_api_address_t as_address; @@ -82,7 +82,7 @@ autoreply manual_print define lb_add_del_as { autoreply manual_print define lb_flush_vip { u32 client_index; u32 context; - vl_api_prefix_t pfx; + vl_api_address_with_prefix_t pfx; u8 protocol; u16 port; }; @@ -94,7 +94,7 @@ autoreply manual_print define lb_flush_vip { define lb_vip_dump{ u32 client_index; u32 context; - vl_api_prefix_t pfx; + vl_api_address_with_prefix_t pfx; vl_api_prefix_matcher_t pfx_matcher; u8 protocol [default=255]; u16 port; @@ -126,7 +126,7 @@ define lb_as_dump{ u32 client_index; u32 context; /* vip */ - vl_api_prefix_t pfx; + vl_api_address_with_prefix_t pfx; u8 protocol; u16 port; }; diff --git a/src/plugins/lb/lb_types.api b/src/plugins/lb/lb_types.api index e01db5dd16c..cadd2b033f2 100644 --- a/src/plugins/lb/lb_types.api +++ b/src/plugins/lb/lb_types.api @@ -67,7 +67,7 @@ enum lb_nat_protocol */ typedef lb_vip { - vl_api_prefix_t pfx; + vl_api_address_with_prefix_t pfx; vl_api_ip_proto_t protocol; u16 port; }; diff --git a/src/tools/vppapigen/vppapigen.py b/src/tools/vppapigen/vppapigen.py index 03362b0e656..861b71ddf43 100755 --- a/src/tools/vppapigen/vppapigen.py +++ b/src/tools/vppapigen/vppapigen.py @@ -206,6 +206,9 @@ class Using(): def __init__(self, name, flags, alias): self.name = name self.vla = False + self.block = [] + self.manual_print = True + self.manual_endian = True self.manual_print = False self.manual_endian = False @@ -750,7 +753,6 @@ class VPPAPI(object): s['Service'] = [] s['types'] = [] s['Import'] = [] - s['Alias'] = {} crc = 0 for o in objs: tname = o.__class__.__name__ @@ -770,10 +772,9 @@ class VPPAPI(object): s['Service'].append(o2) elif (isinstance(o, Enum) or isinstance(o, Typedef) or + isinstance(o, Using) or isinstance(o, Union)): s['types'].append(o) - elif isinstance(o, Using): - s['Alias'][o.name] = o else: if tname not in s: raise ValueError('Unknown class type: {} {}' diff --git a/src/tools/vppapigen/vppapigen_c.py b/src/tools/vppapigen/vppapigen_c.py index d6cdda8baac..7c383c27472 100644 --- a/src/tools/vppapigen/vppapigen_c.py +++ b/src/tools/vppapigen/vppapigen_c.py @@ -95,7 +95,7 @@ def api2c(fieldtype): return fieldtype -def typedefs(objs, aliases, filename): +def typedefs(objs, filename): name = filename.replace('.', '_') output = '''\ @@ -108,16 +108,14 @@ def typedefs(objs, aliases, filename): ''' output = output.format(module=name) - for k, v in aliases.items(): - if 'length' in v.alias: - output += ('typedef %s vl_api_%s_t[%s];\n' - % (v.alias['type'], k, v.alias['length'])) - else: - output += 'typedef %s vl_api_%s_t;\n' % (v.alias['type'], k) - for o in objs: tname = o.__class__.__name__ - if tname == 'Enum': + if tname == 'Using': + if 'length' in o.alias: + output += 'typedef %s vl_api_%s_t[%s];\n' % (o.alias['type'], o.name, o.alias['length']) + else: + output += 'typedef %s vl_api_%s_t;\n' % (o.alias['type'], o.name) + elif tname == 'Enum': if o.enumtype == 'u32': output += "typedef enum {\n" else: @@ -282,7 +280,7 @@ class Printfun(): write(' return format(s, "{}", *a);\n' .format(format_strings[v.alias['type']])) else: - write(' return format(s, "{} (print not implemented)"' + write(' return format(s, "{} (print not implemented)");\n' .format(k)) def print_enum(self, o, stream): @@ -357,7 +355,7 @@ static inline void *vl_api_{name}_t_print (vl_api_{name}_t *a, void *handle) return '' -def printfun_types(objs, aliases, stream, modulename): +def printfun_types(objs, stream, modulename): write = stream.write pp = Printfun(stream) @@ -380,15 +378,6 @@ static inline u8 *format_vl_api_{name}_t (u8 *s, va_list * args) indent += 2; ''' - for k, v in aliases.items(): - if v.manual_print: - write("/***** manual: vl_api_%s_t_print *****/\n\n" % k) - continue - - write(signature.format(name=k)) - pp.print_alias(k, v, stream) - write('}\n\n') - for t in objs: if t.__class__.__name__ == 'Enum': write(signature.format(name=t.name)) @@ -401,6 +390,12 @@ static inline u8 *format_vl_api_{name}_t (u8 *s, va_list * args) write("/***** manual: vl_api_%s_t_print *****/\n\n" % t.name) continue + if t.__class__.__name__ == 'Using': + write(signature.format(name=t.name)) + pp.print_alias(t.name, t, stream) + write('}\n\n') + continue + write(signature.format(name=t.name)) for o in t.block: pp.print_obj(o, stream) @@ -485,7 +480,7 @@ def endianfun_obj(o): return output -def endianfun(objs, aliases, modulename): +def endianfun(objs, modulename): output = '''\ /****** Endian swap functions *****/\n\ @@ -509,23 +504,6 @@ static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a) int i __attribute__((unused)); ''' - for k, v in aliases.items(): - if v.manual_endian: - output += "/***** manual: vl_api_%s_t_endian *****/\n\n" % k - continue - - output += signature.format(name=k) - if ('length' in v.alias and v.alias['length'] and - v.alias['type'] == 'u8'): - output += (' /* a->{name} = a->{name} (no-op) */\n' - .format(name=k)) - elif v.alias['type'] in format_strings: - output += (' *a = {}(*a);\n' - .format(endian_strings[v.alias['type']])) - else: - output += ' /* Not Implemented yet {} */'.format(k) - output += '}\n\n' - for t in objs: if t.__class__.__name__ == 'Enum': output += signature.format(name=t.name) @@ -543,6 +521,21 @@ static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a) output += "/***** manual: vl_api_%s_t_endian *****/\n\n" % t.name continue + + if t.__class__.__name__ == 'Using': + output += signature.format(name=t.name) + if ('length' in t.alias and t.alias['length'] and + t.alias['type'] == 'u8'): + output += (' /* a->{name} = a->{name} (no-op) */\n' + .format(name=t.name)) + elif t.alias['type'] in format_strings: + output += (' *a = {}(*a);\n' + .format(endian_strings[t.alias['type']])) + else: + output += ' /* Not Implemented yet {} */'.format(t.name) + output += '}\n\n' + continue + output += signature.format(name=t.name) for o in t.block: @@ -588,12 +581,11 @@ def run(input_filename, s): output += msg_ids(s) output += msg_names(s) output += msg_name_crc_list(s, filename) - output += typedefs(s['types'] + s['Define'], s['Alias'], - filename + file_extension) - printfun_types(s['types'], s['Alias'], stream, modulename) + output += typedefs(s['types'] + s['Define'], filename + file_extension) + printfun_types(s['types'], stream, modulename) printfun(s['Define'], stream, modulename) output += stream.getvalue() - output += endianfun(s['types'] + s['Define'], s['Alias'], modulename) + output += endianfun(s['types'] + s['Define'], modulename) output += version_tuple(s, basename) output += bottom_boilerplate.format(input_filename=basename, file_crc=s['file_crc']) diff --git a/src/tools/vppapigen/vppapigen_json.py b/src/tools/vppapigen/vppapigen_json.py index ef1c9823c33..f67a3d62da1 100644 --- a/src/tools/vppapigen/vppapigen_json.py +++ b/src/tools/vppapigen/vppapigen_json.py @@ -58,7 +58,6 @@ def walk_defs(s, is_message=False): r.append(d) return r - # # Plugin entry point # @@ -74,6 +73,6 @@ def run(filename, s): if o.__class__.__name__ == 'Enum'])) j['services'] = walk_services(s['Service']) j['options'] = s['Option'] - j['aliases'] = {k: v.alias for k, v in s['Alias'].items()} + j['aliases'] = {o.name:o.alias for o in s['types'] if o.__class__.__name__ == 'Using'} j['vl_api_version'] = hex(s['file_crc']) return json.dumps(j, indent=4, separators=(',', ': ')) diff --git a/src/vnet/interface.api b/src/vnet/interface.api index dff954438af..ff0946538f4 100644 --- a/src/vnet/interface.api +++ b/src/vnet/interface.api @@ -223,7 +223,7 @@ autoreply define sw_interface_add_del_address bool is_add; bool del_all; - vl_api_prefix_t prefix; + vl_api_address_with_prefix_t prefix; }; /** \brief Associate the specified interface with a fib table diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index 67cdf9377b3..5d22bc52fea 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -29,7 +29,7 @@ import "vnet/mfib/mfib_types.api"; /** \brief An IP table @param is_ipv6 - V4 or V6 table @param table_id - table ID associated with the route - This table ID will apply to both the unicats + This table ID will apply to both the unicats and mlticast FIBs @param name - A client provided name/tag for the table. If this is not set by the client, then VPP will generate something @@ -496,7 +496,7 @@ define ip_address_details { u32 context; u32 sw_if_index; - vl_api_prefix_t prefix; + vl_api_address_with_prefix_t prefix; }; define ip_address_dump diff --git a/src/vnet/ip/ip_format_fns.h b/src/vnet/ip/ip_format_fns.h index b24c59454d4..4db10d1bb41 100644 --- a/src/vnet/ip/ip_format_fns.h +++ b/src/vnet/ip/ip_format_fns.h @@ -83,4 +83,10 @@ format_vl_api_prefix_t (u8 * s, va_list * args) return format (s, "%U/%u", format_vl_api_address_t, &a->address, indent, a->len); } +static inline u8 * +format_vl_api_address_with_prefix_t (u8 * s, va_list * args) +{ + return format_vl_api_prefix_t (s, args); +} + #endif diff --git a/src/vnet/ip/ip_types.api b/src/vnet/ip/ip_types.api index d9ad893412d..49294587991 100644 --- a/src/vnet/ip/ip_types.api +++ b/src/vnet/ip/ip_types.api @@ -108,6 +108,23 @@ manual_print typedef ip4_prefix { u8 len; }; +/** \brief + * + * The vl_api_[ip4|ip6]_address_with_prefix_t types are used as a type to denote + * both an IP address and a prefix. I.e. in CIDR notation + * '192.168.10.1/24' the address is 192.168.10.1 and the network + * prefix is 192.168.10.0/24. + * + * If only an address is needed use: vl_api_address_t types and if + * only a network prefix is needed (i.e. no hosts bits), then use the + * vl_api_prefix_t types. + * + **/ + +manual_print typedef vl_api_prefix_t address_with_prefix; +manual_print typedef vl_api_ip4_prefix_t ip4_address_with_prefix; +manual_print typedef vl_api_ip6_prefix_t ip6_address_with_prefix; + /** \brief A context for matching prefixes against. (Think ip prefix list.) The meaning (exact match / want subnets) of an unset matcher is left to the implementer. @param le - le mut be <= to prefix.len. Default: 255 (not set). diff --git a/src/vnet/mpls/mpls.api b/src/vnet/mpls/mpls.api index 2a0c83d4dd5..535bcea2b60 100644 --- a/src/vnet/mpls/mpls.api +++ b/src/vnet/mpls/mpls.api @@ -26,8 +26,7 @@ import "vnet/ip/ip_types.api"; @param mb_ip_table_id - The IP table-id of the IP prefix to bind to. @param mb_is_bind - Bind or unbind @param mb_is_ip4 - The prefix to bind to is IPv4 - @param mb_address_length - Length of IP prefix - @param mb_address[16] - IP prefix/ + @param mb_prefix - IP prefix */ autoreply define mpls_ip_bind_unbind { diff --git a/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py b/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py index 6ca8e6c4ff3..9ac3e78224c 100755 --- a/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py +++ b/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py @@ -104,6 +104,10 @@ class TestAddType(unittest.TestCase): [['vl_api_address_family_t', 'af'], ['vl_api_address_union_t', 'un']]) + prefix = VPPType('vl_api_prefix_t', + [['vl_api_address_t', 'address'], + ['u8', 'len']]) + va_address_list = VPPType('list_addresses', [['u8', 'count'], ['vl_api_address_t', 'addresses', @@ -151,6 +155,96 @@ class TestAddType(unittest.TestCase): nt, size = message_with_va_address_list.unpack(b) self.assertEqual(nt.is_cool, 100) + def test_address_with_prefix(self): + af = VPPEnumType('vl_api_address_family_t', [["ADDRESS_IP4", 0], + ["ADDRESS_IP6", 1], + {"enumtype": "u32"}]) + ip4 = VPPTypeAlias('vl_api_ip4_address_t', {'type': 'u8', + 'length': 4}) + ip6 = VPPTypeAlias('vl_api_ip6_address_t', {'type': 'u8', + 'length': 16}) + VPPUnionType('vl_api_address_union_t', + [["vl_api_ip4_address_t", "ip4"], + ["vl_api_ip6_address_t", "ip6"]]) + + address = VPPType('vl_api_address_t', + [['vl_api_address_family_t', 'af'], + ['vl_api_address_union_t', 'un']]) + + + prefix = VPPType('vl_api_prefix_t', + [['vl_api_address_t', 'address'], + ['u8', 'len']]) + prefix4 = VPPType('vl_api_ip4_prefix_t', + [['vl_api_ip4_address_t', 'address'], + ['u8', 'len']]) + prefix6 = VPPType('vl_api_ip6_prefix_t', + [['vl_api_ip6_address_t', 'address'], + ['u8', 'len']]) + + address_with_prefix = VPPTypeAlias('vl_api_address_with_prefix_t', {'type': 'vl_api_prefix_t' }) + address4_with_prefix = VPPTypeAlias('vl_api_ip4_address_with_prefix_t', + {'type': 'vl_api_ip4_prefix_t' }) + address6_with_prefix = VPPTypeAlias('vl_api_ip6_address_with_prefix_t', + {'type': 'vl_api_ip6_prefix_t' }) + + awp_type = VPPType('foobar_t', + [['vl_api_address_with_prefix_t', 'address']]) + + # address with prefix + b = address_with_prefix.pack(IPv4Interface('2.2.2.2/24')) + self.assertEqual(len(b), 21) + nt, size = address_with_prefix.unpack(b) + self.assertTrue(isinstance(nt, IPv4Interface)) + self.assertEqual(str(nt), '2.2.2.2/24') + + b = address_with_prefix.pack(IPv6Interface('2::2/64')) + self.assertEqual(len(b), 21) + nt, size = address_with_prefix.unpack(b) + self.assertTrue(isinstance(nt, IPv6Interface)) + self.assertEqual(str(nt), '2::2/64') + + b = address_with_prefix.pack(IPv4Network('2.2.2.2/24', strict=False)) + self.assertEqual(len(b), 21) + nt, size = address_with_prefix.unpack(b) + self.assertTrue(isinstance(nt, IPv4Interface)) + self.assertEqual(str(nt), '2.2.2.0/24') + + b = address4_with_prefix.pack('2.2.2.2/24') + self.assertEqual(len(b), 5) + nt, size = address4_with_prefix.unpack(b) + self.assertTrue(isinstance(nt, IPv4Interface)) + self.assertEqual(str(nt), '2.2.2.2/24') + b = address4_with_prefix.pack(IPv4Interface('2.2.2.2/24')) + self.assertEqual(len(b), 5) + + b = address6_with_prefix.pack('2::2/64') + self.assertEqual(len(b), 17) + nt, size = address6_with_prefix.unpack(b) + self.assertTrue(isinstance(nt, IPv6Interface)) + self.assertEqual(str(nt), '2::2/64') + b = address6_with_prefix.pack(IPv6Interface('2::2/64')) + self.assertEqual(len(b), 17) + + b = prefix.pack('192.168.10.0/24') + self.assertEqual(len(b), 21) + nt, size = prefix.unpack(b) + self.assertTrue(isinstance(nt, IPv4Network)) + self.assertEqual(str(nt), '192.168.10.0/24') + + b = awp_type.pack({'address': '1.2.3.4/24'}) + self.assertEqual(len(b), 21) + nt, size = awp_type.unpack(b) + self.assertTrue(isinstance(nt.address, IPv4Interface)) + self.assertEqual(str(nt.address), '1.2.3.4/24') + + b = awp_type.pack({'address': IPv4Interface('1.2.3.4/24')}) + self.assertEqual(len(b), 21) + nt, size = awp_type.unpack(b) + self.assertTrue(isinstance(nt.address, IPv4Interface)) + self.assertEqual(str(nt.address), '1.2.3.4/24') + + def test_recursive_address(self): af = VPPEnumType('vl_api_address_family_t', [["ADDRESS_IP4", 0], ["ADDRESS_IP6", 1], diff --git a/src/vpp-api/python/vpp_papi/vpp_format.py b/src/vpp-api/python/vpp_papi/vpp_format.py index 7d2dcba491a..3e836c9da6b 100644 --- a/src/vpp-api/python/vpp_papi/vpp_format.py +++ b/src/vpp-api/python/vpp_papi/vpp_format.py @@ -52,6 +52,15 @@ def format_vl_api_prefix_t(args): return {'address': format_vl_api_address_t(p), 'len': int(length)} +def format_vl_api_address_with_prefix_t(args): + if isinstance(args, (ipaddress.IPv4Interface, ipaddress.IPv6Interface)): + return {'address': format_vl_api_address_t( + text_type(args.network_address)), + 'len': int(args.prefixlen)} + p, length = args.split('/') + return {'address': format_vl_api_address_t(p), + 'len': int(length)} + def format_vl_api_ip6_prefix_t(args): if isinstance(args, ipaddress.IPv6Network): @@ -61,6 +70,13 @@ def format_vl_api_ip6_prefix_t(args): return {'address': inet_pton(AF_INET6, p), 'len': int(length)} +def format_vl_api_ip6_address_with_prefix_t(args): + if isinstance(args, ipaddress.IPv6Interface): + return {'address': args.network_address.packed, + 'len': int(args.prefixlen)} + p, length = args.split('/') + return {'address': inet_pton(AF_INET6, p), + 'len': int(length)} def format_vl_api_ip4_prefix_t(args): if isinstance(args, ipaddress.IPv4Network): @@ -70,6 +86,14 @@ def format_vl_api_ip4_prefix_t(args): return {'address': inet_pton(AF_INET, p), 'len': int(length)} +def format_vl_api_ip4_address_with_prefix_t(args): + if isinstance(args, ipaddress.IPv4Interface): + return {'address': args.network_address.packed, + 'len': int(args.prefixlen)} + p, length = args.split('/') + return {'address': inet_pton(AF_INET, p), + 'len': int(length)} + conversion_table = { 'vl_api_ip6_address_t': @@ -112,6 +136,30 @@ conversion_table = { 'len': o.prefixlen}, 'str': lambda s: format_vl_api_prefix_t(s) }, + 'vl_api_address_with_prefix_t': + { + 'IPv4Interface': lambda o: {'address': + {'af': ADDRESS_IP4, 'un': + {'ip4': o.packed}}, + 'len': o.network.prefixlen}, + 'IPv6Interface': lambda o: {'address': + {'af': ADDRESS_IP6, 'un': + {'ip6': o.packed}}, + 'len': o.network.prefixlen}, + 'str': lambda s: format_vl_api_address_with_prefix_t(s) + }, + 'vl_api_ip4_address_with_prefix_t': + { + 'IPv4Interface': lambda o: {'address': o.packed, + 'len': o.network.prefixlen}, + 'str': lambda s: format_vl_api_ip4_address_with_prefix_t(s) + }, + 'vl_api_ip6_address_with_prefix_t': + { + 'IPv6Interface': lambda o: {'address': o.packed, + 'len': o.network.prefixlen}, + 'str': lambda s: format_vl_api_ip6_address_with_prefix_t(s) + }, 'vl_api_mac_address_t': { 'MACAddress': lambda o: o.packed, @@ -130,14 +178,33 @@ def unformat_api_address_t(o): return ipaddress.IPv6Address(o.un.ip6) if o.af == 0: return ipaddress.IPv4Address(o.un.ip4) - + raise ValueError('Unknown address family {}'.format(o)) def unformat_api_prefix_t(o): + if o.address.af == 1: + return ipaddress.IPv6Network((o.address.un.ip6, o.len), False) + if o.address.af == 0: + return ipaddress.IPv4Network((o.address.un.ip4, o.len), False) + raise ValueError('Unknown address family {}'.format(o)) + if isinstance(o.address, ipaddress.IPv4Address): return ipaddress.IPv4Network((o.address, o.len), False) if isinstance(o.address, ipaddress.IPv6Address): return ipaddress.IPv6Network((o.address, o.len), False) + raise ValueError('Unknown instance {}', format(o)) + +def unformat_api_address_with_prefix_t(o): + if o.address.af == 1: + return ipaddress.IPv6Interface((o.address.un.ip6, o.len)) + if o.address.af == 0: + return ipaddress.IPv4Interface((o.address.un.ip4, o.len)) + raise ValueError('Unknown address family {}'.format(o)) + +def unformat_api_ip4_address_with_prefix_t(o): + return ipaddress.IPv4Interface((o.address, o.len)) +def unformat_api_ip6_address_with_prefix_t(o): + return ipaddress.IPv6Interface((o.address, o.len)) conversion_unpacker_table = { 'vl_api_ip6_address_t': lambda o: ipaddress.IPv6Address(o), @@ -146,6 +213,9 @@ conversion_unpacker_table = { 'vl_api_ip4_prefix_t': lambda o: ipaddress.IPv4Network((o.address, o.len)), 'vl_api_address_t': lambda o: unformat_api_address_t(o), 'vl_api_prefix_t': lambda o: unformat_api_prefix_t(o), + 'vl_api_address_with_prefix_t': lambda o: unformat_api_address_with_prefix_t(o), + 'vl_api_ip4_address_with_prefix_t': lambda o: unformat_api_ip4_address_with_prefix_t(o), + 'vl_api_ip6_address_with_prefix_t': lambda o: unformat_api_ip6_address_with_prefix_t(o), 'vl_api_mac_address_t': lambda o: macaddress.MACAddress(o), 'vl_api_timestamp_t': lambda o: datetime.datetime.fromtimestamp(o), 'vl_api_timedelta_t': lambda o: datetime.timedelta(seconds=o), diff --git a/src/vpp-api/python/vpp_papi/vpp_serializer.py b/src/vpp-api/python/vpp_papi/vpp_serializer.py index 443dd83ba68..c01b2d3bd8b 100644 --- a/src/vpp-api/python/vpp_papi/vpp_serializer.py +++ b/src/vpp-api/python/vpp_papi/vpp_serializer.py @@ -414,7 +414,7 @@ class VPPTypeAlias(object): self.name = name t = vpp_get_type(msgdef['type']) if not t: - raise ValueError() + raise ValueError('No such type: {}'.format(msgdef['type'])) if 'length' in msgdef: if msgdef['length'] == 0: raise ValueError() @@ -429,6 +429,7 @@ class VPPTypeAlias(object): self.size = t.size types[name] = self + self.toplevelconversion = False def __call__(self, args): self.options = args @@ -445,8 +446,13 @@ class VPPTypeAlias(object): return self.packer.pack(data, kwargs) def unpack(self, data, offset=0, result=None, ntc=False): + if ntc == False and self.name in vpp_format.conversion_unpacker_table: + # Disable type conversion for dependent types + ntc = True + self.toplevelconversion = True t, size = self.packer.unpack(data, offset, result, ntc=ntc) - if not ntc: + if self.toplevelconversion: + self.toplevelconversion = False return conversion_unpacker(t, self.name), size return t, size @@ -513,6 +519,7 @@ class VPPType(object): self.size = size self.tuple = collections.namedtuple(name, self.fields, rename=True) types[name] = self + self.toplevelconversion = False def __call__(self, args): self.options = args @@ -551,6 +558,11 @@ class VPPType(object): # Return a list of arguments result = [] total = 0 + if ntc == False and self.name in vpp_format.conversion_unpacker_table: + # Disable type conversion for dependent types + ntc = True + self.toplevelconversion = True + for p in self.packers: x, size = p.unpack(data, offset, result, ntc) if type(x) is tuple and len(x) == 1: @@ -559,7 +571,9 @@ class VPPType(object): offset += size total += size t = self.tuple._make(result) - if not ntc: + + if self.toplevelconversion: + self.toplevelconversion = False t = conversion_unpacker(t, self.name) return t, total diff --git a/src/vpp-api/vapi/vapi_c_gen.py b/src/vpp-api/vapi/vapi_c_gen.py index b9b9aa750a8..9a285eb98ad 100755 --- a/src/vpp-api/vapi/vapi_c_gen.py +++ b/src/vpp-api/vapi/vapi_c_gen.py @@ -713,12 +713,12 @@ def gen_json_unified_header(parser, logger, j, io, name): emitted = [] for e in parser.enums_by_json[j]: emit_definition(parser, j, emitted, e) - for a in parser.aliases_by_json[j]: - emit_definition(parser, j, emitted, a) for u in parser.unions_by_json[j]: emit_definition(parser, j, emitted, u) for t in parser.types_by_json[j]: emit_definition(parser, j, emitted, t) + for a in parser.aliases_by_json[j]: + emit_definition(parser, j, emitted, a) for m in parser.messages_by_json[j].values(): emit_definition(parser, j, emitted, m) diff --git a/src/vpp-api/vapi/vapi_json_parser.py b/src/vpp-api/vapi/vapi_json_parser.py index d7669365ce8..98143e26756 100644 --- a/src/vpp-api/vapi/vapi_json_parser.py +++ b/src/vpp-api/vapi/vapi_json_parser.py @@ -377,19 +377,6 @@ class JsonParser(object): self.unions[union.name] = union self.logger.debug("Parsed union: %s" % union) self.unions_by_json[path].append(union) - for name, body in j['aliases'].iteritems(): - if name in self.aliases: - progress = progress + 1 - continue - if 'length' in body: - array_len = body['length'] - else: - array_len = None - t = self.types[body['type']] - alias = self.alias_class(name, t, array_len) - self.aliases[name] = alias - self.logger.debug("Parsed alias: %s" % alias) - self.aliases_by_json[path].append(alias) for t in j['types']: if t[0] in self.types: progress = progress + 1 @@ -408,6 +395,23 @@ class JsonParser(object): self.types[type_.name] = type_ self.types_by_json[path].append(type_) self.logger.debug("Parsed type: %s" % type_) + for name, body in j['aliases'].iteritems(): + if name in self.aliases: + progress = progress + 1 + continue + if 'length' in body: + array_len = body['length'] + else: + array_len = None + try: + t = self.lookup_type_like_id(body['type']) + except ParseError as e: + exceptions.append(e) + continue + alias = self.alias_class(name, t, array_len) + self.aliases[name] = alias + self.logger.debug("Parsed alias: %s" % alias) + self.aliases_by_json[path].append(alias) if not exceptions: # finished parsing break diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py index 7742936a8a0..8f9d51a7d2a 100644 --- a/test/vpp_ip_route.py +++ b/test/vpp_ip_route.py @@ -153,7 +153,7 @@ def fib_interface_ip_prefix(test, address, length, sw_if_index): # TODO: refactor this to VppIpPrefix.__eq__ for a in addrs: if a.sw_if_index == sw_if_index and \ - a.prefix == prefix: + a.prefix.network == prefix: return True return False -- 2.16.6