1#   Copyright 2017 - The Android Open Source Project
2#
3#   Licensed under the Apache License, Version 2.0 (the "License");
4#   you may not use this file except in compliance with the License.
5#   You may obtain a copy of the License at
6#
7#       http://www.apache.org/licenses/LICENSE-2.0
8#
9#   Unless required by applicable law or agreed to in writing, software
10#   distributed under the License is distributed on an "AS IS" BASIS,
11#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12#   See the License for the specific language governing permissions and
13#   limitations under the License.
14
15from acts import utils
16
17import acts.controllers.ap_lib.third_party_ap_profiles.actiontec as actiontec
18import acts.controllers.ap_lib.third_party_ap_profiles.asus as asus
19import acts.controllers.ap_lib.third_party_ap_profiles.belkin as belkin
20import acts.controllers.ap_lib.third_party_ap_profiles.linksys as linksys
21import acts.controllers.ap_lib.third_party_ap_profiles.netgear as netgear
22import acts.controllers.ap_lib.third_party_ap_profiles.securifi as securifi
23import acts.controllers.ap_lib.third_party_ap_profiles.tplink as tplink
24
25from acts.controllers.ap_lib import hostapd_config
26from acts.controllers.ap_lib import hostapd_constants
27from acts.controllers.ap_lib import hostapd_utils
28
29
30def _get_or_default(var, default_value):
31    """Check variable and return non-null value.
32
33   Args:
34        var: Any variable.
35        default_value: Value to return if the var is None.
36
37   Returns:
38        Variable value if not None, default value otherwise.
39    """
40    return var if var is not None else default_value
41
42
43def create_ap_preset(profile_name='whirlwind',
44                     iface_wlan_2g=None,
45                     iface_wlan_5g=None,
46                     channel=None,
47                     mode=None,
48                     frequency=None,
49                     security=None,
50                     ssid=None,
51                     hidden=None,
52                     dtim_period=None,
53                     frag_threshold=None,
54                     rts_threshold=None,
55                     force_wmm=None,
56                     beacon_interval=None,
57                     short_preamble=None,
58                     n_capabilities=None,
59                     ac_capabilities=None,
60                     vht_bandwidth=None,
61                     bss_settings=[]):
62    """AP preset config generator.  This a wrapper for hostapd_config but
63       but supplies the default settings for the preset that is selected.
64
65        You may specify channel or frequency, but not both.  Both options
66        are checked for validity (i.e. you can't specify an invalid channel
67        or a frequency that will not be accepted).
68
69    Args:
70        profile_name: The name of the device want the preset for.
71                      Options: whirlwind
72        channel: int, channel number.
73        dtim: int, DTIM value of the AP, default is 2.
74        frequency: int, frequency of channel.
75        security: Security, the secuirty settings to use.
76        ssid: string, The name of the ssid to brodcast.
77        vht_bandwidth: VHT bandwidth for 11ac operation.
78        bss_settings: The settings for all bss.
79        iface_wlan_2g: the wlan 2g interface name of the AP.
80        iface_wlan_5g: the wlan 5g interface name of the AP.
81        mode: The hostapd 802.11 mode of operation.
82        ssid: The ssid for the wireless network.
83        hidden: Whether to include the ssid in the beacons.
84        dtim_period: The dtim period for the BSS
85        frag_threshold: Max size of packet before fragmenting the packet.
86        rts_threshold: Max size of packet before requiring protection for
87            rts/cts or cts to self.
88        n_capabilities: 802.11n capabilities for for BSS to advertise.
89        ac_capabilities: 802.11ac capabilities for for BSS to advertise.
90
91    Returns: A hostapd_config object that can be used by the hostapd object.
92    """
93
94    # Verify interfaces
95    hostapd_utils.verify_interface(iface_wlan_2g,
96                                   hostapd_constants.INTERFACE_2G_LIST)
97    hostapd_utils.verify_interface(iface_wlan_5g,
98                                   hostapd_constants.INTERFACE_5G_LIST)
99
100    if channel:
101        frequency = hostapd_config.get_frequency_for_channel(channel)
102    elif frequency:
103        channel = hostapd_config.get_channel_for_frequency(frequency)
104    else:
105        raise ValueError('Specify either frequency or channel.')
106
107    if profile_name == 'whirlwind':
108        # profile indicates phy mode is 11bgn for 2.4Ghz or 11acn for 5Ghz
109        hidden = _get_or_default(hidden, False)
110        force_wmm = _get_or_default(force_wmm, True)
111        beacon_interval = _get_or_default(beacon_interval, 100)
112        short_preamble = _get_or_default(short_preamble, True)
113        dtim_period = _get_or_default(dtim_period, 2)
114        frag_threshold = _get_or_default(frag_threshold, 2346)
115        rts_threshold = _get_or_default(rts_threshold, 2347)
116        if frequency < 5000:
117            interface = iface_wlan_2g
118            mode = _get_or_default(mode, hostapd_constants.MODE_11N_MIXED)
119            n_capabilities = _get_or_default(n_capabilities, [
120                hostapd_constants.N_CAPABILITY_LDPC,
121                hostapd_constants.N_CAPABILITY_SGI20,
122                hostapd_constants.N_CAPABILITY_SGI40,
123                hostapd_constants.N_CAPABILITY_TX_STBC,
124                hostapd_constants.N_CAPABILITY_RX_STBC1,
125                hostapd_constants.N_CAPABILITY_DSSS_CCK_40
126            ])
127            config = hostapd_config.HostapdConfig(
128                ssid=ssid,
129                hidden=hidden,
130                security=security,
131                interface=interface,
132                mode=mode,
133                force_wmm=force_wmm,
134                beacon_interval=beacon_interval,
135                dtim_period=dtim_period,
136                short_preamble=short_preamble,
137                frequency=frequency,
138                n_capabilities=n_capabilities,
139                frag_threshold=frag_threshold,
140                rts_threshold=rts_threshold,
141                bss_settings=bss_settings)
142        else:
143            interface = iface_wlan_5g
144            vht_bandwidth = _get_or_default(vht_bandwidth, 80)
145            mode = _get_or_default(mode, hostapd_constants.MODE_11AC_MIXED)
146            if hostapd_config.ht40_plus_allowed(channel):
147                extended_channel = hostapd_constants.N_CAPABILITY_HT40_PLUS
148            elif hostapd_config.ht40_minus_allowed(channel):
149                extended_channel = hostapd_constants.N_CAPABILITY_HT40_MINUS
150            # Channel 165 operates in 20MHz with n or ac modes.
151            if channel == 165:
152                mode = hostapd_constants.MODE_11N_MIXED
153                extended_channel = hostapd_constants.N_CAPABILITY_HT20
154            # Define the n capability vector for 20 MHz and higher bandwidth
155            if not vht_bandwidth:
156                pass
157            elif vht_bandwidth >= 40:
158                n_capabilities = _get_or_default(n_capabilities, [
159                    hostapd_constants.N_CAPABILITY_LDPC, extended_channel,
160                    hostapd_constants.N_CAPABILITY_SGI20,
161                    hostapd_constants.N_CAPABILITY_SGI40,
162                    hostapd_constants.N_CAPABILITY_TX_STBC,
163                    hostapd_constants.N_CAPABILITY_RX_STBC1
164                ])
165            else:
166                n_capabilities = _get_or_default(n_capabilities, [
167                    hostapd_constants.N_CAPABILITY_LDPC,
168                    hostapd_constants.N_CAPABILITY_SGI20,
169                    hostapd_constants.N_CAPABILITY_SGI40,
170                    hostapd_constants.N_CAPABILITY_TX_STBC,
171                    hostapd_constants.N_CAPABILITY_RX_STBC1,
172                    hostapd_constants.N_CAPABILITY_HT20
173                ])
174            ac_capabilities = _get_or_default(ac_capabilities, [
175                hostapd_constants.AC_CAPABILITY_MAX_MPDU_11454,
176                hostapd_constants.AC_CAPABILITY_RXLDPC,
177                hostapd_constants.AC_CAPABILITY_SHORT_GI_80,
178                hostapd_constants.AC_CAPABILITY_TX_STBC_2BY1,
179                hostapd_constants.AC_CAPABILITY_RX_STBC_1,
180                hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP7,
181                hostapd_constants.AC_CAPABILITY_RX_ANTENNA_PATTERN,
182                hostapd_constants.AC_CAPABILITY_TX_ANTENNA_PATTERN
183            ])
184            config = hostapd_config.HostapdConfig(
185                ssid=ssid,
186                hidden=hidden,
187                security=security,
188                interface=interface,
189                mode=mode,
190                force_wmm=force_wmm,
191                vht_channel_width=vht_bandwidth,
192                beacon_interval=beacon_interval,
193                dtim_period=dtim_period,
194                short_preamble=short_preamble,
195                frequency=frequency,
196                frag_threshold=frag_threshold,
197                rts_threshold=rts_threshold,
198                n_capabilities=n_capabilities,
199                ac_capabilities=ac_capabilities,
200                bss_settings=bss_settings)
201    elif profile_name == 'whirlwind_11ab_legacy':
202        if frequency < 5000:
203            mode = hostapd_constants.MODE_11B
204        else:
205            mode = hostapd_constants.MODE_11A
206
207        config = create_ap_preset(iface_wlan_2g=iface_wlan_2g,
208                                  iface_wlan_5g=iface_wlan_5g,
209                                  ssid=ssid,
210                                  channel=channel,
211                                  mode=mode,
212                                  security=security,
213                                  hidden=hidden,
214                                  force_wmm=force_wmm,
215                                  beacon_interval=beacon_interval,
216                                  short_preamble=short_preamble,
217                                  dtim_period=dtim_period,
218                                  rts_threshold=rts_threshold,
219                                  frag_threshold=frag_threshold,
220                                  n_capabilities=[],
221                                  ac_capabilities=[],
222                                  vht_bandwidth=None)
223    elif profile_name == 'whirlwind_11ag_legacy':
224        if frequency < 5000:
225            mode = hostapd_constants.MODE_11G
226        else:
227            mode = hostapd_constants.MODE_11A
228
229        config = create_ap_preset(iface_wlan_2g=iface_wlan_2g,
230                                  iface_wlan_5g=iface_wlan_5g,
231                                  ssid=ssid,
232                                  channel=channel,
233                                  mode=mode,
234                                  security=security,
235                                  hidden=hidden,
236                                  force_wmm=force_wmm,
237                                  beacon_interval=beacon_interval,
238                                  short_preamble=short_preamble,
239                                  dtim_period=dtim_period,
240                                  rts_threshold=rts_threshold,
241                                  frag_threshold=frag_threshold,
242                                  n_capabilities=[],
243                                  ac_capabilities=[],
244                                  vht_bandwidth=None)
245    elif profile_name == 'mistral':
246        hidden = _get_or_default(hidden, False)
247        force_wmm = _get_or_default(force_wmm, True)
248        beacon_interval = _get_or_default(beacon_interval, 100)
249        short_preamble = _get_or_default(short_preamble, True)
250        dtim_period = _get_or_default(dtim_period, 2)
251        frag_threshold = None
252        rts_threshold = None
253
254        # Google IE
255        # Country Code IE ('us' lowercase)
256        vendor_elements = {
257            'vendor_elements':
258            'dd0cf4f5e80505ff0000ffffffff'
259            '070a75732024041e95051e00'
260        }
261        default_configs = {'bridge': 'br-lan', 'iapp_interface': 'br-lan'}
262
263        if frequency < 5000:
264            interface = iface_wlan_2g
265            mode = _get_or_default(mode, hostapd_constants.MODE_11N_MIXED)
266            n_capabilities = _get_or_default(n_capabilities, [
267                hostapd_constants.N_CAPABILITY_LDPC,
268                hostapd_constants.N_CAPABILITY_SGI20,
269                hostapd_constants.N_CAPABILITY_SGI40,
270                hostapd_constants.N_CAPABILITY_TX_STBC,
271                hostapd_constants.N_CAPABILITY_RX_STBC1,
272                hostapd_constants.N_CAPABILITY_DSSS_CCK_40
273            ])
274
275            additional_params = utils.merge_dicts(
276                vendor_elements, hostapd_constants.ENABLE_RRM_BEACON_REPORT,
277                hostapd_constants.ENABLE_RRM_NEIGHBOR_REPORT, default_configs)
278            config = hostapd_config.HostapdConfig(
279                ssid=ssid,
280                hidden=hidden,
281                security=security,
282                interface=interface,
283                mode=mode,
284                force_wmm=force_wmm,
285                beacon_interval=beacon_interval,
286                dtim_period=dtim_period,
287                short_preamble=short_preamble,
288                frequency=frequency,
289                n_capabilities=n_capabilities,
290                frag_threshold=frag_threshold,
291                rts_threshold=rts_threshold,
292                bss_settings=bss_settings,
293                additional_parameters=additional_params,
294                set_ap_defaults_profile=profile_name)
295        else:
296            interface = iface_wlan_5g
297            vht_bandwidth = _get_or_default(vht_bandwidth, 80)
298            mode = _get_or_default(mode, hostapd_constants.MODE_11AC_MIXED)
299            if hostapd_config.ht40_plus_allowed(channel):
300                extended_channel = hostapd_constants.N_CAPABILITY_HT40_PLUS
301            elif hostapd_config.ht40_minus_allowed(channel):
302                extended_channel = hostapd_constants.N_CAPABILITY_HT40_MINUS
303            # Channel 165 operates in 20MHz with n or ac modes.
304            if channel == 165:
305                mode = hostapd_constants.MODE_11N_MIXED
306                extended_channel = hostapd_constants.N_CAPABILITY_HT20
307            if vht_bandwidth >= 40:
308                n_capabilities = _get_or_default(n_capabilities, [
309                    hostapd_constants.N_CAPABILITY_LDPC, extended_channel,
310                    hostapd_constants.N_CAPABILITY_SGI20,
311                    hostapd_constants.N_CAPABILITY_SGI40,
312                    hostapd_constants.N_CAPABILITY_TX_STBC,
313                    hostapd_constants.N_CAPABILITY_RX_STBC1
314                ])
315            else:
316                n_capabilities = _get_or_default(n_capabilities, [
317                    hostapd_constants.N_CAPABILITY_LDPC,
318                    hostapd_constants.N_CAPABILITY_SGI20,
319                    hostapd_constants.N_CAPABILITY_SGI40,
320                    hostapd_constants.N_CAPABILITY_TX_STBC,
321                    hostapd_constants.N_CAPABILITY_RX_STBC1,
322                    hostapd_constants.N_CAPABILITY_HT20
323                ])
324            ac_capabilities = _get_or_default(ac_capabilities, [
325                hostapd_constants.AC_CAPABILITY_MAX_MPDU_11454,
326                hostapd_constants.AC_CAPABILITY_RXLDPC,
327                hostapd_constants.AC_CAPABILITY_SHORT_GI_80,
328                hostapd_constants.AC_CAPABILITY_TX_STBC_2BY1,
329                hostapd_constants.AC_CAPABILITY_RX_STBC_1,
330                hostapd_constants.AC_CAPABILITY_MAX_A_MPDU_LEN_EXP7,
331                hostapd_constants.AC_CAPABILITY_RX_ANTENNA_PATTERN,
332                hostapd_constants.AC_CAPABILITY_TX_ANTENNA_PATTERN,
333                hostapd_constants.AC_CAPABILITY_SU_BEAMFORMER,
334                hostapd_constants.AC_CAPABILITY_SU_BEAMFORMEE,
335                hostapd_constants.AC_CAPABILITY_MU_BEAMFORMER,
336                hostapd_constants.AC_CAPABILITY_SOUNDING_DIMENSION_4,
337                hostapd_constants.AC_CAPABILITY_BF_ANTENNA_4
338            ])
339
340            additional_params = utils.merge_dicts(
341                vendor_elements, hostapd_constants.ENABLE_RRM_BEACON_REPORT,
342                hostapd_constants.ENABLE_RRM_NEIGHBOR_REPORT, default_configs)
343            config = hostapd_config.HostapdConfig(
344                ssid=ssid,
345                hidden=hidden,
346                security=security,
347                interface=interface,
348                mode=mode,
349                force_wmm=force_wmm,
350                vht_channel_width=vht_bandwidth,
351                beacon_interval=beacon_interval,
352                dtim_period=dtim_period,
353                short_preamble=short_preamble,
354                frequency=frequency,
355                frag_threshold=frag_threshold,
356                rts_threshold=rts_threshold,
357                n_capabilities=n_capabilities,
358                ac_capabilities=ac_capabilities,
359                bss_settings=bss_settings,
360                additional_parameters=additional_params,
361                set_ap_defaults_profile=profile_name)
362    elif profile_name == 'actiontec_pk5000':
363        config = actiontec.actiontec_pk5000(iface_wlan_2g=iface_wlan_2g,
364                                            channel=channel,
365                                            ssid=ssid,
366                                            security=security)
367    elif profile_name == 'actiontec_mi424wr':
368        config = actiontec.actiontec_mi424wr(iface_wlan_2g=iface_wlan_2g,
369                                             channel=channel,
370                                             ssid=ssid,
371                                             security=security)
372    elif profile_name == 'asus_rtac66u':
373        config = asus.asus_rtac66u(iface_wlan_2g=iface_wlan_2g,
374                                   iface_wlan_5g=iface_wlan_5g,
375                                   channel=channel,
376                                   ssid=ssid,
377                                   security=security)
378    elif profile_name == 'asus_rtac86u':
379        config = asus.asus_rtac86u(iface_wlan_2g=iface_wlan_2g,
380                                   iface_wlan_5g=iface_wlan_5g,
381                                   channel=channel,
382                                   ssid=ssid,
383                                   security=security)
384    elif profile_name == 'asus_rtac5300':
385        config = asus.asus_rtac5300(iface_wlan_2g=iface_wlan_2g,
386                                    iface_wlan_5g=iface_wlan_5g,
387                                    channel=channel,
388                                    ssid=ssid,
389                                    security=security)
390    elif profile_name == 'asus_rtn56u':
391        config = asus.asus_rtn56u(iface_wlan_2g=iface_wlan_2g,
392                                  iface_wlan_5g=iface_wlan_5g,
393                                  channel=channel,
394                                  ssid=ssid,
395                                  security=security)
396    elif profile_name == 'asus_rtn66u':
397        config = asus.asus_rtn66u(iface_wlan_2g=iface_wlan_2g,
398                                  iface_wlan_5g=iface_wlan_5g,
399                                  channel=channel,
400                                  ssid=ssid,
401                                  security=security)
402    elif profile_name == 'belkin_f9k1001v5':
403        config = belkin.belkin_f9k1001v5(iface_wlan_2g=iface_wlan_2g,
404                                         channel=channel,
405                                         ssid=ssid,
406                                         security=security)
407    elif profile_name == 'linksys_ea4500':
408        config = linksys.linksys_ea4500(iface_wlan_2g=iface_wlan_2g,
409                                        iface_wlan_5g=iface_wlan_5g,
410                                        channel=channel,
411                                        ssid=ssid,
412                                        security=security)
413    elif profile_name == 'linksys_ea9500':
414        config = linksys.linksys_ea9500(iface_wlan_2g=iface_wlan_2g,
415                                        iface_wlan_5g=iface_wlan_5g,
416                                        channel=channel,
417                                        ssid=ssid,
418                                        security=security)
419    elif profile_name == 'linksys_wrt1900acv2':
420        config = linksys.linksys_wrt1900acv2(iface_wlan_2g=iface_wlan_2g,
421                                             iface_wlan_5g=iface_wlan_5g,
422                                             channel=channel,
423                                             ssid=ssid,
424                                             security=security)
425    elif profile_name == 'netgear_r7000':
426        config = netgear.netgear_r7000(iface_wlan_2g=iface_wlan_2g,
427                                       iface_wlan_5g=iface_wlan_5g,
428                                       channel=channel,
429                                       ssid=ssid,
430                                       security=security)
431    elif profile_name == 'netgear_wndr3400':
432        config = netgear.netgear_wndr3400(iface_wlan_2g=iface_wlan_2g,
433                                          iface_wlan_5g=iface_wlan_5g,
434                                          channel=channel,
435                                          ssid=ssid,
436                                          security=security)
437    elif profile_name == 'securifi_almond':
438        config = securifi.securifi_almond(iface_wlan_2g=iface_wlan_2g,
439                                          channel=channel,
440                                          ssid=ssid,
441                                          security=security)
442    elif profile_name == 'tplink_archerc5':
443        config = tplink.tplink_archerc5(iface_wlan_2g=iface_wlan_2g,
444                                        iface_wlan_5g=iface_wlan_5g,
445                                        channel=channel,
446                                        ssid=ssid,
447                                        security=security)
448    elif profile_name == 'tplink_archerc7':
449        config = tplink.tplink_archerc7(iface_wlan_2g=iface_wlan_2g,
450                                        iface_wlan_5g=iface_wlan_5g,
451                                        channel=channel,
452                                        ssid=ssid,
453                                        security=security)
454    elif profile_name == 'tplink_c1200':
455        config = tplink.tplink_c1200(iface_wlan_2g=iface_wlan_2g,
456                                     iface_wlan_5g=iface_wlan_5g,
457                                     channel=channel,
458                                     ssid=ssid,
459                                     security=security)
460    elif profile_name == 'tplink_tlwr940n':
461        config = tplink.tplink_tlwr940n(iface_wlan_2g=iface_wlan_2g,
462                                        channel=channel,
463                                        ssid=ssid,
464                                        security=security)
465    else:
466        raise ValueError('Invalid ap model specified (%s)' % profile_name)
467
468    return config
469