Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 44910master
parent
f7a861615c
commit
9143cf5fc9
@ -0,0 +1,21 @@ |
|||||||
|
From: Johannes Berg <johannes.berg@intel.com>
|
||||||
|
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 <johannes.berg@intel.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- 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) &&
|
@ -0,0 +1,130 @@ |
|||||||
|
From: Johannes Berg <johannes.berg@intel.com>
|
||||||
|
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 <johannes.berg@intel.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- 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;
|
@ -0,0 +1,71 @@ |
|||||||
|
From: Johannes Berg <johannes.berg@intel.com>
|
||||||
|
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 <johannes.berg@intel.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- 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);
|
@ -0,0 +1,27 @@ |
|||||||
|
From: Johannes Berg <johannes.berg@intel.com>
|
||||||
|
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 <johannes.berg@intel.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- 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);
|
@ -0,0 +1,33 @@ |
|||||||
|
From: Johannes Berg <johannes.berg@intel.com>
|
||||||
|
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 <johannes.berg@intel.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- 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);
|
@ -0,0 +1,267 @@ |
|||||||
|
From: Johannes Berg <johannes.berg@intel.com>
|
||||||
|
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 <johannes.berg@intel.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
--- 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();
|
||||||
|
}
|
Loading…
Reference in new issue