from parameterized import parameterized
import scapy.compat
import scapy.layers.inet6 as inet6
-from scapy.layers.inet import UDP
+from scapy.layers.inet import UDP, IP
from scapy.contrib.mpls import MPLS
from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6ND_RS, \
ICMPv6ND_RA, ICMPv6NDOptMTU, ICMPv6NDOptSrcLLAddr, ICMPv6NDOptPrefixInfo, \
ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, ICMPv6DestUnreach, icmp6types, \
ICMPv6TimeExceeded, ICMPv6EchoRequest, ICMPv6EchoReply, \
IPv6ExtHdrHopByHop, ICMPv6MLReport2, ICMPv6MLDMultAddrRec
-from scapy.layers.l2 import Ether, Dot1Q
+from scapy.layers.l2 import Ether, Dot1Q, GRE
from scapy.packet import Raw
from scapy.utils6 import in6_getnsma, in6_getnsmac, in6_ptop, in6_islladdr, \
in6_mactoifaceid
from vpp_sub_interface import VppSubInterface, VppDot1QSubint
from vpp_policer import VppPolicer, PolicerAction
from ipaddress import IPv6Network, IPv6Address
+from vpp_gre_interface import VppGreInterface
+from vpp_teib import VppTeib
AF_INET6 = socket.AF_INET6
"RS sourced from link-local",
dst_ip=ll)
+ #
+ # Source an RS from a link local address
+ # Ensure suppress also applies to solicited RS
+ #
+ self.pg0.ip6_ra_config(send_unicast=1, suppress=1)
+ ll = mk_ll_addr(self.pg0.remote_mac)
+ p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+ IPv6(dst=self.pg0.local_ip6, src=ll) /
+ ICMPv6ND_RS())
+ pkts = [p]
+ self.send_and_assert_no_replies(self.pg0, pkts,
+ "Suppressed RS from link-local")
+
#
# Send the RS multicast
#
+ self.pg0.ip6_ra_config(no=1, suppress=1) # Reset suppress flag to zero
self.pg0.ip6_ra_config(send_unicast=1)
dmac = in6_getnsmac(inet_pton(AF_INET6, "ff02::2"))
ll = mk_ll_addr(self.pg0.remote_mac)
# If we happen to pick up the periodic RA at this point then so be it,
# it's not an error.
#
- self.pg0.ip6_ra_config(send_unicast=1, suppress=1)
+ self.pg0.ip6_ra_config(send_unicast=1, suppress=0)
p = (Ether(dst=dmac, src=self.pg0.remote_mac) /
IPv6(dst="ff02::2", src="::") /
ICMPv6ND_RS())
ll2 = "fe80:2::2"
ll3 = "fe80:3::3"
+ VppNeighbor(self,
+ self.pg0.sw_if_index,
+ self.pg0.remote_mac,
+ ll2).add_vpp_config()
+
VppIpInterfaceAddress(self, self.pg0, ll1, 128).add_vpp_config()
#
VppIp6LinkLocalAddress(self, self.pg1, ll3).add_vpp_config()
self.send_and_expect(self.pg1, [p_echo_request_3], self.pg1)
+ def test_ip6_ll_p2p(self):
+ """ IPv6 Link Local P2P (GRE)"""
+
+ self.pg0.config_ip4()
+ self.pg0.resolve_arp()
+ gre_if = VppGreInterface(self,
+ self.pg0.local_ip4,
+ self.pg0.remote_ip4).add_vpp_config()
+ gre_if.admin_up()
+
+ ll1 = "fe80:1::1"
+ ll2 = "fe80:2::2"
+
+ VppIpInterfaceAddress(self, gre_if, ll1, 128).add_vpp_config()
+
+ self.logger.info(self.vapi.cli("sh ip6-ll gre0 fe80:2::2"))
+
+ p_echo_request_1 = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4,
+ dst=self.pg0.local_ip4) /
+ GRE() /
+ IPv6(src=ll2, dst=ll1) /
+ ICMPv6EchoRequest())
+ self.send_and_expect(self.pg0, [p_echo_request_1], self.pg0)
+
+ self.pg0.unconfig_ip4()
+ gre_if.remove_vpp_config()
+
+ def test_ip6_ll_p2mp(self):
+ """ IPv6 Link Local P2MP (GRE)"""
+
+ self.pg0.config_ip4()
+ self.pg0.resolve_arp()
+
+ gre_if = VppGreInterface(
+ self,
+ self.pg0.local_ip4,
+ "0.0.0.0",
+ mode=(VppEnum.vl_api_tunnel_mode_t.
+ TUNNEL_API_MODE_MP)).add_vpp_config()
+ gre_if.admin_up()
+
+ ll1 = "fe80:1::1"
+ ll2 = "fe80:2::2"
+
+ VppIpInterfaceAddress(self, gre_if, ll1, 128).add_vpp_config()
+
+ p_echo_request_1 = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4,
+ dst=self.pg0.local_ip4) /
+ GRE() /
+ IPv6(src=ll2, dst=ll1) /
+ ICMPv6EchoRequest())
+
+ # no route back at this point
+ self.send_and_assert_no_replies(self.pg0, [p_echo_request_1])
+
+ # add teib entry for the peer
+ teib = VppTeib(self, gre_if, ll2, self.pg0.remote_ip4)
+ teib.add_vpp_config()
+
+ self.logger.info(self.vapi.cli("sh ip6-ll gre0 %s" % ll2))
+ self.send_and_expect(self.pg0, [p_echo_request_1], self.pg0)
+
+ # teardown
+ self.pg0.unconfig_ip4()
+
class TestIPv6PathMTU(VppTestCase):
""" IPv6 Path MTU """
self.assertFalse(find_route(self, "2001::1", 128))
+class TestIPxAF(VppTestCase):
+ """ IP cross AF """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestIPxAF, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestIPxAF, cls).tearDownClass()
+
+ def setUp(self):
+ super(TestIPxAF, self).setUp()
+
+ self.create_pg_interfaces(range(2))
+
+ for i in self.pg_interfaces:
+ i.admin_up()
+ i.config_ip6()
+ i.config_ip4()
+ i.resolve_arp()
+ i.resolve_ndp()
+
+ def tearDown(self):
+ super(TestIPxAF, self).tearDown()
+ for i in self.pg_interfaces:
+ i.admin_down()
+ i.unconfig_ip4()
+ i.unconfig_ip6()
+
+ def test_x_af(self):
+ """ Cross AF routing """
+
+ N_PKTS = 63
+ # a v4 route via a v6 attached next-hop
+ VppIpRoute(
+ self, "1.1.1.1", 32,
+ [VppRoutePath(self.pg1.remote_ip6,
+ self.pg1.sw_if_index)]).add_vpp_config()
+
+ p = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst="1.1.1.1") /
+ UDP(sport=1234, dport=1234) /
+ Raw(b'\xa5' * 100))
+ rxs = self.send_and_expect(self.pg0, p * N_PKTS, self.pg1)
+
+ for rx in rxs:
+ self.assertEqual(rx[IP].dst, "1.1.1.1")
+
+ # a v6 route via a v4 attached next-hop
+ VppIpRoute(
+ self, "2001::1", 128,
+ [VppRoutePath(self.pg1.remote_ip4,
+ self.pg1.sw_if_index)]).add_vpp_config()
+
+ p = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IPv6(src=self.pg0.remote_ip6, dst="2001::1") /
+ UDP(sport=1234, dport=1234) /
+ Raw(b'\xa5' * 100))
+ rxs = self.send_and_expect(self.pg0, p * N_PKTS, self.pg1)
+
+ for rx in rxs:
+ self.assertEqual(rx[IPv6].dst, "2001::1")
+
+ # a recursive v4 route via a v6 next-hop (from above)
+ VppIpRoute(
+ self, "2.2.2.2", 32,
+ [VppRoutePath("2001::1",
+ 0xffffffff)]).add_vpp_config()
+
+ p = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst="2.2.2.2") /
+ UDP(sport=1234, dport=1234) /
+ Raw(b'\xa5' * 100))
+ rxs = self.send_and_expect(self.pg0, p * N_PKTS, self.pg1)
+
+ # a recursive v4 route via a v6 next-hop
+ VppIpRoute(
+ self, "2.2.2.3", 32,
+ [VppRoutePath(self.pg1.remote_ip6,
+ 0xffffffff)]).add_vpp_config()
+
+ p = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst="2.2.2.3") /
+ UDP(sport=1234, dport=1234) /
+ Raw(b'\xa5' * 100))
+ rxs = self.send_and_expect(self.pg0, p * N_PKTS, self.pg1)
+
+ # a recursive v6 route via a v4 next-hop
+ VppIpRoute(
+ self, "3001::1", 128,
+ [VppRoutePath(self.pg1.remote_ip4,
+ 0xffffffff)]).add_vpp_config()
+
+ p = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IPv6(src=self.pg0.remote_ip6, dst="3001::1") /
+ UDP(sport=1234, dport=1234) /
+ Raw(b'\xa5' * 100))
+ rxs = self.send_and_expect(self.pg0, p * N_PKTS, self.pg1)
+
+ for rx in rxs:
+ self.assertEqual(rx[IPv6].dst, "3001::1")
+
+ VppIpRoute(
+ self, "3001::2", 128,
+ [VppRoutePath("1.1.1.1",
+ 0xffffffff)]).add_vpp_config()
+
+ p = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IPv6(src=self.pg0.remote_ip6, dst="3001::2") /
+ UDP(sport=1234, dport=1234) /
+ Raw(b'\xa5' * 100))
+ rxs = self.send_and_expect(self.pg0, p * N_PKTS, self.pg1)
+
+ for rx in rxs:
+ self.assertEqual(rx[IPv6].dst, "3001::2")
+
+
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)