@@ -58,16 +58,19 @@ def exit_vm():
runner.stop()
class Interface:
- def __init__(self, name, config):
+ def __init__(self, name, config, ns=None):
self.name = name
self.ctrl_interface = '/var/run/hostapd/' + name
self.config = config
+ self.ns = ns
def __del__(self):
- Process(['iw', 'dev', self.name, 'del']).wait()
+ Process(['iw', 'dev', self.name, 'del'],
+ namespace=self.ns.name if self.ns else None).wait()
def set_interface_state(self, state):
- Process(['ip', 'link', 'set', self.name, state]).wait()
+ Process(['ip', 'link', 'set', self.name, state],
+ namespace=self.ns.name if self.ns else None).wait()
class Radio:
def __init__(self, name):
@@ -75,11 +78,16 @@ class Radio:
# hostapd will reset this if this radio is used by it
self.use = 'iwd'
self.interface = None
+ self.ns = None
def __del__(self):
print("Removing radio %s" % self.name)
self.interface = None
+ def set_namespace(self, ns):
+ self.ns = ns
+ Process(['iw', 'phy', self.name, 'set', 'netns', 'name', ns.name]).wait()
+
def create_interface(self, config, use):
global intf_id
@@ -87,19 +95,21 @@ class Radio:
intf_id += 1
- self.interface = Interface(ifname, config)
+ self.interface = Interface(ifname, config, ns=self.ns)
self.use = use
Process(['iw', 'phy', self.name, 'interface', 'add', ifname,
- 'type', 'managed']).wait()
+ 'type', 'managed'], namespace=self.ns.name if self.ns else None).wait()
return self.interface
def __str__(self):
ret = self.name + ':\n'
- ret += '\tUsed By: %s ' % self.use
+ ret += '\tUsed By: %s' % self.use
if self.interface:
- ret += '(%s)' % self.interface.name
+ ret += ' (%s)' % self.interface.name
+ if self.ns is not None:
+ ret += ' (ns=%s)' % self.ns.name
ret += '\n'
@@ -188,7 +198,7 @@ class Hostapd:
A set of running hostapd instances. This is really just a single
process since hostapd can be started with multiple config files.
'''
- def __init__(self, radios, configs, radius):
+ def __init__(self, ns, radios, configs, radius):
if len(configs) != len(radios):
raise Exception("Config (%d) and radio (%d) list length not equal" % \
(len(configs), len(radios)))
@@ -198,8 +208,8 @@ class Hostapd:
Process(['ip', 'link', 'set', 'eth0', 'up']).wait()
Process(['ip', 'link', 'set', 'eth1', 'up']).wait()
- self.global_ctrl_iface = '/var/run/hostapd/ctrl'
-
+ self.ns = ns
+ self.global_ctrl_iface = '/var/run/hostapd/ctrl' + (str(ns.name) if ns.name else 'main')
self.instances = [HostapdInstance(c, r) for c, r in zip(configs, radios)]
ifaces = [rad.interface.name for rad in radios]
@@ -227,7 +237,7 @@ class Hostapd:
if Process.is_verbose('hostapd'):
args.append('-d')
- self.process = Process(args)
+ self.process = Process(args, namespace=ns.name)
self.process.wait_for_socket(self.global_ctrl_iface, 30)
@@ -397,32 +407,42 @@ class TestContext(Namespace):
# tests. In this case you would not care what
# was using each radio, just that there was
# enough to run all tests.
- nradios = 0
- for k, _ in settings.items():
- if k == 'radius_server':
- continue
- nradios += 1
-
- hapd_radios = self.radios[:nradios]
-
+ hapd_configs = [conf for rad, conf in settings.items() if rad != 'radius_server']
+ hapd_processes = [(self, self.radios[:len(hapd_configs)], hapd_configs)]
else:
- hapd_radios = [rad for rad in self.radios if rad.name in settings]
-
- hapd_configs = [conf for rad, conf in settings.items() if rad != 'radius_server']
+ hapd_processes = []
+ for ns in [self] + self.namespaces:
+ ns_radios = [rad for rad in ns.radios if rad.name in settings]
+ if len(ns_radios):
+ ns_configs = [settings[rad.name] for rad in ns_radios]
+ hapd_processes.append((ns, ns_radios, ns_configs))
radius_config = settings.get('radius_server', None)
- self.hostapd = Hostapd(hapd_radios, hapd_configs, radius_config)
- self.hostapd.attach_cli()
+ self.hostapd = [Hostapd(ns, radios, configs, radius_config)
+ for ns, radios, configs in hapd_processes]
+
+ for hapd in self.hostapd:
+ hapd.attach_cli()
def get_frequencies(self):
frequencies = []
- for hapd in self.hostapd.instances:
- frequencies.append(hapd.cli.frequency)
+ for hapd in self.hostapd:
+ frequencies += [instance.cli.frequency for instance in hapd.instances]
return frequencies
+ def get_hapd_instance(self, config=None):
+ instances = [i for hapd in self.hostapd for i in hapd.instances]
+
+ if config is None:
+ return instances[0]
+
+ for hapd in instances:
+ if hapd.config == config:
+ return hapd
+
def start_wpas_interfaces(self):
if 'WPA_SUPPLICANT' not in self.hw_config:
return
@@ -543,11 +563,13 @@ class TestContext(Namespace):
for arg in vars(self.args):
ret += '\t --%s %s\n' % (arg, str(getattr(self.args, arg)))
- ret += 'Hostapd:\n'
if self.hostapd:
- for h in self.hostapd.instances:
- ret += '\t%s\n' % str(h)
+ for hapd in self.hostapd:
+ ret += 'Hostapd (ns=%s):\n' % (hapd.ns.name,)
+ for h in hapd.instances:
+ ret += '\t%s\n' % (str(h),)
else:
+ ret += 'Hostapd:\n'
ret += '\tNo Hostapd instances\n'
info = self.meminfo_to_dict()
@@ -324,7 +324,7 @@ class Namespace:
Process(['ip', 'netns', 'add', name]).wait()
for r in radios:
- Process(['iw', 'phy', r.name, 'set', 'netns', 'name', name]).wait()
+ r.set_namespace(self)
self.start_dbus()