mirror of
https://github.com/berlin-open-wireless-lab/DAWN.git
synced 2025-02-12 16:51:53 +00:00
kicking: improve kicking algorithm
- Tweak disassociate / kick NR code to reduce build overhead - Add set_hostapd_nrdynamic == 2 to build of AP local station NR from what current clients hear elsewhere - Tighten up hex string length usage for strncpy(), etc [cleanup commit message] Signed-off-by: Nick Hainke <vincent@systemli.org>
This commit is contained in:
parent
60ea5b4daf
commit
829fa0faed
7 changed files with 217 additions and 125 deletions
|
@ -74,6 +74,7 @@ struct probe_metric_s {
|
|||
int min_number_to_kick; // kick_clients()
|
||||
int chan_util_avg_period;
|
||||
int set_hostapd_nr;
|
||||
int disassoc_nr_length; // FIXME: Is there a standard for how many? Use 6 as default to suit iOS.
|
||||
int kicking;
|
||||
int kicking_threshold;
|
||||
int duration;
|
||||
|
@ -192,7 +193,7 @@ typedef struct hostapd_notify_entry_s {
|
|||
} hostapd_notify_entry;
|
||||
|
||||
// ---------------- Defines ----------------
|
||||
|
||||
// FIXME: Is this enough of the NR to allow 802.11 operations to work? Should we go for max possible length of 256 * 2 + 1
|
||||
#define NEIGHBOR_REPORT_LEN 200
|
||||
/* Neighbor report string elements
|
||||
* [Elemen ID|1][LENGTH|1][BSSID|6][BSSID INFORMATION|4][Operating Class|1][Channel Number|1][PHY Type|1][Operational Subelements]
|
||||
|
@ -259,7 +260,7 @@ typedef struct ap_s {
|
|||
time_t time; // remove_old...entries // (2)
|
||||
uint32_t station_count; // compare_station_count() <- better_ap_available() // (1)
|
||||
uint8_t ssid[SSID_MAX_LEN + 1]; // compare_sid() < -better_ap_available() // (1)
|
||||
char neighbor_report[NEIGHBOR_REPORT_LEN]; // (1) // TODO: Check whether we should store and AP one or generate on fly for client
|
||||
char neighbor_report[NEIGHBOR_REPORT_LEN + 1]; // (1) // This is the self-NR of the AP
|
||||
uint32_t op_class; // ubus_send_beacon_report() // (1)
|
||||
uint32_t channel; // ubus_send_beacon_report() // (1)
|
||||
//uint32_t collision_domain; // TODO: ap_get_collision_count() never evaluated?
|
||||
|
@ -345,7 +346,7 @@ void send_beacon_requests(ap *a, int id);
|
|||
|
||||
/* Utils */
|
||||
struct kicking_nr {
|
||||
char nr[NEIGHBOR_REPORT_LEN];
|
||||
ap *nr_ap;
|
||||
int score;
|
||||
struct kicking_nr *next;
|
||||
};
|
||||
|
|
|
@ -60,6 +60,8 @@ void del_client_all_interfaces(const struct dawn_mac client_addr, uint32_t reaso
|
|||
*/
|
||||
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);
|
||||
|
||||
void uloop_add_data_cbs();
|
||||
|
|
|
@ -277,68 +277,88 @@ static int compare_station_count(ap* ap_entry_own, ap* ap_entry_to_compare, stru
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct kicking_nr *find_position(struct kicking_nr *nrlist, int score) {
|
||||
struct kicking_nr *ret = NULL;
|
||||
|
||||
dawnlog_debug_func("Entering...");
|
||||
|
||||
while (nrlist && nrlist->score < score) {
|
||||
ret = nrlist;
|
||||
nrlist = nrlist->next;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void remove_kicking_nr_list(struct kicking_nr *nr_list) {
|
||||
struct kicking_nr *n;
|
||||
|
||||
dawnlog_debug_func("Entering...");
|
||||
|
||||
while(nr_list) {
|
||||
n = nr_list->next;
|
||||
dawn_free(nr_list);
|
||||
nr_list = n;
|
||||
}
|
||||
}
|
||||
|
||||
static struct kicking_nr *prune_kicking_nr_list(struct kicking_nr *nr_list, int min_score) {
|
||||
struct kicking_nr *next;
|
||||
|
||||
dawnlog_debug_func("Entering...");
|
||||
|
||||
while (nr_list && nr_list->score <= min_score) {
|
||||
next = nr_list->next;
|
||||
struct kicking_nr* next = nr_list->next;
|
||||
dawn_free(nr_list);
|
||||
nr_list = next;
|
||||
}
|
||||
return nr_list;
|
||||
}
|
||||
|
||||
static struct kicking_nr *insert_kicking_nr(struct kicking_nr *head, char *nr, int score, bool prune) {
|
||||
struct kicking_nr *new_entry, *pos;
|
||||
|
||||
#if 0
|
||||
static void prune_kicking_nr_list(struct kicking_nr **nr_list, int min_score) {
|
||||
dawnlog_debug_func("Entering...");
|
||||
|
||||
if (prune)
|
||||
head = prune_kicking_nr_list(head, score - dawn_metric.kicking_threshold);
|
||||
|
||||
// we are giving no error information here (not really critical)
|
||||
if (!(new_entry = dawn_malloc(sizeof (struct kicking_nr))))
|
||||
return head;
|
||||
|
||||
strncpy(new_entry->nr, nr, NEIGHBOR_REPORT_LEN);
|
||||
new_entry->score = score;
|
||||
pos = find_position(head, score);
|
||||
if (pos) {
|
||||
new_entry->next = pos->next;
|
||||
pos -> next = new_entry;
|
||||
} else {
|
||||
new_entry->next = head;
|
||||
head = new_entry;
|
||||
while (*nr_list) {
|
||||
if ((*nr_list)->score <= min_score)
|
||||
{
|
||||
struct kicking_nr* next = (*nr_list)->next;
|
||||
dawn_free(*nr_list);
|
||||
*nr_list = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
nr_list = &((*nr_list)->next);
|
||||
}
|
||||
}
|
||||
return head;
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void insert_kicking_nr_by_bssid(struct kicking_nr** nrlist, ap* nr_ap) {
|
||||
dawnlog_debug_func("Entering...");
|
||||
dawn_mutex_require(&ap_array_mutex);
|
||||
|
||||
// Look for the proposed BSSID in the current list
|
||||
while (*nrlist && mac_compare_bb((*nrlist)->nr_ap->bssid_addr, nr_ap->bssid_addr) < 0) {
|
||||
nrlist = &((*nrlist)->next);
|
||||
}
|
||||
|
||||
// If it isn't there then add it
|
||||
if (!*nrlist || mac_compare_bb((*nrlist)->nr_ap->bssid_addr, nr_ap->bssid_addr) != 0)
|
||||
{
|
||||
// we are giving no error information here (not really critical)
|
||||
struct kicking_nr* new_entry = dawn_malloc(sizeof(struct kicking_nr));
|
||||
|
||||
if (new_entry)
|
||||
{
|
||||
new_entry->nr_ap = nr_ap;
|
||||
new_entry->score = 0;
|
||||
|
||||
new_entry->next = *nrlist;
|
||||
*nrlist = new_entry;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void insert_kicking_nr_by_score(struct kicking_nr** nrlist, ap* nr_ap, int score) {
|
||||
dawnlog_debug_func("Entering...");
|
||||
dawn_mutex_require(&ap_array_mutex);
|
||||
|
||||
// we are giving no error information here (not really critical)
|
||||
struct kicking_nr* new_entry = dawn_malloc(sizeof(struct kicking_nr));
|
||||
|
||||
if (!new_entry)
|
||||
return;
|
||||
|
||||
new_entry->nr_ap = nr_ap;
|
||||
new_entry->score = score;
|
||||
|
||||
// Order entries high-low score so we can read first N highest values
|
||||
while (*nrlist && (*nrlist)->score > score) {
|
||||
nrlist = &((*nrlist)->next);
|
||||
}
|
||||
|
||||
new_entry->next = *nrlist;
|
||||
*nrlist = new_entry;
|
||||
|
||||
return;
|
||||
}
|
||||
int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, struct kicking_nr **neighbor_report) {
|
||||
|
||||
dawnlog_debug_func("Entering...");
|
||||
|
@ -430,12 +450,14 @@ int better_ap_available(ap *kicking_ap, struct dawn_mac client_mac, struct kicki
|
|||
else
|
||||
{
|
||||
dawnlog_trace("Better AP after full evaluation - add to NR (%s pruning)\n", ap_outcome == 2 ? "with" : "without");
|
||||
// Pointer is NULL if we're only finding a better AP without actually using it
|
||||
// NR is NULL if we're only testing for a better AP without actually using it
|
||||
if (neighbor_report != NULL)
|
||||
{
|
||||
// Test this_kick_outcome for pruning
|
||||
*neighbor_report = insert_kicking_nr(*neighbor_report, candidate_ap->neighbor_report,
|
||||
score_to_compare, ap_outcome == 2);
|
||||
// FIXME: Do we need to prune this list as we build it? trying new approach to send N best entries to hostapd
|
||||
// if (ap_outcome == 2)
|
||||
// prune_kicking_nr_list(neighbor_report, score_to_compare - dawn_metric.kicking_threshold);
|
||||
|
||||
insert_kicking_nr_by_score(neighbor_report, candidate_ap, score_to_compare);
|
||||
}
|
||||
|
||||
// If we find a single candidate then we will be kicking
|
||||
|
@ -471,6 +493,9 @@ int kick_clients(struct dawn_mac bssid_mac, uint32_t id) {
|
|||
|
||||
int kicked_clients = 0;
|
||||
|
||||
// Keep a list of nearby APs to update local AP Neighbor Report from
|
||||
struct kicking_nr* ap_nr_list = NULL;
|
||||
|
||||
dawnlog_info("AP BSSID " MACSTR ": Looking for candidates to kick\n", MAC2STR(kicking_ap->bssid_addr.u8));
|
||||
|
||||
// Seach for BSSID
|
||||
|
@ -478,7 +503,7 @@ int kick_clients(struct dawn_mac bssid_mac, uint32_t id) {
|
|||
|
||||
// Go through clients
|
||||
while (j != NULL && mac_is_equal_bb(j->bssid_addr, kicking_ap->bssid_addr)) {
|
||||
struct kicking_nr *neighbor_report = NULL;
|
||||
struct kicking_nr *kick_nr_list = NULL;
|
||||
|
||||
int do_kick = 0;
|
||||
|
||||
|
@ -486,7 +511,14 @@ int kick_clients(struct dawn_mac bssid_mac, uint32_t id) {
|
|||
dawnlog_info("Station " MACSTR ": Suppressing check due to MAC list entry\n", MAC2STR(j->client_addr.u8));
|
||||
}
|
||||
else {
|
||||
do_kick = better_ap_available(kicking_ap, j->client_addr, &neighbor_report);
|
||||
do_kick = better_ap_available(kicking_ap, j->client_addr, &kick_nr_list);
|
||||
}
|
||||
|
||||
// If we found any candidates (even if too low to kick to) add the highest scoring one to local AP NR set
|
||||
if (dawn_metric.set_hostapd_nr == 2 && kick_nr_list)
|
||||
{
|
||||
dawnlog_trace("Adding " MACSTR "as local NR entry candidate\n", MAC2STR(kick_nr_list->nr_ap->bssid_addr.u8));
|
||||
insert_kicking_nr_by_bssid(&ap_nr_list, kick_nr_list->nr_ap);
|
||||
}
|
||||
|
||||
// better ap available
|
||||
|
@ -527,8 +559,8 @@ int kick_clients(struct dawn_mac bssid_mac, uint32_t id) {
|
|||
|
||||
if (dawnlog_showing(DAWNLOG_INFO))
|
||||
{
|
||||
for (struct kicking_nr* n = neighbor_report; n; n = n->next)
|
||||
dawnlog_info("Kicking NR entry: " NR_MACSTR ", score=%d\n", NR_MAC2STR(n->nr), n->score);
|
||||
for (struct kicking_nr* n = kick_nr_list; n; n = n->next)
|
||||
dawnlog_info("Kicking NR entry: " NR_MACSTR ", score=%d\n", NR_MAC2STR(n->nr_ap->neighbor_report), n->score);
|
||||
}
|
||||
|
||||
// here we should send a messsage to set the probe.count for all aps to the min that there is no delay between switching
|
||||
|
@ -538,7 +570,7 @@ int kick_clients(struct dawn_mac bssid_mac, uint32_t id) {
|
|||
// don't deauth station? <- deauth is better!
|
||||
// maybe we can use handovers...
|
||||
//del_client_interface(id, client_array[j].client_addr, NO_MORE_STAS, 1, 1000);
|
||||
int sync_kick = wnm_disassoc_imminent(id, j->client_addr, neighbor_report, 12);
|
||||
int sync_kick = wnm_disassoc_imminent(id, j->client_addr, kick_nr_list, 12);
|
||||
|
||||
// Synchronous kick is a test harness feature to indicate arrays have been updated, so don't change further
|
||||
if (sync_kick)
|
||||
|
@ -572,12 +604,18 @@ int kick_clients(struct dawn_mac bssid_mac, uint32_t id) {
|
|||
j->kick_count = 0;
|
||||
}
|
||||
|
||||
remove_kicking_nr_list(neighbor_report);
|
||||
neighbor_report = NULL;
|
||||
remove_kicking_nr_list(kick_nr_list);
|
||||
kick_nr_list = NULL;
|
||||
|
||||
j = j->next_entry_bc;
|
||||
}
|
||||
|
||||
if (dawn_metric.set_hostapd_nr == 2)
|
||||
ubus_set_nr_from_clients(ap_nr_list);
|
||||
|
||||
remove_kicking_nr_list(ap_nr_list);
|
||||
ap_nr_list = NULL;
|
||||
|
||||
dawnlog_trace("KICKING: --------- AP Finished ---------\n");
|
||||
|
||||
dawn_mutex_unlock(&ap_array_mutex);
|
||||
|
@ -1318,9 +1356,9 @@ static void print_ap_entry(int level, ap *entry) {
|
|||
{
|
||||
dawnlog_info("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
|
||||
);
|
||||
//entry->collision_domain, ap_get_collision_count(entry->collision_domain), // TODO: Fix format string if readding
|
||||
entry->neighbor_report
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ int ret = 0;
|
|||
|
||||
if (neighbor_list != NULL)
|
||||
{
|
||||
// Fake a client being disassociated and then rejoining on the recommended neoghbor
|
||||
// Fake a client being disassociated and then rejoining on the recommended neighbor
|
||||
client *mc = client_array_get_client(client_addr);
|
||||
mc = client_array_delete(mc, true);
|
||||
// Originally, there was only one AP, not a list of them; that AP is at the tail of the list
|
||||
|
@ -50,9 +50,9 @@ int ret = 0;
|
|||
while (neighbor_list && neighbor_list->next)
|
||||
neighbor_list = neighbor_list->next;
|
||||
for (int n=0; n < ETH_ALEN; n++)
|
||||
sscanf(neighbor_list->nr + n*2, "%2hhx", mc->bssid_addr.u8 + n);
|
||||
sscanf(neighbor_list->nr_ap->neighbor_report + n*2, "%2hhx", mc->bssid_addr.u8 + n);
|
||||
insert_client_to_array(mc, 0);
|
||||
printf("BSS TRANSITION TO " NR_MACSTR "\n", NR_MAC2STR(neighbor_list->nr));
|
||||
printf("BSS TRANSITION TO " NR_MACSTR "\n", NR_MAC2STR(neighbor_list->nr_ap->neighbor_report));
|
||||
|
||||
// Tell caller not to change the arrays any further
|
||||
ret = 1;
|
||||
|
@ -588,6 +588,7 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity)
|
|||
dawn_metric.min_number_to_kick = 3;
|
||||
dawn_metric.chan_util_avg_period = 3;
|
||||
dawn_metric.set_hostapd_nr = 1;
|
||||
dawn_metric.disassoc_nr_length = 6;
|
||||
dawn_metric.kicking = 0;
|
||||
dawn_metric.duration = 0;
|
||||
dawn_metric.rrm_mode_mask = WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
|
||||
|
@ -624,6 +625,7 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity)
|
|||
else if (!strncmp(fn, "min_number_to_kick=", 19)) load_int(&dawn_metric.min_number_to_kick, fn + 19);
|
||||
else if (!strncmp(fn, "chan_util_avg_period=", 21)) load_int(&dawn_metric.chan_util_avg_period, fn + 21);
|
||||
else if (!strncmp(fn, "set_hostapd_nr=", 15)) load_int(&dawn_metric.set_hostapd_nr, fn + 15);
|
||||
else if (!strncmp(fn, "disassoc_nr_length=", 19)) load_int(&dawn_metric.disassoc_nr_length, fn + 19);
|
||||
else if (!strncmp(fn, "kicking=", 8)) load_int(&dawn_metric.kicking, fn + 8);
|
||||
else if (!strncmp(fn, "duration=", 9)) load_int(&dawn_metric.duration, fn + 9);
|
||||
else if (!strncmp(fn, "rrm_mode=", 9)) dawn_metric.rrm_mode_mask = parse_rrm_mode(dawn_metric.rrm_mode_order, fn + 9);
|
||||
|
@ -873,44 +875,26 @@ static int consume_actions(int argc, char* argv[], int harness_verbosity)
|
|||
}
|
||||
else if (strcmp(*argv, "better_ap_available") == 0)
|
||||
{
|
||||
args_required = 4;
|
||||
args_required = 5;
|
||||
if (curr_arg + args_required <= argc)
|
||||
{
|
||||
struct dawn_mac bssid_mac;
|
||||
struct dawn_mac client_mac;
|
||||
uint32_t autokick;
|
||||
uint32_t with_nr;
|
||||
|
||||
int tr = 9999; // Tamper evident value
|
||||
|
||||
hwaddr_aton(argv[1], bssid_mac.u8);
|
||||
hwaddr_aton(argv[2], client_mac.u8);
|
||||
load_u32(&autokick, argv[3]);
|
||||
load_u32(&with_nr, argv[4]);
|
||||
|
||||
char nb[NEIGHBOR_REPORT_LEN] = "TAMPER EVIDENT NEIGHBOR REPORT INITIALISATION STRING";
|
||||
struct kicking_nr neighbor = {0};
|
||||
struct kicking_nr *neighbor_list = &neighbor;
|
||||
struct kicking_nr *neighbor_list = NULL;
|
||||
|
||||
if (curr_arg + 5 <= argc)
|
||||
{
|
||||
args_required = 5;
|
||||
tr = better_ap_available(ap_array_get_ap(bssid_mac), client_mac, with_nr ? &neighbor_list : NULL);
|
||||
|
||||
if (strcmp(argv[4], "\0") == 0) // Provide a way to set an empty string
|
||||
{
|
||||
strcpy(nb, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(nb, argv[4]);
|
||||
}
|
||||
strncpy(neighbor.nr, nb, NEIGHBOR_REPORT_LEN);
|
||||
tr = better_ap_available(ap_array_get_ap(bssid_mac), client_mac, &neighbor_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr = better_ap_available(ap_array_get_ap(bssid_mac), client_mac, NULL);
|
||||
}
|
||||
|
||||
printf("better_ap_available returned %d (with neighbour report %s)\n", tr, nb);
|
||||
printf("better_ap_available returned %d (with neighbour report %s)\n", tr, neighbor_list ? neighbor_list->nr_ap->neighbor_report : "NONE");
|
||||
}
|
||||
}
|
||||
else if (strcmp(*argv, "eval_probe_metric") == 0)
|
||||
|
|
|
@ -241,6 +241,7 @@ struct probe_metric_s uci_get_dawn_metric() {
|
|||
.eval_probe_req = 0,
|
||||
.min_number_to_kick = 3,
|
||||
.set_hostapd_nr = 1,
|
||||
.disassoc_nr_length = 6,
|
||||
.max_station_diff = 1,
|
||||
.bandwidth_threshold = 6,
|
||||
.use_driver_recog = 1,
|
||||
|
@ -295,6 +296,7 @@ struct probe_metric_s uci_get_dawn_metric() {
|
|||
DAWN_SET_CONFIG_INT(ret, global_s, eval_probe_req);
|
||||
DAWN_SET_CONFIG_INT(ret, global_s, min_number_to_kick);
|
||||
DAWN_SET_CONFIG_INT(ret, global_s, set_hostapd_nr);
|
||||
DAWN_SET_CONFIG_INT(ret, global_s, disassoc_nr_length);
|
||||
DAWN_SET_CONFIG_INT(ret, global_s, max_station_diff);
|
||||
DAWN_SET_CONFIG_INT(ret, global_s, bandwidth_threshold);
|
||||
DAWN_SET_CONFIG_INT(ret, global_s, use_driver_recog);
|
||||
|
|
|
@ -566,8 +566,16 @@ int parse_to_clients(struct blob_attr* msg) {
|
|||
|
||||
ap_entry->op_class = ap_entry->channel = 0;
|
||||
if (tb[CLIENT_TABLE_NEIGHBOR]) {
|
||||
// Copy part of report that we have space for, and discard remainder
|
||||
strncpy(ap_entry->neighbor_report, blobmsg_get_string(tb[CLIENT_TABLE_NEIGHBOR]), NEIGHBOR_REPORT_LEN);
|
||||
ap_entry->neighbor_report[NEIGHBOR_REPORT_LEN] = '\0';
|
||||
sscanf(ap_entry->neighbor_report + NR_OP_CLASS, "%2x%2x", &ap_entry->op_class, &ap_entry->channel);
|
||||
|
||||
int nrl = strlen(ap_entry->neighbor_report);
|
||||
if (nrl == NEIGHBOR_REPORT_LEN)
|
||||
dawnlog_warning("Neighbor Report possibly truncated - hex length of %d\n", nrl);
|
||||
else
|
||||
dawnlog_debug("Neighbor Report - hex length of %d\n", nrl);
|
||||
}
|
||||
else {
|
||||
ap_entry->neighbor_report[0] = '\0';
|
||||
|
|
123
src/utils/ubus.c
123
src/utils/ubus.c
|
@ -94,7 +94,7 @@ struct hostapd_sock_entry {
|
|||
/*
|
||||
[Elemen ID|1][LENGTH|1][BSSID|6][BSSID INFORMATION|4][Operating Class|1][Channel Number|1][PHY Type|1][Operational Subelements]
|
||||
*/
|
||||
char neighbor_report[NEIGHBOR_REPORT_LEN];
|
||||
char neighbor_report[NEIGHBOR_REPORT_LEN + 1];
|
||||
|
||||
struct ubus_subscriber subscriber;
|
||||
struct ubus_event_handler wait_handler;
|
||||
|
@ -947,7 +947,7 @@ void update_clients(struct uloop_timeout *t) {
|
|||
dawnlog_debug_func("Entering...");
|
||||
|
||||
ubus_get_clients();
|
||||
if(dawn_metric.set_hostapd_nr)
|
||||
if(dawn_metric.set_hostapd_nr == 1)
|
||||
ubus_set_nr();
|
||||
// maybe to much?! don't set timer again...
|
||||
uloop_timeout_set(&client_timer, timeout_config.update_client * 1000);
|
||||
|
@ -1084,6 +1084,7 @@ void ubus_set_nr(){
|
|||
struct hostapd_sock_entry *sub;
|
||||
int timeout = 1;
|
||||
|
||||
// FIXME: Should we then call ubus_get_nr() to cache it locally?
|
||||
list_for_each_entry(sub, &hostapd_sock_list, list)
|
||||
{
|
||||
if (sub->subscribed) {
|
||||
|
@ -1160,10 +1161,14 @@ int wnm_disassoc_imminent(uint32_t id, const struct dawn_mac client_addr, struct
|
|||
blobmsg_add_u8(&b, "abridged", 1); // prefer aps in neighborlist
|
||||
|
||||
void* nbs = blobmsg_open_array(&b, "neighbors");
|
||||
while(neighbor_list != NULL) {
|
||||
dawnlog_info("BSS TRANSITION NEIGHBOR " NR_MACSTR ", Score=%d\n", NR_MAC2STR(neighbor_list->nr), neighbor_list->score);
|
||||
blobmsg_add_string(&b, NULL, neighbor_list->nr);
|
||||
|
||||
// Add the first N AP, where list order id high->low score
|
||||
int neighbors_added = 0;
|
||||
while(neighbors_added < dawn_metric.disassoc_nr_length && neighbor_list != NULL) {
|
||||
dawnlog_info("BSS TRANSITION NEIGHBOR " NR_MACSTR ", Score=%d\n", NR_MAC2STR(neighbor_list->nr_ap->neighbor_report), neighbor_list->score);
|
||||
blobmsg_add_string(&b, NULL, neighbor_list->nr_ap->neighbor_report);
|
||||
neighbor_list = neighbor_list->next;
|
||||
neighbors_added++;
|
||||
}
|
||||
|
||||
blobmsg_close_array(&b, nbs);
|
||||
|
@ -1708,6 +1713,7 @@ int uci_send_via_network()
|
|||
blobmsg_add_u32(&b, "min_number_to_kick", dawn_metric.min_number_to_kick);
|
||||
blobmsg_add_u32(&b, "chan_util_avg_period", dawn_metric.chan_util_avg_period);
|
||||
blobmsg_add_u32(&b, "set_hostapd_nr", dawn_metric.set_hostapd_nr);
|
||||
blobmsg_add_u32(&b, "disassoc_nr_length", dawn_metric.disassoc_nr_length);
|
||||
blobmsg_add_u32(&b, "duration", dawn_metric.duration);
|
||||
blobmsg_add_string(&b, "rrm_mode", get_rrm_mode_string(dawn_metric.rrm_mode_order));
|
||||
band_table = blobmsg_open_table(&b, "band_metrics");
|
||||
|
@ -1966,7 +1972,7 @@ int build_network_overview(struct blob_buf *b) {
|
|||
|
||||
char *nr;
|
||||
nr = blobmsg_alloc_string_buffer(b, "neighbor_report", NEIGHBOR_REPORT_LEN);
|
||||
sprintf(nr, "%s", m->neighbor_report); // TODO: Why not strcpy()
|
||||
strcpy(nr, m->neighbor_report);
|
||||
blobmsg_add_string_buffer(b);
|
||||
|
||||
char *iface;
|
||||
|
@ -2053,45 +2059,96 @@ static int mac_is_in_entry_list(const struct dawn_mac mac, const struct mac_entr
|
|||
return 0;
|
||||
}
|
||||
|
||||
// TODO: Does all APs constitute neighbor report? How about using list of AP connected
|
||||
// clients can also see (from probe_set) to give more (physically) local set?
|
||||
// Here, we let the user configure a list of preferred APs that clients can see, and then
|
||||
// add the rest of all APs. hostapd inserts this list backwards, so we must start with
|
||||
// the regular APs, then add the preferred ones, which are already ordered backwards.
|
||||
int ap_get_nr(struct blob_buf *b_local, struct dawn_mac own_bssid_addr, const char *ssid) {
|
||||
|
||||
ap *i, *own_ap;
|
||||
struct mac_entry_s *preferred_list, *n;
|
||||
|
||||
int ap_get_nr(struct blob_buf* b_local, struct dawn_mac own_bssid_addr, const char* ssid) {
|
||||
dawnlog_debug_func("Entering...");
|
||||
|
||||
void* nbs = blobmsg_open_array(b_local, "list");
|
||||
int ret = 0;
|
||||
|
||||
dawn_mutex_lock(&ap_array_mutex);
|
||||
|
||||
dawn_mutex_require(&ap_array_mutex);
|
||||
own_ap = ap_array_get_ap(own_bssid_addr);
|
||||
ap* own_ap = ap_array_get_ap(own_bssid_addr);
|
||||
|
||||
if (!own_ap)
|
||||
return -1;
|
||||
for (int band = 0; band < __DAWN_BAND_MAX; band++) {
|
||||
preferred_list = dawn_metric.neighbors[band];
|
||||
if (own_ap->freq <= max_band_freq[band])
|
||||
break;
|
||||
ret = -1;
|
||||
else
|
||||
{
|
||||
void* nbs = blobmsg_open_array(b_local, "list");
|
||||
|
||||
struct mac_entry_s* preferred_list = NULL;
|
||||
for (int band = 0; band < __DAWN_BAND_MAX; band++) {
|
||||
preferred_list = dawn_metric.neighbors[band];
|
||||
if (own_ap->freq <= max_band_freq[band])
|
||||
break;
|
||||
}
|
||||
|
||||
for (ap* i = ap_set; i != NULL; i = i->next_ap) {
|
||||
if (i != own_ap && !strncmp((char*)i->ssid, ssid, SSID_MAX_LEN) &&
|
||||
!mac_is_in_entry_list(i->bssid_addr, preferred_list))
|
||||
{
|
||||
blobmsg_add_nr(b_local, i);
|
||||
}
|
||||
}
|
||||
|
||||
for (struct mac_entry_s* n = preferred_list; n; n = n->next_mac) {
|
||||
dawn_mutex_require(&ap_array_mutex);
|
||||
ap* j = ap_array_get_ap(n->mac);
|
||||
if (j)
|
||||
blobmsg_add_nr(b_local, j);
|
||||
}
|
||||
|
||||
blobmsg_close_array(b_local, nbs);
|
||||
}
|
||||
|
||||
for (i = ap_set; i != NULL; i = i->next_ap) {
|
||||
if (i != own_ap && !strncmp((char *)i->ssid, ssid, SSID_MAX_LEN) &&
|
||||
!mac_is_in_entry_list(i->bssid_addr, preferred_list))
|
||||
{
|
||||
blobmsg_add_nr(b_local, i);
|
||||
dawn_mutex_unlock(&ap_array_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Use list of specifc AP to create local NR
|
||||
// TODO: Do we need to do the reverse insert thing mentioned above?
|
||||
void ubus_set_nr_from_clients(struct kicking_nr *ap_list) {
|
||||
dawnlog_debug_func("Entering...");
|
||||
|
||||
struct hostapd_sock_entry* sub;
|
||||
int timeout = 1;
|
||||
|
||||
int has_content = 0;
|
||||
|
||||
list_for_each_entry(sub, &hostapd_sock_list, list)
|
||||
{
|
||||
if (sub->subscribed) {
|
||||
struct blob_buf b = { 0 };
|
||||
blob_buf_init(&b, 0);
|
||||
dawn_regmem(&b);
|
||||
|
||||
void* nbs = blobmsg_open_array(&b, "list");
|
||||
|
||||
struct kicking_nr* this_ap = ap_list;
|
||||
while (this_ap)
|
||||
{
|
||||
// Candidates in this list will be for one SSID - so match that to the hostapd socket
|
||||
if (strncmp((char*)this_ap->nr_ap->ssid, sub->ssid, SSID_MAX_LEN) == 0)
|
||||
{
|
||||
blobmsg_add_nr(&b, this_ap->nr_ap);
|
||||
has_content = 1;
|
||||
}
|
||||
|
||||
this_ap = this_ap->next;
|
||||
}
|
||||
|
||||
blobmsg_close_array(&b, nbs);
|
||||
|
||||
if (has_content)
|
||||
ubus_invoke(ctx, sub->id, "rrm_nr_set", b.head, NULL, NULL, timeout * 1000);
|
||||
|
||||
blob_buf_free(&b);
|
||||
dawn_unregmem(&b);
|
||||
}
|
||||
}
|
||||
|
||||
for (n = preferred_list; n; n = n->next_mac) {
|
||||
if ((i = ap_array_get_ap(n->mac)))
|
||||
blobmsg_add_nr(b_local, i);
|
||||
}
|
||||
blobmsg_close_array(b_local, nbs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uloop_add_data_cbs() {
|
||||
|
|
Loading…
Reference in a new issue