autotest: WiFi: Allow stopping of individual hostapd instances

Allow the "deconfig" command to take an instance number to
be removed.  In order to allow this to happen, we need to
be able to do an individual interface remove (for "silent mode"
deconfig) and hostapd kill for a specific interface.

BUG=chrome-os-partner:15005
TEST=Tested for regression using network_WiFiRoaming/006BeaconLoss.
Testing for functionality using new PMKSA test.

Change-Id: Icb146b2759bf65caef931b65d81a2a90c7309234
Reviewed-on: https://gerrit.chromium.org/gerrit/39320
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/server/site_linux_router.py b/server/site_linux_router.py
index 769e059..3833cb1 100644
--- a/server/site_linux_router.py
+++ b/server/site_linux_router.py
@@ -147,7 +147,7 @@
             'interface': conf['interface']
         })
 
-    def kill_hostapd(self):
+    def kill_hostapd_instance(self, instance):
         """
         Kills the hostapd process.  Makes sure hostapd exits before
         continuing since it sets the interface back to station mode in its
@@ -155,11 +155,20 @@
         previous instance exits, the interface station mode will overwrite the
         ap mode.
         """
-        self.router.run("pkill hostapd >/dev/null 2>&1 && "
-                        "while pgrep hostapd &> /dev/null; do sleep 1; done",
+        if instance:
+            search_arg = '-f "hostapd.*%s"' % instance['conf_file']
+        else:
+            search_arg = 'hostapd'
+
+        self.router.run("pkill %s >/dev/null 2>&1 && "
+                        "while pgrep %s &> /dev/null; "
+                        "do sleep 1; done" % (search_arg, search_arg),
                         timeout=30,
                         ignore_status=True)
 
+    def kill_hostapd(self):
+        self.kill_hostapd_instance(None)
+
     def hostap_config(self, params):
         """ Configure the AP per test requirements """
 
@@ -459,15 +468,20 @@
         if not self.hostapd['configured'] and not self.station['configured']:
             return
 
-        # Taking down hostapd takes wlan0 and mon.wlan0 down.
         if self.hostapd['configured']:
-            if 'silent' in params:
-                # Deconfigure without notifying DUT.  Remove the monitor
-                # interface hostapd uses to send beacon and DEAUTH packets
-                self._remove_interfaces()
+            if 'instance' in params:
+                instances = [ self.hostapd_instances.pop(params['instance']) ]
+            else:
+                instances = self.hostapd_instances
+                self.hostapd_instances = []
 
-            self.kill_hostapd()
-            for instance in self.hostapd_instances:
+            for instance in instances:
+                if 'silent' in params:
+                    # Deconfigure without notifying DUT.  Remove the interface
+                    # hostapd uses to send beacon and DEAUTH packets.
+                    self._remove_interface(instance['interface'], True)
+
+                self.kill_hostapd_instance(instance)
                 self.router.get_file(instance['log_file'],
                                      'debug/hostapd_router_%d_%s.log' %
                                      (self.hostapd['log_count'],
@@ -475,7 +489,6 @@
                 self._release_wlanif(instance['interface'])
 #               self.router.run("rm -f %(log_file)s %(conf_file)s" % instance)
             self.hostapd['log_count'] += 1
-            self.hostapd_instances = []
         if self.station['configured']:
             if self.station['type'] == 'ibss':
                 self.router.run("%s dev %s ibss leave" %
@@ -490,7 +503,8 @@
             self.stop_dhcp_servers()
             for server in self.local_servers:
                 self.router.run("%s addr del %s" %
-                                (self.cmd_ip, server['ip_params']))
+                                (self.cmd_ip, server['ip_params']),
+                                ignore_status=True)
             self.local_servers = []
 
         self.hostapd['configured'] = False