def send_and_expect_ra(self, intf, pkts, remark, dst_ip=None,
filter_out_fn=is_ipv6_misc):
intf.add_stream(pkts)
- self.pg0.add_stream(pkts)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
rx = intf.get_capture(1, filter_out_fn=filter_out_fn)
rx = rx[0]
self.validate_ra(intf, rx, dst_ip)
+ def send_and_expect_na(self, intf, pkts, remark, dst_ip=None,
+ tgt_ip=None,
+ filter_out_fn=is_ipv6_misc):
+ intf.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ rx = intf.get_capture(1, filter_out_fn=filter_out_fn)
+
+ self.assertEqual(len(rx), 1)
+ rx = rx[0]
+ self.validate_na(intf, rx, dst_ip, tgt_ip)
+
def send_and_assert_no_replies(self, intf, pkts, remark):
intf.add_stream(pkts)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- intf.assert_nothing_captured(remark=remark)
+ for i in self.pg_interfaces:
+ i.get_capture(0)
+ i.assert_nothing_captured(remark=remark)
class TestIPv6(TestIPv6ND):
128,
inet=AF_INET6))
+ #
+ # send an NS from a link local address to the interface's global
+ # address
+ #
+ p = (Ether(dst=in6_getnsmac(nsma), src=self.pg0.remote_mac) /
+ IPv6(dst=d, src=self.pg0._remote_hosts[2].ip6_ll) /
+ ICMPv6ND_NS(tgt=self.pg0.local_ip6) /
+ ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
+
+ self.send_and_expect_na(self.pg0, p,
+ "NS from link-local",
+ dst_ip=self.pg0._remote_hosts[2].ip6_ll,
+ tgt_ip=self.pg0.local_ip6)
+
+ #
+ # we should have learned an ND entry for the peer's link-local
+ # but not inserted a route to it in the FIB
+ #
+ self.assertTrue(find_nbr(self,
+ self.pg0.sw_if_index,
+ self.pg0._remote_hosts[2].ip6_ll,
+ inet=AF_INET6))
+ self.assertFalse(find_route(self,
+ self.pg0._remote_hosts[2].ip6_ll,
+ 128,
+ inet=AF_INET6))
+
+ #
+ # An NS to the router's own Link-local
+ #
+ p = (Ether(dst=in6_getnsmac(nsma), src=self.pg0.remote_mac) /
+ IPv6(dst=d, src=self.pg0._remote_hosts[3].ip6_ll) /
+ ICMPv6ND_NS(tgt=self.pg0.local_ip6_ll) /
+ ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
+
+ self.send_and_expect_na(self.pg0, p,
+ "NS to/from link-local",
+ dst_ip=self.pg0._remote_hosts[3].ip6_ll,
+ tgt_ip=self.pg0.local_ip6_ll)
+
+ #
+ # we should have learned an ND entry for the peer's link-local
+ # but not inserted a route to it in the FIB
+ #
+ self.assertTrue(find_nbr(self,
+ self.pg0.sw_if_index,
+ self.pg0._remote_hosts[3].ip6_ll,
+ inet=AF_INET6))
+ self.assertFalse(find_route(self,
+ self.pg0._remote_hosts[3].ip6_ll,
+ 128,
+ inet=AF_INET6))
+
def validate_ra(self, intf, rx, dst_ip=None, mtu=9000, pi_opt=None):
if not dst_ip:
dst_ip = intf.remote_ip6
#
# try that NS again. this time we expect an NA back
#
- self.pg1.add_stream(ns_pg1)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- rx = self.pg1.get_capture(1)
-
- self.validate_na(self.pg1, rx[0],
- dst_ip=self.pg0._remote_hosts[2].ip6,
- tgt_ip=self.pg0.local_ip6)
+ self.send_and_expect_na(self.pg1, ns_pg1,
+ "NS to proxy entry",
+ dst_ip=self.pg0._remote_hosts[2].ip6,
+ tgt_ip=self.pg0.local_ip6)
#
# ... and that we have an entry in the ND cache
ICMPv6ND_NS(tgt=self.pg0._remote_hosts[2].ip6) /
ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
- self.pg0.add_stream(ns_pg0)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- rx = self.pg0.get_capture(1)
-
- self.validate_na(self.pg0, rx[0],
- tgt_ip=self.pg0._remote_hosts[2].ip6,
- dst_ip=self.pg0.remote_ip6)
+ self.send_and_expect_na(self.pg0, ns_pg0,
+ "NS to proxy entry on main",
+ tgt_ip=self.pg0._remote_hosts[2].ip6,
+ dst_ip=self.pg0.remote_ip6)
#
# Setup and resolve proxy for another host on another interface
inet_pton(AF_INET6, self.pg0._remote_hosts[3].ip6),
self.pg2.sw_if_index)
- self.pg2.add_stream(ns_pg2)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- rx = self.pg2.get_capture(1)
-
- self.validate_na(self.pg2, rx[0],
- dst_ip=self.pg0._remote_hosts[3].ip6,
- tgt_ip=self.pg0.local_ip6)
+ self.send_and_expect_na(self.pg2, ns_pg2,
+ "NS to proxy entry other interface",
+ dst_ip=self.pg0._remote_hosts[3].ip6,
+ tgt_ip=self.pg0.local_ip6)
self.assertTrue(find_nbr(self,
self.pg2.sw_if_index,
import sys
from abc import abstractmethod, ABCMeta
from cStringIO import StringIO
+from scapy.layers.inet6 import in6_mactoifaceid
def ppp(headline, packet):
return mac.replace(':', '').decode('hex')
+def mk_ll_addr(mac):
+ euid = in6_mactoifaceid(mac)
+ addr = "fe80::" + euid
+ return addr
+
+
class NumericConstant(object):
__metaclass__ = ABCMeta
""" IPv6 address of remote host - raw, suitable as API parameter."""
return socket.inet_pton(socket.AF_INET6, self._ip6)
- def __init__(self, mac=None, ip4=None, ip6=None):
+ @property
+ def ip6_ll(self):
+ """ IPv6 link-local address - string """
+ return self._ip6_ll
+
+ @property
+ def ip6n_ll(self):
+ """ IPv6 link-local address of remote host -
+ raw, suitable as API parameter."""
+ return socket.inet_pton(socket.AF_INET6, self._ip6_ll)
+
+ def __init__(self, mac=None, ip4=None, ip6=None, ip6_ll=None):
self._mac = mac
self._ip4 = ip4
self._ip6 = ip6
+ self._ip6_ll = ip6_ll
class ForeignAddressFactory(object):
from abc import abstractmethod, ABCMeta
import socket
-from util import Host
+from util import Host, mk_ll_addr
from vpp_neighbor import VppNeighbor
"""Local IPv6 address - raw, suitable as API parameter."""
return socket.inet_pton(socket.AF_INET6, self.local_ip6)
+ @property
+ def local_ip6_ll(self):
+ """Local IPv6 linnk-local address on VPP interface (string)."""
+ return self._local_ip6_ll
+
+ @property
+ def local_ip6n_ll(self):
+ """Local IPv6 link-local address - raw, suitable as API parameter."""
+ return self.local_ip6n_ll
+
@property
def remote_ip6(self):
"""IPv6 address of remote peer "connected" to this interface."""
mac = "02:%02x:00:00:ff:%02x" % (self.sw_if_index, i)
ip4 = "172.16.%u.%u" % (self.sw_if_index, i)
ip6 = "fd01:%x::%x" % (self.sw_if_index, i)
- host = Host(mac, ip4, ip6)
+ ip6_ll = mk_ll_addr(mac)
+ host = Host(mac, ip4, ip6, ip6_ll)
self._remote_hosts.append(host)
self._hosts_by_mac[mac] = host
self._hosts_by_ip4[ip4] = host
"Could not find interface with sw_if_index %d "
"in interface dump %s" %
(self.sw_if_index, repr(r)))
+ self._local_ip6_ll = mk_ll_addr(self.local_mac)
+ self._local_ip6n_ll = socket.inet_pton(socket.AF_INET6,
+ self.local_ip6_ll)
def config_ip4(self):
"""Configure IPv4 address on the VPP interface."""