diff mbox

[2/2] test: verify correct vlan operation in multi-bss multi-vlan case

Message ID 1430118484-30111-2-git-send-email-michael-dev@fami-braun.de
State Accepted
Headers show

Commit Message

michael-dev April 27, 2015, 7:08 a.m. UTC
This adds hwsim test ap_vlan_iface_cleanup_multibss. It connects two stations
in different BSS but the same hostapd process. First both stations are in
VLAN 1, then they get reauthenticated into VLAN 2. Due to the ordering of the
stations moving around, this patch checks that bridge and tagged interface
referencing counting is done globally, such that the tagged interface is not
removed too early and not bridge is left over.

Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
---
 tests/hwsim/hostapd.py           |   5 +-
 tests/hwsim/multi-bss-iface.conf |  41 ++++++++++
 tests/hwsim/test_ap_vlan.py      | 156 +++++++++++++++++++++++++++++++++++++++
 tests/hwsim/utils.py             |  13 ++++
 4 files changed, 213 insertions(+), 2 deletions(-)
 create mode 100644 tests/hwsim/multi-bss-iface.conf

Comments

Jouni Malinen May 3, 2015, 6:37 p.m. UTC | #1
On Mon, Apr 27, 2015 at 09:08:04AM +0200, Michael Braun wrote:
> This adds hwsim test ap_vlan_iface_cleanup_multibss. It connects two stations
> in different BSS but the same hostapd process. First both stations are in
> VLAN 1, then they get reauthenticated into VLAN 2. Due to the ordering of the
> stations moving around, this patch checks that bridge and tagged interface
> referencing counting is done globally, such that the tagged interface is not
> removed too early and not bridge is left over.

This seems to fail for me with "Exception: dummy0.1 not in brvlan1". The
reason for that shows up in hostapd log:

VLAN: Set interface brvlan1 up
VLAN: Set interface dummy0 up
VLAN: vlan_add(if_name=dummy0, vid=1, vlan_if_name=dummy0.1)
VLAN: failed to create link dummy0.1 for vlan 1 on dummy0 (11)
VLAN: br_addif(brvlan1, dummy0.1)
VLAN: br_addif: Failure determining interface index for 'dummy0.1'
VLAN: Set interface dummy0.1 up
VLAN: ifconfig_helper: ioctl(SIOCGIFFLAGS) failed for interface dummy0.1: No such device


Any idea what would be causing this? I already had to add CONFIG_DUMMY=y
to get even this far, but that did not seem to be enough to make the
test case work for me.
michael-dev June 9, 2015, 7:56 a.m. UTC | #2
Hi,

is there anything left I can do about it?

Would you mind trying this again now that 9649b534 is applied, so there
should be a more readable error message in the log (I belive you were
testing with hostapd config CONFIG_VLAN_NETLINK=y set).

Thanks,
M. Braun


Am 03.05.2015 um 20:37 schrieb Jouni Malinen:
> On Mon, Apr 27, 2015 at 09:08:04AM +0200, Michael Braun wrote:
>> This adds hwsim test ap_vlan_iface_cleanup_multibss. It connects two stations
>> in different BSS but the same hostapd process. First both stations are in
>> VLAN 1, then they get reauthenticated into VLAN 2. Due to the ordering of the
>> stations moving around, this patch checks that bridge and tagged interface
>> referencing counting is done globally, such that the tagged interface is not
>> removed too early and not bridge is left over.
> 
> This seems to fail for me with "Exception: dummy0.1 not in brvlan1". The
> reason for that shows up in hostapd log:
> 
> VLAN: Set interface brvlan1 up
> VLAN: Set interface dummy0 up
> VLAN: vlan_add(if_name=dummy0, vid=1, vlan_if_name=dummy0.1)
> VLAN: failed to create link dummy0.1 for vlan 1 on dummy0 (11)
> VLAN: br_addif(brvlan1, dummy0.1)
> VLAN: br_addif: Failure determining interface index for 'dummy0.1'
> VLAN: Set interface dummy0.1 up
> VLAN: ifconfig_helper: ioctl(SIOCGIFFLAGS) failed for interface dummy0.1: No such device
> 
> 
> Any idea what would be causing this? I already had to add CONFIG_DUMMY=y
> to get even this far, but that did not seem to be enough to make the
> test case work for me.
>
diff mbox

Patch

diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py
index 83defb0..d726ca1 100644
--- a/tests/hwsim/hostapd.py
+++ b/tests/hwsim/hostapd.py
@@ -49,16 +49,17 @@  class HostapdGlobal:
 
 
 class Hostapd:
-    def __init__(self, ifname):
+    def __init__(self, ifname, bssidx=0):
         self.ifname = ifname
         self.ctrl = wpaspy.Ctrl(os.path.join(hapd_ctrl, ifname))
         self.mon = wpaspy.Ctrl(os.path.join(hapd_ctrl, ifname))
         self.mon.attach()
         self.bssid = None
+        self.bssidx = bssidx
 
     def own_addr(self):
         if self.bssid is None:
-            self.bssid = self.get_status_field('bssid[0]')
+            self.bssid = self.get_status_field('bssid['+str(self.bssidx)+']')
         return self.bssid
 
     def request(self, cmd):
diff --git a/tests/hwsim/multi-bss-iface.conf b/tests/hwsim/multi-bss-iface.conf
new file mode 100644
index 0000000..115358a
--- /dev/null
+++ b/tests/hwsim/multi-bss-iface.conf
@@ -0,0 +1,41 @@ 
+driver=nl80211
+
+hw_mode=g
+channel=0
+ieee80211n=1
+
+interface=wlan3
+ctrl_interface=/var/run/hostapd
+
+ssid=bss-1
+dynamic_vlan=1
+vlan_tagged_interface=dummy0
+vlan_bridge=brvlan
+wpa=2
+wpa_key_mgmt=WPA-EAP
+rsn_pairwise=CCMP
+ieee8021x=1
+auth_server_addr=127.0.0.1
+auth_server_port=18128
+auth_server_shared_secret=radius
+nas_identifier=nas.w1.fi
+vlan_naming=1
+
+bss=wlan3-2
+bssid=02:00:00:00:03:01
+ctrl_interface=/var/run/hostapd
+ssid=bss-2
+
+dynamic_vlan=1
+vlan_tagged_interface=dummy0
+vlan_bridge=brvlan
+wpa=2
+wpa_key_mgmt=WPA-EAP
+rsn_pairwise=CCMP
+ieee8021x=1
+auth_server_addr=127.0.0.1
+auth_server_port=18128
+auth_server_shared_secret=radius
+nas_identifier=nas.w1.fi
+vlan_naming=1
+
diff --git a/tests/hwsim/test_ap_vlan.py b/tests/hwsim/test_ap_vlan.py
index 5a8af73..f5348a5 100644
--- a/tests/hwsim/test_ap_vlan.py
+++ b/tests/hwsim/test_ap_vlan.py
@@ -13,6 +13,8 @@  logger = logging.getLogger(__name__)
 
 import hwsim_utils
 import hostapd
+import netifaces
+from utils import iface_is_in_bridge
 
 def test_ap_vlan_open(dev, apdev):
     """AP VLAN with open network"""
@@ -195,3 +197,157 @@  def test_ap_vlan_tagged(dev, apdev):
     hwsim_utils.test_connectivity_iface(dev[0], hapd, "brlo.1")
     hwsim_utils.test_connectivity_iface(dev[1], hapd, "brlo.2")
     hwsim_utils.test_connectivity(dev[2], hapd)
+
+def helper_ap_vlan_iface_cleanup_multibss_cleanup():
+    subprocess.call(['ifconfig','dummy0','down'],
+                    stderr=open('/dev/null', 'w'))
+    subprocess.call(['ip','link','del','wlan3.1'],
+                    stderr=open('/dev/null', 'w'))
+    subprocess.call(['ip','link','del','wlan3.2'],
+                    stderr=open('/dev/null', 'w'))
+    subprocess.call(['ip','link','del','wlan3-2.1'],
+                    stderr=open('/dev/null', 'w'))
+    subprocess.call(['ip','link','del','wlan3-2.2'],
+                    stderr=open('/dev/null', 'w'))
+    subprocess.call(['ip','link','del','dummy0.2'],
+                    stderr=open('/dev/null', 'w'))
+    subprocess.call(['ip','link','del','dummy0.1'],
+                    stderr=open('/dev/null', 'w'))
+    subprocess.call(['ip','link','del','dummy0'],
+                    stderr=open('/dev/null', 'w'))
+    subprocess.call(['ip','link','del','brvlan1'],
+                    stderr=open('/dev/null', 'w'))
+    subprocess.call(['ip','link','del','brvlan2'],
+                    stderr=open('/dev/null', 'w'))
+
+def test_ap_vlan_iface_cleanup_multibss(dev, apdev):
+    """AP VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID
+       check that multiple bss do not interfere with each other with respect
+       to deletion of bridge and tagged interface
+    """
+    try:
+        helper_ap_vlan_iface_cleanup_multibss_cleanup()
+        subprocess.call(['ip','link','add','dummy0','type','dummy'])
+        subprocess.call(['ifconfig','dummy0','up'])
+
+        as_params = { "ssid": "as",
+                      "beacon_int": "2000",
+                      "radius_server_clients": "auth_serv/radius_clients.conf",
+                      "radius_server_auth_port": '18128',
+                      "eap_server": "1",
+                      "eap_user_file": "auth_serv/eap_user.conf",
+                      "ca_cert": "auth_serv/ca.pem",
+                      "server_cert": "auth_serv/server.pem",
+                      "private_key": "auth_serv/server.key",
+                      "vlan_naming": "1" }
+        authserv = hostapd.add_ap(apdev[1]['ifname'], as_params)
+
+        ifname = apdev[0]['ifname']
+
+        # start the actual test
+        hostapd.add_iface(ifname, 'multi-bss-iface.conf')
+        hapd = hostapd.Hostapd(ifname)
+        hapd1 = hostapd.Hostapd("wlan3-2",1)
+        hapd1.enable()
+
+        freq = hapd.get_status_field("freq")
+
+        ifaces = netifaces.interfaces()
+        if "brvlan1" in ifaces:
+            raise Exception("bridge brvlan1 already exists before")
+        if "brvlan2" in ifaces:
+            raise Exception("bridge brvlan2 already exists before")
+
+        dev[0].connect("bss-1", key_mgmt="WPA-EAP", eap="PAX",
+                       identity="vlan1",
+                       password_hex="0123456789abcdef0123456789abcdef",
+                       scan_freq=freq)
+
+        ifaces = netifaces.interfaces()
+        if not("brvlan1" in ifaces):
+            raise Exception("bridge brvlan1 was not created")
+
+        hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
+        if not iface_is_in_bridge("brvlan1", "dummy0.1"):
+            raise Exception("dummy0.1 not in brvlan1")
+
+        dev[1].connect("bss-2", key_mgmt="WPA-EAP", eap="PAX",
+                       identity="vlan1",
+                       password_hex="0123456789abcdef0123456789abcdef",
+                       scan_freq=freq)
+
+        hwsim_utils.test_connectivity_iface(dev[1], hapd1, "brvlan1")
+        if not iface_is_in_bridge("brvlan1", "dummy0.1"):
+            raise Exception("dummy0.1 not in brvlan1")
+
+        authserv.disable()
+        authserv.set('eap_user_file', "auth_serv/eap_user_vlan.conf")
+        authserv.enable()
+
+        logger.info("wlan0 -> VLAN 2")
+
+        dev[0].dump_monitor()
+        dev[0].request("REAUTHENTICATE")
+        ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
+        if ev is None:
+            raise Exception("EAP reauthentication timed out")
+        ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=5)
+        if ev is None:
+            raise Exception("4-way handshake after reauthentication timed out")
+        state = dev[0].get_status_field('wpa_state')
+        if state != "COMPLETED":
+            raise Exception("Unexpected state after reauth: " + state)
+
+        ifaces = netifaces.interfaces()
+        if not ("brvlan1" in ifaces):
+            raise Exception("bridge brvlan1 has been removed too early")
+
+        hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan2")
+
+        if not iface_is_in_bridge("brvlan2", "dummy0.2"):
+            raise Exception("dummy0.2 not in brvlan2")
+
+        logger.info("test wlan1 == VLAN 1")
+        hwsim_utils.test_connectivity_iface(dev[1], hapd1, "brvlan1")
+        if not iface_is_in_bridge("brvlan1", "dummy0.1"):
+            raise Exception("dummy0.1 not in brvlan1")
+
+        logger.info("wlan1 -> VLAN 2")
+
+        dev[1].dump_monitor()
+        dev[1].request("REAUTHENTICATE")
+        ev = dev[1].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
+        if ev is None:
+            raise Exception("EAP reauthentication timed out")
+        ev = dev[1].wait_event(["WPA: Key negotiation completed"], timeout=5)
+        if ev is None:
+            raise Exception("4-way handshake after reauthentication timed out")
+        state = dev[1].get_status_field('wpa_state')
+        if state != "COMPLETED":
+            raise Exception("Unexpected state after reauth: " + state)
+
+        hwsim_utils.test_connectivity_iface(dev[1], hapd1, "brvlan2")
+        logger.info("test wlan0 == VLAN 2")
+        hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan2")
+
+        if not iface_is_in_bridge("brvlan2", "dummy0.2"):
+            raise Exception("dummy0.2 not in brvlan2")
+
+        ifaces = netifaces.interfaces()
+        if "brvlan1" in ifaces:
+            raise Exception("bridge brvlan1 has not been cleaned up")
+
+        # disconnect dev0 first to test a corner case
+        dev[0].request("DISCONNECT")
+        dev[0].wait_disconnected()
+        dev[1].request("DISCONNECT")
+        dev[1].wait_disconnected()
+        time.sleep(5) # station removal needs some time
+
+        ifaces = netifaces.interfaces()
+        if "brvlan2" in ifaces:
+            raise Exception("bridge brvlan2 has not been cleaned up")
+
+        hapd.request("DISABLE")
+    finally:
+        helper_ap_vlan_iface_cleanup_multibss_cleanup()
diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py
index 43dd331..2769e19 100644
--- a/tests/hwsim/utils.py
+++ b/tests/hwsim/utils.py
@@ -4,6 +4,8 @@ 
 # This software may be distributed under the terms of the BSD license.
 # See README for more details.
 
+import os
+
 def get_ifnames():
     ifnames = []
     with open("/proc/net/dev", "r") as f:
@@ -39,3 +41,14 @@  def require_under_vm():
         cmd = f.read()
         if "inside.sh" not in cmd:
             raise HwsimSkip("Not running under VM")
+
+def iface_is_in_bridge(bridge, ifname):
+    fname = "/sys/class/net/"+ifname+"/brport/bridge"
+    if not os.path.exists(fname):
+        return False
+    if not os.path.islink(fname):
+        return False
+    truebridge = os.path.basename(os.readlink(fname))
+    if bridge == truebridge:
+        return True
+    return False