1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3 2*2f2c4c7aSAndroid Build Coastguard Worker# 3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2014 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 os 18*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import * # pylint: disable=wildcard-import 19*2f2c4c7aSAndroid Build Coastguard Workerimport threading 20*2f2c4c7aSAndroid Build Coastguard Workerimport time 21*2f2c4c7aSAndroid Build Coastguard Workerimport unittest 22*2f2c4c7aSAndroid Build Coastguard Worker 23*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct 24*2f2c4c7aSAndroid Build Coastguard Workerimport multinetwork_base 25*2f2c4c7aSAndroid Build Coastguard Workerimport net_test 26*2f2c4c7aSAndroid Build Coastguard Worker 27*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_JOIN_ANYCAST = 27 28*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_LEAVE_ANYCAST = 28 29*2f2c4c7aSAndroid Build Coastguard Worker 30*2f2c4c7aSAndroid Build Coastguard Worker# pylint: disable=invalid-name 31*2f2c4c7aSAndroid Build Coastguard WorkerIPv6Mreq = cstruct.Struct("IPv6Mreq", "=16si", "multiaddr ifindex") 32*2f2c4c7aSAndroid Build Coastguard Worker 33*2f2c4c7aSAndroid Build Coastguard Worker 34*2f2c4c7aSAndroid Build Coastguard Worker_CLOSE_HUNG = False 35*2f2c4c7aSAndroid Build Coastguard Worker 36*2f2c4c7aSAndroid Build Coastguard Worker 37*2f2c4c7aSAndroid Build Coastguard Workerdef CauseOops(): 38*2f2c4c7aSAndroid Build Coastguard Worker with open("/proc/sysrq-trigger", "w") as trigger: 39*2f2c4c7aSAndroid Build Coastguard Worker trigger.write("c") 40*2f2c4c7aSAndroid Build Coastguard Worker 41*2f2c4c7aSAndroid Build Coastguard Worker 42*2f2c4c7aSAndroid Build Coastguard Workerclass CloseFileDescriptorThread(threading.Thread): 43*2f2c4c7aSAndroid Build Coastguard Worker 44*2f2c4c7aSAndroid Build Coastguard Worker def __init__(self, fd): 45*2f2c4c7aSAndroid Build Coastguard Worker super(CloseFileDescriptorThread, self).__init__() 46*2f2c4c7aSAndroid Build Coastguard Worker self.daemon = True 47*2f2c4c7aSAndroid Build Coastguard Worker self._fd = fd 48*2f2c4c7aSAndroid Build Coastguard Worker self.finished = False 49*2f2c4c7aSAndroid Build Coastguard Worker 50*2f2c4c7aSAndroid Build Coastguard Worker def run(self): 51*2f2c4c7aSAndroid Build Coastguard Worker global _CLOSE_HUNG 52*2f2c4c7aSAndroid Build Coastguard Worker _CLOSE_HUNG = True 53*2f2c4c7aSAndroid Build Coastguard Worker self._fd.close() 54*2f2c4c7aSAndroid Build Coastguard Worker _CLOSE_HUNG = False 55*2f2c4c7aSAndroid Build Coastguard Worker self.finished = True 56*2f2c4c7aSAndroid Build Coastguard Worker 57*2f2c4c7aSAndroid Build Coastguard Worker 58*2f2c4c7aSAndroid Build Coastguard Workerclass AnycastTest(multinetwork_base.MultiNetworkBaseTest): 59*2f2c4c7aSAndroid Build Coastguard Worker """Tests for IPv6 anycast addresses. 60*2f2c4c7aSAndroid Build Coastguard Worker 61*2f2c4c7aSAndroid Build Coastguard Worker Relevant kernel commits: 62*2f2c4c7aSAndroid Build Coastguard Worker upstream net-next: 63*2f2c4c7aSAndroid Build Coastguard Worker 381f4dc ipv6: clean up anycast when an interface is destroyed 64*2f2c4c7aSAndroid Build Coastguard Worker 65*2f2c4c7aSAndroid Build Coastguard Worker android-3.10: 66*2f2c4c7aSAndroid Build Coastguard Worker 86a47ad ipv6: clean up anycast when an interface is destroyed 67*2f2c4c7aSAndroid Build Coastguard Worker """ 68*2f2c4c7aSAndroid Build Coastguard Worker _TEST_NETID = 123 69*2f2c4c7aSAndroid Build Coastguard Worker 70*2f2c4c7aSAndroid Build Coastguard Worker def AnycastSetsockopt(self, s, is_add, netid, addr): 71*2f2c4c7aSAndroid Build Coastguard Worker ifindex = self.ifindices[netid] 72*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(ifindex) 73*2f2c4c7aSAndroid Build Coastguard Worker ipv6mreq = IPv6Mreq((addr, ifindex)) 74*2f2c4c7aSAndroid Build Coastguard Worker option = IPV6_JOIN_ANYCAST if is_add else IPV6_LEAVE_ANYCAST 75*2f2c4c7aSAndroid Build Coastguard Worker s.setsockopt(IPPROTO_IPV6, option, ipv6mreq.Pack()) 76*2f2c4c7aSAndroid Build Coastguard Worker 77*2f2c4c7aSAndroid Build Coastguard Worker def testAnycastNetdeviceUnregister(self): 78*2f2c4c7aSAndroid Build Coastguard Worker netid = self._TEST_NETID 79*2f2c4c7aSAndroid Build Coastguard Worker self.assertNotIn(netid, self.tuns) 80*2f2c4c7aSAndroid Build Coastguard Worker self.tuns[netid] = self.CreateTunInterface(netid) 81*2f2c4c7aSAndroid Build Coastguard Worker self.SendRA(netid) 82*2f2c4c7aSAndroid Build Coastguard Worker iface = self.GetInterfaceName(netid) 83*2f2c4c7aSAndroid Build Coastguard Worker self.ifindices[netid] = net_test.GetInterfaceIndex(iface) 84*2f2c4c7aSAndroid Build Coastguard Worker 85*2f2c4c7aSAndroid Build Coastguard Worker s = socket(AF_INET6, SOCK_DGRAM, 0) 86*2f2c4c7aSAndroid Build Coastguard Worker addr = self.MyAddress(6, netid) 87*2f2c4c7aSAndroid Build Coastguard Worker self.assertIsNotNone(addr) 88*2f2c4c7aSAndroid Build Coastguard Worker 89*2f2c4c7aSAndroid Build Coastguard Worker addr = inet_pton(AF_INET6, addr) 90*2f2c4c7aSAndroid Build Coastguard Worker addr = addr[:8] + os.urandom(8) 91*2f2c4c7aSAndroid Build Coastguard Worker self.AnycastSetsockopt(s, True, netid, addr) 92*2f2c4c7aSAndroid Build Coastguard Worker 93*2f2c4c7aSAndroid Build Coastguard Worker # Close the tun fd in the background. 94*2f2c4c7aSAndroid Build Coastguard Worker # This will hang if the kernel has the bug. 95*2f2c4c7aSAndroid Build Coastguard Worker thread = CloseFileDescriptorThread(self.tuns[netid]) 96*2f2c4c7aSAndroid Build Coastguard Worker thread.start() 97*2f2c4c7aSAndroid Build Coastguard Worker # Wait up to 3 seconds for the thread to finish, but 98*2f2c4c7aSAndroid Build Coastguard Worker # continue and fail the test if the thread hangs. 99*2f2c4c7aSAndroid Build Coastguard Worker 100*2f2c4c7aSAndroid Build Coastguard Worker # For kernels with MPTCP ported, closing tun interface need more 101*2f2c4c7aSAndroid Build Coastguard Worker # than 0.5 sec. DAD procedure within MPTCP fullmesh module takes 102*2f2c4c7aSAndroid Build Coastguard Worker # more time, because duplicate address-timer takes a refcount 103*2f2c4c7aSAndroid Build Coastguard Worker # on the IPv6-address, preventing it from getting closed. 104*2f2c4c7aSAndroid Build Coastguard Worker thread.join(3) 105*2f2c4c7aSAndroid Build Coastguard Worker 106*2f2c4c7aSAndroid Build Coastguard Worker # Make teardown work. 107*2f2c4c7aSAndroid Build Coastguard Worker del self.tuns[netid] 108*2f2c4c7aSAndroid Build Coastguard Worker # Check that the interface is gone. 109*2f2c4c7aSAndroid Build Coastguard Worker try: 110*2f2c4c7aSAndroid Build Coastguard Worker self.assertIsNone(self.MyAddress(6, netid)) 111*2f2c4c7aSAndroid Build Coastguard Worker finally: 112*2f2c4c7aSAndroid Build Coastguard Worker # This doesn't seem to help, but still. 113*2f2c4c7aSAndroid Build Coastguard Worker self.AnycastSetsockopt(s, False, netid, addr) 114*2f2c4c7aSAndroid Build Coastguard Worker self.assertTrue(thread.finished) 115*2f2c4c7aSAndroid Build Coastguard Worker s.close() 116*2f2c4c7aSAndroid Build Coastguard Worker 117*2f2c4c7aSAndroid Build Coastguard Worker 118*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__": 119*2f2c4c7aSAndroid Build Coastguard Worker unittest.main(exit=False) 120*2f2c4c7aSAndroid Build Coastguard Worker if _CLOSE_HUNG: 121*2f2c4c7aSAndroid Build Coastguard Worker time.sleep(3) 122*2f2c4c7aSAndroid Build Coastguard Worker CauseOops() 123