1#!/usr/bin/env python3
2#
3#   Copyright 2019 - The Android secure Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16import time
17
18from acts import asserts
19from acts import context
20from acts.controllers.ap_lib import hostapd_constants
21from acts.controllers.ap_lib.radvd import Radvd
22from acts.controllers.ap_lib import radvd_constants
23from acts.controllers.ap_lib.radvd_config import RadvdConfig
24from acts.controllers.ap_lib.hostapd_security import Security
25from acts.controllers.attenuator import get_attenuators_for_device
26from acts.controllers.iperf_server import IPerfResult
27from acts.test_utils.abstract_devices.utils_lib.wlan_utils import associate
28from acts.test_utils.abstract_devices.utils_lib.wlan_utils import setup_ap
29from acts.test_utils.abstract_devices.wlan_device import create_wlan_device
30from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
31from acts.utils import rand_ascii_str
32
33from bokeh.plotting import ColumnDataSource
34from bokeh.plotting import figure
35from bokeh.plotting import output_file
36from bokeh.plotting import save
37
38AP_11ABG_PROFILE_NAME = 'whirlwind_11ag_legacy'
39RADVD_PREFIX = 'fd00::/64'
40REPORTING_SPEED_UNITS = 'Mbps'
41
42RVR_GRAPH_SUMMARY_FILE = 'rvr_summary.html'
43
44
45def create_rvr_graph(test_name, graph_path, graph_data):
46    """Creates the RvR graphs
47    Args:
48        test_name: The name of test that was run.  This is the title of the
49            graph
50        graph_path: Where to put the graph html file.
51        graph_data: A dictionary of the data to be graphed.
52    Returns:
53        A list of bokeh graph objects.
54        """
55    output_file('%srvr_throughput_vs_attn_%s.html' % (graph_path, test_name),
56                title=test_name)
57    throughput_vs_attn_data = ColumnDataSource(data=dict(
58        relative_attn=graph_data['throughput_vs_attn']['relative_attn'],
59        throughput=graph_data['throughput_vs_attn']['throughput']))
60    TOOLTIPS = [("Attenuation", "@relative_attn"),
61                ("Throughput", "@throughput")]
62    throughput_vs_attn_graph = figure(
63        title="Throughput vs Relative Attenuation (Test Case: %s)" % test_name,
64        x_axis_label=graph_data['throughput_vs_attn']['x_label'],
65        y_axis_label=graph_data['throughput_vs_attn']['y_label'],
66        x_range=graph_data['throughput_vs_attn']['relative_attn'],
67        tooltips=TOOLTIPS)
68    throughput_vs_attn_graph.sizing_mode = 'stretch_width'
69    throughput_vs_attn_graph.title.align = 'center'
70    throughput_vs_attn_graph.line('relative_attn',
71                                  'throughput',
72                                  source=throughput_vs_attn_data,
73                                  line_width=2)
74    throughput_vs_attn_graph.circle('relative_attn',
75                                    'throughput',
76                                    source=throughput_vs_attn_data,
77                                    size=10)
78    save([throughput_vs_attn_graph])
79    return [throughput_vs_attn_graph]
80
81
82def write_csv_rvr_data(test_name, csv_path, csv_data):
83    """Writes the CSV data for the RvR test
84    Args:
85        test_name: The name of test that was run.
86        csv_path: Where to put the csv file.
87        csv_data: A dictionary of the data to be put in the csv file.
88    """
89    csv_file_name = '%srvr_throughput_vs_attn_%s.csv' % (csv_path, test_name)
90    throughput = csv_data['throughput_vs_attn']['throughput']
91    relative_attn = csv_data['throughput_vs_attn']['relative_attn']
92    with open(csv_file_name, 'w+') as csv_fileId:
93        csv_fileId.write('%s,%s\n' %
94                         (csv_data['throughput_vs_attn']['x_label'],
95                          csv_data['throughput_vs_attn']['y_label']))
96        for csv_loop_counter in range(0, len(relative_attn)):
97            csv_fileId.write('%s,%s\n' % (int(relative_attn[csv_loop_counter]),
98                                          throughput[csv_loop_counter]))
99
100
101class WlanRvrTest(WifiBaseTest):
102    """Tests running WLAN RvR.
103
104    Test Bed Requirement:
105    * One Android device or Fuchsia device
106    * One Access Point
107    * One attenuator
108    * One Linux iPerf Server
109    """
110    def __init__(self, controllers):
111        WifiBaseTest.__init__(self, controllers)
112        self.rvr_graph_summary = []
113
114    def setup_class(self):
115        super(WlanRvrTest, self).setup_class()
116        if 'dut' in self.user_params:
117            if self.user_params['dut'] == 'fuchsia_devices':
118                self.dut = create_wlan_device(self.fuchsia_devices[0])
119            elif self.user_params['dut'] == 'android_devices':
120                self.dut = create_wlan_device(self.android_devices[0])
121            else:
122                raise ValueError('Invalid DUT specified in config. (%s)' %
123                                 self.user_params['dut'])
124        else:
125            # Default is an android device, just like the other tests
126            self.dut = create_wlan_device(self.android_devices[0])
127
128        self.starting_attn = (self.user_params['rvr_settings'].get(
129            'starting_attn', 0))
130
131        self.ending_attn = (self.user_params['rvr_settings'].get(
132            'ending_attn', 95))
133
134        self.step_size_in_db = (self.user_params['rvr_settings'].get(
135            'step_size_in_db', 1))
136
137        self.dwell_time_in_secs = (self.user_params['rvr_settings'].get(
138            'dwell_time_in_secs', 10))
139
140        self.reverse_rvr_after_forward = bool(
141            (self.user_params['rvr_settings'].get('reverse_rvr_after_forward',
142                                                  None)))
143
144        self.iperf_flags = (self.user_params['rvr_settings'].get(
145            'iperf_flags', '-i 1'))
146
147        self.iperf_flags = '%s -t %s -J' % (self.iperf_flags,
148                                            self.dwell_time_in_secs)
149
150        self.debug_loop_count = (self.user_params['rvr_settings'].get(
151            'debug_loop_count', 1))
152
153        self.debug_pre_traffic_cmd = (self.user_params['rvr_settings'].get(
154            'debug_pre_traffic_cmd', None))
155
156        self.debug_post_traffic_cmd = (self.user_params['rvr_settings'].get(
157            'debug_post_traffic_cmd', None))
158
159        self.router_adv_daemon = None
160        self.check_if_has_private_local_ipv6_address = True
161
162        if self.ending_attn == 'auto':
163            self.use_auto_end = True
164            self.ending_attn = 100
165            if self.step_size_in_db > 2:
166                asserts.fail('When using an ending attenuation of \'auto\' '
167                             'please use a value < 2db.  Larger jumps will '
168                             'break the test reporting.')
169
170        self.access_point = self.access_points[0]
171        self.attenuators_2g = get_attenuators_for_device(
172            self.controller_configs['AccessPoint'][0]['Attenuator'],
173            self.attenuators, 'attenuator_ports_wifi_2g')
174        self.attenuators_5g = get_attenuators_for_device(
175            self.controller_configs['AccessPoint'][0]['Attenuator'],
176            self.attenuators, 'attenuator_ports_wifi_5g')
177
178        self.iperf_server = self.iperf_servers[0]
179        self.dut_iperf_client = self.iperf_clients[0]
180
181        self.access_point.stop_all_aps()
182
183    def setup_test(self):
184        if self.iperf_server:
185            self.iperf_server.start()
186        if hasattr(self, "android_devices"):
187            for ad in self.android_devices:
188                ad.droid.wakeLockAcquireBright()
189                ad.droid.wakeUpNow()
190        self.dut.wifi_toggle_state(True)
191
192    def teardown_test(self):
193        if self.router_adv_daemon:
194            self.router_adv_daemon.stop()
195        if hasattr(self, "android_devices"):
196            for ad in self.android_devices:
197                ad.droid.wakeLockRelease()
198                ad.droid.goToSleepNow()
199        if self.iperf_server:
200            self.iperf_server.stop()
201        self.dut.turn_location_off_and_scan_toggle_off()
202        self.dut.disconnect()
203        self.dut.reset_wifi()
204        self.access_point.stop_all_aps()
205
206    def teardown_class(self):
207        if self.router_adv_daemon:
208            self.router_adv_daemon.stop()
209        try:
210            output_path = context.get_current_context().get_base_output_path()
211            test_class_name = context.get_current_context().test_class_name
212
213            output_file(f'{output_path}/{test_class_name}/rvr_summary.html',
214                        title='RvR Sumamry')
215            save(list(self.rvr_graph_summary))
216        except Exception as e:
217            self.log.info('Unable to generate RvR summary file due '
218                          'to Exception')
219            self.log.info(e)
220
221    def on_fail(self, test_name, begin_time):
222        self.dut.take_bug_report(test_name, begin_time)
223        self.dut.get_log(test_name, begin_time)
224
225    def run_rvr(self,
226                ssid,
227                password=None,
228                band='2g',
229                traffic_dir='tx',
230                ip_version=4):
231        """Setups and runs the RvR test
232
233        Args:
234            ssid: The SSID for the client to associate to.
235            password: Password for the network, if necessary.
236            band: 2g or 5g
237            traffic_dir: rx or tx, bi is not supported by iperf3
238            ip_version: 4 or 6
239
240        Returns:
241            The bokeh graph data.
242        """
243        throughput = []
244        relative_attn = []
245        self.check_if_has_private_local_ipv6_address = True
246        if band == '2g':
247            rvr_attenuators = self.attenuators_2g
248        elif band == '5g':
249            rvr_attenuators = self.attenuators_5g
250        else:
251            raise ValueError('Invalid WLAN band specified: %s' % band)
252        if ip_version == 6:
253            ravdvd_config = RadvdConfig(
254                prefix=RADVD_PREFIX,
255                adv_send_advert=radvd_constants.ADV_SEND_ADVERT_ON,
256                adv_on_link=radvd_constants.ADV_ON_LINK_ON,
257                adv_autonomous=radvd_constants.ADV_AUTONOMOUS_ON)
258            self.router_adv_daemon = Radvd(
259                self.access_point.ssh,
260                self.access_point.interfaces.get_bridge_interface()[0])
261            self.router_adv_daemon.start(ravdvd_config)
262
263        for rvr_loop_counter in range(0, self.debug_loop_count):
264            for rvr_attenuator in rvr_attenuators:
265                rvr_attenuator.set_atten(self.starting_attn)
266
267            associate_counter = 0
268            associate_max_attempts = 3
269            while associate_counter < associate_max_attempts:
270                if associate(self.dut,
271                             ssid,
272                             password,
273                             check_connectivity=False):
274                    break
275                else:
276                    associate_counter += 1
277            if associate_counter == associate_max_attempts:
278                asserts.fail('Unable to associate at starting '
279                             'attenuation: %s' % self.starting_attn)
280
281            ip_address_checker_counter = 0
282            ip_address_checker_max_attempts = 3
283            while ip_address_checker_counter < ip_address_checker_max_attempts:
284                self.iperf_server.renew_test_interface_ip_address()
285                iperf_server_ip_addresses = (
286                    self.iperf_server.get_interface_ip_addresses(
287                        self.iperf_server.test_interface))
288                dut_ip_addresses = self.dut.get_interface_ip_addresses(
289                    self.dut_iperf_client.test_interface)
290                self.log.info('IPerf server IP info: %s' %
291                              iperf_server_ip_addresses)
292                self.log.info('DUT IP info: %s' % dut_ip_addresses)
293                if ip_version == 4:
294                    if iperf_server_ip_addresses['ipv4_private']:
295                        iperf_server_ip_address = (
296                            iperf_server_ip_addresses['ipv4_private'][0])
297                    if not dut_ip_addresses['ipv4_private']:
298                        self.log.warn('Unable to get IPv4 address at starting '
299                                      'attenuation: %s Retrying.' %
300                                      self.starting_attn)
301                        ip_address_checker_counter += 1
302                        time.sleep(1)
303                    else:
304                        break
305                elif ip_version == 6:
306                    if iperf_server_ip_addresses['ipv6_private_local']:
307                        iperf_server_ip_address = (
308                            iperf_server_ip_addresses['ipv6_private_local'][0])
309                    else:
310                        self.check_if_has_private_local_ipv6_address = False
311                        iperf_server_ip_address = (
312                            '%s%%%s' %
313                            (iperf_server_ip_addresses['ipv6_link_local'][0],
314                             self.dut_iperf_client.test_interface))
315                    if self.check_if_has_private_local_ipv6_address:
316                        if not dut_ip_addresses['ipv6_private_local']:
317                            self.log.warn('Unable to get IPv6 address at '
318                                          'starting attenuation: %s' %
319                                          self.starting_attn)
320                            ip_address_checker_counter += 1
321                            time.sleep(1)
322                        else:
323                            break
324                    else:
325                        break
326                else:
327                    raise ValueError('Invalid IP version: %s' % ip_version)
328            if ip_address_checker_counter == ip_address_checker_max_attempts:
329                if self.dut.ping(iperf_server_ip_address):
330                    self.log.error('IPerf server is pingable. Continuing with '
331                                   'test.  The missing IP address information '
332                                   'should be marked as a bug.')
333                else:
334                    asserts.fail('DUT was unable to get IPv%s address and '
335                                 'could not ping the IPerf server.' %
336                                 str(ip_version))
337            throughput, relative_attn = (self.rvr_loop(
338                traffic_dir,
339                rvr_attenuators,
340                iperf_server_ip_address,
341                ip_version,
342                throughput=throughput,
343                relative_attn=relative_attn))
344            if self.reverse_rvr_after_forward:
345                throughput, relative_attn = self.rvr_loop(
346                    traffic_dir,
347                    rvr_attenuators,
348                    iperf_server_ip_address,
349                    ip_version,
350                    ssid=ssid,
351                    password=password,
352                    reverse=True,
353                    throughput=throughput,
354                    relative_attn=relative_attn)
355            self.dut.disconnect()
356
357        throughput_vs_attn = {
358            'throughput': throughput,
359            'relative_attn': relative_attn,
360            'x_label': 'Attenuation(db)',
361            'y_label': 'Throughput(%s)' % REPORTING_SPEED_UNITS
362        }
363        graph_data = {'throughput_vs_attn': throughput_vs_attn}
364        return graph_data
365
366    def rvr_loop(self,
367                 traffic_dir,
368                 rvr_attenuators,
369                 iperf_server_ip_address,
370                 ip_version,
371                 ssid=None,
372                 password=None,
373                 reverse=False,
374                 throughput=None,
375                 relative_attn=None):
376        """The loop that goes through each attenuation level and runs the iperf
377        throughput pair.
378        Args:
379            traffic_dir: The traffic direction from the perspective of the DUT.
380            rvr_attenuators: A list of attenuators to set.
381            iperf_server_ip_address: The IP address of the iperf server.
382            ssid: The ssid of the wireless network that the should associated
383                to.
384            password: Password of the wireless network.
385            reverse: Whether to run RvR test starting from the highest
386                attenuation and going to the lowest.  This is run after the
387                normal low attenuation to high attenuation RvR test.
388            throughput: The list of throughput data for the test.
389            relative_attn: The list of attenuation data for the test.
390
391        Returns:
392            throughput: The list of throughput data for the test.
393            relative_attn: The list of attenuation data for the test.
394            """
395        iperf_flags = self.iperf_flags
396        if traffic_dir == 'rx':
397            iperf_flags = '%s -R' % self.iperf_flags
398        starting_attn = self.starting_attn
399        ending_attn = self.ending_attn
400        step_size_in_db = self.step_size_in_db
401        if reverse:
402            starting_attn = self.ending_attn
403            ending_attn = self.starting_attn
404            step_size_in_db = step_size_in_db * -1
405            self.dut.disconnect()
406        for step in range(starting_attn, ending_attn, step_size_in_db):
407            try:
408                for attenuator in rvr_attenuators:
409                    attenuator.set_atten(step)
410            except ValueError:
411                self.log.info('%s is beyond the max or min of the testbed '
412                              'attenuator\'s capability. Stopping.')
413                break
414
415            associated = self.dut.is_connected()
416            if associated:
417                self.log.info('DUT is currently associated.')
418            else:
419                self.log.info('DUT is not currently associated.')
420
421            if reverse:
422                if not associated:
423                    self.log.info('Trying to associate at relative '
424                                  'attenuation of %s db' % step)
425                    if associate(self.dut,
426                                 ssid,
427                                 password,
428                                 check_connectivity=False):
429                        associated = True
430                        self.log.info('Successfully associated.')
431                    else:
432                        associated = False
433                        self.log.info(
434                            'Association failed. Marking a 0 %s for'
435                            ' throughput. Skipping running traffic.' %
436                            REPORTING_SPEED_UNITS)
437            attn_value_inserted = False
438            value_to_insert = str(step)
439            while not attn_value_inserted:
440                if value_to_insert in relative_attn:
441                    value_to_insert = '%s ' % value_to_insert
442                else:
443                    relative_attn.append(value_to_insert)
444                    attn_value_inserted = True
445
446            dut_ip_addresses = self.dut.get_interface_ip_addresses(
447                self.dut_iperf_client.test_interface)
448            if ip_version == 4:
449                if not dut_ip_addresses['ipv4_private']:
450                    self.log.info('DUT does not have an IPv4 address. '
451                                  'Traffic attempt to be run if the server '
452                                  'is pingable.')
453                else:
454                    self.log.info('DUT has the following IPv4 address: "%s"' %
455                                  dut_ip_addresses['ipv4_private'][0])
456            elif ip_version == 6:
457                if self.check_if_has_private_local_ipv6_address:
458                    if not dut_ip_addresses['ipv6_private_local']:
459                        self.log.info(
460                            'DUT does not have an IPv6 address. '
461                            'Traffic attempt to be run if the server '
462                            'is pingable.')
463                    else:
464                        self.log.info(
465                            'DUT has the following IPv6 address: "%s"' %
466                            dut_ip_addresses['ipv6_private_local'][0])
467                else:
468                    self.log.info('DUT has the following IPv6 address: "%s"' %
469                                  dut_ip_addresses['ipv6_link_local'][0])
470            server_pingable = self.dut.ping(iperf_server_ip_address)
471            if not server_pingable:
472                self.log.info('Iperf server "%s" is not pingable. Marking '
473                              'a 0 %s for throughput. Skipping running '
474                              'traffic.' %
475                              (iperf_server_ip_address, REPORTING_SPEED_UNITS))
476            else:
477                self.log.info('Iperf server "%s" is pingable.' %
478                              iperf_server_ip_address)
479            if self.debug_pre_traffic_cmd:
480                self.log.info('\nDEBUG: Sending command \'%s\' to DUT' %
481                              self.debug_pre_traffic_cmd)
482                self.log.info(
483                    '\n%s' % self.dut.send_command(self.debug_pre_traffic_cmd))
484            if server_pingable:
485                if traffic_dir == 'tx':
486                    self.log.info('Running traffic DUT to %s at relative '
487                                  'attenuation of %s' %
488                                  (iperf_server_ip_address, step))
489                elif traffic_dir == 'rx':
490                    self.log.info('Running traffic %s to DUT at relative '
491                                  'attenuation of %s' %
492                                  (iperf_server_ip_address, step))
493                else:
494                    raise ValueError('Invalid traffic direction')
495                try:
496                    iperf_tag = 'decreasing'
497                    if reverse:
498                        iperf_tag = 'increasing'
499                    iperf_results_file = self.dut_iperf_client.start(
500                        iperf_server_ip_address,
501                        iperf_flags,
502                        '%s_%s_%s' %
503                        (iperf_tag, traffic_dir, self.starting_attn),
504                        timeout=(self.dwell_time_in_secs * 2))
505                except TimeoutError:
506                    iperf_results_file = None
507                    self.log.info('Iperf traffic timed out. Marking 0 %s for '
508                                  'throughput.' % REPORTING_SPEED_UNITS)
509
510                if not iperf_results_file:
511                    throughput.append(0)
512                else:
513                    try:
514                        iperf_results = IPerfResult(
515                            iperf_results_file,
516                            reporting_speed_units=REPORTING_SPEED_UNITS)
517                        if iperf_results.error:
518                            self.iperf_server.stop()
519                            self.iperf_server.start()
520                            self.log.info('\nErrors in iperf logs:\n%s' %
521                                          iperf_results.error)
522                        if not iperf_results.avg_send_rate:
523                            throughput.append(0)
524                        else:
525                            throughput.append(iperf_results.avg_send_rate)
526                    except ValueError:
527                        self.iperf_server.stop()
528                        self.iperf_server.start()
529                        self.log.info(
530                            'No data in Iperf file. Marking 0 %s for '
531                            'throughput.' % REPORTING_SPEED_UNITS)
532                        throughput.append(0)
533                    except Exception as e:
534                        self.iperf_server.stop()
535                        self.iperf_server.start()
536                        self.log.info('Unknown exception. Marking 0 %s for '
537                                      'throughput.' % REPORTING_SPEED_UNITS)
538                        self.log.error(e)
539                        throughput.append(0)
540
541                self.log.info(
542                    'Iperf traffic complete. %s traffic received at '
543                    '%s %s at relative attenuation of %s db' %
544                    (traffic_dir, throughput[-1], REPORTING_SPEED_UNITS,
545                     str(relative_attn[-1]).strip()))
546
547            else:
548                self.log.debug('DUT Associated: %s' % associated)
549                self.log.debug('%s pingable: %s' %
550                               (iperf_server_ip_address, server_pingable))
551                throughput.append(0)
552            if self.debug_post_traffic_cmd:
553                self.log.info('\nDEBUG: Sending command \'%s\' to DUT' %
554                              self.debug_post_traffic_cmd)
555                self.log.info(
556                    '\n%s' %
557                    self.dut.send_command(self.debug_post_traffic_cmd))
558        return throughput, relative_attn
559
560    def test_rvr_11ac_5g_80mhz_open_tx_ipv4(self):
561        ssid = rand_ascii_str(20)
562        setup_ap(access_point=self.access_point,
563                 profile_name='whirlwind',
564                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
565                 ssid=ssid,
566                 setup_bridge=True)
567        graph_data = self.run_rvr(ssid,
568                                  band='5g',
569                                  traffic_dir='tx',
570                                  ip_version=4)
571        for rvr_graph in create_rvr_graph(
572                self.test_name,
573                context.get_current_context().get_full_output_path(),
574                graph_data):
575            self.rvr_graph_summary.append(rvr_graph)
576        write_csv_rvr_data(
577            self.test_name,
578            context.get_current_context().get_full_output_path(), graph_data)
579
580    def test_rvr_11ac_5g_80mhz_open_rx_ipv4(self):
581        ssid = rand_ascii_str(20)
582        setup_ap(access_point=self.access_point,
583                 profile_name='whirlwind',
584                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
585                 ssid=ssid,
586                 setup_bridge=True)
587        graph_data = self.run_rvr(ssid,
588                                  band='5g',
589                                  traffic_dir='rx',
590                                  ip_version=4)
591        for rvr_graph in create_rvr_graph(
592                self.test_name,
593                context.get_current_context().get_full_output_path(),
594                graph_data):
595            self.rvr_graph_summary.append(rvr_graph)
596        write_csv_rvr_data(
597            self.test_name,
598            context.get_current_context().get_full_output_path(), graph_data)
599
600    def test_rvr_11ac_5g_80mhz_open_tx_ipv6(self):
601        ssid = rand_ascii_str(20)
602        setup_ap(access_point=self.access_point,
603                 profile_name='whirlwind',
604                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
605                 ssid=ssid,
606                 setup_bridge=True)
607        graph_data = self.run_rvr(ssid,
608                                  band='5g',
609                                  traffic_dir='tx',
610                                  ip_version=6)
611        for rvr_graph in create_rvr_graph(
612                self.test_name,
613                context.get_current_context().get_full_output_path(),
614                graph_data):
615            self.rvr_graph_summary.append(rvr_graph)
616        write_csv_rvr_data(
617            self.test_name,
618            context.get_current_context().get_full_output_path(), graph_data)
619
620    def test_rvr_11ac_5g_80mhz_open_rx_ipv6(self):
621        ssid = rand_ascii_str(20)
622        setup_ap(access_point=self.access_point,
623                 profile_name='whirlwind',
624                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
625                 ssid=ssid,
626                 setup_bridge=True)
627        graph_data = self.run_rvr(ssid,
628                                  band='5g',
629                                  traffic_dir='rx',
630                                  ip_version=6)
631        for rvr_graph in create_rvr_graph(
632                self.test_name,
633                context.get_current_context().get_full_output_path(),
634                graph_data):
635            self.rvr_graph_summary.append(rvr_graph)
636        write_csv_rvr_data(
637            self.test_name,
638            context.get_current_context().get_full_output_path(), graph_data)
639
640    def test_rvr_11ac_5g_80mhz_wpa2_tx_ipv4(self):
641        ssid = rand_ascii_str(20)
642        password = rand_ascii_str(20)
643        security_profile = Security(security_mode='wpa2', password=password)
644        setup_ap(access_point=self.access_point,
645                 profile_name='whirlwind',
646                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
647                 ssid=ssid,
648                 security=security_profile,
649                 setup_bridge=True)
650        graph_data = self.run_rvr(ssid,
651                                  password=password,
652                                  band='5g',
653                                  traffic_dir='tx',
654                                  ip_version=4)
655        for rvr_graph in create_rvr_graph(
656                self.test_name,
657                context.get_current_context().get_full_output_path(),
658                graph_data):
659            self.rvr_graph_summary.append(rvr_graph)
660        write_csv_rvr_data(
661            self.test_name,
662            context.get_current_context().get_full_output_path(), graph_data)
663
664    def test_rvr_11ac_5g_80mhz_wpa2_rx_ipv4(self):
665        ssid = rand_ascii_str(20)
666        password = rand_ascii_str(20)
667        security_profile = Security(security_mode='wpa2', password=password)
668        setup_ap(access_point=self.access_point,
669                 profile_name='whirlwind',
670                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
671                 ssid=ssid,
672                 security=security_profile,
673                 setup_bridge=True)
674        graph_data = self.run_rvr(ssid,
675                                  password=password,
676                                  band='5g',
677                                  traffic_dir='rx',
678                                  ip_version=4)
679        for rvr_graph in create_rvr_graph(
680                self.test_name,
681                context.get_current_context().get_full_output_path(),
682                graph_data):
683            self.rvr_graph_summary.append(rvr_graph)
684        write_csv_rvr_data(
685            self.test_name,
686            context.get_current_context().get_full_output_path(), graph_data)
687
688    def test_rvr_11ac_5g_80mhz_wpa2_tx_ipv6(self):
689        ssid = rand_ascii_str(20)
690        password = rand_ascii_str(20)
691        security_profile = Security(security_mode='wpa2', password=password)
692        setup_ap(access_point=self.access_point,
693                 profile_name='whirlwind',
694                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
695                 ssid=ssid,
696                 security=security_profile,
697                 setup_bridge=True)
698        graph_data = self.run_rvr(ssid,
699                                  password=password,
700                                  band='5g',
701                                  traffic_dir='tx',
702                                  ip_version=6)
703        for rvr_graph in create_rvr_graph(
704                self.test_name,
705                context.get_current_context().get_full_output_path(),
706                graph_data):
707            self.rvr_graph_summary.append(rvr_graph)
708        write_csv_rvr_data(
709            self.test_name,
710            context.get_current_context().get_full_output_path(), graph_data)
711
712    def test_rvr_11ac_5g_80mhz_wpa2_rx_ipv6(self):
713        ssid = rand_ascii_str(20)
714        password = rand_ascii_str(20)
715        security_profile = Security(security_mode='wpa2', password=password)
716        setup_ap(access_point=self.access_point,
717                 profile_name='whirlwind',
718                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
719                 ssid=ssid,
720                 security=security_profile,
721                 setup_bridge=True)
722        graph_data = self.run_rvr(ssid,
723                                  password=password,
724                                  band='5g',
725                                  traffic_dir='rx',
726                                  ip_version=6)
727        for rvr_graph in create_rvr_graph(
728                self.test_name,
729                context.get_current_context().get_full_output_path(),
730                graph_data):
731            self.rvr_graph_summary.append(rvr_graph)
732        write_csv_rvr_data(
733            self.test_name,
734            context.get_current_context().get_full_output_path(), graph_data)
735
736    def test_rvr_11n_2g_20mhz_open_tx_ipv4(self):
737        ssid = rand_ascii_str(20)
738        setup_ap(access_point=self.access_point,
739                 profile_name='whirlwind',
740                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
741                 ssid=ssid,
742                 setup_bridge=True)
743        graph_data = self.run_rvr(ssid,
744                                  band='2g',
745                                  traffic_dir='tx',
746                                  ip_version=4)
747        for rvr_graph in create_rvr_graph(
748                self.test_name,
749                context.get_current_context().get_full_output_path(),
750                graph_data):
751            self.rvr_graph_summary.append(rvr_graph)
752        write_csv_rvr_data(
753            self.test_name,
754            context.get_current_context().get_full_output_path(), graph_data)
755
756    def test_rvr_11n_2g_20mhz_open_rx_ipv4(self):
757        ssid = rand_ascii_str(20)
758        setup_ap(access_point=self.access_point,
759                 profile_name='whirlwind',
760                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
761                 ssid=ssid,
762                 setup_bridge=True)
763        graph_data = self.run_rvr(ssid,
764                                  band='2g',
765                                  traffic_dir='rx',
766                                  ip_version=4)
767        for rvr_graph in create_rvr_graph(
768                self.test_name,
769                context.get_current_context().get_full_output_path(),
770                graph_data):
771            self.rvr_graph_summary.append(rvr_graph)
772        write_csv_rvr_data(
773            self.test_name,
774            context.get_current_context().get_full_output_path(), graph_data)
775
776    def test_rvr_11n_2g_20mhz_open_tx_ipv6(self):
777        ssid = rand_ascii_str(20)
778        setup_ap(access_point=self.access_point,
779                 profile_name='whirlwind',
780                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
781                 ssid=ssid,
782                 setup_bridge=True)
783        graph_data = self.run_rvr(ssid,
784                                  band='2g',
785                                  traffic_dir='tx',
786                                  ip_version=6)
787        for rvr_graph in create_rvr_graph(
788                self.test_name,
789                context.get_current_context().get_full_output_path(),
790                graph_data):
791            self.rvr_graph_summary.append(rvr_graph)
792        write_csv_rvr_data(
793            self.test_name,
794            context.get_current_context().get_full_output_path(), graph_data)
795
796    def test_rvr_11n_2g_20mhz_open_rx_ipv6(self):
797        ssid = rand_ascii_str(20)
798        setup_ap(access_point=self.access_point,
799                 profile_name='whirlwind',
800                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
801                 ssid=ssid,
802                 setup_bridge=True)
803        graph_data = self.run_rvr(ssid,
804                                  band='2g',
805                                  traffic_dir='rx',
806                                  ip_version=6)
807        for rvr_graph in create_rvr_graph(
808                self.test_name,
809                context.get_current_context().get_full_output_path(),
810                graph_data):
811            self.rvr_graph_summary.append(rvr_graph)
812        write_csv_rvr_data(
813            self.test_name,
814            context.get_current_context().get_full_output_path(), graph_data)
815
816    def test_rvr_11n_2g_20mhz_wpa2_tx_ipv4(self):
817        ssid = rand_ascii_str(20)
818        password = rand_ascii_str(20)
819        security_profile = Security(security_mode='wpa2', password=password)
820        setup_ap(access_point=self.access_point,
821                 profile_name='whirlwind',
822                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
823                 ssid=ssid,
824                 security=security_profile,
825                 setup_bridge=True)
826        graph_data = self.run_rvr(ssid,
827                                  password=password,
828                                  band='2g',
829                                  traffic_dir='tx',
830                                  ip_version=4)
831        for rvr_graph in create_rvr_graph(
832                self.test_name,
833                context.get_current_context().get_full_output_path(),
834                graph_data):
835            self.rvr_graph_summary.append(rvr_graph)
836        write_csv_rvr_data(
837            self.test_name,
838            context.get_current_context().get_full_output_path(), graph_data)
839
840    def test_rvr_11n_2g_20mhz_wpa2_rx_ipv4(self):
841        ssid = rand_ascii_str(20)
842        password = rand_ascii_str(20)
843        security_profile = Security(security_mode='wpa2', password=password)
844        setup_ap(access_point=self.access_point,
845                 profile_name='whirlwind',
846                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
847                 ssid=ssid,
848                 security=security_profile,
849                 setup_bridge=True)
850        graph_data = self.run_rvr(ssid,
851                                  password=password,
852                                  band='2g',
853                                  traffic_dir='rx',
854                                  ip_version=4)
855        for rvr_graph in create_rvr_graph(
856                self.test_name,
857                context.get_current_context().get_full_output_path(),
858                graph_data):
859            self.rvr_graph_summary.append(rvr_graph)
860        write_csv_rvr_data(
861            self.test_name,
862            context.get_current_context().get_full_output_path(), graph_data)
863
864    def test_rvr_11n_2g_20mhz_wpa2_tx_ipv6(self):
865        ssid = rand_ascii_str(20)
866        password = rand_ascii_str(20)
867        security_profile = Security(security_mode='wpa2', password=password)
868        setup_ap(access_point=self.access_point,
869                 profile_name='whirlwind',
870                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
871                 ssid=ssid,
872                 security=security_profile,
873                 setup_bridge=True)
874        graph_data = self.run_rvr(ssid,
875                                  password=password,
876                                  band='2g',
877                                  traffic_dir='tx',
878                                  ip_version=6)
879        for rvr_graph in create_rvr_graph(
880                self.test_name,
881                context.get_current_context().get_full_output_path(),
882                graph_data):
883            self.rvr_graph_summary.append(rvr_graph)
884        write_csv_rvr_data(
885            self.test_name,
886            context.get_current_context().get_full_output_path(), graph_data)
887
888    def test_rvr_11n_2g_20mhz_wpa2_rx_ipv6(self):
889        ssid = rand_ascii_str(20)
890        password = rand_ascii_str(20)
891        security_profile = Security(security_mode='wpa2', password=password)
892        setup_ap(access_point=self.access_point,
893                 profile_name='whirlwind',
894                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
895                 ssid=ssid,
896                 security=security_profile,
897                 setup_bridge=True)
898        graph_data = self.run_rvr(ssid,
899                                  password=password,
900                                  band='2g',
901                                  traffic_dir='rx',
902                                  ip_version=6)
903        for rvr_graph in create_rvr_graph(
904                self.test_name,
905                context.get_current_context().get_full_output_path(),
906                graph_data):
907            self.rvr_graph_summary.append(rvr_graph)
908        write_csv_rvr_data(
909            self.test_name,
910            context.get_current_context().get_full_output_path(), graph_data)
911