All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/6] station: reorder AP roam logic
@ 2022-09-28 16:36 James Prestwood
  2022-09-28 16:36 ` [PATCH 2/6] auto-t: set disassociation imminent for bss transitions James Prestwood
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: James Prestwood @ 2022-09-28 16:36 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

There are a few checks that can be done prior to parsing the
request, in addition the explicit check for preparing_roam was
removed since this is taken care of by station_cannot_roam().
---
 src/station.c | 55 +++++++++++++++++++++++----------------------------
 1 file changed, 25 insertions(+), 30 deletions(-)

diff --git a/src/station.c b/src/station.c
index 4e07ef19..061e8747 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2763,6 +2763,31 @@ static void station_ap_directed_roam(struct station *station,
 	if (station_cannot_roam(station))
 		return;
 
+	if (station->state != STATION_STATE_CONNECTED) {
+		l_debug("roam: unexpected AP directed roam -- ignore");
+		return;
+	}
+
+	/*
+	 * Sanitize the frame to check that it is from our current AP.
+	 *
+	 * 802.11-2020 Section 9.3.3.1 about Address2:
+	 * "If the STA is an AP with dot11MultiBSSDImplemented set to false,
+	 * then this address is the BSSID."
+	 *
+	 * Address3:
+	 * "If the STA is an AP or PCP, the Address 3 field is the same as the
+	 * Address 2 field."
+	 *
+	 * For now check that Address2 & Address3 is the same as the connected
+	 * BSS address.
+	 */
+	if (memcmp(hdr->address_2, station->connected_bss, ETH_ALEN) ||
+			memcmp(hdr->address_2, hdr->address_3, ETH_ALEN)) {
+		l_debug("roam: AP directed roam not from our AP -- ignore");
+		return;
+	}
+
 	if (body_len < 7)
 		goto format_error;
 
@@ -2816,36 +2841,6 @@ static void station_ap_directed_roam(struct station *station,
 		pos += url_len;
 	}
 
-	if (station->state != STATION_STATE_CONNECTED) {
-		l_debug("roam: unexpected AP directed roam -- ignore");
-		return;
-	}
-
-	/*
-	 * Sanitize the frame to check that it is from our current AP.
-	 *
-	 * 802.11-2020 Section 9.3.3.1 about Address2:
-	 * "If the STA is an AP with dot11MultiBSSDImplemented set to false,
-	 * then this address is the BSSID."
-	 *
-	 * Address3:
-	 * "If the STA is an AP or PCP, the Address 3 field is the same as the
-	 * Address 2 field."
-	 *
-	 * For now check that Address2 & Address3 is the same as the connected
-	 * BSS address.
-	 */
-	if (memcmp(hdr->address_2, station->connected_bss, ETH_ALEN) ||
-			memcmp(hdr->address_2, hdr->address_3, ETH_ALEN)) {
-		l_debug("roam: AP directed roam not from our AP -- ignore");
-		return;
-	}
-
-	if (station->preparing_roam) {
-		l_debug("roam: roam attempt already in progress -- ignore");
-		return;
-	}
-
 	station->ap_directed_roaming = true;
 	station->preparing_roam = true;
 
-- 
2.34.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/6] auto-t: set disassociation imminent for bss transitions
  2022-09-28 16:36 [PATCH 1/6] station: reorder AP roam logic James Prestwood
@ 2022-09-28 16:36 ` James Prestwood
  2022-09-28 16:36 ` [PATCH 3/6] station: check disassociation bits for AP roaming James Prestwood
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2022-09-28 16:36 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

Allow the caller to set the disassociation imminent bit when
sending the BSS transition request.
---
 autotests/util/hostapd.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/autotests/util/hostapd.py b/autotests/util/hostapd.py
index d6c13e2b..bb27686f 100644
--- a/autotests/util/hostapd.py
+++ b/autotests/util/hostapd.py
@@ -199,7 +199,7 @@ class HostapdCLI(object):
         cmd = self.cmdline + ['remove_neighbor', addr]
         ctx.start_process(cmd).wait()
 
-    def send_bss_transition(self, device, nr_list):
+    def send_bss_transition(self, device, nr_list, disassoc_imminent=True):
         # Send a BSS transition to a station (device). nr_list should be an
         # array of tuples containing the BSS address and neighbor report.
         # Parsing the neighbor report is a bit ugly but it makes it more
@@ -207,6 +207,10 @@ class HostapdCLI(object):
         # string could be used in both API's.
         pref = 1
         cmd = self.cmdline + ['bss_tm_req', device]
+
+        if disassoc_imminent:
+            cmd.append('disassoc_imminent=1')
+
         for i in nr_list:
             addr = i[0]
             nr = i[1]
-- 
2.34.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/6] station: check disassociation bits for AP roaming
  2022-09-28 16:36 [PATCH 1/6] station: reorder AP roam logic James Prestwood
  2022-09-28 16:36 ` [PATCH 2/6] auto-t: set disassociation imminent for bss transitions James Prestwood
@ 2022-09-28 16:36 ` James Prestwood
  2022-09-28 16:36 ` [PATCH 4/6] auto-t: change wait_for_object_change behavior James Prestwood
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2022-09-28 16:36 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

AP roaming was structured such that any AP roam request would
force IWD to roam (assuming BSS's were found in scan results).
This isn't always the best behavior since IWD may be connected
to the best BSS in range.

Only force a roam if the AP includes one of the 3 disassociation/
termination bits. Otherwise attempt to roam but don't set the
ap_directed_roaming flag which will allows IWD to stay with the
current BSS if no better candidates are found.
---
 src/station.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/station.c b/src/station.c
index 061e8747..2ae8a6bf 100644
--- a/src/station.c
+++ b/src/station.c
@@ -2746,6 +2746,7 @@ static bool station_cannot_roam(struct station *station)
 }
 
 #define WNM_REQUEST_MODE_PREFERRED_CANDIDATE_LIST	(1 << 0)
+#define WNM_REQUEST_MODE_DISASSOCIATION_IMMINENT	(1 << 2)
 #define WNM_REQUEST_MODE_TERMINATION_IMMINENT		(1 << 3)
 #define WNM_REQUEST_MODE_ESS_DISASSOCIATION_IMMINENT	(1 << 4)
 
@@ -2818,7 +2819,20 @@ static void station_ap_directed_roam(struct station *station,
 			dtimer, valid_interval,
 			MAC_STR(hdr->address_3));
 
-	/* check req_mode for optional values */
+	/*
+	 * The ap_directed_roaming flag forces IWD to roam if there are any
+	 * candidates, even if they are worse than the current BSS. This isn't
+	 * always a good idea since we may be associated to the best BSS. Where
+	 * this does matter is if the AP indicates its going down or will be
+	 * disassociating us. If either of these bits are set, set the
+	 * ap_directed_roaming flag. Otherwise still try roaming but don't
+	 * treat it any different than a normal roam.
+	 */
+	if (req_mode & (WNM_REQUEST_MODE_DISASSOCIATION_IMMINENT |
+			WNM_REQUEST_MODE_TERMINATION_IMMINENT |
+			WNM_REQUEST_MODE_ESS_DISASSOCIATION_IMMINENT))
+		station->ap_directed_roaming = true;
+
 	if (req_mode & WNM_REQUEST_MODE_TERMINATION_IMMINENT) {
 		if (pos + 12 > body_len)
 			goto format_error;
@@ -2841,7 +2855,6 @@ static void station_ap_directed_roam(struct station *station,
 		pos += url_len;
 	}
 
-	station->ap_directed_roaming = true;
 	station->preparing_roam = true;
 
 	l_timeout_remove(station->roam_trigger_timeout);
-- 
2.34.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/6] auto-t: change wait_for_object_change behavior
  2022-09-28 16:36 [PATCH 1/6] station: reorder AP roam logic James Prestwood
  2022-09-28 16:36 ` [PATCH 2/6] auto-t: set disassociation imminent for bss transitions James Prestwood
  2022-09-28 16:36 ` [PATCH 3/6] station: check disassociation bits for AP roaming James Prestwood
@ 2022-09-28 16:36 ` James Prestwood
  2022-09-28 16:36 ` [PATCH 5/6] auto-t: update uses of wait_for_object_change James Prestwood
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2022-09-28 16:36 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

Instead of requiring the initial condition be met when calling
wait_for_object_change, wait for it.

This is how every caller of this function uses it, specifically
with roaming where we first wait for DeviceState.roaming, then
call wait_for_object_change. This can be simplified for the caller
so the initial condition is first waited for.
---
 autotests/util/iwd.py | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/autotests/util/iwd.py b/autotests/util/iwd.py
index 5f5699df..a9df0dca 100755
--- a/autotests/util/iwd.py
+++ b/autotests/util/iwd.py
@@ -1160,7 +1160,7 @@ class IWD(AsyncOpAbstract):
 
     def wait_for_object_change(self, obj, from_str, to_str, max_wait = 50):
         '''
-            Expects condition 'from_str' to evaluate true while waiting for 'to_str'. If
+            Wait for 'from_str' to evaluate true then waits for 'to_str'. If
             at any point during the wait 'from_str' evaluates false, an exception is
             raised.
 
@@ -1180,9 +1180,8 @@ class IWD(AsyncOpAbstract):
 
             return False
 
-        # Does initial condition pass?
-        if not eval(from_str):
-            raise Exception("initial condition [%s] not met" % from_str)
+        # wait for initial condition
+        self._wait_for_object_condition(obj, from_str)
 
         ctx.non_block_wait(_eval_from_to, max_wait, obj, from_str, to_str,
                             exception=TimeoutError('[' + to_str + ']'\
-- 
2.34.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/6] auto-t: update uses of wait_for_object_change
  2022-09-28 16:36 [PATCH 1/6] station: reorder AP roam logic James Prestwood
                   ` (2 preceding siblings ...)
  2022-09-28 16:36 ` [PATCH 4/6] auto-t: change wait_for_object_change behavior James Prestwood
@ 2022-09-28 16:36 ` James Prestwood
  2022-09-28 16:36 ` [PATCH 6/6] auto-t: add a no candidate test to testAPRoam James Prestwood
  2022-09-28 17:36 ` [PATCH 1/6] station: reorder AP roam logic Denis Kenzior
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2022-09-28 16:36 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

This removes waiting for DeviceState.roaming, which is now done
automatically by wait_for_object_change.
---
 autotests/testFT-8021x-roam/connection_test.py | 3 ---
 autotests/testFT-FILS/connection_test.py       | 3 ---
 autotests/testOWE/connection_test.py           | 3 ---
 autotests/testPSK-roam/connection_test.py      | 6 ------
 autotests/testPreauth-roam/connection_test.py  | 3 ---
 autotests/testRoamRetry/fast_retry_test.py     | 3 ---
 autotests/testRoamRetry/stop_retry_test.py     | 3 ---
 autotests/testSAE-roam/connection_test.py      | 3 ---
 8 files changed, 27 deletions(-)

diff --git a/autotests/testFT-8021x-roam/connection_test.py b/autotests/testFT-8021x-roam/connection_test.py
index d3f8e2c6..356a9af2 100644
--- a/autotests/testFT-8021x-roam/connection_test.py
+++ b/autotests/testFT-8021x-roam/connection_test.py
@@ -37,9 +37,6 @@ class Test(unittest.TestCase):
 
         device.roam(self.bss_hostapd[1].bssid)
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
         # Check that iwd is on BSS 1 once out of roaming state and doesn't
         # go through 'disconnected', 'autoconnect', 'connecting' in between
         from_condition = 'obj.state == DeviceState.roaming'
diff --git a/autotests/testFT-FILS/connection_test.py b/autotests/testFT-FILS/connection_test.py
index 5d60bf4d..28aaa955 100644
--- a/autotests/testFT-FILS/connection_test.py
+++ b/autotests/testFT-FILS/connection_test.py
@@ -70,9 +70,6 @@ class Test(unittest.TestCase):
         #rule0.signal = -8000
         device.roam(self.bss_hostapd[1].bssid)
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
         # Check that iwd is on BSS 1 once out of roaming state and doesn't
         # go through 'disconnected', 'autoconnect', 'connecting' in between
         from_condition = 'obj.state == DeviceState.roaming'
diff --git a/autotests/testOWE/connection_test.py b/autotests/testOWE/connection_test.py
index 391d8cf5..1fdc990a 100644
--- a/autotests/testOWE/connection_test.py
+++ b/autotests/testOWE/connection_test.py
@@ -53,9 +53,6 @@ class Test(unittest.TestCase):
 
         device.roam(hapd1.bssid)
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
         from_condition = 'obj.state == DeviceState.roaming'
         to_condition = 'obj.state == DeviceState.connected'
         wd.wait_for_object_change(device, from_condition, to_condition)
diff --git a/autotests/testPSK-roam/connection_test.py b/autotests/testPSK-roam/connection_test.py
index 2206f120..7a135e95 100644
--- a/autotests/testPSK-roam/connection_test.py
+++ b/autotests/testPSK-roam/connection_test.py
@@ -52,9 +52,6 @@ class Test(unittest.TestCase):
         else:
             device.roam(self.bss_hostapd[1].bssid)
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
         # Check that iwd is on BSS 1 once out of roaming state and doesn't
         # go through 'disconnected', 'autoconnect', 'connecting' in between
         from_condition = 'obj.state == DeviceState.roaming'
@@ -76,9 +73,6 @@ class Test(unittest.TestCase):
 
         device.roam(self.bss_hostapd[0].bssid)
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
         # Check that iwd is on BSS 0 once out of roaming state and doesn't
         # go through 'disconnected', 'autoconnect', 'connecting' in between
         from_condition = 'obj.state == DeviceState.roaming'
diff --git a/autotests/testPreauth-roam/connection_test.py b/autotests/testPreauth-roam/connection_test.py
index 02d03361..87799df1 100644
--- a/autotests/testPreauth-roam/connection_test.py
+++ b/autotests/testPreauth-roam/connection_test.py
@@ -48,9 +48,6 @@ class Test(unittest.TestCase):
 
         device.roam(bss1_addr)
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
         # TODO: verify that the PMK from preauthentication was used
 
         # Check that iwd is on BSS 1 once out of roaming state and doesn't
diff --git a/autotests/testRoamRetry/fast_retry_test.py b/autotests/testRoamRetry/fast_retry_test.py
index 373f3d45..d380b2e3 100644
--- a/autotests/testRoamRetry/fast_retry_test.py
+++ b/autotests/testRoamRetry/fast_retry_test.py
@@ -91,9 +91,6 @@ class Test(unittest.TestCase):
         rule0.signal = -8000
         rule1.signal = -2000
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
         # Check that iwd is on BSS 1 once out of roaming state and doesn't
         # go through 'disconnected', 'autoconnect', 'connecting' in between
         from_condition = 'obj.state == DeviceState.roaming'
diff --git a/autotests/testRoamRetry/stop_retry_test.py b/autotests/testRoamRetry/stop_retry_test.py
index b5eb6f77..e46b79d7 100644
--- a/autotests/testRoamRetry/stop_retry_test.py
+++ b/autotests/testRoamRetry/stop_retry_test.py
@@ -67,9 +67,6 @@ class Test(unittest.TestCase):
         # connects to BSS 1
         rule0.signal = -8000
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
         # Check that iwd is on BSS 1 once out of roaming state and doesn't
         # go through 'disconnected', 'autoconnect', 'connecting' in between
         from_condition = 'obj.state == DeviceState.roaming'
diff --git a/autotests/testSAE-roam/connection_test.py b/autotests/testSAE-roam/connection_test.py
index ac44b4b2..ca7234a6 100644
--- a/autotests/testSAE-roam/connection_test.py
+++ b/autotests/testSAE-roam/connection_test.py
@@ -39,9 +39,6 @@ class Test(unittest.TestCase):
 
         device.roam(self.bss_hostapd[1].bssid)
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
         # Check that iwd is on BSS 1 once out of roaming state and doesn't
         # go through 'disconnected', 'autoconnect', 'connecting' in between
         from_condition = 'obj.state == DeviceState.roaming'
-- 
2.34.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 6/6] auto-t: add a no candidate test to testAPRoam
  2022-09-28 16:36 [PATCH 1/6] station: reorder AP roam logic James Prestwood
                   ` (3 preceding siblings ...)
  2022-09-28 16:36 ` [PATCH 5/6] auto-t: update uses of wait_for_object_change James Prestwood
@ 2022-09-28 16:36 ` James Prestwood
  2022-09-28 17:36 ` [PATCH 1/6] station: reorder AP roam logic Denis Kenzior
  5 siblings, 0 replies; 7+ messages in thread
From: James Prestwood @ 2022-09-28 16:36 UTC (permalink / raw)
  To: iwd; +Cc: James Prestwood

This tests the new behavior where the roam request does not
indicate disassociation is imminent. In this case if no
candidates are found IWD should not roam.
---
 autotests/testAPRoam/connection_test.py | 43 ++++++++++++++-----------
 1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/autotests/testAPRoam/connection_test.py b/autotests/testAPRoam/connection_test.py
index 41d70f3a..a419f4aa 100644
--- a/autotests/testAPRoam/connection_test.py
+++ b/autotests/testAPRoam/connection_test.py
@@ -12,11 +12,7 @@ from hostapd import HostapdCLI
 
 class Test(unittest.TestCase):
 
-    def test_connection_success(self):
-        bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
-                        HostapdCLI(config='ssid2.conf'),
-                        HostapdCLI(config='ssid3.conf') ]
-
+    def validate(self, expect_roam=True):
         wd = IWD()
 
         devices = wd.list_devices(1)
@@ -29,38 +25,47 @@ class Test(unittest.TestCase):
         condition = 'not obj.connected'
         wd.wait_for_object_condition(ordered_network.network_object, condition)
 
-        device.connect_bssid(bss_hostapd[0].bssid)
+        device.connect_bssid(self.bss_hostapd[0].bssid)
 
         condition = 'obj.state == DeviceState.connected'
         wd.wait_for_object_condition(device, condition)
 
-        bss_hostapd[0].wait_for_event('AP-STA-CONNECTED')
-
-        self.assertFalse(bss_hostapd[1].list_sta())
+        self.bss_hostapd[0].wait_for_event('AP-STA-CONNECTED')
 
-        bss_hostapd[0].send_bss_transition(device.address,
-                [(bss_hostapd[1].bssid, '8f0000005102060603000000')])
+        self.assertFalse(self.bss_hostapd[1].list_sta())
 
-        condition = 'obj.state == DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
-
-        condition = 'obj.state != DeviceState.roaming'
-        wd.wait_for_object_condition(device, condition)
+        self.bss_hostapd[0].send_bss_transition(device.address,
+                [(self.bss_hostapd[1].bssid, '8f0000005102060603000000')],
+                disassoc_imminent=expect_roam)
 
-        condition = 'obj.state == DeviceState.connected'
-        wd.wait_for_object_condition(device, condition)
+        if expect_roam:
+            from_condition = 'obj.state == DeviceState.roaming'
+            to_condition = 'obj.state == DeviceState.connected'
+            wd.wait_for_object_change(device, from_condition, to_condition)
 
-        bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
+            self.bss_hostapd[1].wait_for_event('AP-STA-CONNECTED %s' % device.address)
+        else:
+            device.wait_for_event("no-roam-candidates")
 
         device.disconnect()
 
         condition = 'not obj.connected'
         wd.wait_for_object_condition(ordered_network.network_object, condition)
 
+    def test_disassoc_imminent(self):
+        self.validate(expect_roam=True)
+
+    def test_no_candidates(self):
+        self.validate(expect_roam=False)
+
     @classmethod
     def setUpClass(cls):
         IWD.copy_to_storage('TestAPRoam.psk')
 
+        cls.bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
+                            HostapdCLI(config='ssid2.conf'),
+                            HostapdCLI(config='ssid3.conf') ]
+
     @classmethod
     def tearDownClass(cls):
         IWD.clear_storage()
-- 
2.34.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/6] station: reorder AP roam logic
  2022-09-28 16:36 [PATCH 1/6] station: reorder AP roam logic James Prestwood
                   ` (4 preceding siblings ...)
  2022-09-28 16:36 ` [PATCH 6/6] auto-t: add a no candidate test to testAPRoam James Prestwood
@ 2022-09-28 17:36 ` Denis Kenzior
  5 siblings, 0 replies; 7+ messages in thread
From: Denis Kenzior @ 2022-09-28 17:36 UTC (permalink / raw)
  To: James Prestwood, iwd

Hi James,

On 9/28/22 11:36, James Prestwood wrote:
> There are a few checks that can be done prior to parsing the
> request, in addition the explicit check for preparing_roam was
> removed since this is taken care of by station_cannot_roam().
> ---
>   src/station.c | 55 +++++++++++++++++++++++----------------------------
>   1 file changed, 25 insertions(+), 30 deletions(-)
> 

All applied, thanks.

Regards,
-Denis


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-09-28 17:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-28 16:36 [PATCH 1/6] station: reorder AP roam logic James Prestwood
2022-09-28 16:36 ` [PATCH 2/6] auto-t: set disassociation imminent for bss transitions James Prestwood
2022-09-28 16:36 ` [PATCH 3/6] station: check disassociation bits for AP roaming James Prestwood
2022-09-28 16:36 ` [PATCH 4/6] auto-t: change wait_for_object_change behavior James Prestwood
2022-09-28 16:36 ` [PATCH 5/6] auto-t: update uses of wait_for_object_change James Prestwood
2022-09-28 16:36 ` [PATCH 6/6] auto-t: add a no candidate test to testAPRoam James Prestwood
2022-09-28 17:36 ` [PATCH 1/6] station: reorder AP roam logic Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.