diff options
Diffstat (limited to 'package/kernel/mac80211/patches/subsys/324-mac80211-MBSSID-beacon-handling-in-AP-mode.patch')
-rw-r--r-- | package/kernel/mac80211/patches/subsys/324-mac80211-MBSSID-beacon-handling-in-AP-mode.patch | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/subsys/324-mac80211-MBSSID-beacon-handling-in-AP-mode.patch b/package/kernel/mac80211/patches/subsys/324-mac80211-MBSSID-beacon-handling-in-AP-mode.patch new file mode 100644 index 0000000000..c76f4ae468 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/324-mac80211-MBSSID-beacon-handling-in-AP-mode.patch @@ -0,0 +1,326 @@ +From: Lorenzo Bianconi <lorenzo@kernel.org> +Date: Thu, 24 Feb 2022 12:54:58 +0100 +Subject: [PATCH] mac80211: MBSSID beacon handling in AP mode + +Add new fields in struct beacon_data to store all MBSSID elements. +Generate a beacon template which includes all MBSSID elements. +Move CSA offset to reflect the MBSSID element length. + +Co-developed-by: Aloka Dixit <alokad@codeaurora.org> +Signed-off-by: Aloka Dixit <alokad@codeaurora.org> +Co-developed-by: John Crispin <john@phrozen.org> +Signed-off-by: John Crispin <john@phrozen.org> +Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> +Tested-by: Money Wang <money.wang@mediatek.com> +Link: https://lore.kernel.org/r/5322db3c303f431adaf191ab31c45e151dde5465.1645702516.git.lorenzo@kernel.org +[small cleanups] +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +--- + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -4938,12 +4938,14 @@ void ieee80211_report_low_ack(struct iee + * @cntdwn_counter_offs: array of IEEE80211_MAX_CNTDWN_COUNTERS_NUM offsets + * to countdown counters. This array can contain zero values which + * should be ignored. ++ * @mbssid_off: position of the multiple bssid element + */ + struct ieee80211_mutable_offsets { + u16 tim_offset; + u16 tim_length; + + u16 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; ++ u16 mbssid_off; + }; + + /** +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -989,11 +989,29 @@ static int ieee80211_set_ftm_responder_p + return 0; + } + ++static int ++ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst, ++ struct cfg80211_mbssid_elems *src) ++{ ++ int i, offset = 0; ++ ++ for (i = 0; i < src->cnt; i++) { ++ memcpy(pos + offset, src->elem[i].data, src->elem[i].len); ++ dst->elem[i].len = src->elem[i].len; ++ dst->elem[i].data = pos + offset; ++ offset += dst->elem[i].len; ++ } ++ dst->cnt = src->cnt; ++ ++ return offset; ++} ++ + static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, + struct cfg80211_beacon_data *params, + const struct ieee80211_csa_settings *csa, + const struct ieee80211_color_change_settings *cca) + { ++ struct cfg80211_mbssid_elems *mbssid = NULL; + struct beacon_data *new, *old; + int new_head_len, new_tail_len; + int size, err; +@@ -1021,6 +1039,17 @@ static int ieee80211_assign_beacon(struc + + size = sizeof(*new) + new_head_len + new_tail_len; + ++ /* new or old multiple BSSID elements? */ ++ if (params->mbssid_ies) { ++ mbssid = params->mbssid_ies; ++ size += struct_size(new->mbssid_ies, elem, mbssid->cnt); ++ size += ieee80211_get_mbssid_beacon_len(mbssid); ++ } else if (old && old->mbssid_ies) { ++ mbssid = old->mbssid_ies; ++ size += struct_size(new->mbssid_ies, elem, mbssid->cnt); ++ size += ieee80211_get_mbssid_beacon_len(mbssid); ++ } ++ + new = kzalloc(size, GFP_KERNEL); + if (!new) + return -ENOMEM; +@@ -1029,12 +1058,20 @@ static int ieee80211_assign_beacon(struc + + /* + * pointers go into the block we allocated, +- * memory is | beacon_data | head | tail | ++ * memory is | beacon_data | head | tail | mbssid_ies + */ + new->head = ((u8 *) new) + sizeof(*new); + new->tail = new->head + new_head_len; + new->head_len = new_head_len; + new->tail_len = new_tail_len; ++ /* copy in optional mbssid_ies */ ++ if (mbssid) { ++ u8 *pos = new->tail + new->tail_len; ++ ++ new->mbssid_ies = (void *)pos; ++ pos += struct_size(new->mbssid_ies, elem, mbssid->cnt); ++ ieee80211_copy_mbssid_beacon(pos, new->mbssid_ies, mbssid); ++ } + + if (csa) { + new->cntdwn_current_counter = csa->count; +@@ -1329,8 +1366,11 @@ static int ieee80211_stop_ap(struct wiph + + mutex_unlock(&local->mtx); + +- kfree(sdata->u.ap.next_beacon); +- sdata->u.ap.next_beacon = NULL; ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + + /* turn off carrier for this interface and dependent VLANs */ + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) +@@ -3126,12 +3166,24 @@ cfg80211_beacon_dup(struct cfg80211_beac + + len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len + + beacon->proberesp_ies_len + beacon->assocresp_ies_len + +- beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len; ++ beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len + ++ ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); + + new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL); + if (!new_beacon) + return NULL; + ++ if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) { ++ new_beacon->mbssid_ies = ++ kzalloc(struct_size(new_beacon->mbssid_ies, ++ elem, beacon->mbssid_ies->cnt), ++ GFP_KERNEL); ++ if (!new_beacon->mbssid_ies) { ++ kfree(new_beacon); ++ return NULL; ++ } ++ } ++ + pos = (u8 *)(new_beacon + 1); + if (beacon->head_len) { + new_beacon->head_len = beacon->head_len; +@@ -3169,6 +3221,10 @@ cfg80211_beacon_dup(struct cfg80211_beac + memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); + pos += beacon->probe_resp_len; + } ++ if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) ++ pos += ieee80211_copy_mbssid_beacon(pos, ++ new_beacon->mbssid_ies, ++ beacon->mbssid_ies); + + /* might copy -1, meaning no changes requested */ + new_beacon->ftm_responder = beacon->ftm_responder; +@@ -3206,8 +3262,11 @@ static int ieee80211_set_after_csa_beaco + case NL80211_IFTYPE_AP: + err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, + NULL, NULL); +- kfree(sdata->u.ap.next_beacon); +- sdata->u.ap.next_beacon = NULL; ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + + if (err < 0) + return err; +@@ -3362,8 +3421,12 @@ static int ieee80211_set_csa_beacon(stru + if ((params->n_counter_offsets_beacon > + IEEE80211_MAX_CNTDWN_COUNTERS_NUM) || + (params->n_counter_offsets_presp > +- IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) ++ IEEE80211_MAX_CNTDWN_COUNTERS_NUM)) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; + return -EINVAL; ++ } + + csa.counter_offsets_beacon = params->counter_offsets_beacon; + csa.counter_offsets_presp = params->counter_offsets_presp; +@@ -3373,7 +3436,9 @@ static int ieee80211_set_csa_beacon(stru + + err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa, NULL); + if (err < 0) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); + kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; + return err; + } + *changed |= err; +@@ -3463,8 +3528,11 @@ static int ieee80211_set_csa_beacon(stru + static void ieee80211_color_change_abort(struct ieee80211_sub_if_data *sdata) + { + sdata->vif.color_change_active = false; +- kfree(sdata->u.ap.next_beacon); +- sdata->u.ap.next_beacon = NULL; ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + + cfg80211_color_change_aborted_notify(sdata->dev); + } +@@ -4202,8 +4270,11 @@ ieee80211_set_after_color_change_beacon( + + ret = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, + NULL, NULL); +- kfree(sdata->u.ap.next_beacon); +- sdata->u.ap.next_beacon = NULL; ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + + if (ret < 0) + return ret; +@@ -4246,7 +4317,11 @@ ieee80211_set_color_change_beacon(struct + err = ieee80211_assign_beacon(sdata, ¶ms->beacon_color_change, + NULL, &color_change); + if (err < 0) { +- kfree(sdata->u.ap.next_beacon); ++ if (sdata->u.ap.next_beacon) { ++ kfree(sdata->u.ap.next_beacon->mbssid_ies); ++ kfree(sdata->u.ap.next_beacon); ++ sdata->u.ap.next_beacon = NULL; ++ } + return err; + } + *changed |= err; +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -261,6 +261,7 @@ struct beacon_data { + struct ieee80211_meshconf_ie *meshconf; + u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM]; + u8 cntdwn_current_counter; ++ struct cfg80211_mbssid_elems *mbssid_ies; + struct rcu_head rcu_head; + }; + +@@ -1063,6 +1064,20 @@ ieee80211_vif_get_shift(struct ieee80211 + return shift; + } + ++static inline int ++ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems) ++{ ++ int i, len = 0; ++ ++ if (!elems) ++ return 0; ++ ++ for (i = 0; i < elems->cnt; i++) ++ len += elems->elem[i].len; ++ ++ return len; ++} ++ + enum { + IEEE80211_RX_MSG = 1, + IEEE80211_TX_STATUS_MSG = 2, +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -5041,6 +5041,19 @@ ieee80211_beacon_get_finish(struct ieee8 + IEEE80211_TX_CTL_FIRST_FRAGMENT; + } + ++static void ++ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon) ++{ ++ int i; ++ ++ if (!beacon->mbssid_ies) ++ return; ++ ++ for (i = 0; i < beacon->mbssid_ies->cnt; i++) ++ skb_put_data(skb, beacon->mbssid_ies->elem[i].data, ++ beacon->mbssid_ies->elem[i].len); ++} ++ + static struct sk_buff * + ieee80211_beacon_get_ap(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, +@@ -5054,6 +5067,7 @@ ieee80211_beacon_get_ap(struct ieee80211 + struct ieee80211_if_ap *ap = &sdata->u.ap; + struct sk_buff *skb = NULL; + u16 csa_off_base = 0; ++ int mbssid_len; + + if (beacon->cntdwn_counter_offsets[0]) { + if (!is_template) +@@ -5063,11 +5077,12 @@ ieee80211_beacon_get_ap(struct ieee80211 + } + + /* headroom, head length, +- * tail length and maximum TIM length ++ * tail length, maximum TIM length and multiple BSSID length + */ ++ mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies); + skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + + beacon->tail_len + 256 + +- local->hw.extra_beacon_tailroom); ++ local->hw.extra_beacon_tailroom + mbssid_len); + if (!skb) + return NULL; + +@@ -5081,6 +5096,11 @@ ieee80211_beacon_get_ap(struct ieee80211 + offs->tim_length = skb->len - beacon->head_len; + offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; + ++ if (mbssid_len) { ++ ieee80211_beacon_add_mbssid(skb, beacon); ++ offs->mbssid_off = skb->len - mbssid_len; ++ } ++ + /* for AP the csa offsets are from tail */ + csa_off_base = skb->len; + } |