X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=test%2Fvpp_ip_route.py;h=00a79f442329f43b6fe05ea1427607b93efd7fe4;hb=28c142e3;hp=e1c2b4b41f9fb0952ac4442f5e676c68e2ebbc08;hpb=69b7aa424abaec4adae0e9007794cf35a7f9849f;p=vpp.git diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py index e1c2b4b41f9..00a79f44232 100644 --- a/test/vpp_ip_route.py +++ b/test/vpp_ip_route.py @@ -6,12 +6,35 @@ from vpp_object import * from socket import inet_pton, inet_ntop, AF_INET, AF_INET6 +from vpp_ip import * # from vnet/vnet/mpls/mpls_types.h MPLS_IETF_MAX_LABEL = 0xfffff MPLS_LABEL_INVALID = MPLS_IETF_MAX_LABEL + 1 +class MRouteItfFlags: + MFIB_ITF_FLAG_NONE = 0 + MFIB_ITF_FLAG_NEGATE_SIGNAL = 1 + MFIB_ITF_FLAG_ACCEPT = 2 + MFIB_ITF_FLAG_FORWARD = 4 + MFIB_ITF_FLAG_SIGNAL_PRESENT = 8 + MFIB_ITF_FLAG_INTERNAL_COPY = 16 + + +class MRouteEntryFlags: + MFIB_ENTRY_FLAG_NONE = 0 + MFIB_ENTRY_FLAG_SIGNAL = 1 + MFIB_ENTRY_FLAG_DROP = 2 + MFIB_ENTRY_FLAG_CONNECTED = 4 + MFIB_ENTRY_FLAG_INHERIT_ACCEPT = 8 + + +class MplsLspMode: + PIPE = 0 + UNIFORM = 1 + + def find_route(test, ip_addr, len, table_id=0, inet=AF_INET): if inet == AF_INET: s = 4 @@ -29,6 +52,80 @@ def find_route(test, ip_addr, len, table_id=0, inet=AF_INET): return False +def find_mroute(test, grp_addr, src_addr, grp_addr_len, + table_id=0, inet=AF_INET): + if inet == AF_INET: + s = 4 + routes = test.vapi.ip_mfib_dump() + else: + s = 16 + routes = test.vapi.ip6_mfib_dump() + gaddr = inet_pton(inet, grp_addr) + saddr = inet_pton(inet, src_addr) + for e in routes: + if gaddr == e.grp_address[:s] \ + and grp_addr_len == e.address_length \ + and saddr == e.src_address[:s] \ + and table_id == e.table_id: + return True + return False + + +class VppIpTable(VppObject): + + def __init__(self, + test, + table_id, + is_ip6=0): + self._test = test + self.table_id = table_id + self.is_ip6 = is_ip6 + + def add_vpp_config(self): + self._test.vapi.ip_table_add_del( + self.table_id, + is_ipv6=self.is_ip6, + is_add=1) + self._test.registry.register(self, self._test.logger) + + def remove_vpp_config(self): + self._test.vapi.ip_table_add_del( + self.table_id, + is_ipv6=self.is_ip6, + is_add=0) + + def query_vpp_config(self): + # find the default route + return find_route(self._test, + "::" if self.is_ip6 else "0.0.0.0", + 0, + self.table_id, + inet=AF_INET6 if self.is_ip6 == 1 else AF_INET) + + def __str__(self): + return self.object_id() + + def object_id(self): + return ("table-%s-%d" % + ("v6" if self.is_ip6 == 1 else "v4", + self.table_id)) + + +class VppMplsLabel(object): + def __init__(self, value, mode=MplsLspMode.PIPE, ttl=64, exp=0): + self.value = value + self.mode = mode + self.ttl = ttl + self.exp = exp + + def encode(self): + is_uniform = 0 if self.mode is MplsLspMode.PIPE else 1 + return {'label': self.value, + 'ttl': self.ttl, + 'exp': self.exp, + 'is_uniform': is_uniform} + + class VppRoutePath(object): def __init__( @@ -38,23 +135,80 @@ class VppRoutePath(object): nh_table_id=0, labels=[], nh_via_label=MPLS_LABEL_INVALID, - is_ip6=0): + rpf_id=0, + is_interface_rx=0, + is_resolve_host=0, + is_resolve_attached=0, + is_source_lookup=0, + is_udp_encap=0, + is_dvr=0, + next_hop_id=0xffffffff, + proto=DpoProto.DPO_PROTO_IP4): self.nh_itf = nh_sw_if_index self.nh_table_id = nh_table_id self.nh_via_label = nh_via_label self.nh_labels = labels - if is_ip6: + self.weight = 1 + self.rpf_id = rpf_id + self.proto = proto + if self.proto is DpoProto.DPO_PROTO_IP6: self.nh_addr = inet_pton(AF_INET6, nh_addr) - else: + elif self.proto is DpoProto.DPO_PROTO_IP4: self.nh_addr = inet_pton(AF_INET, nh_addr) + else: + self.nh_addr = inet_pton(AF_INET6, "::") + self.is_resolve_host = is_resolve_host + self.is_resolve_attached = is_resolve_attached + self.is_interface_rx = is_interface_rx + self.is_source_lookup = is_source_lookup + self.is_rpf_id = 0 + if rpf_id != 0: + self.is_rpf_id = 1 + self.nh_itf = rpf_id + self.is_udp_encap = is_udp_encap + self.next_hop_id = next_hop_id + self.is_dvr = is_dvr + + def encode_labels(self): + lstack = [] + for l in self.nh_labels: + if type(l) == VppMplsLabel: + lstack.append(l.encode()) + else: + lstack.append({'label': l, + 'ttl': 255}) + return lstack + + def encode(self): + return {'next_hop': self.nh_addr, + 'weight': 1, + 'afi': 0, + 'preference': 0, + 'table_id': self.nh_table_id, + 'next_hop_id': self.next_hop_id, + 'sw_if_index': self.nh_itf, + 'afi': self.proto, + 'is_udp_encap': self.is_udp_encap, + 'n_labels': len(self.nh_labels), + 'label_stack': self.encode_labels()} + + def __eq__(self, other): + return self.nh_addr == other.nh_addr class VppMRoutePath(VppRoutePath): - def __init__(self, nh_sw_if_index, flags): - super(VppMRoutePath, self).__init__("0.0.0.0", - nh_sw_if_index) + def __init__(self, nh_sw_if_index, flags, + nh=None, + proto=DpoProto.DPO_PROTO_IP4, + bier_imp=0): + if not nh: + nh = "::" if proto is DpoProto.DPO_PROTO_IP6 else "0.0.0.0" + super(VppMRoutePath, self).__init__(nh, + nh_sw_if_index, + proto=proto) self.nh_i_flags = flags + self.bier_imp = bier_imp class VppIpRoute(VppObject): @@ -64,7 +218,7 @@ class VppIpRoute(VppObject): def __init__(self, test, dest_addr, dest_addr_len, paths, table_id=0, is_ip6=0, is_local=0, - is_unreach=0, is_prohibit=0): + is_unreach=0, is_prohibit=0, is_drop=0): self._test = test self.paths = paths self.dest_addr_len = dest_addr_len @@ -73,6 +227,7 @@ class VppIpRoute(VppObject): self.is_local = is_local self.is_unreach = is_unreach self.is_prohibit = is_prohibit + self.is_drop = is_drop self.dest_addr_p = dest_addr if is_ip6: self.dest_addr = inet_pton(AF_INET6, dest_addr) @@ -87,8 +242,9 @@ class VppIpRoute(VppObject): self.is_prohibit = is_prohibit def add_vpp_config(self): - if self.is_local or self.is_unreach or self.is_prohibit: - self._test.vapi.ip_add_del_route( + if self.is_local or self.is_unreach or \ + self.is_prohibit or self.is_drop: + r = self._test.vapi.ip_add_del_route( self.dest_addr, self.dest_addr_len, inet_pton(AF_INET6, "::"), @@ -96,25 +252,37 @@ class VppIpRoute(VppObject): is_local=self.is_local, is_unreach=self.is_unreach, is_prohibit=self.is_prohibit, + is_drop=self.is_drop, table_id=self.table_id, is_ipv6=self.is_ip6) else: for path in self.paths: - self._test.vapi.ip_add_del_route( + lstack = path.encode_labels() + + r = self._test.vapi.ip_add_del_route( self.dest_addr, self.dest_addr_len, path.nh_addr, path.nh_itf, table_id=self.table_id, - next_hop_out_label_stack=path.nh_labels, - next_hop_n_out_labels=len( - path.nh_labels), + next_hop_out_label_stack=lstack, + next_hop_n_out_labels=len(lstack), next_hop_via_label=path.nh_via_label, - is_ipv6=self.is_ip6) + next_hop_table_id=path.nh_table_id, + next_hop_id=path.next_hop_id, + is_ipv6=self.is_ip6, + is_dvr=path.is_dvr, + is_resolve_host=path.is_resolve_host, + is_resolve_attached=path.is_resolve_attached, + is_source_lookup=path.is_source_lookup, + is_udp_encap=path.is_udp_encap, + is_multipath=1 if len(self.paths) > 1 else 0) + self.stats_index = r.stats_index self._test.registry.register(self, self._test.logger) def remove_vpp_config(self): - if self.is_local or self.is_unreach or self.is_prohibit: + if self.is_local or self.is_unreach or \ + self.is_prohibit or self.is_drop: self._test.vapi.ip_add_del_route( self.dest_addr, self.dest_addr_len, @@ -128,13 +296,19 @@ class VppIpRoute(VppObject): is_ipv6=self.is_ip6) else: for path in self.paths: - self._test.vapi.ip_add_del_route(self.dest_addr, - self.dest_addr_len, - path.nh_addr, - path.nh_itf, - table_id=self.table_id, - is_add=0, - is_ipv6=self.is_ip6) + self._test.vapi.ip_add_del_route( + self.dest_addr, + self.dest_addr_len, + path.nh_addr, + path.nh_itf, + table_id=self.table_id, + next_hop_table_id=path.nh_table_id, + next_hop_via_label=path.nh_via_label, + next_hop_id=path.next_hop_id, + is_add=0, + is_udp_encap=path.is_udp_encap, + is_ipv6=self.is_ip6, + is_dvr=path.is_dvr) def query_vpp_config(self): return find_route(self._test, @@ -152,6 +326,14 @@ class VppIpRoute(VppObject): self.dest_addr_p, self.dest_addr_len)) + def get_stats_to(self): + c = self._test.statistics.get_counter("/net/route/to") + return c[0][self.stats_index] + + def get_stats_via(self): + c = self._test.statistics.get_counter("/net/route/via") + return c[0][self.stats_index] + class VppIpMRoute(VppObject): """ @@ -159,14 +341,18 @@ class VppIpMRoute(VppObject): """ def __init__(self, test, src_addr, grp_addr, - grp_addr_len, e_flags, paths, table_id=0, is_ip6=0): + grp_addr_len, e_flags, paths, table_id=0, + rpf_id=0, is_ip6=0): self._test = test self.paths = paths self.grp_addr_len = grp_addr_len self.table_id = table_id self.e_flags = e_flags self.is_ip6 = is_ip6 + self.rpf_id = rpf_id + self.grp_addr_p = grp_addr + self.src_addr_p = src_addr if is_ip6: self.grp_addr = inet_pton(AF_INET6, grp_addr) self.src_addr = inet_pton(AF_INET6, src_addr) @@ -176,14 +362,19 @@ class VppIpMRoute(VppObject): def add_vpp_config(self): for path in self.paths: - self._test.vapi.ip_mroute_add_del(self.src_addr, - self.grp_addr, - self.grp_addr_len, - self.e_flags, - path.nh_itf, - path.nh_i_flags, - table_id=self.table_id, - is_ipv6=self.is_ip6) + r = self._test.vapi.ip_mroute_add_del(self.src_addr, + self.grp_addr, + self.grp_addr_len, + self.e_flags, + path.proto, + path.nh_itf, + path.nh_addr, + path.nh_i_flags, + bier_imp=path.bier_imp, + rpf_id=self.rpf_id, + table_id=self.table_id, + is_ipv6=self.is_ip6) + self.stats_index = r.stats_index self._test.registry.register(self, self._test.logger) def remove_vpp_config(self): @@ -192,9 +383,12 @@ class VppIpMRoute(VppObject): self.grp_addr, self.grp_addr_len, self.e_flags, + path.proto, path.nh_itf, + path.nh_addr, path.nh_i_flags, table_id=self.table_id, + bier_imp=path.bier_imp, is_add=0, is_ipv6=self.is_ip6) @@ -204,11 +398,27 @@ class VppIpMRoute(VppObject): self.grp_addr, self.grp_addr_len, self.e_flags, + 0, 0xffffffff, + "", 0, table_id=self.table_id, is_ipv6=self.is_ip6) + def update_rpf_id(self, rpf_id): + self.rpf_id = rpf_id + self._test.vapi.ip_mroute_add_del(self.src_addr, + self.grp_addr, + self.grp_addr_len, + self.e_flags, + 0, + 0xffffffff, + "", + 0, + rpf_id=self.rpf_id, + table_id=self.table_id, + is_ipv6=self.is_ip6) + def update_path_flags(self, itf, flags): for path in self.paths: if path.nh_itf == itf: @@ -218,19 +428,20 @@ class VppIpMRoute(VppObject): self.grp_addr, self.grp_addr_len, self.e_flags, + path.proto, path.nh_itf, + path.nh_addr, path.nh_i_flags, table_id=self.table_id, is_ipv6=self.is_ip6) def query_vpp_config(self): - dump = self._test.vapi.ip_fib_dump() - for e in dump: - if self.grp_addr == e.address \ - and self.grp_addr_len == e.address_length \ - and self.table_id == e.table_id: - return True - return False + return find_mroute(self._test, + self.grp_addr_p, + self.src_addr_p, + self.grp_addr_len, + self.table_id, + inet=AF_INET6 if self.is_ip6 == 1 else AF_INET) def __str__(self): return self.object_id() @@ -249,6 +460,10 @@ class VppIpMRoute(VppObject): inet_ntop(AF_INET, self.grp_addr), self.grp_addr_len)) + def get_stats(self): + c = self._test.statistics.get_counter("/net/mroute") + return c[0][self.stats_index] + class VppMFibSignal(object): def __init__(self, test, route, interface, packet): @@ -277,33 +492,41 @@ class VppMplsIpBind(VppObject): """ def __init__(self, test, local_label, dest_addr, dest_addr_len, - table_id=0, ip_table_id=0): + table_id=0, ip_table_id=0, is_ip6=0): self._test = test - self.dest_addr = inet_pton(AF_INET, dest_addr) self.dest_addr_len = dest_addr_len + self.dest_addr = dest_addr self.local_label = local_label self.table_id = table_id self.ip_table_id = ip_table_id + self.is_ip6 = is_ip6 + if is_ip6: + self.dest_addrn = inet_pton(AF_INET6, dest_addr) + else: + self.dest_addrn = inet_pton(AF_INET, dest_addr) def add_vpp_config(self): self._test.vapi.mpls_ip_bind_unbind(self.local_label, - self.dest_addr, + self.dest_addrn, self.dest_addr_len, table_id=self.table_id, - ip_table_id=self.ip_table_id) + ip_table_id=self.ip_table_id, + is_ip4=(self.is_ip6 == 0)) self._test.registry.register(self, self._test.logger) def remove_vpp_config(self): self._test.vapi.mpls_ip_bind_unbind(self.local_label, - self.dest_addr, + self.dest_addrn, self.dest_addr_len, - is_bind=0) + table_id=self.table_id, + ip_table_id=self.ip_table_id, + is_bind=0, + is_ip4=(self.is_ip6 == 0)) def query_vpp_config(self): dump = self._test.vapi.mpls_fib_dump() for e in dump: if self.local_label == e.label \ - and self.eos_bit == e.eos_bit \ and self.table_id == e.table_id: return True return False @@ -316,45 +539,88 @@ class VppMplsIpBind(VppObject): % (self.table_id, self.local_label, self.ip_table_id, - inet_ntop(AF_INET, self.dest_addr), + self.dest_addr, self.dest_addr_len)) +class VppMplsTable(VppObject): + + def __init__(self, + test, + table_id): + self._test = test + self.table_id = table_id + + def add_vpp_config(self): + self._test.vapi.mpls_table_add_del( + self.table_id, + is_add=1) + self._test.registry.register(self, self._test.logger) + + def remove_vpp_config(self): + self._test.vapi.mpls_table_add_del( + self.table_id, + is_add=0) + + def query_vpp_config(self): + # find the default route + dump = self._test.vapi.mpls_fib_dump() + if len(dump): + return True + return False + + def __str__(self): + return self.object_id() + + def object_id(self): + return ("table-mpls-%d" % (self.table_id)) + + class VppMplsRoute(VppObject): """ MPLS Route/LSP """ - def __init__(self, test, local_label, eos_bit, paths, table_id=0): + def __init__(self, test, local_label, eos_bit, paths, table_id=0, + is_multicast=0): self._test = test self.paths = paths self.local_label = local_label self.eos_bit = eos_bit self.table_id = table_id + self.is_multicast = is_multicast def add_vpp_config(self): + is_multipath = len(self.paths) > 1 for path in self.paths: - self._test.vapi.mpls_route_add_del( + lstack = path.encode_labels() + + r = self._test.vapi.mpls_route_add_del( self.local_label, self.eos_bit, - 1, + path.proto, path.nh_addr, path.nh_itf, + is_multicast=self.is_multicast, + is_multipath=is_multipath, table_id=self.table_id, - next_hop_out_label_stack=path.nh_labels, - next_hop_n_out_labels=len( - path.nh_labels), + is_interface_rx=path.is_interface_rx, + is_rpf_id=path.is_rpf_id, + next_hop_out_label_stack=lstack, + next_hop_n_out_labels=len(lstack), next_hop_via_label=path.nh_via_label, next_hop_table_id=path.nh_table_id) + self.stats_index = r.stats_index self._test.registry.register(self, self._test.logger) def remove_vpp_config(self): for path in self.paths: self._test.vapi.mpls_route_add_del(self.local_label, self.eos_bit, - 1, + path.proto, path.nh_addr, path.nh_itf, + is_rpf_id=path.is_rpf_id, table_id=self.table_id, is_add=0) @@ -375,3 +641,11 @@ class VppMplsRoute(VppObject): % (self.table_id, self.local_label, 20+self.eos_bit)) + + def get_stats_to(self): + c = self._test.statistics.get_counter("/net/route/to") + return c[0][self.stats_index] + + def get_stats_via(self): + c = self._test.statistics.get_counter("/net/route/via") + return c[0][self.stats_index]