diff mbox series

[2/6] nl80211: handle control port tx status events over nl80211

Message ID 20200528084612.6530-3-markus.theil@tu-ilmenau.de
State Superseded
Headers show
Series nl80211: add support for control port tx status | expand

Commit Message

Markus Theil May 28, 2020, 8:46 a.m. UTC
In order to retransmit faster in AP mode, hostapd can handle
tx status notifications. When using nl80211, this is currently
only possible with socket control msgs. This patchs adds support
for receiving such events directly over nl80211 and detecting,
if this feature is supported.

This finally allows for a clean separation between mgmt/ctrl
path (over nl80211) and in-kernel data path.

A follow up patch enables the feature in AP mode.

Control port tx status contains the original frame content for
matching with the current hostapd code. Furthermore, a cookie
is included, which allows for matching against outstanding cookies
in the future. This patch only prints the cookie value for debugging
purposes on tx status receive.

Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
 src/drivers/driver.h               |  4 +++-
 src/drivers/driver_nl80211_capa.c  |  3 +++
 src/drivers/driver_nl80211_event.c | 29 +++++++++++++++++++++++++++++
 3 files changed, 35 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 1e2e332a6..1f6487c29 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1922,7 +1922,9 @@  struct wpa_driver_capa {
 	u64 flags;
 
 /** Driver supports a separate control port RX for EAPOL frames */
-#define WPA_DRIVER_FLAGS2_CONTROL_PORT_RX	0x0000000000000001ULL
+#define WPA_DRIVER_FLAGS2_CONTROL_PORT_RX	 0x0000000000000001ULL
+/** Driver supports tx status reports for EAPOL frames */
+#define WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS 0x0000000000000002ULL
 	u64 flags2;
 
 #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index a3341a088..a260f6f41 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -598,6 +598,9 @@  static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
 	if (ext_feature_isset(ext_features, len,
 			      NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH))
 		capa->flags2 |= WPA_DRIVER_FLAGS2_CONTROL_PORT_RX;
+	if (ext_feature_isset(ext_features, len,
+			      NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS))
+		capa->flags2 |= WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS;
 
 	if (ext_feature_isset(ext_features, len,
 			      NL80211_EXT_FEATURE_VLAN_OFFLOAD))
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 6a2de1f3c..f7bf9d21e 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -138,6 +138,8 @@  static const char * nl80211_command_to_string(enum nl80211_commands cmd)
 	C2S(NL80211_CMD_CONTROL_PORT_FRAME)
 	C2S(NL80211_CMD_UPDATE_OWE_INFO)
 	C2S(NL80211_CMD_UNPROT_BEACON)
+	C2S(NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS)
+
 	default:
 		return "NL80211_CMD_UNKNOWN";
 	}
@@ -2557,6 +2559,28 @@  static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv,
 }
 
 
+static void nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv,
+						 struct nlattr **tb)
+{
+	bool acked = tb[NL80211_ATTR_ACK];
+	union wpa_event_data event;
+
+	if (!tb[NL80211_ATTR_FRAME] ||
+	    !tb[NL80211_ATTR_COOKIE])
+		return;
+
+	if (nla_len(tb[NL80211_ATTR_FRAME]) < 14)
+		return;
+
+	memset(&event, 0, sizeof(event));
+	event.eapol_tx_status.dst = nla_data(tb[NL80211_ATTR_FRAME]);
+	event.eapol_tx_status.data = nla_data(tb[NL80211_ATTR_FRAME]) + 14;
+	event.eapol_tx_status.data_len = nla_len(tb[NL80211_ATTR_FRAME]) - 14;
+	event.eapol_tx_status.ack = acked;
+	wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
+}
+
+
 static void do_process_drv_event(struct i802_bss *bss, int cmd,
 				 struct nlattr **tb)
 {
@@ -2775,10 +2799,15 @@  static void do_process_drv_event(struct i802_bss *bss, int cmd,
 			mlme_event_unprot_beacon(drv, nla_data(frame),
 						 nla_len(frame));
 		break;
+	case NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS:
+		wpa_printf(MSG_DEBUG, "nl80211: control port frame tx status, cookie=%lu", nla_get_u64(tb[NL80211_ATTR_COOKIE]));
+		nl80211_control_port_frame_tx_status(drv, tb);
+		break;
 	default:
 		wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
 			"(cmd=%d)", cmd);
 		break;
+		
 	}
 }