diff options
author | Michal Kazior <michal.kazior@tieto.com> | 2014-01-29 08:22:27 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-02-04 15:58:17 -0500 |
commit | 9e0e29615a2077be852b1245b57c5b00fa609522 (patch) | |
tree | 73d899373e01efe1fd72a895d8e2fe2f6bc8fcb2 /net/wireless/chan.c | |
parent | fe94f3a4ffaa20c7470038c69ffc8e545ef5f90a (diff) |
cfg80211: consider existing DFS interfaces
It was possible to break interface combinations in
the following way:
combo 1: iftype = AP, num_ifaces = 2, num_chans = 2,
combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20
With the above interface combinations it was
possible to:
step 1. start AP on DFS channel by matching combo 2
step 2. start AP on non-DFS channel by matching combo 1
This was possible beacuse (step 2) did not consider
if other interfaces require radar detection.
The patch changes how cfg80211 tracks channels -
instead of channel itself now a complete chandef
is stored.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/chan.c')
-rw-r--r-- | net/wireless/chan.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 78559b5bbd1f..f8ab7df1ab0d 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, | |||
642 | void | 642 | void |
643 | cfg80211_get_chan_state(struct wireless_dev *wdev, | 643 | cfg80211_get_chan_state(struct wireless_dev *wdev, |
644 | struct ieee80211_channel **chan, | 644 | struct ieee80211_channel **chan, |
645 | enum cfg80211_chan_mode *chanmode) | 645 | enum cfg80211_chan_mode *chanmode, |
646 | u8 *radar_detect) | ||
646 | { | 647 | { |
647 | *chan = NULL; | 648 | *chan = NULL; |
648 | *chanmode = CHAN_MODE_UNDEFINED; | 649 | *chanmode = CHAN_MODE_UNDEFINED; |
@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
660 | !wdev->ibss_dfs_possible) | 661 | !wdev->ibss_dfs_possible) |
661 | ? CHAN_MODE_SHARED | 662 | ? CHAN_MODE_SHARED |
662 | : CHAN_MODE_EXCLUSIVE; | 663 | : CHAN_MODE_EXCLUSIVE; |
664 | |||
665 | /* consider worst-case - IBSS can try to return to the | ||
666 | * original user-specified channel as creator */ | ||
667 | if (wdev->ibss_dfs_possible) | ||
668 | *radar_detect |= BIT(wdev->chandef.width); | ||
663 | return; | 669 | return; |
664 | } | 670 | } |
665 | break; | 671 | break; |
@@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
674 | case NL80211_IFTYPE_AP: | 680 | case NL80211_IFTYPE_AP: |
675 | case NL80211_IFTYPE_P2P_GO: | 681 | case NL80211_IFTYPE_P2P_GO: |
676 | if (wdev->cac_started) { | 682 | if (wdev->cac_started) { |
677 | *chan = wdev->channel; | 683 | *chan = wdev->chandef.chan; |
678 | *chanmode = CHAN_MODE_SHARED; | 684 | *chanmode = CHAN_MODE_SHARED; |
685 | *radar_detect |= BIT(wdev->chandef.width); | ||
679 | } else if (wdev->beacon_interval) { | 686 | } else if (wdev->beacon_interval) { |
680 | *chan = wdev->channel; | 687 | *chan = wdev->chandef.chan; |
681 | *chanmode = CHAN_MODE_SHARED; | 688 | *chanmode = CHAN_MODE_SHARED; |
689 | |||
690 | if (cfg80211_chandef_dfs_required(wdev->wiphy, | ||
691 | &wdev->chandef)) | ||
692 | *radar_detect |= BIT(wdev->chandef.width); | ||
682 | } | 693 | } |
683 | return; | 694 | return; |
684 | case NL80211_IFTYPE_MESH_POINT: | 695 | case NL80211_IFTYPE_MESH_POINT: |
685 | if (wdev->mesh_id_len) { | 696 | if (wdev->mesh_id_len) { |
686 | *chan = wdev->channel; | 697 | *chan = wdev->chandef.chan; |
687 | *chanmode = CHAN_MODE_SHARED; | 698 | *chanmode = CHAN_MODE_SHARED; |
699 | |||
700 | if (cfg80211_chandef_dfs_required(wdev->wiphy, | ||
701 | &wdev->chandef)) | ||
702 | *radar_detect |= BIT(wdev->chandef.width); | ||
688 | } | 703 | } |
689 | return; | 704 | return; |
690 | case NL80211_IFTYPE_MONITOR: | 705 | case NL80211_IFTYPE_MONITOR: |