Newer
Older
* Copyright (C) 2020 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <json-c/json.h>
#include <libubox/blobmsg.h>
#include <libubox/blobmsg_json.h>
#include <libubox/uloop.h>
#include <libubox/ustream.h>
#include <libubox/utils.h>
#include <libubus.h>
#include <easy/easy.h>
#include <wifi.h> // FIXME: should not be included
#include <timer_impl.h>
#include <cmdu.h>
#include <1905_tlvs.h>
#include <map2.h>
#include <map_module.h>
#include "config.h"
#include "cntlr.h"
#include "comm.h"
#include "allsta.h"
#include "cntlr_ubus.h"
#include "cntlr_cmdu_generator.h"
extern bool waitext;
static int update_fronthaul_bsslist(struct node *n, struct netif_iface *fh);
static void node_getbssinfo(void *cntlr, void *resp, int len, void *cookie);
static int enumerate_topology_indirect(struct controller *c);
static void mapclient_subscribe_for_cmdus(struct controller *c);
void stop_cntlr(struct controller *c)
{
if (!c) {
warn("%s: (cntlr = NULL)\n", __func__);
exit(0);
}
stop_test_logging();
ubus_unregister_event_handler(c->ubus_ctx, &c->ieee1905_evh);
cntlr_remove_object(c);
uloop_done();
cntlr_config_clean(&c->cfg);
comm_destroy(c->comm);
ubus_free(c->ubus_ctx);
free(c);
}
static void cntlr_terminate(struct controller *c)
{
dbg("%s: called.\n", __func__);
stop_cntlr(c);
stop_logging();
//unlink(pidfile);
exit(0);
}
/* find node by macaddress */
struct netif_iface *find_interface_by_mac(struct controller *c,
struct netif_radio *r, uint8_t *hwaddr)
{
struct netif_iface *p;
list_for_each_entry(p, &r->iflist, list) {
if (!memcmp(p->bssid, hwaddr, 6))
return p;
}
return NULL;
}
struct netif_radio *find_radio_by_node(struct controller *c, struct node *n,
uint8_t *radio)
{
struct netif_radio *p;
list_for_each_entry(p, &n->radiolist, list) {
if (!memcmp(p->macaddr, radio, 6))
return p;
}
return NULL;
}
/* find node by macaddress */
struct node *find_node_by_mac(struct controller *c, uint8_t *mac)
{
struct node *p;
list_for_each_entry(p, &c->nodelist, list) {
if (!memcmp(p->alid, mac, 6))
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/* find node by macaddress */
struct sta *cntlr_find_sta(struct controller *c, uint8_t *mac)
{
struct sta *s;
list_for_each_entry(s, &c->stalist, list) {
if (!memcmp(s->macaddr, mac, 6))
return s;
}
return NULL;
}
#if 0
/* find node by macaddress */
struct netif_iface *cntlr_get_fbss_by_mac(struct controller *c, struct node *n,
uint8_t *mac)
{
struct netif_iface *p;
list_for_each_entry(p, &n->iflist, list) {
if (!memcmp(p->bssid, mac, 6))
return p;
}
return NULL;
}
#endif
/* find fbss based on macaddr */
struct netif_iface *cntlr_iterate_fbss(struct controller *c, uint8_t *mac)
{
struct node *n;
list_for_each_entry(n, &c->nodelist, list) {
struct netif_radio *r;
list_for_each_entry(r, &n->radiolist, list) {
struct netif_iface *p;
list_for_each_entry(p, &r->iflist, list) {
if (!memcmp(p->bssid, mac, 6))
return p;
}
}
}
return NULL;
}
/* find node by ip address */
static struct node *find_node_by_ip(struct controller *c, const char *ip)
{
struct node *p;
struct in_addr ipn;
if (ip && strlen(ip) && !inet_aton(ip, &ipn)) {
warn("Invalid ipaddr: %s\n", ip);
return NULL;
}
list_for_each_entry(p, &c->nodelist, list) {
if (!memcmp(&p->ipaddr, &ipn, sizeof(struct in_addr)))
return p;
}
return NULL;
}
/* find node by any of its fh-bssid */
struct node *get_node_by_bssid(struct controller *c, unsigned char *bssid)
{
struct node *n;
list_for_each_entry(p, &n->iflist, list) {
if (memcmp(bssid, p->bssid, 6))
continue;
return n;
}
}
return NULL;
}
static void cntlr_log_nodes(struct controller *c)
{
struct node *n;
int i = 0;
list_for_each_entry(n, &c->nodelist, list) {
cntlr_dbg(" %d | agent = %p, hwaddr = '"MACFMT"')\n",
i++, n, MAC2STR(n->alid));
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
static int forall_node_update_neighbors(struct controller *c)
{
struct node *n, *p;
if (c->num_nodes == 0)
return 0;
cntlr_dbg("num nodes = %d\n", c->num_nodes);
/* For single node, there will be no neighbors. So, delete
* neighbors from it, if any.
* A broadcast neighbor address passed to CMD_DEL_NEIGHBOR
* command will delete all neighbors from a node.
*/
if (c->num_nodes == 1) {
char nbrstr[12 + 1] = {0};
unsigned char nbrmac[6] = "\xff\xff\xff\xff\xff\xff";
n = list_first_entry(&c->nodelist, struct node, list);
if (!n)
return -1;
btostr((unsigned char *)nbrmac, sizeof(nbrmac), nbrstr);
return 0;
}
list_for_each_entry(n, &c->nodelist, list) {
list_for_each_entry(p, &c->nodelist, list) {
list_for_each_entry(fh, &p->iflist, list) {
struct nbr nbr;
char nbrstr[2*sizeof(struct nbr) + 1] = {0};
memset(&nbr, 0, sizeof(nbr));
memcpy(nbr.bssid, fh->bssid, 6);
nbr.bssid_info = htonl(fh->bssid_info);
nbr.channel = fh->channel;
nbr.reg = fh->reg;
nbr.phy = fh->phy;
btostr((unsigned char *)&nbr, sizeof(nbr), nbrstr);
}
}
}
return 0;
}
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
#endif
static void cntlr_bcn_metrics_parse(struct uloop_timeout *t)
{
trace("%s %d\n", __func__, __LINE__);
struct sta *s = container_of(t, struct sta, bcn_metrics_timer);
struct bcn_metrics *best = NULL, *b;
struct node *n = s->fh->agent;
struct controller *c = n->cntlr;
int i;
dbg("%s %d for "MACFMT" attached to bssid " MACFMT "\n", __func__, __LINE__, MAC2STR(s->macaddr), MAC2STR(s->bssid));
dbg("%s %d node = "MACFMT"\n", __func__, __LINE__, MAC2STR(n->alid));
//for (i = 0; i < s->num_bcn_metrics; i++) {
list_for_each_entry(b, &s->bcnlist, list) {
dbg("%s %d bcn "MACFMT" \n", __func__, __LINE__,
MAC2STR(b->bssid));
if (!best) {
best = b;
continue;
}
dbg("%s %d best rcpi %u this rcpi %u\n", __func__, __LINE__,
best->rcpi, b->rcpi);
if ((best->rcpi - b->rcpi) > 10) {
dbg("%s %d new best bcn "MACFMT" with rcpi %d\n",
__func__, __LINE__,
MAC2STR(b->bssid),
b->rcpi);
best = b;
}
}
if (!best) {
dbg("%s %d\n", __func__, __LINE__);
return;
}
if (!hwaddr_is_zero(best->bssid) && memcmp(best->bssid, s->bssid, 6)) {
struct cmdu_buff *cmdu;
uint8_t stas[1][6];
if (!c->cfg.enable_sta_steer) {
trace("|%s:%d| better bssid found, but will not steer "MACFMT",\
because the 'enable_sta_steer' is not set!\n",
__func__, __LINE__, MAC2STR(s->macaddr));
return;
}
dbg("%s %d new bssid, wow! try to steer "MACFMT " " MACFMT " " MACFMT "\n", __func__,
__LINE__, MAC2STR(s->macaddr), MAC2STR(best->bssid), MAC2STR(s->bssid));
memcpy(stas[0], s->macaddr, 6);
cmdu = cntlr_gen_client_steer_request(c, s->fh->agent->alid,
s->bssid, 0, 1, s->macaddr, 1, best->bssid, 1);
if (cmdu) {
send_cmdu(c, cmdu);
cmdu_free(cmdu);
}
}
dbg("%s %d\n", __func__, __LINE__);
}
struct sta *cntlr_add_sta(struct controller *c, uint8_t *macaddr)
{
struct sta *s;
s = cntlr_find_sta(c, macaddr);
if (s)
return s;
s = calloc(1, sizeof(struct sta));
if (!s)
return NULL;
INIT_LIST_HEAD(&s->bcnlist);
memcpy(s->macaddr, macaddr, 6);
list_add(&s->list, &c->stalist);
s->bcn_metrics_timer.cb = cntlr_bcn_metrics_parse;
return s;
}
static void forall_but_node_restrict_sta(struct controller *c, struct node *ex,
uint8_t *sta)
{
#define sc_sz (sizeof(struct cmd_assoc_control))
unsigned char sccmd[sc_sz] = {0};
struct cmd_assoc_control *asc = (struct cmd_assoc_control *)sccmd;
char sccmd_str[2 * sc_sz + 1] = {0};
struct node *n;
asc->len = htonl(sizeof(asc));
asc->enable = htonl(1);
asc->duration = htonl(0); /* use fh-iface's assoc_ctrl_time */
asc->num = htonl(1);
memcpy(asc->stas, sta, 6);
btostr(sccmd, sc_sz, sccmd_str);
list_for_each_entry(n, &c->nodelist, list) {
if (n == ex)
continue;
}
}
static int cntlr_monitor_sta(struct controller *c, uint8_t *sta,
struct node *sta_node)
{
char sta_macstr[12 + 1] = {0};
struct node *n;
btostr((unsigned char *)sta, 6, sta_macstr);
list_for_each_entry(n, &c->nodelist, list) {
/* skip monitoring on sta's current node */
if (n == sta_node)
continue;
if (list_empty(&n->iflist))
#endif
static void forall_node_get_bcn_metrics(struct controller *c)
{
struct sta *s;
list_for_each_entry(s, &c->stalist, list) {
struct cmdu_buff *cmdu;
cmdu = cntlr_gen_sta_metric_query(c, s->fh->agent->alid, s->macaddr);
if (!cmdu)
continue;
send_cmdu(c, cmdu);
cmdu_free(cmdu);
}
}
static void forall_node_get_fhinfo(struct controller *c)
{
struct node *n;
}
static void node_get_monitor_sta(void *cntlr, void *resp, int len, void *cookie)
{
struct controller *c = (struct controller *)cntlr;
/* struct node *n = (struct node *)cookie; */
struct cmd_monitor_sta *info;
#define SZ sizeof(struct cmd_monitor_sta)
unsigned char rbytes[SZ] = {0};
struct active_sta *entry;
int nbr_rssi = 0;
cntlr_dbg("%s(): received: %s\n", __func__, (char *)resp);
strtob(resp, len, rbytes);
info = (struct cmd_monitor_sta *)rbytes;
/* TODO: info->rssi[0..3] */
nbr_rssi = (info->rssi[0] > 0) ? info->rssi[0] - 256 : info->rssi[0];
info->seen = ntohl(info->seen);
if (hwaddr_is_zero(info->addr) || nbr_rssi == 0) {
cntlr_dbg("Invalid GET_MONITOR resp!!!\n");
return;
}
entry = as_lookup(c->as_table, info->addr);
if (!entry)
return;
cntlr_dbg("STA " MACFMT " old best nbr-rssi = %d nbr-rssi = %d " \
"seen = %d secs ago\n",
MAC2STR(entry->hwaddr), entry->best_nbr_rssi,
nbr_rssi, info->seen);
if (entry->best_nbr_rssi < nbr_rssi &&
(info->seen >= 0 && info->seen < 30)) {
entry->best_nbr_rssi = nbr_rssi;
memcpy(entry->best_nbr, info->bss, 6);
cntlr_dbg("STA " MACFMT " better neighbor is " MACFMT \
" with rssi %d\n",
MAC2STR(info->addr),
MAC2STR(entry->best_nbr),
entry->best_nbr_rssi);
}
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
static int cntlr_handle_sta_rssi_low(struct controller *c, struct node *sta_n,
uint8_t *sta, int lowrssi)
{
struct node *n;
char sta_macstr[12 + 1] = {0};
struct active_sta *s_entry;
if (hwaddr_is_zero(sta))
return 0;
s_entry = as_lookup(c->as_table, sta);
if (!s_entry)
return -1;
/* reset lowrssi and best_nbr */
s_entry->lowrssi = lowrssi;
s_entry->best_nbr_rssi = -127;
memset(s_entry->best_nbr, 0, 6);
/* get this sta's monitored data from other nodes,
* if any available.
*/
btostr((unsigned char *)sta, 6, sta_macstr);
list_for_each_entry(n, &c->nodelist, list) {
if (n == sta_n)
continue; /* skip sta's currently assoc'd node */
}
cntlr_dbg("%s: After doing get monitor sta .......\n", __func__);
if (hwaddr_is_zero(s_entry->best_nbr))
return 0;
#define lowrssi_thresh -65
#define diffrssi 9
if (lowrssi < lowrssi_thresh &&
(s_entry->best_nbr_rssi != -127 &&
s_entry->best_nbr_rssi - lowrssi >= diffrssi)) {
/* found a better neighbor for this lowrssi sta */
#define ss_sz (sizeof(struct cmd_steer_sta) + 6)
unsigned char sscmd[ss_sz] = {0};
struct cmd_steer_sta *ss = (struct cmd_steer_sta *)sscmd;
char sscmd_str[2 * ss_sz + 1] = {0};
struct node *best_nbr_node;
/* 1. assoc_control STA on all nodes but the best_nbr node */
best_nbr_node = get_node_by_bssid(c, s_entry->best_nbr);
if (best_nbr_node)
forall_but_node_restrict_sta(c, best_nbr_node, sta);
/* 2. send steer mandate */
memcpy(ss->sta, sta, 6);
ss->num = htonl(1);
memcpy(ss->nbrs, s_entry->best_nbr, 6);
btostr(sscmd, ss_sz, sscmd_str);
cntlr_dbg("CMD_STEER in agent with best nbr +++++++++++>\n");
static bool endpoint_hwaddr(struct controller *c, unsigned char *sta)
{
struct node *n;
list_for_each_entry(n, &c->nodelist, list) {
if (!memcmp(n->alid, sta, 6))
return false;
}
return true;
}
static void cntlr_handle_assoclist_resp(void *cntlr,
void *resp,
int len,
void *cookie)
{
struct controller *c = (struct controller *)cntlr;
struct netif_fhbss *p, *fh = (struct netif_fhbss *)cookie;
unsigned char rbytes[sizeof(struct cmd_get_assoclist)] = {0};
unsigned char *bssid = fh->bssid;
struct cmd_get_assoclist *info;
bool found = false;
int i, num_sta;
struct node *n;
/* cntlr_dbg("%s(): received: %s\n", __func__, (char *)resp); */
strtob(resp, len, rbytes);
info = (struct cmd_get_assoclist *)rbytes;
num_sta = ntohl(info->num);
/* TODO: include node pointer in netif_fhbss, so that
* we don't have to parse for node from fh.
*/
list_for_each_entry(n, &c->nodelist, list) {
list_for_each_entry(p, &n->iflist, list) {
if (p == fh) {
found = true;
break;
}
}
}
if (!found)
n = NULL;
for (i = 0; i < num_sta; i++) {
unsigned char *macaddr = &info->sta[6 * i];
if (!endpoint_hwaddr(c, macaddr))
continue;
as_insert(c->as_table, macaddr, bssid);
if (n) {
cntlr_dbg("Start Monitoring for STA " MACFMT " ....\n",
MAC2STR(macaddr));
cntlr_monitor_sta(c, macaddr, n);
}
}
}
/* XXX: now doing for only the first fh-iface of a node */
static void forall_node_get_assoclist(struct controller *c)
{
struct node *n;
list_for_each_entry(n, &c->nodelist, list) {
struct netif_fhbss *p;
struct cmd_get_assoclist req;
char reqbuf[2 * sizeof(struct cmd_get_assoclist) + 1] = {0};
if (list_empty(&n->iflist))
p = list_first_entry(&n->iflist,
if (!p)
continue;
memset(&req, 0, sizeof(req));
strncpy(req.ifname, p->ifname, 16);
btostr((unsigned char *)&req, sizeof(req), reqbuf);
if (ret)
cntlr_dbg("Failed to get assoclist (ret = %d)\n", ret);
}
int invoke_disconnect_sta(struct node *n, struct netif_iface *p,
}
int invoke_disconnect_sta_by_bssid(struct controller *c, unsigned char *bssid,
unsigned char *hwaddr)
{
int ret = 0;
struct node *n;
struct netif_fhbss *p;
n = get_node_by_bssid(c, bssid);
if (!n)
return -1;
list_for_each_entry(p, &n->iflist, list) {
if (memcmp(bssid, p->bssid, 6))
continue;
invoke_disconnect_sta(n, p, hwaddr);
break;
}
return ret;
struct netif_iface *cntlr_radio_add_interface(struct controller *c,
struct netif_radio *r, uint8_t *hwaddr)
n = find_interface_by_mac(c, r, hwaddr);
if (n) {
n->active = true;
n->band = r->band;
return n;
n = calloc(1, sizeof(*n));
if (!n)
return NULL;
memcpy(n->bssid, hwaddr, 6);
n->type = NETIF_FHBSS;
n->active = true;
list_add(&n->list, &r->iflist);
n->agent = r->agent;
n->band = r->band;
return n;
struct netif_radio *cntlr_node_add_radio(struct controller *c, struct node *n,
uint8_t *radio)
r = find_radio_by_node(c, n, radio);
if (r)
return r;
r = calloc(1, sizeof(*r));
if (!r)
return NULL;
memcpy(r->macaddr, radio, 6);
INIT_LIST_HEAD(&r->iflist);
list_add(&r->list, &n->radiolist);
r->agent = n;
struct node *alloc_node_init(struct controller *c, uint8_t *hwaddr)
n = find_node_by_mac(c, hwaddr);
if (n)
return n;
n = calloc(1, sizeof(struct node));
if (!n) {
warn("OOM: node malloc failed!\n");
return NULL;
n->cntlr = c;
n->depth = -1;
n->scan_supported = true;
memcpy(n->alid, hwaddr, 6);
//INIT_LIST_HEAD(&n->stalist);
INIT_LIST_HEAD(&n->radiolist);
list_add(&n->list, &c->nodelist);
dbg("%s %d --------------------------- " MACFMT "\n", __func__, __LINE__, MAC2STR(hwaddr));
cmdu = cntlr_gen_bk_caps_query(c, n->alid);
if (!cmdu)
return n;
send_cmdu(c, cmdu);
cmdu_free(cmdu);
cmdu = cntlr_gen_ap_capability_query(c, n->alid);
if (!cmdu)
return n;
send_cmdu(c, cmdu);
cmdu_free(cmdu);
void free_bcn_metrics(struct controller *c, struct sta *s)
struct bcn_metrics *b, *tmp;
list_for_each_entry_safe(b, tmp, &s->bcnlist, list) {
list_del(&b->list);
free(b);
}
}
void free_watchnode_cleanup(struct controller *c, struct watchnode *wn)
{
uloop_timeout_cancel(&wn->scan_timer);
uloop_timeout_cancel(&wn->scanres_timer);
list_del(&wn->list);
free(wn);
}
void free_node_cleanup(struct controller *c, struct node *n)
{
#if 0
uloop_timeout_cancel(&n->refresh_timer);
#endif
ubus_unregister_event_handler(c->ubus_ctx, &n->evh);
list_flush(&n->iflist, struct netif_iface, list);
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
static int topology_add_node(struct controller *c, char *prefix)
{
struct node *n;
struct in_addr ipn;
if (!prefix) {
cntlr_dbg("%s: prefix = NULL!\n", __func__);
return -1;
}
if (strlen(prefix) && !inet_aton(prefix, &ipn)) {
cntlr_dbg("Invalid prefix: %s\n", prefix);
return -1;
}
if (strlen(prefix))
n = find_node_by_ip(c, prefix);
else
n = find_node_by_ip(c, "127.0.0.1");
if (n) {
/* This node is already in our list.
* If the comm path to it is still
* alive, then we can discard add.
*/
/* TODO: check if uobj[4] is valid? */
return 0;
}
info("Alloc new node ### for ipaddr '%s'\n",
strlen(prefix) ? prefix : "127.0.0.1");
n = alloc_node_init(c, prefix);
if (!n)
return -1;
if (strlen(prefix)) {
struct active_sta *as;
hwaddr_from_ip(c->cfg.al_bridge, prefix, n->hwaddr);
info("%s: " MACFMT "\n", __func__, MAC2STR(n->hwaddr));
/* TODO
* if (node_uplink_wifi(c, n->hwaddr))
* n->ul_type = UL_WIFI;
*/
/* Remove this backhaul iface macaddr from active STA list */
as = as_lookup(c->as_table, n->hwaddr);
if (as)
as_clean_entry(c->as_table, n->hwaddr, as->bssid);
} else
info("%s: (local) " MACFMT "\n", __func__, MAC2STR(n->hwaddr));
list_add(&n->list, &c->nodelist);
c->num_nodes++;
return 0;
}
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
static int cntlr_cmd_set_channel(struct controller *c,
void *agent,
uint32_t ch,
uint32_t bw)
{
#define sz (sizeof(struct cmd_param) + 4 + 4)
unsigned char chbuf[sz] = {0};
char chbufstr[2 * sz + 1] = {0};
struct cmd_param_channel {
struct cmd_param p;
uint32_t ch;
uint32_t bw;
} *pch = (struct cmd_param_channel *)chbuf;
sprintf(pch->p.type, "%s", "channel");
pch->p.len = htonl(8); /* channel, bw */
pch->ch = htonl(ch);
pch->bw = htonl(bw);
btostr(chbuf, sz, chbufstr);
dbg("cmd_set_param: %s\n", chbufstr);
CMD(c->comm, c, agent, CMD_SET_PARAM,
chbufstr, sizeof(chbufstr), NULL, NULL);
return 0;
}
static void cntlr_radar_exit(struct uloop_timeout *t)
{
/*TODO: before change channel due to radar, save old chandef.
* Restore that chandef upon exit from radar nop.
*/
#if 0 /* Not setting chandef to auto due to reason above */
struct controller *c = container_of(t, struct controller, radar_timer);
struct node *n;
list_for_each_entry(n, &c->nodelist, list) {
if (list_empty(&n->iflist))
continue;
cntlr_dbg("Sending SET_CHANNEL to node (%p:%p)---->\n",
n, n->uobj[4]);
/* auto channel */
cntlr_cmd_set_channel(c, (void *)n->uobj[4], 0, 80);
}
#endif
}
static int cntlr_handle_radar_alert(struct controller *c, struct watchnode *wn)
{
struct node *n;
list_for_each_entry(n, &c->nodelist, list) {
/* skip watchnode as CMD for it will fail */
if (!memcmp(n->hwaddr, wn->hwaddr, 6)) /* TODO: verify this */
continue;
if (list_empty(&n->iflist))
continue;
cntlr_dbg("Sending SET_CHANNEL to node (%p:%p)---->\n",
n, n->uobj[4]);
/* switch to a fixed non-dfs channel */
cntlr_cmd_set_channel(c, (void *)n->uobj[4], 36, 80);
}
uloop_timeout_set(&c->radar_timer, 3600 * 1000);
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
static void watchlist_scanres_node_dump(void *cntlr, void *resp, int len,
void *cookie)
{
struct controller *c = (struct controller *)cntlr;
struct watchnode *wn = (struct watchnode *)cookie;
unsigned char rbytes[sizeof(struct wifi_bss_detail)] = {0};
struct wifi_bss_detail *bx;
unsigned char radar_ie[9] = "\xdd\x0b\x00\x22\x07\xdd\x06\xaa\x04";
int ret;
/* cntlr_dbg("%s(): received: %s\n", __func__, (char *)resp); */
strtob(resp, len, rbytes);
bx = (struct wifi_bss_detail *)rbytes;
bx->ielen = ntohl(bx->ielen);
if (!memmem(bx->ie, bx->ielen, radar_ie, sizeof(radar_ie))) {
cntlr_dbg("radar ie not present\n");
if (++wn->scan_retry > WATCHNODE_SCAN_RETRY_MAX) {
free_watchnode_cleanup(c, wn);
return;
}
uloop_timeout_set(&wn->scan_timer, 30 * 1000);
return;
}
info("Node " MACFMT " has detected radar\n", MAC2STR(wn->hwaddr));
ret = cntlr_handle_radar_alert(c, wn);
free_watchnode_cleanup(c, wn);
}
static void watchlist_scanres_node(struct uloop_timeout *t)
{
struct watchnode *wn = container_of(t, struct watchnode, scanres_timer);
struct controller *c = wn->cntlr;
char bssidstr[12 + 1] = {0};
struct node *n;
int ret = 0;
btostr(wn->fh_bssid, sizeof(wn->fh_bssid), bssidstr);
list_for_each_entry(n, &c->nodelist, list) {
/* skip watchnode as CMD for it will fail */
if (!memcmp(n->hwaddr, wn->hwaddr, 6)) /* TODO: verify this */
continue;
if (list_empty(&n->iflist))
continue;
}
if (ret && ++wn->scan_retry < WATCHNODE_SCAN_RETRY_MAX) {
cntlr_dbg("Will retry-%d watchnode scan\n", wn->scan_retry);
uloop_timeout_set(&wn->scan_timer, 20 * 1000);
}
}
static void watchlist_scan_node(struct uloop_timeout *t)
{
struct watchnode *wn = container_of(t, struct watchnode, scan_timer);
struct controller *c = wn->cntlr;
struct node *n;
list_for_each_entry(n, &c->nodelist, list) {
struct scan_param sp;
char spbuf[2*sizeof(struct scan_param) + 1] = {0};
/* skip watchnode as CMD for it will fail */
if (!memcmp(n->hwaddr, wn->hwaddr, 6))
continue;
if (list_empty(&n->iflist))