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
40 def find_route(test, ip_addr, len, table_id=0, inet=AF_INET):
43 routes = test.vapi.ip_fib_dump()
46 routes = test.vapi.ip6_fib_dump()
48 route_addr = inet_pton(inet, ip_addr)
50 if route_addr == e.address[:s] \
51 and len == e.address_length \
52 and table_id == e.table_id:
57 class VppIpTable(VppObject):
64 self.table_id = table_id
67 def add_vpp_config(self):
68 self._test.vapi.ip_table_add_del(
72 self._test.registry.register(self, self._test.logger)
74 def remove_vpp_config(self):
75 self._test.vapi.ip_table_add_del(
80 def query_vpp_config(self):
81 # find the default route
82 return find_route(self._test,
83 "::" if self.is_ip6 else "0.0.0.0",
86 inet=AF_INET6 if self.is_ip6 == 1 else AF_INET)
89 return self.object_id()
92 return ("table-%s-%d" %
93 ("v6" if self.is_ip6 == 1 else "v4",
97 class VppRoutePath(object):
105 nh_via_label=MPLS_LABEL_INVALID,
109 is_resolve_attached=0,
111 proto=DpoProto.DPO_PROTO_IP4):
112 self.nh_itf = nh_sw_if_index
113 self.nh_table_id = nh_table_id
114 self.nh_via_label = nh_via_label
115 self.nh_labels = labels
119 if self.proto is DpoProto.DPO_PROTO_IP6:
120 self.nh_addr = inet_pton(AF_INET6, nh_addr)
121 elif self.proto is DpoProto.DPO_PROTO_IP4:
122 self.nh_addr = inet_pton(AF_INET, nh_addr)
124 self.nh_addr = inet_pton(AF_INET6, "::")
125 self.is_resolve_host = is_resolve_host
126 self.is_resolve_attached = is_resolve_attached
127 self.is_interface_rx = is_interface_rx
128 self.is_source_lookup = is_source_lookup
135 class VppMRoutePath(VppRoutePath):
137 def __init__(self, nh_sw_if_index, flags):
138 super(VppMRoutePath, self).__init__("0.0.0.0",
140 self.nh_i_flags = flags
143 class VppIpRoute(VppObject):
148 def __init__(self, test, dest_addr,
149 dest_addr_len, paths, table_id=0, is_ip6=0, is_local=0,
150 is_unreach=0, is_prohibit=0):
153 self.dest_addr_len = dest_addr_len
154 self.table_id = table_id
156 self.is_local = is_local
157 self.is_unreach = is_unreach
158 self.is_prohibit = is_prohibit
159 self.dest_addr_p = dest_addr
161 self.dest_addr = inet_pton(AF_INET6, dest_addr)
163 self.dest_addr = inet_pton(AF_INET, dest_addr)
165 def modify(self, paths, is_local=0,
166 is_unreach=0, is_prohibit=0):
168 self.is_local = is_local
169 self.is_unreach = is_unreach
170 self.is_prohibit = is_prohibit
172 def add_vpp_config(self):
173 if self.is_local or self.is_unreach or self.is_prohibit:
174 self._test.vapi.ip_add_del_route(
177 inet_pton(AF_INET6, "::"),
179 is_local=self.is_local,
180 is_unreach=self.is_unreach,
181 is_prohibit=self.is_prohibit,
182 table_id=self.table_id,
185 for path in self.paths:
186 self._test.vapi.ip_add_del_route(
191 table_id=self.table_id,
192 next_hop_out_label_stack=path.nh_labels,
193 next_hop_n_out_labels=len(
195 next_hop_via_label=path.nh_via_label,
196 next_hop_table_id=path.nh_table_id,
199 if path.proto == DpoProto.DPO_PROTO_ETHERNET else 0,
200 is_resolve_host=path.is_resolve_host,
201 is_resolve_attached=path.is_resolve_attached,
202 is_source_lookup=path.is_source_lookup,
203 is_multipath=1 if len(self.paths) > 1 else 0)
204 self._test.registry.register(self, self._test.logger)
206 def remove_vpp_config(self):
207 if self.is_local or self.is_unreach or self.is_prohibit:
208 self._test.vapi.ip_add_del_route(
211 inet_pton(AF_INET6, "::"),
213 is_local=self.is_local,
214 is_unreach=self.is_unreach,
215 is_prohibit=self.is_prohibit,
217 table_id=self.table_id,
220 for path in self.paths:
221 self._test.vapi.ip_add_del_route(
226 table_id=self.table_id,
227 next_hop_table_id=path.nh_table_id,
228 next_hop_via_label=path.nh_via_label,
232 def query_vpp_config(self):
233 return find_route(self._test,
237 inet=AF_INET6 if self.is_ip6 == 1 else AF_INET)
240 return self.object_id()
249 class VppIpMRoute(VppObject):
254 def __init__(self, test, src_addr, grp_addr,
255 grp_addr_len, e_flags, paths, table_id=0,
259 self.grp_addr_len = grp_addr_len
260 self.table_id = table_id
261 self.e_flags = e_flags
266 self.grp_addr = inet_pton(AF_INET6, grp_addr)
267 self.src_addr = inet_pton(AF_INET6, src_addr)
269 self.grp_addr = inet_pton(AF_INET, grp_addr)
270 self.src_addr = inet_pton(AF_INET, src_addr)
272 def add_vpp_config(self):
273 for path in self.paths:
274 self._test.vapi.ip_mroute_add_del(self.src_addr,
281 table_id=self.table_id,
283 self._test.registry.register(self, self._test.logger)
285 def remove_vpp_config(self):
286 for path in self.paths:
287 self._test.vapi.ip_mroute_add_del(self.src_addr,
293 table_id=self.table_id,
297 def update_entry_flags(self, flags):
299 self._test.vapi.ip_mroute_add_del(self.src_addr,
305 table_id=self.table_id,
308 def update_rpf_id(self, rpf_id):
310 self._test.vapi.ip_mroute_add_del(self.src_addr,
317 table_id=self.table_id,
320 def update_path_flags(self, itf, flags):
321 for path in self.paths:
322 if path.nh_itf == itf:
323 path.nh_i_flags = flags
325 self._test.vapi.ip_mroute_add_del(self.src_addr,
331 table_id=self.table_id,
334 def query_vpp_config(self):
335 dump = self._test.vapi.ip_fib_dump()
337 if self.grp_addr == e.address \
338 and self.grp_addr_len == e.address_length \
339 and self.table_id == e.table_id:
344 return self.object_id()
348 return ("%d:(%s,%s/%d)"
350 inet_ntop(AF_INET6, self.src_addr),
351 inet_ntop(AF_INET6, self.grp_addr),
354 return ("%d:(%s,%s/%d)"
356 inet_ntop(AF_INET, self.src_addr),
357 inet_ntop(AF_INET, self.grp_addr),
361 class VppMFibSignal(object):
362 def __init__(self, test, route, interface, packet):
364 self.interface = interface
368 def compare(self, signal):
369 self.test.assertEqual(self.interface, signal.sw_if_index)
370 self.test.assertEqual(self.route.table_id, signal.table_id)
371 self.test.assertEqual(self.route.grp_addr_len,
372 signal.grp_address_len)
373 for i in range(self.route.grp_addr_len / 8):
374 self.test.assertEqual(self.route.grp_addr[i],
375 signal.grp_address[i])
376 if (self.route.grp_addr_len > 32):
378 self.test.assertEqual(self.route.src_addr[i],
379 signal.src_address[i])
382 class VppMplsIpBind(VppObject):
387 def __init__(self, test, local_label, dest_addr, dest_addr_len,
388 table_id=0, ip_table_id=0, is_ip6=0):
390 self.dest_addr_len = dest_addr_len
391 self.dest_addr = dest_addr
392 self.local_label = local_label
393 self.table_id = table_id
394 self.ip_table_id = ip_table_id
397 self.dest_addrn = inet_pton(AF_INET6, dest_addr)
399 self.dest_addrn = inet_pton(AF_INET, dest_addr)
401 def add_vpp_config(self):
402 self._test.vapi.mpls_ip_bind_unbind(self.local_label,
405 table_id=self.table_id,
406 ip_table_id=self.ip_table_id,
407 is_ip4=(self.is_ip6 == 0))
408 self._test.registry.register(self, self._test.logger)
410 def remove_vpp_config(self):
411 self._test.vapi.mpls_ip_bind_unbind(self.local_label,
414 table_id=self.table_id,
415 ip_table_id=self.ip_table_id,
417 is_ip4=(self.is_ip6 == 0))
419 def query_vpp_config(self):
420 dump = self._test.vapi.mpls_fib_dump()
422 if self.local_label == e.label \
423 and self.table_id == e.table_id:
428 return self.object_id()
431 return ("%d:%s binds %d:%s/%d"
439 class VppMplsTable(VppObject):
445 self.table_id = table_id
447 def add_vpp_config(self):
448 self._test.vapi.mpls_table_add_del(
451 self._test.registry.register(self, self._test.logger)
453 def remove_vpp_config(self):
454 self._test.vapi.mpls_table_add_del(
458 def query_vpp_config(self):
459 # find the default route
460 dump = self._test.vapi.mpls_fib_dump()
466 return self.object_id()
469 return ("table-mpls-%d" % (self.table_id))
472 class VppMplsRoute(VppObject):
477 def __init__(self, test, local_label, eos_bit, paths, table_id=0,
481 self.local_label = local_label
482 self.eos_bit = eos_bit
483 self.table_id = table_id
484 self.is_multicast = is_multicast
486 def add_vpp_config(self):
487 is_multipath = len(self.paths) > 1
488 for path in self.paths:
489 self._test.vapi.mpls_route_add_del(
495 is_multicast=self.is_multicast,
496 is_multipath=is_multipath,
497 table_id=self.table_id,
498 is_interface_rx=path.is_interface_rx,
499 is_rpf_id=path.is_rpf_id,
500 next_hop_out_label_stack=path.nh_labels,
501 next_hop_n_out_labels=len(
503 next_hop_via_label=path.nh_via_label,
504 next_hop_table_id=path.nh_table_id)
505 self._test.registry.register(self, self._test.logger)
507 def remove_vpp_config(self):
508 for path in self.paths:
509 self._test.vapi.mpls_route_add_del(self.local_label,
514 is_rpf_id=path.is_rpf_id,
515 table_id=self.table_id,
518 def query_vpp_config(self):
519 dump = self._test.vapi.mpls_fib_dump()
521 if self.local_label == e.label \
522 and self.eos_bit == e.eos_bit \
523 and self.table_id == e.table_id:
528 return self.object_id()