Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: enable DFS for IBSS mode

Allow changing to DFS channels if the channel is available for
beaconing and userspace controls DFS operation.

Channel switch announcement from other stations on DFS channels will
be interpreted as radar event. These channels will then be marked as
unvailable.

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Simon Wunderlich and committed by
Johannes Berg
8e8d347d 5336fa88

+45 -5
+44 -5
net/mac80211/ibss.c
··· 229 229 struct beacon_data *presp; 230 230 enum nl80211_bss_scan_width scan_width; 231 231 bool have_higher_than_11mbit; 232 + bool radar_required = false; 232 233 int err; 233 234 234 235 sdata_assert_lock(sdata); ··· 274 273 } 275 274 chandef.width = NL80211_CHAN_WIDTH_20; 276 275 chandef.center_freq1 = chan->center_freq; 276 + /* check again for downgraded chandef */ 277 + if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { 278 + sdata_info(sdata, 279 + "Failed to join IBSS, beacons forbidden\n"); 280 + return; 281 + } 282 + } 283 + 284 + err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, 285 + &chandef); 286 + if (err > 0) { 287 + if (!ifibss->userspace_handles_dfs) { 288 + sdata_info(sdata, 289 + "Failed to join IBSS, DFS channel without control program\n"); 290 + return; 291 + } 292 + radar_required = true; 277 293 } 278 294 279 295 ieee80211_vif_release_channel(sdata); ··· 315 297 rcu_assign_pointer(ifibss->presp, presp); 316 298 mgmt = (void *)presp->head; 317 299 300 + sdata->radar_required = radar_required; 318 301 sdata->vif.bss_conf.enable_beacon = true; 319 302 sdata->vif.bss_conf.beacon_int = beacon_int; 320 303 sdata->vif.bss_conf.basic_rates = basic_rates; ··· 815 796 ieee80211_queue_work(&sdata->local->hw, &sdata->work); 816 797 } 817 798 799 + static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata) 800 + { 801 + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 802 + int err; 803 + 804 + /* if the current channel is a DFS channel, mark the channel as 805 + * unavailable. 806 + */ 807 + err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, 808 + &ifibss->chandef); 809 + if (err > 0) 810 + cfg80211_radar_event(sdata->local->hw.wiphy, &ifibss->chandef, 811 + GFP_ATOMIC); 812 + } 813 + 818 814 static bool 819 815 ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, 820 816 struct ieee802_11_elems *elems, ··· 914 880 goto disconnect; 915 881 } 916 882 917 - if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, &params.chandef, 918 - IEEE80211_CHAN_DISABLED)) { 883 + if (!cfg80211_reg_can_beacon(sdata->local->hw.wiphy, &params.chandef)) { 919 884 sdata_info(sdata, 920 885 "IBSS %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", 921 886 ifibss->bssid, ··· 930 897 if (err < 0) 931 898 goto disconnect; 932 899 if (err) { 933 - params.radar_required = true; 900 + /* IBSS-DFS only allowed with a control program */ 901 + if (!ifibss->userspace_handles_dfs) 902 + goto disconnect; 934 903 935 - /* TODO: IBSS-DFS not (yet) supported, disconnect. */ 936 - goto disconnect; 904 + params.radar_required = true; 937 905 } 938 906 939 907 rcu_read_lock(); ··· 981 947 ieee80211_bss_info_change_notify(sdata, err); 982 948 drv_channel_switch_beacon(sdata, &params.chandef); 983 949 950 + ieee80211_ibss_csa_mark_radar(sdata); 951 + 984 952 return true; 985 953 disconnect: 986 954 ibss_dbg(sdata, "Can't handle channel switch, disconnect\n"); 987 955 ieee80211_queue_work(&sdata->local->hw, 988 956 &ifibss->csa_connection_drop_work); 957 + 958 + ieee80211_ibss_csa_mark_radar(sdata); 989 959 990 960 return true; 991 961 } ··· 1726 1688 1727 1689 sdata->u.ibss.privacy = params->privacy; 1728 1690 sdata->u.ibss.control_port = params->control_port; 1691 + sdata->u.ibss.userspace_handles_dfs = params->userspace_handles_dfs; 1729 1692 sdata->u.ibss.basic_rates = params->basic_rates; 1730 1693 1731 1694 /* fix basic_rates if channel does not support these rates */
+1
net/mac80211/ieee80211_i.h
··· 501 501 bool privacy; 502 502 503 503 bool control_port; 504 + bool userspace_handles_dfs; 504 505 505 506 u8 bssid[ETH_ALEN] __aligned(2); 506 507 u8 ssid[IEEE80211_MAX_SSID_LEN];