Add regulatory test for channel move

Inject an 802.11h Spectrum Management Channel Switch Action Frame
into an actively running 802.11 connection and ensure that the
client vacates the channel.

CQ-DEPEND=CL:*39532
BUG=chrome-os-partner:19953
TEST=This is a test; Passes with Lumpy.  Fails with daisy ToT, and
passes with daisy with kernel changes to support 802.11h.

Change-Id: I25a5d35e5a7f0c429ea52eb38ab9a8fce6c27211
Reviewed-on: https://gerrit.chromium.org/gerrit/58431
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
Commit-Queue: Paul Stewart <pstew@chromium.org>
diff --git a/server/site_linux_router.py b/server/site_linux_router.py
index 3af1d05..c1e8466 100644
--- a/server/site_linux_router.py
+++ b/server/site_linux_router.py
@@ -33,6 +33,18 @@
     """
 
 
+    def get_capabilities(self):
+        """@return iterable object of AP capabilities for this system."""
+        caps = set()
+        try:
+            self.cmd_send_management_frame = wifi_test_utils.must_be_installed(
+                    self.router, '/usr/bin/send_management_frame')
+            caps.add(self.CAPABILITY_SEND_MANAGEMENT_FRAME)
+        except error.TestFail:
+            pass
+        return super(LinuxRouter, self).get_capabilities().union(caps)
+
+
     def __init__(self, host, params, defssid):
         """Build a LinuxRouter.
 
@@ -737,6 +749,21 @@
                          params['client']))
 
 
+    def send_management_frame(self, frame_type, instance=0):
+        """Injects a management frame into an active hostapd session.
+
+        @param frame_type string the type of frame to send.
+        @param instance int indicating which hostapd instance to inject into.
+
+        """
+        hostap_interface = self.hostapd_instances[instance]['interface']
+        interface = self._get_wlanif(0, 'monitor', same_phy_as=hostap_interface)
+        self.router.run("%s link set %s up" % (self.cmd_ip, interface))
+        self.router.run('%s %s %s' %
+                        (self.cmd_send_management_frame, interface, frame_type))
+        self._release_wlanif(interface)
+
+
     def _pre_config_hook(self, config):
         """Hook for subclasses.