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