xref: /aosp_15_r20/kernel/tests/net/test/neighbour_test.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
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