.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright 2002-2005, Instant802 Networks, Inc. |
---|
3 | 4 | * Copyright 2005-2006, Devicescape Software, Inc. |
---|
4 | 5 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
---|
5 | 6 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> |
---|
6 | 7 | * Copyright 2013-2014 Intel Mobile Communications GmbH |
---|
7 | | - * Copyright (C) 2018, 2020 Intel Corporation |
---|
8 | | - * |
---|
9 | | - * This program is free software; you can redistribute it and/or modify |
---|
10 | | - * it under the terms of the GNU General Public License version 2 as |
---|
11 | | - * published by the Free Software Foundation. |
---|
12 | | - * |
---|
| 8 | + * Copyright (C) 2018-2020 Intel Corporation |
---|
13 | 9 | * |
---|
14 | 10 | * Transmit and frame generation functions. |
---|
15 | 11 | */ |
---|
.. | .. |
---|
85 | 81 | txrate = &sband->bitrates[tx->rate.idx]; |
---|
86 | 82 | |
---|
87 | 83 | erp = txrate->flags & IEEE80211_RATE_ERP_G; |
---|
| 84 | + |
---|
| 85 | + /* device is expected to do this */ |
---|
| 86 | + if (sband->band == NL80211_BAND_S1GHZ) |
---|
| 87 | + return 0; |
---|
88 | 88 | |
---|
89 | 89 | /* |
---|
90 | 90 | * data and mgmt (except PS Poll): |
---|
.. | .. |
---|
166 | 166 | break; |
---|
167 | 167 | } |
---|
168 | 168 | case NL80211_BAND_5GHZ: |
---|
| 169 | + case NL80211_BAND_6GHZ: |
---|
169 | 170 | if (r->flags & IEEE80211_RATE_MANDATORY_A) |
---|
170 | 171 | mrate = r->bitrate; |
---|
171 | 172 | break; |
---|
| 173 | + case NL80211_BAND_S1GHZ: |
---|
172 | 174 | case NL80211_BAND_60GHZ: |
---|
173 | 175 | /* TODO, for now fall through */ |
---|
174 | 176 | case NUM_NL80211_BANDS: |
---|
.. | .. |
---|
533 | 535 | |
---|
534 | 536 | info->control.jiffies = jiffies; |
---|
535 | 537 | info->control.vif = &tx->sdata->vif; |
---|
536 | | - info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
---|
| 538 | + info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; |
---|
537 | 539 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; |
---|
538 | 540 | skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); |
---|
539 | 541 | spin_unlock(&sta->ps_lock); |
---|
.. | .. |
---|
660 | 662 | if (!skip_hw && tx->key && |
---|
661 | 663 | tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) |
---|
662 | 664 | info->control.hw_key = &tx->key->conf; |
---|
663 | | - } else if (!ieee80211_is_mgmt(hdr->frame_control) && tx->sta && |
---|
| 665 | + } else if (ieee80211_is_data_present(hdr->frame_control) && tx->sta && |
---|
664 | 666 | test_sta_flag(tx->sta, WLAN_STA_USES_ENCRYPTION)) { |
---|
665 | 667 | return TX_DROP; |
---|
666 | 668 | } |
---|
.. | .. |
---|
827 | 829 | if (ieee80211_is_qos_nullfunc(hdr->frame_control)) |
---|
828 | 830 | return TX_CONTINUE; |
---|
829 | 831 | |
---|
| 832 | + if (info->control.flags & IEEE80211_TX_CTRL_NO_SEQNO) |
---|
| 833 | + return TX_CONTINUE; |
---|
| 834 | + |
---|
830 | 835 | /* |
---|
831 | 836 | * Anything but QoS data that has a sequence number field |
---|
832 | 837 | * (is long enough) gets a sequence number from the global |
---|
.. | .. |
---|
835 | 840 | */ |
---|
836 | 841 | if (!ieee80211_is_data_qos(hdr->frame_control) || |
---|
837 | 842 | is_multicast_ether_addr(hdr->addr1)) { |
---|
838 | | - if (tx->flags & IEEE80211_TX_NO_SEQNO) |
---|
839 | | - return TX_CONTINUE; |
---|
840 | 843 | /* driver should assign sequence number */ |
---|
841 | 844 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; |
---|
842 | 845 | /* for pure STA mode without beacons, we can do it */ |
---|
.. | .. |
---|
1135 | 1138 | tx->sta->sta.addr, tx->sta->sta.aid); |
---|
1136 | 1139 | } |
---|
1137 | 1140 | info->control.vif = &tx->sdata->vif; |
---|
1138 | | - info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
---|
| 1141 | + info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING; |
---|
1139 | 1142 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; |
---|
1140 | 1143 | __skb_queue_tail(&tid_tx->pending, skb); |
---|
1141 | 1144 | if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER) |
---|
.. | .. |
---|
1180 | 1183 | * we are doing the needed processing, so remove the flag |
---|
1181 | 1184 | * now. |
---|
1182 | 1185 | */ |
---|
1183 | | - info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
---|
| 1186 | + info->control.flags &= ~IEEE80211_TX_INTCFL_NEED_TXPROCESSING; |
---|
1184 | 1187 | |
---|
1185 | 1188 | hdr = (struct ieee80211_hdr *) skb->data; |
---|
1186 | 1189 | |
---|
.. | .. |
---|
1259 | 1262 | (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)) |
---|
1260 | 1263 | return NULL; |
---|
1261 | 1264 | |
---|
1262 | | - if (!ieee80211_is_data_present(hdr->frame_control)) |
---|
1263 | | - return NULL; |
---|
1264 | | - |
---|
1265 | | - if (sta) { |
---|
| 1265 | + if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && |
---|
| 1266 | + unlikely(!ieee80211_is_data_present(hdr->frame_control))) { |
---|
| 1267 | + if ((!ieee80211_is_mgmt(hdr->frame_control) || |
---|
| 1268 | + ieee80211_is_bufferable_mmpdu(hdr->frame_control) || |
---|
| 1269 | + vif->type == NL80211_IFTYPE_STATION) && |
---|
| 1270 | + sta && sta->uploaded) { |
---|
| 1271 | + /* |
---|
| 1272 | + * This will be NULL if the driver didn't set the |
---|
| 1273 | + * opt-in hardware flag. |
---|
| 1274 | + */ |
---|
| 1275 | + txq = sta->sta.txq[IEEE80211_NUM_TIDS]; |
---|
| 1276 | + } |
---|
| 1277 | + } else if (sta) { |
---|
1266 | 1278 | u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; |
---|
1267 | 1279 | |
---|
1268 | 1280 | if (!sta->uploaded) |
---|
.. | .. |
---|
1397 | 1409 | { |
---|
1398 | 1410 | struct fq *fq = &local->fq; |
---|
1399 | 1411 | struct fq_tin *tin = &txqi->tin; |
---|
| 1412 | + u32 flow_idx = fq_flow_idx(fq, skb); |
---|
1400 | 1413 | |
---|
1401 | 1414 | ieee80211_set_skb_enqueue_time(skb); |
---|
1402 | | - fq_tin_enqueue(fq, tin, skb, |
---|
| 1415 | + |
---|
| 1416 | + spin_lock_bh(&fq->lock); |
---|
| 1417 | + fq_tin_enqueue(fq, tin, flow_idx, skb, |
---|
1403 | 1418 | fq_skb_free_func, |
---|
1404 | 1419 | fq_flow_get_default_func); |
---|
| 1420 | + spin_unlock_bh(&fq->lock); |
---|
1405 | 1421 | } |
---|
1406 | 1422 | |
---|
1407 | 1423 | static bool fq_vlan_filter_func(struct fq *fq, struct fq_tin *tin, |
---|
.. | .. |
---|
1447 | 1463 | codel_vars_init(&txqi->def_cvars); |
---|
1448 | 1464 | codel_stats_init(&txqi->cstats); |
---|
1449 | 1465 | __skb_queue_head_init(&txqi->frags); |
---|
| 1466 | + INIT_LIST_HEAD(&txqi->schedule_order); |
---|
1450 | 1467 | |
---|
1451 | 1468 | txqi->txq.vif = &sdata->vif; |
---|
1452 | 1469 | |
---|
1453 | | - if (sta) { |
---|
1454 | | - txqi->txq.sta = &sta->sta; |
---|
1455 | | - sta->sta.txq[tid] = &txqi->txq; |
---|
1456 | | - txqi->txq.tid = tid; |
---|
1457 | | - txqi->txq.ac = ieee80211_ac_from_tid(tid); |
---|
1458 | | - } else { |
---|
| 1470 | + if (!sta) { |
---|
1459 | 1471 | sdata->vif.txq = &txqi->txq; |
---|
1460 | 1472 | txqi->txq.tid = 0; |
---|
1461 | 1473 | txqi->txq.ac = IEEE80211_AC_BE; |
---|
| 1474 | + |
---|
| 1475 | + return; |
---|
1462 | 1476 | } |
---|
| 1477 | + |
---|
| 1478 | + if (tid == IEEE80211_NUM_TIDS) { |
---|
| 1479 | + if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
---|
| 1480 | + /* Drivers need to opt in to the management MPDU TXQ */ |
---|
| 1481 | + if (!ieee80211_hw_check(&sdata->local->hw, |
---|
| 1482 | + STA_MMPDU_TXQ)) |
---|
| 1483 | + return; |
---|
| 1484 | + } else if (!ieee80211_hw_check(&sdata->local->hw, |
---|
| 1485 | + BUFF_MMPDU_TXQ)) { |
---|
| 1486 | + /* Drivers need to opt in to the bufferable MMPDU TXQ */ |
---|
| 1487 | + return; |
---|
| 1488 | + } |
---|
| 1489 | + txqi->txq.ac = IEEE80211_AC_VO; |
---|
| 1490 | + } else { |
---|
| 1491 | + txqi->txq.ac = ieee80211_ac_from_tid(tid); |
---|
| 1492 | + } |
---|
| 1493 | + |
---|
| 1494 | + txqi->txq.sta = &sta->sta; |
---|
| 1495 | + txqi->txq.tid = tid; |
---|
| 1496 | + sta->sta.txq[tid] = &txqi->txq; |
---|
1463 | 1497 | } |
---|
1464 | 1498 | |
---|
1465 | 1499 | void ieee80211_txq_purge(struct ieee80211_local *local, |
---|
.. | .. |
---|
1468 | 1502 | struct fq *fq = &local->fq; |
---|
1469 | 1503 | struct fq_tin *tin = &txqi->tin; |
---|
1470 | 1504 | |
---|
| 1505 | + spin_lock_bh(&fq->lock); |
---|
1471 | 1506 | fq_tin_reset(fq, tin, fq_skb_free_func); |
---|
1472 | 1507 | ieee80211_purge_tx_queue(&local->hw, &txqi->frags); |
---|
| 1508 | + spin_unlock_bh(&fq->lock); |
---|
| 1509 | + |
---|
| 1510 | + spin_lock_bh(&local->active_txq_lock[txqi->txq.ac]); |
---|
| 1511 | + list_del_init(&txqi->schedule_order); |
---|
| 1512 | + spin_unlock_bh(&local->active_txq_lock[txqi->txq.ac]); |
---|
1473 | 1513 | } |
---|
1474 | 1514 | |
---|
1475 | 1515 | void ieee80211_txq_set_params(struct ieee80211_local *local) |
---|
.. | .. |
---|
1564 | 1604 | struct sta_info *sta, |
---|
1565 | 1605 | struct sk_buff *skb) |
---|
1566 | 1606 | { |
---|
1567 | | - struct fq *fq = &local->fq; |
---|
1568 | 1607 | struct ieee80211_vif *vif; |
---|
1569 | 1608 | struct txq_info *txqi; |
---|
1570 | 1609 | |
---|
.. | .. |
---|
1582 | 1621 | if (!txqi) |
---|
1583 | 1622 | return false; |
---|
1584 | 1623 | |
---|
1585 | | - spin_lock_bh(&fq->lock); |
---|
1586 | 1624 | ieee80211_txq_enqueue(local, txqi, skb); |
---|
1587 | | - spin_unlock_bh(&fq->lock); |
---|
1588 | 1625 | |
---|
1589 | | - drv_wake_tx_queue(local, txqi); |
---|
| 1626 | + schedule_and_wake_txq(local, txqi); |
---|
1590 | 1627 | |
---|
1591 | 1628 | return true; |
---|
1592 | 1629 | } |
---|
1593 | 1630 | |
---|
1594 | 1631 | static bool ieee80211_tx_frags(struct ieee80211_local *local, |
---|
1595 | 1632 | struct ieee80211_vif *vif, |
---|
1596 | | - struct ieee80211_sta *sta, |
---|
| 1633 | + struct sta_info *sta, |
---|
1597 | 1634 | struct sk_buff_head *skbs, |
---|
1598 | 1635 | bool txpending) |
---|
1599 | 1636 | { |
---|
.. | .. |
---|
1655 | 1692 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
---|
1656 | 1693 | |
---|
1657 | 1694 | info->control.vif = vif; |
---|
1658 | | - control.sta = sta; |
---|
| 1695 | + control.sta = sta ? &sta->sta : NULL; |
---|
1659 | 1696 | |
---|
1660 | 1697 | __skb_unlink(skb, skbs); |
---|
1661 | 1698 | drv_tx(local, &control, skb); |
---|
.. | .. |
---|
1674 | 1711 | struct ieee80211_tx_info *info; |
---|
1675 | 1712 | struct ieee80211_sub_if_data *sdata; |
---|
1676 | 1713 | struct ieee80211_vif *vif; |
---|
1677 | | - struct ieee80211_sta *pubsta; |
---|
1678 | 1714 | struct sk_buff *skb; |
---|
1679 | 1715 | bool result = true; |
---|
1680 | 1716 | __le16 fc; |
---|
.. | .. |
---|
1688 | 1724 | sdata = vif_to_sdata(info->control.vif); |
---|
1689 | 1725 | if (sta && !sta->uploaded) |
---|
1690 | 1726 | sta = NULL; |
---|
1691 | | - |
---|
1692 | | - if (sta) |
---|
1693 | | - pubsta = &sta->sta; |
---|
1694 | | - else |
---|
1695 | | - pubsta = NULL; |
---|
1696 | 1727 | |
---|
1697 | 1728 | switch (sdata->vif.type) { |
---|
1698 | 1729 | case NL80211_IFTYPE_MONITOR: |
---|
.. | .. |
---|
1714 | 1745 | case NL80211_IFTYPE_AP_VLAN: |
---|
1715 | 1746 | sdata = container_of(sdata->bss, |
---|
1716 | 1747 | struct ieee80211_sub_if_data, u.ap); |
---|
1717 | | - /* fall through */ |
---|
| 1748 | + fallthrough; |
---|
1718 | 1749 | default: |
---|
1719 | 1750 | vif = &sdata->vif; |
---|
1720 | 1751 | break; |
---|
1721 | 1752 | } |
---|
1722 | 1753 | |
---|
1723 | | - result = ieee80211_tx_frags(local, vif, pubsta, skbs, |
---|
1724 | | - txpending); |
---|
| 1754 | + result = ieee80211_tx_frags(local, vif, sta, skbs, txpending); |
---|
1725 | 1755 | |
---|
1726 | 1756 | ieee80211_tpt_led_trig_tx(local, fc, led_len); |
---|
1727 | 1757 | |
---|
.. | .. |
---|
1866 | 1896 | */ |
---|
1867 | 1897 | static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, |
---|
1868 | 1898 | struct sta_info *sta, struct sk_buff *skb, |
---|
1869 | | - bool txpending, u32 txdata_flags) |
---|
| 1899 | + bool txpending) |
---|
1870 | 1900 | { |
---|
1871 | 1901 | struct ieee80211_local *local = sdata->local; |
---|
1872 | 1902 | struct ieee80211_tx_data tx; |
---|
.. | .. |
---|
1883 | 1913 | /* initialises tx */ |
---|
1884 | 1914 | led_len = skb->len; |
---|
1885 | 1915 | res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb); |
---|
1886 | | - |
---|
1887 | | - tx.flags |= txdata_flags; |
---|
1888 | 1916 | |
---|
1889 | 1917 | if (unlikely(res_prepare == TX_DROP)) { |
---|
1890 | 1918 | ieee80211_free_txskb(&local->hw, skb); |
---|
.. | .. |
---|
1958 | 1986 | } |
---|
1959 | 1987 | |
---|
1960 | 1988 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, |
---|
1961 | | - struct sta_info *sta, struct sk_buff *skb, |
---|
1962 | | - u32 txdata_flags) |
---|
| 1989 | + struct sta_info *sta, struct sk_buff *skb) |
---|
1963 | 1990 | { |
---|
1964 | 1991 | struct ieee80211_local *local = sdata->local; |
---|
1965 | 1992 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
---|
.. | .. |
---|
2000 | 2027 | } |
---|
2001 | 2028 | |
---|
2002 | 2029 | ieee80211_set_qos_hdr(sdata, skb); |
---|
2003 | | - ieee80211_tx(sdata, sta, skb, false, txdata_flags); |
---|
| 2030 | + ieee80211_tx(sdata, sta, skb, false); |
---|
2004 | 2031 | } |
---|
2005 | 2032 | |
---|
2006 | | -static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local, |
---|
2007 | | - struct sk_buff *skb) |
---|
| 2033 | +static bool ieee80211_validate_radiotap_len(struct sk_buff *skb) |
---|
2008 | 2034 | { |
---|
| 2035 | + struct ieee80211_radiotap_header *rthdr = |
---|
| 2036 | + (struct ieee80211_radiotap_header *)skb->data; |
---|
| 2037 | + |
---|
| 2038 | + /* check for not even having the fixed radiotap header part */ |
---|
| 2039 | + if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) |
---|
| 2040 | + return false; /* too short to be possibly valid */ |
---|
| 2041 | + |
---|
| 2042 | + /* is it a header version we can trust to find length from? */ |
---|
| 2043 | + if (unlikely(rthdr->it_version)) |
---|
| 2044 | + return false; /* only version 0 is supported */ |
---|
| 2045 | + |
---|
| 2046 | + /* does the skb contain enough to deliver on the alleged length? */ |
---|
| 2047 | + if (unlikely(skb->len < ieee80211_get_radiotap_len(skb->data))) |
---|
| 2048 | + return false; /* skb too short for claimed rt header extent */ |
---|
| 2049 | + |
---|
| 2050 | + return true; |
---|
| 2051 | +} |
---|
| 2052 | + |
---|
| 2053 | +bool ieee80211_parse_tx_radiotap(struct sk_buff *skb, |
---|
| 2054 | + struct net_device *dev) |
---|
| 2055 | +{ |
---|
| 2056 | + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
---|
2009 | 2057 | struct ieee80211_radiotap_iterator iterator; |
---|
2010 | 2058 | struct ieee80211_radiotap_header *rthdr = |
---|
2011 | 2059 | (struct ieee80211_radiotap_header *) skb->data; |
---|
2012 | 2060 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
---|
2013 | | - struct ieee80211_supported_band *sband = |
---|
2014 | | - local->hw.wiphy->bands[info->band]; |
---|
2015 | 2061 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, |
---|
2016 | 2062 | NULL); |
---|
2017 | 2063 | u16 txflags; |
---|
.. | .. |
---|
2023 | 2069 | u16 vht_known; |
---|
2024 | 2070 | u8 vht_mcs = 0, vht_nss = 0; |
---|
2025 | 2071 | int i; |
---|
| 2072 | + |
---|
| 2073 | + if (!ieee80211_validate_radiotap_len(skb)) |
---|
| 2074 | + return false; |
---|
2026 | 2075 | |
---|
2027 | 2076 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | |
---|
2028 | 2077 | IEEE80211_TX_CTL_DONTFRAG; |
---|
.. | .. |
---|
2071 | 2120 | txflags = get_unaligned_le16(iterator.this_arg); |
---|
2072 | 2121 | if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK) |
---|
2073 | 2122 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
---|
| 2123 | + if (txflags & IEEE80211_RADIOTAP_F_TX_NOSEQNO) |
---|
| 2124 | + info->control.flags |= IEEE80211_TX_CTRL_NO_SEQNO; |
---|
2074 | 2125 | break; |
---|
2075 | 2126 | |
---|
2076 | 2127 | case IEEE80211_RADIOTAP_RATE: |
---|
.. | .. |
---|
2135 | 2186 | |
---|
2136 | 2187 | /* |
---|
2137 | 2188 | * Please update the file |
---|
2138 | | - * Documentation/networking/mac80211-injection.txt |
---|
| 2189 | + * Documentation/networking/mac80211-injection.rst |
---|
2139 | 2190 | * when parsing new fields here. |
---|
2140 | 2191 | */ |
---|
2141 | 2192 | |
---|
.. | .. |
---|
2148 | 2199 | return false; |
---|
2149 | 2200 | |
---|
2150 | 2201 | if (rate_found) { |
---|
| 2202 | + struct ieee80211_supported_band *sband = |
---|
| 2203 | + local->hw.wiphy->bands[info->band]; |
---|
| 2204 | + |
---|
2151 | 2205 | info->control.flags |= IEEE80211_TX_CTRL_RATE_INJECT; |
---|
2152 | 2206 | |
---|
2153 | 2207 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
---|
.. | .. |
---|
2161 | 2215 | } else if (rate_flags & IEEE80211_TX_RC_VHT_MCS) { |
---|
2162 | 2216 | ieee80211_rate_set_vht(info->control.rates, vht_mcs, |
---|
2163 | 2217 | vht_nss); |
---|
2164 | | - } else { |
---|
| 2218 | + } else if (sband) { |
---|
2165 | 2219 | for (i = 0; i < sband->n_bitrates; i++) { |
---|
2166 | 2220 | if (rate * 5 != sband->bitrates[i].bitrate) |
---|
2167 | 2221 | continue; |
---|
.. | .. |
---|
2179 | 2233 | local->hw.max_rate_tries); |
---|
2180 | 2234 | } |
---|
2181 | 2235 | |
---|
2182 | | - /* |
---|
2183 | | - * remove the radiotap header |
---|
2184 | | - * iterator->_max_length was sanity-checked against |
---|
2185 | | - * skb->len by iterator init |
---|
2186 | | - */ |
---|
2187 | | - skb_pull(skb, iterator._max_length); |
---|
2188 | | - |
---|
2189 | 2236 | return true; |
---|
2190 | 2237 | } |
---|
2191 | 2238 | |
---|
.. | .. |
---|
2194 | 2241 | { |
---|
2195 | 2242 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
---|
2196 | 2243 | struct ieee80211_chanctx_conf *chanctx_conf; |
---|
2197 | | - struct ieee80211_radiotap_header *prthdr = |
---|
2198 | | - (struct ieee80211_radiotap_header *)skb->data; |
---|
2199 | 2244 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
---|
2200 | 2245 | struct ieee80211_hdr *hdr; |
---|
2201 | 2246 | struct ieee80211_sub_if_data *tmp_sdata, *sdata; |
---|
.. | .. |
---|
2203 | 2248 | u16 len_rthdr; |
---|
2204 | 2249 | int hdrlen; |
---|
2205 | 2250 | |
---|
2206 | | - /* check for not even having the fixed radiotap header part */ |
---|
2207 | | - if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) |
---|
2208 | | - goto fail; /* too short to be possibly valid */ |
---|
| 2251 | + memset(info, 0, sizeof(*info)); |
---|
| 2252 | + info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS | |
---|
| 2253 | + IEEE80211_TX_CTL_INJECTED; |
---|
2209 | 2254 | |
---|
2210 | | - /* is it a header version we can trust to find length from? */ |
---|
2211 | | - if (unlikely(prthdr->it_version)) |
---|
2212 | | - goto fail; /* only version 0 is supported */ |
---|
| 2255 | + /* Sanity-check the length of the radiotap header */ |
---|
| 2256 | + if (!ieee80211_validate_radiotap_len(skb)) |
---|
| 2257 | + goto fail; |
---|
2213 | 2258 | |
---|
2214 | | - /* then there must be a radiotap header with a length we can use */ |
---|
| 2259 | + /* we now know there is a radiotap header with a length we can use */ |
---|
2215 | 2260 | len_rthdr = ieee80211_get_radiotap_len(skb->data); |
---|
2216 | | - |
---|
2217 | | - /* does the skb contain enough to deliver on the alleged length? */ |
---|
2218 | | - if (unlikely(skb->len < len_rthdr)) |
---|
2219 | | - goto fail; /* skb too short for claimed rt header extent */ |
---|
2220 | 2261 | |
---|
2221 | 2262 | /* |
---|
2222 | 2263 | * fix up the pointers accounting for the radiotap |
---|
.. | .. |
---|
2254 | 2295 | payload[7]); |
---|
2255 | 2296 | } |
---|
2256 | 2297 | |
---|
2257 | | - memset(info, 0, sizeof(*info)); |
---|
2258 | | - |
---|
2259 | | - info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS | |
---|
2260 | | - IEEE80211_TX_CTL_INJECTED; |
---|
| 2298 | + /* |
---|
| 2299 | + * Initialize skb->priority for QoS frames. This is put in the TID field |
---|
| 2300 | + * of the frame before passing it to the driver. |
---|
| 2301 | + */ |
---|
| 2302 | + if (ieee80211_is_data_qos(hdr->frame_control)) { |
---|
| 2303 | + u8 *p = ieee80211_get_qos_ctl(hdr); |
---|
| 2304 | + skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; |
---|
| 2305 | + } |
---|
2261 | 2306 | |
---|
2262 | 2307 | rcu_read_lock(); |
---|
2263 | 2308 | |
---|
.. | .. |
---|
2268 | 2313 | * isn't always enough to find the interface to use; for proper |
---|
2269 | 2314 | * VLAN/WDS support we will need a different mechanism (which |
---|
2270 | 2315 | * likely isn't going to be monitor interfaces). |
---|
| 2316 | + * |
---|
| 2317 | + * This is necessary, for example, for old hostapd versions that |
---|
| 2318 | + * don't use nl80211-based management TX/RX. |
---|
2271 | 2319 | */ |
---|
2272 | 2320 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
2273 | 2321 | |
---|
.. | .. |
---|
2321 | 2369 | |
---|
2322 | 2370 | info->band = chandef->chan->band; |
---|
2323 | 2371 | |
---|
2324 | | - /* process and remove the injection radiotap header */ |
---|
2325 | | - if (!ieee80211_parse_tx_radiotap(local, skb)) |
---|
| 2372 | + /* |
---|
| 2373 | + * Process the radiotap header. This will now take into account the |
---|
| 2374 | + * selected chandef above to accurately set injection rates and |
---|
| 2375 | + * retransmissions. |
---|
| 2376 | + */ |
---|
| 2377 | + if (!ieee80211_parse_tx_radiotap(skb, dev)) |
---|
2326 | 2378 | goto fail_rcu; |
---|
2327 | 2379 | |
---|
2328 | | - ieee80211_xmit(sdata, NULL, skb, 0); |
---|
| 2380 | + /* remove the injection radiotap header */ |
---|
| 2381 | + skb_pull(skb, len_rthdr); |
---|
| 2382 | + |
---|
| 2383 | + ieee80211_xmit(sdata, NULL, skb); |
---|
2329 | 2384 | rcu_read_unlock(); |
---|
2330 | 2385 | |
---|
2331 | 2386 | return NETDEV_TX_OK; |
---|
.. | .. |
---|
2346 | 2401 | skb->data[14] == WLAN_TDLS_SNAP_RFTYPE; |
---|
2347 | 2402 | } |
---|
2348 | 2403 | |
---|
2349 | | -static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata, |
---|
2350 | | - struct sk_buff *skb, |
---|
2351 | | - struct sta_info **sta_out) |
---|
| 2404 | +int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata, |
---|
| 2405 | + struct sk_buff *skb, |
---|
| 2406 | + struct sta_info **sta_out) |
---|
2352 | 2407 | { |
---|
2353 | 2408 | struct sta_info *sta; |
---|
2354 | 2409 | |
---|
.. | .. |
---|
2361 | 2416 | } else if (sdata->wdev.use_4addr) { |
---|
2362 | 2417 | return -ENOLINK; |
---|
2363 | 2418 | } |
---|
2364 | | - /* fall through */ |
---|
| 2419 | + fallthrough; |
---|
2365 | 2420 | case NL80211_IFTYPE_AP: |
---|
2366 | 2421 | case NL80211_IFTYPE_OCB: |
---|
2367 | 2422 | case NL80211_IFTYPE_ADHOC: |
---|
.. | .. |
---|
2415 | 2470 | return 0; |
---|
2416 | 2471 | } |
---|
2417 | 2472 | |
---|
| 2473 | +static u16 ieee80211_store_ack_skb(struct ieee80211_local *local, |
---|
| 2474 | + struct sk_buff *skb, |
---|
| 2475 | + u32 *info_flags, |
---|
| 2476 | + u64 *cookie) |
---|
| 2477 | +{ |
---|
| 2478 | + struct sk_buff *ack_skb; |
---|
| 2479 | + u16 info_id = 0; |
---|
| 2480 | + |
---|
| 2481 | + if (skb->sk) |
---|
| 2482 | + ack_skb = skb_clone_sk(skb); |
---|
| 2483 | + else |
---|
| 2484 | + ack_skb = skb_clone(skb, GFP_ATOMIC); |
---|
| 2485 | + |
---|
| 2486 | + if (ack_skb) { |
---|
| 2487 | + unsigned long flags; |
---|
| 2488 | + int id; |
---|
| 2489 | + |
---|
| 2490 | + spin_lock_irqsave(&local->ack_status_lock, flags); |
---|
| 2491 | + id = idr_alloc(&local->ack_status_frames, ack_skb, |
---|
| 2492 | + 1, 0x2000, GFP_ATOMIC); |
---|
| 2493 | + spin_unlock_irqrestore(&local->ack_status_lock, flags); |
---|
| 2494 | + |
---|
| 2495 | + if (id >= 0) { |
---|
| 2496 | + info_id = id; |
---|
| 2497 | + *info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
---|
| 2498 | + if (cookie) { |
---|
| 2499 | + *cookie = ieee80211_mgmt_tx_cookie(local); |
---|
| 2500 | + IEEE80211_SKB_CB(ack_skb)->ack.cookie = *cookie; |
---|
| 2501 | + } |
---|
| 2502 | + } else { |
---|
| 2503 | + kfree_skb(ack_skb); |
---|
| 2504 | + } |
---|
| 2505 | + } |
---|
| 2506 | + |
---|
| 2507 | + return info_id; |
---|
| 2508 | +} |
---|
| 2509 | + |
---|
2418 | 2510 | /** |
---|
2419 | 2511 | * ieee80211_build_hdr - build 802.11 header in the given frame |
---|
2420 | 2512 | * @sdata: virtual interface to build the header for |
---|
2421 | 2513 | * @skb: the skb to build the header in |
---|
2422 | 2514 | * @info_flags: skb flags to set |
---|
| 2515 | + * @sta: the station pointer |
---|
2423 | 2516 | * @ctrl_flags: info control flags to set |
---|
| 2517 | + * @cookie: cookie pointer to fill (if not %NULL) |
---|
2424 | 2518 | * |
---|
2425 | 2519 | * This function takes the skb with 802.3 header and reformats the header to |
---|
2426 | 2520 | * the appropriate IEEE 802.11 header based on which interface the packet is |
---|
.. | .. |
---|
2436 | 2530 | */ |
---|
2437 | 2531 | static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, |
---|
2438 | 2532 | struct sk_buff *skb, u32 info_flags, |
---|
2439 | | - struct sta_info *sta, u32 ctrl_flags) |
---|
| 2533 | + struct sta_info *sta, u32 ctrl_flags, |
---|
| 2534 | + u64 *cookie) |
---|
2440 | 2535 | { |
---|
2441 | 2536 | struct ieee80211_local *local = sdata->local; |
---|
2442 | 2537 | struct ieee80211_tx_info *info; |
---|
.. | .. |
---|
2459 | 2554 | |
---|
2460 | 2555 | if (IS_ERR(sta)) |
---|
2461 | 2556 | sta = NULL; |
---|
| 2557 | + |
---|
| 2558 | +#ifdef CONFIG_MAC80211_DEBUGFS |
---|
| 2559 | + if (local->force_tx_status) |
---|
| 2560 | + info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
---|
| 2561 | +#endif |
---|
2462 | 2562 | |
---|
2463 | 2563 | /* convert Ethernet header to proper 802.11 header (based on |
---|
2464 | 2564 | * operation mode) */ |
---|
.. | .. |
---|
2488 | 2588 | band = chanctx_conf->def.chan->band; |
---|
2489 | 2589 | if (sdata->wdev.use_4addr) |
---|
2490 | 2590 | break; |
---|
2491 | | - /* fall through */ |
---|
| 2591 | + fallthrough; |
---|
2492 | 2592 | case NL80211_IFTYPE_AP: |
---|
2493 | 2593 | if (sdata->vif.type == NL80211_IFTYPE_AP) |
---|
2494 | 2594 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
---|
.. | .. |
---|
2590 | 2690 | goto free; |
---|
2591 | 2691 | } |
---|
2592 | 2692 | band = chanctx_conf->def.chan->band; |
---|
| 2693 | + |
---|
| 2694 | + /* For injected frames, fill RA right away as nexthop lookup |
---|
| 2695 | + * will be skipped. |
---|
| 2696 | + */ |
---|
| 2697 | + if ((ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP) && |
---|
| 2698 | + is_zero_ether_addr(hdr.addr1)) |
---|
| 2699 | + memcpy(hdr.addr1, skb->data, ETH_ALEN); |
---|
2593 | 2700 | break; |
---|
2594 | 2701 | #endif |
---|
2595 | 2702 | case NL80211_IFTYPE_STATION: |
---|
.. | .. |
---|
2695 | 2802 | goto free; |
---|
2696 | 2803 | } |
---|
2697 | 2804 | |
---|
2698 | | - if (unlikely(!multicast && skb->sk && |
---|
2699 | | - skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) { |
---|
2700 | | - struct sk_buff *ack_skb = skb_clone_sk(skb); |
---|
2701 | | - |
---|
2702 | | - if (ack_skb) { |
---|
2703 | | - unsigned long flags; |
---|
2704 | | - int id; |
---|
2705 | | - |
---|
2706 | | - spin_lock_irqsave(&local->ack_status_lock, flags); |
---|
2707 | | - id = idr_alloc(&local->ack_status_frames, ack_skb, |
---|
2708 | | - 1, 0x10000, GFP_ATOMIC); |
---|
2709 | | - spin_unlock_irqrestore(&local->ack_status_lock, flags); |
---|
2710 | | - |
---|
2711 | | - if (id >= 0) { |
---|
2712 | | - info_id = id; |
---|
2713 | | - info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
---|
2714 | | - } else { |
---|
2715 | | - kfree_skb(ack_skb); |
---|
2716 | | - } |
---|
2717 | | - } |
---|
2718 | | - } |
---|
| 2805 | + if (unlikely(!multicast && ((skb->sk && |
---|
| 2806 | + skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) || |
---|
| 2807 | + ctrl_flags & IEEE80211_TX_CTL_REQ_TX_STATUS))) |
---|
| 2808 | + info_id = ieee80211_store_ack_skb(local, skb, &info_flags, |
---|
| 2809 | + cookie); |
---|
2719 | 2810 | |
---|
2720 | 2811 | /* |
---|
2721 | 2812 | * If the skb is shared we need to obtain our own copy. |
---|
.. | .. |
---|
2944 | 3035 | build.hdr_len = 30; |
---|
2945 | 3036 | break; |
---|
2946 | 3037 | } |
---|
2947 | | - /* fall through */ |
---|
| 3038 | + fallthrough; |
---|
2948 | 3039 | case NL80211_IFTYPE_AP: |
---|
2949 | 3040 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
---|
2950 | 3041 | /* DA BSSID SA */ |
---|
.. | .. |
---|
2984 | 3075 | if (!(build.key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
---|
2985 | 3076 | goto out; |
---|
2986 | 3077 | |
---|
| 3078 | + /* Key is being removed */ |
---|
| 3079 | + if (build.key->flags & KEY_FLAG_TAINTED) |
---|
| 3080 | + goto out; |
---|
| 3081 | + |
---|
2987 | 3082 | switch (build.key->conf.cipher) { |
---|
2988 | 3083 | case WLAN_CIPHER_SUITE_CCMP: |
---|
2989 | 3084 | case WLAN_CIPHER_SUITE_CCMP_256: |
---|
2990 | | - /* add fixed key ID */ |
---|
2991 | | - if (gen_iv) { |
---|
2992 | | - (build.hdr + build.hdr_len)[3] = |
---|
2993 | | - 0x20 | (build.key->conf.keyidx << 6); |
---|
| 3085 | + if (gen_iv) |
---|
2994 | 3086 | build.pn_offs = build.hdr_len; |
---|
2995 | | - } |
---|
2996 | 3087 | if (gen_iv || iv_spc) |
---|
2997 | 3088 | build.hdr_len += IEEE80211_CCMP_HDR_LEN; |
---|
2998 | 3089 | break; |
---|
2999 | 3090 | case WLAN_CIPHER_SUITE_GCMP: |
---|
3000 | 3091 | case WLAN_CIPHER_SUITE_GCMP_256: |
---|
3001 | | - /* add fixed key ID */ |
---|
3002 | | - if (gen_iv) { |
---|
3003 | | - (build.hdr + build.hdr_len)[3] = |
---|
3004 | | - 0x20 | (build.key->conf.keyidx << 6); |
---|
| 3092 | + if (gen_iv) |
---|
3005 | 3093 | build.pn_offs = build.hdr_len; |
---|
3006 | | - } |
---|
3007 | 3094 | if (gen_iv || iv_spc) |
---|
3008 | 3095 | build.hdr_len += IEEE80211_GCMP_HDR_LEN; |
---|
3009 | 3096 | break; |
---|
.. | .. |
---|
3211 | 3298 | int max_frags = local->hw.max_tx_fragments; |
---|
3212 | 3299 | int max_amsdu_len = sta->sta.max_amsdu_len; |
---|
3213 | 3300 | int orig_truesize; |
---|
| 3301 | + u32 flow_idx; |
---|
3214 | 3302 | __be16 len; |
---|
3215 | 3303 | void *data; |
---|
3216 | 3304 | bool ret = false; |
---|
.. | .. |
---|
3219 | 3307 | u16 hdrlen; |
---|
3220 | 3308 | |
---|
3221 | 3309 | if (!ieee80211_hw_check(&local->hw, TX_AMSDU)) |
---|
| 3310 | + return false; |
---|
| 3311 | + |
---|
| 3312 | + if (skb_is_gso(skb)) |
---|
3222 | 3313 | return false; |
---|
3223 | 3314 | |
---|
3224 | 3315 | if (!txq) |
---|
.. | .. |
---|
3232 | 3323 | max_amsdu_len = min_t(int, max_amsdu_len, |
---|
3233 | 3324 | sta->sta.max_rc_amsdu_len); |
---|
3234 | 3325 | |
---|
| 3326 | + if (sta->sta.max_tid_amsdu_len[tid]) |
---|
| 3327 | + max_amsdu_len = min_t(int, max_amsdu_len, |
---|
| 3328 | + sta->sta.max_tid_amsdu_len[tid]); |
---|
| 3329 | + |
---|
| 3330 | + flow_idx = fq_flow_idx(fq, skb); |
---|
| 3331 | + |
---|
3235 | 3332 | spin_lock_bh(&fq->lock); |
---|
3236 | 3333 | |
---|
3237 | 3334 | /* TODO: Ideally aggregation should be done on dequeue to remain |
---|
.. | .. |
---|
3239 | 3336 | */ |
---|
3240 | 3337 | |
---|
3241 | 3338 | tin = &txqi->tin; |
---|
3242 | | - flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func); |
---|
| 3339 | + flow = fq_flow_classify(fq, tin, flow_idx, skb, |
---|
| 3340 | + fq_flow_get_default_func); |
---|
3243 | 3341 | head = skb_peek_tail(&flow->queue); |
---|
3244 | | - if (!head) |
---|
| 3342 | + if (!head || skb_is_gso(head)) |
---|
3245 | 3343 | goto out; |
---|
3246 | 3344 | |
---|
3247 | 3345 | orig_truesize = head->truesize; |
---|
.. | .. |
---|
3263 | 3361 | goto out; |
---|
3264 | 3362 | |
---|
3265 | 3363 | if (max_frags && nfrags > max_frags) |
---|
| 3364 | + goto out; |
---|
| 3365 | + |
---|
| 3366 | + if (!drv_can_aggregate_in_amsdu(local, head, skb)) |
---|
3266 | 3367 | goto out; |
---|
3267 | 3368 | |
---|
3268 | 3369 | if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head)) |
---|
.. | .. |
---|
3373 | 3474 | pn = atomic64_inc_return(&key->conf.tx_pn); |
---|
3374 | 3475 | crypto_hdr[0] = pn; |
---|
3375 | 3476 | crypto_hdr[1] = pn >> 8; |
---|
| 3477 | + crypto_hdr[3] = 0x20 | (key->conf.keyidx << 6); |
---|
3376 | 3478 | crypto_hdr[4] = pn >> 16; |
---|
3377 | 3479 | crypto_hdr[5] = pn >> 24; |
---|
3378 | 3480 | crypto_hdr[6] = pn >> 32; |
---|
.. | .. |
---|
3465 | 3567 | (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0); |
---|
3466 | 3568 | info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT; |
---|
3467 | 3569 | |
---|
| 3570 | +#ifdef CONFIG_MAC80211_DEBUGFS |
---|
| 3571 | + if (local->force_tx_status) |
---|
| 3572 | + info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
---|
| 3573 | +#endif |
---|
| 3574 | + |
---|
3468 | 3575 | if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { |
---|
3469 | 3576 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
---|
3470 | 3577 | *ieee80211_get_qos_ctl(hdr) = tid; |
---|
.. | .. |
---|
3502 | 3609 | struct ieee80211_sub_if_data, u.ap); |
---|
3503 | 3610 | |
---|
3504 | 3611 | __skb_queue_tail(&tx.skbs, skb); |
---|
3505 | | - ieee80211_tx_frags(local, &sdata->vif, &sta->sta, &tx.skbs, false); |
---|
| 3612 | + ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false); |
---|
3506 | 3613 | return true; |
---|
3507 | 3614 | } |
---|
3508 | 3615 | |
---|
.. | .. |
---|
3518 | 3625 | struct ieee80211_tx_info *info; |
---|
3519 | 3626 | struct ieee80211_tx_data tx; |
---|
3520 | 3627 | ieee80211_tx_result r; |
---|
3521 | | - struct ieee80211_vif *vif; |
---|
| 3628 | + struct ieee80211_vif *vif = txq->vif; |
---|
3522 | 3629 | |
---|
| 3630 | + WARN_ON_ONCE(softirq_count() == 0); |
---|
| 3631 | + |
---|
| 3632 | + if (!ieee80211_txq_airtime_check(hw, txq)) |
---|
| 3633 | + return NULL; |
---|
| 3634 | + |
---|
| 3635 | +begin: |
---|
3523 | 3636 | spin_lock_bh(&fq->lock); |
---|
3524 | 3637 | |
---|
3525 | | - if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags)) |
---|
| 3638 | + if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags) || |
---|
| 3639 | + test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags)) |
---|
3526 | 3640 | goto out; |
---|
| 3641 | + |
---|
| 3642 | + if (vif->txqs_stopped[txq->ac]) { |
---|
| 3643 | + set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags); |
---|
| 3644 | + goto out; |
---|
| 3645 | + } |
---|
3527 | 3646 | |
---|
3528 | 3647 | /* Make sure fragments stay together. */ |
---|
3529 | 3648 | skb = __skb_dequeue(&txqi->frags); |
---|
3530 | 3649 | if (skb) |
---|
3531 | 3650 | goto out; |
---|
3532 | 3651 | |
---|
3533 | | -begin: |
---|
3534 | 3652 | skb = fq_tin_dequeue(fq, tin, fq_tin_dequeue_func); |
---|
3535 | 3653 | if (!skb) |
---|
3536 | 3654 | goto out; |
---|
| 3655 | + |
---|
| 3656 | + spin_unlock_bh(&fq->lock); |
---|
3537 | 3657 | |
---|
3538 | 3658 | hdr = (struct ieee80211_hdr *)skb->data; |
---|
3539 | 3659 | info = IEEE80211_SKB_CB(skb); |
---|
.. | .. |
---|
3548 | 3668 | tx.sta = container_of(txq->sta, struct sta_info, sta); |
---|
3549 | 3669 | /* |
---|
3550 | 3670 | * Drop unicast frames to unauthorised stations unless they are |
---|
3551 | | - * EAPOL frames from the local station. |
---|
| 3671 | + * injected frames or EAPOL frames from the local station. |
---|
3552 | 3672 | */ |
---|
3553 | | - if (unlikely(ieee80211_is_data(hdr->frame_control) && |
---|
| 3673 | + if (unlikely(!(info->flags & IEEE80211_TX_CTL_INJECTED) && |
---|
| 3674 | + ieee80211_is_data(hdr->frame_control) && |
---|
3554 | 3675 | !ieee80211_vif_is_mesh(&tx.sdata->vif) && |
---|
3555 | 3676 | tx.sdata->vif.type != NL80211_IFTYPE_OCB && |
---|
3556 | 3677 | !is_multicast_ether_addr(hdr->addr1) && |
---|
.. | .. |
---|
3580 | 3701 | else |
---|
3581 | 3702 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
---|
3582 | 3703 | |
---|
| 3704 | + if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) |
---|
| 3705 | + goto encap_out; |
---|
| 3706 | + |
---|
3583 | 3707 | if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) { |
---|
3584 | 3708 | struct sta_info *sta = container_of(txq->sta, struct sta_info, |
---|
3585 | 3709 | sta); |
---|
.. | .. |
---|
3597 | 3721 | |
---|
3598 | 3722 | skb = __skb_dequeue(&tx.skbs); |
---|
3599 | 3723 | |
---|
3600 | | - if (!skb_queue_empty(&tx.skbs)) |
---|
| 3724 | + if (!skb_queue_empty(&tx.skbs)) { |
---|
| 3725 | + spin_lock_bh(&fq->lock); |
---|
3601 | 3726 | skb_queue_splice_tail(&tx.skbs, &txqi->frags); |
---|
| 3727 | + spin_unlock_bh(&fq->lock); |
---|
| 3728 | + } |
---|
3602 | 3729 | } |
---|
3603 | 3730 | |
---|
3604 | | - if (skb && skb_has_frag_list(skb) && |
---|
| 3731 | + if (skb_has_frag_list(skb) && |
---|
3605 | 3732 | !ieee80211_hw_check(&local->hw, TX_FRAG_LIST)) { |
---|
3606 | 3733 | if (skb_linearize(skb)) { |
---|
3607 | 3734 | ieee80211_free_txskb(&local->hw, skb); |
---|
.. | .. |
---|
3630 | 3757 | case NL80211_IFTYPE_AP_VLAN: |
---|
3631 | 3758 | tx.sdata = container_of(tx.sdata->bss, |
---|
3632 | 3759 | struct ieee80211_sub_if_data, u.ap); |
---|
3633 | | - /* fall through */ |
---|
| 3760 | + fallthrough; |
---|
3634 | 3761 | default: |
---|
3635 | 3762 | vif = &tx.sdata->vif; |
---|
3636 | 3763 | break; |
---|
3637 | 3764 | } |
---|
3638 | 3765 | |
---|
| 3766 | +encap_out: |
---|
3639 | 3767 | IEEE80211_SKB_CB(skb)->control.vif = vif; |
---|
| 3768 | + |
---|
| 3769 | + if (vif && |
---|
| 3770 | + wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { |
---|
| 3771 | + bool ampdu = txq->ac != IEEE80211_AC_VO; |
---|
| 3772 | + u32 airtime; |
---|
| 3773 | + |
---|
| 3774 | + airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, |
---|
| 3775 | + skb->len, ampdu); |
---|
| 3776 | + if (airtime) { |
---|
| 3777 | + airtime = ieee80211_info_set_tx_time_est(info, airtime); |
---|
| 3778 | + ieee80211_sta_update_pending_airtime(local, tx.sta, |
---|
| 3779 | + txq->ac, |
---|
| 3780 | + airtime, |
---|
| 3781 | + false); |
---|
| 3782 | + } |
---|
| 3783 | + } |
---|
| 3784 | + |
---|
| 3785 | + return skb; |
---|
| 3786 | + |
---|
3640 | 3787 | out: |
---|
3641 | 3788 | spin_unlock_bh(&fq->lock); |
---|
3642 | 3789 | |
---|
.. | .. |
---|
3644 | 3791 | } |
---|
3645 | 3792 | EXPORT_SYMBOL(ieee80211_tx_dequeue); |
---|
3646 | 3793 | |
---|
| 3794 | +struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac) |
---|
| 3795 | +{ |
---|
| 3796 | + struct ieee80211_local *local = hw_to_local(hw); |
---|
| 3797 | + struct ieee80211_txq *ret = NULL; |
---|
| 3798 | + struct txq_info *txqi = NULL, *head = NULL; |
---|
| 3799 | + bool found_eligible_txq = false; |
---|
| 3800 | + |
---|
| 3801 | + spin_lock_bh(&local->active_txq_lock[ac]); |
---|
| 3802 | + |
---|
| 3803 | + begin: |
---|
| 3804 | + txqi = list_first_entry_or_null(&local->active_txqs[ac], |
---|
| 3805 | + struct txq_info, |
---|
| 3806 | + schedule_order); |
---|
| 3807 | + if (!txqi) |
---|
| 3808 | + goto out; |
---|
| 3809 | + |
---|
| 3810 | + if (txqi == head) { |
---|
| 3811 | + if (!found_eligible_txq) |
---|
| 3812 | + goto out; |
---|
| 3813 | + else |
---|
| 3814 | + found_eligible_txq = false; |
---|
| 3815 | + } |
---|
| 3816 | + |
---|
| 3817 | + if (!head) |
---|
| 3818 | + head = txqi; |
---|
| 3819 | + |
---|
| 3820 | + if (txqi->txq.sta) { |
---|
| 3821 | + struct sta_info *sta = container_of(txqi->txq.sta, |
---|
| 3822 | + struct sta_info, sta); |
---|
| 3823 | + bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); |
---|
| 3824 | + s64 deficit = sta->airtime[txqi->txq.ac].deficit; |
---|
| 3825 | + |
---|
| 3826 | + if (aql_check) |
---|
| 3827 | + found_eligible_txq = true; |
---|
| 3828 | + |
---|
| 3829 | + if (deficit < 0) |
---|
| 3830 | + sta->airtime[txqi->txq.ac].deficit += |
---|
| 3831 | + sta->airtime_weight; |
---|
| 3832 | + |
---|
| 3833 | + if (deficit < 0 || !aql_check) { |
---|
| 3834 | + list_move_tail(&txqi->schedule_order, |
---|
| 3835 | + &local->active_txqs[txqi->txq.ac]); |
---|
| 3836 | + goto begin; |
---|
| 3837 | + } |
---|
| 3838 | + } |
---|
| 3839 | + |
---|
| 3840 | + |
---|
| 3841 | + if (txqi->schedule_round == local->schedule_round[ac]) |
---|
| 3842 | + goto out; |
---|
| 3843 | + |
---|
| 3844 | + list_del_init(&txqi->schedule_order); |
---|
| 3845 | + txqi->schedule_round = local->schedule_round[ac]; |
---|
| 3846 | + ret = &txqi->txq; |
---|
| 3847 | + |
---|
| 3848 | +out: |
---|
| 3849 | + spin_unlock_bh(&local->active_txq_lock[ac]); |
---|
| 3850 | + return ret; |
---|
| 3851 | +} |
---|
| 3852 | +EXPORT_SYMBOL(ieee80211_next_txq); |
---|
| 3853 | + |
---|
| 3854 | +void __ieee80211_schedule_txq(struct ieee80211_hw *hw, |
---|
| 3855 | + struct ieee80211_txq *txq, |
---|
| 3856 | + bool force) |
---|
| 3857 | +{ |
---|
| 3858 | + struct ieee80211_local *local = hw_to_local(hw); |
---|
| 3859 | + struct txq_info *txqi = to_txq_info(txq); |
---|
| 3860 | + |
---|
| 3861 | + spin_lock_bh(&local->active_txq_lock[txq->ac]); |
---|
| 3862 | + |
---|
| 3863 | + if (list_empty(&txqi->schedule_order) && |
---|
| 3864 | + (force || !skb_queue_empty(&txqi->frags) || |
---|
| 3865 | + txqi->tin.backlog_packets)) { |
---|
| 3866 | + /* If airtime accounting is active, always enqueue STAs at the |
---|
| 3867 | + * head of the list to ensure that they only get moved to the |
---|
| 3868 | + * back by the airtime DRR scheduler once they have a negative |
---|
| 3869 | + * deficit. A station that already has a negative deficit will |
---|
| 3870 | + * get immediately moved to the back of the list on the next |
---|
| 3871 | + * call to ieee80211_next_txq(). |
---|
| 3872 | + */ |
---|
| 3873 | + if (txqi->txq.sta && local->airtime_flags && |
---|
| 3874 | + wiphy_ext_feature_isset(local->hw.wiphy, |
---|
| 3875 | + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) |
---|
| 3876 | + list_add(&txqi->schedule_order, |
---|
| 3877 | + &local->active_txqs[txq->ac]); |
---|
| 3878 | + else |
---|
| 3879 | + list_add_tail(&txqi->schedule_order, |
---|
| 3880 | + &local->active_txqs[txq->ac]); |
---|
| 3881 | + } |
---|
| 3882 | + |
---|
| 3883 | + spin_unlock_bh(&local->active_txq_lock[txq->ac]); |
---|
| 3884 | +} |
---|
| 3885 | +EXPORT_SYMBOL(__ieee80211_schedule_txq); |
---|
| 3886 | + |
---|
| 3887 | +bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw, |
---|
| 3888 | + struct ieee80211_txq *txq) |
---|
| 3889 | +{ |
---|
| 3890 | + struct sta_info *sta; |
---|
| 3891 | + struct ieee80211_local *local = hw_to_local(hw); |
---|
| 3892 | + |
---|
| 3893 | + if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) |
---|
| 3894 | + return true; |
---|
| 3895 | + |
---|
| 3896 | + if (!txq->sta) |
---|
| 3897 | + return true; |
---|
| 3898 | + |
---|
| 3899 | + sta = container_of(txq->sta, struct sta_info, sta); |
---|
| 3900 | + if (atomic_read(&sta->airtime[txq->ac].aql_tx_pending) < |
---|
| 3901 | + sta->airtime[txq->ac].aql_limit_low) |
---|
| 3902 | + return true; |
---|
| 3903 | + |
---|
| 3904 | + if (atomic_read(&local->aql_total_pending_airtime) < |
---|
| 3905 | + local->aql_threshold && |
---|
| 3906 | + atomic_read(&sta->airtime[txq->ac].aql_tx_pending) < |
---|
| 3907 | + sta->airtime[txq->ac].aql_limit_high) |
---|
| 3908 | + return true; |
---|
| 3909 | + |
---|
| 3910 | + return false; |
---|
| 3911 | +} |
---|
| 3912 | +EXPORT_SYMBOL(ieee80211_txq_airtime_check); |
---|
| 3913 | + |
---|
| 3914 | +bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw, |
---|
| 3915 | + struct ieee80211_txq *txq) |
---|
| 3916 | +{ |
---|
| 3917 | + struct ieee80211_local *local = hw_to_local(hw); |
---|
| 3918 | + struct txq_info *iter, *tmp, *txqi = to_txq_info(txq); |
---|
| 3919 | + struct sta_info *sta; |
---|
| 3920 | + u8 ac = txq->ac; |
---|
| 3921 | + |
---|
| 3922 | + spin_lock_bh(&local->active_txq_lock[ac]); |
---|
| 3923 | + |
---|
| 3924 | + if (!txqi->txq.sta) |
---|
| 3925 | + goto out; |
---|
| 3926 | + |
---|
| 3927 | + if (list_empty(&txqi->schedule_order)) |
---|
| 3928 | + goto out; |
---|
| 3929 | + |
---|
| 3930 | + list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac], |
---|
| 3931 | + schedule_order) { |
---|
| 3932 | + if (iter == txqi) |
---|
| 3933 | + break; |
---|
| 3934 | + |
---|
| 3935 | + if (!iter->txq.sta) { |
---|
| 3936 | + list_move_tail(&iter->schedule_order, |
---|
| 3937 | + &local->active_txqs[ac]); |
---|
| 3938 | + continue; |
---|
| 3939 | + } |
---|
| 3940 | + sta = container_of(iter->txq.sta, struct sta_info, sta); |
---|
| 3941 | + if (sta->airtime[ac].deficit < 0) |
---|
| 3942 | + sta->airtime[ac].deficit += sta->airtime_weight; |
---|
| 3943 | + list_move_tail(&iter->schedule_order, &local->active_txqs[ac]); |
---|
| 3944 | + } |
---|
| 3945 | + |
---|
| 3946 | + sta = container_of(txqi->txq.sta, struct sta_info, sta); |
---|
| 3947 | + if (sta->airtime[ac].deficit >= 0) |
---|
| 3948 | + goto out; |
---|
| 3949 | + |
---|
| 3950 | + sta->airtime[ac].deficit += sta->airtime_weight; |
---|
| 3951 | + list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]); |
---|
| 3952 | + spin_unlock_bh(&local->active_txq_lock[ac]); |
---|
| 3953 | + |
---|
| 3954 | + return false; |
---|
| 3955 | +out: |
---|
| 3956 | + if (!list_empty(&txqi->schedule_order)) |
---|
| 3957 | + list_del_init(&txqi->schedule_order); |
---|
| 3958 | + spin_unlock_bh(&local->active_txq_lock[ac]); |
---|
| 3959 | + |
---|
| 3960 | + return true; |
---|
| 3961 | +} |
---|
| 3962 | +EXPORT_SYMBOL(ieee80211_txq_may_transmit); |
---|
| 3963 | + |
---|
| 3964 | +void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac) |
---|
| 3965 | +{ |
---|
| 3966 | + struct ieee80211_local *local = hw_to_local(hw); |
---|
| 3967 | + |
---|
| 3968 | + spin_lock_bh(&local->active_txq_lock[ac]); |
---|
| 3969 | + local->schedule_round[ac]++; |
---|
| 3970 | + spin_unlock_bh(&local->active_txq_lock[ac]); |
---|
| 3971 | +} |
---|
| 3972 | +EXPORT_SYMBOL(ieee80211_txq_schedule_start); |
---|
| 3973 | + |
---|
3647 | 3974 | void __ieee80211_subif_start_xmit(struct sk_buff *skb, |
---|
3648 | 3975 | struct net_device *dev, |
---|
3649 | 3976 | u32 info_flags, |
---|
3650 | | - u32 ctrl_flags) |
---|
| 3977 | + u32 ctrl_flags, |
---|
| 3978 | + u64 *cookie) |
---|
3651 | 3979 | { |
---|
3652 | 3980 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
| 3981 | + struct ieee80211_local *local = sdata->local; |
---|
3653 | 3982 | struct sta_info *sta; |
---|
3654 | 3983 | struct sk_buff *next; |
---|
3655 | 3984 | |
---|
.. | .. |
---|
3663 | 3992 | if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) |
---|
3664 | 3993 | goto out_free; |
---|
3665 | 3994 | |
---|
3666 | | - if (!IS_ERR_OR_NULL(sta)) { |
---|
| 3995 | + if (IS_ERR(sta)) |
---|
| 3996 | + sta = NULL; |
---|
| 3997 | + |
---|
| 3998 | + if (local->ops->wake_tx_queue) { |
---|
| 3999 | + u16 queue = __ieee80211_select_queue(sdata, sta, skb); |
---|
| 4000 | + skb_set_queue_mapping(skb, queue); |
---|
| 4001 | + skb_get_hash(skb); |
---|
| 4002 | + } |
---|
| 4003 | + |
---|
| 4004 | + if (sta) { |
---|
3667 | 4005 | struct ieee80211_fast_tx *fast_tx; |
---|
3668 | 4006 | |
---|
3669 | | - /* We need a bit of data queued to build aggregates properly, so |
---|
3670 | | - * instruct the TCP stack to allow more than a single ms of data |
---|
3671 | | - * to be queued in the stack. The value is a bit-shift of 1 |
---|
3672 | | - * second, so 7 is ~8ms of queued data. Only affects local TCP |
---|
3673 | | - * sockets. |
---|
3674 | | - */ |
---|
3675 | | - sk_pacing_shift_update(skb->sk, 7); |
---|
| 4007 | + sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift); |
---|
3676 | 4008 | |
---|
3677 | 4009 | fast_tx = rcu_dereference(sta->fast_tx); |
---|
3678 | 4010 | |
---|
.. | .. |
---|
3710 | 4042 | } |
---|
3711 | 4043 | } |
---|
3712 | 4044 | |
---|
3713 | | - next = skb; |
---|
3714 | | - while (next) { |
---|
3715 | | - skb = next; |
---|
3716 | | - next = skb->next; |
---|
| 4045 | + skb_list_walk_safe(skb, skb, next) { |
---|
| 4046 | + skb_mark_not_on_list(skb); |
---|
3717 | 4047 | |
---|
3718 | | - skb->prev = NULL; |
---|
3719 | | - skb->next = NULL; |
---|
| 4048 | + if (skb->protocol == sdata->control_port_protocol) |
---|
| 4049 | + ctrl_flags |= IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP; |
---|
3720 | 4050 | |
---|
3721 | 4051 | skb = ieee80211_build_hdr(sdata, skb, info_flags, |
---|
3722 | | - sta, ctrl_flags); |
---|
3723 | | - if (IS_ERR(skb)) |
---|
| 4052 | + sta, ctrl_flags, cookie); |
---|
| 4053 | + if (IS_ERR(skb)) { |
---|
| 4054 | + kfree_skb_list(next); |
---|
3724 | 4055 | goto out; |
---|
| 4056 | + } |
---|
3725 | 4057 | |
---|
3726 | 4058 | ieee80211_tx_stats(dev, skb->len); |
---|
3727 | 4059 | |
---|
3728 | | - ieee80211_xmit(sdata, sta, skb, 0); |
---|
| 4060 | + ieee80211_xmit(sdata, sta, skb); |
---|
3729 | 4061 | } |
---|
3730 | 4062 | goto out; |
---|
3731 | 4063 | out_free: |
---|
.. | .. |
---|
3766 | 4098 | return false; |
---|
3767 | 4099 | if (sdata->wdev.use_4addr) |
---|
3768 | 4100 | return false; |
---|
3769 | | - /* fall through */ |
---|
| 4101 | + fallthrough; |
---|
3770 | 4102 | case NL80211_IFTYPE_AP: |
---|
3771 | 4103 | /* check runtime toggle for this bss */ |
---|
3772 | 4104 | if (!sdata->bss->multicast_to_unicast) |
---|
.. | .. |
---|
3859 | 4191 | __skb_queue_head_init(&queue); |
---|
3860 | 4192 | ieee80211_convert_to_unicast(skb, dev, &queue); |
---|
3861 | 4193 | while ((skb = __skb_dequeue(&queue))) |
---|
3862 | | - __ieee80211_subif_start_xmit(skb, dev, 0, 0); |
---|
| 4194 | + __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); |
---|
3863 | 4195 | } else { |
---|
3864 | | - __ieee80211_subif_start_xmit(skb, dev, 0, 0); |
---|
| 4196 | + __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); |
---|
3865 | 4197 | } |
---|
| 4198 | + |
---|
| 4199 | + return NETDEV_TX_OK; |
---|
| 4200 | +} |
---|
| 4201 | + |
---|
| 4202 | +static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, |
---|
| 4203 | + struct sk_buff *skb, int led_len, |
---|
| 4204 | + struct sta_info *sta, |
---|
| 4205 | + bool txpending) |
---|
| 4206 | +{ |
---|
| 4207 | + struct ieee80211_local *local = sdata->local; |
---|
| 4208 | + struct ieee80211_tx_control control = {}; |
---|
| 4209 | + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
---|
| 4210 | + struct ieee80211_sta *pubsta = NULL; |
---|
| 4211 | + unsigned long flags; |
---|
| 4212 | + int q = info->hw_queue; |
---|
| 4213 | + |
---|
| 4214 | + if (ieee80211_queue_skb(local, sdata, sta, skb)) |
---|
| 4215 | + return true; |
---|
| 4216 | + |
---|
| 4217 | + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
---|
| 4218 | + |
---|
| 4219 | + if (local->queue_stop_reasons[q] || |
---|
| 4220 | + (!txpending && !skb_queue_empty(&local->pending[q]))) { |
---|
| 4221 | + if (txpending) |
---|
| 4222 | + skb_queue_head(&local->pending[q], skb); |
---|
| 4223 | + else |
---|
| 4224 | + skb_queue_tail(&local->pending[q], skb); |
---|
| 4225 | + |
---|
| 4226 | + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
---|
| 4227 | + |
---|
| 4228 | + return false; |
---|
| 4229 | + } |
---|
| 4230 | + |
---|
| 4231 | + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
---|
| 4232 | + |
---|
| 4233 | + if (sta && sta->uploaded) |
---|
| 4234 | + pubsta = &sta->sta; |
---|
| 4235 | + |
---|
| 4236 | + control.sta = pubsta; |
---|
| 4237 | + |
---|
| 4238 | + drv_tx(local, &control, skb); |
---|
| 4239 | + |
---|
| 4240 | + return true; |
---|
| 4241 | +} |
---|
| 4242 | + |
---|
| 4243 | +static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, |
---|
| 4244 | + struct net_device *dev, struct sta_info *sta, |
---|
| 4245 | + struct ieee80211_key *key, struct sk_buff *skb) |
---|
| 4246 | +{ |
---|
| 4247 | + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
---|
| 4248 | + struct ieee80211_local *local = sdata->local; |
---|
| 4249 | + struct tid_ampdu_tx *tid_tx; |
---|
| 4250 | + u8 tid; |
---|
| 4251 | + |
---|
| 4252 | + if (local->ops->wake_tx_queue) { |
---|
| 4253 | + u16 queue = __ieee80211_select_queue(sdata, sta, skb); |
---|
| 4254 | + skb_set_queue_mapping(skb, queue); |
---|
| 4255 | + skb_get_hash(skb); |
---|
| 4256 | + } |
---|
| 4257 | + |
---|
| 4258 | + if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) && |
---|
| 4259 | + test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) |
---|
| 4260 | + goto out_free; |
---|
| 4261 | + |
---|
| 4262 | + memset(info, 0, sizeof(*info)); |
---|
| 4263 | + |
---|
| 4264 | + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
---|
| 4265 | + tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); |
---|
| 4266 | + if (tid_tx) { |
---|
| 4267 | + if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { |
---|
| 4268 | + /* fall back to non-offload slow path */ |
---|
| 4269 | + __ieee80211_subif_start_xmit(skb, dev, 0, 0, NULL); |
---|
| 4270 | + return; |
---|
| 4271 | + } |
---|
| 4272 | + |
---|
| 4273 | + info->flags |= IEEE80211_TX_CTL_AMPDU; |
---|
| 4274 | + if (tid_tx->timeout) |
---|
| 4275 | + tid_tx->last_tx = jiffies; |
---|
| 4276 | + } |
---|
| 4277 | + |
---|
| 4278 | + if (unlikely(skb->sk && |
---|
| 4279 | + skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) |
---|
| 4280 | + info->ack_frame_id = ieee80211_store_ack_skb(local, skb, |
---|
| 4281 | + &info->flags, NULL); |
---|
| 4282 | + |
---|
| 4283 | + info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; |
---|
| 4284 | + |
---|
| 4285 | + ieee80211_tx_stats(dev, skb->len); |
---|
| 4286 | + |
---|
| 4287 | + sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; |
---|
| 4288 | + sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; |
---|
| 4289 | + |
---|
| 4290 | + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
---|
| 4291 | + sdata = container_of(sdata->bss, |
---|
| 4292 | + struct ieee80211_sub_if_data, u.ap); |
---|
| 4293 | + |
---|
| 4294 | + info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP; |
---|
| 4295 | + info->control.vif = &sdata->vif; |
---|
| 4296 | + |
---|
| 4297 | + if (key) |
---|
| 4298 | + info->control.hw_key = &key->conf; |
---|
| 4299 | + |
---|
| 4300 | + ieee80211_tx_8023(sdata, skb, skb->len, sta, false); |
---|
| 4301 | + |
---|
| 4302 | + return; |
---|
| 4303 | + |
---|
| 4304 | +out_free: |
---|
| 4305 | + kfree_skb(skb); |
---|
| 4306 | +} |
---|
| 4307 | + |
---|
| 4308 | +netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, |
---|
| 4309 | + struct net_device *dev) |
---|
| 4310 | +{ |
---|
| 4311 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
| 4312 | + struct ethhdr *ehdr = (struct ethhdr *)skb->data; |
---|
| 4313 | + struct ieee80211_key *key; |
---|
| 4314 | + struct sta_info *sta; |
---|
| 4315 | + |
---|
| 4316 | + if (unlikely(skb->len < ETH_HLEN)) { |
---|
| 4317 | + kfree_skb(skb); |
---|
| 4318 | + return NETDEV_TX_OK; |
---|
| 4319 | + } |
---|
| 4320 | + |
---|
| 4321 | + rcu_read_lock(); |
---|
| 4322 | + |
---|
| 4323 | + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { |
---|
| 4324 | + kfree_skb(skb); |
---|
| 4325 | + goto out; |
---|
| 4326 | + } |
---|
| 4327 | + |
---|
| 4328 | + if (unlikely(IS_ERR_OR_NULL(sta) || !sta->uploaded || |
---|
| 4329 | + !test_sta_flag(sta, WLAN_STA_AUTHORIZED) || |
---|
| 4330 | + sdata->control_port_protocol == ehdr->h_proto)) |
---|
| 4331 | + goto skip_offload; |
---|
| 4332 | + |
---|
| 4333 | + key = rcu_dereference(sta->ptk[sta->ptk_idx]); |
---|
| 4334 | + if (!key) |
---|
| 4335 | + key = rcu_dereference(sdata->default_unicast_key); |
---|
| 4336 | + |
---|
| 4337 | + if (key && (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) || |
---|
| 4338 | + key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)) |
---|
| 4339 | + goto skip_offload; |
---|
| 4340 | + |
---|
| 4341 | + ieee80211_8023_xmit(sdata, dev, sta, key, skb); |
---|
| 4342 | + goto out; |
---|
| 4343 | + |
---|
| 4344 | +skip_offload: |
---|
| 4345 | + ieee80211_subif_start_xmit(skb, dev); |
---|
| 4346 | +out: |
---|
| 4347 | + rcu_read_unlock(); |
---|
3866 | 4348 | |
---|
3867 | 4349 | return NETDEV_TX_OK; |
---|
3868 | 4350 | } |
---|
.. | .. |
---|
3886 | 4368 | goto out; |
---|
3887 | 4369 | } |
---|
3888 | 4370 | |
---|
3889 | | - skb = ieee80211_build_hdr(sdata, skb, info_flags, sta, 0); |
---|
| 4371 | + skb = ieee80211_build_hdr(sdata, skb, info_flags, sta, 0, NULL); |
---|
3890 | 4372 | if (IS_ERR(skb)) |
---|
3891 | 4373 | goto out; |
---|
3892 | 4374 | |
---|
.. | .. |
---|
3937 | 4419 | |
---|
3938 | 4420 | sdata = vif_to_sdata(info->control.vif); |
---|
3939 | 4421 | |
---|
3940 | | - if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { |
---|
| 4422 | + if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) { |
---|
3941 | 4423 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
---|
3942 | 4424 | if (unlikely(!chanctx_conf)) { |
---|
3943 | 4425 | dev_kfree_skb(skb); |
---|
3944 | 4426 | return true; |
---|
3945 | 4427 | } |
---|
3946 | 4428 | info->band = chanctx_conf->def.chan->band; |
---|
3947 | | - result = ieee80211_tx(sdata, NULL, skb, true, 0); |
---|
| 4429 | + result = ieee80211_tx(sdata, NULL, skb, true); |
---|
| 4430 | + } else if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { |
---|
| 4431 | + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { |
---|
| 4432 | + dev_kfree_skb(skb); |
---|
| 4433 | + return true; |
---|
| 4434 | + } |
---|
| 4435 | + |
---|
| 4436 | + if (IS_ERR(sta) || (sta && !sta->uploaded)) |
---|
| 4437 | + sta = NULL; |
---|
| 4438 | + |
---|
| 4439 | + result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true); |
---|
3948 | 4440 | } else { |
---|
3949 | 4441 | struct sk_buff_head skbs; |
---|
3950 | 4442 | |
---|
.. | .. |
---|
4100 | 4592 | return 0; |
---|
4101 | 4593 | } |
---|
4102 | 4594 | |
---|
4103 | | -static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata, |
---|
4104 | | - struct beacon_data *beacon) |
---|
| 4595 | +static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata, |
---|
| 4596 | + struct beacon_data *beacon) |
---|
4105 | 4597 | { |
---|
4106 | 4598 | struct probe_resp *resp; |
---|
4107 | 4599 | u8 *beacon_data; |
---|
4108 | 4600 | size_t beacon_data_len; |
---|
4109 | 4601 | int i; |
---|
4110 | | - u8 count = beacon->csa_current_counter; |
---|
| 4602 | + u8 count = beacon->cntdwn_current_counter; |
---|
4111 | 4603 | |
---|
4112 | 4604 | switch (sdata->vif.type) { |
---|
4113 | 4605 | case NL80211_IFTYPE_AP: |
---|
.. | .. |
---|
4127 | 4619 | } |
---|
4128 | 4620 | |
---|
4129 | 4621 | rcu_read_lock(); |
---|
4130 | | - for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) { |
---|
| 4622 | + for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; ++i) { |
---|
4131 | 4623 | resp = rcu_dereference(sdata->u.ap.probe_resp); |
---|
4132 | 4624 | |
---|
4133 | | - if (beacon->csa_counter_offsets[i]) { |
---|
4134 | | - if (WARN_ON_ONCE(beacon->csa_counter_offsets[i] >= |
---|
| 4625 | + if (beacon->cntdwn_counter_offsets[i]) { |
---|
| 4626 | + if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[i] >= |
---|
4135 | 4627 | beacon_data_len)) { |
---|
4136 | 4628 | rcu_read_unlock(); |
---|
4137 | 4629 | return; |
---|
4138 | 4630 | } |
---|
4139 | 4631 | |
---|
4140 | | - beacon_data[beacon->csa_counter_offsets[i]] = count; |
---|
| 4632 | + beacon_data[beacon->cntdwn_counter_offsets[i]] = count; |
---|
4141 | 4633 | } |
---|
4142 | 4634 | |
---|
4143 | 4635 | if (sdata->vif.type == NL80211_IFTYPE_AP && resp) |
---|
4144 | | - resp->data[resp->csa_counter_offsets[i]] = count; |
---|
| 4636 | + resp->data[resp->cntdwn_counter_offsets[i]] = count; |
---|
4145 | 4637 | } |
---|
4146 | 4638 | rcu_read_unlock(); |
---|
4147 | 4639 | } |
---|
4148 | 4640 | |
---|
4149 | | -static u8 __ieee80211_csa_update_counter(struct beacon_data *beacon) |
---|
| 4641 | +static u8 __ieee80211_beacon_update_cntdwn(struct beacon_data *beacon) |
---|
4150 | 4642 | { |
---|
4151 | | - beacon->csa_current_counter--; |
---|
| 4643 | + beacon->cntdwn_current_counter--; |
---|
4152 | 4644 | |
---|
4153 | 4645 | /* the counter should never reach 0 */ |
---|
4154 | | - WARN_ON_ONCE(!beacon->csa_current_counter); |
---|
| 4646 | + WARN_ON_ONCE(!beacon->cntdwn_current_counter); |
---|
4155 | 4647 | |
---|
4156 | | - return beacon->csa_current_counter; |
---|
| 4648 | + return beacon->cntdwn_current_counter; |
---|
4157 | 4649 | } |
---|
4158 | 4650 | |
---|
4159 | | -u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif) |
---|
| 4651 | +u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif) |
---|
4160 | 4652 | { |
---|
4161 | 4653 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
---|
4162 | 4654 | struct beacon_data *beacon = NULL; |
---|
.. | .. |
---|
4174 | 4666 | if (!beacon) |
---|
4175 | 4667 | goto unlock; |
---|
4176 | 4668 | |
---|
4177 | | - count = __ieee80211_csa_update_counter(beacon); |
---|
| 4669 | + count = __ieee80211_beacon_update_cntdwn(beacon); |
---|
4178 | 4670 | |
---|
4179 | 4671 | unlock: |
---|
4180 | 4672 | rcu_read_unlock(); |
---|
4181 | 4673 | return count; |
---|
4182 | 4674 | } |
---|
4183 | | -EXPORT_SYMBOL(ieee80211_csa_update_counter); |
---|
| 4675 | +EXPORT_SYMBOL(ieee80211_beacon_update_cntdwn); |
---|
4184 | 4676 | |
---|
4185 | | -void ieee80211_csa_set_counter(struct ieee80211_vif *vif, u8 counter) |
---|
| 4677 | +void ieee80211_beacon_set_cntdwn(struct ieee80211_vif *vif, u8 counter) |
---|
4186 | 4678 | { |
---|
4187 | 4679 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
---|
4188 | 4680 | struct beacon_data *beacon = NULL; |
---|
.. | .. |
---|
4199 | 4691 | if (!beacon) |
---|
4200 | 4692 | goto unlock; |
---|
4201 | 4693 | |
---|
4202 | | - if (counter < beacon->csa_current_counter) |
---|
4203 | | - beacon->csa_current_counter = counter; |
---|
| 4694 | + if (counter < beacon->cntdwn_current_counter) |
---|
| 4695 | + beacon->cntdwn_current_counter = counter; |
---|
4204 | 4696 | |
---|
4205 | 4697 | unlock: |
---|
4206 | 4698 | rcu_read_unlock(); |
---|
4207 | 4699 | } |
---|
4208 | | -EXPORT_SYMBOL(ieee80211_csa_set_counter); |
---|
| 4700 | +EXPORT_SYMBOL(ieee80211_beacon_set_cntdwn); |
---|
4209 | 4701 | |
---|
4210 | | -bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) |
---|
| 4702 | +bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif) |
---|
4211 | 4703 | { |
---|
4212 | 4704 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
---|
4213 | 4705 | struct beacon_data *beacon = NULL; |
---|
.. | .. |
---|
4250 | 4742 | goto out; |
---|
4251 | 4743 | } |
---|
4252 | 4744 | |
---|
4253 | | - if (!beacon->csa_counter_offsets[0]) |
---|
| 4745 | + if (!beacon->cntdwn_counter_offsets[0]) |
---|
4254 | 4746 | goto out; |
---|
4255 | 4747 | |
---|
4256 | | - if (WARN_ON_ONCE(beacon->csa_counter_offsets[0] > beacon_data_len)) |
---|
| 4748 | + if (WARN_ON_ONCE(beacon->cntdwn_counter_offsets[0] > beacon_data_len)) |
---|
4257 | 4749 | goto out; |
---|
4258 | 4750 | |
---|
4259 | | - if (beacon_data[beacon->csa_counter_offsets[0]] == 1) |
---|
| 4751 | + if (beacon_data[beacon->cntdwn_counter_offsets[0]] == 1) |
---|
4260 | 4752 | ret = true; |
---|
| 4753 | + |
---|
4261 | 4754 | out: |
---|
4262 | 4755 | rcu_read_unlock(); |
---|
4263 | 4756 | |
---|
4264 | 4757 | return ret; |
---|
4265 | 4758 | } |
---|
4266 | | -EXPORT_SYMBOL(ieee80211_csa_is_complete); |
---|
| 4759 | +EXPORT_SYMBOL(ieee80211_beacon_cntdwn_is_complete); |
---|
| 4760 | + |
---|
| 4761 | +static int ieee80211_beacon_protect(struct sk_buff *skb, |
---|
| 4762 | + struct ieee80211_local *local, |
---|
| 4763 | + struct ieee80211_sub_if_data *sdata) |
---|
| 4764 | +{ |
---|
| 4765 | + ieee80211_tx_result res; |
---|
| 4766 | + struct ieee80211_tx_data tx; |
---|
| 4767 | + struct sk_buff *check_skb; |
---|
| 4768 | + |
---|
| 4769 | + memset(&tx, 0, sizeof(tx)); |
---|
| 4770 | + tx.key = rcu_dereference(sdata->default_beacon_key); |
---|
| 4771 | + if (!tx.key) |
---|
| 4772 | + return 0; |
---|
| 4773 | + tx.local = local; |
---|
| 4774 | + tx.sdata = sdata; |
---|
| 4775 | + __skb_queue_head_init(&tx.skbs); |
---|
| 4776 | + __skb_queue_tail(&tx.skbs, skb); |
---|
| 4777 | + res = ieee80211_tx_h_encrypt(&tx); |
---|
| 4778 | + check_skb = __skb_dequeue(&tx.skbs); |
---|
| 4779 | + /* we may crash after this, but it'd be a bug in crypto */ |
---|
| 4780 | + WARN_ON(check_skb != skb); |
---|
| 4781 | + if (WARN_ON_ONCE(res != TX_CONTINUE)) |
---|
| 4782 | + return -EINVAL; |
---|
| 4783 | + |
---|
| 4784 | + return 0; |
---|
| 4785 | +} |
---|
4267 | 4786 | |
---|
4268 | 4787 | static struct sk_buff * |
---|
4269 | 4788 | __ieee80211_beacon_get(struct ieee80211_hw *hw, |
---|
.. | .. |
---|
4297 | 4816 | |
---|
4298 | 4817 | beacon = rcu_dereference(ap->beacon); |
---|
4299 | 4818 | if (beacon) { |
---|
4300 | | - if (beacon->csa_counter_offsets[0]) { |
---|
| 4819 | + if (beacon->cntdwn_counter_offsets[0]) { |
---|
4301 | 4820 | if (!is_template) |
---|
4302 | | - __ieee80211_csa_update_counter(beacon); |
---|
| 4821 | + ieee80211_beacon_update_cntdwn(vif); |
---|
4303 | 4822 | |
---|
4304 | | - ieee80211_set_csa(sdata, beacon); |
---|
| 4823 | + ieee80211_set_beacon_cntdwn(sdata, beacon); |
---|
4305 | 4824 | } |
---|
4306 | 4825 | |
---|
4307 | 4826 | /* |
---|
.. | .. |
---|
4332 | 4851 | if (beacon->tail) |
---|
4333 | 4852 | skb_put_data(skb, beacon->tail, |
---|
4334 | 4853 | beacon->tail_len); |
---|
| 4854 | + |
---|
| 4855 | + if (ieee80211_beacon_protect(skb, local, sdata) < 0) |
---|
| 4856 | + goto out; |
---|
4335 | 4857 | } else |
---|
4336 | 4858 | goto out; |
---|
4337 | 4859 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
---|
.. | .. |
---|
4342 | 4864 | if (!beacon) |
---|
4343 | 4865 | goto out; |
---|
4344 | 4866 | |
---|
4345 | | - if (beacon->csa_counter_offsets[0]) { |
---|
| 4867 | + if (beacon->cntdwn_counter_offsets[0]) { |
---|
4346 | 4868 | if (!is_template) |
---|
4347 | | - __ieee80211_csa_update_counter(beacon); |
---|
| 4869 | + __ieee80211_beacon_update_cntdwn(beacon); |
---|
4348 | 4870 | |
---|
4349 | | - ieee80211_set_csa(sdata, beacon); |
---|
| 4871 | + ieee80211_set_beacon_cntdwn(sdata, beacon); |
---|
4350 | 4872 | } |
---|
4351 | 4873 | |
---|
4352 | 4874 | skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + |
---|
.. | .. |
---|
4366 | 4888 | if (!beacon) |
---|
4367 | 4889 | goto out; |
---|
4368 | 4890 | |
---|
4369 | | - if (beacon->csa_counter_offsets[0]) { |
---|
| 4891 | + if (beacon->cntdwn_counter_offsets[0]) { |
---|
4370 | 4892 | if (!is_template) |
---|
4371 | 4893 | /* TODO: For mesh csa_counter is in TU, so |
---|
4372 | 4894 | * decrementing it by one isn't correct, but |
---|
4373 | 4895 | * for now we leave it consistent with overall |
---|
4374 | 4896 | * mac80211's behavior. |
---|
4375 | 4897 | */ |
---|
4376 | | - __ieee80211_csa_update_counter(beacon); |
---|
| 4898 | + __ieee80211_beacon_update_cntdwn(beacon); |
---|
4377 | 4899 | |
---|
4378 | | - ieee80211_set_csa(sdata, beacon); |
---|
| 4900 | + ieee80211_set_beacon_cntdwn(sdata, beacon); |
---|
4379 | 4901 | } |
---|
4380 | 4902 | |
---|
4381 | 4903 | if (ifmsh->sync_ops) |
---|
.. | .. |
---|
4407 | 4929 | if (offs && beacon) { |
---|
4408 | 4930 | int i; |
---|
4409 | 4931 | |
---|
4410 | | - for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) { |
---|
4411 | | - u16 csa_off = beacon->csa_counter_offsets[i]; |
---|
| 4932 | + for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) { |
---|
| 4933 | + u16 csa_off = beacon->cntdwn_counter_offsets[i]; |
---|
4412 | 4934 | |
---|
4413 | 4935 | if (!csa_off) |
---|
4414 | 4936 | continue; |
---|
4415 | 4937 | |
---|
4416 | | - offs->csa_counter_offs[i] = csa_off_base + csa_off; |
---|
| 4938 | + offs->cntdwn_counter_offs[i] = csa_off_base + csa_off; |
---|
4417 | 4939 | } |
---|
4418 | 4940 | } |
---|
4419 | 4941 | |
---|
.. | .. |
---|
4431 | 4953 | txrc.bss_conf = &sdata->vif.bss_conf; |
---|
4432 | 4954 | txrc.skb = skb; |
---|
4433 | 4955 | txrc.reported_rate.idx = -1; |
---|
4434 | | - txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; |
---|
| 4956 | + if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band]) |
---|
| 4957 | + txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band]; |
---|
| 4958 | + else |
---|
| 4959 | + txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; |
---|
4435 | 4960 | txrc.bss = true; |
---|
4436 | 4961 | rate_control_get_rate(sdata, NULL, &txrc); |
---|
4437 | 4962 | |
---|
.. | .. |
---|
4488 | 5013 | if (!sband) |
---|
4489 | 5014 | return bcn; |
---|
4490 | 5015 | |
---|
4491 | | - ieee80211_tx_monitor(hw_to_local(hw), copy, sband, 1, shift, false); |
---|
| 5016 | + ieee80211_tx_monitor(hw_to_local(hw), copy, sband, 1, shift, false, |
---|
| 5017 | + NULL); |
---|
4492 | 5018 | |
---|
4493 | 5019 | return bcn; |
---|
4494 | 5020 | } |
---|
.. | .. |
---|
4528 | 5054 | } |
---|
4529 | 5055 | EXPORT_SYMBOL(ieee80211_proberesp_get); |
---|
4530 | 5056 | |
---|
| 5057 | +struct sk_buff *ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw, |
---|
| 5058 | + struct ieee80211_vif *vif) |
---|
| 5059 | +{ |
---|
| 5060 | + struct sk_buff *skb = NULL; |
---|
| 5061 | + struct fils_discovery_data *tmpl = NULL; |
---|
| 5062 | + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
---|
| 5063 | + |
---|
| 5064 | + if (sdata->vif.type != NL80211_IFTYPE_AP) |
---|
| 5065 | + return NULL; |
---|
| 5066 | + |
---|
| 5067 | + rcu_read_lock(); |
---|
| 5068 | + tmpl = rcu_dereference(sdata->u.ap.fils_discovery); |
---|
| 5069 | + if (!tmpl) { |
---|
| 5070 | + rcu_read_unlock(); |
---|
| 5071 | + return NULL; |
---|
| 5072 | + } |
---|
| 5073 | + |
---|
| 5074 | + skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len); |
---|
| 5075 | + if (skb) { |
---|
| 5076 | + skb_reserve(skb, sdata->local->hw.extra_tx_headroom); |
---|
| 5077 | + skb_put_data(skb, tmpl->data, tmpl->len); |
---|
| 5078 | + } |
---|
| 5079 | + |
---|
| 5080 | + rcu_read_unlock(); |
---|
| 5081 | + return skb; |
---|
| 5082 | +} |
---|
| 5083 | +EXPORT_SYMBOL(ieee80211_get_fils_discovery_tmpl); |
---|
| 5084 | + |
---|
| 5085 | +struct sk_buff * |
---|
| 5086 | +ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw, |
---|
| 5087 | + struct ieee80211_vif *vif) |
---|
| 5088 | +{ |
---|
| 5089 | + struct sk_buff *skb = NULL; |
---|
| 5090 | + struct unsol_bcast_probe_resp_data *tmpl = NULL; |
---|
| 5091 | + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
---|
| 5092 | + |
---|
| 5093 | + if (sdata->vif.type != NL80211_IFTYPE_AP) |
---|
| 5094 | + return NULL; |
---|
| 5095 | + |
---|
| 5096 | + rcu_read_lock(); |
---|
| 5097 | + tmpl = rcu_dereference(sdata->u.ap.unsol_bcast_probe_resp); |
---|
| 5098 | + if (!tmpl) { |
---|
| 5099 | + rcu_read_unlock(); |
---|
| 5100 | + return NULL; |
---|
| 5101 | + } |
---|
| 5102 | + |
---|
| 5103 | + skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + tmpl->len); |
---|
| 5104 | + if (skb) { |
---|
| 5105 | + skb_reserve(skb, sdata->local->hw.extra_tx_headroom); |
---|
| 5106 | + skb_put_data(skb, tmpl->data, tmpl->len); |
---|
| 5107 | + } |
---|
| 5108 | + |
---|
| 5109 | + rcu_read_unlock(); |
---|
| 5110 | + return skb; |
---|
| 5111 | +} |
---|
| 5112 | +EXPORT_SYMBOL(ieee80211_get_unsol_bcast_probe_resp_tmpl); |
---|
| 5113 | + |
---|
4531 | 5114 | struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, |
---|
4532 | 5115 | struct ieee80211_vif *vif) |
---|
4533 | 5116 | { |
---|
.. | .. |
---|
4553 | 5136 | pspoll = skb_put_zero(skb, sizeof(*pspoll)); |
---|
4554 | 5137 | pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | |
---|
4555 | 5138 | IEEE80211_STYPE_PSPOLL); |
---|
4556 | | - pspoll->aid = cpu_to_le16(ifmgd->aid); |
---|
| 5139 | + pspoll->aid = cpu_to_le16(sdata->vif.bss_conf.aid); |
---|
4557 | 5140 | |
---|
4558 | 5141 | /* aid in PS-Poll has its two MSBs each set to 1 */ |
---|
4559 | 5142 | pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); |
---|
.. | .. |
---|
4604 | 5187 | IEEE80211_STYPE_NULLFUNC | |
---|
4605 | 5188 | IEEE80211_FCTL_TODS); |
---|
4606 | 5189 | if (qos) { |
---|
4607 | | - __le16 qos = cpu_to_le16(7); |
---|
| 5190 | + __le16 qoshdr = cpu_to_le16(7); |
---|
4608 | 5191 | |
---|
4609 | 5192 | BUILD_BUG_ON((IEEE80211_STYPE_QOS_NULLFUNC | |
---|
4610 | 5193 | IEEE80211_STYPE_NULLFUNC) != |
---|
.. | .. |
---|
4613 | 5196 | cpu_to_le16(IEEE80211_STYPE_QOS_NULLFUNC); |
---|
4614 | 5197 | skb->priority = 7; |
---|
4615 | 5198 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); |
---|
4616 | | - skb_put_data(skb, &qos, sizeof(qos)); |
---|
| 5199 | + skb_put_data(skb, &qoshdr, sizeof(qoshdr)); |
---|
4617 | 5200 | } |
---|
4618 | 5201 | |
---|
4619 | 5202 | memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN); |
---|
.. | .. |
---|
4860 | 5443 | |
---|
4861 | 5444 | void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, |
---|
4862 | 5445 | struct sk_buff *skb, int tid, |
---|
4863 | | - enum nl80211_band band, u32 txdata_flags) |
---|
| 5446 | + enum nl80211_band band) |
---|
4864 | 5447 | { |
---|
4865 | 5448 | int ac = ieee80211_ac_from_tid(tid); |
---|
4866 | 5449 | |
---|
.. | .. |
---|
4877 | 5460 | */ |
---|
4878 | 5461 | local_bh_disable(); |
---|
4879 | 5462 | IEEE80211_SKB_CB(skb)->band = band; |
---|
4880 | | - ieee80211_xmit(sdata, NULL, skb, txdata_flags); |
---|
| 5463 | + ieee80211_xmit(sdata, NULL, skb); |
---|
4881 | 5464 | local_bh_enable(); |
---|
4882 | 5465 | } |
---|
4883 | 5466 | |
---|
4884 | 5467 | int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, |
---|
4885 | 5468 | const u8 *buf, size_t len, |
---|
4886 | | - const u8 *dest, __be16 proto, bool unencrypted) |
---|
| 5469 | + const u8 *dest, __be16 proto, bool unencrypted, |
---|
| 5470 | + u64 *cookie) |
---|
4887 | 5471 | { |
---|
4888 | 5472 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
4889 | 5473 | struct ieee80211_local *local = sdata->local; |
---|
4890 | 5474 | struct sk_buff *skb; |
---|
4891 | 5475 | struct ethhdr *ehdr; |
---|
4892 | 5476 | u32 ctrl_flags = 0; |
---|
4893 | | - u32 flags; |
---|
| 5477 | + u32 flags = 0; |
---|
4894 | 5478 | |
---|
4895 | 5479 | /* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE |
---|
4896 | 5480 | * or Pre-Authentication |
---|
.. | .. |
---|
4900 | 5484 | return -EINVAL; |
---|
4901 | 5485 | |
---|
4902 | 5486 | if (proto == sdata->control_port_protocol) |
---|
4903 | | - ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; |
---|
| 5487 | + ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO | |
---|
| 5488 | + IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP; |
---|
4904 | 5489 | |
---|
4905 | 5490 | if (unencrypted) |
---|
4906 | | - flags = IEEE80211_TX_INTFL_DONT_ENCRYPT; |
---|
4907 | | - else |
---|
4908 | | - flags = 0; |
---|
| 5491 | + flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
---|
| 5492 | + |
---|
| 5493 | + if (cookie) |
---|
| 5494 | + ctrl_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
---|
| 5495 | + |
---|
| 5496 | + flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX | |
---|
| 5497 | + IEEE80211_TX_CTL_INJECTED; |
---|
4909 | 5498 | |
---|
4910 | 5499 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
---|
4911 | 5500 | sizeof(struct ethhdr) + len); |
---|
.. | .. |
---|
4926 | 5515 | skb_reset_network_header(skb); |
---|
4927 | 5516 | skb_reset_mac_header(skb); |
---|
4928 | 5517 | |
---|
| 5518 | + /* mutex lock is only needed for incrementing the cookie counter */ |
---|
| 5519 | + mutex_lock(&local->mtx); |
---|
| 5520 | + |
---|
4929 | 5521 | local_bh_disable(); |
---|
4930 | | - __ieee80211_subif_start_xmit(skb, skb->dev, flags, ctrl_flags); |
---|
| 5522 | + __ieee80211_subif_start_xmit(skb, skb->dev, flags, ctrl_flags, cookie); |
---|
| 5523 | + local_bh_enable(); |
---|
| 5524 | + |
---|
| 5525 | + mutex_unlock(&local->mtx); |
---|
| 5526 | + |
---|
| 5527 | + return 0; |
---|
| 5528 | +} |
---|
| 5529 | + |
---|
| 5530 | +int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev, |
---|
| 5531 | + const u8 *buf, size_t len) |
---|
| 5532 | +{ |
---|
| 5533 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
---|
| 5534 | + struct ieee80211_local *local = sdata->local; |
---|
| 5535 | + struct sk_buff *skb; |
---|
| 5536 | + |
---|
| 5537 | + skb = dev_alloc_skb(local->hw.extra_tx_headroom + len + |
---|
| 5538 | + 30 + /* header size */ |
---|
| 5539 | + 18); /* 11s header size */ |
---|
| 5540 | + if (!skb) |
---|
| 5541 | + return -ENOMEM; |
---|
| 5542 | + |
---|
| 5543 | + skb_reserve(skb, local->hw.extra_tx_headroom); |
---|
| 5544 | + skb_put_data(skb, buf, len); |
---|
| 5545 | + |
---|
| 5546 | + skb->dev = dev; |
---|
| 5547 | + skb->protocol = htons(ETH_P_802_3); |
---|
| 5548 | + skb_reset_network_header(skb); |
---|
| 5549 | + skb_reset_mac_header(skb); |
---|
| 5550 | + |
---|
| 5551 | + local_bh_disable(); |
---|
| 5552 | + __ieee80211_subif_start_xmit(skb, skb->dev, 0, |
---|
| 5553 | + IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP, |
---|
| 5554 | + NULL); |
---|
4931 | 5555 | local_bh_enable(); |
---|
4932 | 5556 | |
---|
4933 | 5557 | return 0; |
---|