tests: Close wpa_supplicant control interface more robustly

Some of the test cases left behind attached control interface monitor
sockets that could result in hitting the wpa_supplicant socket TX queue
limit. Try to be a bit more careful about detaching and closing the
sockets to avoid this.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2019-03-17 15:26:34 +02:00
parent 4d916a7f3e
commit b21540e682
4 changed files with 105 additions and 42 deletions

View file

@ -1,5 +1,5 @@
# P2P helper functions # P2P helper functions
# Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi> # Copyright (c) 2013-2019, Jouni Malinen <j@w1.fi>
# #
# This software may be distributed under the terms of the BSD license. # This software may be distributed under the terms of the BSD license.
# See README for more details. # See README for more details.
@ -105,6 +105,7 @@ def go_neg_pin_authorized_persistent(i_dev, r_dev, i_intent=None, r_intent=None,
def terminate_group(go, cli): def terminate_group(go, cli):
logger.info("Terminate persistent group") logger.info("Terminate persistent group")
cli.close_monitor_group()
go.remove_group() go.remove_group()
cli.wait_go_ending_session() cli.wait_go_ending_session()

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# #
# Test case executor # Test case executor
# Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi> # Copyright (c) 2013-2019, Jouni Malinen <j@w1.fi>
# #
# This software may be distributed under the terms of the BSD license. # This software may be distributed under the terms of the BSD license.
# See README for more details. # See README for more details.
@ -63,6 +63,7 @@ def reset_devs(dev, apdev):
pass pass
if wpas: if wpas:
wpas.close_ctrl() wpas.close_ctrl()
del wpas
try: try:
hapd = HostapdGlobal() hapd = HostapdGlobal()
@ -560,7 +561,8 @@ def main():
reset_ok = reset_devs(dev, apdev) reset_ok = reset_devs(dev, apdev)
wpas = None wpas = None
try: try:
wpas = WpaSupplicant(global_iface="/tmp/wpas-wlan5") wpas = WpaSupplicant(global_iface="/tmp/wpas-wlan5",
monitor=False)
rename_log(args.logdir, 'log5', name, wpas) rename_log(args.logdir, 'log5', name, wpas)
if not args.no_reset: if not args.no_reset:
wpas.remove_ifname() wpas.remove_ifname()
@ -568,6 +570,7 @@ def main():
pass pass
if wpas: if wpas:
wpas.close_ctrl() wpas.close_ctrl()
del wpas
for i in range(0, 3): for i in range(0, 3):
rename_log(args.logdir, 'log' + str(i), name, dev[i]) rename_log(args.logdir, 'log' + str(i), name, dev[i])

View file

@ -1,5 +1,5 @@
# Test cases for MACsec/MKA # Test cases for MACsec/MKA
# Copyright (c) 2018, Jouni Malinen <j@w1.fi> # Copyright (c) 2018-2019, Jouni Malinen <j@w1.fi>
# #
# This software may be distributed under the terms of the BSD license. # This software may be distributed under the terms of the BSD license.
# See README for more details. # See README for more details.
@ -17,9 +17,10 @@ import hwsim_utils
from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
def cleanup_macsec(): def cleanup_macsec():
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False)
wpas.interface_remove("veth0") wpas.interface_remove("veth0")
wpas.interface_remove("veth1") wpas.interface_remove("veth1")
del wpas
subprocess.call(["ip", "link", "del", "veth0"], subprocess.call(["ip", "link", "del", "veth0"],
stderr=open('/dev/null', 'w')) stderr=open('/dev/null', 'w'))
@ -34,8 +35,9 @@ def test_macsec_psk_mka_life_time(dev, apdev, params):
"""MACsec PSK - MKA life time""" """MACsec PSK - MKA life time"""
try: try:
run_macsec_psk(dev, apdev, params, "macsec_psk_mka_life_time") run_macsec_psk(dev, apdev, params, "macsec_psk_mka_life_time")
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False)
wpas.interface_remove("veth1") wpas.interface_remove("veth1")
del wpas
# Wait for live peer to be removed on veth0 # Wait for live peer to be removed on veth0
time.sleep(6.1) time.sleep(6.1)
finally: finally:
@ -319,7 +321,7 @@ def run_macsec_psk(dev, apdev, params, prefix, integ_only=False, port0=None,
cmd[i].terminate() cmd[i].terminate()
def cleanup_macsec_br(count): def cleanup_macsec_br(count):
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False)
for i in range(count): for i in range(count):
wpas.interface_remove("veth%d" % i) wpas.interface_remove("veth%d" % i)
subprocess.call(["ip", "link", "del", "veth%d" % i], subprocess.call(["ip", "link", "del", "veth%d" % i],
@ -428,8 +430,9 @@ def run_macsec_psk_br(dev, apdev, count, mka_priority):
logger.info("Data traffic test failed - ignore for now for >= 3 device cases") logger.info("Data traffic test failed - ignore for now for >= 3 device cases")
for i in range(count): for i in range(count):
wpa[i].dump_monitor() wpa[i].close_monitor()
for i in range(count): for i in range(count):
wpa[0].close_control()
del wpa[0] del wpa[0]
def test_macsec_psk_ns(dev, apdev, params): def test_macsec_psk_ns(dev, apdev, params):
@ -651,9 +654,13 @@ def run_macsec_psk_ns(dev, apdev, params):
if "2 packets transmitted, 2 received" not in res: if "2 packets transmitted, 2 received" not in res:
raise Exception("ping did not work") raise Exception("ping did not work")
wpas0.close_monitor()
wpas0.request("TERMINATE") wpas0.request("TERMINATE")
wpas0.close_control()
del wpas0 del wpas0
wpas1.close_monitor()
wpas1.request("TERMINATE") wpas1.request("TERMINATE")
wpas1.close_control()
del wpas1 del wpas1
time.sleep(1) time.sleep(1)

View file

@ -23,7 +23,12 @@ class WpaSupplicant:
self.monitor = monitor self.monitor = monitor
self.hostname = hostname self.hostname = hostname
self.group_ifname = None self.group_ifname = None
self.global_mon = None
self.global_ctrl = None
self.gctrl_mon = None self.gctrl_mon = None
self.ctrl = None
self.mon = None
self.ifname = None
self.host = remotehost.Host(hostname, ifname) self.host = remotehost.Host(hostname, ifname)
self._group_dbg = None self._group_dbg = None
if ifname: if ifname:
@ -33,12 +38,9 @@ class WpaSupplicant:
self.p2p_dev_ifname = 'p2p-dev-' + self.ifname self.p2p_dev_ifname = 'p2p-dev-' + self.ifname
else: else:
self.p2p_dev_ifname = ifname self.p2p_dev_ifname = ifname
else:
self.ifname = None
self.global_iface = global_iface self.global_iface = global_iface
if global_iface: if global_iface:
self.global_mon = None
if hostname != None: if hostname != None:
self.global_ctrl = wpaspy.Ctrl(hostname, global_port) self.global_ctrl = wpaspy.Ctrl(hostname, global_port)
if self.monitor: if self.monitor:
@ -51,8 +53,77 @@ class WpaSupplicant:
self.global_dbg = "" self.global_dbg = ""
if self.monitor: if self.monitor:
self.global_mon.attach() self.global_mon.attach()
else:
self.global_mon = None def __del__(self):
self.close_monitor()
self.close_control()
def close_control_ctrl(self):
if self.ctrl:
del self.ctrl
self.ctrl = None
def close_control_global(self):
if self.global_ctrl:
del self.global_ctrl
self.global_ctrl = None
def close_control(self):
self.close_control_ctrl()
self.close_control_global()
def close_monitor_mon(self):
if not self.mon:
return
try:
while self.mon.pending():
ev = self.mon.recv()
logger.debug(self.dbg + ": " + ev)
except:
pass
try:
self.mon.detach()
except ConnectionRefusedError:
pass
del self.mon
self.mon = None
def close_monitor_global(self):
if not self.global_mon:
return
try:
while self.global_mon.pending():
ev = self.global_mon.recv()
logger.debug(self.global_dbg + ": " + ev)
except:
pass
try:
self.global_mon.detach()
except ConnectionRefusedError:
pass
del self.global_mon
self.global_mon = None
def close_monitor_group(self):
if not self.gctrl_mon:
return
try:
while self.gctrl_mon.pending():
ev = self.gctrl_mon.recv()
logger.debug(self.dbg + ": " + ev)
except:
pass
try:
self.gctrl_mon.detach()
except:
pass
del self.gctrl_mon
self.gctrl_mon = None
def close_monitor(self):
self.close_monitor_mon()
self.close_monitor_global()
self.close_monitor_group()
def cmd_execute(self, cmd_array, shell=False): def cmd_execute(self, cmd_array, shell=False):
if self.hostname is None: if self.hostname is None:
@ -70,19 +141,17 @@ class WpaSupplicant:
def terminate(self): def terminate(self):
if self.global_mon: if self.global_mon:
self.global_mon.detach() self.close_monitor_global()
self.global_mon = None
self.global_ctrl.terminate() self.global_ctrl.terminate()
self.global_ctrl = None self.global_ctrl = None
def close_ctrl(self): def close_ctrl(self):
if self.global_mon: self.close_monitor_global()
self.global_mon.detach() self.close_control_global()
self.global_mon = None
self.global_ctrl = None
self.remove_ifname() self.remove_ifname()
def set_ifname(self, ifname, hostname=None, port=9877): def set_ifname(self, ifname, hostname=None, port=9877):
self.remove_ifname()
self.ifname = ifname self.ifname = ifname
if hostname != None: if hostname != None:
self.ctrl = wpaspy.Ctrl(hostname, port) self.ctrl = wpaspy.Ctrl(hostname, port)
@ -99,11 +168,9 @@ class WpaSupplicant:
self.mon.attach() self.mon.attach()
def remove_ifname(self): def remove_ifname(self):
if self.ifname: self.close_monitor_mon()
self.mon.detach() self.close_control_ctrl()
self.mon = None self.ifname = None
self.ctrl = None
self.ifname = None
def get_ctrl_iface_port(self, ifname): def get_ctrl_iface_port(self, ifname):
if self.hostname is None: if self.hostname is None:
@ -217,12 +284,7 @@ class WpaSupplicant:
self.global_request("REMOVE_NETWORK all") self.global_request("REMOVE_NETWORK all")
self.global_request("SET p2p_no_group_iface 1") self.global_request("SET p2p_no_group_iface 1")
self.global_request("P2P_FLUSH") self.global_request("P2P_FLUSH")
if self.gctrl_mon: self.close_monitor_group()
try:
self.gctrl_mon.detach()
except:
pass
self.gctrl_mon = None
self.group_ifname = None self.group_ifname = None
self.dump_monitor() self.dump_monitor()
@ -814,12 +876,7 @@ class WpaSupplicant:
return self.wait_event(events, timeout) return self.wait_event(events, timeout)
def wait_go_ending_session(self): def wait_go_ending_session(self):
if self.gctrl_mon: self.close_monitor_group()
try:
self.gctrl_mon.detach()
except:
pass
self.gctrl_mon = None
timeout = 3 if self.hostname is None else 10 timeout = 3 if self.hostname is None else 10
ev = self.wait_global_event(["P2P-GROUP-REMOVED"], timeout=timeout) ev = self.wait_global_event(["P2P-GROUP-REMOVED"], timeout=timeout)
if ev is None: if ev is None:
@ -841,12 +898,7 @@ class WpaSupplicant:
return (count_iface, count_global) return (count_iface, count_global)
def remove_group(self, ifname=None): def remove_group(self, ifname=None):
if self.gctrl_mon: self.close_monitor_group()
try:
self.gctrl_mon.detach()
except:
pass
self.gctrl_mon = None
if ifname is None: if ifname is None:
ifname = self.group_ifname if self.group_ifname else self.ifname ifname = self.group_ifname if self.group_ifname else self.ifname
if "OK" not in self.global_request("P2P_GROUP_REMOVE " + ifname): if "OK" not in self.global_request("P2P_GROUP_REMOVE " + ifname):