aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2014-06-11 10:18:24 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-06-23 08:27:58 -0400
commitdb67d661e82da22f751585a7f284a9251e8a2a51 (patch)
tree48b626800ca5aa8d866380f4f105f90baea71cb9
parent191dd46905ce9a25174dd9eea4ff3029802ac37c (diff)
mac80211: implement proper Tx path flushing for TDLS
As the spec mandates, flush data in the AP path before transmitting the first setup frame. Data packets transmitted during setup are already dropped in the Tx path. For the teardown flow, flush all packets in the direct path before transmitting the teardown frame. Un-authorize the peer sta after teardown is sent, forcing all subsequent Tx to the peer through the AP. Make sure to flush the queues when disabling the link to get the teardown packet out. Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com> [adjust to Luca's new quuee API and stop only vif queues] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/tdls.c57
2 files changed, 58 insertions, 0 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 75f79c168e90..6c8089429892 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -925,6 +925,7 @@ enum queue_stop_reason {
925 IEEE80211_QUEUE_STOP_REASON_SKB_ADD, 925 IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
926 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, 926 IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
927 IEEE80211_QUEUE_STOP_REASON_FLUSH, 927 IEEE80211_QUEUE_STOP_REASON_FLUSH,
928 IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN,
928 929
929 IEEE80211_QUEUE_STOP_REASONS, 930 IEEE80211_QUEUE_STOP_REASONS,
930}; 931};
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 92d203a3be07..0ba7e4c029c8 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -331,6 +331,8 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,
331 goto exit; 331 goto exit;
332 } 332 }
333 333
334 ieee80211_flush_queues(local, sdata);
335
334 ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code, 336 ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
335 dialog_token, status_code, 337 dialog_token, status_code,
336 peer_capability, initiator, 338 peer_capability, initiator,
@@ -348,6 +350,52 @@ exit:
348 return ret; 350 return ret;
349} 351}
350 352
353static int
354ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev,
355 const u8 *peer, u8 action_code, u8 dialog_token,
356 u16 status_code, u32 peer_capability,
357 bool initiator, const u8 *extra_ies,
358 size_t extra_ies_len)
359{
360 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
361 struct ieee80211_local *local = sdata->local;
362 struct sta_info *sta;
363 int ret;
364
365 /*
366 * No packets can be transmitted to the peer via the AP during setup -
367 * the STA is set as a TDLS peer, but is not authorized.
368 * During teardown, we prevent direct transmissions by stopping the
369 * queues and flushing all direct packets.
370 */
371 ieee80211_stop_vif_queues(local, sdata,
372 IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
373 ieee80211_flush_queues(local, sdata);
374
375 ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
376 dialog_token, status_code,
377 peer_capability, initiator,
378 extra_ies, extra_ies_len);
379 if (ret < 0)
380 sdata_err(sdata, "Failed sending TDLS teardown packet %d\n",
381 ret);
382
383 /*
384 * Remove the STA AUTH flag to force further traffic through the AP. If
385 * the STA was unreachable, it was already removed.
386 */
387 rcu_read_lock();
388 sta = sta_info_get(sdata, peer);
389 if (sta)
390 clear_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
391 rcu_read_unlock();
392
393 ieee80211_wake_vif_queues(local, sdata,
394 IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN);
395
396 return 0;
397}
398
351int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, 399int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
352 const u8 *peer, u8 action_code, u8 dialog_token, 400 const u8 *peer, u8 action_code, u8 dialog_token,
353 u16 status_code, u32 peer_capability, 401 u16 status_code, u32 peer_capability,
@@ -374,6 +422,12 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
374 extra_ies, extra_ies_len); 422 extra_ies, extra_ies_len);
375 break; 423 break;
376 case WLAN_TDLS_TEARDOWN: 424 case WLAN_TDLS_TEARDOWN:
425 ret = ieee80211_tdls_mgmt_teardown(wiphy, dev, peer,
426 action_code, dialog_token,
427 status_code,
428 peer_capability, initiator,
429 extra_ies, extra_ies_len);
430 break;
377 case WLAN_TDLS_SETUP_CONFIRM: 431 case WLAN_TDLS_SETUP_CONFIRM:
378 case WLAN_TDLS_DISCOVERY_REQUEST: 432 case WLAN_TDLS_DISCOVERY_REQUEST:
379 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: 433 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
@@ -442,6 +496,9 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
442 ret = 0; 496 ret = 0;
443 break; 497 break;
444 case NL80211_TDLS_DISABLE_LINK: 498 case NL80211_TDLS_DISABLE_LINK:
499 /* flush a potentially queued teardown packet */
500 ieee80211_flush_queues(local, sdata);
501
445 ret = sta_info_destroy_addr(sdata, peer); 502 ret = sta_info_destroy_addr(sdata, peer);
446 break; 503 break;
447 default: 504 default: