2020-05-08 14:45:17

by Markus Theil

[permalink] [raw]
Subject: [PATCH 0/3] nl80211/mac80211: add tx status for ctrl port

When sending EAPOL frames from an AP to a STA, SO_WIFI_STATUS can be used
on raw/packet sockets to get notified of (un-)successful frame
transmissions in order to trigger retransmits earlier.

The nl80211 control port currently lacks such a feature, which therefore
gets added in this series, in order to function as a drop in replacement
for using dedicated AF_PACKET sockets for handling EAPOL messages.
With this series it is finally possible to run hostapd in AP mode with
mgmt and EAPOL control port frames solely over nl80211 and data frames on
the kernel data path.

The intended behaviour stems from tx notifications for mgmt frames over
nl80211. A cookie is provided to match request and reply, furthermore the
frame content is also included in status messages.

This series has been tested with a modified hostapd version. Patches for
hostapd will follow soon on its mailing list.

Markus Theil (3):
nl80211: cookie arg for tx control port
nl80211: add control port tx status method
nl80211: add feature flag for control port tx status capability

include/net/cfg80211.h | 18 +++++++-
include/uapi/linux/nl80211.h | 12 ++++++
net/mac80211/ieee80211_i.h | 8 +++-
net/mac80211/main.c | 2 +
net/mac80211/status.c | 7 ++-
net/mac80211/tdls.c | 2 +-
net/mac80211/tx.c | 83 +++++++++++++++++++++++++++---------
net/wireless/nl80211.c | 73 ++++++++++++++++++++++++++-----
net/wireless/rdev-ops.h | 9 ++--
net/wireless/trace.h | 17 ++++++++
10 files changed, 193 insertions(+), 38 deletions(-)

--
2.26.2


2020-05-08 14:45:17

by Markus Theil

[permalink] [raw]
Subject: [PATCH 3/3] nl80211: add feature flag for control port tx status capability

This patch adds a feature flag in order to detect control port tx
status capability.

Signed-off-by: Markus Theil <[email protected]>
---
include/uapi/linux/nl80211.h | 4 ++++
net/mac80211/main.c | 2 ++
2 files changed, 6 insertions(+)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index e3b7a911b35c..02e1aa10f9a2 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -5713,6 +5713,9 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS: management frame registrations
* are possible for multicast frames and those will be reported properly.
*
+ * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS: The driver
+ * can report tx status for control port over nl80211 tx operations.
+ *
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
@@ -5766,6 +5769,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_DEL_IBSS_STA,
NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS,
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT,
+ NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS,

/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index dfcee5e462da..6381e6c1f58b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -596,6 +596,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
wiphy_ext_feature_set(wiphy,
NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH);
+ wiphy_ext_feature_set(wiphy,
+ NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS);

if (!ops->hw_scan) {
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
--
2.26.2

2020-05-08 14:45:18

by Markus Theil

[permalink] [raw]
Subject: [PATCH 1/3] nl80211: cookie arg for tx control port

This patch is a preparation for getting tx status reports for nl80211
control port frames. It adds a cookie parameter and replies the cookie
to the sending process. This cookie can later be used to identify
succesfull or lost ACKs (analog to already existing status reports for
mgmt frames).

Signed-off-by: Markus Theil <[email protected]>
---
include/net/cfg80211.h | 3 ++-
net/mac80211/ieee80211_i.h | 3 ++-
net/mac80211/tx.c | 3 ++-
net/wireless/nl80211.c | 45 +++++++++++++++++++++++++++++++++-----
net/wireless/rdev-ops.h | 4 ++--
5 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a82fc59a1d82..d3d18481f6da 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4067,7 +4067,8 @@ struct cfg80211_ops {
struct net_device *dev,
const u8 *buf, size_t len,
const u8 *dest, const __be16 proto,
- const bool noencrypt);
+ const bool noencrypt,
+ u64 *cookie);

int (*get_ftm_responder_stats)(struct wiphy *wiphy,
struct net_device *dev,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8cbae66b5cdb..4f6432c7e150 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1800,7 +1800,8 @@ void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata);
void ieee80211_clear_fast_xmit(struct sta_info *sta);
int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len,
- const u8 *dest, __be16 proto, bool unencrypted);
+ const u8 *dest, __be16 proto, bool unencrypted,
+ u64 *cookie);
int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len);

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 6dad67eb60b2..ba34cc392ea8 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -5339,7 +5339,8 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,

int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len,
- const u8 *dest, __be16 proto, bool unencrypted)
+ const u8 *dest, __be16 proto, bool unencrypted,
+ u64 *cookie)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3d27b24c68b2..4fe232a51078 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -13862,14 +13862,18 @@ static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)

static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
{
+ bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct sk_buff *msg = NULL;
+ void *hdr = NULL;
const u8 *buf;
size_t len;
u8 *dest;
u16 proto;
bool noencrypt;
+ u64 cookie;
int err;

if (!wiphy_ext_feature_isset(&rdev->wiphy,
@@ -13899,10 +13903,10 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
if (wdev->current_bss)
break;
err = -ENOTCONN;
- goto out;
+ goto out_unlock;
default:
err = -EOPNOTSUPP;
- goto out;
+ goto out_unlock;
}

wdev_unlock(wdev);
@@ -13914,11 +13918,42 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
noencrypt =
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);

- return rdev_tx_control_port(rdev, dev, buf, len,
- dest, cpu_to_be16(proto), noencrypt);
+ if (!dont_wait_for_ack) {
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;

- out:
+ hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
+ NL80211_CMD_CONTROL_PORT_FRAME);
+ if (!hdr) {
+ err = -ENOBUFS;
+ goto free_msg;
+ }
+ }
+
+ err = rdev_tx_control_port(rdev, dev, buf, len,
+ dest, cpu_to_be16(proto), noencrypt,
+ dont_wait_for_ack ? NULL : &cookie);
+ if (err)
+ goto free_msg;
+
+ if (msg) {
+ if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
+ NL80211_ATTR_PAD))
+ goto nla_put_failure;
+
+ genlmsg_end(msg, hdr);
+ return genlmsg_reply(msg, info);
+ }
+
+ return 0;
+
+out_unlock:
wdev_unlock(wdev);
+nla_put_failure:
+ err = -ENOBUFS;
+free_msg:
+ nlmsg_free(msg);
return err;
}

diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index df5142e86c4f..63b5786572d0 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -748,13 +748,13 @@ static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev,
struct net_device *dev,
const void *buf, size_t len,
const u8 *dest, __be16 proto,
- const bool noencrypt)
+ const bool noencrypt, u64 *cookie)
{
int ret;
trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,
dest, proto, noencrypt);
ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,
- dest, proto, noencrypt);
+ dest, proto, noencrypt, cookie);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
--
2.26.2

2020-05-26 13:31:50

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/3] nl80211/mac80211: add tx status for ctrl port

Hi Markus,

Generally, this seems fine.

I have applied the cfg80211/nl80211 bits in my tree (currently in
mac80211-next pending branch), and recombined the patches for that.

I've also modified the nl80211 code to return the cookie in the extack
message, rather than a separate message, which is much nicer. That means
you'll have to modify the hostapd changes for this.

The mac80211 changes seem overly complex, I'll reply in detail.

johannes