All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/8] netdev: Track SET_INTERFACE events
@ 2021-04-20 16:35 Denis Kenzior
  2021-04-20 16:35 ` [PATCH 2/8] frame-xchg: iftype changes to be managed by netdev Denis Kenzior
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Denis Kenzior @ 2021-04-20 16:35 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 2304 bytes --]

And set the interface type based on the event rather than the command
callback.  This allows us to track interface type changes even if they
come from outside iwd (which shouldn't happen.)
---
 src/netdev.c | 47 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 41 insertions(+), 6 deletions(-)

diff --git a/src/netdev.c b/src/netdev.c
index a63c6b12a5d1..05e22148e495 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -4867,6 +4867,43 @@ static int netdev_cqm_rssi_update(struct netdev *netdev)
 	return 0;
 }
 
+static void netdev_set_interface_event(struct l_genl_msg *msg,
+							struct netdev *netdev)
+{
+	uint32_t iftype;
+
+	if (nl80211_parse_attrs(msg, NL80211_ATTR_IFTYPE, &iftype,
+					NL80211_ATTR_UNSPEC) < 0)
+		return;
+
+	if (iftype == netdev->type)
+		return;
+
+	l_debug("Interface type changed from %s to %s",
+			netdev_iftype_to_string(netdev->type),
+			netdev_iftype_to_string(iftype));
+	netdev->type = iftype;
+
+	/* Set RSSI threshold for CQM notifications */
+	if (netdev->type == NL80211_IFTYPE_STATION)
+		netdev_cqm_rssi_update(netdev);
+}
+
+static void netdev_config_notify(struct l_genl_msg *msg, void *user_data)
+{
+	struct netdev *netdev;
+
+	netdev = netdev_from_message(msg);
+	if (!netdev)
+		return;
+
+	switch (l_genl_msg_get_command(msg)) {
+	case NL80211_CMD_SET_INTERFACE:
+		netdev_set_interface_event(msg, netdev);
+		break;
+	}
+}
+
 static struct l_genl_msg *netdev_build_cmd_set_interface(struct netdev *netdev,
 							uint32_t iftype)
 {
@@ -4927,12 +4964,6 @@ static void netdev_set_iftype_cb(struct l_genl_msg *msg, void *user_data)
 	if (error != 0)
 		goto done;
 
-	netdev->type = req->pending_type;
-
-	/* Set RSSI threshold for CQM notifications */
-	if (netdev->type == NL80211_IFTYPE_STATION)
-		netdev_cqm_rssi_update(netdev);
-
 	/* If the netdev was down originally, we're done */
 	if (!req->bring_up)
 		goto done;
@@ -5635,6 +5666,10 @@ static int netdev_init(void)
 								NULL, NULL))
 		l_error("Registering for scan notifications failed");
 
+	if (!l_genl_family_register(nl80211, "config", netdev_config_notify,
+								NULL, NULL))
+		l_error("Registering for config notifications failed");
+
 	return 0;
 
 fail_netlink:
-- 
2.26.3

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

* [PATCH 2/8] frame-xchg: iftype changes to be managed by netdev
  2021-04-20 16:35 [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
@ 2021-04-20 16:35 ` Denis Kenzior
  2021-04-20 16:35 ` [PATCH 3/8] netdev: Re-add frame watches on iftype change Denis Kenzior
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2021-04-20 16:35 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 1952 bytes --]

Since netdev now keeps track of iftype changes, let it call
frame_watch_wdev_remove on netdevs that it manages to clear frame
registrations that should be cleared due to an iftype change.

Note that P2P_DEVICE wdevs are not managed by any netdev object, but
since their iftype cannot be changed, they should not be affected
by this change.
---
 src/frame-xchg.c | 7 +------
 src/netdev.c     | 3 +++
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/frame-xchg.c b/src/frame-xchg.c
index e01747326fc5..85f55f2bf941 100644
--- a/src/frame-xchg.c
+++ b/src/frame-xchg.c
@@ -1312,7 +1312,6 @@ static void frame_xchg_config_notify(struct l_genl_msg *msg, void *user_data)
 		if (!wdev) {
 			wdev = l_new(struct wdev_info, 1);
 			wdev->id = wdev_id;
-			wdev->iftype = iftype;
 
 			if (!wdevs)
 				wdevs = l_queue_new();
@@ -1321,11 +1320,7 @@ static void frame_xchg_config_notify(struct l_genl_msg *msg, void *user_data)
 			break;
 		}
 
-		if (wdev->iftype != iftype) {
-			wdev->iftype = iftype;
-			frame_watch_wdev_remove(wdev_id);
-		}
-
+		wdev->iftype = iftype;
 		break;
 
 	case NL80211_CMD_DEL_INTERFACE:
diff --git a/src/netdev.c b/src/netdev.c
index 05e22148e495..f4877bbd6fbb 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -4871,8 +4871,10 @@ static void netdev_set_interface_event(struct l_genl_msg *msg,
 							struct netdev *netdev)
 {
 	uint32_t iftype;
+	uint64_t wdev_id;
 
 	if (nl80211_parse_attrs(msg, NL80211_ATTR_IFTYPE, &iftype,
+					NL80211_ATTR_WDEV, &wdev_id,
 					NL80211_ATTR_UNSPEC) < 0)
 		return;
 
@@ -4883,6 +4885,7 @@ static void netdev_set_interface_event(struct l_genl_msg *msg,
 			netdev_iftype_to_string(netdev->type),
 			netdev_iftype_to_string(iftype));
 	netdev->type = iftype;
+	frame_watch_wdev_remove(wdev_id);
 
 	/* Set RSSI threshold for CQM notifications */
 	if (netdev->type == NL80211_IFTYPE_STATION)
-- 
2.26.3

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

* [PATCH 3/8] netdev: Re-add frame watches on iftype change
  2021-04-20 16:35 [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
  2021-04-20 16:35 ` [PATCH 2/8] frame-xchg: iftype changes to be managed by netdev Denis Kenzior
@ 2021-04-20 16:35 ` Denis Kenzior
  2021-04-20 16:35 ` [PATCH 4/8] rrm: Track that station is removed Denis Kenzior
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2021-04-20 16:35 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 4902 bytes --]

If the iftype changes, kernel silently wipes out any frame registrations
we may have registered.  Right now, frame registrations are only done when
the interface is created.  This can result in frame watches not being
added if the interface type is changed between station mode to ap mode
and then back to station mode, e.g.:

device wlan0 set-property Mode ap
device wlan0 set-property Mode station

Make sure to re-add frame registrations according to the mode if the
interface type is changed.
---
 src/netdev.c | 80 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 47 insertions(+), 33 deletions(-)

diff --git a/src/netdev.c b/src/netdev.c
index f4877bbd6fbb..4208deea35fa 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -4867,6 +4867,51 @@ static int netdev_cqm_rssi_update(struct netdev *netdev)
 	return 0;
 }
 
+static void netdev_add_station_frame_watches(struct netdev *netdev)
+{
+	static const uint8_t action_neighbor_report_prefix[2] = { 0x05, 0x05 };
+	static const uint8_t action_sa_query_resp_prefix[2] = { 0x08, 0x01 };
+	static const uint8_t action_sa_query_req_prefix[2] = { 0x08, 0x00 };
+	static const uint8_t action_ft_response_prefix[] =  { 0x06, 0x02 };
+	static const uint8_t action_qos_map_prefix[] = { 0x01, 0x04 };
+	uint64_t wdev = netdev->wdev_id;
+
+	/* Subscribe to Management -> Action -> RM -> Neighbor Report frames */
+	frame_watch_add(wdev, 0, 0x00d0, action_neighbor_report_prefix,
+			sizeof(action_neighbor_report_prefix),
+			netdev_neighbor_report_frame_event, netdev, NULL);
+
+	frame_watch_add(wdev, 0, 0x00d0, action_sa_query_resp_prefix,
+			sizeof(action_sa_query_resp_prefix),
+			netdev_sa_query_resp_frame_event, netdev, NULL);
+
+	frame_watch_add(wdev, 0, 0x00d0, action_sa_query_req_prefix,
+			sizeof(action_sa_query_req_prefix),
+			netdev_sa_query_req_frame_event, netdev, NULL);
+
+	frame_watch_add(wdev, 0, 0x00d0, action_ft_response_prefix,
+			sizeof(action_ft_response_prefix),
+			netdev_ft_response_frame_event, netdev, NULL);
+
+	if (wiphy_supports_qos_set_map(netdev->wiphy))
+		frame_watch_add(wdev, 0, 0x00d0, action_qos_map_prefix,
+				sizeof(action_qos_map_prefix),
+				netdev_qos_map_frame_event, netdev, NULL);
+}
+
+static void netdev_setup_interface(struct netdev *netdev)
+{
+	switch (netdev->type) {
+	case NL80211_IFTYPE_STATION:
+		/* Set RSSI threshold for CQM notifications */
+		netdev_cqm_rssi_update(netdev);
+		netdev_add_station_frame_watches(netdev);
+		break;
+	default:
+		break;
+	}
+}
+
 static void netdev_set_interface_event(struct l_genl_msg *msg,
 							struct netdev *netdev)
 {
@@ -4887,9 +4932,7 @@ static void netdev_set_interface_event(struct l_genl_msg *msg,
 	netdev->type = iftype;
 	frame_watch_wdev_remove(wdev_id);
 
-	/* Set RSSI threshold for CQM notifications */
-	if (netdev->type == NL80211_IFTYPE_STATION)
-		netdev_cqm_rssi_update(netdev);
+	netdev_setup_interface(netdev);
 }
 
 static void netdev_config_notify(struct l_genl_msg *msg, void *user_data)
@@ -5447,11 +5490,6 @@ struct netdev *netdev_create_from_genl(struct l_genl_msg *msg,
 	struct wiphy *wiphy = NULL;
 	struct ifinfomsg *rtmmsg;
 	size_t bufsize;
-	const uint8_t action_neighbor_report_prefix[2] = { 0x05, 0x05 };
-	const uint8_t action_sa_query_resp_prefix[2] = { 0x08, 0x01 };
-	const uint8_t action_sa_query_req_prefix[2] = { 0x08, 0x00 };
-	const uint8_t action_ft_response_prefix[] =  { 0x06, 0x02 };
-	const uint8_t action_qos_map_prefix[] = { 0x01, 0x04 };
 	struct l_io *pae_io = NULL;
 
 	if (nl80211_parse_attrs(msg, NL80211_ATTR_IFINDEX, &ifindex,
@@ -5525,31 +5563,7 @@ struct netdev *netdev_create_from_genl(struct l_genl_msg *msg,
 
 	l_free(rtmmsg);
 
-	/* Subscribe to Management -> Action -> RM -> Neighbor Report frames */
-	frame_watch_add(wdev, 0, 0x00d0, action_neighbor_report_prefix,
-			sizeof(action_neighbor_report_prefix),
-			netdev_neighbor_report_frame_event, netdev, NULL);
-
-	frame_watch_add(wdev, 0, 0x00d0, action_sa_query_resp_prefix,
-			sizeof(action_sa_query_resp_prefix),
-			netdev_sa_query_resp_frame_event, netdev, NULL);
-
-	frame_watch_add(wdev, 0, 0x00d0, action_sa_query_req_prefix,
-			sizeof(action_sa_query_req_prefix),
-			netdev_sa_query_req_frame_event, netdev, NULL);
-
-	frame_watch_add(wdev, 0, 0x00d0, action_ft_response_prefix,
-			sizeof(action_ft_response_prefix),
-			netdev_ft_response_frame_event, netdev, NULL);
-
-	if (wiphy_supports_qos_set_map(netdev->wiphy))
-		frame_watch_add(wdev, 0, 0x00d0, action_qos_map_prefix,
-				sizeof(action_qos_map_prefix),
-				netdev_qos_map_frame_event, netdev, NULL);
-
-	/* Set RSSI threshold for CQM notifications */
-	if (netdev->type == NL80211_IFTYPE_STATION)
-		netdev_cqm_rssi_update(netdev);
+	netdev_setup_interface(netdev);
 
 	return netdev;
 }
-- 
2.26.3

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

* [PATCH 4/8] rrm: Track that station is removed
  2021-04-20 16:35 [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
  2021-04-20 16:35 ` [PATCH 2/8] frame-xchg: iftype changes to be managed by netdev Denis Kenzior
  2021-04-20 16:35 ` [PATCH 3/8] netdev: Re-add frame watches on iftype change Denis Kenzior
@ 2021-04-20 16:35 ` Denis Kenzior
  2021-04-20 16:35 ` [PATCH 5/8] netdev: Add new iftype change event Denis Kenzior
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2021-04-20 16:35 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 1952 bytes --]

In the case that a netdev is powered down, or an interface type change
occurs, the station object will be removed and any watches will be
freed.

Since rrm is created when the netdev is created and persists across
iftype and power up/down changes, it should provide a destroy callback
to station_add_state_watch so that it can be notified when the watch is
removed.
---
 src/rrm.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/rrm.c b/src/rrm.c
index f41bc907703b..860691a6f258 100644
--- a/src/rrm.c
+++ b/src/rrm.c
@@ -117,6 +117,7 @@ struct rrm_beacon_req_info {
 /* Per-netdev state */
 struct rrm_state {
 	struct station *station;
+	uint32_t watch_id;
 	uint32_t ifindex;
 	uint64_t wdev_id;
 	struct rrm_request_info *pending;
@@ -662,6 +663,17 @@ static void rrm_station_watch_cb(enum station_state state, void *userdata)
 	}
 }
 
+static void rrm_station_watch_destroy(void *user_data)
+{
+	struct rrm_state *rrm = user_data;
+
+	l_debug("");
+
+	rrm_cancel_pending(rrm);
+	rrm->watch_id = 0;
+	rrm->station = NULL;
+}
+
 static void rrm_frame_watch_cb(const struct mmpdu_header *mpdu,
 				const void *body, size_t body_len,
 				int rssi, void *user_data)
@@ -684,8 +696,9 @@ static void rrm_frame_watch_cb(const struct mmpdu_header *mpdu,
 			return;
 		}
 
-		station_add_state_watch(rrm->station, rrm_station_watch_cb,
-						rrm, NULL);
+		rrm->watch_id = station_add_state_watch(rrm->station,
+						rrm_station_watch_cb, rrm,
+						rrm_station_watch_destroy);
 	}
 
 	/*
@@ -806,7 +819,10 @@ static void rrm_netdev_watch(struct netdev *netdev,
 		rrm = l_queue_remove_if(states, match_ifindex,
 						L_UINT_TO_PTR(ifindex));
 		if (rrm) {
-			rrm_cancel_pending(rrm);
+			if (rrm->station && rrm->watch_id)
+				station_remove_state_watch(rrm->station,
+								rrm->watch_id);
+
 			l_free(rrm);
 		}
 
-- 
2.26.3

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

* [PATCH 5/8] netdev: Add new iftype change event
  2021-04-20 16:35 [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
                   ` (2 preceding siblings ...)
  2021-04-20 16:35 ` [PATCH 4/8] rrm: Track that station is removed Denis Kenzior
@ 2021-04-20 16:35 ` Denis Kenzior
  2021-04-20 16:35 ` [PATCH 6/8] rrm: Always create RRM state Denis Kenzior
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2021-04-20 16:35 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 960 bytes --]

---
 src/netdev.c | 3 +++
 src/netdev.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/src/netdev.c b/src/netdev.c
index 4208deea35fa..a524a9feb88c 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -4933,6 +4933,9 @@ static void netdev_set_interface_event(struct l_genl_msg *msg,
 	frame_watch_wdev_remove(wdev_id);
 
 	netdev_setup_interface(netdev);
+
+	WATCHLIST_NOTIFY(&netdev_watches, netdev_watch_func_t,
+				netdev, NETDEV_WATCH_EVENT_IFTYPE_CHANGE);
 }
 
 static void netdev_config_notify(struct l_genl_msg *msg, void *user_data)
diff --git a/src/netdev.h b/src/netdev.h
index 7b321bfb5bcc..0e09ae698260 100644
--- a/src/netdev.h
+++ b/src/netdev.h
@@ -57,6 +57,7 @@ enum netdev_watch_event {
 	NETDEV_WATCH_EVENT_DOWN,
 	NETDEV_WATCH_EVENT_NAME_CHANGE,
 	NETDEV_WATCH_EVENT_ADDRESS_CHANGE,
+	NETDEV_WATCH_EVENT_IFTYPE_CHANGE,
 };
 
 /* Mirror definitions from nl80211.h to make conversions simpler */
-- 
2.26.3

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

* [PATCH 6/8] rrm: Always create RRM state
  2021-04-20 16:35 [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
                   ` (3 preceding siblings ...)
  2021-04-20 16:35 ` [PATCH 5/8] netdev: Add new iftype change event Denis Kenzior
@ 2021-04-20 16:35 ` Denis Kenzior
  2021-04-20 16:35 ` [PATCH 7/8] rrm: React to IFTYPE_CHANGE events Denis Kenzior
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2021-04-20 16:35 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 2097 bytes --]

Right now, RRM is created when a new netdev is detected and its iftype
is of type station.  That means that any devices that start their life
as any other iftype cannot be changed to a station and have RRM function
properly.  Fix that by always creating the RRM state regardless of the
initial iftype.
---
 src/rrm.c | 31 ++++++++++++++++++++-----------
 1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/src/rrm.c b/src/rrm.c
index 860691a6f258..71442abb105f 100644
--- a/src/rrm.c
+++ b/src/rrm.c
@@ -770,14 +770,20 @@ static void rrm_state_destroy(void *data)
 	l_free(rrm);
 }
 
-static void rrm_new_state(struct netdev *netdev)
+static void rrm_add_frame_watches(struct rrm_state *rrm)
 {
-	struct rrm_state *rrm;
-	uint16_t frame_type = 0x00d0;
-	uint8_t prefix[] = { 0x05, 0x00 };
+	static const uint16_t frame_type = 0x00d0;
+	static const uint8_t prefix[] = { 0x05, 0x00 };
 
-	if (netdev_get_iftype(netdev) != NETDEV_IFTYPE_STATION)
-		return;
+	l_debug("");
+
+	frame_watch_add(rrm->wdev_id, 0, frame_type, prefix, sizeof(prefix),
+					rrm_frame_watch_cb, rrm, NULL);
+}
+
+static struct rrm_state *rrm_new_state(struct netdev *netdev)
+{
+	struct rrm_state *rrm;
 
 	rrm = l_new(struct rrm_state, 1);
 
@@ -785,10 +791,9 @@ static void rrm_new_state(struct netdev *netdev)
 	rrm->ifindex = netdev_get_ifindex(netdev);
 	rrm->wdev_id = netdev_get_wdev_id(netdev);
 
-	frame_watch_add(rrm->wdev_id, 0, frame_type, prefix, sizeof(prefix),
-					rrm_frame_watch_cb, rrm, NULL);
-
 	l_queue_push_head(states, rrm);
+
+	return rrm;
 }
 
 static bool match_ifindex(const void *a, const void *b)
@@ -807,8 +812,12 @@ static void rrm_netdev_watch(struct netdev *netdev,
 
 	switch (event) {
 	case NETDEV_WATCH_EVENT_NEW:
-		rrm_new_state(netdev);
-		return;
+		rrm = rrm_new_state(netdev);
+
+		if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION)
+			rrm_add_frame_watches(rrm);
+
+		break;
 	case NETDEV_WATCH_EVENT_DEL:
 		/*
 		 * This event is triggered by the netdev being removed, which
-- 
2.26.3

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

* [PATCH 7/8] rrm: React to IFTYPE_CHANGE events
  2021-04-20 16:35 [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
                   ` (4 preceding siblings ...)
  2021-04-20 16:35 ` [PATCH 6/8] rrm: Always create RRM state Denis Kenzior
@ 2021-04-20 16:35 ` Denis Kenzior
  2021-04-20 16:35 ` [PATCH 8/8] station: Move AP directed roam watch to station Denis Kenzior
  2021-04-23 14:52 ` [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
  7 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2021-04-20 16:35 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 884 bytes --]

If a netdev iftype is changed, all frame registrations are removed.
Make sure to re-register for the appropriate frame notifications in case
our iftype is switched back to 'station'.  In any other iftype, no frame
watches are registered and rrm_state object is effectively dormant.
---
 src/rrm.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/rrm.c b/src/rrm.c
index 71442abb105f..889402561c8a 100644
--- a/src/rrm.c
+++ b/src/rrm.c
@@ -835,7 +835,15 @@ static void rrm_netdev_watch(struct netdev *netdev,
 			l_free(rrm);
 		}
 
-		return;
+		break;
+	case NETDEV_WATCH_EVENT_IFTYPE_CHANGE:
+		rrm = l_queue_find(states, match_ifindex,
+						L_UINT_TO_PTR(ifindex));
+
+		if (rrm && netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION)
+			rrm_add_frame_watches(rrm);
+
+		break;
 	default:
 		break;
 	}
-- 
2.26.3

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

* [PATCH 8/8] station: Move AP directed roam watch to station
  2021-04-20 16:35 [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
                   ` (5 preceding siblings ...)
  2021-04-20 16:35 ` [PATCH 7/8] rrm: React to IFTYPE_CHANGE events Denis Kenzior
@ 2021-04-20 16:35 ` Denis Kenzior
  2021-04-23 14:52 ` [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
  7 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2021-04-20 16:35 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 5819 bytes --]

Logically this frame watch belongs in station.  It was kept in device.c
for the purported reason that the station object was removed with
ifdown/ifup changes and hence the frame watch might need to be removed
and re-added unnecessarily.  Since the kernel does not actually allow to
unregister a frame watch (only when the netdev is removed or its iftype
changes), re-adding a frame watch might trigger a -EALREADY or similar
error.

Avoid this by registering the frame watch when a new netdev is detected
in STATION mode, or when the interface type changes to STATION.
---
 src/device.c  | 22 ----------------------
 src/station.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------
 src/station.h |  4 ----
 3 files changed, 45 insertions(+), 32 deletions(-)

diff --git a/src/device.c b/src/device.c
index dc2c181ad4b3..02da2cdc0f08 100644
--- a/src/device.c
+++ b/src/device.c
@@ -37,8 +37,6 @@
 #include "src/scan.h"
 #include "src/netdev.h"
 #include "src/dbus.h"
-#include "src/frame-xchg.h"
-#include "src/station.h"
 
 struct device {
 	uint32_t index;
@@ -54,18 +52,6 @@ struct device {
 
 static uint32_t netdev_watch;
 
-static void device_ap_roam_frame_event(const struct mmpdu_header *hdr,
-		const void *body, size_t body_len, int rssi, void *user_data)
-{
-	struct device *device = user_data;
-	struct station *station = station_find(device->index);
-
-	if (!station)
-		return;
-
-	station_ap_directed_roam(station, hdr, body, body_len);
-}
-
 static bool device_property_get_name(struct l_dbus *dbus,
 					struct l_dbus_message *message,
 					struct l_dbus_message_builder *builder,
@@ -304,7 +290,6 @@ static struct device *device_create(struct wiphy *wiphy, struct netdev *netdev)
 	struct device *device;
 	struct l_dbus *dbus = dbus_get_bus();
 	uint32_t ifindex = netdev_get_ifindex(netdev);
-	const uint8_t action_ap_roam_prefix[2] = { 0x0a, 0x07 };
 
 	device = l_new(struct device, 1);
 	device->index = ifindex;
@@ -320,13 +305,6 @@ static struct device *device_create(struct wiphy *wiphy, struct netdev *netdev)
 		l_info("Unable to register %s interface",
 				L_DBUS_INTERFACE_PROPERTIES);
 
-	/*
-	 * register for AP roam transition watch
-	 */
-	frame_watch_add(netdev_get_wdev_id(netdev), 0, 0x00d0,
-			action_ap_roam_prefix, sizeof(action_ap_roam_prefix),
-			device_ap_roam_frame_event, device, NULL);
-
 	device->powered = netdev_get_is_up(netdev);
 
 	device->dbus_powered = true;
diff --git a/src/station.c b/src/station.c
index 064872c688af..5e3338f0dace 100644
--- a/src/station.c
+++ b/src/station.c
@@ -55,6 +55,7 @@
 #include "src/anqp.h"
 #include "src/anqputil.h"
 #include "src/diagnostic.h"
+#include "src/frame-xchg.h"
 
 static struct l_queue *station_list;
 static uint32_t netdev_watch;
@@ -2221,9 +2222,9 @@ static bool station_cannot_roam(struct station *station)
 #define WNM_REQUEST_MODE_TERMINATION_IMMINENT		(1 << 3)
 #define WNM_REQUEST_MODE_ESS_DISASSOCIATION_IMMINENT	(1 << 4)
 
-void station_ap_directed_roam(struct station *station,
-				const struct mmpdu_header *hdr,
-				const void *body, size_t body_len)
+static void station_ap_directed_roam(struct station *station,
+					const struct mmpdu_header *hdr,
+					const void *body, size_t body_len)
 {
 	uint32_t pos = 0;
 	uint8_t req_mode;
@@ -3704,15 +3705,48 @@ static void station_destroy_diagnostic_interface(void *user_data)
 {
 }
 
+static void ap_roam_frame_event(const struct mmpdu_header *hdr,
+					const void *body, size_t body_len,
+					int rssi, void *user_data)
+{
+	uint32_t ifindex = L_PTR_TO_UINT(user_data);
+	struct station *station = station_find(ifindex);
+
+	if (!station)
+		return;
+
+	station_ap_directed_roam(station, hdr, body, body_len);
+}
+
+static void add_frame_watches(struct netdev *netdev)
+{
+	static const uint8_t action_ap_roam_prefix[2] = { 0x0a, 0x07 };
+
+	/*
+	 * register for AP roam transition watch
+	 */
+	frame_watch_add(netdev_get_wdev_id(netdev), 0, 0x00d0,
+			action_ap_roam_prefix, sizeof(action_ap_roam_prefix),
+			ap_roam_frame_event,
+			L_UINT_TO_PTR(netdev_get_ifindex(netdev)), NULL);
+}
+
 static void station_netdev_watch(struct netdev *netdev,
 				enum netdev_watch_event event, void *userdata)
 {
 	switch (event) {
-	case NETDEV_WATCH_EVENT_UP:
 	case NETDEV_WATCH_EVENT_NEW:
-		if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION &&
-				netdev_get_is_up(netdev))
+		if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION) {
+			add_frame_watches(netdev);
+
+			if (netdev_get_is_up(netdev))
+				station_create(netdev);
+		}
+		break;
+	case NETDEV_WATCH_EVENT_UP:
+		if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION)
 			station_create(netdev);
+
 		break;
 	case NETDEV_WATCH_EVENT_DOWN:
 	case NETDEV_WATCH_EVENT_DEL:
@@ -3720,6 +3754,11 @@ static void station_netdev_watch(struct netdev *netdev,
 						netdev_get_path(netdev),
 						IWD_STATION_INTERFACE);
 		break;
+	case NETDEV_WATCH_EVENT_IFTYPE_CHANGE:
+		if (netdev_get_iftype(netdev) == NETDEV_IFTYPE_STATION)
+			add_frame_watches(netdev);
+
+		break;
 	default:
 		break;
 	}
diff --git a/src/station.h b/src/station.h
index f114733b0cbc..6918b1464a5a 100644
--- a/src/station.h
+++ b/src/station.h
@@ -83,10 +83,6 @@ void station_remove_anqp_watch(uint32_t id);
 
 bool station_set_autoconnect(struct station *station, bool autoconnect);
 
-void station_ap_directed_roam(struct station *station,
-				const struct mmpdu_header *hdr,
-				const void *body, size_t body_len);
-
 int __station_connect_network(struct station *station, struct network *network,
 				struct scan_bss *bss);
 void station_connect_network(struct station *station, struct network *network,
-- 
2.26.3

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

* Re: [PATCH 1/8] netdev: Track SET_INTERFACE events
  2021-04-20 16:35 [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
                   ` (6 preceding siblings ...)
  2021-04-20 16:35 ` [PATCH 8/8] station: Move AP directed roam watch to station Denis Kenzior
@ 2021-04-23 14:52 ` Denis Kenzior
  7 siblings, 0 replies; 9+ messages in thread
From: Denis Kenzior @ 2021-04-23 14:52 UTC (permalink / raw)
  To: iwd

[-- Attachment #1: Type: text/plain, Size: 391 bytes --]

On 4/20/21 11:35 AM, Denis Kenzior wrote:
> And set the interface type based on the event rather than the command
> callback.  This allows us to track interface type changes even if they
> come from outside iwd (which shouldn't happen.)
> ---
>   src/netdev.c | 47 +++++++++++++++++++++++++++++++++++++++++------
>   1 file changed, 41 insertions(+), 6 deletions(-)
> 

All applied.

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

end of thread, other threads:[~2021-04-23 14:52 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-20 16:35 [PATCH 1/8] netdev: Track SET_INTERFACE events Denis Kenzior
2021-04-20 16:35 ` [PATCH 2/8] frame-xchg: iftype changes to be managed by netdev Denis Kenzior
2021-04-20 16:35 ` [PATCH 3/8] netdev: Re-add frame watches on iftype change Denis Kenzior
2021-04-20 16:35 ` [PATCH 4/8] rrm: Track that station is removed Denis Kenzior
2021-04-20 16:35 ` [PATCH 5/8] netdev: Add new iftype change event Denis Kenzior
2021-04-20 16:35 ` [PATCH 6/8] rrm: Always create RRM state Denis Kenzior
2021-04-20 16:35 ` [PATCH 7/8] rrm: React to IFTYPE_CHANGE events Denis Kenzior
2021-04-20 16:35 ` [PATCH 8/8] station: Move AP directed roam watch to station Denis Kenzior
2021-04-23 14:52 ` [PATCH 1/8] netdev: Track SET_INTERFACE events 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.