aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
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
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')
-rw-r--r--net/mac80211/cfg.c10
-rw-r--r--net/mac80211/sta_info.h5
-rw-r--r--net/mac80211/tx.c42
3 files changed, 52 insertions, 5 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 119a573af14b..bdf9852eec5b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2427,6 +2427,7 @@ fail:
2427static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, 2427static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
2428 u8 *peer, enum nl80211_tdls_operation oper) 2428 u8 *peer, enum nl80211_tdls_operation oper)
2429{ 2429{
2430 struct sta_info *sta;
2430 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 2431 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2431 2432
2432 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) 2433 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
@@ -2441,6 +2442,15 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
2441 2442
2442 switch (oper) { 2443 switch (oper) {
2443 case NL80211_TDLS_ENABLE_LINK: 2444 case NL80211_TDLS_ENABLE_LINK:
2445 rcu_read_lock();
2446 sta = sta_info_get(sdata, peer);
2447 if (!sta) {
2448 rcu_read_unlock();
2449 return -ENOLINK;
2450 }
2451
2452 set_sta_flags(sta, WLAN_STA_TDLS_PEER_AUTH);
2453 rcu_read_unlock();
2444 break; 2454 break;
2445 case NL80211_TDLS_DISABLE_LINK: 2455 case NL80211_TDLS_DISABLE_LINK:
2446 return sta_info_destroy_addr(sdata, peer); 2456 return sta_info_destroy_addr(sdata, peer);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index b6bd4e9d8722..c10e2e8632b5 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -45,7 +45,9 @@
45 * station in power-save mode, reply when the driver unblocks. 45 * station in power-save mode, reply when the driver unblocks.
46 * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal 46 * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
47 * buffers. Automatically cleared on station wake-up. 47 * buffers. Automatically cleared on station wake-up.
48 * @WLAN_STA_TDLS_PEER: station is a TDLS peer. 48 * @WLAN_STA_TDLS_PEER: Station is a TDLS peer.
49 * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct
50 * packets. This means the link is enabled.
49 */ 51 */
50enum ieee80211_sta_info_flags { 52enum ieee80211_sta_info_flags {
51 WLAN_STA_AUTH = 1<<0, 53 WLAN_STA_AUTH = 1<<0,
@@ -63,6 +65,7 @@ enum ieee80211_sta_info_flags {
63 WLAN_STA_PSPOLL = 1<<13, 65 WLAN_STA_PSPOLL = 1<<13,
64 WLAN_STA_PS_DRIVER_BUF = 1<<14, 66 WLAN_STA_PS_DRIVER_BUF = 1<<14,
65 WLAN_STA_TDLS_PEER = 1<<15, 67 WLAN_STA_TDLS_PEER = 1<<15,
68 WLAN_STA_TDLS_PEER_AUTH = 1<<16,
66}; 69};
67 70
68#define STA_TID_NUM 16 71#define STA_TID_NUM 16
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;