diff --git a/package/network/services/hostapd/patches/174-ap-keep-the-obss-colors-of-a-radio.patch b/package/network/services/hostapd/patches/174-ap-keep-the-obss-colors-of-a-radio.patch new file mode 100644 index 00000000000..b5163862d5c --- /dev/null +++ b/package/network/services/hostapd/patches/174-ap-keep-the-obss-colors-of-a-radio.patch @@ -0,0 +1,302 @@ +From: Felix Fietkau +Date: Sat, 3 Oct 2026 22:00:00 +0200 +Subject: [PATCH] AP: keep the OBSS colours of a radio + +hostapd kept the colours in use in color_collision_bitmap of a BSS. +hostapd_switch_color() replaced it with the bitmap of each collision +event or BSS Color Collision report, on the first BSS of the radio, and +a BSS Color In Use report added its colour to the BSS that received it. +The kernel repeats a collision event every 500 ms, with the colliding +colour alone (mac80211 ieee80211_rx_check_bss_color_collision() +compares the OBSS colour with the BSS's own), so each event erased the +colours stations had reported, and the next report brought them back. +A BSS Color In Use report names no OBSS colour either: it names a +colour the station uses with a peer (IEEE Std 802.11-2024 11.21.2.8), +and a report of colour 0 cancels it. + +Keep two sets per radio: +- the OBSS colours (struct hostapd_iface bss_colors_in_use), which the + kernel's collision events and the BSS Color Collision reports of + stations add to. A colour leaves the set 60 s after an event named + it (DOT11BSS_COLOR_COLLISION_AP_PERIOD + 10 s: the kernel repeats an + event every 500 ms while it hears the colliding OBSS, and hostapd + judges a collision persistent within that time), or 130 s after a + report did (the longest dot11BSSColorCollisionSTAPeriod, 120 s, with + which a station repeats its report, plus the 10 s margin hostapd + gives its own period, for a report that power save or retries + delay). Stations stop reporting while BSS Color is disabled + (26.17.3.5.2), and mac80211 compares no OBSS colour then, so the + ageing pauses while BSS Color is disabled; +- the colours that stations use with a peer, held per station + (struct sta_info bss_color_in_use) until a report of colour 0 or + until the station leaves. + +A colour change picks a colour outside both sets. +hostapd_switch_color() no longer changes either. + +Signed-off-by: Felix Fietkau +--- +--- a/src/ap/hostapd.c ++++ b/src/ap/hostapd.c +@@ -797,6 +797,9 @@ static void hostapd_cleanup_iface(struct + hostapd_afc_stop(iface); + eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface, + NULL); ++#ifdef CONFIG_IEEE80211AX ++ eloop_cancel_timeout(hostapd_bss_colors_in_use_timeout, iface, NULL); ++#endif /* CONFIG_IEEE80211AX */ + + hostapd_cleanup_iface_partial(iface); + hostapd_config_free(iface->conf); +@@ -5068,6 +5071,7 @@ void hostapd_switch_color_timeout_handle + struct hostapd_data *hapd = (struct hostapd_data *) eloop_data; + os_time_t delta_t; + unsigned int b; ++ u64 avoided; + int i, r; + + /* CCA can be triggered once the handler constantly receives +@@ -5085,10 +5089,12 @@ void hostapd_switch_color_timeout_handle + * during the CCA countdown carry the correct Disabled=1 state. + */ + hapd->iface->conf->he_op.he_bss_color_disabled = 1; ++ hostapd_bss_colors_in_use_update(hapd->iface); + ++ avoided = hostapd_bss_colors_avoided(hapd->iface); + r = os_random() % HE_OPERATION_BSS_COLOR_MAX; + for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) { +- if (r && !(hapd->color_collision_bitmap & (1ULL << r))) ++ if (r && !(avoided & (1ULL << r))) + break; + + r = (r + 1) % HE_OPERATION_BSS_COLOR_MAX; +@@ -5131,6 +5137,112 @@ void hostapd_switch_color_timeout_handle + } + + ++/* An OBSS colour expires BSS_COLOR_EVENT_AGE seconds after a collision ++ * event and BSS_COLOR_REPORT_AGE seconds after a station report names it ++ * (IEEE Std 802.11-2024 26.17.3.5.2). The ageing pauses while BSS Color ++ * is disabled. */ ++#define BSS_COLOR_EVENT_AGE (DOT11BSS_COLOR_COLLISION_AP_PERIOD + 10) ++#define BSS_COLOR_REPORT_AGE (120 + 10) ++ ++static void hostapd_bss_colors_in_use_age(struct hostapd_iface *iface, ++ u64 added, os_time_t age) ++{ ++ struct os_reltime now; ++ os_time_t next = 0; ++ u64 in_use = 0; ++ bool paused; ++ int i; ++ ++ if (os_get_reltime(&now)) ++ return; ++ ++ eloop_cancel_timeout(hostapd_bss_colors_in_use_timeout, iface, NULL); ++ ++ paused = iface->conf->he_op.he_bss_color_disabled; ++ if (paused && !iface->bss_color_aging_paused) { ++ iface->bss_color_aging_paused = true; ++ iface->bss_color_paused_at = now; ++ } else if (!paused && iface->bss_color_aging_paused) { ++ iface->bss_color_aging_paused = false; ++ for (i = 1; i < 64; i++) ++ iface->bss_color_expiry[i].sec += ++ now.sec - iface->bss_color_paused_at.sec; ++ } ++ ++ for (i = 1; i < 64; i++) { ++ os_time_t left; ++ ++ if (!((iface->bss_colors_in_use | added) & BIT_ULL(i))) ++ continue; ++ ++ if ((added & BIT_ULL(i)) && ++ (!(iface->bss_colors_in_use & BIT_ULL(i)) || ++ iface->bss_color_expiry[i].sec < now.sec + age)) ++ iface->bss_color_expiry[i].sec = now.sec + age; ++ ++ left = iface->bss_color_expiry[i].sec - now.sec; ++ if (!paused && left <= 0) ++ continue; ++ ++ in_use |= BIT_ULL(i); ++ if (!paused && (!next || left < next)) ++ next = left; ++ } ++ ++ if (next) ++ eloop_register_timeout(next, 0, ++ hostapd_bss_colors_in_use_timeout, ++ iface, NULL); ++ ++ iface->bss_colors_in_use = in_use; ++} ++ ++ ++void hostapd_bss_colors_in_use_timeout(void *eloop_data, void *user_ctx) ++{ ++ hostapd_bss_colors_in_use_age(eloop_data, 0, 0); ++} ++ ++ ++void hostapd_bss_colors_in_use_update(struct hostapd_iface *iface) ++{ ++ hostapd_bss_colors_in_use_age(iface, 0, 0); ++} ++ ++ ++void hostapd_bss_colors_collision_event(struct hostapd_iface *iface, ++ u64 bitmap) ++{ ++ hostapd_bss_colors_in_use_age(iface, bitmap & ~BIT_ULL(0), ++ BSS_COLOR_EVENT_AGE); ++} ++ ++ ++void hostapd_bss_colors_collision_report(struct hostapd_iface *iface, ++ u64 bitmap) ++{ ++ hostapd_bss_colors_in_use_age(iface, bitmap & ~BIT_ULL(0), ++ BSS_COLOR_REPORT_AGE); ++} ++ ++ ++/* The OBSS colours and the colours of BSS Color In Use reports (IEEE Std ++ * 802.11-2024 11.21.2.8) */ ++u64 hostapd_bss_colors_avoided(struct hostapd_iface *iface) ++{ ++ u64 avoided = iface->bss_colors_in_use; ++ struct sta_info *sta; ++ size_t j; ++ ++ for (j = 0; j < iface->num_bss; j++) ++ for (sta = iface->bss[j]->sta_list; sta; sta = sta->next) ++ if (sta->bss_color_in_use) ++ avoided |= BIT_ULL(sta->bss_color_in_use); ++ ++ return avoided; ++} ++ ++ + bool hostapd_is_cca_in_progress(struct hostapd_iface *iface) + { + size_t i; +@@ -5154,7 +5266,6 @@ void hostapd_switch_color(struct hostapd + if (os_get_reltime(&now)) + return; + +- hapd->color_collision_bitmap = bitmap; + hapd->last_color_collision = now; + + if (eloop_is_timeout_registered(hostapd_switch_color_timeout_handler, +--- a/src/ap/hostapd.h ++++ b/src/ap/hostapd.h +@@ -355,7 +355,6 @@ struct hostapd_data { + unsigned int cca_c_off_proberesp; + struct os_reltime first_color_collision; + struct os_reltime last_color_collision; +- u64 color_collision_bitmap; + #endif /* CONFIG_IEEE80211AX */ + + #ifdef CONFIG_P2P +@@ -790,6 +789,14 @@ struct hostapd_iface { + bool data_valid; + } afc; + #endif /* CONFIG_AFC */ ++ ++#ifdef CONFIG_IEEE80211AX ++ /* OBSS colours and their expiry (hostapd_bss_colors_in_use_age()) */ ++ u64 bss_colors_in_use; ++ struct os_reltime bss_color_expiry[64]; ++ struct os_reltime bss_color_paused_at; ++ bool bss_color_aging_paused; ++#endif /* CONFIG_IEEE80211AX */ + }; + + /* hostapd.c */ +@@ -845,6 +852,12 @@ int hostapd_owe_trans_get_info(struct ho + void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); + + void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap); ++void hostapd_bss_colors_collision_event(struct hostapd_iface *iface, ++ u64 bitmap); ++void hostapd_bss_colors_collision_report(struct hostapd_iface *iface, ++ u64 bitmap); ++void hostapd_bss_colors_in_use_update(struct hostapd_iface *iface); ++u64 hostapd_bss_colors_avoided(struct hostapd_iface *iface); + void hostapd_cleanup_cca_params(struct hostapd_data *hapd); + #ifdef CONFIG_AFC + int hostap_afc_get_chan_max_eirp_power(struct hostapd_iface *iface, bool psd, +@@ -952,6 +965,7 @@ void free_beacon_data(struct beacon_data + int hostapd_fill_cca_settings(struct hostapd_data *hapd, + struct cca_settings *settings); + void hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx); ++void hostapd_bss_colors_in_use_timeout(void *eloop_data, void *user_ctx); + bool hostapd_is_cca_in_progress(struct hostapd_iface *iface); + void hostapd_refresh_all_iface_beacons(struct hostapd_iface *hapd_iface); + +--- a/src/ap/wnm_ap.c ++++ b/src/ap/wnm_ap.c +@@ -753,6 +753,7 @@ static void ieee802_11_rx_wnm_event_repo + wpa_printf(MSG_DEBUG, + "WNM: BSS color collision bitmap 0x%llx reported by " + MACSTR, (unsigned long long) bitmap, MAC2STR(addr)); ++ hostapd_bss_colors_collision_report(hapd->iface, bitmap); + hostapd_switch_color(hapd->iface->bss[0], bitmap); + break; + case WNM_EVENT_TYPE_BSS_COLOR_IN_USE: +@@ -771,17 +772,15 @@ static void ieee802_11_rx_wnm_event_repo + MACSTR, color, MAC2STR(addr)); + return; + } ++ sta->bss_color_in_use = color; + if (color == 0) { + wpa_printf(MSG_DEBUG, + "WNM: BSS color use report canceled by " + MACSTR, MAC2STR(addr)); +- /* TODO: Clear stored color from the collision bitmap +- * if there are no other users for it. */ + return; + } + wpa_printf(MSG_DEBUG, "WNM: BSS color %u use report by " + MACSTR, color, MAC2STR(addr)); +- hapd->color_collision_bitmap |= 1ULL << color; + break; + #endif /* CONFIG_IEEE80211AX */ + default: +--- a/src/ap/drv_callbacks.c ++++ b/src/ap/drv_callbacks.c +@@ -2524,6 +2524,8 @@ static void hostapd_event_color_change(s + hostapd_cleanup_cca_params(bss); + } + } ++ ++ hostapd_bss_colors_in_use_update(hapd->iface); + } + #endif /* CONFIG_IEEE80211AX */ + +@@ -2944,6 +2946,8 @@ void wpa_supplicant_event(void *ctx, enu + data->bss_color_collision.link_id); + wpa_printf(MSG_DEBUG, "BSS color collision on %s", + hapd->conf->iface); ++ hostapd_bss_colors_collision_event(hapd->iface, ++ data->bss_color_collision.bitmap); + hostapd_switch_color(hapd->iface->bss[0], + data->bss_color_collision.bitmap); + break; +--- a/src/ap/sta_info.h ++++ b/src/ap/sta_info.h +@@ -359,6 +359,11 @@ struct sta_info { + #ifdef CONFIG_IEEE8021X_AUTH + struct eap_over_auth_data eap_auth_data; + #endif /* CONFIG_IEEE8021X_AUTH */ ++ ++#ifdef CONFIG_IEEE80211AX ++ /* last BSS Color In Use report, 0 for none */ ++ u8 bss_color_in_use; ++#endif /* CONFIG_IEEE80211AX */ + }; + + diff --git a/package/network/services/hostapd/patches/180-fix_owe_ssid_update.patch b/package/network/services/hostapd/patches/180-fix_owe_ssid_update.patch index e3178439fbc..74818856a96 100644 --- a/package/network/services/hostapd/patches/180-fix_owe_ssid_update.patch +++ b/package/network/services/hostapd/patches/180-fix_owe_ssid_update.patch @@ -1,6 +1,6 @@ --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -2521,7 +2521,11 @@ static int hostapd_owe_iface_iter(struct +@@ -2524,7 +2524,11 @@ static int hostapd_owe_iface_iter(struct if (!bss->conf->ssid.ssid_set || !bss->conf->ssid.ssid_len || is_zero_ether_addr(bss->own_addr)) continue; @@ -13,7 +13,7 @@ os_memcpy(hapd->conf->owe_transition_bssid, bss->own_addr, ETH_ALEN); os_memcpy(hapd->conf->owe_transition_ssid, -@@ -2538,10 +2542,6 @@ static int hostapd_owe_iface_iter(struct +@@ -2541,10 +2545,6 @@ static int hostapd_owe_iface_iter(struct int hostapd_owe_trans_get_info(struct hostapd_data *hapd) { diff --git a/package/network/services/hostapd/patches/181-ap-mld-re-add-station-after-sa-query-timeout.patch b/package/network/services/hostapd/patches/181-ap-mld-re-add-station-after-sa-query-timeout.patch index 434d5dc6f75..791154f16f5 100644 --- a/package/network/services/hostapd/patches/181-ap-mld-re-add-station-after-sa-query-timeout.patch +++ b/package/network/services/hostapd/patches/181-ap-mld-re-add-station-after-sa-query-timeout.patch @@ -107,7 +107,7 @@ Upstream hostap still refuses the links as of 2026-09-22 (24c033de8775). --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h -@@ -478,6 +478,7 @@ void clear_wpa_sm_for_each_partner_link( +@@ -483,6 +483,7 @@ void clear_wpa_sm_for_each_partner_link( struct sta_info *psta); void clear_wpa_sm_for_all_sta(struct hostapd_data *hapd, struct wpa_state_machine *wpa_sm); diff --git a/package/network/services/hostapd/patches/182-ap-mld-remove-a-link-only-when-it-is-on-the-list.patch b/package/network/services/hostapd/patches/182-ap-mld-remove-a-link-only-when-it-is-on-the-list.patch index 23ec7735f68..e2b2399d544 100644 --- a/package/network/services/hostapd/patches/182-ap-mld-remove-a-link-only-when-it-is-on-the-list.patch +++ b/package/network/services/hostapd/patches/182-ap-mld-remove-a-link-only-when-it-is-on-the-list.patch @@ -21,7 +21,7 @@ Signed-off-by: Felix Fietkau --- --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -5325,6 +5325,9 @@ int hostapd_mld_remove_link(struct hosta +@@ -5436,6 +5436,9 @@ int hostapd_mld_remove_link(struct hosta if (!mld) return -1; diff --git a/package/network/services/hostapd/patches/185-ap-mld-answer-a-frame-from-an-unknown-station-on-its-own-link.patch b/package/network/services/hostapd/patches/185-ap-mld-answer-a-frame-from-an-unknown-station-on-its-own-link.patch index ec0c808b884..d696265d32e 100644 --- a/package/network/services/hostapd/patches/185-ap-mld-answer-a-frame-from-an-unknown-station-on-its-own-link.patch +++ b/package/network/services/hostapd/patches/185-ap-mld-answer-a-frame-from-an-unknown-station-on-its-own-link.patch @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau if (hapd == NULL || hapd == HAPD_BROADCAST) return; -@@ -2702,7 +2702,8 @@ void wpa_supplicant_event(void *ctx, enu +@@ -2704,7 +2704,8 @@ void wpa_supplicant_event(void *ctx, enu hapd = switch_link_hapd(hapd, data->rx_from_unknown.link_id); hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid, data->rx_from_unknown.addr, diff --git a/package/network/services/hostapd/patches/186-ap-mld-announce-the-removal-of-an-affiliated-ap.patch b/package/network/services/hostapd/patches/186-ap-mld-announce-the-removal-of-an-affiliated-ap.patch index 6b02b10eabf..061e1fb5a4c 100644 --- a/package/network/services/hostapd/patches/186-ap-mld-announce-the-removal-of-an-affiliated-ap.patch +++ b/package/network/services/hostapd/patches/186-ap-mld-announce-the-removal-of-an-affiliated-ap.patch @@ -212,7 +212,7 @@ Signed-off-by: Felix Fietkau } --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h -@@ -517,9 +517,9 @@ struct hostapd_data { +@@ -516,9 +516,9 @@ struct hostapd_data { * total, additional 7 characters required. */ char ctrl_sock_iface[IFNAMSIZ + 7 + 1]; @@ -225,7 +225,7 @@ Signed-off-by: Felix Fietkau #endif /* CONFIG_IEEE80211BE */ #ifdef CONFIG_NAN_USD -@@ -938,6 +938,7 @@ int hostapd_mbssid_get_bss_index(struct +@@ -951,6 +951,7 @@ int hostapd_mbssid_get_bss_index(struct struct hostapd_data * hostapd_mld_get_link_bss(struct hostapd_data *hapd, u8 link_id); int hostapd_link_remove(struct hostapd_data *hapd, u32 count); diff --git a/package/network/services/hostapd/patches/189-ap-mld-free-the-partner-link-stations-of-a-torn-down-bss.patch b/package/network/services/hostapd/patches/189-ap-mld-free-the-partner-link-stations-of-a-torn-down-bss.patch index 9e6267c5036..4440891aace 100644 --- a/package/network/services/hostapd/patches/189-ap-mld-free-the-partner-link-stations-of-a-torn-down-bss.patch +++ b/package/network/services/hostapd/patches/189-ap-mld-free-the-partner-link-stations-of-a-torn-down-bss.patch @@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -940,6 +940,9 @@ static int hostapd_flush_old_stations(st +@@ -943,6 +943,9 @@ static int hostapd_flush_old_stations(st void hostapd_bss_deinit_no_free(struct hostapd_data *hapd) { @@ -60,7 +60,7 @@ Signed-off-by: Felix Fietkau --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h -@@ -472,6 +472,7 @@ static inline void ap_sta_set_mld(struct +@@ -477,6 +477,7 @@ static inline void ap_sta_set_mld(struct void ap_sta_free_sta_profile(struct mld_info *info); void hostapd_free_link_stas(struct hostapd_data *hapd); diff --git a/package/network/services/hostapd/patches/191-hostapd-add-support-for-specifying-the-link-id-in-th.patch b/package/network/services/hostapd/patches/191-hostapd-add-support-for-specifying-the-link-id-in-th.patch index f1fa62a3312..8835c6b67c2 100644 --- a/package/network/services/hostapd/patches/191-hostapd-add-support-for-specifying-the-link-id-in-th.patch +++ b/package/network/services/hostapd/patches/191-hostapd-add-support-for-specifying-the-link-id-in-th.patch @@ -43,7 +43,7 @@ Signed-off-by: Felix Fietkau * If set indicate the AP as disabled in the RNR element included in the --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -3230,7 +3230,10 @@ struct hostapd_iface * hostapd_alloc_ifa +@@ -3233,7 +3233,10 @@ struct hostapd_iface * hostapd_alloc_ifa #ifdef CONFIG_IEEE80211BE static void hostapd_bss_alloc_link_id(struct hostapd_data *hapd) { diff --git a/package/network/services/hostapd/patches/196-ap-mld-keep-the-configured-bssid-of-the-first-link.patch b/package/network/services/hostapd/patches/196-ap-mld-keep-the-configured-bssid-of-the-first-link.patch index b8a888b5282..741da390594 100644 --- a/package/network/services/hostapd/patches/196-ap-mld-keep-the-configured-bssid-of-the-first-link.patch +++ b/package/network/services/hostapd/patches/196-ap-mld-keep-the-configured-bssid-of-the-first-link.patch @@ -34,7 +34,7 @@ Signed-off-by: Felix Fietkau --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -1604,12 +1604,17 @@ static int hostapd_setup_bss(struct host +@@ -1607,12 +1607,17 @@ static int hostapd_setup_bss(struct host os_memcpy(hapd->own_addr, if_addr, ETH_ALEN); #ifdef CONFIG_IEEE80211BE diff --git a/package/network/services/hostapd/patches/197-ap-mld-drop-a-link-that-goes-from-the-station-links.patch b/package/network/services/hostapd/patches/197-ap-mld-drop-a-link-that-goes-from-the-station-links.patch index a6afa59dcc1..9c2e7576ec4 100644 --- a/package/network/services/hostapd/patches/197-ap-mld-drop-a-link-that-goes-from-the-station-links.patch +++ b/package/network/services/hostapd/patches/197-ap-mld-drop-a-link-that-goes-from-the-station-links.patch @@ -256,7 +256,7 @@ Signed-off-by: Felix Fietkau struct sta_info *sta, *prev; --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h -@@ -476,6 +476,7 @@ static inline void ap_sta_set_mld(struct +@@ -481,6 +481,7 @@ static inline void ap_sta_set_mld(struct void ap_sta_free_sta_profile(struct mld_info *info); diff --git a/package/network/services/hostapd/patches/200-multicall.patch b/package/network/services/hostapd/patches/200-multicall.patch index 9d71ccf3448..c25921c3f04 100644 --- a/package/network/services/hostapd/patches/200-multicall.patch +++ b/package/network/services/hostapd/patches/200-multicall.patch @@ -94,7 +94,7 @@ This allows building both hostapd and wpa_supplicant as a single binary if (c < 0) --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c -@@ -2611,8 +2611,8 @@ static void hostapd_mld_iface_disable(st +@@ -2613,8 +2613,8 @@ static void hostapd_mld_iface_disable(st #endif /* CONFIG_IEEE80211BE */ @@ -105,7 +105,7 @@ This allows building both hostapd and wpa_supplicant as a single binary { struct hostapd_data *hapd = ctx; struct sta_info *sta; -@@ -2983,7 +2983,7 @@ void wpa_supplicant_event(void *ctx, enu +@@ -2987,7 +2987,7 @@ void wpa_supplicant_event(void *ctx, enu } diff --git a/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch b/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch index 16079a4651c..6dc99e5c02c 100644 --- a/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch +++ b/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch @@ -63,7 +63,7 @@ method. wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to " MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u " "validity_interval=%u", -@@ -814,10 +815,12 @@ int ieee802_11_rx_wnm_action_ap(struct h +@@ -813,10 +814,12 @@ int ieee802_11_rx_wnm_action_ap(struct h plen); return 0; case WNM_BSS_TRANS_MGMT_QUERY: @@ -76,7 +76,7 @@ method. ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload, plen); return 0; -@@ -865,6 +868,7 @@ int wnm_send_disassoc_imminent(struct ho +@@ -864,6 +867,7 @@ int wnm_send_disassoc_imminent(struct ho pos = mgmt->u.action.u.bss_tm_req.variable; @@ -84,7 +84,7 @@ method. wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to " MACSTR, disassoc_timer, MAC2STR(sta->addr)); if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) { -@@ -947,6 +951,7 @@ int wnm_send_ess_disassoc_imminent(struc +@@ -946,6 +950,7 @@ int wnm_send_ess_disassoc_imminent(struc return -1; } @@ -92,7 +92,7 @@ method. if (disassoc_timer) { /* send disassociation frame after time-out */ set_disassoc_timer(hapd, sta, disassoc_timer); -@@ -1030,6 +1035,7 @@ int wnm_send_bss_tm_req(struct hostapd_d +@@ -1029,6 +1034,7 @@ int wnm_send_bss_tm_req(struct hostapd_d } os_free(buf); diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch index 29f9cc47e1b..c885441f1cf 100644 --- a/package/network/services/hostapd/patches/600-ubus_support.patch +++ b/package/network/services/hostapd/patches/600-ubus_support.patch @@ -134,7 +134,7 @@ probe/assoc/auth requests via object subscribe. accounting_deinit(hapd); hostapd_deinit_wpa(hapd); vlan_deinit(hapd); -@@ -1433,6 +1434,8 @@ static int hostapd_start_beacon(struct h +@@ -1436,6 +1437,8 @@ static int hostapd_start_beacon(struct h if (hapd->driver && hapd->driver->set_operstate) hapd->driver->set_operstate(hapd->drv_priv, 1); @@ -143,7 +143,7 @@ probe/assoc/auth requests via object subscribe. return 0; } -@@ -2681,6 +2684,7 @@ static int hostapd_setup_interface_compl +@@ -2684,6 +2687,7 @@ static int hostapd_setup_interface_compl if (err) goto fail; @@ -151,7 +151,7 @@ probe/assoc/auth requests via object subscribe. wpa_printf(MSG_DEBUG, "Completing interface initialization"); if (iface->freq) { #ifdef NEED_AP_MLME -@@ -2910,6 +2914,7 @@ dfs_offload: +@@ -2913,6 +2917,7 @@ dfs_offload: fail: wpa_printf(MSG_ERROR, "Interface initialization failed"); @@ -159,7 +159,7 @@ probe/assoc/auth requests via object subscribe. if (iface->is_no_ir) { hostapd_set_state(iface, HAPD_IFACE_NO_IR); -@@ -3660,6 +3665,7 @@ void hostapd_interface_deinit_free(struc +@@ -3663,6 +3668,7 @@ void hostapd_interface_deinit_free(struc (unsigned int) iface->conf->num_bss); driver = iface->bss[0]->driver; drv_priv = iface->bss[0]->drv_priv; @@ -185,7 +185,7 @@ probe/assoc/auth requests via object subscribe. int interface_added; /* virtual interface added for this BSS */ unsigned int started:1; unsigned int disabled:1; -@@ -822,6 +824,7 @@ hostapd_alloc_bss_data(struct hostapd_if +@@ -829,6 +831,7 @@ hostapd_alloc_bss_data(struct hostapd_if struct hostapd_bss_config *bss); int hostapd_setup_interface(struct hostapd_iface *iface); int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err); @@ -505,7 +505,7 @@ probe/assoc/auth requests via object subscribe. wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", pos, end - pos); } -@@ -816,6 +822,9 @@ int ieee802_11_rx_wnm_action_ap(struct h +@@ -815,6 +821,9 @@ int ieee802_11_rx_wnm_action_ap(struct h return 0; case WNM_BSS_TRANS_MGMT_QUERY: hapd->openwrt_stats.wnm.bss_transition_query_rx++; @@ -515,7 +515,7 @@ probe/assoc/auth requests via object subscribe. ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload, plen); return 0; -@@ -828,6 +837,8 @@ int ieee802_11_rx_wnm_action_ap(struct h +@@ -827,6 +836,8 @@ int ieee802_11_rx_wnm_action_ap(struct h ieee802_11_rx_wnmsleep_req(hapd, mgmt->sa, payload, plen); return 0; case WNM_NOTIFICATION_REQ: diff --git a/package/network/services/hostapd/patches/601-ucode_support.patch b/package/network/services/hostapd/patches/601-ucode_support.patch index cb1ee18ea4c..1577e254604 100644 --- a/package/network/services/hostapd/patches/601-ucode_support.patch +++ b/package/network/services/hostapd/patches/601-ucode_support.patch @@ -271,7 +271,7 @@ as adding/removing interfaces. hostapd_afc_stop(iface); eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface, NULL); -@@ -1435,6 +1439,7 @@ static int hostapd_start_beacon(struct h +@@ -1438,6 +1442,7 @@ static int hostapd_start_beacon(struct h hapd->driver->set_operstate(hapd->drv_priv, 1); hostapd_ubus_add_bss(hapd); @@ -279,7 +279,7 @@ as adding/removing interfaces. return 0; } -@@ -1510,7 +1515,7 @@ static int hostapd_bss_radius_init(struc +@@ -1513,7 +1518,7 @@ static int hostapd_bss_radius_init(struc * initialized. Most of the modules that are initialized here will be * deinitialized in hostapd_cleanup(). */ @@ -288,7 +288,7 @@ as adding/removing interfaces. bool start_beacon) { struct hostapd_bss_config *conf = hapd->conf; -@@ -1553,12 +1558,17 @@ static int hostapd_setup_bss(struct host +@@ -1556,12 +1561,17 @@ static int hostapd_setup_bss(struct host if (!first) { u8 *addr = hapd->own_addr; @@ -307,7 +307,7 @@ as adding/removing interfaces. hapd->iface->bss[0]->own_addr) == 0) { wpa_printf(MSG_ERROR, "BSS '%s' may not have " -@@ -1588,6 +1598,7 @@ static int hostapd_setup_bss(struct host +@@ -1591,6 +1601,7 @@ static int hostapd_setup_bss(struct host hapd->mld_link_id, hapd->conf->iface); goto setup_mld; } @@ -315,7 +315,7 @@ as adding/removing interfaces. } #endif /* CONFIG_IEEE80211BE */ -@@ -1596,7 +1607,7 @@ static int hostapd_setup_bss(struct host +@@ -1599,7 +1610,7 @@ static int hostapd_setup_bss(struct host conf->iface, addr, hapd, &hapd->drv_priv, force_ifname, if_addr, conf->bridge[0] ? conf->bridge : NULL, @@ -324,7 +324,7 @@ as adding/removing interfaces. wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" MACSTR ")", MAC2STR(hapd->own_addr)); hapd->interface_added = 0; -@@ -1642,6 +1653,8 @@ setup_mld: +@@ -1645,6 +1656,8 @@ setup_mld: } #endif /* CONFIG_IEEE80211BE */ @@ -333,7 +333,7 @@ as adding/removing interfaces. if (conf->wmm_enabled < 0) conf->wmm_enabled = hapd->iconf->ieee80211n | hapd->iconf->ieee80211ax; -@@ -1970,7 +1983,7 @@ int hostapd_set_acl(struct hostapd_data +@@ -1973,7 +1986,7 @@ int hostapd_set_acl(struct hostapd_data } @@ -342,7 +342,7 @@ as adding/removing interfaces. { #ifdef CONFIG_IEEE80211BE int ret; -@@ -2643,7 +2656,7 @@ static int hostapd_owe_iface_iter2(struc +@@ -2646,7 +2659,7 @@ static int hostapd_owe_iface_iter2(struc #endif /* CONFIG_OWE */ @@ -351,7 +351,7 @@ as adding/removing interfaces. { #ifdef CONFIG_OWE /* Check whether the enabled BSS can complete OWE transition mode -@@ -3115,7 +3128,7 @@ hostapd_alloc_bss_data(struct hostapd_if +@@ -3118,7 +3131,7 @@ hostapd_alloc_bss_data(struct hostapd_if } @@ -360,7 +360,7 @@ as adding/removing interfaces. { if (!hapd) return; -@@ -3324,7 +3337,7 @@ fail: +@@ -3327,7 +3340,7 @@ fail: } @@ -369,7 +369,7 @@ as adding/removing interfaces. { #ifdef CONFIG_IEEE80211BE struct hostapd_mld *mld, **all_mld; -@@ -4205,7 +4218,8 @@ int hostapd_remove_iface(struct hapd_int +@@ -4208,7 +4221,8 @@ int hostapd_remove_iface(struct hapd_int hapd_iface = interfaces->iface[i]; if (hapd_iface == NULL) return -1; @@ -409,7 +409,7 @@ as adding/removing interfaces. int interface_added; /* virtual interface added for this BSS */ unsigned int started:1; unsigned int disabled:1; -@@ -595,6 +602,7 @@ struct hostapd_mld { +@@ -594,6 +601,7 @@ struct hostapd_mld { */ struct hostapd_iface { struct hapd_interfaces *interfaces; @@ -417,7 +417,7 @@ as adding/removing interfaces. void *owner; char *config_fname; struct hostapd_config *conf; -@@ -833,11 +841,16 @@ struct hostapd_iface * hostapd_init(stru +@@ -840,11 +848,16 @@ struct hostapd_iface * hostapd_init(stru struct hostapd_iface * hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy, const char *config_fname, int debug); @@ -434,7 +434,7 @@ as adding/removing interfaces. int hostapd_enable_iface(struct hostapd_iface *hapd_iface); int hostapd_reload_iface(struct hostapd_iface *hapd_iface); int hostapd_reload_bss_only(struct hostapd_data *bss); -@@ -863,6 +876,7 @@ hostapd_switch_channel_fallback(struct h +@@ -870,6 +883,7 @@ hostapd_switch_channel_fallback(struct h void hostapd_cleanup_cs_params(struct hostapd_data *hapd); void hostapd_periodic_iface(struct hostapd_iface *iface); int hostapd_owe_trans_get_info(struct hostapd_data *hapd); diff --git a/package/network/services/hostapd/patches/603-ap-mld-remove-an-affiliated-ap-at-the-expiry.patch b/package/network/services/hostapd/patches/603-ap-mld-remove-an-affiliated-ap-at-the-expiry.patch index edce169b366..5759ef2890f 100644 --- a/package/network/services/hostapd/patches/603-ap-mld-remove-an-affiliated-ap-at-the-expiry.patch +++ b/package/network/services/hostapd/patches/603-ap-mld-remove-an-affiliated-ap-at-the-expiry.patch @@ -436,7 +436,7 @@ Signed-off-by: Felix Fietkau os_free(hapd->probereq_cb); --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h -@@ -547,6 +547,8 @@ struct hostapd_data { +@@ -546,6 +546,8 @@ struct hostapd_data { u16 eht_mld_link_removal_start; u16 eht_mld_link_removal_count; struct os_reltime eht_mld_link_removal_due; @@ -445,7 +445,7 @@ Signed-off-by: Felix Fietkau #endif /* CONFIG_IEEE80211BE */ #ifdef CONFIG_NAN_USD -@@ -974,6 +976,10 @@ struct hostapd_data * hostapd_mld_get_li +@@ -987,6 +989,10 @@ struct hostapd_data * hostapd_mld_get_li u8 link_id); int hostapd_link_remove(struct hostapd_data *hapd, u32 count); bool hostapd_link_remove_critical_update(struct hostapd_data *hapd); diff --git a/package/network/services/hostapd/patches/701-reload_config_inline.patch b/package/network/services/hostapd/patches/701-reload_config_inline.patch index 4f464993698..ca1c47e76bc 100644 --- a/package/network/services/hostapd/patches/701-reload_config_inline.patch +++ b/package/network/services/hostapd/patches/701-reload_config_inline.patch @@ -58,7 +58,7 @@ as adding/removing interfaces. return NULL; --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -3785,8 +3785,13 @@ hostapd_interface_init_bss(struct hapd_i +@@ -3788,8 +3788,13 @@ hostapd_interface_init_bss(struct hapd_i } } diff --git a/package/network/services/hostapd/patches/720-iface_max_num_sta.patch b/package/network/services/hostapd/patches/720-iface_max_num_sta.patch index 43d8ea9ad96..4ed5af6cb81 100644 --- a/package/network/services/hostapd/patches/720-iface_max_num_sta.patch +++ b/package/network/services/hostapd/patches/720-iface_max_num_sta.patch @@ -79,11 +79,11 @@ full device, e.g. in order to deal with hardware/driver limitations { --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h -@@ -880,6 +880,7 @@ void hostapd_periodic_iface(struct hosta +@@ -887,6 +887,7 @@ void hostapd_periodic_iface(struct hosta int hostapd_owe_trans_get_info(struct hostapd_data *hapd); void hostapd_owe_update_trans(struct hostapd_iface *iface);; void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); +int hostapd_check_max_sta(struct hostapd_data *hapd); void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap); - void hostapd_cleanup_cca_params(struct hostapd_data *hapd); + void hostapd_bss_colors_collision_event(struct hostapd_iface *iface, diff --git a/package/network/services/hostapd/patches/761-shared_das_port.patch b/package/network/services/hostapd/patches/761-shared_das_port.patch index ddd3be6d6ce..3adcbc5c160 100644 --- a/package/network/services/hostapd/patches/761-shared_das_port.patch +++ b/package/network/services/hostapd/patches/761-shared_das_port.patch @@ -7,7 +7,7 @@ Use the NAS identifier to find the right receiver context on incoming messages --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -1751,6 +1751,7 @@ static int hostapd_bss_radius_init(struc +@@ -1754,6 +1754,7 @@ static int hostapd_bss_radius_init(struc os_memset(&das_conf, 0, sizeof(das_conf)); das_conf.port = conf->radius_das_port; diff --git a/package/network/services/hostapd/patches/803-hostapd-fix-80211be-build.patch b/package/network/services/hostapd/patches/803-hostapd-fix-80211be-build.patch index 13a536e122e..0e016066b99 100644 --- a/package/network/services/hostapd/patches/803-hostapd-fix-80211be-build.patch +++ b/package/network/services/hostapd/patches/803-hostapd-fix-80211be-build.patch @@ -25,7 +25,7 @@ + --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h -@@ -459,23 +459,8 @@ int ap_sta_re_add(struct hostapd_data *h +@@ -464,23 +464,8 @@ int ap_sta_re_add(struct hostapd_data *h void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta); diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index f0df81a76b0..40aae1b2b29 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -490,12 +490,26 @@ hostapd_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj, return 0; } +/* bss_color is -1 while BSS Color is disabled; he_bss_color holds the + * colour in either case. */ static void hostapd_bss_color_add(struct hostapd_data *hapd) { #ifdef CONFIG_IEEE80211AX - blobmsg_add_u32(&b, "bss_color", hapd->iface->conf->he_op.he_bss_color_disabled ? -1 : - hapd->iface->conf->he_op.he_bss_color); + struct hostapd_iface *iface = hapd->iface; + void *colors; + int i; + + blobmsg_add_u32(&b, "bss_color", iface->conf->he_op.he_bss_color_disabled ? -1 : + iface->conf->he_op.he_bss_color); + blobmsg_add_u32(&b, "he_bss_color", iface->conf->he_op.he_bss_color); + blobmsg_add_u8(&b, "bss_color_partial", !!iface->conf->he_op.he_bss_color_partial); + + colors = blobmsg_open_array(&b, "bss_colors_in_use"); + for (i = 1; i < 64; i++) + if (iface->bss_colors_in_use & BIT_ULL(i)) + blobmsg_add_u32(&b, NULL, i); + blobmsg_close_array(&b, colors); #else blobmsg_add_u32(&b, "bss_color", -1); #endif