diff --git a/src/cntlr.c b/src/cntlr.c index 50b8a5058c723bdc81d88d68fcadc46e18b3d3ea..46fdd9afbf6d824b7b00012091b56aa114d454ce 100644 --- a/src/cntlr.c +++ b/src/cntlr.c @@ -706,8 +706,6 @@ struct netif_radio *cntlr_node_add_radio(struct controller *c, struct node *n, } memcpy(r->radio_el->macaddr, radio, 6); - /* TODO: schedule first channel scan once scan caps avail */ - return r; } @@ -1309,7 +1307,6 @@ static void cntlr_query_nodes(struct uloop_timeout *t) uloop_timeout_set(&c->query_nodes, 60 * 1000); } -#define RADIO_MAX 8 bool cntlr_check_config_diff(struct controller *c, uint8_t diff) { bool reloaded = false; @@ -1350,7 +1347,7 @@ bool cntlr_check_config_diff(struct controller *c, uint8_t diff) int num_bk = 1; uint8_t bk_id[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct radio_policy *rp = NULL; - uint8_t radio_id[RADIO_MAX * 6] = {0}; + uint8_t radio_id[MAX_NUM_RADIO * 6] = {0}; int num_radio = 0; if ((diff & CONFIG_DIFF_AGENT_POLICY) && !n->np->is_policy_diff) diff --git a/src/cntlr.h b/src/cntlr.h index 879e28786ec00d8bade033490e9adc5f295a1dee..48d79571bc23216ac22d0fdd8b9008068453b908 100644 --- a/src/cntlr.h +++ b/src/cntlr.h @@ -181,6 +181,7 @@ struct netif_link { struct list_head list; }; +#define MAX_NUM_RADIO 8 /* TODO - fill this structure */ struct netif_radio { char name[16]; diff --git a/src/cntlr_map.c b/src/cntlr_map.c index 27e4a7a72ab7aebf59a685a58f8c3caa429e10ee..d1e74e9fc8d4d4764eb1e6bef6d6b201e04a2593 100644 --- a/src/cntlr_map.c +++ b/src/cntlr_map.c @@ -896,6 +896,61 @@ static void cntlr_scan_caps_opclass_dump(struct wifi_radio_scan_capabilities *sc dbg("<<<\n"); } +/* Issue initial channel scan based upon received scan capabilities */ +static void cntlr_initial_channel_scan_from_caps(struct controller *c, struct node *n, + uint8_t (*macs)[6], int num_radio) +{ + trace("%s: --->\n", __func__); + + struct scan_req_data srd = {}; + struct netif_radio *r = NULL; + int i; + + for (i = 0; i < num_radio; i++) { + r = find_radio_by_node(c, n, macs[i]); + if (!r) + /* no such radio - try next */ + continue; + + /* TODO: improve by scanning when newest tsp gets old enough */ + + /* There're no scan results - mark for initial channel scan */ + if (list_empty(&r->radio_el->scanlist)) { + int j; + + if (r->radio_el->scan_caps.boot_only) + srd.is_fresh_scan = false; + else + srd.is_fresh_scan = true; + + /* TODO: utilize scan_caps's impact */ + + memcpy(&srd.radios[srd.num_radio].radio_mac, + r->radio_el->macaddr, + 6); + + /* limitation of bottom layers - only one opclass can be scanned */ + if (r->radio_el->scan_caps.opclass.entry_num > 1) + warn("%s: only first opclass from the caps will get scanned\n", __func__); + srd.radios[srd.num_radio].num_opclass = 1; + srd.radios[srd.num_radio].opclasses[0].classid = + r->radio_el->scan_caps.opclass.entry[0].id; + + srd.radios[srd.num_radio].opclasses[0].num_channel = + r->radio_el->scan_caps.opclass.entry[0].channel_num; + + for (j = 0; j < r->radio_el->scan_caps.opclass.entry[0].channel_num; j++) { + srd.radios[srd.num_radio].opclasses[0].channels[j] = + r->radio_el->scan_caps.opclass.entry[0].channel[j].channel; + } + + srd.num_radio++; + } + } + /* Issue channel scan for all radios at once */ + cntlr_send_channel_scan_request(c, n->alid, &srd); +} + /* Check Channel Scan Capabilities TLV */ static int cntlr_parse_radio_scan_caps(struct controller *c, struct node *n, struct tlv *t) @@ -903,6 +958,8 @@ static int cntlr_parse_radio_scan_caps(struct controller *c, struct node *n, struct tlv_channel_scan_capability *tlv; uint8_t *tv_data; int i, j, k, offset = 0; + uint8_t radio_id[MAX_NUM_RADIO][6] = {}; + int num_radio = 0; tlv = (struct tlv_channel_scan_capability *)t->data; tv_data = (uint8_t *)tlv; @@ -911,21 +968,15 @@ static int cntlr_parse_radio_scan_caps(struct controller *c, struct node *n, for (i = 0; i < tlv->num_radio; i++) { struct netif_radio *nr; - struct wifi_radio_scan_capabilities *caps; + struct wifi_radio_scan_capabilities caps; struct channel_scan_capability_radio *csr = (struct channel_scan_capability_radio *)&tv_data[offset]; - nr = find_radio_by_node(c, n, csr->radio); - if (!nr) - return -1; - - caps = &nr->radio_el->scan_caps; + caps.boot_only = !!(csr->cap & SCAN_CAP_ON_BOOT_ONLY); + caps.impact = !!(csr->cap & SCAN_CAP_IMPACT); + caps.interval = csr->min_scan_interval; - caps->boot_only = !!(csr->cap & SCAN_CAP_ON_BOOT_ONLY); - caps->impact = !!(csr->cap & SCAN_CAP_IMPACT); - caps->interval = csr->min_scan_interval; - - caps->opclass.entry_num = csr->num_opclass; + caps.opclass.entry_num = csr->num_opclass; offset += sizeof(*csr); /* radio, cap, min_scan_interval, num_opclass */ @@ -933,22 +984,39 @@ static int cntlr_parse_radio_scan_caps(struct controller *c, struct node *n, struct channel_scan_capability_opclass *opc = (struct channel_scan_capability_opclass *)&tv_data[offset]; - caps->opclass.entry[j].id = opc->classid; - caps->opclass.entry[j].channel_num = opc->num_channel; + caps.opclass.entry[j].id = opc->classid; + caps.opclass.entry[j].channel_num = opc->num_channel; offset += sizeof(*opc); /* classid & num_channel */ for (k = 0; k < opc->num_channel; k++) { - caps->opclass.entry[j].channel[k].channel = opc->channel[k]; + caps.opclass.entry[j].channel[k].channel = opc->channel[k]; } offset += opc->num_channel; } - cntlr_scan_caps_opclass_dump(caps); + /* scan capabilities debug dump */ + cntlr_scan_caps_opclass_dump(&caps); + + nr = find_radio_by_node(c, n, csr->radio); + if (!nr) + /* no such radio - try next */ + continue; + + /* updt caps: no pointers - let the compiler optimize */ + nr->radio_el->scan_caps = caps; + + + /* put addr into an array of radio MACs to be scanned */ + memcpy(&radio_id[num_radio], + nr->radio_el->macaddr, + 6); + num_radio++; } - /* TODO: check re scanlist timestamps & issue channel scan */ + /* issue a channel scan on reported radios */ + cntlr_initial_channel_scan_from_caps(c, n, radio_id, num_radio); return 0; }