aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-03-20 09:18:27 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-03-20 11:27:36 -0400
commit7c10770f995820ec1ed26c761b1583bfc4d88872 (patch)
tree5934c5a2448bf0765c93de85c8f82ffaa9f6bd1e /net/mac80211
parente33f5569aafadfa68aea32457a9246818d3dfe48 (diff)
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>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/tx.c73
4 files changed, 50 insertions, 30 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 57b71432ec65..0aaf8b04a738 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3576,7 +3576,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
3576 nullfunc->qos_ctrl = cpu_to_le16(7); 3576 nullfunc->qos_ctrl = cpu_to_le16(7);
3577 3577
3578 local_bh_disable(); 3578 local_bh_disable();
3579 ieee80211_xmit(sdata, skb); 3579 ieee80211_xmit(sdata, sta, skb);
3580 local_bh_enable(); 3580 local_bh_enable();
3581 rcu_read_unlock(); 3581 rcu_read_unlock();
3582 3582
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4f4bcc6c5dfe..ebc8135e0aaa 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1745,7 +1745,8 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke
1745 gfp_t gfp); 1745 gfp_t gfp);
1746void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, 1746void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
1747 bool bss_notify); 1747 bool bss_notify);
1748void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); 1748void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1749 struct sta_info *sta, struct sk_buff *skb);
1749 1750
1750void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, 1751void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
1751 struct sk_buff *skb, int tid, 1752 struct sk_buff *skb, int tid,
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index d94004e7ce37..aacaa1a85e63 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1231,7 +1231,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
1231 } 1231 }
1232 1232
1233 info->band = chanctx_conf->def.chan->band; 1233 info->band = chanctx_conf->def.chan->band;
1234 ieee80211_xmit(sdata, skb); 1234 ieee80211_xmit(sdata, sta, skb);
1235 rcu_read_unlock(); 1235 rcu_read_unlock();
1236} 1236}
1237 1237
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5af35ef35322..34b0e7545cc5 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1120,11 +1120,13 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
1120 1120
1121/* 1121/*
1122 * initialises @tx 1122 * initialises @tx
1123 * pass %NULL for the station if unknown, a valid pointer if known
1124 * or an ERR_PTR() if the station is known not to exist
1123 */ 1125 */
1124static ieee80211_tx_result 1126static ieee80211_tx_result
1125ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, 1127ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1126 struct ieee80211_tx_data *tx, 1128 struct ieee80211_tx_data *tx,
1127 struct sk_buff *skb) 1129 struct sta_info *sta, struct sk_buff *skb)
1128{ 1130{
1129 struct ieee80211_local *local = sdata->local; 1131 struct ieee80211_local *local = sdata->local;
1130 struct ieee80211_hdr *hdr; 1132 struct ieee80211_hdr *hdr;
@@ -1147,17 +1149,22 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1147 1149
1148 hdr = (struct ieee80211_hdr *) skb->data; 1150 hdr = (struct ieee80211_hdr *) skb->data;
1149 1151
1150 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { 1152 if (likely(sta)) {
1151 tx->sta = rcu_dereference(sdata->u.vlan.sta); 1153 if (!IS_ERR(sta))
1152 if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) 1154 tx->sta = sta;
1153 return TX_DROP; 1155 } else {
1154 } else if (info->flags & (IEEE80211_TX_CTL_INJECTED | 1156 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
1155 IEEE80211_TX_INTFL_NL80211_FRAME_TX) || 1157 tx->sta = rcu_dereference(sdata->u.vlan.sta);
1156 tx->sdata->control_port_protocol == tx->skb->protocol) { 1158 if (!tx->sta && sdata->wdev.use_4addr)
1157 tx->sta = sta_info_get_bss(sdata, hdr->addr1); 1159 return TX_DROP;
1160 } else if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX |
1161 IEEE80211_TX_CTL_INJECTED) ||
1162 tx->sdata->control_port_protocol == tx->skb->protocol) {
1163 tx->sta = sta_info_get_bss(sdata, hdr->addr1);
1164 }
1165 if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
1166 tx->sta = sta_info_get(sdata, hdr->addr1);
1158 } 1167 }
1159 if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
1160 tx->sta = sta_info_get(sdata, hdr->addr1);
1161 1168
1162 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && 1169 if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
1163 !ieee80211_is_qos_nullfunc(hdr->frame_control) && 1170 !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
@@ -1407,7 +1414,7 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
1407 struct ieee80211_tx_data tx; 1414 struct ieee80211_tx_data tx;
1408 struct sk_buff *skb2; 1415 struct sk_buff *skb2;
1409 1416
1410 if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP) 1417 if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP)
1411 return false; 1418 return false;
1412 1419
1413 info->band = band; 1420 info->band = band;
@@ -1440,7 +1447,8 @@ EXPORT_SYMBOL(ieee80211_tx_prepare_skb);
1440 * Returns false if the frame couldn't be transmitted but was queued instead. 1447 * Returns false if the frame couldn't be transmitted but was queued instead.
1441 */ 1448 */
1442static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, 1449static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
1443 struct sk_buff *skb, bool txpending) 1450 struct sta_info *sta, struct sk_buff *skb,
1451 bool txpending)
1444{ 1452{
1445 struct ieee80211_local *local = sdata->local; 1453 struct ieee80211_local *local = sdata->local;
1446 struct ieee80211_tx_data tx; 1454 struct ieee80211_tx_data tx;
@@ -1456,7 +1464,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
1456 1464
1457 /* initialises tx */ 1465 /* initialises tx */
1458 led_len = skb->len; 1466 led_len = skb->len;
1459 res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); 1467 res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb);
1460 1468
1461 if (unlikely(res_prepare == TX_DROP)) { 1469 if (unlikely(res_prepare == TX_DROP)) {
1462 ieee80211_free_txskb(&local->hw, skb); 1470 ieee80211_free_txskb(&local->hw, skb);
@@ -1512,7 +1520,8 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
1512 return 0; 1520 return 0;
1513} 1521}
1514 1522
1515void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) 1523void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1524 struct sta_info *sta, struct sk_buff *skb)
1516{ 1525{
1517 struct ieee80211_local *local = sdata->local; 1526 struct ieee80211_local *local = sdata->local;
1518 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1527 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1547,7 +1556,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
1547 } 1556 }
1548 1557
1549 ieee80211_set_qos_hdr(sdata, skb); 1558 ieee80211_set_qos_hdr(sdata, skb);
1550 ieee80211_tx(sdata, skb, false); 1559 ieee80211_tx(sdata, sta, skb, false);
1551} 1560}
1552 1561
1553static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) 1562static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
@@ -1768,7 +1777,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
1768 goto fail_rcu; 1777 goto fail_rcu;
1769 1778
1770 info->band = chandef->chan->band; 1779 info->band = chandef->chan->band;
1771 ieee80211_xmit(sdata, skb); 1780 ieee80211_xmit(sdata, NULL, skb);
1772 rcu_read_unlock(); 1781 rcu_read_unlock();
1773 1782
1774 return NETDEV_TX_OK; 1783 return NETDEV_TX_OK;
@@ -1799,7 +1808,8 @@ fail:
1799 * Returns: the (possibly reallocated) skb or an ERR_PTR() code 1808 * Returns: the (possibly reallocated) skb or an ERR_PTR() code
1800 */ 1809 */
1801static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, 1810static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
1802 struct sk_buff *skb, u32 info_flags) 1811 struct sk_buff *skb, u32 info_flags,
1812 struct sta_info **sta_out)
1803{ 1813{
1804 struct ieee80211_local *local = sdata->local; 1814 struct ieee80211_local *local = sdata->local;
1805 struct ieee80211_tx_info *info; 1815 struct ieee80211_tx_info *info;
@@ -1842,6 +1852,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
1842 authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); 1852 authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
1843 wme_sta = sta->sta.wme; 1853 wme_sta = sta->sta.wme;
1844 have_station = true; 1854 have_station = true;
1855 *sta_out = sta;
1845 } else if (sdata->wdev.use_4addr) { 1856 } else if (sdata->wdev.use_4addr) {
1846 ret = -ENOLINK; 1857 ret = -ENOLINK;
1847 goto free; 1858 goto free;
@@ -1995,6 +2006,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
1995 have_station = true; 2006 have_station = true;
1996 authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); 2007 authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
1997 wme_sta = sta->sta.wme; 2008 wme_sta = sta->sta.wme;
2009 *sta_out = sta;
1998 } else if (sdata->u.mgd.use_4addr && 2010 } else if (sdata->u.mgd.use_4addr &&
1999 cpu_to_be16(ethertype) != sdata->control_port_protocol) { 2011 cpu_to_be16(ethertype) != sdata->control_port_protocol) {
2000 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | 2012 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
@@ -2058,13 +2070,18 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
2058 * and mesh mode checks authorization later. 2070 * and mesh mode checks authorization later.
2059 */ 2071 */
2060 multicast = is_multicast_ether_addr(hdr.addr1); 2072 multicast = is_multicast_ether_addr(hdr.addr1);
2061 if (!multicast && !have_station && 2073 if (multicast) {
2062 !ieee80211_vif_is_mesh(&sdata->vif)) { 2074 *sta_out = ERR_PTR(-ENOENT);
2063 sta = sta_info_get(sdata, hdr.addr1); 2075 } else if (!have_station && !ieee80211_vif_is_mesh(&sdata->vif)) {
2076 if (sdata->control_port_protocol == skb->protocol)
2077 sta = sta_info_get_bss(sdata, hdr.addr1);
2078 else
2079 sta = sta_info_get(sdata, hdr.addr1);
2064 if (sta) { 2080 if (sta) {
2065 authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); 2081 authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
2066 wme_sta = sta->sta.wme; 2082 wme_sta = sta->sta.wme;
2067 } 2083 }
2084 *sta_out = sta ?: ERR_PTR(-ENOENT);
2068 } 2085 }
2069 2086
2070 /* For mesh, the use of the QoS header is mandatory */ 2087 /* For mesh, the use of the QoS header is mandatory */
@@ -2242,6 +2259,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
2242 u32 info_flags) 2259 u32 info_flags)
2243{ 2260{
2244 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 2261 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2262 struct sta_info *sta = NULL;
2245 2263
2246 if (unlikely(skb->len < ETH_HLEN)) { 2264 if (unlikely(skb->len < ETH_HLEN)) {
2247 kfree_skb(skb); 2265 kfree_skb(skb);
@@ -2250,7 +2268,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
2250 2268
2251 rcu_read_lock(); 2269 rcu_read_lock();
2252 2270
2253 skb = ieee80211_build_hdr(sdata, skb, info_flags); 2271 skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta);
2254 if (IS_ERR(skb)) 2272 if (IS_ERR(skb))
2255 goto out; 2273 goto out;
2256 2274
@@ -2258,7 +2276,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
2258 dev->stats.tx_bytes += skb->len; 2276 dev->stats.tx_bytes += skb->len;
2259 dev->trans_start = jiffies; 2277 dev->trans_start = jiffies;
2260 2278
2261 ieee80211_xmit(sdata, skb); 2279 ieee80211_xmit(sdata, sta, skb);
2262 out: 2280 out:
2263 rcu_read_unlock(); 2281 rcu_read_unlock();
2264} 2282}
@@ -2286,10 +2304,11 @@ ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
2286 .local = sdata->local, 2304 .local = sdata->local,
2287 .sdata = sdata, 2305 .sdata = sdata,
2288 }; 2306 };
2307 struct sta_info *sta_ignore;
2289 2308
2290 rcu_read_lock(); 2309 rcu_read_lock();
2291 2310
2292 skb = ieee80211_build_hdr(sdata, skb, info_flags); 2311 skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta_ignore);
2293 if (IS_ERR(skb)) 2312 if (IS_ERR(skb))
2294 goto out; 2313 goto out;
2295 2314
@@ -2347,7 +2366,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
2347 return true; 2366 return true;
2348 } 2367 }
2349 info->band = chanctx_conf->def.chan->band; 2368 info->band = chanctx_conf->def.chan->band;
2350 result = ieee80211_tx(sdata, skb, true); 2369 result = ieee80211_tx(sdata, NULL, skb, true);
2351 } else { 2370 } else {
2352 struct sk_buff_head skbs; 2371 struct sk_buff_head skbs;
2353 2372
@@ -3085,7 +3104,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
3085 3104
3086 if (sdata->vif.type == NL80211_IFTYPE_AP) 3105 if (sdata->vif.type == NL80211_IFTYPE_AP)
3087 sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); 3106 sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
3088 if (!ieee80211_tx_prepare(sdata, &tx, skb)) 3107 if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb))
3089 break; 3108 break;
3090 dev_kfree_skb_any(skb); 3109 dev_kfree_skb_any(skb);
3091 } 3110 }
@@ -3217,6 +3236,6 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
3217 */ 3236 */
3218 local_bh_disable(); 3237 local_bh_disable();
3219 IEEE80211_SKB_CB(skb)->band = band; 3238 IEEE80211_SKB_CB(skb)->band = band;
3220 ieee80211_xmit(sdata, skb); 3239 ieee80211_xmit(sdata, NULL, skb);
3221 local_bh_enable(); 3240 local_bh_enable();
3222} 3241}