mirror of
				https://github.com/berlin-open-wireless-lab/DAWN.git
				synced 2025-03-09 15:40:12 +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…
	
	Add table
		Add a link
		
	
		Reference in a new issue