From 5fe8fade02b39909110e2ea260f60f55e97044e4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 3 Oct 2026 21:34:29 +0200 Subject: [PATCH] hostapd: ubus get_status adds partial and in-use BSS colours A subscriber that reports the BSS colours of a radio needs three fields: the BSS Color subfield and the Partial BSS Color subfield that the radio transmits, and the colours of the OBSSs that the AP identified itself or learnt from the BSS Color Collision reports of its stations. get_status named the colour, as -1 while BSS Color is disabled, and neither of the others. hostapd kept its colours in use per BSS, and each collision event replaced them. It also added the colour of a BSS Color In Use report, which names a colour a station uses with a peer (IEEE Std 802.11-2024 11.21.2.8), not an OBSS colour. 174-ap-keep-the-obss-colors-of-a-radio keeps two sets per radio: - the OBSS colours, 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, or 130 s after a report did (the longest dot11BSSColorCollisionSTAPeriod, 120 s, plus a 10 s margin), and the ageing pauses while BSS Color is disabled; - the colours of BSS Color In Use reports, held per station until a report of colour 0 or until the station leaves. A colour change picks a colour outside both sets. get_status now adds, beside bss_color, at the top level and in each entry of the links of an AP MLD: - he_bss_color: the BSS Color subfield of the HE Operation element. It keeps the colour while BSS Color is disabled (IEEE Std 802.11-2024 26.11.4); bss_color keeps -1 then; - bss_color_partial: he_bss_color_partial of the radio; - bss_colors_in_use: the OBSS colours of the radio, 1 to 63. The colours of BSS Color In Use reports are not among them. On mt76 the kernel's collision events name the colliding colour only: mt7996 does not detect collisions itself, and mac80211 (ieee80211_rx_check_bss_color_collision()) reports an OBSS whose colour equals the BSS's own. Other OBSS colours reach the set only through the BSS Color Collision reports of stations. The colours are a list rather than the 64-bit bitmap, because a blobmsg int64 with bit 63 set reads as a negative number in ucode and JSON. Signed-off-by: Felix Fietkau --- ...4-ap-keep-the-obss-colors-of-a-radio.patch | 302 ++++++++++++++++++ .../patches/180-fix_owe_ssid_update.patch | 4 +- ...e-add-station-after-sa-query-timeout.patch | 2 +- ...e-a-link-only-when-it-is-on-the-list.patch | 2 +- ...m-an-unknown-station-on-its-own-link.patch | 2 +- ...unce-the-removal-of-an-affiliated-ap.patch | 4 +- ...ner-link-stations-of-a-torn-down-bss.patch | 4 +- ...ort-for-specifying-the-link-id-in-th.patch | 2 +- ...e-configured-bssid-of-the-first-link.patch | 2 +- ...ink-that-goes-from-the-station-links.patch | 2 +- .../hostapd/patches/200-multicall.patch | 4 +- .../patches/590-rrm-wnm-statistics.patch | 8 +- .../hostapd/patches/600-ubus_support.patch | 14 +- .../hostapd/patches/601-ucode_support.patch | 28 +- ...emove-an-affiliated-ap-at-the-expiry.patch | 4 +- .../patches/701-reload_config_inline.patch | 2 +- .../patches/720-iface_max_num_sta.patch | 4 +- .../hostapd/patches/761-shared_das_port.patch | 2 +- .../803-hostapd-fix-80211be-build.patch | 2 +- .../services/hostapd/src/src/ap/ubus.c | 18 +- 20 files changed, 364 insertions(+), 48 deletions(-) create mode 100644 package/network/services/hostapd/patches/174-ap-keep-the-obss-colors-of-a-radio.patch 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