@@ -573,6 +573,7 @@ struct ieee80211_fils_discovery {
* Note also that this is not used with MLD associations, mac80211 doesn't
* know how to track beacons for all of the links for this.
* @beacon_int: beacon interval
+ * @short_beacon_period: S1G short beacon period
* @assoc_capability: capabilities taken from assoc resp
* @basic_rates: bitmap of basic rates, each bit stands for an
* index into the rate table configured by the driver in
@@ -706,6 +707,7 @@ struct ieee80211_bss_conf {
bool enable_beacon;
u8 dtim_period;
u16 beacon_int;
+ u16 short_beacon_period;
u16 assoc_capability;
u64 sync_tsf;
u32 sync_device_ts;
@@ -1111,6 +1111,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
struct cfg80211_rnr_elems *rnr = NULL;
struct beacon_data *new, *old;
int new_head_len, new_tail_len;
+ int new_short_head_len, new_short_tail_len;
int size, err;
u32 changed = BSS_CHANGED_BEACON;
struct ieee80211_bss_conf *link_conf = link->conf;
@@ -1127,6 +1128,13 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
else
new_head_len = old->head_len;
+ /* Short head is not a mandatory field */
+ new_short_head_len = 0;
+ if (params->short_head)
+ new_short_head_len = params->short_head_len;
+ else if (old && old->short_head)
+ new_short_head_len = old->short_head_len;
+
/* new or old tail? */
if (params->tail || !old)
/* params->tail_len will be zero for !params->tail */
@@ -1134,7 +1142,14 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
else
new_tail_len = old->tail_len;
- size = sizeof(*new) + new_head_len + new_tail_len;
+ if (params->short_tail || !old)
+ /* params->short_tail_len will be zero for !params->short_tail */
+ new_short_tail_len = params->short_tail_len;
+ else
+ new_short_tail_len = old->short_tail_len;
+
+ size = sizeof(*new) + new_head_len + new_tail_len +
+ new_short_head_len + new_short_tail_len;
/* new or old multiple BSSID elements? */
if (params->mbssid_ies) {
@@ -1169,11 +1184,16 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
*/
new->head = ((u8 *) new) + sizeof(*new);
new->tail = new->head + new_head_len;
+ new->short_head = new->tail + new_tail_len;
+ new->short_tail = new->short_head + new_short_head_len;
new->head_len = new_head_len;
new->tail_len = new_tail_len;
+ new->short_head_len = new_short_head_len;
+ new->short_tail_len = new_short_tail_len;
+
/* copy in optional mbssid_ies */
if (mbssid) {
- u8 *pos = new->tail + new->tail_len;
+ u8 *pos = new->short_tail + new->short_tail_len;
new->mbssid_ies = (void *)pos;
pos += struct_size(new->mbssid_ies, elem, mbssid->cnt);
@@ -1205,6 +1225,11 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
else
memcpy(new->head, old->head, new_head_len);
+ if (params->short_head)
+ memcpy(new->short_head, params->short_head, new_short_head_len);
+ else if (old && old->short_head)
+ memcpy(new->short_head, old->short_head, new_short_head_len);
+
/* copy in optional tail */
if (params->tail)
memcpy(new->tail, params->tail, new_tail_len);
@@ -1212,6 +1237,12 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
if (old)
memcpy(new->tail, old->tail, new_tail_len);
+ /* copy in optional short tail */
+ if (params->short_tail)
+ memcpy(new->short_tail, params->short_tail, new_short_tail_len);
+ else if (old)
+ memcpy(new->short_tail, old->short_tail, new_short_tail_len);
+
err = ieee80211_set_probe_resp(sdata, params->probe_resp,
params->probe_resp_len, csa, cca, link);
if (err < 0) {
@@ -1405,6 +1436,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
}
link_conf->dtim_period = params->dtim_period;
+ link_conf->short_beacon_period = params->short_beacon_period;
link_conf->enable_beacon = true;
link_conf->allow_p2p_go_ps = sdata->vif.p2p;
link_conf->twt_responder = params->twt_responder;
@@ -265,10 +265,13 @@ struct ieee80211_color_change_settings {
struct beacon_data {
u8 *head, *tail;
+ u8 *short_head, *short_tail;
int head_len, tail_len;
+ int short_head_len, short_tail_len;
struct ieee80211_meshconf_ie *meshconf;
u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
u8 cntdwn_current_counter;
+ u8 long_beacon_count;
struct cfg80211_mbssid_elems *mbssid_ies;
struct cfg80211_rnr_elems *rnr_ies;
struct rcu_head rcu_head;
@@ -5256,6 +5256,18 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
struct sk_buff *skb = NULL;
u16 csa_off_base = 0;
int mbssid_len;
+ bool is_short = false;
+
+ if (vif->cfg.s1g) {
+ if (beacon->long_beacon_count == 0) {
+ is_short = false;
+ beacon->long_beacon_count =
+ vif->bss_conf.short_beacon_period - 1;
+ } else {
+ is_short = true;
+ beacon->long_beacon_count--;
+ }
+ }
if (beacon->cntdwn_counter_offsets[0]) {
if (!is_template)
@@ -5278,7 +5290,11 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
return NULL;
skb_reserve(skb, local->tx_headroom);
- skb_put_data(skb, beacon->head, beacon->head_len);
+
+ if (is_short)
+ skb_put_data(skb, beacon->short_head, beacon->short_head_len);
+ else
+ skb_put_data(skb, beacon->head, beacon->head_len);
ieee80211_beacon_add_tim(sdata, link, &ap->ps, skb, is_template);
@@ -5296,7 +5312,9 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
csa_off_base = skb->len;
}
- if (beacon->tail)
+ if (beacon->short_tail && is_short)
+ skb_put_data(skb, beacon->short_tail, beacon->short_tail_len);
+ else if (beacon->tail && !is_short)
skb_put_data(skb, beacon->tail, beacon->tail_len);
if (ieee80211_beacon_protect(skb, local, sdata, link) < 0)