blob: b34e140c458c2aa673be4770e0d8c7fd1910134b [file] [log] [blame]
Kris Rambish3fe58122013-07-30 19:55:20 -07001# Copyright (c) 2013 The Chromium 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
Christopher Wileyf9cb0922013-11-01 09:12:21 -07005from autotest_lib.client.common_lib.cros.network import iw_runner
6
bmahadevc3d2c3b2013-10-28 18:46:09 -07007
Kris Rambish3fe58122013-07-30 19:55:20 -07008# Supported bands
bmahadev72de0462014-03-12 17:46:46 -07009BAND_2GHZ = '2.4GHz'
10BAND_5GHZ = '5GHz'
Kris Rambish3fe58122013-07-30 19:55:20 -070011
12# List of valid bands.
13VALID_BANDS = [BAND_2GHZ, BAND_5GHZ]
14
15# List of valid 802.11 protocols (modes).
16MODE_A = 0x01
17MODE_B = 0x02
18MODE_G = 0x04
19MODE_N = 0x08
Tien Changcdae79e2016-02-01 16:04:04 -080020MODE_AC = 0x10
21MODE_AUTO = 0x20
Kris Rambish3fe58122013-07-30 19:55:20 -070022MODE_M = MODE_A | MODE_B | MODE_G # Used for standard maintenance
23MODE_D = MODE_A | MODE_B | MODE_N # International roaming extensions
Ashakiran Byrappa54c3f912016-06-14 14:40:04 -070024MODE_B_G = MODE_B | MODE_G
25MODE_B_G_N = MODE_B | MODE_G | MODE_N
26MODE_AC_N = MODE_AC | MODE_N
27MODE_A_N = MODE_A | MODE_N
Kris Rambish3fe58122013-07-30 19:55:20 -070028
29# List of valid modes.
Tien Changcdae79e2016-02-01 16:04:04 -080030VALID_MODES = [MODE_A, MODE_AC, MODE_AUTO, MODE_B, MODE_D, MODE_G, MODE_M,
Ashakiran Byrappa54c3f912016-06-14 14:40:04 -070031 MODE_N, MODE_B_G, MODE_B_G_N, MODE_A_N, MODE_AC_N]
32VALID_2GHZ_MODES = [MODE_B, MODE_G, MODE_N, MODE_B_G, MODE_B_G_N]
33VALID_5GHZ_MODES = [MODE_A, MODE_AC, MODE_N, MODE_A_N, MODE_AC_N]
Kris Rambish3fe58122013-07-30 19:55:20 -070034
35# Supported security types
bmahadevc3d2c3b2013-10-28 18:46:09 -070036SECURITY_TYPE_DISABLED = iw_runner.SECURITY_OPEN
37SECURITY_TYPE_WEP = iw_runner.SECURITY_WEP
38SECURITY_TYPE_WPAPSK = iw_runner.SECURITY_WPA
39SECURITY_TYPE_WPA2PSK = iw_runner.SECURITY_WPA2
40# Mixed mode security is wpa/wpa2
41SECURITY_TYPE_MIXED = iw_runner.SECURITY_MIXED
Kris Rambish3fe58122013-07-30 19:55:20 -070042
Kris Rambishc43f4dd2013-12-17 15:57:13 -080043WEP_AUTHENTICATION_OPEN = object()
44WEP_AUTHENTICATION_SHARED = object()
Kris Rambish3fe58122013-07-30 19:55:20 -070045
46# List of valid securities.
47# TODO (krisr) the configurators do not support WEP at this time.
48VALID_SECURITIES = [SECURITY_TYPE_DISABLED,
49 SECURITY_TYPE_WPAPSK,
Godofredo Contreras9be7c5c2016-04-29 10:25:55 -070050 SECURITY_TYPE_WPA2PSK,
51 SECURITY_TYPE_MIXED,
52 SECURITY_TYPE_WEP]
Kris Rambish3fe58122013-07-30 19:55:20 -070053
54# List of valid channels.
Kris Rambishd751a4f2013-08-23 12:25:13 -070055VALID_2GHZ_CHANNELS = range(1,15)
Kris Rambish3fe58122013-07-30 19:55:20 -070056VALID_5GHZ_CHANNELS = [36, 40, 44, 48, 149, 153, 157, 161, 165]
57
Kris Rambish506a99d2013-10-08 19:19:13 -070058# Frequency to channel conversion table
59CHANNEL_TABLE = {2412: 1, 2417: 2, 2422: 3,
60 2427: 4, 2432: 5, 2437: 6,
61 2442: 7, 2447: 8, 2452: 9,
62 2457: 10, 2462: 11, 2467: 12,
63 2472: 13, 2484: 14, 5180: 36,
64 5200: 40, 5220: 44, 5240: 48,
65 5745: 149, 5765: 153, 5785: 157,
66 5805: 161, 5825: 165}
67
68# This only works because the frequency table is one to one
69# for channels/frequencies.
70FREQUENCY_TABLE = dict((v,k) for k,v in CHANNEL_TABLE.iteritems())
71
Kris Rambish045d4172014-01-08 16:31:53 -080072# Configurator type
bmahadev72de0462014-03-12 17:46:46 -070073CONFIGURATOR_STATIC = 1
74CONFIGURATOR_DYNAMIC = 2
75CONFIGURATOR_ANY = 3
Kris Rambishc43f4dd2013-12-17 15:57:13 -080076
Kris Rambish3fe58122013-07-30 19:55:20 -070077# Default values
78DEFAULT_BAND = BAND_2GHZ
79
harpreet23370612018-11-16 17:22:19 -080080DEFAULT_2GHZ_MODE = MODE_N
81DEFAULT_5GHZ_MODE = MODE_AC_N
Kris Rambish3fe58122013-07-30 19:55:20 -070082
harpreet23370612018-11-16 17:22:19 -080083DEFAULT_SECURITY_TYPE = SECURITY_TYPE_WPA2PSK
Kris Rambish3fe58122013-07-30 19:55:20 -070084
harpreet23370612018-11-16 17:22:19 -080085DEFAULT_2GHZ_CHANNEL = 6
Kris Rambish3fe58122013-07-30 19:55:20 -070086DEFAULT_5GHZ_CHANNEL = 149
87
Kris Rambishc1ae75b2013-12-20 17:38:58 -080088# Convenience method to convert modes and bands to human readable strings.
89def band_string_for_band(band):
90 """Returns a human readable string of the band
91
92 @param band: band object
93 @returns: string representation of the band
Kris Rambish3fe58122013-07-30 19:55:20 -070094 """
Kris Rambishc1ae75b2013-12-20 17:38:58 -080095 if band == BAND_2GHZ:
96 return '2.4 GHz'
97 elif band == BAND_5GHZ:
98 return '5 GHz'
99
100
101def mode_string_for_mode(mode):
102 """Returns a human readable string of the mode.
Kris Rambish3fe58122013-07-30 19:55:20 -0700103
104 @param mode: integer, the mode to convert.
105 @returns: string representation of the mode
106 """
Tien Changcdae79e2016-02-01 16:04:04 -0800107 string_table = {MODE_A:'a', MODE_AC:'ac', MODE_B:'b', MODE_G:'g',
108 MODE_N:'n'}
Kris Rambish3fe58122013-07-30 19:55:20 -0700109
110 if mode == MODE_AUTO:
111 return 'Auto'
112 total = 0
113 string = ''
114 for current_mode in sorted(string_table.keys()):
115 i = current_mode & mode
116 total = total | i
117 if i in string_table:
118 string = string + string_table[i] + '/'
119 if total == MODE_M:
120 string = 'm'
121 elif total == MODE_D:
122 string = 'd'
123 if string[-1] == '/':
124 return string[:-1]
125 return string
126
127
128class APSpec(object):
129 """Object to specify an APs desired capabilities.
130
131 The APSpec object is immutable. All of the parameters are optional.
132 For those not given the defaults listed above will be used. Validation
133 is done on the values to make sure the spec created is valid. If
134 validation fails a ValueError is raised.
Kris Rambish3fe58122013-07-30 19:55:20 -0700135 """
136
137
harpreet23370612018-11-16 17:22:19 -0800138 def __init__(self, visible=True, security=SECURITY_TYPE_WPA2PSK,
Kris Rambishc43f4dd2013-12-17 15:57:13 -0800139 band=None, mode=None, channel=None, hostnames=None,
Kris Rambish045d4172014-01-08 16:31:53 -0800140 configurator_type=CONFIGURATOR_ANY,
Roshan Pius22093e32015-04-14 15:01:58 -0700141 # lab_ap set to true means the AP must be in the lab;
142 # if it set to false the AP is outside of the lab.
Kris Rambish045d4172014-01-08 16:31:53 -0800143 lab_ap=True):
Kris Rambish3fe58122013-07-30 19:55:20 -0700144 super(APSpec, self).__init__()
145 self._visible = visible
146 self._security = security
147 self._mode = mode
148 self._channel = channel
Kris Rambish506a99d2013-10-08 19:19:13 -0700149 self._hostnames = hostnames
Kris Rambishc43f4dd2013-12-17 15:57:13 -0800150 self._configurator_type = configurator_type
Kris Rambish045d4172014-01-08 16:31:53 -0800151 self._lab_ap = lab_ap
Tien Changd2ae9742015-06-03 20:26:26 -0700152 self._webdriver_hostname = None
Kris Rambish3fe58122013-07-30 19:55:20 -0700153
Kris Rambish97264b52013-11-25 18:54:36 -0800154 if not self._channel and (self._mode == MODE_N or not self._mode):
Kris Rambish3fe58122013-07-30 19:55:20 -0700155 if band == BAND_2GHZ or not band:
156 self._channel = DEFAULT_2GHZ_CHANNEL
Kris Rambish97264b52013-11-25 18:54:36 -0800157 if not self._mode:
158 self._mode = DEFAULT_2GHZ_MODE
Kris Rambish3fe58122013-07-30 19:55:20 -0700159 elif band == BAND_5GHZ:
160 self._channel = DEFAULT_5GHZ_CHANNEL
Kris Rambish97264b52013-11-25 18:54:36 -0800161 if not self._mode:
162 self._mode = DEFAULT_5GHZ_MODE
Kris Rambish3fe58122013-07-30 19:55:20 -0700163 else:
164 raise ValueError('Invalid Band.')
165
166 self._validate_channel_and_mode()
167
168 if ((band == BAND_2GHZ and self._mode not in VALID_2GHZ_MODES) or
harpreet23370612018-11-16 17:22:19 -0800169 (band == BAND_5GHZ and self._mode not in VALID_5GHZ_MODES) or
170 (band == BAND_2GHZ and self._channel not in VALID_2GHZ_CHANNELS) or
171 (band == BAND_5GHZ and self._channel not in VALID_5GHZ_CHANNELS)):
Kris Rambish3fe58122013-07-30 19:55:20 -0700172 raise ValueError('Conflicting band and modes/channels.')
173
174 self._validate_security()
Kris Rambish3fe58122013-07-30 19:55:20 -0700175
Kris Rambish3fe58122013-07-30 19:55:20 -0700176
177 def __str__(self):
178 return ('AP Specification:\n'
179 'visible=%r\n'
180 'security=%s\n'
181 'band=%s\n'
182 'mode=%s\n'
183 'channel=%d\n'
Kris Rambishc1ae75b2013-12-20 17:38:58 -0800184 'password=%s' % (self._visible, self._security,
185 band_string_for_band(self.band),
186 mode_string_for_mode(self._mode),
187 self._channel, self._password))
Kris Rambish3fe58122013-07-30 19:55:20 -0700188
189
190 @property
191 def password(self):
192 """Returns the password for password supported secured networks."""
193 return self._password
194
195
Kris Rambish3fe58122013-07-30 19:55:20 -0700196
197 @property
198 def visible(self):
199 """Returns if the SSID is visible or not."""
200 return self._visible
201
202
203 @property
204 def security(self):
205 """Returns the type of security."""
206 return self._security
207
208
209 @property
210 def band(self):
211 """Return the band."""
212 if self._channel in VALID_2GHZ_CHANNELS:
213 return BAND_2GHZ
214 return BAND_5GHZ
215
216
217 @property
218 def mode(self):
219 """Return the mode."""
220 return self._mode
221
222
223 @property
224 def channel(self):
225 """Return the channel."""
226 return self._channel
227
228
229 @property
Kris Rambish506a99d2013-10-08 19:19:13 -0700230 def frequency(self):
231 """Return the frequency equivalent of the channel."""
232 return FREQUENCY_TABLE[self._channel]
233
234
235 @property
236 def hostnames(self):
237 """Return the hostnames; this may be None."""
238 return self._hostnames
239
240
Kris Rambishc43f4dd2013-12-17 15:57:13 -0800241 @property
242 def configurator_type(self):
243 """Returns the configurator type."""
244 return self._configurator_type
245
246
Kris Rambish045d4172014-01-08 16:31:53 -0800247 @property
248 def lab_ap(self):
249 """Returns if the AP should be in the lab or not."""
250 return self._lab_ap
251
252
Tien Changd2ae9742015-06-03 20:26:26 -0700253 @property
254 def webdriver_hostname(self):
255 """Returns locked webdriver hostname."""
256 return self._webdriver_hostname
257
258
259 @webdriver_hostname.setter
260 def webdriver_hostname(self, value):
261 """Sets webdriver_hostname to locked instance.
262
263 @param value: locked webdriver hostname
264
265 """
266 self._webdriver_hostname = value
267
268
Kris Rambish3fe58122013-07-30 19:55:20 -0700269 def _validate_channel_and_mode(self):
270 """Validates the channel and mode selected are correct.
271
272 raises ValueError: if the channel or mode selected is invalid
273 """
274 if self._channel and self._mode:
275 if ((self._channel in VALID_2GHZ_CHANNELS and
276 self._mode not in VALID_2GHZ_MODES) or
277 (self._channel in VALID_5GHZ_CHANNELS and
278 self._mode not in VALID_5GHZ_MODES)):
279 raise ValueError('Conflicting mode/channel has been selected.')
280 elif self._channel:
281 if self._channel in VALID_2GHZ_CHANNELS:
282 self._mode = DEFAULT_2GHZ_MODE
283 elif self._channel in VALID_5GHZ_CHANNELS:
284 self._mode = DEFAULT_5GHZ_MODE
285 else:
286 raise ValueError('Invalid channel passed.')
287 else:
288 if self._mode in VALID_2GHZ_MODES:
289 self._channel = DEFAULT_2GHZ_CHANNEL
290 elif self._mode in VALID_5GHZ_MODES:
291 self._channel = DEFAULT_5GHZ_CHANNEL
292 else:
293 raise ValueError('Invalid mode passed.')
294
295
296 def _validate_security(self):
297 """Sets a password for security settings that need it.
298
299 raises ValueError: if the security setting passed is invalid.
300 """
301 if self._security == SECURITY_TYPE_DISABLED:
302 self._password = None
303 elif (self._security == SECURITY_TYPE_WPAPSK or
Godofredo Contreras9be7c5c2016-04-29 10:25:55 -0700304 self._security == SECURITY_TYPE_WPA2PSK or
305 self._security == SECURITY_TYPE_MIXED):
Kris Rambish3fe58122013-07-30 19:55:20 -0700306 self._password = 'chromeos'
Godofredo Contreras9be7c5c2016-04-29 10:25:55 -0700307 elif (self._security==SECURITY_TYPE_WEP):
308 self._password = 'chros'
Kris Rambish3fe58122013-07-30 19:55:20 -0700309 else:
310 raise ValueError('Invalid security passed.')