/** * DOC: STA information lifetime rules * * STA info structures (&struct sta_info) are managed in a hash table * for faster lookup and a list for iteration. They are managed using * RCU, i.e. access to the list and hash table is protected by RCU. * * Upon allocating a STA info structure with sta_info_alloc(), the caller * owns that structure. It must then insert it into the hash table using * either sta_info_insert() or sta_info_insert_rcu(); only in the latter * case (which acquires an rcu read section but must not be called from * within one) will the pointer still be valid after the call. Note that * the caller may not do much with the STA info before inserting it; in * particular, it may not start any mesh peer link management or add * encryption keys. * * When the insertion fails (sta_info_insert()) returns non-zero), the * structure will have been freed by sta_info_insert()! * * Station entries are added by mac80211 when you establish a link with a * peer. This means different things for the different type of interfaces * we support. For a regular station this mean we add the AP sta when we * receive an association response from the AP. For IBSS this occurs when * get to know about a peer on the same IBSS. For WDS we add the sta for * the peer immediately upon device open. When using AP mode we add stations * for each respective station upon request from userspace through nl80211. * * In order to remove a STA info structure, various sta_info_destroy_*() * calls are available. * * There is no concept of ownership on a STA entry; each structure is * owned by the global hash table/list until it is removed. All users of * the structure need to be RCU protected so that the structure won't be * freed before they are done using it.
*/
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]);
ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]);
ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]);
}
if (ieee80211_vif_is_mesh(&sdata->vif))
mesh_sta_cleanup(sta);
cancel_work_sync(&sta->drv_deliver_wk);
/* * Destroy aggregation state here. It would be nice to wait for the * driver to finish aggregation stop and then clean up, but for now * drivers have to handle aggregation stop being requested, followed * directly by station destruction.
*/ for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
kfree(sta->ampdu_mlme.tid_start_tx[i]);
tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); if (!tid_tx) continue;
ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
kfree(tid_tx);
}
}
rcu_read_lock();
for_each_sta_info(local, addr, sta, tmp) { if (sta->sdata == sdata) {
rcu_read_unlock(); /* this is safe as the caller must already hold * another rcu read section or the mutex
*/ return sta;
}
}
rcu_read_unlock(); return NULL;
}
/* * Get sta info either from the specified interface * or from one of its vlans
*/ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, const u8 *addr)
{ struct ieee80211_local *local = sdata->local; struct rhlist_head *tmp; struct sta_info *sta;
rcu_read_lock();
for_each_sta_info(local, addr, sta, tmp) { if (sta->sdata == sdata ||
(sta->sdata->bss && sta->sdata->bss == sdata->bss)) {
rcu_read_unlock(); /* this is safe as the caller must already hold * another rcu read section or the mutex
*/ return sta;
}
}
rcu_read_unlock(); return NULL;
}
if (sta->sdata == sdata ||
(sta->sdata->bss && sta->sdata->bss == sdata->bss)) {
rcu_read_unlock(); /* this is safe as the caller must already hold * another rcu read section or the mutex
*/ return link_sta;
}
}
rcu_read_unlock(); return NULL;
}
/** * sta_info_free - free STA * * @local: pointer to the global information * @sta: STA info to free * * This function must undo everything done by sta_info_alloc() * that may happen before sta_info_insert(). It may only be * called when sta_info_insert() has not been attempted (and * if that fails, the station is freed anyway.)
*/ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
{ int i;
for (i = 0; i < ARRAY_SIZE(sta->link); i++) { struct link_sta_info *link_sta;
link_sta = rcu_access_pointer(sta->link[i]); if (!link_sta) continue;
sta_remove_link(sta, i, false);
}
/* * If we had used sta_info_pre_move_state() then we might not * have gone through the state transitions down again, so do * it here now (and warn if it's inserted). * * This will clear state such as fast TX/RX that may have been * allocated during state transitions.
*/ while (sta->sta_state > IEEE80211_STA_NONE) { int ret;
ewma_signal_init(&link_info->rx_stats_avg.signal);
ewma_avg_signal_init(&link_info->status_stats.avg_ack_signal); for (i = 0; i < ARRAY_SIZE(link_info->rx_stats_avg.chain_signal); i++)
ewma_signal_init(&link_info->rx_stats_avg.chain_signal[i]);
/* * Cause (a) warning(s) if IEEE80211_STA_RX_BW_MAX != 320 * or if new values are added to the enum.
*/ switch (link_info->cur_max_bandwidth) { case IEEE80211_STA_RX_BW_20: case IEEE80211_STA_RX_BW_40: case IEEE80211_STA_RX_BW_80: case IEEE80211_STA_RX_BW_160: case IEEE80211_STA_RX_BW_MAX: /* intentionally nothing */ break;
}
/* TODO link specific alloc and assignments for MLO Link STA */
/* Extended Key ID needs to install keys for keyid 0 and 1 Rx-only. * The Tx path starts to use a key as soon as the key slot ptk_idx * references to is not NULL. To not use the initial Rx-only key * prematurely for Tx initialize ptk_idx to an impossible PTK keyid * which always will refer to a NULL key.
*/
BUILD_BUG_ON(ARRAY_SIZE(sta->ptk) <= INVALID_PTK_KEYIDX);
sta->ptk_idx = INVALID_PTK_KEYIDX;
ieee80211_init_frag_cache(&sta->frags);
sta->sta_state = IEEE80211_STA_NONE;
if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
sta->amsdu_mesh_control = -1;
/* Mark TID as unreserved */
sta->reserved_tid = IEEE80211_TID_UNRESERVED;
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
skb_queue_head_init(&sta->ps_tx_buf[i]);
skb_queue_head_init(&sta->tx_filtered[i]);
sta->airtime[i].deficit = sta->airtime_weight;
atomic_set(&sta->airtime[i].aql_tx_pending, 0);
sta->airtime[i].aql_limit_low = local->aql_txq_limit_low[i];
sta->airtime[i].aql_limit_high = local->aql_txq_limit_high[i];
}
for (i = 0; i < IEEE80211_NUM_TIDS; i++)
sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX);
for (i = 0; i < NUM_NL80211_BANDS; i++) {
u32 mandatory = 0; int r;
if (!hw->wiphy->bands[i]) continue;
switch (i) { case NL80211_BAND_2GHZ: case NL80211_BAND_LC: /* * We use both here, even if we cannot really know for * sure the station will support both, but the only use * for this is when we don't know anything yet and send * management frames, and then we'll pick the lowest * possible rate anyway. * If we don't include _G here, we cannot find a rate * in P2P, and thus trigger the WARN_ONCE() in rate.c
*/
mandatory = IEEE80211_RATE_MANDATORY_B |
IEEE80211_RATE_MANDATORY_G; break; case NL80211_BAND_5GHZ: case NL80211_BAND_6GHZ:
mandatory = IEEE80211_RATE_MANDATORY_A; break; case NL80211_BAND_60GHZ:
WARN_ON(1);
mandatory = 0; break;
}
for (r = 0; r < hw->wiphy->bands[i]->n_bitrates; r++) { struct ieee80211_rate *rate;
rate = &hw->wiphy->bands[i]->bitrates[r];
if (!(rate->flags & mandatory)) continue;
sta->sta.deflink.supp_rates[i] |= BIT(r);
}
}
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
/* * Can't be a WARN_ON because it can be triggered through a race: * something inserts a STA (on one CPU) without holding the RTNL * and another CPU turns off the net device.
*/ if (unlikely(!ieee80211_sdata_running(sdata))) return -ENETDOWN;
if (WARN_ON(ether_addr_equal(sta->sta.addr, sdata->vif.addr) ||
!is_valid_ether_addr(sta->sta.addr))) return -EINVAL;
/* The RCU read lock is required by rhashtable due to * asynchronous resize/rehash. We also require the mutex * for correctness.
*/
rcu_read_lock(); if (ieee80211_hw_check(&sdata->local->hw, NEEDS_UNIQUE_STA_ADDR) &&
ieee80211_find_sta_by_ifaddr(&sdata->local->hw, sta->addr, NULL)) {
rcu_read_unlock(); return -ENOTUNIQ;
}
rcu_read_unlock();
for (state = IEEE80211_STA_NOTEXIST; state < sta->sta_state; state++) {
err = drv_sta_state(local, sdata, sta, state, state + 1); if (err) break;
}
if (!err) { /* * Drivers using legacy sta_add/sta_remove callbacks only * get uploaded set to true after sta_add is called.
*/ if (!local->ops->sta_add)
sta->uploaded = true; return 0;
}
if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
sdata_info(sdata, "failed to move IBSS STA %pM to state %d (%d) - keeping it anyway\n",
sta->sta.addr, state + 1, err);
err = 0;
}
/* unwind on error */ for (; state > IEEE80211_STA_NOTEXIST; state--)
WARN_ON(drv_sta_state(local, sdata, sta, state, state - 1));
/* simplify things and don't accept BA sessions yet */
set_sta_flag(sta, WLAN_STA_BLOCK_BA);
/* make the station visible */
err = sta_info_hash_add(local, sta); if (err) goto out_drop_sta;
if (sta->sta.valid_links) {
err = link_sta_info_hash_add(local, &sta->deflink); if (err) {
sta_info_hash_del(local, sta); goto out_drop_sta;
}
}
list_add_tail_rcu(&sta->list, &local->sta_list);
/* update channel context before notifying the driver about state * change, this enables driver using the updated channel context right away.
*/ if (sta->sta_state >= IEEE80211_STA_ASSOC) {
ieee80211_recalc_min_chandef(sta->sdata, -1); if (!sta->sta.support_p2p_ps)
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
}
int sta_info_insert(struct sta_info *sta)
{ int err = sta_info_insert_rcu(sta);
rcu_read_unlock();
return err;
}
staticinlinevoid __bss_tim_set(u8 *tim, u16 id)
{ /* * This format has been mandated by the IEEE specifications, * so this line may not be changed to use the __set_bit() format.
*/
tim[id / 8] |= (1 << (id % 8));
}
staticinlinevoid __bss_tim_clear(u8 *tim, u16 id)
{ /* * This format has been mandated by the IEEE specifications, * so this line may not be changed to use the __clear_bit() format.
*/
tim[id / 8] &= ~(1 << (id % 8));
}
staticinlinebool __bss_tim_get(u8 *tim, u16 id)
{ /* * This format has been mandated by the IEEE specifications, * so this line may not be changed to use the test_bit() format.
*/ return tim[id / 8] & (1 << (id % 8));
}
staticunsignedlong ieee80211_tids_for_ac(int ac)
{ /* If we ever support TIDs > 7, this obviously needs to be adjusted */ switch (ac) { case IEEE80211_AC_VO: return BIT(6) | BIT(7); case IEEE80211_AC_VI: return BIT(4) | BIT(5); case IEEE80211_AC_BE: return BIT(0) | BIT(3); case IEEE80211_AC_BK: return BIT(1) | BIT(2); default:
WARN_ON(1); return 0;
}
}
/* No need to do anything if the driver does all */ if (ieee80211_hw_check(&local->hw, AP_LINK_PS) && !local->ops->set_tim) return;
if (sta->dead) goto done;
/* * If all ACs are delivery-enabled then we should build * the TIM bit for all ACs anyway; if only some are then * we ignore those and build the TIM bit using only the * non-enabled ones.
*/ if (ignore_for_tim == BIT(IEEE80211_NUM_ACS) - 1)
ignore_for_tim = 0;
if (ignore_pending)
ignore_for_tim = BIT(IEEE80211_NUM_ACS) - 1;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { unsignedlong tids;
if (ignore_for_tim & ieee80211_ac_to_qos_mask[ac]) continue;
indicate_tim |= !skb_queue_empty(&sta->tx_filtered[ac]) ||
!skb_queue_empty(&sta->ps_tx_buf[ac]); if (indicate_tim) break;
/* * First check for frames that should expire on the filtered * queue. Frames here were rejected by the driver and are on * a separate queue to avoid reordering with normal PS-buffered * frames. They also aren't accounted for right now in the * total_ps_buffered counter.
*/ for (;;) {
spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags);
skb = skb_peek(&sta->tx_filtered[ac]); if (sta_info_buffer_expired(sta, skb))
skb = __skb_dequeue(&sta->tx_filtered[ac]); else
skb = NULL;
spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags);
/* * Frames are queued in order, so if this one * hasn't expired yet we can stop testing. If * we actually reached the end of the queue we * also need to stop, of course.
*/ if (!skb) break;
ieee80211_free_txskb(&local->hw, skb);
}
/* * Now also check the normal PS-buffered queue, this will * only find something if the filtered queue was emptied * since the filtered frames are all before the normal PS * buffered frames.
*/ for (;;) {
spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags);
skb = skb_peek(&sta->ps_tx_buf[ac]); if (sta_info_buffer_expired(sta, skb))
skb = __skb_dequeue(&sta->ps_tx_buf[ac]); else
skb = NULL;
spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags);
/* * frames are queued in order, so if this one * hasn't expired yet (or we reached the end of * the queue) we can stop testing
*/ if (!skb) break;
/* * Finally, recalculate the TIM bit for this station -- it might * now be clear because the station was too slow to retrieve its * frames.
*/
sta_info_recalc_tim(sta);
/* * Return whether there are any frames still buffered, this is * used to check whether the cleanup timer still needs to run, * if there are no frames we don't need to rearm the timer.
*/ return !(skb_queue_empty(&sta->ps_tx_buf[ac]) &&
skb_queue_empty(&sta->tx_filtered[ac]));
}
/* * Before removing the station from the driver and * rate control, it might still start new aggregation * sessions -- block that to make sure the tear-down * will be sufficient.
*/
set_sta_flag(sta, WLAN_STA_BLOCK_BA);
ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA);
/* * Before removing the station from the driver there might be pending * rx frames on RSS queues sent prior to the disassociation - wait for * all such frames to be processed.
*/
drv_sync_rx_queues(local, sta);
for (i = 0; i < ARRAY_SIZE(sta->link); i++) { struct link_sta_info *link_sta;
ret = sta_info_hash_del(local, sta); if (WARN_ON(ret)) return ret;
/* * for TDLS peers, make sure to return to the base channel before * removal.
*/ if (test_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL)) {
drv_tdls_cancel_channel_switch(local, sdata, &sta->sta);
clear_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL);
}
list_del_rcu(&sta->list);
sta->removed = true;
if (sta->uploaded)
drv_sta_pre_rcu_remove(local, sta->sdata, sta);
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
rcu_access_pointer(sdata->u.vlan.sta) == sta)
RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
switch (new_state) { case IEEE80211_STA_NONE: if (sta->sta_state != IEEE80211_STA_AUTH) return -EINVAL; break; case IEEE80211_STA_AUTH: if (sta->sta_state != IEEE80211_STA_NONE &&
sta->sta_state != IEEE80211_STA_ASSOC) return -EINVAL; break; case IEEE80211_STA_ASSOC: if (sta->sta_state != IEEE80211_STA_AUTH &&
sta->sta_state != IEEE80211_STA_AUTHORIZED) return -EINVAL; break; case IEEE80211_STA_AUTHORIZED: if (sta->sta_state != IEEE80211_STA_ASSOC) return -EINVAL; break; default:
WARN(1, "invalid state %d", new_state); return -EINVAL;
}
sta_dbg(sta->sdata, "moving STA %pM to state %d\n",
sta->sta.addr, new_state);
/* notify the driver before the actual changes so it can * fail the transition if the state is increasing. * The driver is required not to fail when the transition * is decreasing the state, so first, do all the preparation * work and only then, notify the driver.
*/ if (new_state > sta->sta_state &&
test_sta_flag(sta, WLAN_STA_INSERTED)) { int err = drv_sta_state(sta->local, sta->sdata, sta,
sta->sta_state, new_state); if (err) return err;
}
/* reflect the change in all state variables */
switch (new_state) { case IEEE80211_STA_NONE: if (sta->sta_state == IEEE80211_STA_AUTH)
clear_bit(WLAN_STA_AUTH, &sta->_flags); break; case IEEE80211_STA_AUTH: if (sta->sta_state == IEEE80211_STA_NONE) {
set_bit(WLAN_STA_AUTH, &sta->_flags);
} elseif (sta->sta_state == IEEE80211_STA_ASSOC) {
clear_bit(WLAN_STA_ASSOC, &sta->_flags); if (recalc) {
ieee80211_recalc_min_chandef(sta->sdata, -1); if (!sta->sta.support_p2p_ps)
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
}
} break; case IEEE80211_STA_ASSOC: if (sta->sta_state == IEEE80211_STA_AUTH) {
set_bit(WLAN_STA_ASSOC, &sta->_flags);
sta->assoc_at = ktime_get_boottime_ns(); if (recalc) {
ieee80211_recalc_min_chandef(sta->sdata, -1); if (!sta->sta.support_p2p_ps)
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
}
} elseif (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
ieee80211_vif_dec_num_mcast(sta->sdata);
clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
/* * If we have encryption offload, flush (station) queues * (after ensuring concurrent TX completed) so we won't * transmit anything later unencrypted if/when keys are * also removed, which might otherwise happen depending * on how the hardware offload works.
*/ if (local->ops->set_key) {
synchronize_net(); if (local->ops->flush_sta)
drv_flush_sta(local, sta->sdata, sta); else
ieee80211_flush_queues(local,
sta->sdata, false);
}
/* * NOTE: This assumes at least synchronize_net() was done * after _part1 and before _part2!
*/
/* * There's a potential race in _part1 where we set WLAN_STA_BLOCK_BA * but someone might have just gotten past a check, and not yet into * queuing the work/creating the data/etc. * * Do another round of destruction so that the worker is certainly * canceled before we later free the station. * * Since this is after synchronize_rcu()/synchronize_net() we're now * certain that nobody can actually hold a reference to the STA and * be calling e.g. ieee80211_start_tx_ba_session().
*/
ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA);
/* * Just return a random station if localaddr is NULL * ... first in list.
*/
for_each_sta_info(local, addr, sta, tmp) { if (localaddr &&
!ether_addr_equal(sta->sdata->vif.addr, localaddr)) continue; if (!sta->uploaded) return NULL; return &sta->sta;
}
/* sync with ieee80211_tx_h_unicast_ps_buf */
spin_lock_bh(&sta->ps_lock); /* Send all buffered frames to the station */ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { int count = skb_queue_len(&pending), tmp;
/* now we're no longer in the deliver code */
clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
/* The station might have polled and then woken up before we responded, * so clear these flags now to avoid them sticking around.
*/
clear_sta_flag(sta, WLAN_STA_PSPOLL);
clear_sta_flag(sta, WLAN_STA_UAPSD);
spin_unlock_bh(&sta->ps_lock);
atomic_dec(&ps->num_sta_ps);
local->total_ps_buffered -= buffered;
sta_info_recalc_tim(sta);
ps_dbg(sdata, "STA %pM aid %d sending %d filtered/%d PS frames since STA woke up\n",
sta->sta.addr, sta->sta.aid, filtered, buffered);
if (reason == IEEE80211_FRAME_RELEASE_UAPSD) {
nullfunc->qos_ctrl |=
cpu_to_le16(IEEE80211_QOS_CTL_EOSP); if (more_data)
nullfunc->frame_control |=
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
}
}
info = IEEE80211_SKB_CB(skb);
/* * Tell TX path to send this frame even though the * STA may still remain is PS mode after this frame * exchange. Also set EOSP to indicate this packet * ends the poll/service period.
*/
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER |
IEEE80211_TX_STATUS_EOSP |
IEEE80211_TX_CTL_REQ_TX_STATUS;
staticint find_highest_prio_tid(unsignedlong tids)
{ /* lower 3 TIDs aren't ordered perfectly */ if (tids & 0xF8) return fls(tids) - 1; /* TID 0 is BE just like TID 3 */ if (tids & BIT(0)) return 0; return fls(tids) - 1;
}
/* Indicates if the MORE_DATA bit should be set in the last * frame obtained by ieee80211_sta_ps_get_frames. * Note that driver_release_tids is relevant only if * reason = IEEE80211_FRAME_RELEASE_PSPOLL
*/ staticbool
ieee80211_sta_ps_more_data(struct sta_info *sta, u8 ignored_acs, enum ieee80211_frame_release_type reason, unsignedlong driver_release_tids)
{ int ac;
/* If the driver has data on more than one TID then * certainly there's more data if we release just a * single frame now (from a single TID). This will * only happen for PS-Poll.
*/ if (reason == IEEE80211_FRAME_RELEASE_PSPOLL &&
hweight16(driver_release_tids) > 1) returntrue;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { if (ignored_acs & ieee80211_ac_to_qos_mask[ac]) continue;
if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
!skb_queue_empty(&sta->ps_tx_buf[ac])) returntrue;
}
/* Get response frame(s) and more data bit for the last one. */ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { unsignedlong tids;
if (ignored_acs & ieee80211_ac_to_qos_mask[ac]) continue;
tids = ieee80211_tids_for_ac(ac);
/* if we already have frames from software, then we can't also * release from hardware queues
*/ if (skb_queue_empty(frames)) {
*driver_release_tids |=
sta->driver_buffered_tids & tids;
*driver_release_tids |= sta->txq_buffered_tids & tids;
}
if (!*driver_release_tids) { struct sk_buff *skb;
while (n_frames > 0) {
skb = skb_dequeue(&sta->tx_filtered[ac]); if (!skb) {
skb = skb_dequeue(
&sta->ps_tx_buf[ac]); if (skb)
local->total_ps_buffered--;
} if (!skb) break;
n_frames--;
__skb_queue_tail(frames, skb);
}
}
/* If we have more frames buffered on this AC, then abort the * loop since we can't send more data from other ACs before * the buffered frames from this.
*/ if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
!skb_queue_empty(&sta->ps_tx_buf[ac])) break;
}
}
if (driver_release_tids && reason == IEEE80211_FRAME_RELEASE_PSPOLL)
driver_release_tids =
BIT(find_highest_prio_tid(driver_release_tids));
if (skb_queue_empty(&frames) && !driver_release_tids) { int tid, ac;
/* * For PS-Poll, this can only happen due to a race condition * when we set the TIM bit and the station notices it, but * before it can poll for the frame we expire it. * * For uAPSD, this is said in the standard (11.2.1.5 h): * At each unscheduled SP for a non-AP STA, the AP shall * attempt to transmit at least one MSDU or MMPDU, but no * more than the value specified in the Max SP Length field * in the QoS Capability element from delivery-enabled ACs, * that are destined for the non-AP STA. * * Since we have no other MSDU/MMPDU, transmit a QoS null frame.
*/
/* This will evaluate to 1, 3, 5 or 7. */ for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) if (!(ignored_acs & ieee80211_ac_to_qos_mask[ac])) break;
tid = 7 - 2 * ac;
/* * Tell TX path to send this frame even though the * STA may still remain is PS mode after this frame * exchange.
*/
info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE;
/* * Use MoreData flag to indicate whether there are * more buffered frames for this STA
*/ if (more_data || !skb_queue_empty(&frames))
hdr->frame_control |=
cpu_to_le16(IEEE80211_FCTL_MOREDATA); else
hdr->frame_control &=
cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
if (ieee80211_is_data_qos(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control))
qoshdr = ieee80211_get_qos_ctl(hdr);
tids |= BIT(skb->priority);
__skb_queue_tail(&pending, skb);
/* end service period after last frame or add one */ if (!skb_queue_empty(&frames)) continue;
if (reason != IEEE80211_FRAME_RELEASE_UAPSD) { /* for PS-Poll, there's only one frame */
info->flags |= IEEE80211_TX_STATUS_EOSP |
IEEE80211_TX_CTL_REQ_TX_STATUS; break;
}
/* For uAPSD, things are a bit more complicated. If the * last frame has a QoS header (i.e. is a QoS-data or * QoS-nulldata frame) then just set the EOSP bit there * and be done. * If the frame doesn't have a QoS header (which means * it should be a bufferable MMPDU) then we can't set * the EOSP bit in the QoS header; add a QoS-nulldata * frame to the list to send it after the MMPDU. * * Note that this code is only in the mac80211-release * code path, we assume that the driver will not buffer * anything but QoS-data frames, or if it does, will * create the QoS-nulldata frame by itself if needed. * * Cf. 802.11-2012 10.2.1.10 (c).
*/ if (qoshdr) {
*qoshdr |= IEEE80211_QOS_CTL_EOSP;
info->flags |= IEEE80211_TX_STATUS_EOSP |
IEEE80211_TX_CTL_REQ_TX_STATUS;
} else { /* The standard isn't completely clear on this * as it says the more-data bit should be set * if there are more BUs. The QoS-Null frame * we're about to send isn't buffered yet, we * only create it below, but let's pretend it * was buffered just in case some clients only * expect more-data=0 when eosp=1.
*/
hdr->frame_control |=
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
need_null = true;
num++;
} break;
}
if (need_null)
ieee80211_send_null_response(
sta, find_highest_prio_tid(tids),
reason, false, false);
sta_info_recalc_tim(sta);
} else { int tid;
/* * We need to release a frame that is buffered somewhere in the * driver ... it'll have to handle that. * Note that the driver also has to check the number of frames * on the TIDs we're releasing from - if there are more than * n_frames it has to set the more-data bit (if we didn't ask * it to set it anyway due to other buffered frames); if there * are fewer than n_frames it has to make sure to adjust that * to allow the service period to end properly.
*/
drv_release_buffered_frames(local, sta, driver_release_tids,
n_frames, reason, more_data);
/* * Note that we don't recalculate the TIM bit here as it would * most likely have no effect at all unless the driver told us * that the TID(s) became empty before returning here from the * release function. * Either way, however, when the driver tells us that the TID(s) * became empty or we find that a txq became empty, we'll do the * TIM recalculation.
*/
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { if (!sta->sta.txq[tid] ||
!(driver_release_tids & BIT(tid)) ||
txq_has_queue(sta->sta.txq[tid])) continue;
/* * If all ACs are delivery-enabled then we should reply * from any of them, if only some are enabled we reply * only from the non-enabled ones.
*/ if (ignore_for_response == BIT(IEEE80211_NUM_ACS) - 1)
ignore_for_response = 0;
/* * If we ever grow support for TSPEC this might happen if * the TSPEC update from hostapd comes in between a trigger * frame setting WLAN_STA_UAPSD in the RX path and this * actually getting called.
*/ if (!delivery_enabled) return;
switch (sta->sta.max_sp) { case 1:
n_frames = 2; break; case 2:
n_frames = 4; break; case 3:
n_frames = 6; break; case 0: /* XXX: what is a good value? */
n_frames = 128; break;
}
for (i = 0; i < ARRAY_SIZE(sta->cur.max_tid_amsdu_len); i++)
sta->cur.max_tid_amsdu_len[i] =
min(sta->cur.max_tid_amsdu_len[i],
link_sta->agg.max_tid_amsdu_len[i]);
}
rcu_read_unlock();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.