[PATCH v3 3/3] WNM: Use standard BSS selection and enable abridged bit handling

Janusz Dziedzic janusz.dziedzic at gmail.com
Tue Dec 16 04:20:44 PST 2025


czw., 19 wrz 2024 o 12:21 Benjamin Berg <benjamin at sipsolutions.net> napisał(a):
>
> From: Benjamin Berg <benjamin.berg at intel.com>
>
> Most of the logic to reject BSSs during transition has been moved into
> wnm_is_bss_excluded. In addition to this, since commit 67bf89f55442
> ("WNM: Choose the best available BSS, not just the first one") we will
> simply choose the BSS with the best throughput.
>
> Overall, this matches the behaviour that the supplicant will use anyway
> in wpa_supplicant_select_bss. The only bigger difference is that using
> this will check all known BSSs instead of only the ones in the candidate
> list. This means that with this change the abridged bit is handled
> according to spec.
>
> There are some subtle changes to the logic. Once is, that candidates
> with a very low signal level are not explicitly dropped anymore.
> However, that code pre-dates the logic to prefer the best BSS and should
> not be relevant anymore.
>
> Another small adjustment is to change the custom logic to avoid roaming
> when it is not needed to use wpa_supplicant_need_to_roam_within_ess.
>
> Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
>
> ---
>
> v3: Apply normal roaming rules, to fix the issue found by Ben Greear
> Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
> ---
>  wpa_supplicant/events.c           |   2 +-
>  wpa_supplicant/wnm_sta.c          | 137 +++++-------------------------
>  wpa_supplicant/wpa_supplicant_i.h |   5 ++
>  3 files changed, 26 insertions(+), 118 deletions(-)
>
> diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
> index 668068167f..8e43db3e41 100644
> --- a/wpa_supplicant/events.c
> +++ b/wpa_supplicant/events.c
> @@ -1733,7 +1733,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
>  }
>
>
> -static struct wpa_bss *
> +struct wpa_bss *
>  wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
>                           struct wpa_ssid *group,
>                           struct wpa_ssid **selected_ssid,
> diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
> index dcef8053ee..0ee47c2b4b 100644
> --- a/wpa_supplicant/wnm_sta.c
> +++ b/wpa_supplicant/wnm_sta.c
> @@ -687,117 +687,6 @@ end:
>  }
>
>
> -static struct wpa_bss * find_better_target(struct wpa_bss *a,
> -                                          struct wpa_bss *b)
> -{
> -       if (!a)
> -               return b;
> -       if (!b)
> -               return a;
> -
> -       if (a->est_throughput > b->est_throughput) {
> -               wpa_printf(MSG_DEBUG, "WNM: A is better: " MACSTR
> -                          " est-tput: %d  B: " MACSTR " est-tput: %d",
> -                          MAC2STR(a->bssid), a->est_throughput,
> -                          MAC2STR(b->bssid), b->est_throughput);
> -               return a;
> -       }
> -
> -       wpa_printf(MSG_DEBUG, "WNM: B is better, A: " MACSTR
> -                  " est-tput: %d  B: " MACSTR " est-tput: %d",
> -                  MAC2STR(a->bssid), a->est_throughput,
> -                  MAC2STR(b->bssid), b->est_throughput);
> -       return b;
> -}
> -
> -static struct wpa_bss *
> -compare_scan_neighbor_results(struct wpa_supplicant *wpa_s,
> -                             enum mbo_transition_reject_reason *reason)
> -{
> -       u8 i;
> -       struct wpa_bss *bss = wpa_s->current_bss;
> -       struct wpa_bss *target;
> -       struct wpa_bss *best_target = NULL;
> -       struct wpa_bss *bss_in_list = NULL;
> -
> -       if (!bss)
> -               return NULL;
> -
> -       wpa_printf(MSG_DEBUG, "WNM: Current BSS " MACSTR " RSSI %d",
> -                  MAC2STR(wpa_s->bssid), bss->level);
> -
> -       for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
> -               struct neighbor_report *nei;
> -
> -               nei = &wpa_s->wnm_neighbor_report_elements[i];
> -
> -               target = wpa_bss_get_bssid(wpa_s, nei->bssid);
> -               if (!target) {
> -                       wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
> -                                  " (pref %d) not found in scan results",
> -                                  MAC2STR(nei->bssid),
> -                                  nei->preference_present ? nei->preference :
> -                                  -1);
> -                       continue;
> -               }
> -
> -               /*
> -                * TODO: Could consider allowing transition to another ESS if
> -                * PMF was enabled for the association.
> -                */
> -               if (!wpa_scan_res_match(wpa_s, 0, target, wpa_s->current_ssid,
> -                                       1, 0)) {
> -                       wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
> -                                  " (pref %d) does not match the current network profile",
> -                                  MAC2STR(nei->bssid),
> -                                  nei->preference_present ? nei->preference :
> -                                  -1);
> -                       continue;
> -               }
> -
> -               if (target->level < bss->level && target->level < -80) {
> -                       wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
> -                                  " (pref %d) does not have sufficient signal level (%d)",
> -                                  MAC2STR(nei->bssid),
> -                                  nei->preference_present ? nei->preference :
> -                                  -1,
> -                                  target->level);
> -                       continue;
> -               }
> -
> -               best_target = find_better_target(target, best_target);
> -               if (target == bss)
> -                       bss_in_list = bss;
> -       }
> -
> -       target = best_target;
> -
> -       if (!target)
> -               return NULL;
> -
> -       wpa_printf(MSG_DEBUG,
> -                  "WNM: Found an acceptable preferred transition candidate BSS "
> -                  MACSTR " (RSSI %d, tput: %d  bss-tput: %d)",
> -                  MAC2STR(target->bssid), target->level,
> -                  target->est_throughput, bss->est_throughput);
> -
> -       if (!bss_in_list)
> -               return target;
> -
> -       if ((!target->est_throughput && !bss_in_list->est_throughput) ||
> -           (target->est_throughput > bss_in_list->est_throughput &&
> -            target->est_throughput - bss_in_list->est_throughput >
> -            bss_in_list->est_throughput >> 4)) {
> -               /* It is more than 100/16 percent better, so switch. */
> -               return target;
> -       }
> -
> -       wpa_printf(MSG_DEBUG,
> -                  "WNM: Stay with our current BSS, not enough change in estimated throughput to switch");
> -       return bss_in_list;
> -}
> -
> -
>  static int wpa_bss_ies_eq(struct wpa_bss *a, struct wpa_bss *b, u8 eid)
>  {
>         const u8 *ie_a, *ie_b;
> @@ -1115,11 +1004,12 @@ static void wnm_bss_tm_connect(struct wpa_supplicant *wpa_s,
>
>  int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
>  {
> -       struct wpa_bss *bss;
> +       struct wpa_bss *bss, *current_bss = wpa_s->current_bss;
>         struct wpa_ssid *ssid = wpa_s->current_ssid;
>         enum bss_trans_mgmt_status_code status = WNM_BSS_TM_REJECT_UNSPECIFIED;
>         enum mbo_transition_reject_reason reason =
>                 MBO_TRANSITION_REJECT_REASON_UNSPECIFIED;
> +       struct wpa_ssid *selected_ssid = NULL;
>
>         if (!wpa_s->wnm_dialog_token)
>                 return 0;
> @@ -1143,7 +1033,7 @@ int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
>         fetch_drv_mbo_candidate_info(wpa_s, &reason);
>
>         /* Compare the Neighbor Report and scan results */
> -       bss = compare_scan_neighbor_results(wpa_s, &reason);
> +       bss = wpa_supplicant_select_bss(wpa_s, ssid, &selected_ssid, 1);
>  #ifdef CONFIG_MBO
>         if (!bss && wpa_s->wnm_mbo_trans_reason_present &&
>             wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
> @@ -1169,7 +1059,7 @@ int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
>                                 nei->drv_mbo_reject = 0;
>                 }
>
> -               bss = compare_scan_neighbor_results(wpa_s, &reason);
> +               bss = wpa_supplicant_select_bss(wpa_s, ssid, &selected_ssid, 1);
>         }
>  #endif /* CONFIG_MBO */
>
> @@ -1194,20 +1084,33 @@ int wnm_scan_process(struct wpa_supplicant *wpa_s, bool pre_scan_check)
>                         return 0;
>
>  #ifndef CONFIG_NO_ROAMING
> -               if (wpa_s->current_bss && bss != wpa_s->current_bss &&
> +               if (current_bss && bss != current_bss &&
>                     wpa_supplicant_need_to_roam_within_ess(wpa_s, bss,
> -                                                          wpa_s->current_bss,
> -                                                          false))
> +                                                          current_bss, false))
>                         return 0;
>  #endif /* CONFIG_NO_ROAMING */
>         }
>
> +       /* Apply normal roaming rules if we can stay with the current BSS */
> +       if (current_bss && bss != current_bss &&
> +           wpa_scan_res_match(wpa_s, 0, current_bss, wpa_s->current_ssid,
> +                              1, 0) &&
> +           !wpa_supplicant_need_to_roam_within_ess(wpa_s, current_bss, bss,
> +                                                   true))
> +               bss = current_bss;
> +
>         if (!bss) {
>                 wpa_printf(MSG_DEBUG, "WNM: No BSS transition candidate match found");
>                 status = WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES;
>                 goto send_bss_resp_fail;
>         }
>
> +       wpa_printf(MSG_DEBUG,
> +                  "WNM: Found an acceptable preferred transition candidate BSS "
> +                  MACSTR " (RSSI %d, tput: %d  bss-tput: %d)",
> +                  MAC2STR(bss->bssid), bss->level, bss->est_throughput,
> +                  current_bss ? current_bss->est_throughput : -1);
> +
>         /* Associate to the network */
>         wnm_bss_tm_connect(wpa_s, bss, ssid, 1);
>         return 1;
> diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
> index 7c51cdb20e..0bd4fcdedd 100644
> --- a/wpa_supplicant/wpa_supplicant_i.h
> +++ b/wpa_supplicant/wpa_supplicant_i.h
> @@ -1965,6 +1965,11 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
>                                      struct wpa_ssid *group,
>                                      int only_first_ssid, int debug_print);
>
> +struct wpa_bss * wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
> +                                          struct wpa_ssid *group,
> +                                          struct wpa_ssid **selected_ssid,
> +                                          int only_first_ssid);
> +
>  int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
>                                                 enum wpa_driver_if_type if_type,
>                                                 unsigned int *num,

Not sure you see same problem (have multiple APs with same SSID and
testing BTM) - CONFIG_NO_ROAMING set:

 1764069336.216142: WNM: BSS Transition Candidate List
1764069336.216153: 0: 58:00:32:c0:13:23 info=0x9af op_class=128
chan=52 phy=9 pref=1 freq=5260
1764069336.216177: WNM: Candidate list valid for 102 ms
1764069336.217207: nl80211: Received scan results (32 BSSes)
1764069336.217347: nl80211: Scan results indicate BSS status with
58:00:32:c0:13:22 as associated

1764069336.222433: wlan2:    selected BSS 7a:d4:37:e7:4e:1f ssid='testap'
1764069336.222461: WNM: Found an acceptable preferred transition
candidate BSS 7a:d4:37:e7:4e:1f (RSSI -16, tput: 143402  bss-tput:
143402)
1764069336.222512: wlan2: WNM: Transition to BSS 7a:d4:37:e7:4e:1f
based on BSS Transition Management Request (old BSSID
58:00:32:c0:13:22 after_new_scan=1)
1764069336.222539: WNM: Sending successful BSS Transition Management Response
1764069336.222551: WNM: Send BSS Transition Management Response to
58:00:32:c0:13:22 dialog_token=1 status=0 reason=0 delay=0
1764069336.222577: WNM: Add candidate list to BSS Transition
Management Response frame


Looks like find first AP from scan results and use it - just skip BTM
prefered candidate.
After revert works correctly and connect to bssid from candidate list.
Testing it using latest OpenWrt (with Intel BE200 as client), so could
be already fixed in main?


Didn't dig in that a lot, just revert this one.
After revert:
1764069110.452716: WNM: BSS Transition Candidate List
1764069110.452729: 0: 58:00:32:c0:13:23 info=0x9af op_class=128
chan=52 phy=9 pref=1 freq=5260
1764069110.452752: WNM: Candidate list valid for 102 ms
1764069110.453740: nl80211: Received scan results (32 BSSes)
1764069110.453876: nl80211: Scan results indicate BSS status with
58:00:32:c0:13:22 as associated
1764069110.455368: wlan2: BSS: Start scan result update 2
1764069110.455928: wlan2: WNM: Process scan results for BSS Transition
Management
1764069110.455977: WNM: Current BSS 58:00:32:c0:13:22 RSSI -35
1764069110.456003: Candidate BSS 58:00:32:c0:13:23 (pref 1) not found
in scan results
1764069110.456021: WNM: No valid match in previous scan results - try a new scan
1764069110.456038: WNM: Scan 1 frequencies based on transition candidate list
1764069110.456051: WNM: Scan only for a specific BSSID since there is
only a single candidate 58:00:32:c0:13:23

1764069110.603181: wlan2: WNM: Process scan results for BSS Transition
Management
1764069110.603225: WNM: Current BSS 58:00:32:c0:13:22 RSSI -35
1764069110.603512: WNM: Found an acceptable preferred transition
candidate BSS 58:00:32:c0:13:23 (RSSI -40, tput: 600502  bss-tput:
143402)
1764069110.603564: wlan2: WNM: Transition to BSS 58:00:32:c0:13:23
based on BSS Transition Management Request (old BSSID
58:00:32:c0:13:22 after_new_scan=1)
1764069110.603592: WNM: Sending successful BSS Transition Management Response
1764069110.603604: WNM: Send BSS Transition Management Response to
58:00:32:c0:13:22 dialog_token=1 status=0 reason=0 delay=0
1764069110.603629: WNM: Add candidate list to BSS Transition
Management Response frame

BR
Janusz



More information about the Hostap mailing list