diff options
author | Johannes Berg <johannes.berg@intel.com> | 2014-11-09 11:50:10 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-11-19 12:44:38 -0500 |
commit | 4c9451ed94087abf0e45835f133e0fa44b809f96 (patch) | |
tree | 978e19f77041210d534027b898a2527a13701b95 /net/mac80211/tx.c | |
parent | 73c4e195e6396eea04e11f88dc0336e1bc3c8e66 (diff) |
mac80211: factor out 802.11 header building code
Factor out the 802.11 header building code from the xmit function
to be able to use it separately in a later commit.
While at it, fix up some documentation.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 144 |
1 files changed, 92 insertions, 52 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c4a5494c2ac6..55d69fda4c6a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1784,24 +1784,26 @@ static void ieee80211_tx_latency_start_msrmnt(struct ieee80211_local *local, | |||
1784 | } | 1784 | } |
1785 | 1785 | ||
1786 | /** | 1786 | /** |
1787 | * __ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type | 1787 | * ieee80211_build_hdr - build 802.11 header in the given frame |
1788 | * subinterfaces (wlan#, WDS, and VLAN interfaces) | 1788 | * @sdata: virtual interface to build the header for |
1789 | * @skb: packet to be sent | 1789 | * @skb: the skb to build the header in |
1790 | * @dev: incoming interface | ||
1791 | * @info_flags: skb flags to set | 1790 | * @info_flags: skb flags to set |
1792 | * | 1791 | * |
1793 | * On failure skb will be freed. | 1792 | * This function takes the skb with 802.3 header and reformats the header to |
1793 | * the appropriate IEEE 802.11 header based on which interface the packet is | ||
1794 | * being transmitted on. | ||
1795 | * | ||
1796 | * Note that this function also takes care of the TX status request and | ||
1797 | * potential unsharing of the SKB - this needs to be interleaved with the | ||
1798 | * header building. | ||
1799 | * | ||
1800 | * The function requires the read-side RCU lock held | ||
1794 | * | 1801 | * |
1795 | * This function takes in an Ethernet header and encapsulates it with suitable | 1802 | * Returns: the (possibly reallocated) skb or an ERR_PTR() code |
1796 | * IEEE 802.11 header based on which interface the packet is coming in. The | ||
1797 | * encapsulated packet will then be passed to master interface, wlan#.11, for | ||
1798 | * transmission (through low-level driver). | ||
1799 | */ | 1803 | */ |
1800 | void __ieee80211_subif_start_xmit(struct sk_buff *skb, | 1804 | static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, |
1801 | struct net_device *dev, | 1805 | struct sk_buff *skb, u32 info_flags) |
1802 | u32 info_flags) | ||
1803 | { | 1806 | { |
1804 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1805 | struct ieee80211_local *local = sdata->local; | 1807 | struct ieee80211_local *local = sdata->local; |
1806 | struct ieee80211_tx_info *info; | 1808 | struct ieee80211_tx_info *info; |
1807 | int head_need; | 1809 | int head_need; |
@@ -1821,20 +1823,13 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1821 | struct ieee80211_chanctx_conf *chanctx_conf; | 1823 | struct ieee80211_chanctx_conf *chanctx_conf; |
1822 | struct ieee80211_sub_if_data *ap_sdata; | 1824 | struct ieee80211_sub_if_data *ap_sdata; |
1823 | enum ieee80211_band band; | 1825 | enum ieee80211_band band; |
1824 | 1826 | int ret; | |
1825 | if (unlikely(skb->len < ETH_HLEN)) | ||
1826 | goto fail; | ||
1827 | 1827 | ||
1828 | /* convert Ethernet header to proper 802.11 header (based on | 1828 | /* convert Ethernet header to proper 802.11 header (based on |
1829 | * operation mode) */ | 1829 | * operation mode) */ |
1830 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1830 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
1831 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); | 1831 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); |
1832 | 1832 | ||
1833 | rcu_read_lock(); | ||
1834 | |||
1835 | /* Measure frame arrival for Tx latency statistics calculation */ | ||
1836 | ieee80211_tx_latency_start_msrmnt(local, skb); | ||
1837 | |||
1838 | switch (sdata->vif.type) { | 1833 | switch (sdata->vif.type) { |
1839 | case NL80211_IFTYPE_AP_VLAN: | 1834 | case NL80211_IFTYPE_AP_VLAN: |
1840 | sta = rcu_dereference(sdata->u.vlan.sta); | 1835 | sta = rcu_dereference(sdata->u.vlan.sta); |
@@ -1852,8 +1847,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1852 | ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, | 1847 | ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, |
1853 | u.ap); | 1848 | u.ap); |
1854 | chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); | 1849 | chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); |
1855 | if (!chanctx_conf) | 1850 | if (!chanctx_conf) { |
1856 | goto fail_rcu; | 1851 | ret = -ENOTCONN; |
1852 | goto free; | ||
1853 | } | ||
1857 | band = chanctx_conf->def.chan->band; | 1854 | band = chanctx_conf->def.chan->band; |
1858 | if (sta) | 1855 | if (sta) |
1859 | break; | 1856 | break; |
@@ -1861,8 +1858,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1861 | case NL80211_IFTYPE_AP: | 1858 | case NL80211_IFTYPE_AP: |
1862 | if (sdata->vif.type == NL80211_IFTYPE_AP) | 1859 | if (sdata->vif.type == NL80211_IFTYPE_AP) |
1863 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1860 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1864 | if (!chanctx_conf) | 1861 | if (!chanctx_conf) { |
1865 | goto fail_rcu; | 1862 | ret = -ENOTCONN; |
1863 | goto free; | ||
1864 | } | ||
1866 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 1865 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
1867 | /* DA BSSID SA */ | 1866 | /* DA BSSID SA */ |
1868 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1867 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
@@ -1949,8 +1948,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1949 | 1948 | ||
1950 | } | 1949 | } |
1951 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1950 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1952 | if (!chanctx_conf) | 1951 | if (!chanctx_conf) { |
1953 | goto fail_rcu; | 1952 | ret = -ENOTCONN; |
1953 | goto free; | ||
1954 | } | ||
1954 | band = chanctx_conf->def.chan->band; | 1955 | band = chanctx_conf->def.chan->band; |
1955 | break; | 1956 | break; |
1956 | #endif | 1957 | #endif |
@@ -1980,8 +1981,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1980 | * of a link teardown after a TDLS sta is removed due to being | 1981 | * of a link teardown after a TDLS sta is removed due to being |
1981 | * unreachable. | 1982 | * unreachable. |
1982 | */ | 1983 | */ |
1983 | if (tdls_peer && !tdls_auth && !tdls_setup_frame) | 1984 | if (tdls_peer && !tdls_auth && !tdls_setup_frame) { |
1984 | goto fail_rcu; | 1985 | ret = -EINVAL; |
1986 | goto free; | ||
1987 | } | ||
1985 | 1988 | ||
1986 | /* send direct packets to authorized TDLS peers */ | 1989 | /* send direct packets to authorized TDLS peers */ |
1987 | if (tdls_peer && tdls_auth) { | 1990 | if (tdls_peer && tdls_auth) { |
@@ -2009,8 +2012,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2009 | hdrlen = 24; | 2012 | hdrlen = 24; |
2010 | } | 2013 | } |
2011 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 2014 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
2012 | if (!chanctx_conf) | 2015 | if (!chanctx_conf) { |
2013 | goto fail_rcu; | 2016 | ret = -ENOTCONN; |
2017 | goto free; | ||
2018 | } | ||
2014 | band = chanctx_conf->def.chan->band; | 2019 | band = chanctx_conf->def.chan->band; |
2015 | break; | 2020 | break; |
2016 | case NL80211_IFTYPE_OCB: | 2021 | case NL80211_IFTYPE_OCB: |
@@ -2020,8 +2025,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2020 | eth_broadcast_addr(hdr.addr3); | 2025 | eth_broadcast_addr(hdr.addr3); |
2021 | hdrlen = 24; | 2026 | hdrlen = 24; |
2022 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 2027 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
2023 | if (!chanctx_conf) | 2028 | if (!chanctx_conf) { |
2024 | goto fail_rcu; | 2029 | ret = -ENOTCONN; |
2030 | goto free; | ||
2031 | } | ||
2025 | band = chanctx_conf->def.chan->band; | 2032 | band = chanctx_conf->def.chan->band; |
2026 | break; | 2033 | break; |
2027 | case NL80211_IFTYPE_ADHOC: | 2034 | case NL80211_IFTYPE_ADHOC: |
@@ -2031,12 +2038,15 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2031 | memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN); | 2038 | memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN); |
2032 | hdrlen = 24; | 2039 | hdrlen = 24; |
2033 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 2040 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
2034 | if (!chanctx_conf) | 2041 | if (!chanctx_conf) { |
2035 | goto fail_rcu; | 2042 | ret = -ENOTCONN; |
2043 | goto free; | ||
2044 | } | ||
2036 | band = chanctx_conf->def.chan->band; | 2045 | band = chanctx_conf->def.chan->band; |
2037 | break; | 2046 | break; |
2038 | default: | 2047 | default: |
2039 | goto fail_rcu; | 2048 | ret = -EINVAL; |
2049 | goto free; | ||
2040 | } | 2050 | } |
2041 | 2051 | ||
2042 | /* | 2052 | /* |
@@ -2074,12 +2084,13 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2074 | !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) { | 2084 | !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) { |
2075 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2085 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
2076 | net_info_ratelimited("%s: dropped frame to %pM (unauthorized port)\n", | 2086 | net_info_ratelimited("%s: dropped frame to %pM (unauthorized port)\n", |
2077 | dev->name, hdr.addr1); | 2087 | sdata->name, hdr.addr1); |
2078 | #endif | 2088 | #endif |
2079 | 2089 | ||
2080 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); | 2090 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); |
2081 | 2091 | ||
2082 | goto fail_rcu; | 2092 | ret = -EPERM; |
2093 | goto free; | ||
2083 | } | 2094 | } |
2084 | 2095 | ||
2085 | if (unlikely(!multicast && skb->sk && | 2096 | if (unlikely(!multicast && skb->sk && |
@@ -2116,8 +2127,10 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2116 | skb = skb_clone(skb, GFP_ATOMIC); | 2127 | skb = skb_clone(skb, GFP_ATOMIC); |
2117 | kfree_skb(tmp_skb); | 2128 | kfree_skb(tmp_skb); |
2118 | 2129 | ||
2119 | if (!skb) | 2130 | if (!skb) { |
2120 | goto fail_rcu; | 2131 | ret = -ENOMEM; |
2132 | goto free; | ||
2133 | } | ||
2121 | } | 2134 | } |
2122 | 2135 | ||
2123 | hdr.frame_control = fc; | 2136 | hdr.frame_control = fc; |
@@ -2166,7 +2179,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2166 | if (ieee80211_skb_resize(sdata, skb, head_need, true)) { | 2179 | if (ieee80211_skb_resize(sdata, skb, head_need, true)) { |
2167 | ieee80211_free_txskb(&local->hw, skb); | 2180 | ieee80211_free_txskb(&local->hw, skb); |
2168 | skb = NULL; | 2181 | skb = NULL; |
2169 | goto fail_rcu; | 2182 | return ERR_PTR(-ENOMEM); |
2170 | } | 2183 | } |
2171 | } | 2184 | } |
2172 | 2185 | ||
@@ -2200,9 +2213,6 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2200 | nh_pos += hdrlen; | 2213 | nh_pos += hdrlen; |
2201 | h_pos += hdrlen; | 2214 | h_pos += hdrlen; |
2202 | 2215 | ||
2203 | dev->stats.tx_packets++; | ||
2204 | dev->stats.tx_bytes += skb->len; | ||
2205 | |||
2206 | /* Update skb pointers to various headers since this modified frame | 2216 | /* Update skb pointers to various headers since this modified frame |
2207 | * is going to go through Linux networking code that may potentially | 2217 | * is going to go through Linux networking code that may potentially |
2208 | * need things like pointer to IP header. */ | 2218 | * need things like pointer to IP header. */ |
@@ -2213,23 +2223,53 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2213 | info = IEEE80211_SKB_CB(skb); | 2223 | info = IEEE80211_SKB_CB(skb); |
2214 | memset(info, 0, sizeof(*info)); | 2224 | memset(info, 0, sizeof(*info)); |
2215 | 2225 | ||
2216 | dev->trans_start = jiffies; | ||
2217 | |||
2218 | info->flags = info_flags; | 2226 | info->flags = info_flags; |
2219 | info->ack_frame_id = info_id; | 2227 | info->ack_frame_id = info_id; |
2220 | info->band = band; | 2228 | info->band = band; |
2221 | 2229 | ||
2222 | ieee80211_xmit(sdata, skb); | 2230 | return skb; |
2223 | rcu_read_unlock(); | 2231 | free: |
2232 | kfree_skb(skb); | ||
2233 | return ERR_PTR(ret); | ||
2234 | } | ||
2235 | |||
2236 | void __ieee80211_subif_start_xmit(struct sk_buff *skb, | ||
2237 | struct net_device *dev, | ||
2238 | u32 info_flags) | ||
2239 | { | ||
2240 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2241 | struct ieee80211_local *local = sdata->local; | ||
2242 | |||
2243 | if (unlikely(skb->len < ETH_HLEN)) { | ||
2244 | kfree_skb(skb); | ||
2245 | return; | ||
2246 | } | ||
2247 | |||
2248 | rcu_read_lock(); | ||
2249 | |||
2250 | /* Measure frame arrival for Tx latency statistics calculation */ | ||
2251 | ieee80211_tx_latency_start_msrmnt(local, skb); | ||
2252 | |||
2253 | skb = ieee80211_build_hdr(sdata, skb, info_flags); | ||
2254 | if (IS_ERR(skb)) | ||
2255 | goto out; | ||
2224 | 2256 | ||
2225 | return; | 2257 | dev->stats.tx_packets++; |
2258 | dev->stats.tx_bytes += skb->len; | ||
2259 | dev->trans_start = jiffies; | ||
2226 | 2260 | ||
2227 | fail_rcu: | 2261 | ieee80211_xmit(sdata, skb); |
2262 | out: | ||
2228 | rcu_read_unlock(); | 2263 | rcu_read_unlock(); |
2229 | fail: | ||
2230 | dev_kfree_skb(skb); | ||
2231 | } | 2264 | } |
2232 | 2265 | ||
2266 | /** | ||
2267 | * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs | ||
2268 | * @skb: packet to be sent | ||
2269 | * @dev: incoming interface | ||
2270 | * | ||
2271 | * On failure skb will be freed. | ||
2272 | */ | ||
2233 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | 2273 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, |
2234 | struct net_device *dev) | 2274 | struct net_device *dev) |
2235 | { | 2275 | { |