From 185f31b46eaf2229fb0c414505ab9b7c3ffe8dae Mon Sep 17 00:00:00 2001 From: Ian Clowes Date: Sat, 2 Apr 2022 17:27:02 +0100 Subject: [PATCH] treewide: improve beacon request handling Updated approach to sending BEACON REQUEST. Each AP asks every 802.11k enabled client for the BEACON REPORT of a single other AP in the network at N second intervals, where N is the refresh period / num-APs. N seconds later the request is sent for the next AP. [cleanup commit message] Signed-off-by: Nick Hainke --- src/include/datastorage.h | 3 +- src/include/ubus.h | 2 +- src/storage/datastorage.c | 34 ++++++++------- src/test/test_storage.c | 4 +- src/utils/dawn_uci.c | 4 +- src/utils/ubus.c | 91 ++++++++++++++++++++++++++++----------- 6 files changed, 93 insertions(+), 45 deletions(-) diff --git a/src/include/datastorage.h b/src/include/datastorage.h index 77afbe1..34dd0dd 100644 --- a/src/include/datastorage.h +++ b/src/include/datastorage.h @@ -275,6 +275,7 @@ typedef struct ap_s { // ---------------- Global variables ---------------- extern struct ap_s* ap_set; +extern int ap_entry_last; extern pthread_mutex_t ap_array_mutex; extern struct client_s *client_set_bc; @@ -338,7 +339,7 @@ ap *ap_array_get_ap(struct dawn_mac bssid_mac); int probe_array_set_all_probe_count(struct dawn_mac client_addr, uint32_t probe_count); //int ap_get_collision_count(int col_domain); -void send_beacon_requests(ap *a, int id); +void send_beacon_requests(ap* h, ap* a, int id); /* Utils */ struct kicking_nr { diff --git a/src/include/ubus.h b/src/include/ubus.h index 17833b1..bd7d9f4 100644 --- a/src/include/ubus.h +++ b/src/include/ubus.h @@ -62,7 +62,7 @@ void update_hostapd_sockets(struct uloop_timeout *t); void ubus_set_nr_from_clients(struct kicking_nr* ap_list); -void ubus_send_beacon_request(client *c, ap *a, int id); +int ubus_send_beacon_request(client *c, ap *a, int d, int id); void uloop_add_data_cbs(); diff --git a/src/storage/datastorage.c b/src/storage/datastorage.c index b847d42..52d0381 100644 --- a/src/storage/datastorage.c +++ b/src/storage/datastorage.c @@ -42,7 +42,7 @@ struct probe_head_s probe_set = { 0, 0, 4, NULL, NULL }; pthread_mutex_t probe_array_mutex; struct ap_s *ap_set = NULL; -static int ap_entry_last = 0; +int ap_entry_last = 0; pthread_mutex_t ap_array_mutex; struct client_s* client_set_bc = NULL; // Ordered by BSSID + client MAC @@ -162,17 +162,15 @@ struct mac_entry_s* mac_find_entry(struct dawn_mac mac) return ret; } -void send_beacon_requests(ap *a, int id) { - dawn_mutex_require(&ap_array_mutex); - dawn_mutex_lock(&client_array_mutex); - +void send_beacon_requests(ap* target_ap, ap* host_ap, int sub_id) { dawnlog_debug_func("Entering..."); + dawn_mutex_require(&client_array_mutex); // Seach for BSSID - client* i = *client_find_first_bc_entry(a->bssid_addr, dawn_mac_null, false); + client* i = *client_find_first_bc_entry(host_ap->bssid_addr, dawn_mac_null, false); - // Go through clients - while (i != NULL && mac_is_equal_bb(i->bssid_addr, a->bssid_addr)) { + // Go through clients to request BEACON + while (i != NULL && mac_is_equal_bb(i->bssid_addr, host_ap->bssid_addr)) { if (dawnlog_showing(DAWNLOG_DEBUG)) dawnlog_debug("Client " MACSTR ": rrm_enabled_capa=%02x: PASSIVE=%d, ACTIVE=%d, TABLE=%d\n", MAC2STR(i->client_addr.u8), i->rrm_enabled_capa, @@ -180,13 +178,17 @@ void send_beacon_requests(ap *a, int id) { !!(i->rrm_enabled_capa & WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE), !!(i->rrm_enabled_capa & WLAN_RRM_CAPS_BEACON_REPORT_TABLE)); + // Bitwise AND to check for overlap in RRM capabilities if (i->rrm_enabled_capa & dawn_metric.rrm_mode_mask) - ubus_send_beacon_request(i, a, id); + { + int ubus_status = ubus_send_beacon_request(i, target_ap, dawn_metric.duration, sub_id); + if (ubus_status) + dawnlog_warning("Client / BSSID = " MACSTR " / " MACSTR ": BEACON REQUEST failed", + MAC2STR(i->client_addr.u8), MAC2STR(target_ap->bssid_addr.u8)); + } i = i->next_entry_bc; } - - dawn_mutex_unlock(&client_array_mutex); } int get_band(int freq) { @@ -1409,9 +1411,9 @@ void print_client_array() { static void print_ap_entry(int level, ap *entry) { dawn_mutex_require(&ap_array_mutex); - if (dawnlog_showing(DAWNLOG_INFO)) + if (dawnlog_showing(level)) { - dawnlog_info("ssid: %s, bssid_addr: " MACSTR ", freq: %d, ht: %d, vht: %d, chan_utilz: %d, neighbor_report: %s\n", + dawnlog(level,"ssid: %s, bssid_addr: " MACSTR ", freq: %d, ht: %d, vht: %d, chan_utilz: %d, neighbor_report: %s\n", entry->ssid, MAC2STR(entry->bssid_addr.u8), entry->freq, entry->ht_support, entry->vht_support, entry->channel_utilization, //entry->collision_domain, ap_get_collision_count(entry->collision_domain), // TODO: Fix format string if readding entry->neighbor_report @@ -1420,12 +1422,12 @@ static void print_ap_entry(int level, ap *entry) { } void print_ap_array() { - if (dawnlog_showing(DAWNLOG_DEBUG)) + if (dawnlog_showing(DAWNLOG_TRACE)) { - dawnlog_debug("--------APs------\n"); + dawnlog_trace("--------APs------\n"); dawn_mutex_require(&ap_array_mutex); for (ap* i = ap_set; i != NULL; i = i->next_ap) { - print_ap_entry(DAWNLOG_DEBUG, i); + print_ap_entry(DAWNLOG_TRACE, i); } dawnlog_debug("------------------\n"); } diff --git a/src/test/test_storage.c b/src/test/test_storage.c index 14e7fdf..20499f3 100644 --- a/src/test/test_storage.c +++ b/src/test/test_storage.c @@ -23,9 +23,11 @@ void ubus_set_nr_from_clients(struct kicking_nr* ap_list) { } -void ubus_send_beacon_request(client *c, ap *a, int id) +int ubus_send_beacon_request(client *c, ap *a, int d, int id) { printf("ubus_send_beacon_request() was called...\n"); + + return 0; } int send_set_probe(struct dawn_mac client_addr) diff --git a/src/utils/dawn_uci.c b/src/utils/dawn_uci.c index abb5330..ff776a2 100644 --- a/src/utils/dawn_uci.c +++ b/src/utils/dawn_uci.c @@ -269,7 +269,7 @@ struct probe_metric_s uci_get_dawn_metric() { // CONFIG-G: chan_util_avg_period|Number of sampling periods to average channel utilization values over|[3] .chan_util_avg_period = 3, // CONFIG-G: duration|802.11k BEACON request DURATION parameter|[0] - .duration = 600, + .duration = 150, // CONFIG-G: rrm_mode|Preferred order for using Passive, Active or Table 802.11k BEACON information|[PAT] String of 'P', 'A' and / or 'T' .rrm_mode_mask = WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE | WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE | @@ -551,7 +551,7 @@ int uci_set_network(char* uci_cmd) { ret = uci_lookup_ptr(ctx, &ptr, uci_cmd, 1); } - + if (ret == UCI_OK) { // Magic code to add unnamed section like 'config times' exactly once - no idea if this is quite right diff --git a/src/utils/ubus.c b/src/utils/ubus.c index ed4c992..836465e 100644 --- a/src/utils/ubus.c +++ b/src/utils/ubus.c @@ -1003,11 +1003,11 @@ static int get_mode_from_capability(int capability) { return -1; } -void ubus_send_beacon_request(client *c, ap *a, int id) +int ubus_send_beacon_request(client *c, ap *a, int d, int id) { + dawnlog_debug_func("Entering..."); dawn_mutex_require(&ap_array_mutex); struct blob_buf b = {0}; - dawnlog_debug_func("Entering..."); int timeout = 1; @@ -1016,40 +1016,83 @@ void ubus_send_beacon_request(client *c, ap *a, int id) blobmsg_add_macaddr(&b, "addr", c->client_addr); blobmsg_add_u32(&b, "op_class", a->op_class); blobmsg_add_u32(&b, "channel", a->channel); - blobmsg_add_u32(&b, "duration", dawn_metric.duration); + blobmsg_add_u32(&b, "duration", d); blobmsg_add_u32(&b, "mode", get_mode_from_capability(c->rrm_enabled_capa)); + blobmsg_add_macaddr(&b, "bssid", a->bssid_addr); blobmsg_add_string(&b, "ssid", (char*)a->ssid); - dawnlog_debug("Invoking beacon request!\n"); - ubus_invoke(ctx, id, "rrm_beacon_req", b.head, NULL, NULL, timeout * 1000); + if (dawnlog_showing(DAWNLOG_TRACE)) + { + char* str = blobmsg_format_json(b.head, true); + dawn_regmem(str); + dawnlog_debug("Invoking rrm_beacon_req: %s", str); + dawn_free(str); + str = NULL; + } + + int ret = ubus_invoke(ctx, id, "rrm_beacon_req", b.head, NULL, NULL, timeout * 1000); blob_buf_free(&b); dawn_unregmem(&b); + + return ret; } void update_beacon_reports(struct uloop_timeout *t) { - ap *a; +static int target_ap = 0; +dawnlog_debug_func("Entering (to target AP %d)...", target_ap); - dawnlog_debug_func("Entering..."); - - if(!timeout_config.update_beacon_reports) // if 0 just return - { - return; - } - dawnlog_debug("Sending beacon requests!\n"); - struct hostapd_sock_entry *sub; - dawn_mutex_lock(&ap_array_mutex); - - list_for_each_entry(sub, &hostapd_sock_list, list) + if (timeout_config.update_beacon_reports) // if 0 just return { + dawn_mutex_lock(&ap_array_mutex); dawn_mutex_require(&ap_array_mutex); - if (sub->subscribed && (a = ap_array_get_ap(sub->bssid_addr))) { - dawnlog_debug("Sending beacon request Sub!\n"); - send_beacon_requests(a, sub->id); - } - } - dawn_mutex_unlock(&ap_array_mutex); - uloop_timeout_set(&beacon_reports_timer, timeout_config.update_beacon_reports * 1000); + // FIXME: We should make this the set of AP in the NR of local AP. For now just use all AP... + ap* beacon_ap = ap_set; + int count_ap = target_ap; + while (count_ap-- > 0 && beacon_ap) + { + beacon_ap = beacon_ap->next_ap; + } + + if (!beacon_ap) + { + target_ap = 0; + beacon_ap = ap_set; + } + + if (beacon_ap) + { + target_ap++; + + dawn_mutex_lock(&client_array_mutex); + + // For each local AP providing same SSID, request BEACONS from each current client + struct hostapd_sock_entry* sub; + list_for_each_entry(sub, &hostapd_sock_list, list) + { + dawn_mutex_require(&ap_array_mutex); + + if (sub->subscribed) { + ap* host_ap = ap_array_get_ap(sub->bssid_addr); + if (host_ap && strcmp((char*)host_ap->ssid, (char*)beacon_ap->ssid) == 0) + { + send_beacon_requests(beacon_ap, host_ap, sub->id); + } + } + } + + dawn_mutex_unlock(&client_array_mutex); + } + + dawn_mutex_unlock(&ap_array_mutex); + int inter_ap_delay = timeout_config.update_beacon_reports; + inter_ap_delay *= 1000; + + if (ap_entry_last > 1) + inter_ap_delay /= ap_entry_last; + + uloop_timeout_set(&beacon_reports_timer, inter_ap_delay); + } } void update_tcp_connections(struct uloop_timeout *t) {