blob: 2c489e3ccb0f5a2753a0d9d5b7c735625303f74c [file] [log] [blame]
Neale Ranns177bbdc2016-11-15 09:46:51 +00001"""
2 IP Routes
3
4 object abstractions for representing IP routes in VPP
5"""
6
Neale Ranns5a8123b2017-01-26 01:18:23 -08007from vpp_object import *
Neale Rannsb3b2de72017-03-08 05:17:22 -08008from socket import inet_pton, inet_ntop, AF_INET, AF_INET6
Neale Ranns177bbdc2016-11-15 09:46:51 +00009
Neale Rannsad422ed2016-11-02 14:20:04 +000010# from vnet/vnet/mpls/mpls_types.h
11MPLS_IETF_MAX_LABEL = 0xfffff
12MPLS_LABEL_INVALID = MPLS_IETF_MAX_LABEL + 1
Neale Ranns177bbdc2016-11-15 09:46:51 +000013
Neale Ranns177bbdc2016-11-15 09:46:51 +000014
Neale Ranns180279b2017-03-16 15:49:09 -040015class MRouteItfFlags:
16 MFIB_ITF_FLAG_NONE = 0
17 MFIB_ITF_FLAG_NEGATE_SIGNAL = 1
18 MFIB_ITF_FLAG_ACCEPT = 2
19 MFIB_ITF_FLAG_FORWARD = 4
20 MFIB_ITF_FLAG_SIGNAL_PRESENT = 8
21 MFIB_ITF_FLAG_INTERNAL_COPY = 16
22
23
24class MRouteEntryFlags:
25 MFIB_ENTRY_FLAG_NONE = 0
26 MFIB_ENTRY_FLAG_SIGNAL = 1
27 MFIB_ENTRY_FLAG_DROP = 2
28 MFIB_ENTRY_FLAG_CONNECTED = 4
29 MFIB_ENTRY_FLAG_INHERIT_ACCEPT = 8
30
31
Neale Rannsda78f952017-05-24 09:15:43 -070032class DpoProto:
33 DPO_PROTO_IP4 = 0
34 DPO_PROTO_IP6 = 1
35 DPO_PROTO_MPLS = 2
36 DPO_PROTO_ETHERNET = 3
37 DPO_PROTO_NSH = 4
38
39
Neale Rannsb3b2de72017-03-08 05:17:22 -080040def find_route(test, ip_addr, len, table_id=0, inet=AF_INET):
41 if inet == AF_INET:
42 s = 4
43 routes = test.vapi.ip_fib_dump()
44 else:
45 s = 16
46 routes = test.vapi.ip6_fib_dump()
47
48 route_addr = inet_pton(inet, ip_addr)
49 for e in routes:
50 if route_addr == e.address[:s] \
51 and len == e.address_length \
52 and table_id == e.table_id:
53 return True
54 return False
55
56
Neale Ranns5a8123b2017-01-26 01:18:23 -080057class VppRoutePath(object):
Neale Rannsad422ed2016-11-02 14:20:04 +000058
Klement Sekerada505f62017-01-04 12:58:53 +010059 def __init__(
60 self,
61 nh_addr,
62 nh_sw_if_index,
63 nh_table_id=0,
64 labels=[],
Neale Rannsfca0c242017-01-13 07:57:46 -080065 nh_via_label=MPLS_LABEL_INVALID,
Neale Ranns0f26c5a2017-03-01 15:12:11 -080066 rpf_id=0,
Neale Rannsf12a83f2017-04-18 09:09:40 -070067 is_interface_rx=0,
68 is_resolve_host=0,
Neale Rannsda78f952017-05-24 09:15:43 -070069 is_resolve_attached=0,
70 proto=DpoProto.DPO_PROTO_IP4):
Neale Ranns177bbdc2016-11-15 09:46:51 +000071 self.nh_itf = nh_sw_if_index
72 self.nh_table_id = nh_table_id
Neale Rannsad422ed2016-11-02 14:20:04 +000073 self.nh_via_label = nh_via_label
74 self.nh_labels = labels
Neale Ranns0f26c5a2017-03-01 15:12:11 -080075 self.weight = 1
76 self.rpf_id = rpf_id
Neale Rannsda78f952017-05-24 09:15:43 -070077 self.proto = proto
78 if self.proto is DpoProto.DPO_PROTO_IP6:
79 self.nh_addr = inet_pton(AF_INET6, nh_addr)
80 elif self.proto is DpoProto.DPO_PROTO_IP4:
Neale Rannsb3b2de72017-03-08 05:17:22 -080081 self.nh_addr = inet_pton(AF_INET, nh_addr)
Neale Ranns31426c62017-05-24 10:32:58 -070082 else:
Neale Rannsda78f952017-05-24 09:15:43 -070083 self.nh_addr = inet_pton(AF_INET6, "::")
Neale Rannsf12a83f2017-04-18 09:09:40 -070084 self.is_resolve_host = is_resolve_host
85 self.is_resolve_attached = is_resolve_attached
Neale Ranns0f26c5a2017-03-01 15:12:11 -080086 self.is_interface_rx = is_interface_rx
87 self.is_rpf_id = 0
88 if rpf_id != 0:
89 self.is_rpf_id = 1
90 self.nh_itf = rpf_id
Neale Ranns177bbdc2016-11-15 09:46:51 +000091
92
Neale Ranns5a8123b2017-01-26 01:18:23 -080093class VppMRoutePath(VppRoutePath):
Neale Ranns32e1c012016-11-22 17:07:28 +000094
95 def __init__(self, nh_sw_if_index, flags):
Neale Ranns5a8123b2017-01-26 01:18:23 -080096 super(VppMRoutePath, self).__init__("0.0.0.0",
97 nh_sw_if_index)
Neale Ranns32e1c012016-11-22 17:07:28 +000098 self.nh_i_flags = flags
99
100
Neale Ranns5a8123b2017-01-26 01:18:23 -0800101class VppIpRoute(VppObject):
Neale Ranns177bbdc2016-11-15 09:46:51 +0000102 """
103 IP Route
104 """
105
106 def __init__(self, test, dest_addr,
Neale Ranns37be7362017-02-21 17:30:26 -0800107 dest_addr_len, paths, table_id=0, is_ip6=0, is_local=0,
108 is_unreach=0, is_prohibit=0):
Neale Ranns177bbdc2016-11-15 09:46:51 +0000109 self._test = test
110 self.paths = paths
Neale Ranns177bbdc2016-11-15 09:46:51 +0000111 self.dest_addr_len = dest_addr_len
112 self.table_id = table_id
Neale Rannsfca0c242017-01-13 07:57:46 -0800113 self.is_ip6 = is_ip6
114 self.is_local = is_local
Neale Ranns37be7362017-02-21 17:30:26 -0800115 self.is_unreach = is_unreach
116 self.is_prohibit = is_prohibit
Neale Rannsb3b2de72017-03-08 05:17:22 -0800117 self.dest_addr_p = dest_addr
Neale Rannsfca0c242017-01-13 07:57:46 -0800118 if is_ip6:
Neale Rannsb3b2de72017-03-08 05:17:22 -0800119 self.dest_addr = inet_pton(AF_INET6, dest_addr)
Neale Rannsfca0c242017-01-13 07:57:46 -0800120 else:
Neale Rannsb3b2de72017-03-08 05:17:22 -0800121 self.dest_addr = inet_pton(AF_INET, dest_addr)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000122
Neale Ranns69b7aa42017-03-10 03:04:12 -0800123 def modify(self, paths, is_local=0,
124 is_unreach=0, is_prohibit=0):
125 self.paths = paths
126 self.is_local = is_local
127 self.is_unreach = is_unreach
128 self.is_prohibit = is_prohibit
129
Neale Ranns177bbdc2016-11-15 09:46:51 +0000130 def add_vpp_config(self):
Neale Ranns37be7362017-02-21 17:30:26 -0800131 if self.is_local or self.is_unreach or self.is_prohibit:
Klement Sekerada505f62017-01-04 12:58:53 +0100132 self._test.vapi.ip_add_del_route(
133 self.dest_addr,
134 self.dest_addr_len,
Neale Rannsb3b2de72017-03-08 05:17:22 -0800135 inet_pton(AF_INET6, "::"),
Neale Rannsfca0c242017-01-13 07:57:46 -0800136 0xffffffff,
Neale Ranns37be7362017-02-21 17:30:26 -0800137 is_local=self.is_local,
138 is_unreach=self.is_unreach,
139 is_prohibit=self.is_prohibit,
Klement Sekerada505f62017-01-04 12:58:53 +0100140 table_id=self.table_id,
Neale Rannsfca0c242017-01-13 07:57:46 -0800141 is_ipv6=self.is_ip6)
142 else:
143 for path in self.paths:
144 self._test.vapi.ip_add_del_route(
145 self.dest_addr,
146 self.dest_addr_len,
147 path.nh_addr,
148 path.nh_itf,
149 table_id=self.table_id,
150 next_hop_out_label_stack=path.nh_labels,
151 next_hop_n_out_labels=len(
152 path.nh_labels),
153 next_hop_via_label=path.nh_via_label,
Neale Rannsf12a83f2017-04-18 09:09:40 -0700154 next_hop_table_id=path.nh_table_id,
155 is_ipv6=self.is_ip6,
156 is_resolve_host=path.is_resolve_host,
157 is_resolve_attached=path.is_resolve_attached,
158 is_multipath=1 if len(self.paths) > 1 else 0)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800159 self._test.registry.register(self, self._test.logger)
Neale Ranns177bbdc2016-11-15 09:46:51 +0000160
161 def remove_vpp_config(self):
Neale Ranns37be7362017-02-21 17:30:26 -0800162 if self.is_local or self.is_unreach or self.is_prohibit:
Neale Rannsfca0c242017-01-13 07:57:46 -0800163 self._test.vapi.ip_add_del_route(
164 self.dest_addr,
165 self.dest_addr_len,
Neale Rannsb3b2de72017-03-08 05:17:22 -0800166 inet_pton(AF_INET6, "::"),
Neale Rannsfca0c242017-01-13 07:57:46 -0800167 0xffffffff,
Neale Ranns37be7362017-02-21 17:30:26 -0800168 is_local=self.is_local,
169 is_unreach=self.is_unreach,
170 is_prohibit=self.is_prohibit,
Neale Rannsfca0c242017-01-13 07:57:46 -0800171 is_add=0,
172 table_id=self.table_id,
173 is_ipv6=self.is_ip6)
174 else:
175 for path in self.paths:
Neale Rannsf12a83f2017-04-18 09:09:40 -0700176 self._test.vapi.ip_add_del_route(
177 self.dest_addr,
178 self.dest_addr_len,
179 path.nh_addr,
180 path.nh_itf,
181 table_id=self.table_id,
182 next_hop_table_id=path.nh_table_id,
183 next_hop_via_label=path.nh_via_label,
184 is_add=0,
185 is_ipv6=self.is_ip6)
Neale Rannsad422ed2016-11-02 14:20:04 +0000186
Neale Ranns5a8123b2017-01-26 01:18:23 -0800187 def query_vpp_config(self):
Neale Rannsb3b2de72017-03-08 05:17:22 -0800188 return find_route(self._test,
189 self.dest_addr_p,
190 self.dest_addr_len,
191 self.table_id,
192 inet=AF_INET6 if self.is_ip6 == 1 else AF_INET)
Neale Rannsad422ed2016-11-02 14:20:04 +0000193
Neale Ranns5a8123b2017-01-26 01:18:23 -0800194 def __str__(self):
195 return self.object_id()
196
197 def object_id(self):
Neale Rannsb3b2de72017-03-08 05:17:22 -0800198 return ("%d:%s/%d"
199 % (self.table_id,
200 self.dest_addr_p,
201 self.dest_addr_len))
Neale Ranns5a8123b2017-01-26 01:18:23 -0800202
203
204class VppIpMRoute(VppObject):
Neale Ranns32e1c012016-11-22 17:07:28 +0000205 """
206 IP Multicast Route
207 """
208
209 def __init__(self, test, src_addr, grp_addr,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800210 grp_addr_len, e_flags, paths, table_id=0,
211 rpf_id=0, is_ip6=0):
Neale Ranns32e1c012016-11-22 17:07:28 +0000212 self._test = test
213 self.paths = paths
214 self.grp_addr_len = grp_addr_len
215 self.table_id = table_id
216 self.e_flags = e_flags
217 self.is_ip6 = is_ip6
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800218 self.rpf_id = rpf_id
Neale Ranns32e1c012016-11-22 17:07:28 +0000219
220 if is_ip6:
Neale Rannsb3b2de72017-03-08 05:17:22 -0800221 self.grp_addr = inet_pton(AF_INET6, grp_addr)
222 self.src_addr = inet_pton(AF_INET6, src_addr)
Neale Ranns32e1c012016-11-22 17:07:28 +0000223 else:
Neale Rannsb3b2de72017-03-08 05:17:22 -0800224 self.grp_addr = inet_pton(AF_INET, grp_addr)
225 self.src_addr = inet_pton(AF_INET, src_addr)
Neale Ranns32e1c012016-11-22 17:07:28 +0000226
227 def add_vpp_config(self):
228 for path in self.paths:
229 self._test.vapi.ip_mroute_add_del(self.src_addr,
230 self.grp_addr,
231 self.grp_addr_len,
232 self.e_flags,
233 path.nh_itf,
234 path.nh_i_flags,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800235 rpf_id=self.rpf_id,
Neale Ranns32e1c012016-11-22 17:07:28 +0000236 table_id=self.table_id,
237 is_ipv6=self.is_ip6)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800238 self._test.registry.register(self, self._test.logger)
Neale Ranns32e1c012016-11-22 17:07:28 +0000239
240 def remove_vpp_config(self):
241 for path in self.paths:
242 self._test.vapi.ip_mroute_add_del(self.src_addr,
243 self.grp_addr,
244 self.grp_addr_len,
245 self.e_flags,
246 path.nh_itf,
247 path.nh_i_flags,
248 table_id=self.table_id,
249 is_add=0,
250 is_ipv6=self.is_ip6)
251
252 def update_entry_flags(self, flags):
253 self.e_flags = flags
254 self._test.vapi.ip_mroute_add_del(self.src_addr,
255 self.grp_addr,
256 self.grp_addr_len,
257 self.e_flags,
258 0xffffffff,
259 0,
260 table_id=self.table_id,
261 is_ipv6=self.is_ip6)
262
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800263 def update_rpf_id(self, rpf_id):
264 self.rpf_id = rpf_id
265 self._test.vapi.ip_mroute_add_del(self.src_addr,
266 self.grp_addr,
267 self.grp_addr_len,
268 self.e_flags,
269 0xffffffff,
270 0,
271 rpf_id=self.rpf_id,
272 table_id=self.table_id,
273 is_ipv6=self.is_ip6)
274
Neale Ranns32e1c012016-11-22 17:07:28 +0000275 def update_path_flags(self, itf, flags):
276 for path in self.paths:
277 if path.nh_itf == itf:
278 path.nh_i_flags = flags
279 break
280 self._test.vapi.ip_mroute_add_del(self.src_addr,
281 self.grp_addr,
282 self.grp_addr_len,
283 self.e_flags,
284 path.nh_itf,
285 path.nh_i_flags,
286 table_id=self.table_id,
287 is_ipv6=self.is_ip6)
288
Neale Ranns5a8123b2017-01-26 01:18:23 -0800289 def query_vpp_config(self):
290 dump = self._test.vapi.ip_fib_dump()
291 for e in dump:
292 if self.grp_addr == e.address \
293 and self.grp_addr_len == e.address_length \
294 and self.table_id == e.table_id:
295 return True
296 return False
Neale Ranns32e1c012016-11-22 17:07:28 +0000297
Neale Ranns5a8123b2017-01-26 01:18:23 -0800298 def __str__(self):
299 return self.object_id()
300
301 def object_id(self):
302 if self.is_ip6:
303 return ("%d:(%s,%s/%d)"
304 % (self.table_id,
Neale Rannsb3b2de72017-03-08 05:17:22 -0800305 inet_ntop(AF_INET6, self.src_addr),
306 inet_ntop(AF_INET6, self.grp_addr),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800307 self.grp_addr_len))
308 else:
309 return ("%d:(%s,%s/%d)"
310 % (self.table_id,
Neale Rannsb3b2de72017-03-08 05:17:22 -0800311 inet_ntop(AF_INET, self.src_addr),
312 inet_ntop(AF_INET, self.grp_addr),
Neale Ranns5a8123b2017-01-26 01:18:23 -0800313 self.grp_addr_len))
314
315
316class VppMFibSignal(object):
Neale Ranns32e1c012016-11-22 17:07:28 +0000317 def __init__(self, test, route, interface, packet):
318 self.route = route
319 self.interface = interface
320 self.packet = packet
321 self.test = test
322
323 def compare(self, signal):
324 self.test.assertEqual(self.interface, signal.sw_if_index)
325 self.test.assertEqual(self.route.table_id, signal.table_id)
326 self.test.assertEqual(self.route.grp_addr_len,
327 signal.grp_address_len)
328 for i in range(self.route.grp_addr_len / 8):
329 self.test.assertEqual(self.route.grp_addr[i],
330 signal.grp_address[i])
331 if (self.route.grp_addr_len > 32):
332 for i in range(4):
333 self.test.assertEqual(self.route.src_addr[i],
334 signal.src_address[i])
335
336
Neale Ranns5a8123b2017-01-26 01:18:23 -0800337class VppMplsIpBind(VppObject):
Neale Rannsad422ed2016-11-02 14:20:04 +0000338 """
339 MPLS to IP Binding
340 """
341
Neale Ranns5a8123b2017-01-26 01:18:23 -0800342 def __init__(self, test, local_label, dest_addr, dest_addr_len,
Neale Rannsf12a83f2017-04-18 09:09:40 -0700343 table_id=0, ip_table_id=0, is_ip6=0):
Neale Rannsad422ed2016-11-02 14:20:04 +0000344 self._test = test
Neale Rannsad422ed2016-11-02 14:20:04 +0000345 self.dest_addr_len = dest_addr_len
Neale Rannsf12a83f2017-04-18 09:09:40 -0700346 self.dest_addr = dest_addr
Neale Rannsad422ed2016-11-02 14:20:04 +0000347 self.local_label = local_label
Neale Ranns5a8123b2017-01-26 01:18:23 -0800348 self.table_id = table_id
349 self.ip_table_id = ip_table_id
Neale Rannsf12a83f2017-04-18 09:09:40 -0700350 self.is_ip6 = is_ip6
351 if is_ip6:
352 self.dest_addrn = inet_pton(AF_INET6, dest_addr)
353 else:
354 self.dest_addrn = inet_pton(AF_INET, dest_addr)
Neale Rannsad422ed2016-11-02 14:20:04 +0000355
356 def add_vpp_config(self):
357 self._test.vapi.mpls_ip_bind_unbind(self.local_label,
Neale Rannsf12a83f2017-04-18 09:09:40 -0700358 self.dest_addrn,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800359 self.dest_addr_len,
360 table_id=self.table_id,
Neale Rannsf12a83f2017-04-18 09:09:40 -0700361 ip_table_id=self.ip_table_id,
362 is_ip4=(self.is_ip6 == 0))
Neale Ranns5a8123b2017-01-26 01:18:23 -0800363 self._test.registry.register(self, self._test.logger)
Neale Rannsad422ed2016-11-02 14:20:04 +0000364
365 def remove_vpp_config(self):
366 self._test.vapi.mpls_ip_bind_unbind(self.local_label,
Neale Rannsf12a83f2017-04-18 09:09:40 -0700367 self.dest_addrn,
Neale Rannsad422ed2016-11-02 14:20:04 +0000368 self.dest_addr_len,
Neale Rannsf12a83f2017-04-18 09:09:40 -0700369 table_id=self.table_id,
370 ip_table_id=self.ip_table_id,
371 is_bind=0,
372 is_ip4=(self.is_ip6 == 0))
Neale Rannsad422ed2016-11-02 14:20:04 +0000373
Neale Ranns5a8123b2017-01-26 01:18:23 -0800374 def query_vpp_config(self):
375 dump = self._test.vapi.mpls_fib_dump()
376 for e in dump:
377 if self.local_label == e.label \
Neale Ranns5a8123b2017-01-26 01:18:23 -0800378 and self.table_id == e.table_id:
379 return True
380 return False
Neale Rannsad422ed2016-11-02 14:20:04 +0000381
Neale Ranns5a8123b2017-01-26 01:18:23 -0800382 def __str__(self):
383 return self.object_id()
384
385 def object_id(self):
386 return ("%d:%s binds %d:%s/%d"
387 % (self.table_id,
388 self.local_label,
389 self.ip_table_id,
Neale Rannsf12a83f2017-04-18 09:09:40 -0700390 self.dest_addr,
Neale Ranns5a8123b2017-01-26 01:18:23 -0800391 self.dest_addr_len))
392
393
394class VppMplsRoute(VppObject):
Neale Rannsad422ed2016-11-02 14:20:04 +0000395 """
Neale Ranns5a8123b2017-01-26 01:18:23 -0800396 MPLS Route/LSP
Neale Rannsad422ed2016-11-02 14:20:04 +0000397 """
398
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800399 def __init__(self, test, local_label, eos_bit, paths, table_id=0,
400 is_multicast=0):
Neale Rannsad422ed2016-11-02 14:20:04 +0000401 self._test = test
402 self.paths = paths
403 self.local_label = local_label
404 self.eos_bit = eos_bit
405 self.table_id = table_id
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800406 self.is_multicast = is_multicast
Neale Rannsad422ed2016-11-02 14:20:04 +0000407
408 def add_vpp_config(self):
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800409 is_multipath = len(self.paths) > 1
Neale Rannsad422ed2016-11-02 14:20:04 +0000410 for path in self.paths:
Klement Sekerada505f62017-01-04 12:58:53 +0100411 self._test.vapi.mpls_route_add_del(
412 self.local_label,
413 self.eos_bit,
Neale Rannsda78f952017-05-24 09:15:43 -0700414 path.proto,
Klement Sekerada505f62017-01-04 12:58:53 +0100415 path.nh_addr,
416 path.nh_itf,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800417 is_multicast=self.is_multicast,
418 is_multipath=is_multipath,
Klement Sekerada505f62017-01-04 12:58:53 +0100419 table_id=self.table_id,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800420 is_interface_rx=path.is_interface_rx,
421 is_rpf_id=path.is_rpf_id,
Klement Sekerada505f62017-01-04 12:58:53 +0100422 next_hop_out_label_stack=path.nh_labels,
423 next_hop_n_out_labels=len(
424 path.nh_labels),
425 next_hop_via_label=path.nh_via_label,
426 next_hop_table_id=path.nh_table_id)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800427 self._test.registry.register(self, self._test.logger)
Neale Rannsad422ed2016-11-02 14:20:04 +0000428
429 def remove_vpp_config(self):
430 for path in self.paths:
431 self._test.vapi.mpls_route_add_del(self.local_label,
432 self.eos_bit,
Neale Rannsda78f952017-05-24 09:15:43 -0700433 path.proto,
Neale Rannsad422ed2016-11-02 14:20:04 +0000434 path.nh_addr,
435 path.nh_itf,
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800436 is_rpf_id=path.is_rpf_id,
Neale Rannsad422ed2016-11-02 14:20:04 +0000437 table_id=self.table_id,
438 is_add=0)
Neale Ranns5a8123b2017-01-26 01:18:23 -0800439
440 def query_vpp_config(self):
441 dump = self._test.vapi.mpls_fib_dump()
442 for e in dump:
443 if self.local_label == e.label \
444 and self.eos_bit == e.eos_bit \
445 and self.table_id == e.table_id:
446 return True
447 return False
448
449 def __str__(self):
450 return self.object_id()
451
452 def object_id(self):
453 return ("%d:%s/%d"
454 % (self.table_id,
455 self.local_label,
456 20+self.eos_bit))