aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2011-09-28 07:12:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-30 15:57:09 -0400
commit941c93cd039852b7ab02c74f4698c99d82bd6cfe (patch)
tree8f527535dcb145877ac8cb68f43723b05d574e6e /net/mac80211/tx.c
parent07ba55d7f1d0da174c9bc545c713b44cee760197 (diff)
mac80211: data path modification for TDLS peers
Mark the STA entries of enabled TDLS peers with a new "peer authorized" flag. During link setup, allow special TDLS setup frames through the AP, but otherwise drop all packets destined to the peer. This is required by the TDLS (802.11z) specification in order to prevent reordering of MSDUs between the AP and direct paths. When setup completes and the peer is authorized, send data directly, bypassing the AP. In the Rx path, allow data to be received directly from TDLS peers. Signed-off-by: Arik Nemtsov <arik@wizery.com> Cc: Kalyan C Gaddam <chakkal@iit.edu> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 542272acfc1a..0ca16880bbb4 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1726,6 +1726,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1726 struct sta_info *sta = NULL; 1726 struct sta_info *sta = NULL;
1727 u32 sta_flags = 0; 1727 u32 sta_flags = 0;
1728 struct sk_buff *tmp_skb; 1728 struct sk_buff *tmp_skb;
1729 bool tdls_direct = false;
1729 1730
1730 if (unlikely(skb->len < ETH_HLEN)) { 1731 if (unlikely(skb->len < ETH_HLEN)) {
1731 ret = NETDEV_TX_OK; 1732 ret = NETDEV_TX_OK;
@@ -1837,11 +1838,43 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1837 break; 1838 break;
1838#endif 1839#endif
1839 case NL80211_IFTYPE_STATION: 1840 case NL80211_IFTYPE_STATION:
1840 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); 1841 if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
1841 if (sdata->u.mgd.use_4addr && 1842 rcu_read_lock();
1842 cpu_to_be16(ethertype) != sdata->control_port_protocol) { 1843 sta = sta_info_get(sdata, skb->data);
1843 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1844 if (sta)
1845 sta_flags = get_sta_flags(sta);
1846 rcu_read_unlock();
1847
1848 /*
1849 * If the TDLS link is enabled, send everything
1850 * directly. Otherwise, allow TDLS setup frames
1851 * to be transmitted indirectly.
1852 */
1853 tdls_direct =
1854 (sta_flags & WLAN_STA_TDLS_PEER) &&
1855 ((sta_flags & WLAN_STA_TDLS_PEER_AUTH) ||
1856 !(ethertype == ETH_P_TDLS && skb->len > 14 &&
1857 skb->data[14] == WLAN_TDLS_SNAP_RFTYPE));
1858 }
1859
1860 if (tdls_direct) {
1861 /* link during setup - throw out frames to peer */
1862 if (!(sta_flags & WLAN_STA_TDLS_PEER_AUTH)) {
1863 ret = NETDEV_TX_OK;
1864 goto fail;
1865 }
1866
1867 /* DA SA BSSID */
1868 memcpy(hdr.addr1, skb->data, ETH_ALEN);
1869 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
1870 memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN);
1871 hdrlen = 24;
1872 } else if (sdata->u.mgd.use_4addr &&
1873 cpu_to_be16(ethertype) != sdata->control_port_protocol) {
1874 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
1875 IEEE80211_FCTL_TODS);
1844 /* RA TA DA SA */ 1876 /* RA TA DA SA */
1877 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
1845 memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); 1878 memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
1846 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1879 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1847 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); 1880 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
@@ -1849,6 +1882,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1849 } else { 1882 } else {
1850 fc |= cpu_to_le16(IEEE80211_FCTL_TODS); 1883 fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
1851 /* BSSID SA DA */ 1884 /* BSSID SA DA */
1885 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
1852 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); 1886 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
1853 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1887 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1854 hdrlen = 24; 1888 hdrlen = 24;