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 <ot@cisco.com>
Change-Id: Icfec51d9b7d5cde1d69fbecdd97498688ab7b295
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Klement Sekera <ksekera@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
diff --git a/src/plugins/lb/lb.api b/src/plugins/lb/lb.api
index 867832d..b9f5c22 100644
--- a/src/plugins/lb/lb.api
+++ b/src/plugins/lb/lb.api
@@ -39,7 +39,7 @@
 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_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_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 @@
 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 @@
   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 e01db5d..cadd2b0 100644
--- a/src/plugins/lb/lb_types.api
+++ b/src/plugins/lb/lb_types.api
@@ -67,7 +67,7 @@
 */
 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 03362b0..861b71d 100755
--- a/src/tools/vppapigen/vppapigen.py
+++ b/src/tools/vppapigen/vppapigen.py
@@ -206,6 +206,9 @@
     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 @@
         s['Service'] = []
         s['types'] = []
         s['Import'] = []
-        s['Alias'] = {}
         crc = 0
         for o in objs:
             tname = o.__class__.__name__
@@ -770,10 +772,9 @@
                         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 d6cdda8..7c383c2 100644
--- a/src/tools/vppapigen/vppapigen_c.py
+++ b/src/tools/vppapigen/vppapigen_c.py
@@ -95,7 +95,7 @@
     return fieldtype
 
 
-def typedefs(objs, aliases, filename):
+def typedefs(objs, filename):
     name = filename.replace('.', '_')
     output = '''\
 
@@ -108,16 +108,14 @@
 '''
     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 @@
             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 @@
     return ''
 
 
-def printfun_types(objs, aliases, stream, modulename):
+def printfun_types(objs, stream, modulename):
     write = stream.write
     pp = Printfun(stream)
 
@@ -380,15 +378,6 @@
     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 @@
             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 @@
     return output
 
 
-def endianfun(objs, aliases, modulename):
+def endianfun(objs, modulename):
     output = '''\
 
 /****** Endian swap functions *****/\n\
@@ -509,23 +504,6 @@
     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 @@
             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 @@
     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 ef1c982..f67a3d6 100644
--- a/src/tools/vppapigen/vppapigen_json.py
+++ b/src/tools/vppapigen/vppapigen_json.py
@@ -58,7 +58,6 @@
         r.append(d)
     return r
 
-
 #
 # Plugin entry point
 #
@@ -74,6 +73,6 @@
                               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 dff9544..ff09465 100644
--- a/src/vnet/interface.api
+++ b/src/vnet/interface.api
@@ -223,7 +223,7 @@
   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 67cdf93..5d22bc5 100644
--- a/src/vnet/ip/ip.api
+++ b/src/vnet/ip/ip.api
@@ -29,7 +29,7 @@
 /** \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 @@
 {
   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 b24c594..4db10d1 100644
--- a/src/vnet/ip/ip_format_fns.h
+++ b/src/vnet/ip/ip_format_fns.h
@@ -83,4 +83,10 @@
   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 d9ad893..4929458 100644
--- a/src/vnet/ip/ip_types.api
+++ b/src/vnet/ip/ip_types.api
@@ -108,6 +108,23 @@
   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 2a0c83d..535bcea 100644
--- a/src/vnet/mpls/mpls.api
+++ b/src/vnet/mpls/mpls.api
@@ -26,8 +26,7 @@
     @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 6ca8e6c..9ac3e78 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 @@
                           [['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 @@
         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 7d2dcba..3e836c9 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 @@
     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 @@
     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 @@
     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 @@
                                   '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 @@
         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 @@
     '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 443dd83..c01b2d3 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 @@
         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 @@
             self.size = t.size
 
         types[name] = self
+        self.toplevelconversion = False
 
     def __call__(self, args):
         self.options = args
@@ -445,8 +446,13 @@
         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 @@
         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 @@
         # 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 @@
             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 b9b9aa7..9a285eb 100755
--- a/src/vpp-api/vapi/vapi_c_gen.py
+++ b/src/vpp-api/vapi/vapi_c_gen.py
@@ -713,12 +713,12 @@
     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 d766936..98143e2 100644
--- a/src/vpp-api/vapi/vapi_json_parser.py
+++ b/src/vpp-api/vapi/vapi_json_parser.py
@@ -377,19 +377,6 @@
                     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 @@
                     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