4 object abstractions for representing IP routes in VPP
7 from vpp_object import *
8 from socket import inet_pton, inet_ntop, AF_INET, AF_INET6
10 # from vnet/vnet/mpls/mpls_types.h
11 MPLS_IETF_MAX_LABEL = 0xfffff
12 MPLS_LABEL_INVALID = MPLS_IETF_MAX_LABEL + 1
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
24 class 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
36 DPO_PROTO_ETHERNET = 3
41 def find_route(test, ip_addr, len, table_id=0, inet=AF_INET):
44 routes = test.vapi.ip_fib_dump()
47 routes = test.vapi.ip6_fib_dump()
49 route_addr = inet_pton(inet, ip_addr)
51 if route_addr == e.address[:s] \
52 and len == e.address_length \
53 and table_id == e.table_id:
58 class VppIpTable(VppObject):
65 self.table_id = table_id
68 def add_vpp_config(self):
69 self._test.vapi.ip_table_add_del(
73 self._test.registry.register(self, self._test.logger)
75 def remove_vpp_config(self):
76 self._test.vapi.ip_table_add_del(
81 def query_vpp_config(self):
82 # find the default route
83 return find_route(self._test,
84 "::" if self.is_ip6 else "0.0.0.0",
87 inet=AF_INET6 if self.is_ip6 == 1 else AF_INET)
90 return self.object_id()
93 return ("table-%s-%d" %
94 ("v6" if self.is_ip6 == 1 else "v4",
98 class VppRoutePath(object):
106 nh_via_label=MPLS_LABEL_INVALID,
110 is_resolve_attached=0,
114 next_hop_id=0xffffffff,
115 proto=DpoProto.DPO_PROTO_IP4):
116 self.nh_itf = nh_sw_if_index
117 self.nh_table_id = nh_table_id
118 self.nh_via_label = nh_via_label
119 self.nh_labels = labels
123 if self.proto is DpoProto.DPO_PROTO_IP6:
124 self.nh_addr = inet_pton(AF_INET6, nh_addr)
125 elif self.proto is DpoProto.DPO_PROTO_IP4:
126 self.nh_addr = inet_pton(AF_INET, nh_addr)
128 self.nh_addr = inet_pton(AF_INET6, "::")
129 self.is_resolve_host = is_resolve_host
130 self.is_resolve_attached = is_resolve_attached
131 self.is_interface_rx = is_interface_rx
132 self.is_source_lookup = is_source_lookup
137 self.is_udp_encap = is_udp_encap
138 self.next_hop_id = next_hop_id
142 class VppMRoutePath(VppRoutePath):
144 def __init__(self, nh_sw_if_index, flags,
145 proto=DpoProto.DPO_PROTO_IP4,
147 super(VppMRoutePath, self).__init__(
148 "::" if proto is DpoProto.DPO_PROTO_IP6 else "0.0.0.0",
151 self.nh_i_flags = flags
152 self.bier_imp = bier_imp
155 class VppIpRoute(VppObject):
160 def __init__(self, test, dest_addr,
161 dest_addr_len, paths, table_id=0, is_ip6=0, is_local=0,
162 is_unreach=0, is_prohibit=0):
165 self.dest_addr_len = dest_addr_len
166 self.table_id = table_id
168 self.is_local = is_local
169 self.is_unreach = is_unreach
170 self.is_prohibit = is_prohibit
171 self.dest_addr_p = dest_addr
173 self.dest_addr = inet_pton(AF_INET6, dest_addr)
175 self.dest_addr = inet_pton(AF_INET, dest_addr)
177 def modify(self, paths, is_local=0,
178 is_unreach=0, is_prohibit=0):
180 self.is_local = is_local
181 self.is_unreach = is_unreach
182 self.is_prohibit = is_prohibit
184 def add_vpp_config(self):
185 if self.is_local or self.is_unreach or self.is_prohibit:
186 self._test.vapi.ip_add_del_route(
189 inet_pton(AF_INET6, "::"),
191 is_local=self.is_local,
192 is_unreach=self.is_unreach,
193 is_prohibit=self.is_prohibit,
194 table_id=self.table_id,
197 for path in self.paths:
198 self._test.vapi.ip_add_del_route(
203 table_id=self.table_id,
204 next_hop_out_label_stack=path.nh_labels,
205 next_hop_n_out_labels=len(
207 next_hop_via_label=path.nh_via_label,
208 next_hop_table_id=path.nh_table_id,
209 next_hop_id=path.next_hop_id,
212 is_resolve_host=path.is_resolve_host,
213 is_resolve_attached=path.is_resolve_attached,
214 is_source_lookup=path.is_source_lookup,
215 is_udp_encap=path.is_udp_encap,
216 is_multipath=1 if len(self.paths) > 1 else 0)
217 self._test.registry.register(self, self._test.logger)
219 def remove_vpp_config(self):
220 if self.is_local or self.is_unreach or self.is_prohibit:
221 self._test.vapi.ip_add_del_route(
224 inet_pton(AF_INET6, "::"),
226 is_local=self.is_local,
227 is_unreach=self.is_unreach,
228 is_prohibit=self.is_prohibit,
230 table_id=self.table_id,
233 for path in self.paths:
234 self._test.vapi.ip_add_del_route(
239 table_id=self.table_id,
240 next_hop_table_id=path.nh_table_id,
241 next_hop_via_label=path.nh_via_label,
242 next_hop_id=path.next_hop_id,
244 is_udp_encap=path.is_udp_encap,
248 def query_vpp_config(self):
249 return find_route(self._test,
253 inet=AF_INET6 if self.is_ip6 == 1 else AF_INET)
256 return self.object_id()
265 class VppIpMRoute(VppObject):
270 def __init__(self, test, src_addr, grp_addr,
271 grp_addr_len, e_flags, paths, table_id=0,
275 self.grp_addr_len = grp_addr_len
276 self.table_id = table_id
277 self.e_flags = e_flags
282 self.grp_addr = inet_pton(AF_INET6, grp_addr)
283 self.src_addr = inet_pton(AF_INET6, src_addr)
285 self.grp_addr = inet_pton(AF_INET, grp_addr)
286 self.src_addr = inet_pton(AF_INET, src_addr)
288 def add_vpp_config(self):
289 for path in self.paths:
290 self._test.vapi.ip_mroute_add_del(self.src_addr,
297 bier_imp=path.bier_imp,
299 table_id=self.table_id,
301 self._test.registry.register(self, self._test.logger)
303 def remove_vpp_config(self):
304 for path in self.paths:
305 self._test.vapi.ip_mroute_add_del(self.src_addr,
312 table_id=self.table_id,
313 bier_imp=path.bier_imp,
317 def update_entry_flags(self, flags):
319 self._test.vapi.ip_mroute_add_del(self.src_addr,
326 table_id=self.table_id,
329 def update_rpf_id(self, rpf_id):
331 self._test.vapi.ip_mroute_add_del(self.src_addr,
339 table_id=self.table_id,
342 def update_path_flags(self, itf, flags):
343 for path in self.paths:
344 if path.nh_itf == itf:
345 path.nh_i_flags = flags
347 self._test.vapi.ip_mroute_add_del(self.src_addr,
354 table_id=self.table_id,
357 def query_vpp_config(self):
359 dump = self._test.vapi.ip6_mfib_dump()
361 dump = self._test.vapi.ip_mfib_dump()
363 if self.grp_addr == e.grp_address \
364 and self.grp_addr_len == e.address_length \
365 and self.src_addr == e.src_address \
366 and self.table_id == e.table_id:
371 return self.object_id()
375 return ("%d:(%s,%s/%d)"
377 inet_ntop(AF_INET6, self.src_addr),
378 inet_ntop(AF_INET6, self.grp_addr),
381 return ("%d:(%s,%s/%d)"
383 inet_ntop(AF_INET, self.src_addr),
384 inet_ntop(AF_INET, self.grp_addr),
388 class VppMFibSignal(object):
389 def __init__(self, test, route, interface, packet):
391 self.interface = interface
395 def compare(self, signal):
396 self.test.assertEqual(self.interface, signal.sw_if_index)
397 self.test.assertEqual(self.route.table_id, signal.table_id)
398 self.test.assertEqual(self.route.grp_addr_len,
399 signal.grp_address_len)
400 for i in range(self.route.grp_addr_len / 8):
401 self.test.assertEqual(self.route.grp_addr[i],
402 signal.grp_address[i])
403 if (self.route.grp_addr_len > 32):
405 self.test.assertEqual(self.route.src_addr[i],
406 signal.src_address[i])
409 class VppMplsIpBind(VppObject):
414 def __init__(self, test, local_label, dest_addr, dest_addr_len,
415 table_id=0, ip_table_id=0, is_ip6=0):
417 self.dest_addr_len = dest_addr_len
418 self.dest_addr = dest_addr
419 self.local_label = local_label
420 self.table_id = table_id
421 self.ip_table_id = ip_table_id
424 self.dest_addrn = inet_pton(AF_INET6, dest_addr)
426 self.dest_addrn = inet_pton(AF_INET, dest_addr)
428 def add_vpp_config(self):
429 self._test.vapi.mpls_ip_bind_unbind(self.local_label,
432 table_id=self.table_id,
433 ip_table_id=self.ip_table_id,
434 is_ip4=(self.is_ip6 == 0))
435 self._test.registry.register(self, self._test.logger)
437 def remove_vpp_config(self):
438 self._test.vapi.mpls_ip_bind_unbind(self.local_label,
441 table_id=self.table_id,
442 ip_table_id=self.ip_table_id,
444 is_ip4=(self.is_ip6 == 0))
446 def query_vpp_config(self):
447 dump = self._test.vapi.mpls_fib_dump()
449 if self.local_label == e.label \
450 and self.table_id == e.table_id:
455 return self.object_id()
458 return ("%d:%s binds %d:%s/%d"
466 class VppMplsTable(VppObject):
472 self.table_id = table_id
474 def add_vpp_config(self):
475 self._test.vapi.mpls_table_add_del(
478 self._test.registry.register(self, self._test.logger)
480 def remove_vpp_config(self):
481 self._test.vapi.mpls_table_add_del(
485 def query_vpp_config(self):
486 # find the default route
487 dump = self._test.vapi.mpls_fib_dump()
493 return self.object_id()
496 return ("table-mpls-%d" % (self.table_id))
499 class VppMplsRoute(VppObject):
504 def __init__(self, test, local_label, eos_bit, paths, table_id=0,
508 self.local_label = local_label
509 self.eos_bit = eos_bit
510 self.table_id = table_id
511 self.is_multicast = is_multicast
513 def add_vpp_config(self):
514 is_multipath = len(self.paths) > 1
515 for path in self.paths:
516 self._test.vapi.mpls_route_add_del(
522 is_multicast=self.is_multicast,
523 is_multipath=is_multipath,
524 table_id=self.table_id,
525 is_interface_rx=path.is_interface_rx,
526 is_rpf_id=path.is_rpf_id,
527 next_hop_out_label_stack=path.nh_labels,
528 next_hop_n_out_labels=len(
530 next_hop_via_label=path.nh_via_label,
531 next_hop_table_id=path.nh_table_id)
532 self._test.registry.register(self, self._test.logger)
534 def remove_vpp_config(self):
535 for path in self.paths:
536 self._test.vapi.mpls_route_add_del(self.local_label,
541 is_rpf_id=path.is_rpf_id,
542 table_id=self.table_id,
545 def query_vpp_config(self):
546 dump = self._test.vapi.mpls_fib_dump()
548 if self.local_label == e.label \
549 and self.eos_bit == e.eos_bit \
550 and self.table_id == e.table_id:
555 return self.object_id()