blob: 18b1951f6e7796aa54942e31b32592e429864731 [file] [log] [blame]
developerec4ebe42022-04-12 11:17:45 +08001From: Aloka Dixit <alokad@codeaurora.org>
2Date: Tue, 5 Oct 2021 21:09:36 -0700
3Subject: [PATCH] mac80211: split beacon retrieval functions
4
5Split __ieee80211_beacon_get() into a separate function for AP mode
6ieee80211_beacon_get_ap().
7Also, move the code common to all modes (AP, adhoc and mesh) to
8a separate function ieee80211_beacon_get_finish().
9
10Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
11Link: https://lore.kernel.org/r/20211006040938.9531-2-alokad@codeaurora.org
12Signed-off-by: Johannes Berg <johannes.berg@intel.com>
13---
14
15--- a/net/mac80211/tx.c
16+++ b/net/mac80211/tx.c
17@@ -4987,6 +4987,115 @@ static int ieee80211_beacon_protect(stru
18 return 0;
19 }
20
21+static void
22+ieee80211_beacon_get_finish(struct ieee80211_hw *hw,
23+ struct ieee80211_vif *vif,
24+ struct ieee80211_mutable_offsets *offs,
25+ struct beacon_data *beacon,
26+ struct sk_buff *skb,
27+ struct ieee80211_chanctx_conf *chanctx_conf,
28+ u16 csa_off_base)
29+{
30+ struct ieee80211_local *local = hw_to_local(hw);
31+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
32+ struct ieee80211_tx_info *info;
33+ enum nl80211_band band;
34+ struct ieee80211_tx_rate_control txrc;
35+
36+ /* CSA offsets */
37+ if (offs && beacon) {
38+ u16 i;
39+
40+ for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) {
41+ u16 csa_off = beacon->cntdwn_counter_offsets[i];
42+
43+ if (!csa_off)
44+ continue;
45+
46+ offs->cntdwn_counter_offs[i] = csa_off_base + csa_off;
47+ }
48+ }
49+
50+ band = chanctx_conf->def.chan->band;
51+ info = IEEE80211_SKB_CB(skb);
52+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
53+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
54+ info->band = band;
55+
56+ memset(&txrc, 0, sizeof(txrc));
57+ txrc.hw = hw;
58+ txrc.sband = local->hw.wiphy->bands[band];
59+ txrc.bss_conf = &sdata->vif.bss_conf;
60+ txrc.skb = skb;
61+ txrc.reported_rate.idx = -1;
62+ if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band])
63+ txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band];
64+ else
65+ txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
66+ txrc.bss = true;
67+ rate_control_get_rate(sdata, NULL, &txrc);
68+
69+ info->control.vif = vif;
70+ info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
71+ IEEE80211_TX_CTL_ASSIGN_SEQ |
72+ IEEE80211_TX_CTL_FIRST_FRAGMENT;
73+}
74+
75+static struct sk_buff *
76+ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
77+ struct ieee80211_vif *vif,
78+ struct ieee80211_mutable_offsets *offs,
79+ bool is_template,
80+ struct beacon_data *beacon,
81+ struct ieee80211_chanctx_conf *chanctx_conf)
82+{
83+ struct ieee80211_local *local = hw_to_local(hw);
84+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
85+ struct ieee80211_if_ap *ap = &sdata->u.ap;
86+ struct sk_buff *skb = NULL;
87+ u16 csa_off_base = 0;
88+
89+ if (beacon->cntdwn_counter_offsets[0]) {
90+ if (!is_template)
91+ ieee80211_beacon_update_cntdwn(vif);
92+
93+ ieee80211_set_beacon_cntdwn(sdata, beacon);
94+ }
95+
96+ /* headroom, head length,
97+ * tail length and maximum TIM length
98+ */
99+ skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
100+ beacon->tail_len + 256 +
101+ local->hw.extra_beacon_tailroom);
102+ if (!skb)
103+ return NULL;
104+
105+ skb_reserve(skb, local->tx_headroom);
106+ skb_put_data(skb, beacon->head, beacon->head_len);
107+
108+ ieee80211_beacon_add_tim(sdata, &ap->ps, skb, is_template);
109+
110+ if (offs) {
111+ offs->tim_offset = beacon->head_len;
112+ offs->tim_length = skb->len - beacon->head_len;
113+ offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
114+
115+ /* for AP the csa offsets are from tail */
116+ csa_off_base = skb->len;
117+ }
118+
119+ if (beacon->tail)
120+ skb_put_data(skb, beacon->tail, beacon->tail_len);
121+
122+ if (ieee80211_beacon_protect(skb, local, sdata) < 0)
123+ return NULL;
124+
125+ ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, chanctx_conf,
126+ csa_off_base);
127+ return skb;
128+}
129+
130 static struct sk_buff *
131 __ieee80211_beacon_get(struct ieee80211_hw *hw,
132 struct ieee80211_vif *vif,
133@@ -4996,12 +5105,8 @@ __ieee80211_beacon_get(struct ieee80211_
134 struct ieee80211_local *local = hw_to_local(hw);
135 struct beacon_data *beacon = NULL;
136 struct sk_buff *skb = NULL;
137- struct ieee80211_tx_info *info;
138 struct ieee80211_sub_if_data *sdata = NULL;
139- enum nl80211_band band;
140- struct ieee80211_tx_rate_control txrc;
141 struct ieee80211_chanctx_conf *chanctx_conf;
142- int csa_off_base = 0;
143
144 rcu_read_lock();
145
146@@ -5018,48 +5123,11 @@ __ieee80211_beacon_get(struct ieee80211_
147 struct ieee80211_if_ap *ap = &sdata->u.ap;
148
149 beacon = rcu_dereference(ap->beacon);
150- if (beacon) {
151- if (beacon->cntdwn_counter_offsets[0]) {
152- if (!is_template)
153- ieee80211_beacon_update_cntdwn(vif);
154-
155- ieee80211_set_beacon_cntdwn(sdata, beacon);
156- }
157-
158- /*
159- * headroom, head length,
160- * tail length and maximum TIM length
161- */
162- skb = dev_alloc_skb(local->tx_headroom +
163- beacon->head_len +
164- beacon->tail_len + 256 +
165- local->hw.extra_beacon_tailroom);
166- if (!skb)
167- goto out;
168-
169- skb_reserve(skb, local->tx_headroom);
170- skb_put_data(skb, beacon->head, beacon->head_len);
171-
172- ieee80211_beacon_add_tim(sdata, &ap->ps, skb,
173- is_template);
174-
175- if (offs) {
176- offs->tim_offset = beacon->head_len;
177- offs->tim_length = skb->len - beacon->head_len;
178- offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
179-
180- /* for AP the csa offsets are from tail */
181- csa_off_base = skb->len;
182- }
183-
184- if (beacon->tail)
185- skb_put_data(skb, beacon->tail,
186- beacon->tail_len);
187-
188- if (ieee80211_beacon_protect(skb, local, sdata) < 0)
189- goto out;
190- } else
191+ if (!beacon)
192 goto out;
193+
194+ skb = ieee80211_beacon_get_ap(hw, vif, offs, is_template,
195+ beacon, chanctx_conf);
196 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
197 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
198 struct ieee80211_hdr *hdr;
199@@ -5085,6 +5153,9 @@ __ieee80211_beacon_get(struct ieee80211_
200 hdr = (struct ieee80211_hdr *) skb->data;
201 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
202 IEEE80211_STYPE_BEACON);
203+
204+ ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb,
205+ chanctx_conf, 0);
206 } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
207 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
208
209@@ -5124,51 +5195,13 @@ __ieee80211_beacon_get(struct ieee80211_
210 }
211
212 skb_put_data(skb, beacon->tail, beacon->tail_len);
213+ ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb,
214+ chanctx_conf, 0);
215 } else {
216 WARN_ON(1);
217 goto out;
218 }
219
220- /* CSA offsets */
221- if (offs && beacon) {
222- int i;
223-
224- for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) {
225- u16 csa_off = beacon->cntdwn_counter_offsets[i];
226-
227- if (!csa_off)
228- continue;
229-
230- offs->cntdwn_counter_offs[i] = csa_off_base + csa_off;
231- }
232- }
233-
234- band = chanctx_conf->def.chan->band;
235-
236- info = IEEE80211_SKB_CB(skb);
237-
238- info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
239- info->flags |= IEEE80211_TX_CTL_NO_ACK;
240- info->band = band;
241-
242- memset(&txrc, 0, sizeof(txrc));
243- txrc.hw = hw;
244- txrc.sband = local->hw.wiphy->bands[band];
245- txrc.bss_conf = &sdata->vif.bss_conf;
246- txrc.skb = skb;
247- txrc.reported_rate.idx = -1;
248- if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band])
249- txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band];
250- else
251- txrc.rate_idx_mask = sdata->rc_rateidx_mask[band];
252- txrc.bss = true;
253- rate_control_get_rate(sdata, NULL, &txrc);
254-
255- info->control.vif = vif;
256-
257- info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
258- IEEE80211_TX_CTL_ASSIGN_SEQ |
259- IEEE80211_TX_CTL_FIRST_FRAGMENT;
260 out:
261 rcu_read_unlock();
262 return skb;