History

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.

Markus Theil committed 6 years ago

Commit dca9ca21 parent 3c232157 files · +91 −14Browse files

Unified · Split

7 files
  1. include/net/cfg80211.h +19 −1
  2. include/uapi/linux/nl80211.h +12 −0
  3. net/mac80211/ieee80211_i.h +2 −1
  4. net/mac80211/tx.c +2 −1
  5. net/wireless/nl80211.c +33 −8
  6. net/wireless/rdev-ops.h +6 −3
  7. net/wireless/trace.h +17 −0
include/net/cfg80211.h+19−1
@@ -4069,7 +4069,8 @@ struct cfg80211_ops { · 4068 unmodified lines
40694069 struct net_device *dev,
40704070 const u8 *buf, size_t len,
40714071 const u8 *dest, const __be16 proto,
4072− const bool noencrypt);
4072+ const bool noencrypt,
4073+ u64 *cookie);
40734074
40744075 int (*get_ftm_responder_stats)(struct wiphy *wiphy,
40754076 struct net_device *dev,
@@ -7049,6 +7050,23 @@ static inline bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, · 2973 unmodified lines
70497050 void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
70507051 const u8 *buf, size_t len, bool ack, gfp_t gfp);
70517052
7053+/**
7054+ * cfg80211_control_port_tx_status - notification of TX status for control
7055+ * port frames
7056+ * @wdev: wireless device receiving the frame
7057+ * @cookie: Cookie returned by cfg80211_ops::tx_control_port()
7058+ * @buf: Data frame (header + body)
7059+ * @len: length of the frame data
7060+ * @ack: Whether frame was acknowledged
7061+ * @gfp: context flags
7062+ *
7063+ * This function is called whenever a control port frame was requested to be
7064+ * transmitted with cfg80211_ops::tx_control_port() to report the TX status of
7065+ * the transmission attempt.
7066+ */
7067+void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
7068+ const u8 *buf, size_t len, bool ack,
7069+ gfp_t gfp);
70527070
70537071 /**
70547072 * cfg80211_rx_control_port - notification about a received control port frame
include/uapi/linux/nl80211.h+12−0
@@ -1164,6 +1164,12 @@ · 1163 unmodified lines
11641164 * dropped because it did not include a valid MME MIC while beacon
11651165 * protection was enabled (BIGTK configured in station mode).
11661166 *
1167+ * @NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS: Report TX status of a control
1168+ * port frame transmitted with %NL80211_CMD_CONTROL_PORT_FRAME.
1169+ * %NL80211_ATTR_COOKIE identifies the TX command and %NL80211_ATTR_FRAME
1170+ * includes the contents of the frame. %NL80211_ATTR_ACK flag is included
1171+ * if the recipient acknowledged the frame.
1172+ *
11671173 * @NL80211_CMD_MAX: highest used command number
11681174 * @__NL80211_CMD_AFTER_LAST: internal use
11691175 */
@@ -1392,6 +1398,8 @@ enum nl80211_commands { · 222 unmodified lines
13921398
13931399 NL80211_CMD_UNPROT_BEACON,
13941400
1401+ NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS,
1402+
13951403 /* add new commands above here */
13961404
13971405 /* used to define NL80211_CMD_MAX below */
@@ -5729,6 +5737,9 @@ enum nl80211_feature_flags { · 4331 unmodified lines
57295737 * report %NL80211_ATTR_SCAN_FREQ_KHZ, %NL80211_SCAN_FLAG_FREQ_KHZ must be
57305738 * included in the scan request.
57315739 *
5740+ * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS: The driver
5741+ * can report tx status for control port over nl80211 tx operations.
5742+ *
57325743 * @NUM_NL80211_EXT_FEATURES: number of extended features.
57335744 * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
57345745 */
@@ -5783,6 +5794,7 @@ enum nl80211_ext_feature_index { · 48 unmodified lines
57835794 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS,
57845795 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT,
57855796 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ,
5797+ NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS,
57865798
57875799 /* add new features before the definition below */
57885800 NUM_NL80211_EXT_FEATURES,
net/mac80211/ieee80211_i.h+2−1
@@ -1800,7 +1800,8 @@ void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata); · 1799 unmodified lines
18001800 void ieee80211_clear_fast_xmit(struct sta_info *sta);
18011801 int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
18021802 const u8 *buf, size_t len,
1803− const u8 *dest, __be16 proto, bool unencrypted);
1803+ const u8 *dest, __be16 proto, bool unencrypted,
1804+ u64 *cookie);
18041805 int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
18051806 const u8 *buf, size_t len);
18061807
net/mac80211/tx.c+2−1
@@ -5339,7 +5339,8 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, · 5338 unmodified lines
53395339
53405340 int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
53415341 const u8 *buf, size_t len,
5342− const u8 *dest, __be16 proto, bool unencrypted)
5342+ const u8 *dest, __be16 proto, bool unencrypted,
5343+ u64 *cookie)
53435344 {
53445345 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
53455346 struct ieee80211_local *local = sdata->local;
net/wireless/nl80211.c+33−8
@@ -13866,6 +13866,7 @@ static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info) · 13865 unmodified lines
1386613866
1386713867 static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
1386813868 {
13869+ bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
1386913870 struct cfg80211_registered_device *rdev = info->user_ptr[0];
1387013871 struct net_device *dev = info->user_ptr[1];
1387113872 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) · 2 unmodified lines
1387413875 u8 *dest;
1387513876 u16 proto;
1387613877 bool noencrypt;
13878+ u64 cookie = 0;
1387713879 int err;
1387813880
1387913881 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) · 38 unmodified lines
1391813920 noencrypt =
1391913921 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
1392013922
13921− return rdev_tx_control_port(rdev, dev, buf, len,
13922− dest, cpu_to_be16(proto), noencrypt);
13923−
13923+ err = rdev_tx_control_port(rdev, dev, buf, len,
13924+ dest, cpu_to_be16(proto), noencrypt,
13925+ dont_wait_for_ack ? NULL : &cookie);
13926+ if (!err && !dont_wait_for_ack)
13927+ nl_set_extack_cookie_u64(info->extack, cookie);
13928+ return err;
1392413929 out:
1392513930 wdev_unlock(wdev);
1392613931 return err;
@@ -16294,8 +16299,9 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, · 2367 unmodified lines
1629416299 return -ENOBUFS;
1629516300 }
1629616301
16297−void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
16298− const u8 *buf, size_t len, bool ack, gfp_t gfp)
16302+static void nl80211_frame_tx_status(struct wireless_dev *wdev, u64 cookie,
16303+ const u8 *buf, size_t len, bool ack,
16304+ gfp_t gfp, enum nl80211_commands command)
1629916305 {
1630016306 struct wiphy *wiphy = wdev->wiphy;
1630116307 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@@ -16303,13 +16309,16 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, · 1 unmodified line
1630316309 struct sk_buff *msg;
1630416310 void *hdr;
1630516311
16306− trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
16312+ if (command == NL80211_CMD_FRAME_TX_STATUS)
16313+ trace_cfg80211_mgmt_tx_status(wdev, cookie, ack);
16314+ else
16315+ trace_cfg80211_control_port_tx_status(wdev, cookie, ack);
1630716316
1630816317 msg = nlmsg_new(100 + len, gfp);
1630916318 if (!msg)
1631016319 return;
1631116320
16312− hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS);
16321+ hdr = nl80211hdr_put(msg, 0, 0, 0, command);
1631316322 if (!hdr) {
1631416323 nlmsg_free(msg);
1631516324 return;
@@ -16332,9 +16341,25 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, · 16 unmodified lines
1633216341 NL80211_MCGRP_MLME, gfp);
1633316342 return;
1633416343
16335− nla_put_failure:
16344+nla_put_failure:
1633616345 nlmsg_free(msg);
1633716346 }
16347+
16348+void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
16349+ const u8 *buf, size_t len, bool ack,
16350+ gfp_t gfp)
16351+{
16352+ nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
16353+ NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS);
16354+}
16355+EXPORT_SYMBOL(cfg80211_control_port_tx_status);
16356+
16357+void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
16358+ const u8 *buf, size_t len, bool ack, gfp_t gfp)
16359+{
16360+ nl80211_frame_tx_status(wdev, cookie, buf, len, ack, gfp,
16361+ NL80211_CMD_FRAME_TX_STATUS);
16362+}
1633816363 EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
1633916364
1634016365 static int __nl80211_rx_control_port(struct net_device *dev,
net/wireless/rdev-ops.h+6−3
@@ -748,14 +748,17 @@ static inline int rdev_tx_control_port(struct cfg80211_registered_device *rdev, · 747 unmodified lines
748748 struct net_device *dev,
749749 const void *buf, size_t len,
750750 const u8 *dest, __be16 proto,
751− const bool noencrypt)
751+ const bool noencrypt, u64 *cookie)
752752 {
753753 int ret;
754754 trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,
755755 dest, proto, noencrypt);
756756 ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,
757− dest, proto, noencrypt);
758− trace_rdev_return_int(&rdev->wiphy, ret);
757+ dest, proto, noencrypt, cookie);
758+ if (cookie)
759+ trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
760+ else
761+ trace_rdev_return_int(&rdev->wiphy, ret);
759762 return ret;
760763 }
761764
net/wireless/trace.h+17−0
@@ -2861,6 +2861,23 @@ TRACE_EVENT(cfg80211_mgmt_tx_status, · 2860 unmodified lines
28612861 WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack))
28622862 );
28632863
2864+TRACE_EVENT(cfg80211_control_port_tx_status,
2865+ TP_PROTO(struct wireless_dev *wdev, u64 cookie, bool ack),
2866+ TP_ARGS(wdev, cookie, ack),
2867+ TP_STRUCT__entry(
2868+ WDEV_ENTRY
2869+ __field(u64, cookie)
2870+ __field(bool, ack)
2871+ ),
2872+ TP_fast_assign(
2873+ WDEV_ASSIGN;
2874+ __entry->cookie = cookie;
2875+ __entry->ack = ack;
2876+ ),
2877+ TP_printk(WDEV_PR_FMT", cookie: %llu, ack: %s",
2878+ WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack))
2879+);
2880+
28642881 TRACE_EVENT(cfg80211_rx_control_port,
28652882 TP_PROTO(struct net_device *netdev, struct sk_buff *skb,
28662883 bool unencrypted),