1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3 2*2f2c4c7aSAndroid Build Coastguard Worker# 3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2015 The Android Open Source Project 4*2f2c4c7aSAndroid Build Coastguard Worker# 5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*2f2c4c7aSAndroid Build Coastguard Worker# 9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*2f2c4c7aSAndroid Build Coastguard Worker# 11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License. 16*2f2c4c7aSAndroid Build Coastguard Worker 17*2f2c4c7aSAndroid Build Coastguard Workerimport errno 18*2f2c4c7aSAndroid Build Coastguard Workerimport random 19*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import * # pylint: disable=wildcard-import 20*2f2c4c7aSAndroid Build Coastguard Workerimport time 21*2f2c4c7aSAndroid Build Coastguard Workerimport unittest 22*2f2c4c7aSAndroid Build Coastguard Worker 23*2f2c4c7aSAndroid Build Coastguard Workerfrom scapy import all as scapy 24*2f2c4c7aSAndroid Build Coastguard Worker 25*2f2c4c7aSAndroid Build Coastguard Workerimport csocket 26*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base 27*2f2c4c7aSAndroid Build Coastguard Workerimport net_test 28*2f2c4c7aSAndroid Build Coastguard Worker 29*2f2c4c7aSAndroid Build Coastguard Worker 30*2f2c4c7aSAndroid Build Coastguard WorkerRTMGRP_NEIGH = 4 31*2f2c4c7aSAndroid Build Coastguard Worker 32*2f2c4c7aSAndroid Build Coastguard WorkerNUD_INCOMPLETE = 0x01 33*2f2c4c7aSAndroid Build Coastguard WorkerNUD_REACHABLE = 0x02 34*2f2c4c7aSAndroid Build Coastguard WorkerNUD_STALE = 0x04 35*2f2c4c7aSAndroid Build Coastguard WorkerNUD_DELAY = 0x08 36*2f2c4c7aSAndroid Build Coastguard WorkerNUD_PROBE = 0x10 37*2f2c4c7aSAndroid Build Coastguard WorkerNUD_FAILED = 0x20 38*2f2c4c7aSAndroid Build Coastguard WorkerNUD_PERMANENT = 0x80 39*2f2c4c7aSAndroid Build Coastguard Worker 40*2f2c4c7aSAndroid Build Coastguard Worker 41*2f2c4c7aSAndroid Build Coastguard Worker# TODO: Support IPv4. 42*2f2c4c7aSAndroid Build Coastguard Workerclass NeighbourTest(multinetwork_base.MultiNetworkBaseTest): 43*2f2c4c7aSAndroid Build Coastguard Worker 44*2f2c4c7aSAndroid Build Coastguard Worker # Set a 500-ms retrans timer so we can test for ND retransmits without 45*2f2c4c7aSAndroid Build Coastguard Worker # waiting too long. Apparently this cannot go below 500ms. 46*2f2c4c7aSAndroid Build Coastguard Worker RETRANS_TIME_MS = 500 47*2f2c4c7aSAndroid Build Coastguard Worker 48*2f2c4c7aSAndroid Build Coastguard Worker # This can only be in seconds, so 1000 is the minimum. 49*2f2c4c7aSAndroid Build Coastguard Worker DELAY_TIME_MS = 1000 50*2f2c4c7aSAndroid Build Coastguard Worker 51*2f2c4c7aSAndroid Build Coastguard Worker # Unfortunately, this must be above the delay timer or the kernel ND code will 52*2f2c4c7aSAndroid Build Coastguard Worker # not behave correctly (e.g., go straight from REACHABLE into DELAY). This is 53*2f2c4c7aSAndroid Build Coastguard Worker # is fuzzed by the kernel from 0.5x to 1.5x of its value, so we need a value 54*2f2c4c7aSAndroid Build Coastguard Worker # that's 2x the delay timer. 55*2f2c4c7aSAndroid Build Coastguard Worker BASE_REACHABLE_TIME_MS = 2 * DELAY_TIME_MS 56*2f2c4c7aSAndroid Build Coastguard Worker MAX_REACHABLE_TIME_MS = 1.5 * BASE_REACHABLE_TIME_MS 57*2f2c4c7aSAndroid Build Coastguard Worker 58*2f2c4c7aSAndroid Build Coastguard Worker # Kernel default unicast solicit is 3, but it need be changed larger 59*2f2c4c7aSAndroid Build Coastguard Worker # when test recofiguration during probing 60*2f2c4c7aSAndroid Build Coastguard Worker UCAST_SOLICIT_DEFAULT = 3 61*2f2c4c7aSAndroid Build Coastguard Worker UCAST_SOLICIT_LARGE = 10 62*2f2c4c7aSAndroid Build Coastguard Worker 63*2f2c4c7aSAndroid Build Coastguard Worker @classmethod 64*2f2c4c7aSAndroid Build Coastguard Worker def setUpClass(cls): 65*2f2c4c7aSAndroid Build Coastguard Worker super(NeighbourTest, cls).setUpClass() 66*2f2c4c7aSAndroid Build Coastguard Worker for netid in cls.tuns: 67*2f2c4c7aSAndroid Build Coastguard Worker iface = cls.GetInterfaceName(netid) 68*2f2c4c7aSAndroid Build Coastguard Worker # This can't be set in an RA. 69*2f2c4c7aSAndroid Build Coastguard Worker for proto in ["ipv4", "ipv6"]: 70*2f2c4c7aSAndroid Build Coastguard Worker cls.SetSysctl( 71*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/%s/neigh/%s/delay_first_probe_time" % (proto, iface), 72*2f2c4c7aSAndroid Build Coastguard Worker cls.DELAY_TIME_MS // 1000) 73*2f2c4c7aSAndroid Build Coastguard Worker cls.SetSysctl( 74*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/%s/neigh/%s/retrans_time_ms" % (proto, iface), 75*2f2c4c7aSAndroid Build Coastguard Worker cls.RETRANS_TIME_MS) 76*2f2c4c7aSAndroid Build Coastguard Worker 77*2f2c4c7aSAndroid Build Coastguard Worker def setUp(self): 78*2f2c4c7aSAndroid Build Coastguard Worker super(NeighbourTest, self).setUp() 79*2f2c4c7aSAndroid Build Coastguard Worker 80*2f2c4c7aSAndroid Build Coastguard Worker for netid in self.tuns: 81*2f2c4c7aSAndroid Build Coastguard Worker # Clear the ND cache entries for all routers, so each test starts with 82*2f2c4c7aSAndroid Build Coastguard Worker # the IPv6 default router in state STALE. 83*2f2c4c7aSAndroid Build Coastguard Worker addr = self._RouterAddress(netid, 6) 84*2f2c4c7aSAndroid Build Coastguard Worker ifindex = self.ifindices[netid] 85*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UpdateNeighbour(6, addr, None, ifindex, NUD_FAILED) 86*2f2c4c7aSAndroid Build Coastguard Worker 87*2f2c4c7aSAndroid Build Coastguard Worker # Configure IPv6 by sending an RA. 88*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(netid, 89*2f2c4c7aSAndroid Build Coastguard Worker retranstimer=self.RETRANS_TIME_MS, 90*2f2c4c7aSAndroid Build Coastguard Worker reachabletime=self.BASE_REACHABLE_TIME_MS) 91*2f2c4c7aSAndroid Build Coastguard Worker 92*2f2c4c7aSAndroid Build Coastguard Worker self.sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) 93*2f2c4c7aSAndroid Build Coastguard Worker self.sock.bind((0, RTMGRP_NEIGH)) 94*2f2c4c7aSAndroid Build Coastguard Worker net_test.SetNonBlocking(self.sock) 95*2f2c4c7aSAndroid Build Coastguard Worker 96*2f2c4c7aSAndroid Build Coastguard Worker self.netid = random.choice(list(self.tuns.keys())) 97*2f2c4c7aSAndroid Build Coastguard Worker self.ifindex = self.ifindices[self.netid] 98*2f2c4c7aSAndroid Build Coastguard Worker 99*2f2c4c7aSAndroid Build Coastguard Worker # MultinetworkBaseTest always uses NUD_PERMANENT for router ARP entries. 100*2f2c4c7aSAndroid Build Coastguard Worker # Temporarily change those entries to NUD_STALE so we can test them. 101*2f2c4c7aSAndroid Build Coastguard Worker self.ChangeRouterNudState(4, NUD_STALE) 102*2f2c4c7aSAndroid Build Coastguard Worker 103*2f2c4c7aSAndroid Build Coastguard Worker def SetUnicastSolicit(self, proto, iface, value): 104*2f2c4c7aSAndroid Build Coastguard Worker self.SetSysctl( 105*2f2c4c7aSAndroid Build Coastguard Worker "/proc/sys/net/%s/neigh/%s/ucast_solicit" % (proto, iface), value) 106*2f2c4c7aSAndroid Build Coastguard Worker 107*2f2c4c7aSAndroid Build Coastguard Worker def tearDown(self): 108*2f2c4c7aSAndroid Build Coastguard Worker super(NeighbourTest, self).tearDown() 109*2f2c4c7aSAndroid Build Coastguard Worker # It is already reset to default by TearDownClass, 110*2f2c4c7aSAndroid Build Coastguard Worker # but here we need to set it to default after each testcase. 111*2f2c4c7aSAndroid Build Coastguard Worker iface = self.GetInterfaceName(self.netid) 112*2f2c4c7aSAndroid Build Coastguard Worker for proto in ["ipv4", "ipv6"]: 113*2f2c4c7aSAndroid Build Coastguard Worker self.SetUnicastSolicit(proto, iface, self.UCAST_SOLICIT_DEFAULT) 114*2f2c4c7aSAndroid Build Coastguard Worker 115*2f2c4c7aSAndroid Build Coastguard Worker # Change router ARP entries back to NUD_PERMANENT, 116*2f2c4c7aSAndroid Build Coastguard Worker # so as not to affect other tests. 117*2f2c4c7aSAndroid Build Coastguard Worker self.ChangeRouterNudState(4, NUD_PERMANENT) 118*2f2c4c7aSAndroid Build Coastguard Worker 119*2f2c4c7aSAndroid Build Coastguard Worker self.sock.close() 120*2f2c4c7aSAndroid Build Coastguard Worker self.sock = None 121*2f2c4c7aSAndroid Build Coastguard Worker 122*2f2c4c7aSAndroid Build Coastguard Worker def ChangeRouterNudState(self, version, state): 123*2f2c4c7aSAndroid Build Coastguard Worker router = self._RouterAddress(self.netid, version) 124*2f2c4c7aSAndroid Build Coastguard Worker macaddr = self.RouterMacAddress(self.netid) 125*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UpdateNeighbour(version, router, macaddr, self.ifindex, state) 126*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router, state) 127*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(state, router) 128*2f2c4c7aSAndroid Build Coastguard Worker 129*2f2c4c7aSAndroid Build Coastguard Worker def GetNeighbour(self, addr, ifindex): 130*2f2c4c7aSAndroid Build Coastguard Worker version = csocket.AddressVersion(addr) 131*2f2c4c7aSAndroid Build Coastguard Worker for msg, args in self.iproute.DumpNeighbours(version, ifindex): 132*2f2c4c7aSAndroid Build Coastguard Worker if args["NDA_DST"] == addr: 133*2f2c4c7aSAndroid Build Coastguard Worker return msg, args 134*2f2c4c7aSAndroid Build Coastguard Worker 135*2f2c4c7aSAndroid Build Coastguard Worker def GetNdEntry(self, addr): 136*2f2c4c7aSAndroid Build Coastguard Worker return self.GetNeighbour(addr, self.ifindex) 137*2f2c4c7aSAndroid Build Coastguard Worker 138*2f2c4c7aSAndroid Build Coastguard Worker def CheckNoNdEvents(self): 139*2f2c4c7aSAndroid Build Coastguard Worker self.assertRaisesErrno(errno.EAGAIN, self.sock.recvfrom, 4096, MSG_PEEK) 140*2f2c4c7aSAndroid Build Coastguard Worker 141*2f2c4c7aSAndroid Build Coastguard Worker def assertNeighbourState(self, state, addr): 142*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(state, self.GetNdEntry(addr)[0].state) 143*2f2c4c7aSAndroid Build Coastguard Worker 144*2f2c4c7aSAndroid Build Coastguard Worker def assertNeighbourAttr(self, addr, name, value): 145*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(value, self.GetNdEntry(addr)[1][name]) 146*2f2c4c7aSAndroid Build Coastguard Worker 147*2f2c4c7aSAndroid Build Coastguard Worker def ExpectNeighbourNotification(self, addr, state, attrs=None): 148*2f2c4c7aSAndroid Build Coastguard Worker msg = self.sock.recv(4096) 149*2f2c4c7aSAndroid Build Coastguard Worker msg, actual_attrs = self.iproute.ParseNeighbourMessage(msg) 150*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(addr, actual_attrs["NDA_DST"]) 151*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(state, msg.state) 152*2f2c4c7aSAndroid Build Coastguard Worker if attrs: 153*2f2c4c7aSAndroid Build Coastguard Worker for name in attrs: 154*2f2c4c7aSAndroid Build Coastguard Worker self.assertEqual(attrs[name], actual_attrs[name]) 155*2f2c4c7aSAndroid Build Coastguard Worker 156*2f2c4c7aSAndroid Build Coastguard Worker def ExpectProbe(self, is_unicast, addr): 157*2f2c4c7aSAndroid Build Coastguard Worker version = csocket.AddressVersion(addr) 158*2f2c4c7aSAndroid Build Coastguard Worker llsrc = self.MyMacAddress(self.netid) 159*2f2c4c7aSAndroid Build Coastguard Worker if version == 6: 160*2f2c4c7aSAndroid Build Coastguard Worker if is_unicast: 161*2f2c4c7aSAndroid Build Coastguard Worker src = self.MyLinkLocalAddress(self.netid) 162*2f2c4c7aSAndroid Build Coastguard Worker dst = addr 163*2f2c4c7aSAndroid Build Coastguard Worker else: 164*2f2c4c7aSAndroid Build Coastguard Worker solicited = inet_pton(AF_INET6, addr) 165*2f2c4c7aSAndroid Build Coastguard Worker last3bytes = tuple([net_test.ByteToHex(b) for b in solicited[-3:]]) 166*2f2c4c7aSAndroid Build Coastguard Worker dst = "ff02::1:ff%s:%s%s" % last3bytes 167*2f2c4c7aSAndroid Build Coastguard Worker src = self.MyAddress(6, self.netid) 168*2f2c4c7aSAndroid Build Coastguard Worker expected = ( 169*2f2c4c7aSAndroid Build Coastguard Worker scapy.IPv6(src=src, dst=dst) / 170*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMPv6ND_NS(tgt=addr) / 171*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMPv6NDOptSrcLLAddr(lladdr=llsrc) 172*2f2c4c7aSAndroid Build Coastguard Worker ) 173*2f2c4c7aSAndroid Build Coastguard Worker msg = "%s probe" % ("Unicast" if is_unicast else "Multicast") 174*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(self.netid, msg, expected) 175*2f2c4c7aSAndroid Build Coastguard Worker else: # version == 4 176*2f2c4c7aSAndroid Build Coastguard Worker if is_unicast: 177*2f2c4c7aSAndroid Build Coastguard Worker src = self._MyIPv4Address(self.netid) 178*2f2c4c7aSAndroid Build Coastguard Worker dst = addr 179*2f2c4c7aSAndroid Build Coastguard Worker else: 180*2f2c4c7aSAndroid Build Coastguard Worker raise NotImplementedError("This test does not support broadcast ARP") 181*2f2c4c7aSAndroid Build Coastguard Worker expected = scapy.ARP(psrc=src, pdst=dst, hwsrc=llsrc, op=1) 182*2f2c4c7aSAndroid Build Coastguard Worker msg = "Unicast ARP probe" 183*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectPacketOn(self.netid, msg, expected) 184*2f2c4c7aSAndroid Build Coastguard Worker 185*2f2c4c7aSAndroid Build Coastguard Worker def ExpectUnicastProbe(self, addr): 186*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectProbe(True, addr) 187*2f2c4c7aSAndroid Build Coastguard Worker 188*2f2c4c7aSAndroid Build Coastguard Worker def ExpectMulticastNS(self, addr): 189*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectProbe(False, addr) 190*2f2c4c7aSAndroid Build Coastguard Worker 191*2f2c4c7aSAndroid Build Coastguard Worker def ReceiveUnicastAdvertisement(self, addr, mac, srcaddr=None, dstaddr=None, 192*2f2c4c7aSAndroid Build Coastguard Worker S=1, O=0, R=1): 193*2f2c4c7aSAndroid Build Coastguard Worker version = csocket.AddressVersion(addr) 194*2f2c4c7aSAndroid Build Coastguard Worker if srcaddr is None: 195*2f2c4c7aSAndroid Build Coastguard Worker srcaddr = addr 196*2f2c4c7aSAndroid Build Coastguard Worker if dstaddr is None: 197*2f2c4c7aSAndroid Build Coastguard Worker dstaddr = self.MyLinkLocalAddress(self.netid) 198*2f2c4c7aSAndroid Build Coastguard Worker if version == 6: 199*2f2c4c7aSAndroid Build Coastguard Worker packet = ( 200*2f2c4c7aSAndroid Build Coastguard Worker scapy.Ether(src=mac, dst=self.MyMacAddress(self.netid)) / 201*2f2c4c7aSAndroid Build Coastguard Worker scapy.IPv6(src=srcaddr, dst=dstaddr) / 202*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMPv6ND_NA(tgt=addr, S=S, O=O, R=R) / 203*2f2c4c7aSAndroid Build Coastguard Worker scapy.ICMPv6NDOptDstLLAddr(lladdr=mac) 204*2f2c4c7aSAndroid Build Coastguard Worker ) 205*2f2c4c7aSAndroid Build Coastguard Worker self.ReceiveEtherPacketOn(self.netid, packet) 206*2f2c4c7aSAndroid Build Coastguard Worker else: 207*2f2c4c7aSAndroid Build Coastguard Worker raise NotImplementedError 208*2f2c4c7aSAndroid Build Coastguard Worker 209*2f2c4c7aSAndroid Build Coastguard Worker def SendDnsRequest(self, addr): 210*2f2c4c7aSAndroid Build Coastguard Worker version = csocket.AddressVersion(addr) 211*2f2c4c7aSAndroid Build Coastguard Worker routing_mode = random.choice(["mark", "oif", "uid"]) 212*2f2c4c7aSAndroid Build Coastguard Worker s = self.BuildSocket(version, net_test.UDPSocket, self.netid, routing_mode) 213*2f2c4c7aSAndroid Build Coastguard Worker s.connect((addr, 53)) 214*2f2c4c7aSAndroid Build Coastguard Worker s.send(net_test.UDP_PAYLOAD) 215*2f2c4c7aSAndroid Build Coastguard Worker return s 216*2f2c4c7aSAndroid Build Coastguard Worker 217*2f2c4c7aSAndroid Build Coastguard Worker def MonitorSleepMs(self, interval, addr): 218*2f2c4c7aSAndroid Build Coastguard Worker slept = 0 219*2f2c4c7aSAndroid Build Coastguard Worker while slept < interval: 220*2f2c4c7aSAndroid Build Coastguard Worker sleep_ms = min(100, interval - slept) 221*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(sleep_ms / 1000.0) 222*2f2c4c7aSAndroid Build Coastguard Worker slept += sleep_ms 223*2f2c4c7aSAndroid Build Coastguard Worker print(self.GetNdEntry(addr)) 224*2f2c4c7aSAndroid Build Coastguard Worker 225*2f2c4c7aSAndroid Build Coastguard Worker def MonitorSleep(self, intervalseconds, addr): 226*2f2c4c7aSAndroid Build Coastguard Worker self.MonitorSleepMs(intervalseconds * 1000, addr) 227*2f2c4c7aSAndroid Build Coastguard Worker 228*2f2c4c7aSAndroid Build Coastguard Worker def SleepMs(self, ms): 229*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(ms / 1000.0) 230*2f2c4c7aSAndroid Build Coastguard Worker 231*2f2c4c7aSAndroid Build Coastguard Worker def testNotifications(self): 232*2f2c4c7aSAndroid Build Coastguard Worker """Tests neighbour notifications. 233*2f2c4c7aSAndroid Build Coastguard Worker 234*2f2c4c7aSAndroid Build Coastguard Worker Relevant kernel commits: 235*2f2c4c7aSAndroid Build Coastguard Worker upstream net-next: 236*2f2c4c7aSAndroid Build Coastguard Worker 765c9c6 neigh: Better handling of transition to NUD_PROBE state 237*2f2c4c7aSAndroid Build Coastguard Worker 53385d2 neigh: Netlink notification for administrative NUD state change 238*2f2c4c7aSAndroid Build Coastguard Worker (only checked on kernel v3.13+, not on v3.10) 239*2f2c4c7aSAndroid Build Coastguard Worker 240*2f2c4c7aSAndroid Build Coastguard Worker android-3.10: 241*2f2c4c7aSAndroid Build Coastguard Worker e4a6d6b neigh: Better handling of transition to NUD_PROBE state 242*2f2c4c7aSAndroid Build Coastguard Worker 243*2f2c4c7aSAndroid Build Coastguard Worker android-3.18: 244*2f2c4c7aSAndroid Build Coastguard Worker 2011e72 neigh: Better handling of transition to NUD_PROBE state 245*2f2c4c7aSAndroid Build Coastguard Worker """ 246*2f2c4c7aSAndroid Build Coastguard Worker router4 = self._RouterAddress(self.netid, 4) 247*2f2c4c7aSAndroid Build Coastguard Worker router6 = self._RouterAddress(self.netid, 6) 248*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_STALE, router4) 249*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_STALE, router6) 250*2f2c4c7aSAndroid Build Coastguard Worker 251*2f2c4c7aSAndroid Build Coastguard Worker # Send a packet and check that we go into DELAY. 252*2f2c4c7aSAndroid Build Coastguard Worker s = self.SendDnsRequest(net_test.IPV6_ADDR) 253*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_DELAY, router6) 254*2f2c4c7aSAndroid Build Coastguard Worker 255*2f2c4c7aSAndroid Build Coastguard Worker # Wait for the probe interval, then check that we're in PROBE, and that the 256*2f2c4c7aSAndroid Build Coastguard Worker # kernel has notified us. 257*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(self.DELAY_TIME_MS * 1.1) 258*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router6, NUD_PROBE) 259*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_PROBE, router6) 260*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectUnicastProbe(router6) 261*2f2c4c7aSAndroid Build Coastguard Worker 262*2f2c4c7aSAndroid Build Coastguard Worker # Respond to the NS and verify we're in REACHABLE again. 263*2f2c4c7aSAndroid Build Coastguard Worker self.ReceiveUnicastAdvertisement(router6, self.RouterMacAddress(self.netid)) 264*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_REACHABLE, router6) 265*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router6, NUD_REACHABLE) 266*2f2c4c7aSAndroid Build Coastguard Worker 267*2f2c4c7aSAndroid Build Coastguard Worker # Wait until the reachable time has passed, and verify we're in STALE. 268*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(self.MAX_REACHABLE_TIME_MS * 1.2) 269*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_STALE, router6) 270*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router6, NUD_STALE) 271*2f2c4c7aSAndroid Build Coastguard Worker 272*2f2c4c7aSAndroid Build Coastguard Worker # Send a packet, and verify we go into DELAY and then to PROBE. 273*2f2c4c7aSAndroid Build Coastguard Worker s.send(net_test.UDP_PAYLOAD) 274*2f2c4c7aSAndroid Build Coastguard Worker s.close() 275*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_DELAY, router6) 276*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(self.DELAY_TIME_MS * 1.1) 277*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_PROBE, router6) 278*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router6, NUD_PROBE) 279*2f2c4c7aSAndroid Build Coastguard Worker 280*2f2c4c7aSAndroid Build Coastguard Worker # Wait for the probes to time out, and expect a FAILED notification. 281*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourAttr(router6, "NDA_PROBES", 1) 282*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectUnicastProbe(router6) 283*2f2c4c7aSAndroid Build Coastguard Worker 284*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(self.RETRANS_TIME_MS) 285*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectUnicastProbe(router6) 286*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourAttr(router6, "NDA_PROBES", 2) 287*2f2c4c7aSAndroid Build Coastguard Worker 288*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(self.RETRANS_TIME_MS) 289*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectUnicastProbe(router6) 290*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourAttr(router6, "NDA_PROBES", 3) 291*2f2c4c7aSAndroid Build Coastguard Worker 292*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(self.RETRANS_TIME_MS) 293*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_FAILED, router6) 294*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router6, NUD_FAILED, {"NDA_PROBES": 3}) 295*2f2c4c7aSAndroid Build Coastguard Worker 296*2f2c4c7aSAndroid Build Coastguard Worker def testRepeatedProbes(self): 297*2f2c4c7aSAndroid Build Coastguard Worker router4 = self._RouterAddress(self.netid, 4) 298*2f2c4c7aSAndroid Build Coastguard Worker router6 = self._RouterAddress(self.netid, 6) 299*2f2c4c7aSAndroid Build Coastguard Worker routermac = self.RouterMacAddress(self.netid) 300*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_STALE, router4) 301*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_STALE, router6) 302*2f2c4c7aSAndroid Build Coastguard Worker 303*2f2c4c7aSAndroid Build Coastguard Worker def ForceProbe(addr, mac): 304*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UpdateNeighbour(6, addr, None, self.ifindex, NUD_PROBE) 305*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_PROBE, addr) 306*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(addr, NUD_PROBE) 307*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(1) # TODO: Why is this necessary? 308*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_PROBE, addr) 309*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectUnicastProbe(addr) 310*2f2c4c7aSAndroid Build Coastguard Worker self.ReceiveUnicastAdvertisement(addr, mac) 311*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_REACHABLE, addr) 312*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(addr, NUD_REACHABLE) 313*2f2c4c7aSAndroid Build Coastguard Worker 314*2f2c4c7aSAndroid Build Coastguard Worker for _ in range(5): 315*2f2c4c7aSAndroid Build Coastguard Worker ForceProbe(router6, routermac) 316*2f2c4c7aSAndroid Build Coastguard Worker 317*2f2c4c7aSAndroid Build Coastguard Worker def testIsRouterFlag(self): 318*2f2c4c7aSAndroid Build Coastguard Worker router6 = self._RouterAddress(self.netid, 6) 319*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_STALE, router6) 320*2f2c4c7aSAndroid Build Coastguard Worker 321*2f2c4c7aSAndroid Build Coastguard Worker # Get into FAILED. 322*2f2c4c7aSAndroid Build Coastguard Worker ifindex = self.ifindices[self.netid] 323*2f2c4c7aSAndroid Build Coastguard Worker self.iproute.UpdateNeighbour(6, router6, None, ifindex, NUD_FAILED) 324*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router6, NUD_FAILED) 325*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_FAILED, router6) 326*2f2c4c7aSAndroid Build Coastguard Worker 327*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(1) 328*2f2c4c7aSAndroid Build Coastguard Worker 329*2f2c4c7aSAndroid Build Coastguard Worker # Send another packet and expect a multicast NS. 330*2f2c4c7aSAndroid Build Coastguard Worker self.SendDnsRequest(net_test.IPV6_ADDR).close() 331*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectMulticastNS(router6) 332*2f2c4c7aSAndroid Build Coastguard Worker 333*2f2c4c7aSAndroid Build Coastguard Worker # Receive a unicast NA with the R flag set to 0. 334*2f2c4c7aSAndroid Build Coastguard Worker self.ReceiveUnicastAdvertisement(router6, self.RouterMacAddress(self.netid), 335*2f2c4c7aSAndroid Build Coastguard Worker srcaddr=self._RouterAddress(self.netid, 6), 336*2f2c4c7aSAndroid Build Coastguard Worker dstaddr=self.MyAddress(6, self.netid), 337*2f2c4c7aSAndroid Build Coastguard Worker S=1, O=0, R=0) 338*2f2c4c7aSAndroid Build Coastguard Worker 339*2f2c4c7aSAndroid Build Coastguard Worker # Expect that this takes us to REACHABLE. 340*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router6, NUD_REACHABLE) 341*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_REACHABLE, router6) 342*2f2c4c7aSAndroid Build Coastguard Worker 343*2f2c4c7aSAndroid Build Coastguard Worker def DoReconfigureDuringProbing(self, version): 344*2f2c4c7aSAndroid Build Coastguard Worker if version == 6: 345*2f2c4c7aSAndroid Build Coastguard Worker proto = "ipv6" 346*2f2c4c7aSAndroid Build Coastguard Worker ip_addr = net_test.IPV6_ADDR 347*2f2c4c7aSAndroid Build Coastguard Worker else: 348*2f2c4c7aSAndroid Build Coastguard Worker proto = "ipv4" 349*2f2c4c7aSAndroid Build Coastguard Worker ip_addr = net_test.IPV4_ADDR 350*2f2c4c7aSAndroid Build Coastguard Worker router = self._RouterAddress(self.netid, version) 351*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_STALE, router) 352*2f2c4c7aSAndroid Build Coastguard Worker 353*2f2c4c7aSAndroid Build Coastguard Worker iface = self.GetInterfaceName(self.netid) 354*2f2c4c7aSAndroid Build Coastguard Worker # set unicast solicit larger. 355*2f2c4c7aSAndroid Build Coastguard Worker self.SetUnicastSolicit(proto, iface, self.UCAST_SOLICIT_LARGE) 356*2f2c4c7aSAndroid Build Coastguard Worker 357*2f2c4c7aSAndroid Build Coastguard Worker # Send a packet and check that we go into DELAY. 358*2f2c4c7aSAndroid Build Coastguard Worker self.SendDnsRequest(ip_addr).close() 359*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_DELAY, router) 360*2f2c4c7aSAndroid Build Coastguard Worker 361*2f2c4c7aSAndroid Build Coastguard Worker # Probing 4 times but no reponse 362*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(self.DELAY_TIME_MS * 1.1) 363*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router, NUD_PROBE) 364*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_PROBE, router) 365*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectUnicastProbe(router) 366*2f2c4c7aSAndroid Build Coastguard Worker 367*2f2c4c7aSAndroid Build Coastguard Worker for i in range(0, 3): 368*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(self.RETRANS_TIME_MS) 369*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectUnicastProbe(router) 370*2f2c4c7aSAndroid Build Coastguard Worker 371*2f2c4c7aSAndroid Build Coastguard Worker # reconfiguration to 3 while probing and the state change to NUD_FAILED 372*2f2c4c7aSAndroid Build Coastguard Worker self.SetUnicastSolicit(proto, iface, self.UCAST_SOLICIT_DEFAULT) 373*2f2c4c7aSAndroid Build Coastguard Worker self.SleepMs(self.RETRANS_TIME_MS) 374*2f2c4c7aSAndroid Build Coastguard Worker self.ExpectNeighbourNotification(router, NUD_FAILED) 375*2f2c4c7aSAndroid Build Coastguard Worker self.assertNeighbourState(NUD_FAILED, router) 376*2f2c4c7aSAndroid Build Coastguard Worker 377*2f2c4c7aSAndroid Build Coastguard Worker # Check neighbor state after re-config ARP probe times. 378*2f2c4c7aSAndroid Build Coastguard Worker def testReconfigureDuringProbing(self): 379*2f2c4c7aSAndroid Build Coastguard Worker self.DoReconfigureDuringProbing(4) 380*2f2c4c7aSAndroid Build Coastguard Worker self.DoReconfigureDuringProbing(6) 381*2f2c4c7aSAndroid Build Coastguard Worker 382*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__": 383*2f2c4c7aSAndroid Build Coastguard Worker unittest.main() 384