[PATCH 2/2] wpa_supplicant: increase AUTH timeout if CAC is started

Дмитрий Лебедь lebed.dmitry at gmail.com
Thu Apr 5 05:41:20 PDT 2018


2018-04-05 13:44 GMT+03:00 Janusz Dziedzic <janusz.dziedzic at gmail.com>:
> 2018-04-04 22:44 GMT+02:00 Dmitry Lebed <lebed.dmitry at gmail.com>:
>> From: Dmitry Lebed <dlebed at quantenna.com>
>>
>> Increase AUTH timeout if CAC is started while AUTH timeout
>> is active.
>> Timeout is increased by dfs_cac_ms from channel data, or
>> by max CAC time (10 minutes) if dfs_cac_ms is not defined.
>> It's needed for some complex cases, e.g. when STA is acting
>> as active slave with DFS offload enabled and decided to start
>> CAC after receiving CONNECT command, in such case 10s timeout
>> is too small and wpa_supplicant need to wait for CAC completion
>> or CAC timeout (up to 10 minutes).
>> Without such timeout modification wpa_supplicant will unable
>> to connect to AP on DFS channel, since default AUTH timeout (10s)
>> is smaller than minumum CAC time (60s).
>>
>> Tested with nl80211 DFS offload implementation.
>>
>
> Interesting.
>
> As I understand STA don't need to wait CAC time. Just check if there
> is an AP1 (BSS1) on such channel and just connect. An AP is
> responsible for radar detection - CSA and other - for BSS1.
> Probably I don't understand your case - why you need CAC for STA interface ...?
>
> Interesting case will be two interfaces on DFS channel here (STA and
> AP) - multiVIF on the same channel.
> So local STA try to connect to another AP1 (BSS1) in the network, and
> local AP2 (BSS2) doing CAC.
>
> Not sure spec cover this case (for FCC/EU) while you have station
> which don't need CAC and have an AP2 that need CAC - both using same
> radio/channel :)
>
> So I think you don't need CAC for STA, and could connect to BSS1 -
> while AP1 will monitor RADARs for BSS1.
> But you can't start beaconing for your local AP2 (BSS2) before you pass CAC.
>
> Not sure current regd can cover this case correctly.
>
> BR
> Janusz

Hi Janusz,

This change is needed to fix wpa_supplicant behavior in some advanced use cases.
One of such cases is repeater (as you've mentioned, it's a multi-VIF
AP+STA on the same WMAC interface).

As I remember, nobody forbids STA to use CAC for DFS channels if it
wants, so STA interface
in DFS-offload case can start CAC on CONNECT call.

The problem with CAC and regulatory compliance is that you can't
transmit anything
(even if it's STA VIF association packets) until CAC is done, sine
both VIF are sharing the same WMAC and channel.
Regulatory specs do not say anything about VIFs and that one VIF can
transmit after beacon reception (STA)
and another can transmit only after CAC (AP), instead of this
regulatory (as I understand) states that the whole
device should not transmit at all (on DFS band it wants to use) until
CAC is completed.

Thus, your STA VIF will not be able to associate (because TX will be
disabled) and will restart association
after 10s timeout (which is much less than CAC time), making a lot of
disturbance to HW, trying to scan and associate again.

You also need to consider that AP VIF and STA VIF are sharing the same
channel and same WMAC, so
even SCAN call after CONNECT timeout during CAC will abort AP's VIF
CAC because of channel change.

My proposed change is just wpa_supplicant CONNECT timeout prolongation
if CAC_STARTED event received,
it will minimize disturbance to HW while it's doing CAC and will just
wait until CAC is completed.

Thanks,
Dmitry

>
>> Signed-off-by: Dmitry Lebed <dlebed at quantenna.com>
>> ---
>>  wpa_supplicant/events.c           | 97 +++++++++++++++++++++++++++++++++++----
>>  wpa_supplicant/wpa_supplicant.c   | 21 +++++++++
>>  wpa_supplicant/wpa_supplicant_i.h |  4 ++
>>  3 files changed, 112 insertions(+), 10 deletions(-)
>>
>> diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
>> index bb76ca93d..e6a693a7d 100644
>> --- a/wpa_supplicant/events.c
>> +++ b/wpa_supplicant/events.c
>> @@ -3770,6 +3770,80 @@ static void wpa_supplicant_event_port_authorized(struct wpa_supplicant *wpa_s)
>>         }
>>  }
>>
>> +static size_t wpa_supplicant_event_cac_ms(const struct wpa_supplicant *wpa_s,
>> +                                         int freq)
>> +{
>> +       size_t i, j;
>> +
>> +       for (i = 0; i < wpa_s->hw.num_modes; i++) {
>> +               const struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
>> +
>> +               for (j = 0; j < mode->num_channels; j++) {
>> +                       const struct hostapd_channel_data *chan;
>> +
>> +                       chan = &mode->channels[j];
>> +                       if (chan->freq == freq)
>> +                               return chan->dfs_cac_ms;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static void wpa_supplicant_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
>> +                                                struct dfs_event *radar)
>> +{
>> +#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
>> +       if (wpa_s->ap_iface != NULL) {
>> +               wpas_ap_event_dfs_cac_started(wpa_s, radar);
>> +       } else
>> +#endif
>> +       {
>> +               size_t cac_time = wpa_supplicant_event_cac_ms(wpa_s,
>> +                                                             radar->freq);
>> +
>> +               cac_time /= 1000; /* convert from ms to sec */
>> +
>> +               if (!cac_time)
>> +                       cac_time = 10 * 60; /* max timeout - 10 minutes */
>> +
>> +               /* restart auth timeout: CAC time added to initial timeout */
>> +               wpa_supplicant_auth_timeout_restart(wpa_s, cac_time);
>> +       }
>> +}
>> +
>> +
>> +static void wpa_supplicant_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
>> +                                                 struct dfs_event *radar)
>> +{
>> +#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
>> +       if (wpa_s->ap_iface != NULL) {
>> +               wpas_ap_event_dfs_cac_finished(wpa_s, radar);
>> +       } else
>> +#endif
>> +       {
>> +               /* restart auth timeout with original value
>> +                * after CAC is finished */
>> +               wpa_supplicant_auth_timeout_restart(wpa_s, 0);
>> +       }
>> +}
>> +
>> +
>> +static void wpa_supplicant_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
>> +                                                struct dfs_event *radar)
>> +{
>> +#if defined(NEED_AP_MLME) && defined(CONFIG_AP)
>> +       if (wpa_s->ap_iface != NULL) {
>> +               wpas_ap_event_dfs_cac_aborted(wpa_s, radar);
>> +       } else
>> +#endif
>> +       {
>> +               /* restart auth timeout with original value
>> +                * after CAC is aborted */
>> +               wpa_supplicant_auth_timeout_restart(wpa_s, 0);
>> +       }
>> +}
>> +
>>
>>  static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
>>                                             union wpa_event_data *data)
>> @@ -4185,25 +4259,28 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
>>                 if (data)
>>                         wpas_ap_event_dfs_radar_detected(wpa_s, &data->dfs_event);
>>                 break;
>> +       case EVENT_DFS_NOP_FINISHED:
>> +               if (data)
>> +                       wpas_ap_event_dfs_cac_nop_finished(wpa_s,
>> +                                                          &data->dfs_event);
>> +               break;
>> +#endif /* NEED_AP_MLME */
>> +#endif /* CONFIG_AP */
>>         case EVENT_DFS_CAC_STARTED:
>>                 if (data)
>> -                       wpas_ap_event_dfs_cac_started(wpa_s, &data->dfs_event);
>> +                       wpa_supplicant_event_dfs_cac_started(wpa_s,
>> +                                                            &data->dfs_event);
>>                 break;
>>         case EVENT_DFS_CAC_FINISHED:
>>                 if (data)
>> -                       wpas_ap_event_dfs_cac_finished(wpa_s, &data->dfs_event);
>> +                       wpa_supplicant_event_dfs_cac_finished(wpa_s,
>> +                                                             &data->dfs_event);
>>                 break;
>>         case EVENT_DFS_CAC_ABORTED:
>>                 if (data)
>> -                       wpas_ap_event_dfs_cac_aborted(wpa_s, &data->dfs_event);
>> -               break;
>> -       case EVENT_DFS_NOP_FINISHED:
>> -               if (data)
>> -                       wpas_ap_event_dfs_cac_nop_finished(wpa_s,
>> -                                                       &data->dfs_event);
>> +                       wpa_supplicant_event_dfs_cac_aborted(wpa_s,
>> +                                                            &data->dfs_event);
>>                 break;
>> -#endif /* NEED_AP_MLME */
>> -#endif /* CONFIG_AP */
>>         case EVENT_RX_MGMT: {
>>                 u16 fc, stype;
>>                 const struct ieee80211_mgmt *mgmt;
>> diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
>> index dcec68a03..b9fed8136 100644
>> --- a/wpa_supplicant/wpa_supplicant.c
>> +++ b/wpa_supplicant/wpa_supplicant.c
>> @@ -243,10 +243,31 @@ void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
>>         wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
>>                 "%d usec", sec, usec);
>>         eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
>> +       wpa_s->last_auth_timeout_sec = sec;
>>         eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
>>  }
>>
>>
>> +/*
>> + * wpa_supplicant_auth_timeout_restart - Restart and change timeout
>> + * @wpa_s: Pointer to wpa_supplicant data
>> + * @sec_diff: difference in seconds applied to original timeout value
>> + */
>> +void wpa_supplicant_auth_timeout_restart(struct wpa_supplicant *wpa_s,
>> +                                        int sec_diff)
>> +{
>> +       int new_sec = wpa_s->last_auth_timeout_sec + sec_diff;
>> +
>> +       if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) {
>> +               wpa_dbg(wpa_s, MSG_DEBUG,
>> +                       "Authentication timeout restart: %d sec ", new_sec);
>> +               eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
>> +               eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout,
>> +                                      wpa_s, NULL);
>> +       }
>> +}
>> +
>> +
>>  /**
>>   * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
>>   * @wpa_s: Pointer to wpa_supplicant data
>> diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
>> index d5bfa7ddf..3f3f6b755 100644
>> --- a/wpa_supplicant/wpa_supplicant_i.h
>> +++ b/wpa_supplicant/wpa_supplicant_i.h
>> @@ -1182,6 +1182,8 @@ struct wpa_supplicant {
>>         /* RIC elements for FT protocol */
>>         struct wpabuf *ric_ies;
>>
>> +       int last_auth_timeout_sec;
>> +
>>  #ifdef CONFIG_DPP
>>         struct dl_list dpp_bootstrap; /* struct dpp_bootstrap_info */
>>         struct dl_list dpp_configurator; /* struct dpp_configurator */
>> @@ -1255,6 +1257,8 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s);
>>  void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr);
>>  void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
>>                                      int sec, int usec);
>> +void wpa_supplicant_auth_timeout_restart(struct wpa_supplicant *wpa_s,
>> +                                        int sec_diff);
>>  void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s);
>>  void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
>>                               enum wpa_states state);
>> --
>> 2.16.3
>>
>>
>> _______________________________________________
>> Hostap mailing list
>> Hostap at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/hostap
>
>
>
> --
> Janusz Dziedzic



-- 
Best regards
Dmitry Lebed



More information about the Hostap mailing list