developer | f11ee16 | 2022-04-12 11:17:45 +0800 | [diff] [blame] | 1 | From: Aloka Dixit <alokad@codeaurora.org> |
| 2 | Date: Tue, 5 Oct 2021 21:09:36 -0700 |
| 3 | Subject: [PATCH] mac80211: split beacon retrieval functions |
| 4 | |
| 5 | Split __ieee80211_beacon_get() into a separate function for AP mode |
| 6 | ieee80211_beacon_get_ap(). |
| 7 | Also, move the code common to all modes (AP, adhoc and mesh) to |
| 8 | a separate function ieee80211_beacon_get_finish(). |
| 9 | |
| 10 | Signed-off-by: Aloka Dixit <alokad@codeaurora.org> |
| 11 | Link: https://lore.kernel.org/r/20211006040938.9531-2-alokad@codeaurora.org |
| 12 | Signed-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; |