summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Scherpelz <jscherpelz@google.com>2017-02-28 11:54:25 +0900
committerJoel Scherpelz <jscherpelz@google.com>2017-03-03 14:44:35 +0900
commitca2d6ec018c15e1dd7219b22f05828a0f987bd34 (patch)
treefe4761347bd5b40da2174adfc757020033a076c2
parentad6a1aa20aea9e0edba7387e74e591d51527b0a3 (diff)
downloadtests-ca2d6ec018c15e1dd7219b22f05828a0f987bd34.tar.gz
Add RIOTest to multinetwork_test.py
This test exercises kernel handling of IPv6 Router Advertisements with Rout Information Options (type = 24). Bug: 33333670 Test: run_net_test.sh all_tests.sh passes Change-Id: Id4e2d114514daa9a70a8f180cc7fba32cf420d1b
-rw-r--r--net/test/iproute.py6
-rw-r--r--net/test/multinetwork_base.py8
-rwxr-xr-xnet/test/multinetwork_test.py109
-rwxr-xr-xnet/test/net_test.py6
-rwxr-xr-xnet/test/run_net_test.sh1
5 files changed, 127 insertions, 3 deletions
diff --git a/net/test/iproute.py b/net/test/iproute.py
index 1d980af..a570d3d 100644
--- a/net/test/iproute.py
+++ b/net/test/iproute.py
@@ -86,6 +86,7 @@ RTA_METRICS = 8
RTA_CACHEINFO = 12
RTA_TABLE = 15
RTA_MARK = 16
+RTA_PREF = 20
RTA_UID = 25
# Route metric attributes.
@@ -493,6 +494,11 @@ class IPRoute(netlink.NetlinkSocket):
routes = self._GetMsgList(RTMsg, data, False)
return routes
+ def DumpRoutes(self, version, ifindex):
+ ndmsg = NdMsg((self._AddressFamily(version), 0, 0, 0, 0))
+ return [(m, r) for (m, r) in self._Dump(RTM_GETROUTE, ndmsg, NdMsg, "")
+ if r['RTA_TABLE'] == ifindex]
+
def _Neighbour(self, version, is_add, addr, lladdr, dev, state, flags=0):
"""Adds or deletes a neighbour cache entry."""
family = self._AddressFamily(version)
diff --git a/net/test/multinetwork_base.py b/net/test/multinetwork_base.py
index ef426db..a4ba472 100644
--- a/net/test/multinetwork_base.py
+++ b/net/test/multinetwork_base.py
@@ -113,6 +113,8 @@ class MultiNetworkBaseTest(net_test.NetworkTest):
IPV4_PING = net_test.IPV4_PING
IPV6_PING = net_test.IPV6_PING
+ RA_VALIDITY = 300 # seconds
+
@classmethod
def UidRangeForNetid(cls, netid):
return (
@@ -210,8 +212,8 @@ class MultiNetworkBaseTest(net_test.NetworkTest):
return f
@classmethod
- def SendRA(cls, netid, retranstimer=None, reachabletime=0):
- validity = 300 # seconds
+ def SendRA(cls, netid, retranstimer=None, reachabletime=0, options=()):
+ validity = cls.RA_VALIDITY # seconds
macaddr = cls.RouterMacAddress(netid)
lladdr = cls._RouterAddress(netid, 6)
@@ -236,6 +238,8 @@ class MultiNetworkBaseTest(net_test.NetworkTest):
L=1, A=1,
validlifetime=validity,
preferredlifetime=validity))
+ for option in options:
+ ra /= option
posix.write(cls.tuns[netid].fileno(), str(ra))
@classmethod
diff --git a/net/test/multinetwork_test.py b/net/test/multinetwork_test.py
index 1e88416..f634d68 100755
--- a/net/test/multinetwork_test.py
+++ b/net/test/multinetwork_test.py
@@ -574,6 +574,115 @@ class TCPAcceptTest(InboundMarkingTest):
def testIPv6ExplicitMark(self):
self.CheckTCP(6, [self.MODE_EXPLICIT_MARK])
+class RIOTest(multinetwork_base.MultiNetworkBaseTest):
+
+ def setUp(self):
+ self.NETID = random.choice(self.NETIDS)
+ self.IFACE = self.GetInterfaceName(self.NETID)
+
+ def GetRoutingTable(self):
+ return self._TableForNetid(self.NETID)
+
+ def SetAcceptRaRtInfoMaxPlen(self, plen):
+ self.SetSysctl(
+ "/proc/sys/net/ipv6/conf/%s/accept_ra_rt_info_max_plen"
+ % self.IFACE, str(plen))
+
+ def GetAcceptRaRtInfoMaxPlen(self):
+ return int(self.GetSysctl(
+ "/proc/sys/net/ipv6/conf/%s/accept_ra_rt_info_max_plen" % self.IFACE))
+
+ def SendRIO(self, rtlifetime, plen, prefix, prf):
+ options = scapy.ICMPv6NDOptRouteInfo(rtlifetime=rtlifetime, plen=plen,
+ prefix=prefix, prf=prf)
+ self.SendRA(self.NETID, options=(options,))
+
+ def FindRoutesWithDestination(self, destination):
+ canonical = net_test.CanonicalizeIPv6Address(destination)
+ return [r for _, r in self.iproute.DumpRoutes(6, self.GetRoutingTable())
+ if ('RTA_DST' in r and r['RTA_DST'] == canonical)]
+
+ def FindRoutesWithGateway(self):
+ return [r for _, r in self.iproute.DumpRoutes(6, self.GetRoutingTable())
+ if 'RTA_GATEWAY' in r]
+
+ def CountRoutes(self):
+ return len(self.iproute.DumpRoutes(6, self.GetRoutingTable()))
+
+ def GetRouteExpiration(self, route):
+ return float(route['RTA_CACHEINFO'].expires) / 100.0
+
+ def testSetAcceptRaRtInfoMaxPlen(self):
+ for plen in xrange(-1, 130):
+ self.SetAcceptRaRtInfoMaxPlen(plen)
+ self.assertEquals(plen, self.GetAcceptRaRtInfoMaxPlen())
+
+ @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE,
+ "no support for per-table autoconf")
+ def testZeroRtLifetime(self):
+ PREFIX = "2001:db8:8901:2300::"
+ RTLIFETIME = 7372
+ PLEN = 56
+ PRF = 0
+ self.SetAcceptRaRtInfoMaxPlen(PLEN)
+ self.SendRIO(RTLIFETIME, PLEN, PREFIX, PRF)
+ self.assertTrue(self.FindRoutesWithDestination(PREFIX))
+ # RIO with rtlifetime = 0 should remove from routing table
+ self.SendRIO(0, PLEN, PREFIX, PRF)
+ self.assertFalse(self.FindRoutesWithDestination(PREFIX))
+
+ @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE,
+ "no support for per-table autoconf")
+ def testMaxPrefixLenRejection(self):
+ PREFIX = "2001:db8:8901:2345::"
+ RTLIFETIME = 7372
+ PRF = 0
+ for plen in xrange(0, 64):
+ self.SetAcceptRaRtInfoMaxPlen(plen)
+ # RIO with plen > max_plen should be ignored
+ self.SendRIO(RTLIFETIME, plen + 1, PREFIX, PRF)
+ routes = self.FindRoutesWithDestination(PREFIX)
+ self.assertFalse(routes)
+
+ @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE,
+ "no support for per-table autoconf")
+ def testZeroLengthPrefix(self):
+ PREFIX = "::"
+ RTLIFETIME = self.RA_VALIDITY * 2
+ PLEN = 0
+ PRF = 0
+ # Max plen = 0 still allows default RIOs!
+ self.SetAcceptRaRtInfoMaxPlen(PLEN)
+ default = self.FindRoutesWithGateway()
+ self.assertTrue(default)
+ self.assertLess(self.GetRouteExpiration(default[0]), self.RA_VALIDITY)
+ # RIO with prefix length = 0, should overwrite default route lifetime
+ # note that the RIO lifetime overwrites the RA lifetime.
+ self.SendRIO(RTLIFETIME, PLEN, PREFIX, PRF)
+ default = self.FindRoutesWithGateway()
+ self.assertTrue(default)
+ self.assertGreater(self.GetRouteExpiration(default[0]), self.RA_VALIDITY)
+
+ @unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE,
+ "no support for per-table autoconf")
+ def testManyRIOs(self):
+ RTLIFETIME = 6809
+ PLEN = 56
+ PRF = 0
+ COUNT = 1000
+ baseline = self.CountRoutes()
+ self.SetAcceptRaRtInfoMaxPlen(56)
+ # Send many RIOs compared to the expected number on a healthy system.
+ for i in xrange(0, COUNT):
+ prefix = "2001:db8:%x:1100::" % i
+ self.SendRIO(RTLIFETIME, PLEN, prefix, PRF)
+ self.assertEquals(COUNT + baseline, self.CountRoutes())
+ # Use lifetime = 0 to cleanup all previously announced RIOs.
+ for i in xrange(0, COUNT):
+ prefix = "2001:db8:%x:1100::" % i
+ self.SendRIO(0, PLEN, prefix, PRF)
+ # Expect that we can return to baseline config without lingering routes.
+ self.assertEquals(baseline, self.CountRoutes())
class RATest(multinetwork_base.MultiNetworkBaseTest):
diff --git a/net/test/net_test.py b/net/test/net_test.py
index 0048ae6..b469009 100755
--- a/net/test/net_test.py
+++ b/net/test/net_test.py
@@ -226,13 +226,17 @@ def SetInterfaceDown(ifname):
return SetInterfaceState(ifname, False)
+def CanonicalizeIPv6Address(addr):
+ return inet_ntop(AF_INET6, inet_pton(AF_INET6, addr))
+
+
def FormatProcAddress(unformatted):
groups = []
for i in xrange(0, len(unformatted), 4):
groups.append(unformatted[i:i+4])
formatted = ":".join(groups)
# Compress the address.
- address = inet_ntop(AF_INET6, inet_pton(AF_INET6, formatted))
+ address = CanonicalizeIPv6Address(formatted)
return address
diff --git a/net/test/run_net_test.sh b/net/test/run_net_test.sh
index 6179b28..e07d10b 100755
--- a/net/test/run_net_test.sh
+++ b/net/test/run_net_test.sh
@@ -9,6 +9,7 @@ OPTIONS="$OPTIONS NETFILTER_XT_MARK NETFILTER_XT_TARGET_MARK"
OPTIONS="$OPTIONS IP_NF_IPTABLES IP_NF_MANGLE IP_NF_FILTER"
OPTIONS="$OPTIONS IP6_NF_IPTABLES IP6_NF_MANGLE IP6_NF_FILTER INET6_IPCOMP"
OPTIONS="$OPTIONS IPV6_PRIVACY IPV6_OPTIMISTIC_DAD"
+OPTIONS="$OPTIONS CONFIG_IPV6_ROUTE_INFO CONFIG_IPV6_ROUTER_PREF"
OPTIONS="$OPTIONS CONFIG_NETFILTER_XT_TARGET_NFLOG"
OPTIONS="$OPTIONS CONFIG_NETFILTER_XT_MATCH_QUOTA"
OPTIONS="$OPTIONS CONFIG_NETFILTER_XT_MATCH_QUOTA2"