From 0c9457ee23a8051f5df5c07bad24cc3865a90a51 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 27 Jul 2021 16:42:22 -0700 Subject: [PATCH] RNR: Additions for a 6 GHz AP Include Reduced Neighbor Report element in Beacon and Probe Response frames by default if the reporting AP is 2.4/5 GHz and it is co-located with a 6 GHz AP. Similarly, include RNR by default in FILS Discovery frames if the AP is a standalone 6 GHz AP. Signed-off-by: John Crispin Co-developed-by: Aloka Dixit Signed-off-by: Aloka Dixit --- src/ap/ieee802_11.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 404f243af..db4104928 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -7150,9 +7150,75 @@ static size_t hostapd_eid_rnr_iface_len(struct hostapd_data *hapd, } +enum colocation_mode { + NO_COLOCATED_6GHZ, + STANDALONE_6GHZ, + COLOCATED_6GHZ, + COLOCATED_LOWER_BAND, +}; + +static enum colocation_mode get_colocation_mode(struct hostapd_data *hapd) +{ + u8 i; + bool is_6ghz = is_6ghz_op_class(hapd->iconf->op_class); + + if (!hapd->iface || !hapd->iface->interfaces) + return NO_COLOCATED_6GHZ; + + if (is_6ghz && hapd->iface->interfaces->count == 1) + return STANDALONE_6GHZ; + + for (i = 0; i < hapd->iface->interfaces->count; i++) { + struct hostapd_iface *iface; + bool is_colocated_6ghz; + + iface = hapd->iface->interfaces->iface[i]; + if (iface == hapd->iface || !iface || !iface->conf) + continue; + + is_colocated_6ghz = is_6ghz_op_class(iface->conf->op_class); + if (!is_6ghz && is_colocated_6ghz) + return COLOCATED_LOWER_BAND; + if (is_6ghz && !is_colocated_6ghz) + return COLOCATED_6GHZ; + } + + if (is_6ghz) + return STANDALONE_6GHZ; + + return NO_COLOCATED_6GHZ; +} + + +static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd, + size_t *current_len) +{ + struct hostapd_iface *iface; + size_t len = 0; + size_t i; + + if (!hapd->iface || !hapd->iface->interfaces) + return 0; + + for (i = 0; i < hapd->iface->interfaces->count; i++) { + iface = hapd->iface->interfaces->iface[i]; + + if (iface == hapd->iface || + !is_6ghz_op_class(iface->conf->op_class)) + continue; + + len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd, + current_len); + } + + return len; +} + + size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type) { size_t total_len = 0, current_len = 0; + enum colocation_mode mode = get_colocation_mode(hapd); switch (type) { case WLAN_FC_STYPE_BEACON: @@ -7161,11 +7227,21 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type) /* fallthrough */ case WLAN_FC_STYPE_PROBE_RESP: + if (mode == COLOCATED_LOWER_BAND) + total_len += hostapd_eid_rnr_colocation_len( + hapd, ¤t_len); + if (hapd->conf->rnr && hapd->iface->num_bss > 1) total_len += hostapd_eid_rnr_iface_len(hapd, hapd, ¤t_len); break; + case WLAN_FC_STYPE_ACTION: + if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ) + total_len += hostapd_eid_rnr_iface_len(hapd, hapd, + ¤t_len); + break; + default: break; } @@ -7315,10 +7391,35 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd, } +static u8 * hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid, + size_t *current_len) +{ + struct hostapd_iface *iface; + size_t i; + + if (!hapd->iface || !hapd->iface->interfaces) + return eid; + + for (i = 0; i < hapd->iface->interfaces->count; i++) { + iface = hapd->iface->interfaces->iface[i]; + + if (iface == hapd->iface || + !is_6ghz_op_class(iface->conf->op_class)) + continue; + + eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid, + current_len); + } + + return eid; +} + + u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type) { u8 *eid_start = eid; size_t current_len = 0; + enum colocation_mode mode = get_colocation_mode(hapd); switch (type) { case WLAN_FC_STYPE_BEACON: @@ -7327,11 +7428,21 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type) /* fallthrough */ case WLAN_FC_STYPE_PROBE_RESP: + if (mode == COLOCATED_LOWER_BAND) + eid = hostapd_eid_rnr_colocation(hapd, eid, + ¤t_len); + if (hapd->conf->rnr && hapd->iface->num_bss > 1) eid = hostapd_eid_rnr_iface(hapd, hapd, eid, ¤t_len); break; + case WLAN_FC_STYPE_ACTION: + if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ) + eid = hostapd_eid_rnr_iface(hapd, hapd, eid, + ¤t_len); + break; + default: return eid_start; }