autotest: Three way Perf setup

Change the WiFi_Perf tests to ustilize the pcap device as a Netperf
endpoint in throughput testing. This setup utilizes some hard-coded
values for ethernet interface names and ip addresses for the LAN ports
on the pcap and router Gale devices. This is necessary because the
router device is not configured with the daemons to handle the
assignment automatically. This also means that some ip routes need to be
set up manually on the devices to allow traffic to move as needed.

Specific arguments for the LAN interface device names and ip addresses
may be provided at the command line. If not provided, default values
will be used instead.

The throughput results after making this change are improved as
expected, but not completely as high as expected. There is still a
bottleneck on the router CPU in some cases. In other cases, we are
measuring the total transmitted data from the source device, rather than
measuring the received data on the target device. This results in some
test cases that have artificially inflated throughput values. These
problems could all be resolved by transition from Netperf to Iperf.

This implementation uses IpConfigContextManager to make ip config
changes on the test devices. This ensures that the ip config changes are
not persisted if the test fails or is otherwise interrupted. To test
this, I exited the test at various stages and checked that the ip
configs were correcty undone.

BUG=b:172211699
TEST=test_that $DUT suite:wifi_perf
test_that --fast $DUT network_WiFi_Perf.vht80 --args='router_lan_ip_addr="192.168.1.49"'

Change-Id: I940d37e8b59379d9bdc03d62390b00a7f718cc79
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/3108426
Commit-Queue: Kevin Lund <kglund@google.com>
Tested-by: Kevin Lund <kglund@google.com>
Reviewed-by: Arowa Suliman <arowa@chromium.org>
diff --git a/server/site_tests/network_WiFi_Perf/network_WiFi_Perf.py b/server/site_tests/network_WiFi_Perf/network_WiFi_Perf.py
index c75e053..430bd65 100644
--- a/server/site_tests/network_WiFi_Perf/network_WiFi_Perf.py
+++ b/server/site_tests/network_WiFi_Perf/network_WiFi_Perf.py
@@ -7,8 +7,10 @@
 
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.common_lib import utils
+from autotest_lib.client.common_lib.cros.network import interface
 from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
 from autotest_lib.server.cros.network import expected_performance_results
+from autotest_lib.server.cros.network import ip_config_context_manager
 from autotest_lib.server.cros.network import netperf_runner
 from autotest_lib.server.cros.network import netperf_session
 from autotest_lib.server.cros.network import wifi_cell_test_base
@@ -39,6 +41,11 @@
                     netperf_runner.NetperfConfig.TEST_TYPE_UDP_BIDIRECTIONAL),
     ]
 
+    DEFAULT_ROUTER_LAN_IP_ADDRESS = "192.168.1.50"
+    DEFAULT_PCAP_LAN_IP_ADDRESS = "192.168.1.51"
+    DEFAULT_ROUTER_LAN_IFACE_NAME = "eth1"
+    DEFAULT_PCAP_LAN_IFACE_NAME = "eth1"
+
     def parse_additional_arguments(self, commandline_args, additional_params):
         """Hook into super class to take control files parameters.
 
@@ -47,6 +54,18 @@
         """
         self._should_required = 'should' in commandline_args
         self._power_save_off = 'power_save_off' in commandline_args
+
+        get_arg_value_or_default = lambda attr, default: commandline_args[
+                attr] if attr in commandline_args else default
+        self._router_lan_ip_addr = get_arg_value_or_default(
+                'router_lan_ip_addr', self.DEFAULT_ROUTER_LAN_IP_ADDRESS)
+        self._router_lan_iface_name = get_arg_value_or_default(
+                'router_lan_iface_name', self.DEFAULT_ROUTER_LAN_IFACE_NAME)
+        self._pcap_lan_ip_addr = get_arg_value_or_default(
+                'pcap_lan_ip_addr', self.DEFAULT_PCAP_LAN_IP_ADDRESS)
+        self._pcap_lan_iface_name = get_arg_value_or_default(
+                'pcap_lan_iface_name', self.DEFAULT_PCAP_LAN_IFACE_NAME)
+
         if 'governor' in commandline_args:
             self._governor = commandline_args['governor']
             # validate governor string. Not all machines will support all of
@@ -225,17 +244,45 @@
                     ssid=self.context.router.get_ssid(),
                     security_config=ap_config.security_config)
             self.context.assert_connect_wifi(assoc_params)
-            session = netperf_session.NetperfSession(self.context.client,
-                                                     self.context.router)
 
-            # Flag a test error if we disconnect for any reason.
-            with self.context.client.assert_no_disconnects():
-                for governor in sorted(set([None, self._governor])):
-                    # Run the performance test and record the test types
-                    # which failed due to low throughput.
-                    low_throughput_tests.update(
-                            self.do_run(ap_config, session,
-                                        not (self._power_save_off), governor))
+            with ip_config_context_manager.IpConfigContextManager(
+            ) as ip_context:
+
+                ip_context.bring_interface_up(self.context.router.host,
+                                              self._router_lan_iface_name)
+                ip_context.bring_interface_up(self.context.pcap_host.host,
+                                              self._pcap_lan_iface_name)
+                ip_context.assign_ip_addr_to_iface(self.context.router.host,
+                                                   self._router_lan_ip_addr,
+                                                   self._router_lan_iface_name)
+                ip_context.assign_ip_addr_to_iface(self.context.pcap_host.host,
+                                                   self._pcap_lan_ip_addr,
+                                                   self._pcap_lan_iface_name)
+                ip_context.add_ip_route(self.context.client.host,
+                                        self._pcap_lan_ip_addr,
+                                        self.context.router.wifi_ip,
+                                        self.context.client.wifi_if)
+                ip_context.add_ip_route(self.context.pcap_host.host,
+                                        self.context.client.wifi_ip,
+                                        self._router_lan_ip_addr,
+                                        self._router_lan_iface_name)
+
+                pcap_lan_iface = interface.Interface(
+                        self._pcap_lan_iface_name, self.context.pcap_host.host)
+                session = netperf_session.NetperfSession(
+                        self.context.client,
+                        self.context.pcap_host,
+                        server_interface=pcap_lan_iface)
+
+                # Flag a test error if we disconnect for any reason.
+                with self.context.client.assert_no_disconnects():
+                    for governor in sorted(set([None, self._governor])):
+                        # Run the performance test and record the test types
+                        # which failed due to low throughput.
+                        low_throughput_tests.update(
+                                self.do_run(ap_config, session,
+                                            not (self._power_save_off),
+                                            governor))
 
             # Clean up router and client state for the next run.
             self.context.client.shill.disconnect(self.context.router.get_ssid())