• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import os
7import time
8from autotest_lib.client.bin import test
9from autotest_lib.client.common_lib import error, utils
10
11
12def FindDriver(ifname):
13  """Finds the driver associated with network interface.
14
15  @param ifname Interface name
16  @return String containing the kernel driver name for this interface
17  """
18
19  driver_file = '/sys/class/net/%s/device/driver/module' % ifname
20  if os.path.exists(driver_file):
21    return os.path.basename(os.readlink(driver_file))
22
23
24def GetInterfaceList():
25  """Gets the list of network interfaces on this host.
26
27  @return List containing a string for each interface name
28  """
29  return os.listdir('/sys/class/net')
30
31
32def FindInterface(typelist=('wlan','mlan','eth')):
33  """Finds an interface that we can unload the driver for.
34
35  Retrieves a dict containing the name of a network interface
36  that can quite likely be removed using the "rmmod" command,
37  and the name of the module used to load the driver.
38
39  @param typelist An iterable of interface prefixes to filter from. Only
40                  return an interface that matches one of these prefixes
41  @return Dict containing a 'intf' key with the interface name
42          and a 'wlan' key with the kernel module name for the driver.
43
44  """
45  interface_list = GetInterfaceList()
46  # Slice through the interfaces on a per-prefix basis priority order.
47  for prefix in typelist:
48    for intf in interface_list:
49      if intf.startswith(prefix):
50        driver = FindDriver(intf)
51        if driver is not None:
52          return {'intf': intf, 'driver': driver}
53
54  logging.debug('Could not find an interface')
55
56
57def RestartInterface():
58  """Find and restart a network interface using "rmmod" and "modprobe".
59
60  This function simulates a device eject and re-insert.
61
62  @return True if successful, or if nothing was done
63  """
64  interface = FindInterface()
65  if interface is None:
66    logging.debug('No interface available for test')
67    # We return success although we haven't done anything!
68    return True
69
70  logging.debug('Using %s for restart', str(interface))
71
72  try:
73    utils.system('rmmod %s' % interface['driver'])
74  except error.CmdError, e:
75    logging.debug(e)
76
77  try:
78    utils.system('modprobe %s' % interface['driver'])
79  except error.CmdError, e:
80    logging.debug(e)
81    raise error.TestFail('Failed to reload driver %s' % interface['driver'])
82
83  return True
84
85
86def Upstart(service, action='status'):
87  """Front-end to the 'initctl' command.
88
89  Accepts arguments to initctl and executes them, raising an exception
90  if it fails.
91
92  @param service Service name to call initctl with.
93  @param action Action to perform on the service
94
95  @return The returned service status from initctl
96  """
97  if action not in ('status', 'start', 'stop'):
98    logging.debug('Bad action')
99    return None
100
101  try:
102    status_str = utils.system_output('initctl %s %s' % (action, service))
103    status_list = status_str.split(' ')
104  except error.CmdError, e:
105    logging.debug(e)
106    raise error.TestFail('Failed to perform %s on service %s' %
107                         (action, service))
108
109  if status_list[0] != service:
110    return None
111
112  return status_list[1].rstrip(',\n')
113
114
115def RestartUdev():
116  """Restarts the udev service.
117
118  Stops and then restarts udev
119
120  @return True if successful
121  """
122  if Upstart('udev') != 'start/running':
123    raise error.TestFail('udev not running')
124
125  if Upstart('udev', 'stop') != 'stop/waiting':
126    raise error.TestFail('could not stop udev')
127
128  if Upstart('udev', 'start') != 'start/running':
129    raise error.TestFail('could not restart udev')
130
131  if Upstart('udev') != 'start/running':
132    raise error.TestFail('udev failed to stay running')
133
134  return True
135
136
137def TestUdevDeviceList(restart_fn):
138  """Test interface list.
139
140  Performs an operation, then compares the network interface list between
141  a time before the test and after.  Raises an exception if the list changes.
142
143  @param restart_fn The function that performs the operation of interest
144  """
145  iflist_pre = GetInterfaceList()
146  if not restart_fn():
147    raise error.TestFail('Reset function failed')
148
149  # Debugging for crbug.com/418983,423741,424605,425066 added the loop to see
150  # if it takes more than 3 attempts for all of the interfaces to come back up.
151  for i in range(3):
152    # We need to wait for udev to rename (or not) the interface!
153    time.sleep(10)
154
155    iflist_post = GetInterfaceList()
156
157    if iflist_post == iflist_pre:
158      logging.debug('Interfaces remain the same after %s; number of tries: %d',
159                    restart_fn.__name__, i)
160      return
161
162  raise error.TestFail('Interfaces changed after %s (%s != %s)' %
163                       (restart_fn.__name__, str(iflist_pre),
164                        str(iflist_post)))
165
166
167class network_UdevRename(test.test):
168  """Test that network devices are not renamed unexpectedly"""
169  version = 1
170
171  def run_once(self):
172    TestUdevDeviceList(RestartUdev)
173    TestUdevDeviceList(RestartInterface)
174