Commit a6e34fde authored by Aloka Dixit's avatar Aloka Dixit Committed by Johannes Berg
Browse files

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: default avatarAloka Dixit <alokad@codeaurora.org>
Link: https://lore.kernel.org/r/20211006040938.9531-2-alokad@codeaurora.org


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 97981d89
Loading
Loading
Loading
Loading
+118 −85
Original line number Diff line number Diff line
@@ -4979,38 +4979,74 @@ static int ieee80211_beacon_protect(struct sk_buff *skb,
	return 0;
}

static struct sk_buff *
__ieee80211_beacon_get(struct ieee80211_hw *hw,
static void
ieee80211_beacon_get_finish(struct ieee80211_hw *hw,
			    struct ieee80211_vif *vif,
			    struct ieee80211_mutable_offsets *offs,
		       bool is_template)
			    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 beacon_data *beacon = NULL;
	struct sk_buff *skb = NULL;
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	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();
	/* CSA offsets */
	if (offs && beacon) {
		u16 i;

	sdata = vif_to_sdata(vif);
	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
		for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) {
			u16 csa_off = beacon->cntdwn_counter_offsets[i];

	if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
		goto out;
			if (!csa_off)
				continue;

	if (offs)
		memset(offs, 0, sizeof(*offs));
			offs->cntdwn_counter_offs[i] = csa_off_base + csa_off;
		}
	}

	if (sdata->vif.type == NL80211_IFTYPE_AP) {
	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;

		beacon = rcu_dereference(ap->beacon);
		if (beacon) {
	if (beacon->cntdwn_counter_offsets[0]) {
		if (!is_template)
			ieee80211_beacon_update_cntdwn(vif);
@@ -5018,22 +5054,19 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
		ieee80211_set_beacon_cntdwn(sdata, beacon);
	}

			/*
			 * headroom, head length,
	/* headroom, head length,
	 * tail length and maximum TIM length
	 */
			skb = dev_alloc_skb(local->tx_headroom +
					    beacon->head_len +
	skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
			    beacon->tail_len + 256 +
			    local->hw.extra_beacon_tailroom);
	if (!skb)
				goto out;
		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);
	ieee80211_beacon_add_tim(sdata, &ap->ps, skb, is_template);

	if (offs) {
		offs->tim_offset = beacon->head_len;
@@ -5045,13 +5078,48 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
	}

	if (beacon->tail)
				skb_put_data(skb, beacon->tail,
					     beacon->tail_len);
		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,
		       struct ieee80211_mutable_offsets *offs,
		       bool is_template)
{
	struct ieee80211_local *local = hw_to_local(hw);
	struct beacon_data *beacon = NULL;
	struct sk_buff *skb = NULL;
	struct ieee80211_sub_if_data *sdata = NULL;
	struct ieee80211_chanctx_conf *chanctx_conf;

	rcu_read_lock();

	sdata = vif_to_sdata(vif);
	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);

	if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
		goto out;
		} else

	if (offs)
		memset(offs, 0, sizeof(*offs));

	if (sdata->vif.type == NL80211_IFTYPE_AP) {
		struct ieee80211_if_ap *ap = &sdata->u.ap;

		beacon = rcu_dereference(ap->beacon);
		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;
@@ -5077,6 +5145,9 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
		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;

@@ -5116,51 +5187,13 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
		}

		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;