tests: implement ipaddress convenience methods
[vpp.git] / src / vpp-api / python / vpp_papi / vpp_format.py
1 #
2 # Copyright (c) 2018 Cisco and/or its affiliates.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 #
15 import datetime
16 from socket import inet_pton, AF_INET6, AF_INET
17 import socket
18 import ipaddress
19 from . import macaddress
20
21 try:
22     text_type = unicode
23 except NameError:
24     text_type = str
25
26 # Copies from vl_api_address_t definition
27 ADDRESS_IP4 = 0
28 ADDRESS_IP6 = 1
29
30
31 def verify_enum_hint(e):
32     return (e.ADDRESS_IP4.value == ADDRESS_IP4) and\
33            (e.ADDRESS_IP6.value == ADDRESS_IP6)
34
35 #
36 # Type conversion for input arguments and return values
37 #
38
39
40 def format_vl_api_address_t(args):
41     try:
42         return {'un': {'ip6': inet_pton(AF_INET6, args)},
43                 'af': ADDRESS_IP6}
44     # PY2: raises socket.error
45     # PY3: raises OSError
46     except (socket.error, OSError):
47         return {'un': {'ip4': inet_pton(AF_INET, args)},
48                 'af': ADDRESS_IP4}
49
50
51 def format_vl_api_prefix_t(args):
52     if isinstance(args, (ipaddress.IPv4Network, ipaddress.IPv6Network)):
53         return {'address': format_vl_api_address_t(
54             text_type(args.network_address)),
55                 'len': int(args.prefixlen)}
56     p, length = args.split('/')
57     return {'address': format_vl_api_address_t(p),
58             'len': int(length)}
59
60 def format_vl_api_address_with_prefix_t(args):
61     if isinstance(args, (ipaddress.IPv4Interface, ipaddress.IPv6Interface)):
62         return {'address': format_vl_api_address_t(
63             text_type(args.network_address)),
64                 'len': int(args.prefixlen)}
65     p, length = args.split('/')
66     return {'address': format_vl_api_address_t(p),
67             'len': int(length)}
68
69
70 def format_vl_api_ip6_prefix_t(args):
71     if isinstance(args, ipaddress.IPv6Network):
72         return {'address': args.network_address.packed,
73                 'len': int(args.prefixlen)}
74     p, length = args.split('/')
75     return {'address': inet_pton(AF_INET6, p),
76             'len': int(length)}
77
78 def format_vl_api_ip6_address_with_prefix_t(args):
79     if isinstance(args, ipaddress.IPv6Interface):
80         return {'address': args.network_address.packed,
81                 'len': int(args.prefixlen)}
82     p, length = args.split('/')
83     return {'address': inet_pton(AF_INET6, p),
84             'len': int(length)}
85
86 def format_vl_api_ip4_prefix_t(args):
87     if isinstance(args, ipaddress.IPv4Network):
88         return {'address': args.network_address.packed,
89                 'len': int(args.prefixlen)}
90     p, length = args.split('/')
91     return {'address': inet_pton(AF_INET, p),
92             'len': int(length)}
93
94 def format_vl_api_ip4_address_with_prefix_t(args):
95     if isinstance(args, ipaddress.IPv4Interface):
96         return {'address': args.network_address.packed,
97                 'len': int(args.prefixlen)}
98     p, length = args.split('/')
99     return {'address': inet_pton(AF_INET, p),
100             'len': int(length)}
101
102
103 conversion_table = {
104     'vl_api_ip6_address_t':
105     {
106         'IPv6Address': lambda o: o.packed,
107         'str': lambda s: inet_pton(AF_INET6, s)
108     },
109     'vl_api_ip4_address_t':
110     {
111         'IPv4Address': lambda o: o.packed,
112         'str': lambda s: inet_pton(AF_INET, s)
113     },
114     'vl_api_ip6_prefix_t':
115     {
116         'IPv6Network': lambda o: {'address': o.network_address.packed,
117                                   'len': o.prefixlen},
118         'str': lambda s: format_vl_api_ip6_prefix_t(s)
119     },
120     'vl_api_ip4_prefix_t':
121     {
122         'IPv4Network': lambda o: {'address': o.network_address.packed,
123                                   'len': o.prefixlen},
124         'str': lambda s: format_vl_api_ip4_prefix_t(s)
125     },
126     'vl_api_address_t':
127     {
128         'IPv4Address': lambda o: {'af': ADDRESS_IP4, 'un': {'ip4': o.packed}},
129         'IPv6Address': lambda o: {'af': ADDRESS_IP6, 'un': {'ip6': o.packed}},
130         'str': lambda s: format_vl_api_address_t(s)
131     },
132     'vl_api_prefix_t':
133     {
134         'IPv4Network': lambda o: {'address':
135                                   {'af': ADDRESS_IP4, 'un':
136                                    {'ip4': o.network_address.packed}},
137                                   'len': o.prefixlen},
138         'IPv6Network': lambda o: {'address':
139                                   {'af': ADDRESS_IP6, 'un':
140                                    {'ip6': o.network_address.packed}},
141                                   'len': o.prefixlen},
142         'str': lambda s: format_vl_api_prefix_t(s)
143     },
144     'vl_api_address_with_prefix_t':
145     {
146         'IPv4Interface': lambda o: {'address':
147                                   {'af': ADDRESS_IP4, 'un':
148                                    {'ip4': o.packed}},
149                                   'len': o.network.prefixlen},
150         'IPv6Interface': lambda o: {'address':
151                                   {'af': ADDRESS_IP6, 'un':
152                                    {'ip6': o.packed}},
153                                   'len': o.network.prefixlen},
154         'str': lambda s: format_vl_api_address_with_prefix_t(s)
155     },
156     'vl_api_ip4_address_with_prefix_t':
157     {
158         'IPv4Interface': lambda o: {'address': o.packed,
159                                     'len': o.network.prefixlen},
160         'str': lambda s: format_vl_api_ip4_address_with_prefix_t(s)
161     },
162     'vl_api_ip6_address_with_prefix_t':
163     {
164         'IPv6Interface': lambda o: {'address': o.packed,
165                                   'len': o.network.prefixlen},
166         'str': lambda s: format_vl_api_ip6_address_with_prefix_t(s)
167     },
168     'vl_api_mac_address_t':
169     {
170         'MACAddress': lambda o: o.packed,
171         'str': lambda s: macaddress.mac_pton(s)
172     },
173     'vl_api_timestamp_t':
174     {
175         'datetime.datetime': lambda o:
176         (o - datetime.datetime(1970, 1, 1)).total_seconds()
177     }
178 }
179
180
181 def unformat_api_address_t(o):
182     if o.af == 1:
183         return ipaddress.IPv6Address(o.un.ip6)
184     if o.af == 0:
185         return ipaddress.IPv4Address(o.un.ip4)
186     raise ValueError('Unknown address family {}'.format(o))
187
188 def unformat_api_prefix_t(o):
189     if o.address.af == 1:
190         return ipaddress.IPv6Network((o.address.un.ip6, o.len), False)
191     if o.address.af == 0:
192         return ipaddress.IPv4Network((o.address.un.ip4, o.len), False)
193     raise ValueError('Unknown address family {}'.format(o))
194
195     if isinstance(o.address, ipaddress.IPv4Address):
196         return ipaddress.IPv4Network((o.address, o.len), False)
197     if isinstance(o.address, ipaddress.IPv6Address):
198         return ipaddress.IPv6Network((o.address, o.len), False)
199     raise ValueError('Unknown instance {}', format(o))
200
201 def unformat_api_address_with_prefix_t(o):
202     if o.address.af == 1:
203         return ipaddress.IPv6Interface((o.address.un.ip6, o.len))
204     if o.address.af == 0:
205         return ipaddress.IPv4Interface((o.address.un.ip4, o.len))
206     raise ValueError('Unknown address family {}'.format(o))
207
208 def unformat_api_ip4_address_with_prefix_t(o):
209     return ipaddress.IPv4Interface((o.address, o.len))
210
211 def unformat_api_ip6_address_with_prefix_t(o):
212     return ipaddress.IPv6Interface((o.address, o.len))
213
214 conversion_unpacker_table = {
215     'vl_api_ip6_address_t': lambda o: ipaddress.IPv6Address(o),
216     'vl_api_ip6_prefix_t': lambda o: ipaddress.IPv6Network((o.address, o.len)),
217     'vl_api_ip4_address_t': lambda o: ipaddress.IPv4Address(o),
218     'vl_api_ip4_prefix_t': lambda o: ipaddress.IPv4Network((o.address, o.len)),
219     'vl_api_address_t': lambda o: unformat_api_address_t(o),
220     'vl_api_prefix_t': lambda o: unformat_api_prefix_t(o),
221     'vl_api_address_with_prefix_t': lambda o: unformat_api_address_with_prefix_t(o),
222     'vl_api_ip4_address_with_prefix_t': lambda o: unformat_api_ip4_address_with_prefix_t(o),
223     'vl_api_ip6_address_with_prefix_t': lambda o: unformat_api_ip6_address_with_prefix_t(o),
224     'vl_api_mac_address_t': lambda o: macaddress.MACAddress(o),
225     'vl_api_timestamp_t': lambda o: datetime.datetime.fromtimestamp(o),
226     'vl_api_timedelta_t': lambda o: datetime.timedelta(seconds=o),
227 }