Create hostap instance for FrameSender on whirlwind

Creating an AP mode interface was enough to allow packet injection
with wireless-3.18 (CL:287305). Moving to wireless-4.2, ath10k
started using channel context. Using hostap configures the channel
context and makes packet injection work with wireless-4.2.

BUG=chromium:755268
TEST=network_WiFi_MalformedProbeResp
TEST=network_WiFi_ChannelScanDwellTime
(on stumpy stable (R47-7424), whirlwind stable (R50-7849)
and whirlwind dev build)

Change-Id: I011a28c9782021e5b442660bedc78d30c8a90ccc
Reviewed-on: https://chromium-review.googlesource.com/621298
Commit-Ready: Edward Hill <ecgh@chromium.org>
Tested-by: Edward Hill <ecgh@chromium.org>
Reviewed-by: Brian Norris <briannorris@chromium.org>
diff --git a/server/cros/network/frame_sender.py b/server/cros/network/frame_sender.py
index d7ca96a..98968e0 100644
--- a/server/cros/network/frame_sender.py
+++ b/server/cros/network/frame_sender.py
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from autotest_lib.server.cros.network import hostap_config
+from autotest_lib.client.common_lib import error
 
 class FrameSender(object):
     """Context manager for sending management frames."""
@@ -10,7 +10,7 @@
 
     def __init__(self, router, frame_type, channel, ssid_prefix=None,
                  num_bss=None, frame_count=None, delay=None, dest_addr=None,
-                 probe_resp_footer=None):
+                 probe_resp_footer=None, instance=0):
         """
         @param router: LinuxRouter object router to send frames from.
         @param frame_type: int management frame type.
@@ -22,11 +22,13 @@
         @param delay: int delay in between frames in milliseconds.
         @param dest_addr: MAC address of the destination address (DA).
         @param probe_resp_footer: footer bytes for probe responses.
+        @param instance: int hostapd instance on router to send frames from.
         """
+        if router.board == "panther":
+            raise error.TestNAError('Panther router does not support manual '
+                                    'beacon frame generation')
         self._router = router
         self._channel = channel
-        self._frequency = (
-            hostap_config.HostapConfig.get_frequency_for_channel(channel))
         self._frame_type = frame_type
         self._ssid_prefix = ssid_prefix
         self._num_bss = num_bss
@@ -34,16 +36,12 @@
         self._delay = delay
         self._dest_addr = dest_addr
         self._probe_resp_footer = probe_resp_footer
-        self._ap_interface = None
+        self._ap_interface = router.hostapd_instances[instance].interface
         self._injection_interface = None
         self._pid = None
 
 
     def __enter__(self):
-        # Some chips don't allow beacon or probe response injection,
-        # unless an AP mode interface is present.
-        self._ap_interface = self._router.get_configured_interface(
-            '__ap', frequency=self._frequency)
         self._injection_interface = self._router.get_configured_interface(
             'monitor', same_phy_as=self._ap_interface)
         self._pid = self._router.send_management_frame(
@@ -58,6 +56,5 @@
     def __exit__(self, exception, value, traceback):
         if self._injection_interface:
             self._router.release_interface(self._injection_interface)
-            self._router.release_interface(self._ap_interface)
         if self._pid:
             self._router.host.run('kill %d' % self._pid, ignore_status=True)
diff --git a/server/site_linux_router.py b/server/site_linux_router.py
index 9fdc2cf..fa51a04 100644
--- a/server/site_linux_router.py
+++ b/server/site_linux_router.py
@@ -886,23 +886,6 @@
         self.release_interface(interface)
 
 
-    def setup_management_frame_interface(self, channel):
-        """
-        Setup interface for injecting management frames.
-
-        @param channel int channel to inject the frames.
-
-        @return string name of the interface.
-
-        """
-        frequency = hostap_config.HostapConfig.get_frequency_for_channel(
-                channel)
-        interface = self.get_wlanif(frequency, 'monitor')
-        self.router.run('%s link set %s up' % (self.cmd_ip, interface))
-        self.iw_runner.set_freq(interface, frequency)
-        return interface
-
-
     def send_management_frame(self, interface, frame_type, channel,
                               ssid_prefix=None, num_bss=None,
                               frame_count=None, delay=None,
diff --git a/server/site_tests/network_WiFi_ChannelScanDwellTime/network_WiFi_ChannelScanDwellTime.py b/server/site_tests/network_WiFi_ChannelScanDwellTime/network_WiFi_ChannelScanDwellTime.py
index c0928e0..b83e72d 100644
--- a/server/site_tests/network_WiFi_ChannelScanDwellTime/network_WiFi_ChannelScanDwellTime.py
+++ b/server/site_tests/network_WiFi_ChannelScanDwellTime/network_WiFi_ChannelScanDwellTime.py
@@ -116,6 +116,8 @@
         dwell_time = 0
         channel = hostap_config.HostapConfig.get_channel_for_frequency(
             self.FREQUENCY_MHZ)
+        # Configure an AP to inject beacons.
+        self.context.configure(hostap_config.HostapConfig(channel=channel))
         self.context.capture_host.start_capture(self.FREQUENCY_MHZ)
         ssid_prefix = self._build_ssid_prefix()
 
@@ -168,12 +170,8 @@
 
 
     def run_once(self):
-        if self.context.router.board == "panther":
-            raise error.TestNAError('Panther router does not support manual '
-                                    'beacon frame generation')
         self.context.router.require_capabilities(
-                  [site_linux_system.LinuxSystem.
-                          CAPABILITY_SEND_MANAGEMENT_FRAME])
+            [site_linux_system.LinuxSystem.CAPABILITY_SEND_MANAGEMENT_FRAME])
         # Claim the control over the wifi interface from WiFiClient, which
         # will prevent shill and wpa_supplicant from managing that interface.
         # So this test can have the sole ownership of the interface and can
diff --git a/server/site_tests/network_WiFi_MalformedProbeResp/network_WiFi_MalformedProbeResp.py b/server/site_tests/network_WiFi_MalformedProbeResp/network_WiFi_MalformedProbeResp.py
index 93606f0..737b7e1 100644
--- a/server/site_tests/network_WiFi_MalformedProbeResp/network_WiFi_MalformedProbeResp.py
+++ b/server/site_tests/network_WiFi_MalformedProbeResp/network_WiFi_MalformedProbeResp.py
@@ -24,16 +24,16 @@
 
     def run_once(self):
         """Sets up a router, connects to it, pings it, and repeats."""
-        if self.context.router.board == "panther":
-            raise error.TestNAError('Panther router does not support manual '
-                                    'beacon frame generation')
         configuration = hostap_config.HostapConfig(
                 channel=self.PROBE_RESPONSE_TEST_CHANNEL,
                 mode=hostap_config.HostapConfig.MODE_11B)
         self.context.router.require_capabilities(
-            [site_linux_system.LinuxSystem.CAPABILITY_SEND_MANAGEMENT_FRAME])
+            [site_linux_system.LinuxSystem.CAPABILITY_SEND_MANAGEMENT_FRAME,
+             site_linux_system.LinuxSystem.CAPABILITY_MULTI_AP_SAME_BAND])
 
         self.context.configure(configuration)
+        # Configure 2nd AP to inject the malformed probe responses.
+        self.context.configure(configuration, multi_interface=True)
         client_mac = self.context.client.wifi_mac
 
         pretest_reset_count = self.context.client.get_num_card_resets()
@@ -42,7 +42,7 @@
                 configuration.frequency,
                 ht_type=configuration.ht_packet_capture_mode)
         assoc_params = xmlrpc_datatypes.AssociationParameters()
-        assoc_params.ssid = self.context.router.get_ssid()
+        assoc_params.ssid = self.context.router.get_ssid(instance=0)
         assoc_result = self.context.assert_connect_wifi(assoc_params)
         start_time = time.time()
         count = 1
@@ -58,7 +58,8 @@
                     frame_count=0,
                     delay=self.PROBE_RESPONSE_DELAY_MSEC,
                     dest_addr=client_mac,
-                    probe_resp_footer='\xdd\xb7\x00\x1a\x11\x01\x01\x02\x03'):
+                    probe_resp_footer='\xdd\xb7\x00\x1a\x11\x01\x01\x02\x03',
+                    instance=1):
                 while time.time() - start_time < self.SCAN_LOOP_SEC:
                     bss_list = self.context.client.iw_runner.scan(
                             self.context.client.wifi_if, [2412])