blob: 8a1d1487412b8014d6d36d508f7660c50ffe22a3 [file] [log] [blame]
Sam Leffler6969d1d2010-03-15 16:07:11 -07001# 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
Paul Stewart310928c2010-09-07 11:54:11 -07005import logging, re, time
Paul Stewartc9628b32010-08-11 13:03:51 -07006from autotest_lib.client.common_lib import error
Paul Stewart2ee7fdf2011-05-19 16:29:23 -07007from autotest_lib.server import site_linux_system
Sam Leffler19bb0a72010-04-12 08:51:08 -07008
9def isLinuxRouter(router):
10 router_uname = router.run('uname').stdout
11 return re.search('Linux', router_uname)
12
Paul Stewart2ee7fdf2011-05-19 16:29:23 -070013class LinuxRouter(site_linux_system.LinuxSystem):
Sam Leffler6969d1d2010-03-15 16:07:11 -070014 """
15 Linux/mac80211-style WiFi Router support for WiFiTest class.
16
17 This class implements test methods/steps that communicate with a
18 router implemented with Linux/mac80211. The router must
19 be pre-configured to enable ssh access and have a mac80211-based
20 wireless device. We also assume hostapd 0.7.x and iw are present
21 and any necessary modules are pre-loaded.
22 """
23
24
25 def __init__(self, host, params, defssid):
Paul Stewart2ee7fdf2011-05-19 16:29:23 -070026 site_linux_system.LinuxSystem.__init__(self, host, params, "router")
mukesh agrawalfe0e85b2011-08-09 14:24:15 -070027 self._remove_interfaces()
Paul Stewart2ee7fdf2011-05-19 16:29:23 -070028
Wade Guthrie24d1e312012-04-24 16:53:40 -070029 # Router host.
30 self.router = host
31
32 self.cmd_hostapd = self.__must_be_installed(host,
33 params.get("cmd_hostapd", "/usr/sbin/hostapd"))
mukesh agrawalfe0e85b2011-08-09 14:24:15 -070034 self.cmd_hostapd_cli = \
35 params.get("cmd_hostapd_cli", "/usr/sbin/hostapd_cli")
Paul Stewart326badb2012-12-18 14:18:54 -080036 self.dhcpd_conf = "/tmp/dhcpd.%s.conf"
mukesh agrawalfe0e85b2011-08-09 14:24:15 -070037 self.dhcpd_leases = "/tmp/dhcpd.leases"
Nebojsa Sabovic138ff912010-04-06 15:47:42 -070038
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -070039 # hostapd configuration persists throughout the test, subsequent
40 # 'config' commands only modify it.
Paul Stewart7cb1f062010-06-10 15:46:20 -070041 self.defssid = defssid
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -070042 self.hostapd = {
43 'configured': False,
Paul Stewart326badb2012-12-18 14:18:54 -080044 'config_file': "/tmp/hostapd-test-%s.conf",
45 'log_file': "/tmp/hostapd-test-%s.log",
Paul Stewartf854d2e2011-05-04 13:19:18 -070046 'log_count': 0,
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -070047 'driver': "nl80211",
48 'conf': {
49 'ssid': defssid,
Paul Stewartaa52e8c2011-05-24 08:46:23 -070050 'hw_mode': 'g',
mukesh agrawal05c455a2011-10-12 13:40:27 -070051 'ctrl_interface': '/tmp/hostapd-test.control',
52 'logger_syslog': '-1',
53 'logger_syslog_level': '0'
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -070054 }
55 }
Paul Stewartc2b3de82011-03-03 14:45:31 -080056 self.station = {
57 'configured': False,
58 'conf': {
59 'ssid': defssid,
Paul Stewartf05d7fd2011-04-06 16:19:37 -070060 },
Paul Stewartc2b3de82011-03-03 14:45:31 -080061 }
mukesh agrawalfe0e85b2011-08-09 14:24:15 -070062 self.local_servers = []
Paul Stewart548cf452012-11-27 17:46:23 -080063 self.hostapd_instances = []
mukesh agrawalfe0e85b2011-08-09 14:24:15 -070064 self.force_local_server = "force_local_server" in params
65 self.dhcp_low = 1
66 self.dhcp_high = 128
Paul Stewartf05d7fd2011-04-06 16:19:37 -070067
Paul Stewart548cf452012-11-27 17:46:23 -080068 # Kill hostapd and dhcp server if already running.
Thieu Le7b23a542012-01-27 15:54:48 -080069 self.kill_hostapd()
Paul Stewart548cf452012-11-27 17:46:23 -080070 self.stop_dhcp_servers()
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -070071
Nebojsa Sabovicbc245c62010-04-28 16:58:50 -070072 # Place us in the US by default
73 self.router.run("%s reg set US" % self.cmd_iw)
Sam Leffler6969d1d2010-03-15 16:07:11 -070074
Wade Guthrie24d1e312012-04-24 16:53:40 -070075 def __must_be_installed(self, host, cmd):
76 if not self.__is_installed(host, cmd):
77 raise error.TestFail('Unable to find %s on %s' % (cmd, host.ip))
78 return cmd
79
80 def __is_installed(self, host, filename):
81 result = host.run("ls %s" % filename, ignore_status=True)
82 m = re.search(filename, result.stdout)
83 return m is not None
84
Paul Stewartf05d7fd2011-04-06 16:19:37 -070085
Sam Leffler6969d1d2010-03-15 16:07:11 -070086 def create(self, params):
87 """ Create a wifi device of the specified type """
88 #
89 # AP mode is handled entirely by hostapd so we only
90 # have to setup others (mapping the bsd type to what
91 # iw wants)
92 #
93 # map from bsd types to iw types
Paul Stewartc2b3de82011-03-03 14:45:31 -080094 self.apmode = params['type'] in ("ap", "hostap")
95 if not self.apmode:
96 self.station['type'] = params['type']
Paul Stewart2ee7fdf2011-05-19 16:29:23 -070097 self.phytype = {
Sam Leffler6969d1d2010-03-15 16:07:11 -070098 "sta" : "managed",
99 "monitor" : "monitor",
100 "adhoc" : "adhoc",
101 "ibss" : "ibss",
Nebojsa Sabovic138ff912010-04-06 15:47:42 -0700102 "ap" : "managed", # NB: handled by hostapd
103 "hostap" : "managed", # NB: handled by hostapd
Sam Leffler6969d1d2010-03-15 16:07:11 -0700104 "mesh" : "mesh",
105 "wds" : "wds",
106 }[params['type']]
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700107
Sam Leffler6969d1d2010-03-15 16:07:11 -0700108
109 def destroy(self, params):
110 """ Destroy a previously created device """
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700111 # For linux, this is the same as deconfig.
112 self.deconfig(params)
113
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700114 def has_local_server(self):
115 return bool(self.local_servers)
Sam Leffler6969d1d2010-03-15 16:07:11 -0700116
Paul Stewart9e3ff0b2011-08-17 20:35:19 -0700117 def cleanup(self, params):
118 """ Clean up any resources in use """
119 # For linux, this is a no-op
120 pass
121
Paul Stewart548cf452012-11-27 17:46:23 -0800122 def start_hostapd(self, conf, params):
Paul Stewart548cf452012-11-27 17:46:23 -0800123 # Figure out the correct interface.
Paul Stewart326badb2012-12-18 14:18:54 -0800124 interface = self._get_wlanif(self.hostapd['frequency'],
125 self.phytype,
126 mode=conf.get('hw_mode', 'b'))
127
128 conf_file = self.hostapd['config_file'] % interface
129 log_file = self.hostapd['log_file'] % interface
130 conf['interface'] = interface
Paul Stewart548cf452012-11-27 17:46:23 -0800131
132 # Generate hostapd.conf.
133 self._pre_config_hook(conf)
134 self.router.run("cat <<EOF >%s\n%s\nEOF\n" %
135 (conf_file, '\n'.join(
136 "%s=%s" % kv for kv in conf.iteritems())))
137
138 # Run hostapd.
139 logging.info("Starting hostapd...")
140 self._pre_start_hook(params)
141 self.router.run("%s -dd %s &> %s &" %
142 (self.cmd_hostapd, conf_file, log_file))
143
144 self.hostapd_instances.append({
145 'conf_file': conf_file,
146 'log_file': log_file,
Paul Stewart326badb2012-12-18 14:18:54 -0800147 'interface': interface
Paul Stewart548cf452012-11-27 17:46:23 -0800148 })
149
Paul Stewart326badb2012-12-18 14:18:54 -0800150 def _kill_process_instance(self, process, instance=None, wait=0):
Thieu Le7b23a542012-01-27 15:54:48 -0800151 """
Paul Stewart326badb2012-12-18 14:18:54 -0800152 Kills program named |process|, optionally only a specific
153 |instance|. If |wait| is specified, we makes sure |process| exits
154 before returning.
Thieu Le7b23a542012-01-27 15:54:48 -0800155 """
Paul Stewart21737812012-12-06 11:03:32 -0800156 if instance:
Paul Stewart326badb2012-12-18 14:18:54 -0800157 search_arg = '-f "%s.*%s"' % (process, instance)
Paul Stewart21737812012-12-06 11:03:32 -0800158 else:
Paul Stewart326badb2012-12-18 14:18:54 -0800159 search_arg = process
Paul Stewart21737812012-12-06 11:03:32 -0800160
Paul Stewart326badb2012-12-18 14:18:54 -0800161 cmd = "pkill %s >/dev/null 2>&1" % search_arg
162
163 if wait:
164 cmd += (" && while pgrep %s &> /dev/null; do sleep 1; done" %
165 search_arg)
166 self.router.run(cmd, timeout=wait, ignore_status=True)
167 else:
168 self.router.run(cmd, ignore_status=True)
169
170 def kill_hostapd_instance(self, instance):
171 self._kill_process_instance('hostapd', instance, 30)
Thieu Le7b23a542012-01-27 15:54:48 -0800172
Paul Stewart21737812012-12-06 11:03:32 -0800173 def kill_hostapd(self):
174 self.kill_hostapd_instance(None)
175
Paul Stewartc2b3de82011-03-03 14:45:31 -0800176 def hostap_config(self, params):
Sam Leffler6969d1d2010-03-15 16:07:11 -0700177 """ Configure the AP per test requirements """
178
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700179 # keep parameter modifications local-only
180 orig_params = params
181 params = params.copy()
182
Paul Stewart45338d22010-10-21 10:57:02 -0700183 multi_interface = 'multi_interface' in params
184 if multi_interface:
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700185 # remove non-hostapd config item from params
Paul Stewart45338d22010-10-21 10:57:02 -0700186 params.pop('multi_interface')
Paul Stewartc2b3de82011-03-03 14:45:31 -0800187 elif self.hostapd['configured'] or self.station['configured']:
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700188 self.deconfig({})
189
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700190 local_server = params.pop('local_server', False)
191
Paul Stewartc2b3de82011-03-03 14:45:31 -0800192 # Construct the hostapd.conf file and start hostapd.
193 conf = self.hostapd['conf']
Sam Lefflerbf5af622011-10-21 12:11:17 -0700194 # default RTS and frag threshold to ``off''
195 conf['rts_threshold'] = '2347'
196 conf['fragm_threshold'] = '2346'
197
Paul Stewartc2b3de82011-03-03 14:45:31 -0800198 tx_power_params = {}
199 htcaps = set()
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700200
Paul Stewartc2b3de82011-03-03 14:45:31 -0800201 conf['driver'] = params.get('hostapd_driver',
202 self.hostapd['driver'])
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700203
Paul Stewartc2b3de82011-03-03 14:45:31 -0800204 for k, v in params.iteritems():
205 if k == 'ssid':
206 conf['ssid'] = v
207 elif k == 'ssid_suffix':
Paul Stewart05cebab2012-05-29 11:58:17 -0700208 conf['ssid'] = self.defssid[:(32-len(v))] + v
Paul Stewartc2b3de82011-03-03 14:45:31 -0800209 elif k == 'channel':
210 freq = int(v)
Paul Stewart2ee7fdf2011-05-19 16:29:23 -0700211 self.hostapd['frequency'] = freq
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700212
Paul Stewartc2b3de82011-03-03 14:45:31 -0800213 # 2.4GHz
214 if freq <= 2484:
215 # Make sure hw_mode is set
216 if conf.get('hw_mode') == 'a':
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700217 conf['hw_mode'] = 'g'
Paul Stewartc2b3de82011-03-03 14:45:31 -0800218
219 # Freq = 5 * chan + 2407, except channel 14
220 if freq == 2484:
221 conf['channel'] = 14
222 else:
223 conf['channel'] = (freq - 2407) / 5
224 # 5GHz
Sam Leffler6969d1d2010-03-15 16:07:11 -0700225 else:
Paul Stewartc2b3de82011-03-03 14:45:31 -0800226 # Make sure hw_mode is set
227 conf['hw_mode'] = 'a'
228 # Freq = 5 * chan + 4000
229 if freq < 5000:
230 conf['channel'] = (freq - 4000) / 5
231 # Freq = 5 * chan + 5000
232 else:
233 conf['channel'] = (freq - 5000) / 5
Sam Leffler6969d1d2010-03-15 16:07:11 -0700234
Paul Stewartc2b3de82011-03-03 14:45:31 -0800235 elif k == 'country':
236 conf['country_code'] = v
237 elif k == 'dotd':
238 conf['ieee80211d'] = 1
239 elif k == '-dotd':
240 conf['ieee80211d'] = 0
241 elif k == 'mode':
242 if v == '11a':
243 conf['hw_mode'] = 'a'
244 elif v == '11g':
245 conf['hw_mode'] = 'g'
246 elif v == '11b':
247 conf['hw_mode'] = 'b'
248 elif v == '11n':
249 conf['ieee80211n'] = 1
250 elif k == 'bintval':
251 conf['beacon_int'] = v
252 elif k == 'dtimperiod':
253 conf['dtim_period'] = v
254 elif k == 'rtsthreshold':
255 conf['rts_threshold'] = v
256 elif k == 'fragthreshold':
257 conf['fragm_threshold'] = v
258 elif k == 'shortpreamble':
259 conf['preamble'] = 1
260 elif k == 'authmode':
261 if v == "open":
262 conf['auth_algs'] = 1
263 elif v == "shared":
264 conf['auth_algs'] = 2
265 elif k == 'hidessid':
266 conf['ignore_broadcast_ssid'] = 1
267 elif k == 'wme':
268 conf['wmm_enabled'] = 1
269 elif k == '-wme':
270 conf['wmm_enabled'] = 0
271 elif k == 'deftxkey':
272 conf['wep_default_key'] = v
273 elif k == 'ht20':
274 htcaps.add('') # NB: ensure 802.11n setup below
275 conf['wmm_enabled'] = 1
276 elif k == 'ht40':
277 htcaps.add('[HT40-]')
278 htcaps.add('[HT40+]')
279 conf['wmm_enabled'] = 1
Paul Stewartc1df8d62011-04-07 14:28:15 -0700280 elif k in ('ht40+', 'ht40-'):
281 htcaps.add('[%s]' % k.upper())
282 conf['wmm_enabled'] = 1
Paul Stewartc2b3de82011-03-03 14:45:31 -0800283 elif k == 'shortgi':
284 htcaps.add('[SHORT-GI-20]')
285 htcaps.add('[SHORT-GI-40]')
286 elif k == 'pureg':
287 pass # TODO(sleffler) need hostapd support
288 elif k == 'puren':
289 pass # TODO(sleffler) need hostapd support
290 elif k == 'protmode':
291 pass # TODO(sleffler) need hostapd support
292 elif k == 'ht':
293 htcaps.add('') # NB: ensure 802.11n setup below
294 elif k == 'htprotmode':
295 pass # TODO(sleffler) need hostapd support
296 elif k == 'rifs':
297 pass # TODO(sleffler) need hostapd support
298 elif k == 'wepmode':
299 pass # NB: meaningless for hostapd; ignore
300 elif k == '-ampdu':
301 pass # TODO(sleffler) need hostapd support
302 elif k == 'txpower':
303 tx_power_params['power'] = v
Nebojsa Sabovic60ae1462010-05-07 16:14:45 -0700304 else:
Paul Stewartc2b3de82011-03-03 14:45:31 -0800305 conf[k] = v
Nebojsa Sabovic60ae1462010-05-07 16:14:45 -0700306
Paul Stewartc2b3de82011-03-03 14:45:31 -0800307 # Aggregate ht_capab.
308 if htcaps:
309 conf['ieee80211n'] = 1
310 conf['ht_capab'] = ''.join(htcaps)
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700311
Paul Stewart548cf452012-11-27 17:46:23 -0800312 self.start_hostapd(conf, orig_params)
Paul Stewart1ae854b2011-02-08 15:10:14 -0800313
Paul Stewartc2b3de82011-03-03 14:45:31 -0800314 # Configure transmit power
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700315 tx_power_params['interface'] = conf['interface']
Paul Stewartc2b3de82011-03-03 14:45:31 -0800316 self.set_txpower(tx_power_params)
Nebojsa Sabovic138ff912010-04-06 15:47:42 -0700317
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700318 if self.force_local_server or local_server is not False:
319 self.start_local_server(conf['interface'])
Sam Leffler6969d1d2010-03-15 16:07:11 -0700320
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700321 self._post_start_hook(orig_params)
322
323 logging.info("AP configured.")
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700324 self.hostapd['configured'] = True
Sam Leffler6969d1d2010-03-15 16:07:11 -0700325
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700326 @staticmethod
327 def ip_addr(netblock, idx):
Paul Stewartf05d7fd2011-04-06 16:19:37 -0700328 """
329 Simple IPv4 calculator. Takes host address in "IP/bits" notation
330 and returns netmask, broadcast address as well as integer offsets
331 into the address range.
332 """
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700333 addr_str,bits = netblock.split('/')
Paul Stewartf05d7fd2011-04-06 16:19:37 -0700334 addr = map(int, addr_str.split('.'))
335 mask_bits = (-1 << (32-int(bits))) & 0xffffffff
336 mask = [(mask_bits >> s) & 0xff for s in range(24, -1, -8)]
Paul Stewart5977da92011-06-01 19:14:08 -0700337 if idx == 'local':
338 return addr_str
339 elif idx == 'netmask':
Paul Stewartf05d7fd2011-04-06 16:19:37 -0700340 return '.'.join(map(str, mask))
341 elif idx == 'broadcast':
342 offset = [m ^ 0xff for m in mask]
343 else:
344 offset = [(idx >> s) & 0xff for s in range(24, -1, -8)]
345 return '.'.join(map(str, [(a & m) + o
346 for a, m, o in zip(addr, mask, offset)]))
347
348
Paul Stewartc2b3de82011-03-03 14:45:31 -0800349 def station_config(self, params):
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700350 # keep parameter modifications local-only
351 orig_params = params
352 params = params.copy()
353
354 if 'multi_interface' in params:
355 raise NotImplementedError("station with multi_interface")
356
357 if self.station['type'] != 'ibss':
358 raise NotImplementedError("non-ibss station")
359
360 if self.station['configured'] or self.hostapd['configured']:
Paul Stewartc2b3de82011-03-03 14:45:31 -0800361 self.deconfig({})
362
Paul Stewartf05d7fd2011-04-06 16:19:37 -0700363 local_server = params.pop('local_server', False)
Paul Stewart2ee7fdf2011-05-19 16:29:23 -0700364 mode = None
Paul Stewartc2b3de82011-03-03 14:45:31 -0800365 conf = self.station['conf']
366 for k, v in params.iteritems():
367 if k == 'ssid_suffix':
368 conf['ssid'] = self.defssid + v
369 elif k == 'channel':
370 freq = int(v)
371 if freq > 2484:
Paul Stewart2ee7fdf2011-05-19 16:29:23 -0700372 mode = 'a'
Paul Stewartc2b3de82011-03-03 14:45:31 -0800373 elif k == 'mode':
374 if v == '11a':
Paul Stewart2ee7fdf2011-05-19 16:29:23 -0700375 mode = 'a'
Paul Stewartc2b3de82011-03-03 14:45:31 -0800376 else:
377 conf[k] = v
378
Paul Stewart2ee7fdf2011-05-19 16:29:23 -0700379 interface = self._get_wlanif(freq, self.phytype, mode)
380
Paul Stewartc2b3de82011-03-03 14:45:31 -0800381 # Run interface configuration commands
382 for k, v in conf.iteritems():
383 if k != 'ssid':
384 self.router.run("%s dev %s set %s %s" %
385 (self.cmd_iw, interface, k, v))
386
387 # Connect the station
388 self.router.run("%s link set %s up" % (self.cmd_ip, interface))
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700389 self.router.run("%s dev %s ibss join %s %d" %
390 (self.cmd_iw, interface, conf['ssid'], freq))
Paul Stewartc2b3de82011-03-03 14:45:31 -0800391
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700392 if self.force_local_server or local_server is not False:
393 self.start_local_server(interface)
Paul Stewartc2b3de82011-03-03 14:45:31 -0800394
395 self.station['configured'] = True
396 self.station['interface'] = interface
397
398
Paul Stewart2bd823b2012-11-21 15:03:37 -0800399 def local_server_address(self, index):
400 return '%d.%d.%d.%d' % (192, 168, index, 254)
401
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700402 def start_local_server(self, interface):
403 logging.info("Starting up local server...")
404
405 if len(self.local_servers) >= 256:
406 raise error.TestFail('Exhausted available local servers')
407
Paul Stewart2bd823b2012-11-21 15:03:37 -0800408 netblock = '%s/24' % self.local_server_address(len(self.local_servers))
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700409
410 params = {}
411 params['netblock'] = netblock
412 params['subnet'] = self.ip_addr(netblock, 0)
413 params['netmask'] = self.ip_addr(netblock, 'netmask')
414 params['dhcp_range'] = ' '.join(
415 (self.ip_addr(netblock, self.dhcp_low),
416 self.ip_addr(netblock, self.dhcp_high)))
mukesh agrawal05c455a2011-10-12 13:40:27 -0700417 params['interface'] = interface
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700418
419 params['ip_params'] = ("%s broadcast %s dev %s" %
420 (netblock,
421 self.ip_addr(netblock, 'broadcast'),
422 interface))
423 self.local_servers.append(params)
424
425 self.router.run("%s addr flush %s" %
426 (self.cmd_ip, interface))
427 self.router.run("%s addr add %s" %
428 (self.cmd_ip, params['ip_params']))
429 self.router.run("%s link set %s up" %
430 (self.cmd_ip, interface))
Paul Stewart548cf452012-11-27 17:46:23 -0800431 self.start_dhcp_server(interface)
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700432
Paul Stewart548cf452012-11-27 17:46:23 -0800433 def start_dhcp_server(self, interface):
Paul Stewart326badb2012-12-18 14:18:54 -0800434 conf_file = self.dhcpd_conf % interface
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700435 dhcp_conf = '\n'.join(map(
436 lambda server_conf: \
437 "subnet %(subnet)s netmask %(netmask)s {\n" \
438 " range %(dhcp_range)s;\n" \
439 "}" % server_conf,
440 self.local_servers))
441 self.router.run("cat <<EOF >%s\n%s\nEOF\n" %
Paul Stewart326badb2012-12-18 14:18:54 -0800442 (conf_file,
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700443 '\n'.join(('ddns-update-style none;', dhcp_conf))))
444 self.router.run("touch %s" % self.dhcpd_leases)
445
446 self.router.run("pkill dhcpd >/dev/null 2>&1", ignore_status=True)
447 self.router.run("%s -q -cf %s -lf %s" %
Paul Stewart326badb2012-12-18 14:18:54 -0800448 (self.cmd_dhcpd, conf_file, self.dhcpd_leases))
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700449
450
Paul Stewart326badb2012-12-18 14:18:54 -0800451 def stop_dhcp_server(self, instance=None):
452 self._kill_process_instance('dhcpd', instance, 0)
453
Paul Stewart548cf452012-11-27 17:46:23 -0800454 def stop_dhcp_servers(self):
Paul Stewart326badb2012-12-18 14:18:54 -0800455 self.stop_dhcp_server(None)
Paul Stewart548cf452012-11-27 17:46:23 -0800456
457
Paul Stewartc2b3de82011-03-03 14:45:31 -0800458 def config(self, params):
459 if self.apmode:
460 self.hostap_config(params)
461 else:
462 self.station_config(params)
463
464
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700465 def get_wifi_ip(self, ap_num):
466 if self.local_servers:
467 return self.ip_addr(self.local_servers[ap_num]['netblock'],
468 'local')
469 else:
470 raise error.TestFail("No IP address assigned")
Paul Stewart5977da92011-06-01 19:14:08 -0700471
472
Sam Leffler6969d1d2010-03-15 16:07:11 -0700473 def deconfig(self, params):
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700474 """ De-configure the AP (will also bring wlan down) """
Sam Leffler6969d1d2010-03-15 16:07:11 -0700475
Paul Stewartc2b3de82011-03-03 14:45:31 -0800476 if not self.hostapd['configured'] and not self.station['configured']:
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700477 return
Sam Leffler6969d1d2010-03-15 16:07:11 -0700478
Paul Stewartc2b3de82011-03-03 14:45:31 -0800479 if self.hostapd['configured']:
Paul Stewart326badb2012-12-18 14:18:54 -0800480 local_servers = []
Paul Stewart21737812012-12-06 11:03:32 -0800481 if 'instance' in params:
482 instances = [ self.hostapd_instances.pop(params['instance']) ]
Paul Stewart326badb2012-12-18 14:18:54 -0800483 for server in self.local_servers:
484 if server['interface'] == instances[0]['interface']:
485 local_servers = [server]
486 self.local_servers.remove(server)
487 break
Paul Stewart21737812012-12-06 11:03:32 -0800488 else:
489 instances = self.hostapd_instances
490 self.hostapd_instances = []
Paul Stewart326badb2012-12-18 14:18:54 -0800491 local_servers = self.local_servers
492 self.local_servers = []
Paul Stewart64cc4292011-06-01 10:59:36 -0700493
Paul Stewart21737812012-12-06 11:03:32 -0800494 for instance in instances:
495 if 'silent' in params:
496 # Deconfigure without notifying DUT. Remove the interface
497 # hostapd uses to send beacon and DEAUTH packets.
498 self._remove_interface(instance['interface'], True)
499
Paul Stewart326badb2012-12-18 14:18:54 -0800500 self.kill_hostapd_instance(instance['conf_file'])
Paul Stewart548cf452012-11-27 17:46:23 -0800501 self.router.get_file(instance['log_file'],
502 'debug/hostapd_router_%d_%s.log' %
503 (self.hostapd['log_count'],
504 instance['interface']))
505 self._release_wlanif(instance['interface'])
506# self.router.run("rm -f %(log_file)s %(conf_file)s" % instance)
Paul Stewartf854d2e2011-05-04 13:19:18 -0700507 self.hostapd['log_count'] += 1
Paul Stewartc2b3de82011-03-03 14:45:31 -0800508 if self.station['configured']:
509 if self.station['type'] == 'ibss':
510 self.router.run("%s dev %s ibss leave" %
511 (self.cmd_iw, self.station['interface']))
512 else:
513 self.router.run("%s dev %s disconnect" %
514 (self.cmd_iw, self.station['interface']))
515 self.router.run("%s link set %s down" % (self.cmd_ip,
516 self.station['interface']))
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700517
Paul Stewart326badb2012-12-18 14:18:54 -0800518 for server in local_servers:
519 self.stop_dhcp_server(server['interface'])
520 self.router.run("%s addr del %s" %
521 (self.cmd_ip, server['ip_params']),
522 ignore_status=True)
Nebojsa Sabovic4cc2ce92010-04-21 15:08:01 -0700523
524 self.hostapd['configured'] = False
Paul Stewartc2b3de82011-03-03 14:45:31 -0800525 self.station['configured'] = False
Paul Stewart7cb1f062010-06-10 15:46:20 -0700526
527
528 def get_ssid(self):
529 return self.hostapd['conf']['ssid']
Paul Stewart98022e22010-10-22 10:33:14 -0700530
531
532 def set_txpower(self, params):
Paul Stewart548cf452012-11-27 17:46:23 -0800533 interface = params.get('interface',
534 self.hostapd_instances[0]['interface'])
535 power = params.get('power', 'auto')
Paul Stewart98022e22010-10-22 10:33:14 -0700536 self.router.run("%s dev %s set txpower %s" %
Paul Stewart548cf452012-11-27 17:46:23 -0800537 (self.cmd_iw, interface, power))
Paul Stewartaa52e8c2011-05-24 08:46:23 -0700538
539
540 def deauth(self, params):
541 self.router.run('%s -p%s deauthenticate %s' %
542 (self.cmd_hostapd_cli,
543 self.hostapd['conf']['ctrl_interface'],
544 params['client']))
mukesh agrawalfe0e85b2011-08-09 14:24:15 -0700545
546
547 def _pre_config_hook(self, config):
548 """
549 Hook for subclasses. Run after gathering configuration parameters,
550 but before writing parameters to config file.
551 """
552 pass
553
554
555 def _pre_start_hook(self, params):
556 """
557 Hook for subclasses. Run after generating hostapd config file, but
558 before starting hostapd.
559 """
560 pass
561
562
563 def _post_start_hook(self, params):
564 """Hook for subclasses. Run after starting hostapd."""
565 pass