summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/ip/ip.api2
-rw-r--r--src/vnet/ip/ip_api.c38
-rw-r--r--test/test_mpls.py56
-rw-r--r--test/vpp_ip_route.py8
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,