| From: Aloka Dixit <alokad@codeaurora.org> |
| Date: Tue, 5 Oct 2021 21:09:36 -0700 |
| Subject: [PATCH] mac80211: split beacon retrieval functions |
| |
| Split __ieee80211_beacon_get() into a separate function for AP mode |
| ieee80211_beacon_get_ap(). |
| Also, move the code common to all modes (AP, adhoc and mesh) to |
| a separate function ieee80211_beacon_get_finish(). |
| |
| Signed-off-by: Aloka Dixit <alokad@codeaurora.org> |
| Link: https://lore.kernel.org/r/20211006040938.9531-2-alokad@codeaurora.org |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| --- |
| |
| --- a/net/mac80211/tx.c |
| +++ b/net/mac80211/tx.c |
| @@ -4987,6 +4987,115 @@ static int ieee80211_beacon_protect(stru |
| return 0; |
| } |
| |
| +static void |
| +ieee80211_beacon_get_finish(struct ieee80211_hw *hw, |
| + struct ieee80211_vif *vif, |
| + struct ieee80211_mutable_offsets *offs, |
| + struct beacon_data *beacon, |
| + struct sk_buff *skb, |
| + struct ieee80211_chanctx_conf *chanctx_conf, |
| + u16 csa_off_base) |
| +{ |
| + struct ieee80211_local *local = hw_to_local(hw); |
| + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
| + struct ieee80211_tx_info *info; |
| + enum nl80211_band band; |
| + struct ieee80211_tx_rate_control txrc; |
| + |
| + /* CSA offsets */ |
| + if (offs && beacon) { |
| + u16 i; |
| + |
| + for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) { |
| + u16 csa_off = beacon->cntdwn_counter_offsets[i]; |
| + |
| + if (!csa_off) |
| + continue; |
| + |
| + offs->cntdwn_counter_offs[i] = csa_off_base + csa_off; |
| + } |
| + } |
| + |
| + band = chanctx_conf->def.chan->band; |
| + info = IEEE80211_SKB_CB(skb); |
| + info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
| + info->flags |= IEEE80211_TX_CTL_NO_ACK; |
| + info->band = band; |
| + |
| + memset(&txrc, 0, sizeof(txrc)); |
| + txrc.hw = hw; |
| + txrc.sband = local->hw.wiphy->bands[band]; |
| + txrc.bss_conf = &sdata->vif.bss_conf; |
| + txrc.skb = skb; |
| + txrc.reported_rate.idx = -1; |
| + if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band]) |
| + txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band]; |
| + else |
| + txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; |
| + txrc.bss = true; |
| + rate_control_get_rate(sdata, NULL, &txrc); |
| + |
| + info->control.vif = vif; |
| + info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT | |
| + IEEE80211_TX_CTL_ASSIGN_SEQ | |
| + IEEE80211_TX_CTL_FIRST_FRAGMENT; |
| +} |
| + |
| +static struct sk_buff * |
| +ieee80211_beacon_get_ap(struct ieee80211_hw *hw, |
| + struct ieee80211_vif *vif, |
| + struct ieee80211_mutable_offsets *offs, |
| + bool is_template, |
| + struct beacon_data *beacon, |
| + struct ieee80211_chanctx_conf *chanctx_conf) |
| +{ |
| + struct ieee80211_local *local = hw_to_local(hw); |
| + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
| + struct ieee80211_if_ap *ap = &sdata->u.ap; |
| + struct sk_buff *skb = NULL; |
| + u16 csa_off_base = 0; |
| + |
| + if (beacon->cntdwn_counter_offsets[0]) { |
| + if (!is_template) |
| + ieee80211_beacon_update_cntdwn(vif); |
| + |
| + ieee80211_set_beacon_cntdwn(sdata, beacon); |
| + } |
| + |
| + /* headroom, head length, |
| + * tail length and maximum TIM length |
| + */ |
| + skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + |
| + beacon->tail_len + 256 + |
| + local->hw.extra_beacon_tailroom); |
| + if (!skb) |
| + return NULL; |
| + |
| + skb_reserve(skb, local->tx_headroom); |
| + skb_put_data(skb, beacon->head, beacon->head_len); |
| + |
| + ieee80211_beacon_add_tim(sdata, &ap->ps, skb, is_template); |
| + |
| + if (offs) { |
| + offs->tim_offset = beacon->head_len; |
| + offs->tim_length = skb->len - beacon->head_len; |
| + offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; |
| + |
| + /* for AP the csa offsets are from tail */ |
| + csa_off_base = skb->len; |
| + } |
| + |
| + if (beacon->tail) |
| + skb_put_data(skb, beacon->tail, beacon->tail_len); |
| + |
| + if (ieee80211_beacon_protect(skb, local, sdata) < 0) |
| + return NULL; |
| + |
| + ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, chanctx_conf, |
| + csa_off_base); |
| + return skb; |
| +} |
| + |
| static struct sk_buff * |
| __ieee80211_beacon_get(struct ieee80211_hw *hw, |
| struct ieee80211_vif *vif, |
| @@ -4996,12 +5105,8 @@ __ieee80211_beacon_get(struct ieee80211_ |
| struct ieee80211_local *local = hw_to_local(hw); |
| struct beacon_data *beacon = NULL; |
| struct sk_buff *skb = NULL; |
| - struct ieee80211_tx_info *info; |
| struct ieee80211_sub_if_data *sdata = NULL; |
| - enum nl80211_band band; |
| - struct ieee80211_tx_rate_control txrc; |
| struct ieee80211_chanctx_conf *chanctx_conf; |
| - int csa_off_base = 0; |
| |
| rcu_read_lock(); |
| |
| @@ -5018,48 +5123,11 @@ __ieee80211_beacon_get(struct ieee80211_ |
| struct ieee80211_if_ap *ap = &sdata->u.ap; |
| |
| beacon = rcu_dereference(ap->beacon); |
| - if (beacon) { |
| - if (beacon->cntdwn_counter_offsets[0]) { |
| - if (!is_template) |
| - ieee80211_beacon_update_cntdwn(vif); |
| - |
| - ieee80211_set_beacon_cntdwn(sdata, beacon); |
| - } |
| - |
| - /* |
| - * headroom, head length, |
| - * tail length and maximum TIM length |
| - */ |
| - skb = dev_alloc_skb(local->tx_headroom + |
| - beacon->head_len + |
| - beacon->tail_len + 256 + |
| - local->hw.extra_beacon_tailroom); |
| - if (!skb) |
| - goto out; |
| - |
| - skb_reserve(skb, local->tx_headroom); |
| - skb_put_data(skb, beacon->head, beacon->head_len); |
| - |
| - ieee80211_beacon_add_tim(sdata, &ap->ps, skb, |
| - is_template); |
| - |
| - if (offs) { |
| - offs->tim_offset = beacon->head_len; |
| - offs->tim_length = skb->len - beacon->head_len; |
| - offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; |
| - |
| - /* for AP the csa offsets are from tail */ |
| - csa_off_base = skb->len; |
| - } |
| - |
| - if (beacon->tail) |
| - skb_put_data(skb, beacon->tail, |
| - beacon->tail_len); |
| - |
| - if (ieee80211_beacon_protect(skb, local, sdata) < 0) |
| - goto out; |
| - } else |
| + if (!beacon) |
| goto out; |
| + |
| + skb = ieee80211_beacon_get_ap(hw, vif, offs, is_template, |
| + beacon, chanctx_conf); |
| } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
| struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
| struct ieee80211_hdr *hdr; |
| @@ -5085,6 +5153,9 @@ __ieee80211_beacon_get(struct ieee80211_ |
| hdr = (struct ieee80211_hdr *) skb->data; |
| hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
| IEEE80211_STYPE_BEACON); |
| + |
| + ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, |
| + chanctx_conf, 0); |
| } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
| struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| |
| @@ -5124,51 +5195,13 @@ __ieee80211_beacon_get(struct ieee80211_ |
| } |
| |
| skb_put_data(skb, beacon->tail, beacon->tail_len); |
| + ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, |
| + chanctx_conf, 0); |
| } else { |
| WARN_ON(1); |
| goto out; |
| } |
| |
| - /* CSA offsets */ |
| - if (offs && beacon) { |
| - int i; |
| - |
| - for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) { |
| - u16 csa_off = beacon->cntdwn_counter_offsets[i]; |
| - |
| - if (!csa_off) |
| - continue; |
| - |
| - offs->cntdwn_counter_offs[i] = csa_off_base + csa_off; |
| - } |
| - } |
| - |
| - band = chanctx_conf->def.chan->band; |
| - |
| - info = IEEE80211_SKB_CB(skb); |
| - |
| - info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
| - info->flags |= IEEE80211_TX_CTL_NO_ACK; |
| - info->band = band; |
| - |
| - memset(&txrc, 0, sizeof(txrc)); |
| - txrc.hw = hw; |
| - txrc.sband = local->hw.wiphy->bands[band]; |
| - txrc.bss_conf = &sdata->vif.bss_conf; |
| - txrc.skb = skb; |
| - txrc.reported_rate.idx = -1; |
| - if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band]) |
| - txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band]; |
| - else |
| - txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; |
| - txrc.bss = true; |
| - rate_control_get_rate(sdata, NULL, &txrc); |
| - |
| - info->control.vif = vif; |
| - |
| - info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT | |
| - IEEE80211_TX_CTL_ASSIGN_SEQ | |
| - IEEE80211_TX_CTL_FIRST_FRAGMENT; |
| out: |
| rcu_read_unlock(); |
| return skb; |