blob: ac707de53e34300df9492c0e4d3b439d7c05f5e8 [file] [log] [blame]
developera1432902023-04-01 04:45:58 +08001From: Johannes Berg <johannes.berg@intel.com>
2Date: Wed, 29 Mar 2023 16:46:26 +0200
3Subject: [PATCH] wifi: ieee80211: correctly mark FTM frames non-bufferable
4
5The checks of whether or not a frame is bufferable were not
6taking into account that some action frames aren't, such as
7FTM. Check this, which requires some changes to the function
8ieee80211_is_bufferable_mmpdu() since we need the whole skb
9for the checks now.
10
11Signed-off-by: Johannes Berg <johannes.berg@intel.com>
12Reviewed-by: Greenman, Gregory <gregory.greenman@intel.com>
13Reviewed-by: Peer, Ilan <ilan.peer@intel.com>
14---
15
16--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
17+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
18@@ -551,8 +551,9 @@ static void iwl_mvm_skb_prepare_status(s
19
20 static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
21 struct ieee80211_tx_info *info,
22- struct ieee80211_hdr *hdr)
23+ struct sk_buff *skb)
24 {
25+ struct ieee80211_hdr *hdr = (void *)skb->data;
26 struct iwl_mvm_vif *mvmvif =
27 iwl_mvm_vif_from_mac80211(info->control.vif);
28 __le16 fc = hdr->frame_control;
29@@ -571,7 +572,7 @@ static int iwl_mvm_get_ctrl_vif_queue(st
30 * reason 7 ("Class 3 frame received from nonassociated STA").
31 */
32 if (ieee80211_is_mgmt(fc) &&
33- (!ieee80211_is_bufferable_mmpdu(fc) ||
34+ (!ieee80211_is_bufferable_mmpdu(skb) ||
35 ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc)))
36 return mvm->probe_queue;
37
38@@ -689,7 +690,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
39 else
40 sta_id = mvmvif->mcast_sta.sta_id;
41
42- queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, hdr);
43+ queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, skb);
44 } else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) {
45 queue = mvm->snif_queue;
46 sta_id = mvm->snif_sta.sta_id;
47--- a/include/linux/ieee80211.h
48+++ b/include/linux/ieee80211.h
49@@ -738,20 +738,6 @@ static inline bool ieee80211_is_any_null
50 }
51
52 /**
53- * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
54- * @fc: frame control field in little-endian byteorder
55- */
56-static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
57-{
58- /* IEEE 802.11-2012, definition of "bufferable management frame";
59- * note that this ignores the IBSS special case. */
60- return ieee80211_is_mgmt(fc) &&
61- (ieee80211_is_action(fc) ||
62- ieee80211_is_disassoc(fc) ||
63- ieee80211_is_deauth(fc));
64-}
65-
66-/**
67 * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
68 * @seq_ctrl: frame sequence control bytes in little-endian byteorder
69 */
70@@ -3672,6 +3658,44 @@ static inline u8 *ieee80211_get_DA(struc
71 }
72
73 /**
74+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
75+ * @skb: the skb to check, starting with the 802.11 header
76+ */
77+static inline bool ieee80211_is_bufferable_mmpdu(struct sk_buff *skb)
78+{
79+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
80+ __le16 fc = mgmt->frame_control;
81+
82+ /*
83+ * IEEE 802.11 REVme D2.0 definition of bufferable MMPDU;
84+ * note that this ignores the IBSS special case.
85+ */
86+ if (!ieee80211_is_mgmt(fc))
87+ return false;
88+
89+ if (ieee80211_is_disassoc(fc) || ieee80211_is_deauth(fc))
90+ return true;
91+
92+ if (!ieee80211_is_action(fc))
93+ return false;
94+
95+ if (skb->len < offsetofend(typeof(*mgmt), u.action.u.ftm.action_code))
96+ return true;
97+
98+ /* action frame - additionally check for non-bufferable FTM */
99+
100+ if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC &&
101+ mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION)
102+ return true;
103+
104+ if (mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_REQUEST ||
105+ mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM)
106+ return false;
107+
108+ return true;
109+}
110+
111+/**
112 * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
113 * @hdr: the frame (buffer must include at least the first octet of payload)
114 */
115--- a/net/mac80211/tx.c
116+++ b/net/mac80211/tx.c
117@@ -487,7 +487,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
118 int ac = skb_get_queue_mapping(tx->skb);
119
120 if (ieee80211_is_mgmt(hdr->frame_control) &&
121- !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
122+ !ieee80211_is_bufferable_mmpdu(tx->skb)) {
123 info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
124 return TX_CONTINUE;
125 }
126@@ -1282,7 +1282,7 @@ static struct txq_info *ieee80211_get_tx
127 if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
128 unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
129 if ((!ieee80211_is_mgmt(hdr->frame_control) ||
130- ieee80211_is_bufferable_mmpdu(hdr->frame_control) ||
131+ ieee80211_is_bufferable_mmpdu(skb) ||
132 vif->type == NL80211_IFTYPE_STATION) &&
133 sta && sta->uploaded) {
134 /*