summaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorMarkus Theil <markus.theil@tu-ilmenau.de>2020-05-08 16:42:00 +0200
committerJohannes Berg <johannes.berg@intel.com>2020-05-27 10:02:04 +0200
commitdca9ca2d588bd2c0989c671f048540b82e57cf1e (patch)
treefc7438876e9248a3227b28806404d90de40afa20 /net/wireless
parent3c23215ba8c70c0e9b16beffb7f700a401391e38 (diff)
downloadlinux-dca9ca2d588bd2c0989c671f048540b82e57cf1e.tar.gz
linux-dca9ca2d588bd2c0989c671f048540b82e57cf1e.tar.bz2
linux-dca9ca2d588bd2c0989c671f048540b82e57cf1e.zip
nl80211: add ability to report TX status for control port TX
This adds the necessary capabilities in nl80211 to allow drivers to assign a cookie to control port TX frames (returned via extack in the netlink ACK message of the command) and then later report the frame's status. Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de> Link: https://lore.kernel.org/r/20200508144202.7678-2-markus.theil@tu-ilmenau.de [use extack cookie instead of explicit message, recombine patches] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c41
-rw-r--r--net/wireless/rdev-ops.h9
-rw-r--r--net/wireless/trace.h17
3 files changed, 56 insertions, 11 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 84bfa147769a..7ea764865546 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -13866,6 +13866,7 @@ 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;
@@ -13874,6 +13875,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
u8 *dest;
u16 proto;
bool noencrypt;
+ u64 cookie = 0;
int err;
if (!wiphy_ext_feature_isset(&rdev->wiphy,
@@ -13918,9 +13920,12 @@ 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);
-
+ err = rdev_tx_control_port(rdev, dev, buf, len,
+ dest, cpu_to_be16(proto), noencrypt,
+ dont_wait_for_ack ? NULL : &cookie);
+ if (!err && !dont_wait_for_ack)
+ nl_set_extack_cookie_u64(info->extack, cookie);
+ return err;
out:
wdev_unlock(wdev);
return err;
@@ -16294,8 +16299,9 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
return -ENOBUFS;
}
-void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
- const u8 *buf, size_t len, bool ack, gfp_t gfp)
+static void nl80211_frame_tx_status(struct wireless_dev *wdev, u64 cookie,
+ const u8 *buf, size_t len, bool ack,
+ gfp_t gfp, enum nl80211_commands command)
{
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@@ -16303,13 +16309,16 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
struct sk_buff *msg;
void *hdr;
- trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
+ if (command == NL80211_CMD_FRAME_TX_STATUS)
+ trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
+ else
+ trace_cfg80211_control_port_tx_status(wdev, cookie, ack);
msg = nlmsg_new(100 + len, gfp);
if (!msg)
return;
- hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS);
+ hdr = nl80211hdr_put(msg, 0, 0, 0, command);
if (!hdr) {
nlmsg_free(msg);
return;
@@ -16332,9 +16341,25 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
NL80211_MCGRP_MLME, gfp);
return;
- nla_put_failure:
+nla_put_failure:
nlmsg_free(msg);
}
+
+void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
+ const u8 *buf, size_t len, bool ack,
+ gfp_t gfp)
+{
+ nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
+ NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
+}
+EXPORT_SYMBOL(cfg80211_control_port_tx_status);
+
+void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
+ const u8 *buf, size_t len, bool ack, gfp_t gfp)
+{
+ nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
+ NL80211_CMD_FRAME_TX_STATUS);
+}
EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
static int __nl80211_rx_control_port(struct net_device *dev,
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index df5142e86c4f..950d57494168 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -748,14 +748,17 @@ 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);
- trace_rdev_return_int(&rdev->wiphy, ret);
+ dest, proto, noencrypt, cookie);
+ if (cookie)
+ trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
+ else
+ trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index f2ab44a2a3e4..b23cab016521 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2861,6 +2861,23 @@ TRACE_EVENT(cfg80211_mgmt_tx_status,
WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack))
);
+TRACE_EVENT(cfg80211_control_port_tx_status,
+ TP_PROTO(struct wireless_dev *wdev, u64 cookie, bool ack),
+ TP_ARGS(wdev, cookie, ack),
+ TP_STRUCT__entry(
+ WDEV_ENTRY
+ __field(u64, cookie)
+ __field(bool, ack)
+ ),
+ TP_fast_assign(
+ WDEV_ASSIGN;
+ __entry->cookie = cookie;
+ __entry->ack = ack;
+ ),
+ TP_printk(WDEV_PR_FMT", cookie: %llu, ack: %s",
+ WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack))
+);
+
TRACE_EVENT(cfg80211_rx_control_port,
TP_PROTO(struct net_device *netdev, struct sk_buff *skb,
bool unencrypted),