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
4069 struct net_device *dev,4069 struct net_device *dev,
4070 const u8 *buf, size_t len,4070 const u8 *buf, size_t len,
4071 const u8 *dest, const __be16 proto,4071 const u8 *dest, const __be16 proto,
4072 const bool noencrypt);4072 const bool noencrypt,
4073 u64 *cookie);
4073 4074
4074 int (*get_ftm_responder_stats)(struct wiphy *wiphy,4075 int (*get_ftm_responder_stats)(struct wiphy *wiphy,
4075 struct net_device *dev,4076 struct net_device *dev,
@@ -7049,6 +7050,23 @@ static inline bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, · 2973 unmodified lines
7049void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,7050void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
7050 const u8 *buf, size_t len, bool ack, gfp_t gfp);7051 const u8 *buf, size_t len, bool ack, gfp_t gfp);
7051 7052
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 */
7067void cfg80211_control_port_tx_status(struct wireless_dev *wdev, u64 cookie,
7068 const u8 *buf, size_t len, bool ack,
7069 gfp_t gfp);
7052 7070
7053/**7071/**
7054 * cfg80211_rx_control_port - notification about a received control port frame7072 * 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
1164 * dropped because it did not include a valid MME MIC while beacon1164 * dropped because it did not include a valid MME MIC while beacon
1165 * protection was enabled (BIGTK configured in station mode).1165 * protection was enabled (BIGTK configured in station mode).
1166 *1166 *
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 *
1167 * @NL80211_CMD_MAX: highest used command number1173 * @NL80211_CMD_MAX: highest used command number
1168 * @__NL80211_CMD_AFTER_LAST: internal use1174 * @__NL80211_CMD_AFTER_LAST: internal use
1169 */1175 */
@@ -1392,6 +1398,8 @@ enum nl80211_commands { · 222 unmodified lines
1392 1398
1393 NL80211_CMD_UNPROT_BEACON,1399 NL80211_CMD_UNPROT_BEACON,
1394 1400
1401 NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS,
1402
1395 /* add new commands above here */1403 /* add new commands above here */
1396 1404
1397 /* used to define NL80211_CMD_MAX below */1405 /* used to define NL80211_CMD_MAX below */
@@ -5729,6 +5737,9 @@ enum nl80211_feature_flags { · 4331 unmodified lines
5729 * report %NL80211_ATTR_SCAN_FREQ_KHZ, %NL80211_SCAN_FLAG_FREQ_KHZ must be5737 * report %NL80211_ATTR_SCAN_FREQ_KHZ, %NL80211_SCAN_FLAG_FREQ_KHZ must be
5730 * included in the scan request.5738 * included in the scan request.
5731 *5739 *
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 *
5732 * @NUM_NL80211_EXT_FEATURES: number of extended features.5743 * @NUM_NL80211_EXT_FEATURES: number of extended features.
5733 * @MAX_NL80211_EXT_FEATURES: highest extended feature index.5744 * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
5734 */5745 */
@@ -5783,6 +5794,7 @@ enum nl80211_ext_feature_index { · 48 unmodified lines
5783 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS,5794 NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS,
5784 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT,5795 NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT,
5785 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ,5796 NL80211_EXT_FEATURE_SCAN_FREQ_KHZ,
5797 NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS,
5786 5798
5787 /* add new features before the definition below */5799 /* add new features before the definition below */
5788 NUM_NL80211_EXT_FEATURES,5800 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
1800void ieee80211_clear_fast_xmit(struct sta_info *sta);1800void ieee80211_clear_fast_xmit(struct sta_info *sta);
1801int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,1801int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
1802 const u8 *buf, size_t len,1802 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);
1804int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,1805int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
1805 const u8 *buf, size_t len);1806 const u8 *buf, size_t len);
1806 1807
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
5339 5339
5340int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,5340int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
5341 const u8 *buf, size_t len,5341 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)
5343{5344{
5344 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);5345 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
5345 struct ieee80211_local *local = sdata->local;5346 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
13866 13866
13867static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)13867static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
13868{13868{
13869 bool dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
13869 struct cfg80211_registered_device *rdev = info->user_ptr[0];13870 struct cfg80211_registered_device *rdev = info->user_ptr[0];
13870 struct net_device *dev = info->user_ptr[1];13871 struct net_device *dev = info->user_ptr[1];
13871 struct wireless_dev *wdev = dev->ieee80211_ptr;13872 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
13874 u8 *dest;13875 u8 *dest;
13875 u16 proto;13876 u16 proto;
13876 bool noencrypt;13877 bool noencrypt;
13878 u64 cookie = 0;
13877 int err;13879 int err;
13878 13880
13879 if (!wiphy_ext_feature_isset(&rdev->wiphy,13881 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
13918 noencrypt =13920 noencrypt =
13919 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);13921 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
13920 13922
13921 return rdev_tx_control_port(rdev, dev, buf, len,13923 err = rdev_tx_control_port(rdev, dev, buf, len,
13922 dest, cpu_to_be16(proto), noencrypt);13924 dest, cpu_to_be16(proto), noencrypt,
13923 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;
13924 out:13929 out:
13925 wdev_unlock(wdev);13930 wdev_unlock(wdev);
13926 return err;13931 return err;
@@ -16294,8 +16299,9 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, · 2367 unmodified lines
16294 return -ENOBUFS;16299 return -ENOBUFS;
16295}16300}
16296 16301
16297void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,16302static void nl80211_frame_tx_status(struct wireless_dev *wdev, u64 cookie,
16298 const u8 *buf, size_t len, bool ack, gfp_t gfp)16303 const u8 *buf, size_t len, bool ack,
16304 gfp_t gfp, enum nl80211_commands command)
16299{16305{
16300 struct wiphy *wiphy = wdev->wiphy;16306 struct wiphy *wiphy = wdev->wiphy;
16301 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);16307 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
16303 struct sk_buff *msg;16309 struct sk_buff *msg;
16304 void *hdr;16310 void *hdr;
16305 16311
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);
16307 16316
16308 msg = nlmsg_new(100 + len, gfp);16317 msg = nlmsg_new(100 + len, gfp);
16309 if (!msg)16318 if (!msg)
16310 return;16319 return;
16311 16320
16312 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS);16321 hdr = nl80211hdr_put(msg, 0, 0, 0, command);
16313 if (!hdr) {16322 if (!hdr) {
16314 nlmsg_free(msg);16323 nlmsg_free(msg);
16315 return;16324 return;
@@ -16332,9 +16341,25 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, · 16 unmodified lines
16332 NL80211_MCGRP_MLME, gfp);16341 NL80211_MCGRP_MLME, gfp);
16333 return;16342 return;
16334 16343
16335 nla_put_failure:16344nla_put_failure:
16336 nlmsg_free(msg);16345 nlmsg_free(msg);
16337}16346}
16347
16348void 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}
16355EXPORT_SYMBOL(cfg80211_control_port_tx_status);
16356
16357void 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}
16338EXPORT_SYMBOL(cfg80211_mgmt_tx_status);16363EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
16339 16364
16340static int __nl80211_rx_control_port(struct net_device *dev,16365static 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
748 struct net_device *dev,748 struct net_device *dev,
749 const void *buf, size_t len,749 const void *buf, size_t len,
750 const u8 *dest, __be16 proto,750 const u8 *dest, __be16 proto,
751 const bool noencrypt)751 const bool noencrypt, u64 *cookie)
752{752{
753 int ret;753 int ret;
754 trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,754 trace_rdev_tx_control_port(&rdev->wiphy, dev, buf, len,
755 dest, proto, noencrypt);755 dest, proto, noencrypt);
756 ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,756 ret = rdev->ops->tx_control_port(&rdev->wiphy, dev, buf, len,
757 dest, proto, noencrypt);757 dest, proto, noencrypt, cookie);
758 trace_rdev_return_int(&rdev->wiphy, ret);758 if (cookie)
759 trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
760 else
761 trace_rdev_return_int(&rdev->wiphy, ret);
759 return ret;762 return ret;
760}763}
761 764
net/wireless/trace.h+17−0
@@ -2861,6 +2861,23 @@ TRACE_EVENT(cfg80211_mgmt_tx_status, · 2860 unmodified lines
2861 WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack))2861 WDEV_PR_ARG, __entry->cookie, BOOL_TO_STR(__entry->ack))
2862);2862);
2863 2863
2864TRACE_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
2864TRACE_EVENT(cfg80211_rx_control_port,2881TRACE_EVENT(cfg80211_rx_control_port,
2865 TP_PROTO(struct net_device *netdev, struct sk_buff *skb,2882 TP_PROTO(struct net_device *netdev, struct sk_buff *skb,
2866 bool unencrypted),2883 bool unencrypted),