From 7eac916e1b00d6a3393a09925e1634d71bf30568 Mon Sep 17 00:00:00 2001 From: Ciara Loftus Date: Fri, 30 Sep 2016 15:47:03 +0100 Subject: GRE over IPv6 Refactors the GRE node to work with both IPv4 and IPv6 transports. Note that this changes the binary configuration API to support both address families; each address uses the same memory for either address type and a flag to indicate which is in use. The CLI and VAT syntax remains unchanged; the code detects whether an IPv4 or an IPv6 address was given. Configuration examples: IPv4 CLI: create gre tunnel src 192.168.1.1 dst 192.168.1.2 IPv6 CLI: create gre tunnel src 2620:124:9000::1 dst 2620:124:9000::2 IPv4 VAT: gre_add_del_tunnel src 192.168.1.1 dst 192.168.1.2 IPv6 VAT: gre_add_del_tunnel src 2620:124:9000::1 dst 2620:124:9000::2 Change-Id: Ica8ee775dc101047fb8cd41617ddc8fafc2741b0 Signed-off-by: Ciara Loftus --- test/test_gre.py | 149 +++++++++++++++++++++++++++++++++++++++++++--- test/vpp_gre_interface.py | 35 +++++++++++ 2 files changed, 177 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/test/test_gre.py b/test/test_gre.py index f2a5e0b0..18b67dbd 100644 --- a/test/test_gre.py +++ b/test/test_gre.py @@ -5,7 +5,7 @@ from logging import * from framework import VppTestCase, VppTestRunner from vpp_sub_interface import VppDot1QSubint -from vpp_gre_interface import VppGreInterface +from vpp_gre_interface import VppGreInterface, VppGre6Interface from vpp_ip_route import VppIpRoute, VppRoutePath from vpp_papi_provider import L2_VTR_OP @@ -28,14 +28,19 @@ class TestGRE(VppTestCase): def setUp(self): super(TestGRE, self).setUp() - # create 2 pg interfaces - set one in a non-default table. - self.create_pg_interfaces(range(2)) - + # create 3 pg interfaces - set one in a non-default table. + self.create_pg_interfaces(range(3)) self.pg1.set_table_ip4(1) + for i in self.pg_interfaces: i.admin_up() - i.config_ip4() - i.resolve_arp() + + self.pg0.config_ip4() + self.pg0.resolve_arp() + self.pg1.config_ip4() + self.pg1.resolve_arp() + self.pg2.config_ip6() + self.pg2.resolve_ndp() def tearDown(self): super(TestGRE, self).tearDown() @@ -57,6 +62,19 @@ class TestGRE(VppTestCase): pkts.append(p) return pkts + def create_stream_ip6(self, src_if, src_ip, dst_ip): + pkts = [] + for i in range(0, 257): + info = self.create_packet_info(src_if, src_if) + payload = self.info_to_payload(info) + p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / + IPv6(src=src_ip, dst=dst_ip) / + UDP(sport=1234, dport=1234) / + Raw(payload)) + info.data = p.copy() + pkts.append(p) + return pkts + def create_tunnel_stream_4o4(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip): @@ -91,6 +109,23 @@ class TestGRE(VppTestCase): pkts.append(p) return pkts + def create_tunnel_stream_6o6(self, src_if, + tunnel_src, tunnel_dst, + src_ip, dst_ip): + pkts = [] + for i in range(0, 257): + info = self.create_packet_info(src_if, src_if) + payload = self.info_to_payload(info) + p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / + IPv6(src=tunnel_src, dst=tunnel_dst) / + GRE() / + IPv6(src=src_ip, dst=dst_ip) / + UDP(sport=1234, dport=1234) / + Raw(payload)) + info.data = p.copy() + pkts.append(p) + return pkts + def create_tunnel_stream_l2o4(self, src_if, tunnel_src, tunnel_dst): pkts = [] @@ -157,6 +192,33 @@ class TestGRE(VppTestCase): self.logger.error(ppp("Tx:", tx)) raise + def verify_tunneled_6o6(self, src_if, capture, sent, + tunnel_src, tunnel_dst): + + self.assertEqual(len(capture), len(sent)) + + for i in range(len(capture)): + try: + tx = sent[i] + rx = capture[i] + + tx_ip = tx[IPv6] + rx_ip = rx[IPv6] + + self.assertEqual(rx_ip.src, tunnel_src) + self.assertEqual(rx_ip.dst, tunnel_dst) + + rx_gre = GRE(str(rx_ip[IPv6].payload)) + rx_ip = rx_gre[IPv6] + + self.assertEqual(rx_ip.src, tx_ip.src) + self.assertEqual(rx_ip.dst, tx_ip.dst) + + except: + self.logger.error(ppp("Rx:", rx)) + self.logger.error(ppp("Tx:", tx)) + raise + def verify_tunneled_l2o4(self, src_if, capture, sent, tunnel_src, tunnel_dst): self.assertEqual(len(capture), len(sent)) @@ -275,7 +337,7 @@ class TestGRE(VppTestCase): raise def test_gre(self): - """ GRE tunnel Tests """ + """ GRE IPv4 tunnel Tests """ # # Create an L3 GRE tunnel. @@ -438,6 +500,79 @@ class TestGRE(VppTestCase): self.pg0.unconfig_ip6() + def test_gre6(self): + """ GRE IPv6 tunnel Tests """ + + # + # Create an L3 GRE tunnel. + # - set it admin up + # - assign an IP Address + # - Add a route via the tunnel + # + gre_if = VppGre6Interface(self, + self.pg2.local_ip6, + "1002::1") + gre_if.add_vpp_config() + gre_if.admin_up() + gre_if.config_ip6() + + route_via_tun = VppIpRoute(self, "4004::1", 128, + [VppRoutePath("0::0", + gre_if.sw_if_index, + is_ip6=1)], + is_ip6=1) + + route_via_tun.add_vpp_config() + + # + # Send a packet stream that is routed into the tunnel + # - they are all dropped since the tunnel's desintation IP + # is unresolved - or resolves via the default route - which + # which is a drop. + # + tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1") + self.pg2.add_stream(tx) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + self.pg2.assert_nothing_captured( + remark="GRE packets forwarded without DIP resolved") + + # + # Add a route that resolves the tunnel's destination + # + route_tun_dst = VppIpRoute(self, "1002::1", 128, + [VppRoutePath(self.pg2.remote_ip6, + self.pg2.sw_if_index, + is_ip6=1)], + is_ip6=1) + route_tun_dst.add_vpp_config() + + # + # Send a packet stream that is routed into the tunnel + # - packets are GRE encapped + # + self.vapi.cli("clear trace") + tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1") + self.pg2.add_stream(tx) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(len(tx)) + self.verify_tunneled_6o6(self.pg2, rx, tx, + self.pg2.local_ip6, "1002::1") + + # + # test case cleanup + # + route_tun_dst.remove_vpp_config() + route_via_tun.remove_vpp_config() + gre_if.remove_vpp_config() + + self.pg2.unconfig_ip6() + def test_gre_vrf(self): """ GRE tunnel VRF Tests """ diff --git a/test/vpp_gre_interface.py b/test/vpp_gre_interface.py index 58a68290..1c71875f 100644 --- a/test/vpp_gre_interface.py +++ b/test/vpp_gre_interface.py @@ -34,3 +34,38 @@ class VppGreInterface(VppInterface): r = self.test.vapi.gre_tunnel_add_del(s, d, outer_fib_id=self.t_outer_fib, is_add=0) + + +class VppGre6Interface(VppInterface): + """ + VPP GRE IPv6 interface + """ + + def __init__(self, test, src_ip, dst_ip, outer_fib_id=0, is_teb=0): + """ Create VPP loopback interface """ + self._sw_if_index = 0 + super(VppGre6Interface, self).__init__(test) + self._test = test + self.t_src = src_ip + self.t_dst = dst_ip + self.t_outer_fib = outer_fib_id + self.t_is_teb = is_teb + + def add_vpp_config(self): + s = socket.inet_pton(socket.AF_INET6, self.t_src) + d = socket.inet_pton(socket.AF_INET6, self.t_dst) + r = self.test.vapi.gre_tunnel_add_del(s, d, + outer_fib_id=self.t_outer_fib, + is_teb=self.t_is_teb, + is_ip6=1) + self._sw_if_index = r.sw_if_index + self.generate_remote_hosts() + + def remove_vpp_config(self): + s = socket.inet_pton(socket.AF_INET6, self.t_src) + d = socket.inet_pton(socket.AF_INET6, self.t_dst) + self.unconfig() + r = self.test.vapi.gre_tunnel_add_del(s, d, + outer_fib_id=self.t_outer_fib, + is_add=0, + is_ip6=1) -- cgit 1.2.3-korg