Add a DFS debugging mode which is useful when doing automated DFS

compliance testing.

In order to allow for radar pattern matching to occur, the DFS CAC/NOL
handling needs to be made configurable.  This commit introduces a new
sysctl, "net.wlan.dfs_debug", which controls which DFS debug mode
net80211 is in.

* 0 = default, CSA/NOL handling as per normal.
* 1 = announce a CSA, but don't add the channel to the non-occupy list
  (NOL.)
* 2 = disable both CSA and NOL - only print that a radar event occured.

This code is not compiled/enabled by default as it breaks regulatory
handling.  A user must enable IEEE80211_DFS_DEBUG in their kernel
configuration file for this option to become available.

Obtained from:	Atheros
This commit is contained in:
Adrian Chadd 2012-01-31 00:03:49 +00:00
parent 7f925de11a
commit 62f8a13a75
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=230793
3 changed files with 74 additions and 17 deletions

View File

@ -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

View File

@ -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);

View File

@ -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 */