From 9143cf5fc9e06af4a9bcf07f0009666ccf66961f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 20 Mar 2015 16:24:14 +0000 Subject: [PATCH] mac80211: merge a few performance enhancements Signed-off-by: Felix Fietkau SVN-Revision: 44910 --- ...ook-up-stations-for-multicast-addres.patch | 21 ++ ...ac80211-remove-drop_unencrypted-code.patch | 130 +++++++++ ...-t-look-up-destination-station-twice.patch | 71 +++++ ...addr-VLAN-frames-earlier-if-not-conn.patch | 27 ++ ...-mesh-avoid-pointless-station-lookup.patch | 33 +++ ...oid-duplicate-TX-path-station-lookup.patch | 267 ++++++++++++++++++ .../522-mac80211_configure_antenna_gain.patch | 2 +- 7 files changed, 550 insertions(+), 1 deletion(-) create mode 100644 package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch create mode 100644 package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch create mode 100644 package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch create mode 100644 package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch create mode 100644 package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch create mode 100644 package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch diff --git a/package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch b/package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch new file mode 100644 index 0000000000..7a039d627a --- /dev/null +++ b/package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch @@ -0,0 +1,21 @@ +From: Johannes Berg +Date: Tue, 24 Feb 2015 00:28:18 +0100 +Subject: [PATCH] mac80211: don't look up stations for multicast addresses + +Since multicast addresses don't exist as stations, don't attempt +to look them up in the hashtable on TX. + +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1162,7 +1162,7 @@ ieee80211_tx_prepare(struct ieee80211_su + tx->sdata->control_port_protocol == tx->skb->protocol) { + tx->sta = sta_info_get_bss(sdata, hdr->addr1); + } +- if (!tx->sta) ++ if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) + tx->sta = sta_info_get(sdata, hdr->addr1); + + if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && diff --git a/package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch b/package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch new file mode 100644 index 0000000000..d6bc082f35 --- /dev/null +++ b/package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch @@ -0,0 +1,130 @@ +From: Johannes Berg +Date: Fri, 20 Mar 2015 11:41:58 +0100 +Subject: [PATCH] mac80211: remove drop_unencrypted code + +This mechanism was historic, and only ever used by IBSS, which +also doesn't need to have it as it properly manages station's +802.1X PAE state (or, with WEP, always has a key.) + +Remove the mechanism to clean up the code. + +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/debugfs.c ++++ b/net/mac80211/debugfs.c +@@ -274,8 +274,6 @@ void debugfs_hw_add(struct ieee80211_loc + #ifdef CPTCFG_MAC80211_DEBUG_COUNTERS + DEBUGFS_STATS_ADD(tx_handlers_drop, local->tx_handlers_drop); + DEBUGFS_STATS_ADD(tx_handlers_queued, local->tx_handlers_queued); +- DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted, +- local->tx_handlers_drop_unencrypted); + DEBUGFS_STATS_ADD(tx_handlers_drop_fragment, + local->tx_handlers_drop_fragment); + DEBUGFS_STATS_ADD(tx_handlers_drop_wep, +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -177,7 +177,6 @@ static ssize_t ieee80211_if_write_##name + IEEE80211_IF_FILE_R(name) + + /* common attributes */ +-IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); + IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], + HEX); + IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], +@@ -562,7 +561,6 @@ IEEE80211_IF_FILE(dot11MeshAwakeWindowDu + + static void add_common_files(struct ieee80211_sub_if_data *sdata) + { +- DEBUGFS_ADD(drop_unencrypted); + DEBUGFS_ADD(rc_rateidx_mask_2ghz); + DEBUGFS_ADD(rc_rateidx_mask_5ghz); + DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -249,8 +249,6 @@ static void __ieee80211_sta_join_ibss(st + if (presp) + kfree_rcu(presp, rcu_head); + +- sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; +- + /* make a copy of the chandef, it could be modified below. */ + chandef = *req_chandef; + chan = chandef.chan; +@@ -1289,8 +1287,6 @@ static void ieee80211_sta_create_ibss(st + + if (ifibss->privacy) + capability |= WLAN_CAPABILITY_PRIVACY; +- else +- sdata->drop_unencrypted = 0; + + __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, + &ifibss->chandef, ifibss->basic_rates, +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -842,8 +842,6 @@ struct ieee80211_sub_if_data { + + unsigned long state; + +- int drop_unencrypted; +- + char name[IFNAMSIZ]; + + /* Fragment table for host-based reassembly */ +@@ -1289,7 +1287,6 @@ struct ieee80211_local { + /* TX/RX handler statistics */ + unsigned int tx_handlers_drop; + unsigned int tx_handlers_queued; +- unsigned int tx_handlers_drop_unencrypted; + unsigned int tx_handlers_drop_fragment; + unsigned int tx_handlers_drop_wep; + unsigned int tx_handlers_drop_not_assoc; +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -1535,7 +1535,6 @@ int ieee80211_if_change_type(struct ieee + } + + /* reset some values that shouldn't be kept across type changes */ +- sdata->drop_unencrypted = 0; + if (type == NL80211_IFTYPE_STATION) + sdata->u.mgd.use_4addr = false; + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1897,8 +1897,7 @@ static int ieee80211_drop_unencrypted(st + /* Drop unencrypted frames if key is set. */ + if (unlikely(!ieee80211_has_protected(fc) && + !ieee80211_is_nullfunc(fc) && +- ieee80211_is_data(fc) && +- (rx->key || rx->sdata->drop_unencrypted))) ++ ieee80211_is_data(fc) && rx->key)) + return -EACCES; + + return 0; +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -594,23 +594,8 @@ ieee80211_tx_h_select_key(struct ieee802 + else if (!is_multicast_ether_addr(hdr->addr1) && + (key = rcu_dereference(tx->sdata->default_unicast_key))) + tx->key = key; +- else if (info->flags & IEEE80211_TX_CTL_INJECTED) +- tx->key = NULL; +- else if (!tx->sdata->drop_unencrypted) +- tx->key = NULL; +- else if (tx->skb->protocol == tx->sdata->control_port_protocol) +- tx->key = NULL; +- else if (ieee80211_is_robust_mgmt_frame(tx->skb) && +- !(ieee80211_is_action(hdr->frame_control) && +- tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) +- tx->key = NULL; +- else if (ieee80211_is_mgmt(hdr->frame_control) && +- !ieee80211_is_robust_mgmt_frame(tx->skb)) ++ else + tx->key = NULL; +- else { +- I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); +- return TX_DROP; +- } + + if (tx->key) { + bool skip_hw = false; diff --git a/package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch b/package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch new file mode 100644 index 0000000000..6109bc2e87 --- /dev/null +++ b/package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch @@ -0,0 +1,71 @@ +From: Johannes Berg +Date: Fri, 20 Mar 2015 16:24:21 +0100 +Subject: [PATCH] mac80211: don't look up destination station twice + +There's no need to look up the destination station twice while +building the 802.11 header for a given frame if the frame will +actually be transmitted to the station we initially looked up. + +This happens for 4-addr VLAN interfaces and TDLS connections, which +both directly send the frame to the station they looked up, though +in the case of TDLS some station conditions need to be checked. + +To avoid that, add a variable indicating that we've looked up the +station that the frame is going to be transmitted to, and avoid the +lookup/flag checking if it already has been done. + +In the TDLS case, also move the authorized/wme_sta flag assignment +to the correct place, i.e. only when that station is really used. +Before this change, the new lookup should always have succeeded so +that the potentially erroneous data would be overwritten. + +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1895,6 +1895,7 @@ static struct sk_buff *ieee80211_build_h + bool wme_sta = false, authorized = false, tdls_auth = false; + bool tdls_peer = false, tdls_setup_frame = false; + bool multicast; ++ bool have_station = false; + u16 info_id = 0; + struct ieee80211_chanctx_conf *chanctx_conf; + struct ieee80211_sub_if_data *ap_sdata; +@@ -1919,6 +1920,7 @@ static struct sk_buff *ieee80211_build_h + hdrlen = 30; + authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); + wme_sta = sta->sta.wme; ++ have_station = true; + } + ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, + u.ap); +@@ -2035,9 +2037,6 @@ static struct sk_buff *ieee80211_build_h + if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { + sta = sta_info_get(sdata, skb->data); + if (sta) { +- authorized = test_sta_flag(sta, +- WLAN_STA_AUTHORIZED); +- wme_sta = sta->sta.wme; + tdls_peer = test_sta_flag(sta, + WLAN_STA_TDLS_PEER); + tdls_auth = test_sta_flag(sta, +@@ -2069,6 +2068,9 @@ static struct sk_buff *ieee80211_build_h + memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); + memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN); + hdrlen = 24; ++ have_station = true; ++ authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); ++ wme_sta = sta->sta.wme; + } else if (sdata->u.mgd.use_4addr && + cpu_to_be16(ethertype) != sdata->control_port_protocol) { + fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | +@@ -2131,7 +2133,7 @@ static struct sk_buff *ieee80211_build_h + * in AP mode) + */ + multicast = is_multicast_ether_addr(hdr.addr1); +- if (!multicast) { ++ if (!multicast && !have_station) { + sta = sta_info_get(sdata, hdr.addr1); + if (sta) { + authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); diff --git a/package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch b/package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch new file mode 100644 index 0000000000..f493f654f8 --- /dev/null +++ b/package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch @@ -0,0 +1,27 @@ +From: Johannes Berg +Date: Fri, 20 Mar 2015 16:24:22 +0100 +Subject: [PATCH] mac80211: drop 4-addr VLAN frames earlier if not + connected + +If there's no station on the 4-addr VLAN interface, then frames +cannot be transmitted. Drop such frames earlier, before setting +up all the information for them. + +We should keep the old check though since that code might be used +for other internally-generated frames. + +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1921,6 +1921,9 @@ static struct sk_buff *ieee80211_build_h + authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); + wme_sta = sta->sta.wme; + have_station = true; ++ } else if (sdata->wdev.use_4addr) { ++ ret = -ENOLINK; ++ goto free; + } + ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, + u.ap); diff --git a/package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch b/package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch new file mode 100644 index 0000000000..c476dd463c --- /dev/null +++ b/package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch @@ -0,0 +1,33 @@ +From: Johannes Berg +Date: Fri, 20 Mar 2015 16:24:23 +0100 +Subject: [PATCH] mac80211: mesh: avoid pointless station lookup + +In ieee80211_build_hdr(), the station is looked up to build the +header correctly (QoS field) and to check for authorization. For +mesh, authorization isn't checked here, and QoS capability is +mandatory, so the station lookup can be avoided. + +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -2131,12 +2131,14 @@ static struct sk_buff *ieee80211_build_h + } + + /* +- * There's no need to try to look up the destination +- * if it is a multicast address (which can only happen +- * in AP mode) ++ * There's no need to try to look up the destination station ++ * if it is a multicast address. In mesh, there's no need to ++ * look up the station at all as it always must be QoS capable ++ * and mesh mode checks authorization later. + */ + multicast = is_multicast_ether_addr(hdr.addr1); +- if (!multicast && !have_station) { ++ if (!multicast && !have_station && ++ !ieee80211_vif_is_mesh(&sdata->vif)) { + sta = sta_info_get(sdata, hdr.addr1); + if (sta) { + authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); diff --git a/package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch b/package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch new file mode 100644 index 0000000000..31ed830c2a --- /dev/null +++ b/package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch @@ -0,0 +1,267 @@ +From: Johannes Berg +Date: Fri, 20 Mar 2015 14:18:27 +0100 +Subject: [PATCH] mac80211: avoid duplicate TX path station lookup + +Instead of looking up the destination station twice in the TX path +(first to build the header, and then for control processing), save +it when building the header and use it later in the TX path. + +To avoid having to look up the station in the many callers, allow +those to pass %NULL which keeps the existing lookup. + +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3565,7 +3565,7 @@ static int ieee80211_probe_client(struct + nullfunc->qos_ctrl = cpu_to_le16(7); + + local_bh_disable(); +- ieee80211_xmit(sdata, skb); ++ ieee80211_xmit(sdata, sta, skb); + local_bh_enable(); + rcu_read_unlock(); + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1775,7 +1775,8 @@ void mac80211_ev_michael_mic_failure(str + gfp_t gfp); + void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, + bool bss_notify); +-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); ++void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb); + + void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, int tid, +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -1279,7 +1279,7 @@ static void ieee80211_send_null_response + } + + info->band = chanctx_conf->def.chan->band; +- ieee80211_xmit(sdata, skb); ++ ieee80211_xmit(sdata, sta, skb); + rcu_read_unlock(); + } + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1111,11 +1111,13 @@ static bool ieee80211_tx_prep_agg(struct + + /* + * initialises @tx ++ * pass %NULL for the station if unknown, a valid pointer if known ++ * or an ERR_PTR() if the station is known not to exist + */ + static ieee80211_tx_result + ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, + struct ieee80211_tx_data *tx, +- struct sk_buff *skb) ++ struct sta_info *sta, struct sk_buff *skb) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_hdr *hdr; +@@ -1138,17 +1140,22 @@ ieee80211_tx_prepare(struct ieee80211_su + + hdr = (struct ieee80211_hdr *) skb->data; + +- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +- tx->sta = rcu_dereference(sdata->u.vlan.sta); +- if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) +- return TX_DROP; +- } else if (info->flags & (IEEE80211_TX_CTL_INJECTED | +- IEEE80211_TX_INTFL_NL80211_FRAME_TX) || +- tx->sdata->control_port_protocol == tx->skb->protocol) { +- tx->sta = sta_info_get_bss(sdata, hdr->addr1); ++ if (likely(sta)) { ++ if (!IS_ERR(sta)) ++ tx->sta = sta; ++ } else { ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { ++ tx->sta = rcu_dereference(sdata->u.vlan.sta); ++ if (!tx->sta && sdata->wdev.use_4addr) ++ return TX_DROP; ++ } else if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX | ++ IEEE80211_TX_CTL_INJECTED) || ++ tx->sdata->control_port_protocol == tx->skb->protocol) { ++ tx->sta = sta_info_get_bss(sdata, hdr->addr1); ++ } ++ if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) ++ tx->sta = sta_info_get(sdata, hdr->addr1); + } +- if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) +- tx->sta = sta_info_get(sdata, hdr->addr1); + + if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && + !ieee80211_is_qos_nullfunc(hdr->frame_control) && +@@ -1486,7 +1493,7 @@ bool ieee80211_tx_prepare_skb(struct iee + struct ieee80211_tx_data tx; + struct sk_buff *skb2; + +- if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP) ++ if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) + return false; + + info->band = band; +@@ -1519,7 +1526,8 @@ EXPORT_SYMBOL(ieee80211_tx_prepare_skb); + * Returns false if the frame couldn't be transmitted but was queued instead. + */ + static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, +- struct sk_buff *skb, bool txpending) ++ struct sta_info *sta, struct sk_buff *skb, ++ bool txpending) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_data tx; +@@ -1535,7 +1543,7 @@ static bool ieee80211_tx(struct ieee8021 + + /* initialises tx */ + led_len = skb->len; +- res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); ++ res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb); + + if (unlikely(res_prepare == TX_DROP)) { + ieee80211_free_txskb(&local->hw, skb); +@@ -1591,7 +1599,8 @@ static int ieee80211_skb_resize(struct i + return 0; + } + +-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) ++void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, struct sk_buff *skb) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +@@ -1626,7 +1635,7 @@ void ieee80211_xmit(struct ieee80211_sub + } + + ieee80211_set_qos_hdr(sdata, skb); +- ieee80211_tx(sdata, skb, false); ++ ieee80211_tx(sdata, sta, skb, false); + } + + static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) +@@ -1847,7 +1856,7 @@ netdev_tx_t ieee80211_monitor_start_xmit + goto fail_rcu; + + info->band = chandef->chan->band; +- ieee80211_xmit(sdata, skb); ++ ieee80211_xmit(sdata, NULL, skb); + rcu_read_unlock(); + + return NETDEV_TX_OK; +@@ -1878,7 +1887,8 @@ fail: + * Returns: the (possibly reallocated) skb or an ERR_PTR() code + */ + static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, +- struct sk_buff *skb, u32 info_flags) ++ struct sk_buff *skb, u32 info_flags, ++ struct sta_info **sta_out) + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_info *info; +@@ -1921,6 +1931,7 @@ static struct sk_buff *ieee80211_build_h + authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); + wme_sta = sta->sta.wme; + have_station = true; ++ *sta_out = sta; + } else if (sdata->wdev.use_4addr) { + ret = -ENOLINK; + goto free; +@@ -2074,6 +2085,7 @@ static struct sk_buff *ieee80211_build_h + have_station = true; + authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); + wme_sta = sta->sta.wme; ++ *sta_out = sta; + } else if (sdata->u.mgd.use_4addr && + cpu_to_be16(ethertype) != sdata->control_port_protocol) { + fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | +@@ -2137,13 +2149,18 @@ static struct sk_buff *ieee80211_build_h + * and mesh mode checks authorization later. + */ + multicast = is_multicast_ether_addr(hdr.addr1); +- if (!multicast && !have_station && +- !ieee80211_vif_is_mesh(&sdata->vif)) { +- sta = sta_info_get(sdata, hdr.addr1); ++ if (multicast) { ++ *sta_out = ERR_PTR(-ENOENT); ++ } else if (!have_station && !ieee80211_vif_is_mesh(&sdata->vif)) { ++ if (sdata->control_port_protocol == skb->protocol) ++ sta = sta_info_get_bss(sdata, hdr.addr1); ++ else ++ sta = sta_info_get(sdata, hdr.addr1); + if (sta) { + authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); + wme_sta = sta->sta.wme; + } ++ *sta_out = sta ?: ERR_PTR(-ENOENT); + } + + /* For mesh, the use of the QoS header is mandatory */ +@@ -2321,6 +2338,7 @@ void __ieee80211_subif_start_xmit(struct + u32 info_flags) + { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ struct sta_info *sta = NULL; + + if (unlikely(skb->len < ETH_HLEN)) { + kfree_skb(skb); +@@ -2329,7 +2347,7 @@ void __ieee80211_subif_start_xmit(struct + + rcu_read_lock(); + +- skb = ieee80211_build_hdr(sdata, skb, info_flags); ++ skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta); + if (IS_ERR(skb)) + goto out; + +@@ -2337,7 +2355,7 @@ void __ieee80211_subif_start_xmit(struct + dev->stats.tx_bytes += skb->len; + dev->trans_start = jiffies; + +- ieee80211_xmit(sdata, skb); ++ ieee80211_xmit(sdata, sta, skb); + out: + rcu_read_unlock(); + } +@@ -2365,10 +2383,11 @@ ieee80211_build_data_template(struct iee + .local = sdata->local, + .sdata = sdata, + }; ++ struct sta_info *sta_ignore; + + rcu_read_lock(); + +- skb = ieee80211_build_hdr(sdata, skb, info_flags); ++ skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta_ignore); + if (IS_ERR(skb)) + goto out; + +@@ -2426,7 +2445,7 @@ static bool ieee80211_tx_pending_skb(str + return true; + } + info->band = chanctx_conf->def.chan->band; +- result = ieee80211_tx(sdata, skb, true); ++ result = ieee80211_tx(sdata, NULL, skb, true); + } else { + struct sk_buff_head skbs; + +@@ -3164,7 +3183,7 @@ ieee80211_get_buffered_bc(struct ieee802 + + if (sdata->vif.type == NL80211_IFTYPE_AP) + sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); +- if (!ieee80211_tx_prepare(sdata, &tx, skb)) ++ if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb)) + break; + dev_kfree_skb_any(skb); + } +@@ -3296,6 +3315,6 @@ void __ieee80211_tx_skb_tid_band(struct + */ + local_bh_disable(); + IEEE80211_SKB_CB(skb)->band = band; +- ieee80211_xmit(sdata, skb); ++ ieee80211_xmit(sdata, NULL, skb); + local_bh_enable(); + } diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch index 673c6dc422..e13fe31d3f 100644 --- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -87,7 +87,7 @@ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1336,6 +1336,7 @@ struct ieee80211_local { +@@ -1333,6 +1333,7 @@ struct ieee80211_local { int dynamic_ps_forced_timeout; int user_power_level; /* in dBm, for all interfaces */