Message ID | 1379310007-2600-2-git-send-email-janusz.dziedzic@tieto.com |
---|---|
State | Superseded |
Headers | show |
Hey Janusz, On Mon, Sep 16, 2013 at 07:40:07AM +0200, Janusz Dziedzic wrote: > Add DFS CAC handling, radar detection. > By default after radar detected or > channel became unavailable random channel > will be choose. > > Signed-hostap: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> > Signed-hostap: Janusz Dziedzic <janusz.dziedzic@tieto.com> Thanks a lot for the rewrite - looks good to me and works well here, so feel free to add: Tested-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Also the patch looks good in general. This series is still missing the dfs channel list patch which is in another patch Jouni has still backed up [1] (doesn't apply currently, but it's trivial to fix). Would be good to merge this as well. Just one remark: What do we do if all channels are taken? Your current implementation will then simply close hostapd, but I'm not sure if this is desired behaviour - shouldn't we rather keep it running and wait for one channel to come back (when the Non-occupancy-period is over) and try again? Cheers and thanks, Simon [1] http://w1.fi/p/dfs/0002-hostapd-Add-config-option-for-DFS-channels.patch
On 17 September 2013 18:25, Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de> wrote: > Hey Janusz, > > On Mon, Sep 16, 2013 at 07:40:07AM +0200, Janusz Dziedzic wrote: >> Add DFS CAC handling, radar detection. >> By default after radar detected or >> channel became unavailable random channel >> will be choose. >> >> Signed-hostap: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> >> Signed-hostap: Janusz Dziedzic <janusz.dziedzic@tieto.com> > > Thanks a lot for the rewrite - looks good to me and works well here, so > feel free to add: > > Tested-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> > Thanks for review and tests. > Also the patch looks good in general. This series is still missing the > dfs channel list patch which is in another patch Jouni has still backed > up [1] (doesn't apply currently, but it's trivial to fix). Would be good > to merge this as well. > > Just one remark: What do we do if all channels are taken? Your current > implementation will then simply close hostapd, but I'm not sure if this > is desired behaviour - shouldn't we rather keep it running and wait for one > channel to come back (when the Non-occupancy-period is over) and try again? > I think we should never hit this case. Base of spec I changed getting new channel little bit. Currently we get random channel from list of: - "standard" 5G channels (!disabled) - defined by regdomain - DFS usable + availabe channels. Even all DFS channels will be unavailable we should get still "standard" channels list I think. > > [1] http://w1.fi/p/dfs/0002-hostapd-Add-config-option-for-DFS-channels.patch BR Janusz
Hey Janusz, On Tue, Sep 17, 2013 at 08:44:37PM +0200, Janusz Dziedzic wrote: > On 17 September 2013 18:25, Simon Wunderlich > <simon.wunderlich@s2003.tu-chemnitz.de> wrote: > > Hey Janusz, > > > > On Mon, Sep 16, 2013 at 07:40:07AM +0200, Janusz Dziedzic wrote: > >> Add DFS CAC handling, radar detection. > >> By default after radar detected or > >> channel became unavailable random channel > >> will be choose. > >> > >> Signed-hostap: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> > >> Signed-hostap: Janusz Dziedzic <janusz.dziedzic@tieto.com> > > > > Thanks a lot for the rewrite - looks good to me and works well here, so > > feel free to add: > > > > Tested-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> > > > Thanks for review and tests. > > > Also the patch looks good in general. This series is still missing the > > dfs channel list patch which is in another patch Jouni has still backed > > up [1] (doesn't apply currently, but it's trivial to fix). Would be good > > to merge this as well. > > > > Just one remark: What do we do if all channels are taken? Your current > > implementation will then simply close hostapd, but I'm not sure if this > > is desired behaviour - shouldn't we rather keep it running and wait for one > > channel to come back (when the Non-occupancy-period is over) and try again? > > > I think we should never hit this case. Base of spec I changed getting > new channel little bit. > Currently we get random channel from list of: > - "standard" 5G channels (!disabled) - defined by regdomain > - DFS usable + availabe channels. > > Even all DFS channels will be unavailable we should get still > "standard" channels list I think. If we want to use 5 GHz outdoors we may only use outdoor channels. These must be limited e.g. by using the DFS channel option in the pending patch[1]. Jumping back to a non-DFS channel is not an option for outdoors, at least in Europe all outdoor channels require DFS. So it might happen that all channels become unavailable for some time. In this case, your current implementation will just stop the hostapd (I've tested after applying the channel list patch [1]), and while this is one option to handle it, I feel that's not the best ... :) > > > > > [1] http://w1.fi/p/dfs/0002-hostapd-Add-config-option-for-DFS-channels.patch Cheers, Simon
On 19 September 2013 13:51, Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de> wrote: > Hey Janusz, > > On Tue, Sep 17, 2013 at 08:44:37PM +0200, Janusz Dziedzic wrote: >> On 17 September 2013 18:25, Simon Wunderlich >> <simon.wunderlich@s2003.tu-chemnitz.de> wrote: >> > Hey Janusz, >> > >> > On Mon, Sep 16, 2013 at 07:40:07AM +0200, Janusz Dziedzic wrote: >> >> Add DFS CAC handling, radar detection. >> >> By default after radar detected or >> >> channel became unavailable random channel >> >> will be choose. >> >> >> >> Signed-hostap: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> >> >> Signed-hostap: Janusz Dziedzic <janusz.dziedzic@tieto.com> >> > >> > Thanks a lot for the rewrite - looks good to me and works well here, so >> > feel free to add: >> > >> > Tested-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> >> > >> Thanks for review and tests. >> >> > Also the patch looks good in general. This series is still missing the >> > dfs channel list patch which is in another patch Jouni has still backed >> > up [1] (doesn't apply currently, but it's trivial to fix). Would be good >> > to merge this as well. >> > >> > Just one remark: What do we do if all channels are taken? Your current >> > implementation will then simply close hostapd, but I'm not sure if this >> > is desired behaviour - shouldn't we rather keep it running and wait for one >> > channel to come back (when the Non-occupancy-period is over) and try again? >> > >> I think we should never hit this case. Base of spec I changed getting >> new channel little bit. >> Currently we get random channel from list of: >> - "standard" 5G channels (!disabled) - defined by regdomain >> - DFS usable + availabe channels. >> >> Even all DFS channels will be unavailable we should get still >> "standard" channels list I think. > > If we want to use 5 GHz outdoors we may only use outdoor channels. These must be > limited e.g. by using the DFS channel option in the pending patch[1]. Jumping back > to a non-DFS channel is not an option for outdoors, at least in Europe all outdoor > channels require DFS. So it might happen that all channels become unavailable for > some time. > > In this case, your current implementation will just stop the hostapd (I've tested > after applying the channel list patch [1]), and while this is one option to handle > it, I feel that's not the best ... :) > Good catch. So I think we can add this as a separate patch + proper NOP handling. This should be quite easy. BR Janusz
On Fri, Sep 20, 2013 at 11:38:48AM +0200, Janusz Dziedzic wrote: > On 19 September 2013 13:51, Simon Wunderlich > <simon.wunderlich@s2003.tu-chemnitz.de> wrote: > > Hey Janusz, > > > > On Tue, Sep 17, 2013 at 08:44:37PM +0200, Janusz Dziedzic wrote: > >> On 17 September 2013 18:25, Simon Wunderlich > >> <simon.wunderlich@s2003.tu-chemnitz.de> wrote: > >> > Hey Janusz, > >> > > >> > On Mon, Sep 16, 2013 at 07:40:07AM +0200, Janusz Dziedzic wrote: > >> >> Add DFS CAC handling, radar detection. > >> >> By default after radar detected or > >> >> channel became unavailable random channel > >> >> will be choose. > >> >> > >> >> Signed-hostap: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> > >> >> Signed-hostap: Janusz Dziedzic <janusz.dziedzic@tieto.com> > >> > > >> > Thanks a lot for the rewrite - looks good to me and works well here, so > >> > feel free to add: > >> > > >> > Tested-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> > >> > > >> Thanks for review and tests. > >> > >> > Also the patch looks good in general. This series is still missing the > >> > dfs channel list patch which is in another patch Jouni has still backed > >> > up [1] (doesn't apply currently, but it's trivial to fix). Would be good > >> > to merge this as well. > >> > > >> > Just one remark: What do we do if all channels are taken? Your current > >> > implementation will then simply close hostapd, but I'm not sure if this > >> > is desired behaviour - shouldn't we rather keep it running and wait for one > >> > channel to come back (when the Non-occupancy-period is over) and try again? > >> > > >> I think we should never hit this case. Base of spec I changed getting > >> new channel little bit. > >> Currently we get random channel from list of: > >> - "standard" 5G channels (!disabled) - defined by regdomain > >> - DFS usable + availabe channels. > >> > >> Even all DFS channels will be unavailable we should get still > >> "standard" channels list I think. > > > > If we want to use 5 GHz outdoors we may only use outdoor channels. These must be > > limited e.g. by using the DFS channel option in the pending patch[1]. Jumping back > > to a non-DFS channel is not an option for outdoors, at least in Europe all outdoor > > channels require DFS. So it might happen that all channels become unavailable for > > some time. > > > > In this case, your current implementation will just stop the hostapd (I've tested > > after applying the channel list patch [1]), and while this is one option to handle > > it, I feel that's not the best ... :) > > > > Good catch. So I think we can add this as a separate patch + proper > NOP handling. This should be quite easy. > Yeah, sounds good. Let's see what Jouni says about the current patchset. :) Thanks, Simon
On Thu, Sep 19, 2013 at 01:51:37PM +0200, Simon Wunderlich wrote: > If we want to use 5 GHz outdoors we may only use outdoor channels. These must be > limited e.g. by using the DFS channel option in the pending patch[1]. Jumping back > to a non-DFS channel is not an option for outdoors, at least in Europe all outdoor > channels require DFS. So it might happen that all channels become unavailable for > some time. > > In this case, your current implementation will just stop the hostapd (I've tested > after applying the channel list patch [1]), and while this is one option to handle > it, I feel that's not the best ... :) > > > > > > > > > [1] http://w1.fi/p/dfs/0002-hostapd-Add-config-option-for-DFS-channels.patch Now that the base DFS changes are in hostap.git, we should decide what to do about this dfs_chanlist config option. Do we still need it and if so, would someone care to submit a rebased version on top of the current hostap.git master branch?
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index d9df9cc..cedfe8e 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -712,7 +712,7 @@ int hostapd_start_dfs_cac(struct hostapd_data *hapd, int freq, int flags) return -1; } - if (!(hapd->iface->dfs_state & DFS_ENABLED)) { + if (!hapd->iface->conf->ieee80211h) { wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality " "is not enabled"); return -1; diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index a54ab0c..68c12d2 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -788,8 +788,26 @@ static void hostapd_event_get_survey(struct hostapd_data *hapd, static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd, struct dfs_event *radar) { + int res; wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq); + if (!hapd->iconf->ieee80211h) + return; + + /* mark radar frequency as invalid */ + res = ieee802_11_set_dfs_state(hapd, radar->freq, + HOSTAPD_CHAN_DFS_UNAVAILABLE); + + /* other frequency, just mark it and return. */ + if (hapd->iface->freq != radar->freq) + return; + + /* we are working on non-DFS channel - skip event */ + if (res == 0) + return; + + /* radar detected while operating, switch the channel. */ + ieee802_11_start_channel_switch(hapd); } @@ -797,6 +815,7 @@ static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd, struct dfs_event *radar) { wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq); + ieee802_11_complete_cac(hapd, 1, radar->freq); } @@ -804,6 +823,7 @@ static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd, struct dfs_event *radar) { wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq); + ieee802_11_complete_cac(hapd, 0, radar->freq); } @@ -811,6 +831,7 @@ static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd, struct dfs_event *radar) { wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); + ieee802_11_set_dfs_state(hapd, radar->freq, HOSTAPD_CHAN_DFS_USABLE); } diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 55e6c95..4af7845 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -932,10 +932,8 @@ static int setup_interface(struct hostapd_iface *iface) return 0; } - if (iface->conf->ieee80211h) { + if (iface->conf->ieee80211h) wpa_printf(MSG_DEBUG, "DFS support is enabled"); - iface->dfs_state |= DFS_ENABLED; - } } return hostapd_setup_interface_complete(iface, 0); } @@ -946,6 +944,9 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) struct hostapd_data *hapd = iface->bss[0]; size_t j; u8 *prev_addr; + int flags; + struct hostapd_channel_data *channel; + if (err) { wpa_printf(MSG_ERROR, "Interface initialization failed"); @@ -961,6 +962,41 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) hostapd_hw_mode_txt(hapd->iconf->hw_mode), hapd->iconf->channel, iface->freq); + /* Handle DFS channel */ +check_dfs_chan_again: + flags = hostapd_hw_get_channel_flag(hapd, hapd->iconf->channel); + if (flags & HOSTAPD_CHAN_RADAR) { + switch(flags & HOSTAPD_CHAN_DFS_MASK) { + case HOSTAPD_CHAN_DFS_USABLE: + wpa_printf(MSG_DEBUG, "DFS start CAC on %dMHz", iface->freq); + if (hostapd_start_dfs_cac(hapd, hapd->iface->freq, flags)) { + wpa_printf(MSG_DEBUG, "DFS start_dfs_cac() failed\n"); + return -1; + } + /* Continue initialisation after CAC */ + return 0; + break; + case HOSTAPD_CHAN_DFS_UNAVAILABLE: + wpa_printf(MSG_DEBUG, "HOSTAPD_CHAN_DFS_UNAVAILABLE, get new chan"); + /* find other channel here */ + channel = hostapd_dfs_get_valid_channel(hapd); + if (!channel) { + wpa_printf(MSG_ERROR, "could not get valid channel"); + return -1; + } + hapd->iconf->channel = channel->chan; + hapd->iface->freq = channel->freq; + goto check_dfs_chan_again; + break; + case HOSTAPD_CHAN_DFS_AVAILABLE: + /* We don't need CAC here */ + wpa_printf(MSG_DEBUG, "HOSTAPD_CHAN_DFS_AVAILABLE, skip CAC"); + break; + default: + break; + } + } + if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq, hapd->iconf->channel, hapd->iconf->ieee80211n, @@ -1477,3 +1513,61 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, ap_handle_timer, hapd, sta); } + +static int hostapd_dfs_find_channel(struct hostapd_data *hapd, + struct hostapd_channel_data **ret_chan, + int idx) +{ + struct hostapd_hw_modes *mode; + struct hostapd_channel_data *chan; + int i, channel_idx = 0; + + mode = hapd->iface->current_mode; + + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; + + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + + if (chan->flag & HOSTAPD_CHAN_RADAR && + chan->flag & HOSTAPD_CHAN_DFS_UNAVAILABLE) + continue; + + if (ret_chan && idx == channel_idx) { + wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan); + *ret_chan = chan; + return idx; + } + channel_idx++; + } + return channel_idx; +} + +struct hostapd_channel_data * hostapd_dfs_get_valid_channel( + struct hostapd_data *hapd) +{ + struct hostapd_hw_modes *mode; + struct hostapd_channel_data *chan = NULL; + int channel_idx, new_channel_idx; + u32 _rand; + + wpa_printf(MSG_DEBUG, "DFS: Selecting random channel"); + + if (hapd->iface->current_mode == NULL) + return NULL; + + mode = hapd->iface->current_mode; + if (mode->mode != HOSTAPD_MODE_IEEE80211A) + return NULL; + + /* get random available channel */ + channel_idx = hostapd_dfs_find_channel(hapd, NULL, 0); + if (channel_idx > 0) { + os_get_random((u8 *) &_rand, sizeof(_rand)); + new_channel_idx = _rand % channel_idx; + hostapd_dfs_find_channel(hapd, &chan, new_channel_idx); + }; + + return chan; +} diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index b5595e7..379dd8d 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -315,18 +315,6 @@ struct hostapd_iface { /* lowest observed noise floor in dBm */ s8 lowest_nf; - - /* DFS functionality is enabled. */ -#define DFS_ENABLED BIT(0) - - /* DFS channel availability check during initialization. */ -#define DFS_CAC_ACTIVE BIT(1) - - /* DFS channel availability check completed successfully. */ -#define DFS_CAC_SUCCESS BIT(2) - - u8 dfs_state; /* DFS_* bitfield */ - #ifdef CONFIG_ACS unsigned int acs_num_completed_scans; #endif /* CONFIG_ACS */ @@ -392,4 +380,6 @@ const struct hostapd_eap_user * hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity, size_t identity_len, int phase2); +struct hostapd_channel_data * hostapd_dfs_get_valid_channel( + struct hostapd_data *hapd); #endif /* HOSTAPD_H */ diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 781f826..52bb5d0 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -2239,5 +2239,78 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); } +int ieee802_11_set_dfs_state(struct hostapd_data *hapd, int freq, u32 state) +{ + struct hostapd_hw_modes *mode; + struct hostapd_channel_data *chan = NULL; + int i; + + mode = hapd->iface->current_mode; + if (mode == NULL) + return 0; + + if (mode->mode != HOSTAPD_MODE_IEEE80211A) { + wpa_printf(MSG_WARNING, "current_mode != IEEE80211A"); + return 0; + } + + for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { + chan = &hapd->iface->current_mode->channels[i]; + if (chan->freq == freq) { + if (chan->flag & HOSTAPD_CHAN_RADAR) { + chan->flag &= ~HOSTAPD_CHAN_DFS_MASK; + chan->flag |= state; + return 1; /* Channel found */ + } + } + } + wpa_printf(MSG_WARNING, "Can't set DFS state for freq %d MHz", freq); + return 0; +} + +int ieee802_11_complete_cac(struct hostapd_data *hapd, int success, int freq) +{ + struct hostapd_channel_data *channel; + int err = 1; + + if (success) { + /* Complete iface/ap configuration */ + ieee802_11_set_dfs_state(hapd, freq, HOSTAPD_CHAN_DFS_AVAILABLE); + hostapd_setup_interface_complete(hapd->iface, 0); + } else { + /* Switch to new channel */ + ieee802_11_set_dfs_state(hapd, freq, HOSTAPD_CHAN_DFS_UNAVAILABLE); + channel = hostapd_dfs_get_valid_channel(hapd); + if (channel) { + hapd->iconf->channel = channel->chan; + hapd->iface->freq = channel->freq; + err = 0; + } else + wpa_printf(MSG_ERROR, "No valid channel available"); + + hostapd_setup_interface_complete(hapd->iface, err); + } + + return 0; +} + +int ieee802_11_start_channel_switch(struct hostapd_data *hapd) +{ + struct hostapd_channel_data *channel; + wpa_printf(MSG_DEBUG, "%s called\n", __func__); + int err = 1; + + channel = hostapd_dfs_get_valid_channel(hapd); + if (channel) { + hapd->iconf->channel = channel->chan; + hapd->iface->freq = channel->freq; + err = 0; + } + + hapd->driver->stop_ap(hapd->drv_priv); + + hostapd_setup_interface_complete(hapd->iface, err); + return 0; +} #endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 2aab56d..358edfd 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -80,5 +80,7 @@ u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid); int hostapd_update_time_adv(struct hostapd_data *hapd); void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr); u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid); - +int ieee802_11_complete_cac(struct hostapd_data *hapd, int success, int freq); +int ieee802_11_set_dfs_state(struct hostapd_data *hapd, int freq, u32 state); +int ieee802_11_start_channel_switch(struct hostapd_data *hapd); #endif /* IEEE802_11_H */