^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2012-2013, Marco Porsch <marco.porsch@s2005.tu-chemnitz.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 2012-2013, cozybit Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2021 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "mesh.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "wme.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /* mesh PS management */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * mps_qos_null_get - create pre-addressed QoS Null frame for mesh powersave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * @sta: the station to get the frame for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static struct sk_buff *mps_qos_null_get(struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct ieee80211_local *local = sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct ieee80211_hdr *nullfunc; /* use 4addr header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int size = sizeof(*nullfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) __le16 fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) skb = dev_alloc_skb(local->hw.extra_tx_headroom + size + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) skb_reserve(skb, local->hw.extra_tx_headroom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) nullfunc = skb_put(skb, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ieee80211_fill_mesh_addresses(nullfunc, &fc, sta->sta.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) sdata->vif.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) nullfunc->frame_control = fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) nullfunc->duration_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) nullfunc->seq_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* no address resolution for this frame -> set addr 1 immediately */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) skb_put_zero(skb, 2); /* append QoS control field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ieee80211_mps_set_frame_flags(sdata, sta, nullfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * mps_qos_null_tx - send a QoS Null to indicate link-specific power mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @sta: the station to send to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static void mps_qos_null_tx(struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) skb = mps_qos_null_get(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mps_dbg(sta->sdata, "announcing peer-specific power mode to %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* don't unintentionally start a MPSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u8 *qc = ieee80211_get_qos_ctl((void *) skb->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) qc[0] |= IEEE80211_QOS_CTL_EOSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ieee80211_tx_skb(sta->sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * ieee80211_mps_local_status_update - track status of local link-specific PMs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * @sdata: local mesh subif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * sets the non-peer power mode and triggers the driver PS (re-)configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * Return BSS_CHANGED_BEACON if a beacon update is necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u32 ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct sta_info *sta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) bool peering = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int light_sleep_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int deep_sleep_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u32 changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) enum nl80211_mesh_power_mode nonpeer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (sdata != sta->sdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) switch (sta->mesh->plink_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) case NL80211_PLINK_OPN_SNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) case NL80211_PLINK_OPN_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) case NL80211_PLINK_CNF_RCVD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) peering = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) case NL80211_PLINK_ESTAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (sta->mesh->local_pm == NL80211_MESH_POWER_LIGHT_SLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) light_sleep_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) else if (sta->mesh->local_pm == NL80211_MESH_POWER_DEEP_SLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) deep_sleep_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * Set non-peer mode to active during peering/scanning/authentication
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * (see IEEE802.11-2012 13.14.8.3). The non-peer mesh power mode is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * deep sleep if the local STA is in light or deep sleep towards at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * least one mesh peer (see 13.14.3.1). Otherwise, set it to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * user-configured default value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (peering) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) mps_dbg(sdata, "setting non-peer PM to active for peering\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) nonpeer_pm = NL80211_MESH_POWER_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) } else if (light_sleep_cnt || deep_sleep_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) mps_dbg(sdata, "setting non-peer PM to deep sleep\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) nonpeer_pm = NL80211_MESH_POWER_DEEP_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) mps_dbg(sdata, "setting non-peer PM to user value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) nonpeer_pm = ifmsh->mshcfg.power_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* need update if sleep counts move between 0 and non-zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (ifmsh->nonpeer_pm != nonpeer_pm ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) !ifmsh->ps_peers_light_sleep != !light_sleep_cnt ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) !ifmsh->ps_peers_deep_sleep != !deep_sleep_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) changed = BSS_CHANGED_BEACON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ifmsh->nonpeer_pm = nonpeer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ifmsh->ps_peers_light_sleep = light_sleep_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ifmsh->ps_peers_deep_sleep = deep_sleep_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * ieee80211_mps_set_sta_local_pm - set local PM towards a mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * @sta: mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @pm: the power mode to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Return BSS_CHANGED_BEACON if a beacon update is in order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) u32 ieee80211_mps_set_sta_local_pm(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) enum nl80211_mesh_power_mode pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (sta->mesh->local_pm == pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) mps_dbg(sdata, "local STA operates in mode %d with %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) pm, sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) sta->mesh->local_pm = pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * announce peer-specific power mode transition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * (see IEEE802.11-2012 13.14.3.2 and 13.14.3.3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (sta->mesh->plink_state == NL80211_PLINK_ESTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) mps_qos_null_tx(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return ieee80211_mps_local_status_update(sdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * ieee80211_mps_set_frame_flags - set mesh PS flags in FC (and QoS Control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @sdata: local mesh subif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @sta: mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * @hdr: 802.11 frame header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * see IEEE802.11-2012 8.2.4.1.7 and 8.2.4.5.11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * NOTE: sta must be given when an individually-addressed QoS frame header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * is handled, for group-addressed and management frames it is not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) void ieee80211_mps_set_frame_flags(struct ieee80211_sub_if_data *sdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct ieee80211_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) enum nl80211_mesh_power_mode pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u8 *qc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (WARN_ON(is_unicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ieee80211_is_data_qos(hdr->frame_control) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) !sta))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (is_unicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) ieee80211_is_data_qos(hdr->frame_control) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) sta->mesh->plink_state == NL80211_PLINK_ESTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) pm = sta->mesh->local_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) pm = sdata->u.mesh.nonpeer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (pm == NL80211_MESH_POWER_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_PM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (!ieee80211_is_data_qos(hdr->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) qc = ieee80211_get_qos_ctl(hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if ((is_unicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) pm == NL80211_MESH_POWER_DEEP_SLEEP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) (is_multicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) sdata->u.mesh.ps_peers_deep_sleep > 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) qc[1] |= (IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) qc[1] &= ~(IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * ieee80211_mps_sta_status_update - update buffering status of neighbor STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * @sta: mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * called after change of peering status or non-peer/peer-specific power mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) void ieee80211_mps_sta_status_update(struct sta_info *sta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) enum nl80211_mesh_power_mode pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) bool do_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* For non-assoc STA, prevent buffering or frame transmission */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (sta->sta_state < IEEE80211_STA_ASSOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * use peer-specific power mode if peering is established and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * peer's power mode is known
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (sta->mesh->plink_state == NL80211_PLINK_ESTAB &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) sta->mesh->peer_pm != NL80211_MESH_POWER_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pm = sta->mesh->peer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) pm = sta->mesh->nonpeer_pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) do_buffer = (pm != NL80211_MESH_POWER_ACTIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* clear the MPSP flags for non-peers or active STA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (sta->mesh->plink_state != NL80211_PLINK_ESTAB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) } else if (!do_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Don't let the same PS state be set twice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (do_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) set_sta_flag(sta, WLAN_STA_PS_STA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) atomic_inc(&sta->sdata->u.mesh.ps.num_sta_ps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) mps_dbg(sta->sdata, "start PS buffering frames towards %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ieee80211_sta_ps_deliver_wakeup(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static void mps_set_sta_peer_pm(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct ieee80211_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) enum nl80211_mesh_power_mode pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u8 *qc = ieee80211_get_qos_ctl(hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * Test Power Management field of frame control (PW) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * mesh power save level subfield of QoS control field (PSL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * | PM | PSL| Mesh PM |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * +----+----+---------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * | 0 |Rsrv| Active |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * | 1 | 0 | Light |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * | 1 | 1 | Deep |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (ieee80211_has_pm(hdr->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (qc[1] & (IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) pm = NL80211_MESH_POWER_DEEP_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) pm = NL80211_MESH_POWER_LIGHT_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) pm = NL80211_MESH_POWER_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (sta->mesh->peer_pm == pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) mps_dbg(sta->sdata, "STA %pM enters mode %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) sta->sta.addr, pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) sta->mesh->peer_pm = pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ieee80211_mps_sta_status_update(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static void mps_set_sta_nonpeer_pm(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct ieee80211_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) enum nl80211_mesh_power_mode pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (ieee80211_has_pm(hdr->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) pm = NL80211_MESH_POWER_DEEP_SLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) pm = NL80211_MESH_POWER_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (sta->mesh->nonpeer_pm == pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) mps_dbg(sta->sdata, "STA %pM sets non-peer mode to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) sta->sta.addr, pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) sta->mesh->nonpeer_pm = pm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ieee80211_mps_sta_status_update(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * ieee80211_mps_rx_h_sta_process - frame receive handler for mesh powersave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * @sta: STA info that transmitted the frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * @hdr: IEEE 802.11 (QoS) Header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) void ieee80211_mps_rx_h_sta_process(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct ieee80211_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (is_unicast_ether_addr(hdr->addr1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ieee80211_is_data_qos(hdr->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * individually addressed QoS Data/Null frames contain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * peer link-specific PS mode towards the local STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) mps_set_sta_peer_pm(sta, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /* check for mesh Peer Service Period trigger frames */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) ieee80211_mpsp_trigger_process(ieee80211_get_qos_ctl(hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) sta, false, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * can only determine non-peer PS mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * (see IEEE802.11-2012 8.2.4.1.7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) mps_set_sta_nonpeer_pm(sta, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* mesh PS frame release */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static void mpsp_trigger_send(struct sta_info *sta, bool rspi, bool eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct ieee80211_hdr *nullfunc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct ieee80211_tx_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) u8 *qc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) skb = mps_qos_null_get(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) nullfunc = (struct ieee80211_hdr *) skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (!eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) nullfunc->frame_control |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) cpu_to_le16(IEEE80211_FCTL_MOREDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * | RSPI | EOSP | MPSP triggering |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * +------+------+--------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * | 0 | 0 | local STA is owner |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * | 0 | 1 | no MPSP (MPSP end) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * | 1 | 0 | both STA are owner |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * | 1 | 1 | peer STA is owner | see IEEE802.11-2012 13.14.9.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) qc = ieee80211_get_qos_ctl(nullfunc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (rspi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) qc[1] |= (IEEE80211_QOS_CTL_RSPI >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) qc[0] |= IEEE80211_QOS_CTL_EOSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) info = IEEE80211_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) IEEE80211_TX_CTL_REQ_TX_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) mps_dbg(sdata, "sending MPSP trigger%s%s to %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) rspi ? " RSPI" : "", eosp ? " EOSP" : "", sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) ieee80211_tx_skb(sdata, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * mpsp_qos_null_append - append QoS Null frame to MPSP skb queue if needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * @sta: the station to handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * @frames: the frame list to append to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * To properly end a mesh MPSP the last transmitted frame has to set the EOSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * flag in the QoS Control field. In case the current tailing frame is not a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * QoS Data frame, append a QoS Null to carry the flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static void mpsp_qos_null_append(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct sk_buff_head *frames)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct ieee80211_sub_if_data *sdata = sta->sdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct sk_buff *new_skb, *skb = skb_peek_tail(frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct ieee80211_tx_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (ieee80211_is_data_qos(hdr->frame_control))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) new_skb = mps_qos_null_get(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (!new_skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) mps_dbg(sdata, "appending QoS Null in MPSP towards %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * This frame has to be transmitted last. Assign lowest priority to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * make sure it cannot pass other frames when releasing multiple ACs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) new_skb->priority = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) skb_set_queue_mapping(new_skb, IEEE80211_AC_BK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ieee80211_set_qos_hdr(sdata, new_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) info = IEEE80211_SKB_CB(new_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) info->control.vif = &sdata->vif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) __skb_queue_tail(frames, new_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * mps_frame_deliver - transmit frames during mesh powersave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * @sta: STA info to transmit to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * @n_frames: number of frames to transmit. -1 for all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static void mps_frame_deliver(struct sta_info *sta, int n_frames)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct ieee80211_local *local = sta->sdata->local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) int ac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct sk_buff_head frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) bool more_data = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) skb_queue_head_init(&frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* collect frame(s) from buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) while (n_frames != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) skb = skb_dequeue(&sta->tx_filtered[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) skb = skb_dequeue(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) &sta->ps_tx_buf[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) local->total_ps_buffered--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) n_frames--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) __skb_queue_tail(&frames, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) !skb_queue_empty(&sta->ps_tx_buf[ac]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) more_data = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* nothing to send? -> EOSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (skb_queue_empty(&frames)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) mpsp_trigger_send(sta, false, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /* in a MPSP make sure the last skb is a QoS Data frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (test_sta_flag(sta, WLAN_STA_MPSP_OWNER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) mpsp_qos_null_append(sta, &frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) mps_dbg(sta->sdata, "sending %d frames to PS STA %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) skb_queue_len(&frames), sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* prepare collected frames for transmission */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) skb_queue_walk(&frames, skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct ieee80211_hdr *hdr = (void *) skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * Tell TX path to send this frame even though the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * STA may still remain is PS mode after this frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * exchange.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (more_data || !skb_queue_is_last(&frames, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) hdr->frame_control |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) cpu_to_le16(IEEE80211_FCTL_MOREDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) hdr->frame_control &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (skb_queue_is_last(&frames, skb) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) ieee80211_is_data_qos(hdr->frame_control)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) u8 *qoshdr = ieee80211_get_qos_ctl(hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* MPSP trigger frame ends service period */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) *qoshdr |= IEEE80211_QOS_CTL_EOSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) ieee80211_add_pending_skbs(local, &frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) sta_info_recalc_tim(sta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * ieee80211_mpsp_trigger_process - track status of mesh Peer Service Periods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * @qc: QoS Control field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * @sta: peer to start a MPSP with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * @tx: frame was transmitted by the local STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * @acked: frame has been transmitted successfully
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * NOTE: active mode STA may only serve as MPSP owner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) bool tx, bool acked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) u8 rspi = qc[1] & (IEEE80211_QOS_CTL_RSPI >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) u8 eosp = qc[0] & IEEE80211_QOS_CTL_EOSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (rspi && acked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) set_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) clear_sta_flag(sta, WLAN_STA_MPSP_OWNER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) else if (acked &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) test_sta_flag(sta, WLAN_STA_PS_STA) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) !test_and_set_sta_flag(sta, WLAN_STA_MPSP_OWNER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) mps_frame_deliver(sta, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (eosp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) else if (sta->mesh->local_pm != NL80211_MESH_POWER_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) set_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (rspi && !test_and_set_sta_flag(sta, WLAN_STA_MPSP_OWNER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) mps_frame_deliver(sta, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * ieee80211_mps_frame_release - release frames buffered due to mesh power save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * @sta: mesh STA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * @elems: IEs of beacon or probe response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * For peers if we have individually-addressed frames buffered or the peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * indicates buffered frames, send a corresponding MPSP trigger frame. Since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * we do not evaluate the awake window duration, QoS Nulls are used as MPSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * trigger frames. If the neighbour STA is not a peer, only send single frames.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) void ieee80211_mps_frame_release(struct sta_info *sta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct ieee802_11_elems *elems)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) int ac, buffer_local = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) bool has_buffered = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (sta->mesh->plink_state == NL80211_PLINK_ESTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) sta->mesh->aid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (has_buffered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) mps_dbg(sta->sdata, "%pM indicates buffered frames\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) sta->sta.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* only transmit to PS STA with announced, non-zero awake window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) (!elems->awake_window || !get_unaligned_le16(elems->awake_window)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (!test_sta_flag(sta, WLAN_STA_MPSP_OWNER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) skb_queue_len(&sta->tx_filtered[ac]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (!has_buffered && !buffer_local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (sta->mesh->plink_state == NL80211_PLINK_ESTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) mpsp_trigger_send(sta, has_buffered, !buffer_local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) mps_frame_deliver(sta, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }