diff --git a/sys/conf/options b/sys/conf/options index 5cbb0d306af4..ca1244371635 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -845,6 +845,7 @@ IEEE80211_SUPPORT_MESH opt_wlan.h IEEE80211_SUPPORT_SUPERG opt_wlan.h IEEE80211_SUPPORT_TDMA opt_wlan.h IEEE80211_ALQ opt_wlan.h +IEEE80211_DFS_DEBUG opt_wlan.h # 802.11 TDMA support TDMA_SLOTLEN_DEFAULT opt_tdma.h diff --git a/sys/net80211/ieee80211_dfs.c b/sys/net80211/ieee80211_dfs.c index ffb05e9dcd40..82e525d523ce 100644 --- a/sys/net80211/ieee80211_dfs.c +++ b/sys/net80211/ieee80211_dfs.c @@ -64,6 +64,28 @@ SYSCTL_INT(_net_wlan, OID_AUTO, cac_timeout, CTLFLAG_RW, &ieee80211_cac_timeout, 0, "CAC timeout (secs)"); #define CAC_TIMEOUT msecs_to_ticks(ieee80211_cac_timeout*1000) +/* + DFS* In order to facilitate debugging, a couple of operating + * modes aside from the default are needed. + * + * 0 - default CAC/NOL behaviour - ie, start CAC, place + * channel on NOL list. + * 1 - send CAC, but don't change channel or add the channel + * to the NOL list. + * 2 - just match on radar, don't send CAC or place channel in + * the NOL list. + */ +static int ieee80211_dfs_debug = DFS_DBG_NONE; + +/* + * This option must not be included in the default kernel + * as it allows users to plainly disable CAC/NOL handling. + */ +#ifdef IEEE80211_DFS_DEBUG +SYSCTL_INT(_net_wlan, OID_AUTO, dfs_debug, CTLFLAG_RW, + &ieee80211_dfs_debug, 0, "DFS debug behaviour"); +#endif + static int null_set_quiet(struct ieee80211_node *ni, u_int8_t *quiet_elm) { @@ -278,24 +300,44 @@ ieee80211_dfs_notify_radar(struct ieee80211com *ic, struct ieee80211_channel *ch IEEE80211_LOCK_ASSERT(ic); /* - * Mark all entries with this frequency. Notify user - * space and arrange for notification when the radar - * indication is cleared. Then kick the NOL processing - * thread if not already running. + * If doing DFS debugging (mode 2), don't bother + * running the rest of this function. + * + * Simply announce the presence of the radar and continue + * along merrily. */ - now = ticks; - for (i = 0; i < ic->ic_nchans; i++) { - struct ieee80211_channel *c = &ic->ic_channels[i]; - if (c->ic_freq == chan->ic_freq) { - c->ic_state &= ~IEEE80211_CHANSTATE_CACDONE; - c->ic_state |= IEEE80211_CHANSTATE_RADAR; - dfs->nol_event[i] = now; - } + if (ieee80211_dfs_debug == DFS_DBG_NOCSANOL) { + announce_radar(ic->ic_ifp, chan, chan); + ieee80211_notify_radar(ic, chan); + return; + } + + /* + * Don't mark the channel and don't put it into NOL + * if we're doing DFS debugging. + */ + if (ieee80211_dfs_debug == DFS_DBG_NONE) { + /* + * Mark all entries with this frequency. Notify user + * space and arrange for notification when the radar + * indication is cleared. Then kick the NOL processing + * thread if not already running. + */ + now = ticks; + for (i = 0; i < ic->ic_nchans; i++) { + struct ieee80211_channel *c = &ic->ic_channels[i]; + if (c->ic_freq == chan->ic_freq) { + c->ic_state &= ~IEEE80211_CHANSTATE_CACDONE; + c->ic_state |= IEEE80211_CHANSTATE_RADAR; + dfs->nol_event[i] = now; + } + } + ieee80211_notify_radar(ic, chan); + chan->ic_state |= IEEE80211_CHANSTATE_NORADAR; + if (!callout_pending(&dfs->nol_timer)) + callout_reset(&dfs->nol_timer, NOL_TIMEOUT, + dfs_timeout, ic); } - ieee80211_notify_radar(ic, chan); - chan->ic_state |= IEEE80211_CHANSTATE_NORADAR; - if (!callout_pending(&dfs->nol_timer)) - callout_reset(&dfs->nol_timer, NOL_TIMEOUT, dfs_timeout, ic); /* * If radar is detected on the bss channel while @@ -310,7 +352,15 @@ ieee80211_dfs_notify_radar(struct ieee80211com *ic, struct ieee80211_channel *ch */ if (chan == ic->ic_bsschan) { /* XXX need a way to defer to user app */ - dfs->newchan = ieee80211_dfs_pickchannel(ic); + + /* + * Don't flip over to a new channel if + * we are currently doing DFS debugging. + */ + if (ieee80211_dfs_debug == DFS_DBG_NONE) + dfs->newchan = ieee80211_dfs_pickchannel(ic); + else + dfs->newchan = chan; announce_radar(ic->ic_ifp, chan, dfs->newchan); diff --git a/sys/net80211/ieee80211_dfs.h b/sys/net80211/ieee80211_dfs.h index 90760777a785..a5688e3bc491 100644 --- a/sys/net80211/ieee80211_dfs.h +++ b/sys/net80211/ieee80211_dfs.h @@ -31,6 +31,12 @@ * 802.11h/DFS definitions. */ +typedef enum { + DFS_DBG_NONE = 0, + DFS_DBG_NONOL = 1, + DFS_DBG_NOCSANOL = 2 +} dfs_debug_t; + struct ieee80211_dfs_state { int nol_event[IEEE80211_CHAN_MAX]; struct callout nol_timer; /* NOL list processing */