Enable full RIOTest.testZeroLengthPrefix test on all kernel versions
Also add new tests to guarantee that RIOs are being accepted as well as
the rejection power of min_plen.
Bug: 33333670
Test: net_test passes on android 3.10, 3.18, 4.1, 4.4, 4.9 common and
device variants.
Change-Id: Ib7c0adff7f081e36d279ff88c5133adb6740a81b
diff --git a/net/test/multinetwork_test.py b/net/test/multinetwork_test.py
index 0ade759..3deea46 100755
--- a/net/test/multinetwork_test.py
+++ b/net/test/multinetwork_test.py
@@ -43,9 +43,6 @@
# The IP[V6]UNICAST_IF socket option was added between 3.1 and 3.4.
HAVE_UNICAST_IF = net_test.LINUX_VERSION >= (3, 4, 0)
-MAX_PLEN_SYSCTL = "/proc/sys/net/ipv6/conf/default/accept_ra_rt_info_max_plen"
-HAVE_MAX_PLEN = os.path.isfile(MAX_PLEN_SYSCTL)
-
class ConfigurationError(AssertionError):
pass
@@ -576,19 +573,57 @@
def testIPv6ExplicitMark(self):
self.CheckTCP(6, [self.MODE_EXPLICIT_MARK])
+@unittest.skipUnless(multinetwork_base.HAVE_AUTOCONF_TABLE,
+ "need support for per-table autoconf")
class RIOTest(multinetwork_base.MultiNetworkBaseTest):
+ """Test for IPv6 RFC 4191 route information option
+
+ Relevant kernel commits:
+ upstream:
+ f104a567e673 ipv6: use rt6_get_dflt_router to get default router in rt6_route_rcv
+ bbea124bc99d net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs.
+
+ android-4.9:
+ d860b2e8a7f1 FROMLIST: net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs
+
+ android-4.4:
+ e953f89b8563 net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs.
+
+ android-4.1:
+ 84f2f47716cd net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs.
+
+ android-3.18:
+ 65f8936934fa net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs.
+
+ android-3.10:
+ 161e88ebebc7 net: ipv6: Add sysctl for minimum prefix len acceptable in RIOs.
+
+ """
def setUp(self):
+ super(RIOTest, self).setUp()
self.NETID = random.choice(self.NETIDS)
self.IFACE = self.GetInterfaceName(self.NETID)
+ # return min/max plen to default values before each test case
+ self.SetAcceptRaRtInfoMinPlen(0)
+ self.SetAcceptRaRtInfoMaxPlen(0)
def GetRoutingTable(self):
return self._TableForNetid(self.NETID)
+ def SetAcceptRaRtInfoMinPlen(self, plen):
+ self.SetSysctl(
+ "/proc/sys/net/ipv6/conf/%s/accept_ra_rt_info_min_plen"
+ % self.IFACE, plen)
+
+ def GetAcceptRaRtInfoMinPlen(self):
+ return int(self.GetSysctl(
+ "/proc/sys/net/ipv6/conf/%s/accept_ra_rt_info_min_plen" % self.IFACE))
+
def SetAcceptRaRtInfoMaxPlen(self, plen):
self.SetSysctl(
"/proc/sys/net/ipv6/conf/%s/accept_ra_rt_info_max_plen"
- % self.IFACE, str(plen))
+ % self.IFACE, plen)
def GetAcceptRaRtInfoMaxPlen(self):
return int(self.GetSysctl(
@@ -614,18 +649,40 @@
def GetRouteExpiration(self, route):
return float(route['RTA_CACHEINFO'].expires) / 100.0
- @unittest.skipUnless(HAVE_MAX_PLEN and multinetwork_base.HAVE_AUTOCONF_TABLE,
- "need support for RIO and per-table autoconf")
+ def AssertExpirationInRange(self, routes, lifetime, epsilon):
+ self.assertTrue(routes)
+ found = False
+ # Assert that at least one route in routes has the expected lifetime
+ for route in routes:
+ expiration = self.GetRouteExpiration(route)
+ if expiration < lifetime - epsilon:
+ continue
+ if expiration > lifetime + epsilon:
+ continue
+ found = True
+ self.assertTrue(found)
+
+ def DelRoute6(self, prefix, plen):
+ version = 6
+ netid = self.NETID
+ table = self._TableForNetid(netid)
+ router = self._RouterAddress(netid, version)
+ ifindex = self.ifindices[netid]
+ self.iproute.DelRoute(version, table, prefix, plen, router, ifindex)
+
+ def testSetAcceptRaRtInfoMinPlen(self):
+ for plen in xrange(-1, 130):
+ self.SetAcceptRaRtInfoMinPlen(plen)
+ self.assertEquals(plen, self.GetAcceptRaRtInfoMinPlen())
+
def testSetAcceptRaRtInfoMaxPlen(self):
for plen in xrange(-1, 130):
self.SetAcceptRaRtInfoMaxPlen(plen)
self.assertEquals(plen, self.GetAcceptRaRtInfoMaxPlen())
- @unittest.skipUnless(HAVE_MAX_PLEN and multinetwork_base.HAVE_AUTOCONF_TABLE,
- "need support for RIO and per-table autoconf")
def testZeroRtLifetime(self):
PREFIX = "2001:db8:8901:2300::"
- RTLIFETIME = 7372
+ RTLIFETIME = 73500
PLEN = 56
PRF = 0
self.SetAcceptRaRtInfoMaxPlen(PLEN)
@@ -639,52 +696,87 @@
time.sleep(0.01)
self.assertFalse(self.FindRoutesWithDestination(PREFIX))
- @unittest.skipUnless(HAVE_MAX_PLEN and multinetwork_base.HAVE_AUTOCONF_TABLE,
- "need support for RIO and per-table autoconf")
- def testMaxPrefixLenRejection(self):
- PREFIX = "2001:db8:8901:2345::"
- RTLIFETIME = 7372
+ def testMinPrefixLenRejection(self):
+ PREFIX = "2001:db8:8902:2345::"
+ RTLIFETIME = 70372
PRF = 0
- for plen in xrange(0, 64):
+ # sweep from high to low to avoid spurious failures from late arrivals.
+ for plen in xrange(130, 1, -1):
+ self.SetAcceptRaRtInfoMinPlen(plen)
+ # RIO with plen < min_plen should be ignored
+ self.SendRIO(RTLIFETIME, plen - 1, PREFIX, PRF)
+ # Give the kernel time to notice our RAs
+ time.sleep(0.1)
+ # Expect no routes
+ routes = self.FindRoutesWithDestination(PREFIX)
+ self.assertFalse(routes)
+
+ def testMaxPrefixLenRejection(self):
+ PREFIX = "2001:db8:8903:2345::"
+ RTLIFETIME = 73078
+ PRF = 0
+ # sweep from low to high to avoid spurious failures from late arrivals.
+ for plen in xrange(-1, 128, 1):
self.SetAcceptRaRtInfoMaxPlen(plen)
# RIO with plen > max_plen should be ignored
self.SendRIO(RTLIFETIME, plen + 1, PREFIX, PRF)
- # Give the kernel time to notice our RA
- time.sleep(0.01)
- routes = self.FindRoutesWithDestination(PREFIX)
- self.assertFalse(routes)
+ # Give the kernel time to notice our RAs
+ time.sleep(0.1)
+ # Expect no routes
+ routes = self.FindRoutesWithDestination(PREFIX)
+ self.assertFalse(routes)
- @unittest.skipUnless(HAVE_MAX_PLEN and multinetwork_base.HAVE_AUTOCONF_TABLE,
- "need support for RIO and per-table autoconf")
+ def testSimpleAccept(self):
+ PREFIX = "2001:db8:8904:2345::"
+ RTLIFETIME = 9993
+ PRF = 0
+ PLEN = 56
+ self.SetAcceptRaRtInfoMinPlen(48)
+ self.SetAcceptRaRtInfoMaxPlen(64)
+ self.SendRIO(RTLIFETIME, PLEN, PREFIX, PRF)
+ # Give the kernel time to notice our RA
+ time.sleep(0.01)
+ routes = self.FindRoutesWithGateway()
+ self.AssertExpirationInRange(routes, RTLIFETIME, 1)
+ self.DelRoute6(PREFIX, PLEN)
+
+ def testEqualMinMaxAccept(self):
+ PREFIX = "2001:db8:8905:2345::"
+ RTLIFETIME = 6326
+ PLEN = 21
+ PRF = 0
+ self.SetAcceptRaRtInfoMinPlen(PLEN)
+ self.SetAcceptRaRtInfoMaxPlen(PLEN)
+ self.SendRIO(RTLIFETIME, PLEN, PREFIX, PRF)
+ # Give the kernel time to notice our RA
+ time.sleep(0.01)
+ routes = self.FindRoutesWithGateway()
+ self.AssertExpirationInRange(routes, RTLIFETIME, 1)
+ self.DelRoute6(PREFIX, PLEN)
+
def testZeroLengthPrefix(self):
- PREFIX = "::"
+ PREFIX = "2001:db8:8906:2345::"
RTLIFETIME = self.RA_VALIDITY * 2
PLEN = 0
PRF = 0
# Max plen = 0 still allows default RIOs!
self.SetAcceptRaRtInfoMaxPlen(PLEN)
+ self.SendRA(self.NETID)
+ # Give the kernel time to notice our RA
+ time.sleep(0.01)
default = self.FindRoutesWithGateway()
- self.assertTrue(default)
- self.assertLess(self.GetRouteExpiration(default[0]), self.RA_VALIDITY)
+ self.AssertExpirationInRange(default, self.RA_VALIDITY, 1)
# 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)
# Give the kernel time to notice our RA
time.sleep(0.01)
default = self.FindRoutesWithGateway()
- self.assertTrue(default)
- if net_test.LINUX_VERSION > (3, 12, 0):
- # Vanilla linux earlier than 3.13 handles RIOs with zero length prefixes
- # incorrectly. There's nothing useful to assert other than the existence
- # of a default route.
- # TODO: remove this condition after pulling bullhead/angler backports to
- # other 3.10 flavors.
- self.assertGreater(self.GetRouteExpiration(default[0]), self.RA_VALIDITY)
+ self.AssertExpirationInRange(default, RTLIFETIME, 1)
+ self.DelRoute6(PREFIX, PLEN)
- @unittest.skipUnless(HAVE_MAX_PLEN and multinetwork_base.HAVE_AUTOCONF_TABLE,
- "need support for RIO and per-table autoconf")
def testManyRIOs(self):
- RTLIFETIME = 6809
+ RTLIFETIME = 68012
PLEN = 56
PRF = 0
COUNT = 1000
@@ -694,11 +786,11 @@
for i in xrange(0, COUNT):
prefix = "2001:db8:%x:1100::" % i
self.SendRIO(RTLIFETIME, PLEN, prefix, PRF)
+ time.sleep(0.1)
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)
+ self.DelRoute6(prefix, PLEN)
# Expect that we can return to baseline config without lingering routes.
self.assertEquals(baseline, self.CountRoutes())