diff options
-rw-r--r-- | src/vnet/ip/ip.api | 2 | ||||
-rw-r--r-- | src/vnet/ip/ip_api.c | 38 | ||||
-rw-r--r-- | test/test_mpls.py | 56 | ||||
-rw-r--r-- | test/vpp_ip_route.py | 8 |
4 files changed, 95 insertions, 9 deletions
diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index 39d394f709d..c4ef626e2fb 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -384,6 +384,8 @@ autoreply define sw_interface_ip6_enable_disable are used for forwarding. lower value is better. @param next_hop_id - Used when the path resolves via an object that has a unique identifier. + @param next_hop_proto - The protocol of the next-hop (address) + 0=use same AF as the route, 1=IPv4, 2=IPv6 @param dst_address_length - @param dst_address[16] - @param next_hop_address[16] - diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index ce3456d77d9..7a6e6fe8501 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -1025,7 +1025,8 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, { u32 fib_index, next_hop_fib_index; fib_mpls_label_t *label_stack = NULL; - int rv, ii, n_labels;; + dpo_proto_t nh_proto; + int rv, ii, n_labels; rv = add_del_route_check (FIB_PROTOCOL_IP4, mp->table_id, @@ -1044,8 +1045,18 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4)); ip46_address_t nh; - clib_memset (&nh, 0, sizeof (nh)); - memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4)); + + if (0 == mp->next_hop_proto || 1 == mp->next_hop_proto) + { + clib_memset (&nh, 0, sizeof (nh)); + memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4)); + nh_proto = DPO_PROTO_IP4; + } + else + { + memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6)); + nh_proto = DPO_PROTO_IP6; + } n_labels = mp->next_hop_n_out_labels; if (n_labels == 0) @@ -1078,7 +1089,7 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, mp->is_dvr, mp->is_source_lookup, mp->is_udp_encap, - fib_index, &pfx, DPO_PROTO_IP4, + fib_index, &pfx, nh_proto, &nh, ntohl (mp->next_hop_id), ntohl (mp->next_hop_sw_if_index), @@ -1099,7 +1110,8 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, { fib_mpls_label_t *label_stack = NULL; u32 fib_index, next_hop_fib_index; - int rv, ii, n_labels;; + dpo_proto_t nh_proto; + int rv, ii, n_labels; rv = add_del_route_check (FIB_PROTOCOL_IP6, mp->table_id, @@ -1118,8 +1130,18 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6)); ip46_address_t nh; - clib_memset (&nh, 0, sizeof (nh)); - memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6)); + + if (1 == mp->next_hop_proto) + { + clib_memset (&nh, 0, sizeof (nh)); + memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4)); + nh_proto = DPO_PROTO_IP4; + } + else + { + memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6)); + nh_proto = DPO_PROTO_IP6; + } n_labels = mp->next_hop_n_out_labels; if (n_labels == 0) @@ -1152,7 +1174,7 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, mp->is_dvr, mp->is_source_lookup, mp->is_udp_encap, - fib_index, &pfx, DPO_PROTO_IP6, + fib_index, &pfx, nh_proto, &nh, ntohl (mp->next_hop_id), ntohl (mp->next_hop_sw_if_index), next_hop_fib_index, diff --git a/test/test_mpls.py b/test/test_mpls.py index 4a1c663c444..0b8883933a3 100644 --- a/test/test_mpls.py +++ b/test/test_mpls.py @@ -4,7 +4,7 @@ import unittest import socket from framework import VppTestCase, VppTestRunner -from vpp_ip import DpoProto +from vpp_ip import DpoProto, INVALID_INDEX from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \ VppMplsIpBind, VppIpMRoute, VppMRoutePath, \ MRouteItfFlags, MRouteEntryFlags, VppIpTable, VppMplsTable, \ @@ -1387,6 +1387,60 @@ class TestMPLS(VppTestCase): dst_ip="ff01::1") self.send_and_assert_no_replies(self.pg0, tx, "RPF-ID drop 56") + def test_6pe(self): + """ MPLS 6PE """ + + # + # Add a non-recursive route with a single out label + # + route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32, + [VppRoutePath(self.pg0.remote_ip4, + self.pg0.sw_if_index, + labels=[VppMplsLabel(45)])]) + route_10_0_0_1.add_vpp_config() + + # bind a local label to the route + binding = VppMplsIpBind(self, 44, "10.0.0.1", 32) + binding.add_vpp_config() + + # + # a labelled v6 route that resolves through the v4 + # + route_2001_3 = VppIpRoute( + self, "2001::3", 128, + [VppRoutePath("10.0.0.1", + INVALID_INDEX, + labels=[VppMplsLabel(32)])], + is_ip6=1) + + route_2001_3.add_vpp_config() + + tx = self.create_stream_ip6(self.pg0, "2001::3") + rx = self.send_and_expect(self.pg0, tx, self.pg0) + + self.verify_capture_labelled_ip6(self.pg0, rx, tx, + [VppMplsLabel(45), + VppMplsLabel(32)]) + + # + # and a v4 recursive via the v6 + # + route_20_3 = VppIpRoute( + self, "20.0.0.3", 32, + [VppRoutePath("2001::3", + INVALID_INDEX, + proto=DpoProto.DPO_PROTO_IP6, + labels=[VppMplsLabel(99)])]) + route_20_3.add_vpp_config() + + tx = self.create_stream_ip4(self.pg0, "20.0.0.3") + rx = self.send_and_expect(self.pg0, tx, self.pg0) + + self.verify_capture_labelled_ip4(self.pg0, rx, tx, + [VppMplsLabel(45), + VppMplsLabel(32), + VppMplsLabel(99)]) + class TestMPLSDisabled(VppTestCase): """ MPLS disabled """ diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py index 0bd6dd33735..516fcb898bf 100644 --- a/test/vpp_ip_route.py +++ b/test/vpp_ip_route.py @@ -389,6 +389,13 @@ class VppIpRoute(VppObject): else: for path in self.paths: lstack = path.encode_labels() + nh_proto = 0 + + # cross AF next-hop + if self.is_ip6 and path.proto == DpoProto.DPO_PROTO_IP4: + nh_proto = 1 + elif not self.is_ip6 and path.proto == DpoProto.DPO_PROTO_IP6: + nh_proto = 2 r = self._test.vapi.ip_add_del_route( dst_address=self.dest_addr, @@ -400,6 +407,7 @@ class VppIpRoute(VppObject): next_hop_out_label_stack=lstack, next_hop_via_label=path.nh_via_label, next_hop_id=path.next_hop_id, + next_hop_proto=nh_proto, is_resolve_host=path.is_resolve_host, is_resolve_attached=path.is_resolve_attached, is_ipv6=self.is_ip6, is_local=self.is_local, |