diff --git a/src/agent.c b/src/agent.c index 6fd836da3a2a3f04771ee74411ed4cfea0ee7a3e..7338d09226b65684264738cfccb8bbf9c8c7e286 100644 --- a/src/agent.c +++ b/src/agent.c @@ -1627,6 +1627,68 @@ out: } #endif +static void wifi_chan_change_event_handler(void *c, struct blob_attr *msg) +{ + struct agent *a = (struct agent *)c; + char ifname[16] = {0}, event[16] = {0}; + struct cmdu_buff *cmdu; + struct blob_attr *tb[3]; + static const struct blobmsg_policy ev_attr[3] = { + [0] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, + [1] = { .name = "event", .type = BLOBMSG_TYPE_STRING }, + [2] = { .name = "data", .type = BLOBMSG_TYPE_TABLE }, + }; + bool chan_change = false; + struct wifi_radio_element *radio = NULL; + + + blobmsg_parse(ev_attr, 3, tb, blob_data(msg), blob_len(msg)); + + if (!tb[0] || !tb[1] || !tb[2]) + return; + + strncpy(ifname, blobmsg_data(tb[0]), sizeof(ifname) - 1); + strncpy(event, blobmsg_data(tb[1]), sizeof(event) - 1); + + chan_change = !strcmp(event, "ap-chan-change"); + + if (chan_change) { + struct blob_attr *data[2]; + static const struct blobmsg_policy data_attr[2] = { + [0] = { .name = "target-channel", .type = BLOBMSG_TYPE_STRING }, + [1] = { .name = "target-width", .type = BLOBMSG_TYPE_STRING }, + }; + char chan[18] = {0}; + char bw[18] = {0}; + uint32_t channel = 0; + uint32_t bandwidth = 0; + blobmsg_parse(data_attr, 2, data, blobmsg_data(tb[2]), + blobmsg_data_len(tb[2])); + + if (!data[0] || !data[1]) + return; + + strncpy(chan, blobmsg_data(data[0]), sizeof(chan) - 1); + strncpy(bw, blobmsg_data(data[1]), sizeof(bw) - 1); + + channel = atoi(chan); + bandwidth = atoi(bw); + trace("|%s:%d| Channel has changed to channel [%d] bandwidth [%d]\n", + __func__, __LINE__, channel, bandwidth); + trace("|%s:%d| Channel has changed ifname [%s]\n", + __func__, __LINE__, ifname); + /*Here we need to send the operating channel report message*/ + radio = wifi_ifname_to_radio_element(a, ifname); + cmdu = agent_gen_oper_channel_response(a, radio, channel, bandwidth, 0); + if (!cmdu) + return -1; + + agent_send_cmdu(a, cmdu); + cmdu_free(cmdu); + } + //TODONEV write the new operating channel in the radio current operating channel +} + static void wifi_sta_event_handler(void *c, struct blob_attr *msg) { struct agent *a = (struct agent *)c; @@ -2807,6 +2869,7 @@ static void agent_event_handler(struct ubus_context *ctx, { "wifi.bsta", wifi_bsta_event_handler }, { "ethport", ethport_event_handler }, { "ubus.object.add", uobj_add_event_handler }, + { "wifi.ap", wifi_chan_change_event_handler }, }; str = blobmsg_format_json(msg, true); @@ -3290,6 +3353,29 @@ static void parse_almac(struct ubus_request *req, int type, } } +int agent_fill_channel_preference_default(struct wifi_radio_element *radio) +{ + int i = 0, j = 0; + + for (i = 0; i < radio->num_supp_opclass; i++) { + struct wifi_opclass_supported_element *supp = + radio->supp_opclass + i; + + if (supp->id != radio->current_opclass) + continue; + + for (j = 0; j < supp->num_supported_channels; j++) { + struct supp_channel *sch = supp->supp_chanlist + j; + + if (sch->channel == radio->current_channel) + sch->pref = 0x0f; + else + sch->pref = 0x01; + + } + } +} + static void parse_radio(struct ubus_request *req, int type, struct blob_attr *msg) { @@ -3297,6 +3383,7 @@ static void parse_radio(struct ubus_request *req, int type, fprintf(stdout, "%s ---> %s\n", __func__, re->name); int rem, remm, rem1, j = 0, i = 0; struct blob_attr *tb[12]; + int ret = 0; static const struct blobmsg_policy radio_attr[12] = { [0] = { .name = "isup", .type = BLOBMSG_TYPE_BOOL }, [1] = { .name = "band", .type = BLOBMSG_TYPE_STRING }, @@ -3478,6 +3565,10 @@ static void parse_radio(struct ubus_request *req, int type, ((blobmsg_get_u64(tb1[3]) * 255) / 100) & 0xff; } + //TODO Here we need to read the preference of the opclass from the config + //TODO see if needed First time when no preference is set for the operating class + //ret = agent_fill_channel_preference_default(re); + //TODONEV Add the config to preference writing here } struct wifi_scanres_channel_element *wifi_get_scanres_ch_element(struct wifi_radio_element *re, uint8_t ch) @@ -4169,6 +4260,7 @@ int agent_init_interfaces(struct agent *a) fn->radio = r_wobj; fn->cfg = f; fn->agent = a; + strncpy(fn->radio_name, radio_name, IFNAMSIZ-1); list_add(&fn->list, &a->fhlist); ubus_call_object(a, wobj, "status", parse_ap, fn); @@ -4583,8 +4675,8 @@ static void agent_subscribe_for_cmdus(struct agent *a) CMDU_BACKHAUL_STEER_REQUEST, CMDU_AP_METRICS_QUERY, CMDU_ASSOC_STA_LINK_METRICS_QUERY, - CMDU_CHANNEL_SCAN_REQUEST, - CMDU_CHANNEL_SCAN_REPORT, + //CMDU_CHANNEL_SCAN_REQUEST, + //CMDU_CHANNEL_SCAN_REPORT, CMDU_POLICY_CONFIG_REQ, CMDU_BACKHAUL_STA_CAPABILITY_QUERY, CMDU_BACKHAUL_STA_CAPABILITY_REPORT, diff --git a/src/agent.h b/src/agent.h index 3f86205c0d012529ed01f59786b14975b7bb87c9..56b39a41a42ebb891c9c4dda818a5757f684568c 100644 --- a/src/agent.h +++ b/src/agent.h @@ -192,6 +192,7 @@ struct netif_fh { unsigned char bssid[6]; char ssid[33]; char standard[32]; + char radio_name[6]; bool enabled; bool torndown; int bssload; diff --git a/src/agent_cmdu.c b/src/agent_cmdu.c index 3983d9fd84be3d023225718ef6e8dd0bb71c992c..5afc83224f263d8d83a9b8d3df10a8bac0d65dea 100644 --- a/src/agent_cmdu.c +++ b/src/agent_cmdu.c @@ -1195,30 +1195,40 @@ error: return NULL; } -struct cmdu_buff *agent_gen_oper_channel_response(struct agent *a, - struct cmdu_buff *rx_cmdu) +struct cmdu_buff *agent_gen_oper_channel_response(struct agent *a, struct wifi_radio_element *radio, + uint32_t channel, uint32_t bandwidth, bool all) { uint32_t j; uint16_t mid = 0; struct cmdu_buff *cmdu; int ret; - mid = cmdu_get_mid(rx_cmdu); cmdu = cmdu_alloc_simple(CMDU_OPERATING_CHANNEL_REPORT, &mid); if (!cmdu) { dbg("%s: -ENOMEM\n", __func__); return NULL; } - memcpy(cmdu->origin, rx_cmdu->origin, 6); - - /* Operating Channel Report TLV 17.2.17 */ - for (j = 0; j < a->num_radios; j++) { - ret = agent_gen_oper_channel_report(a, cmdu, j); - if (ret) + if (all == 1) { + /* Operating Channel Report TLV 17.2.17 */ + for (j = 0; j < a->num_radios; j++) { + struct wifi_radio_element *radio = a->radios + j; + uint32_t chan = radio->current_channel; + uint32_t op_class = radio->current_opclass; + ret = agent_gen_oper_channel_report(a, cmdu, radio, chan, 0, op_class); + if (ret) + goto error; + } + } + else { + ret = agent_gen_oper_channel_report(a, cmdu, radio, channel, bandwidth, 0); + if (ret) goto error; } + /* destination controller */ + memcpy(cmdu->origin, a->cntlr_almac, 6); + cmdu_put_eom(cmdu); return cmdu; diff --git a/src/agent_cmdu.h b/src/agent_cmdu.h index a60fb77ab8c13fa1dcb703b204ed3ae2621159c1..aa3a688625179960a38161dc44dd9a2c5c684ddd 100644 --- a/src/agent_cmdu.h +++ b/src/agent_cmdu.h @@ -54,7 +54,7 @@ struct cmdu_buff *agent_gen_channel_preference_report(struct agent *a, struct cmdu_buff *rx_cmdu); struct cmdu_buff *agent_gen_association_status_notify(struct agent *a, int num_data, void *data); -struct cmdu_buff *agent_gen_oper_channel_response(struct agent *a, - struct cmdu_buff *rx_cmdu); +struct cmdu_buff *agent_gen_oper_channel_response(struct agent *a, struct wifi_radio_element *radio, + uint32_t channel, uint32_t bandwidth, bool all); #endif /* MAPAGENT_CMDU_H */ diff --git a/src/agent_map.c b/src/agent_map.c index efba8d8a4692ed0feed32e59e9165d3658127c39..ac8122e5d1789c828468165e2f78777dfd05be5d 100644 --- a/src/agent_map.c +++ b/src/agent_map.c @@ -149,7 +149,7 @@ int send_oper_channel_report(void *agent, struct cmdu_buff *rx_cmdu) struct agent *a = (struct agent *) agent; struct cmdu_buff *cmdu; - cmdu = agent_gen_oper_channel_response(a, rx_cmdu); + cmdu = agent_gen_oper_channel_response(a, NULL, 0, 0, 1); if (!cmdu) return -1; @@ -1839,11 +1839,9 @@ int send_channel_sel_response(void *agent, struct cmdu_buff *rx_cmdu, agent_send_cmdu(a, cmdu); cmdu_free(cmdu); - /* TODO send a report message for each radio. This will be - * sent not here but on receiving of the event when the - * actually radio channel poreference have been changed - */ - send_oper_channel_report(agent, rx_cmdu); + /* send a report message for each radio. specifying current operating channels + * as per the spec pg 30*/ + //send_oper_channel_report(agent, rx_cmdu); return 0; error: @@ -1877,6 +1875,170 @@ int agent_fill_radio_max_preference(void *agent, return 0; } +static int f2c(int freq) +{ + int chan; + + if (freq > 5000) + chan = (freq - 5000) / 5; + else if (freq == 2484) + chan = 14; + else + chan = (freq - 2407) / 5; + + return chan; +} + +static int c2f(int chan) +{ + int freq = 0; + + if (chan >= 1 && chan <= 13) + freq = 2407 + chan * 5; + if (chan == 14) + freq = 2484; + if (chan >= 36) + freq = 5000 + chan * 5; + + return freq; +} + +int get_op_class_bw(int op_class) +{ + switch(op_class) { + + case 115: + case 118: + case 121: + case 125: + case 81: + case 82: + case 124: + return 20; + case 116: + case 119: + case 122: + case 117: + case 120: + case 123: + case 83: + case 84: + case 126: + case 127: + return 40; + case 128: + case 130: + return 80; + case 129: + return 160; + default: + return 0; + } + +} +/*This function return the channel with the highest preference*/ +int agent_get_highest_preference(struct agent *a, uint8_t *radio_id, int op_class_id, int *channel) +{ + trace("%s: --->\n", __func__); + int found = 0; + int pref = 0; + int l = 0, ret = 0; + struct wifi_radio_element *radio = NULL; + + trace("\tradio_id: " MACFMT "\n", MAC2STR(radio_id)); + for (l = 0; l < a->num_radios; l++) { + radio = a->radios + l; + ret = memcmp(radio->macaddr, radio_id, 6); + if (ret == 0) { + found = 1; + break; + } + } + + if (found == 0) + return -1; + + for (l = 0; l < radio->num_supp_opclass; l++) { + if (radio->supp_opclass[l].id == op_class_id) { + int m; + for (m = 0; m <radio->supp_opclass[l]. + num_supported_channels ; m++) { + trace("channel %d\n",radio->supp_opclass[l].supp_chanlist[m].channel ); + trace("channel preference %d\n",radio->supp_opclass[l].supp_chanlist[m].pref ); + if (pref < radio->supp_opclass[l].supp_chanlist[m].pref) { + pref = radio->supp_opclass[l].supp_chanlist[m].pref; + *channel = radio->supp_opclass[l].supp_chanlist[m].channel; + } + } + } + } + trace("channel to which channel needs to switch %d\n",*channel ); +} + +int agent_channel_switch(struct agent *a, uint8_t *radio_id, int channel, int opclass) +{ + trace("%s: --->\n", __func__); + struct blob_buf bb = {}; + int ret; + int freq = 0; + int bandwidth = 0; + struct netif_fh *p = NULL; + struct netif_fh *fh; + char ifname[16]; + int found = 0; + const char *radio_name = NULL; + trace("channel switch channel %d radio is "MACFMT" \n", channel, MAC2STR(radio_id)); + + list_for_each_entry(p, &a->fhlist, list) { + struct wifi_radio_element *radio = NULL; + + trace("radio name %s\n", p->name); + radio_name = wifi_ifname_to_radio(a, p->name); + if (!radio_name) + continue; + trace("radio name 2%s\n", radio_name); + radio = wifi_ifname_to_radio_element(a, p->name); + trace("radio name 3 mac is "MACFMT"\n", MAC2STR(radio->macaddr)); + ret = memcmp(radio_id, &radio->macaddr, 6); + trace ("after point 1 %d\n",ret); + trace("radio name 4\n"); + if(ret == 0) { + trace("I am here %p \n", p->cfg); + //trace("radio name 5 multi_ap flag is %d\n", p->cfg->band); + // trace("radio name 51 multi_ap flag is %d\n", p->cfg->multi_ap); + // if (p->cfg->multi_ap != 2) + // continue; + // else { + found = 1; + break; + // } + } + } + + if (found == 0) + return -1; + + freq = c2f(channel); + bandwidth = get_op_class_bw(opclass); + + trace("Calling channel switch for channel %d bandwidth %d point1\n", channel, bandwidth); + blob_buf_init(&bb, 0); + blobmsg_add_u32(&bb, "count", 5); + blobmsg_add_u32(&bb, "freq", freq); + blobmsg_add_u32(&bb, "bw", bandwidth); + trace("Calling channel switch for channel %d bandwidth %d \n", channel, bandwidth); + ret = ubus_invoke(a->ubus_ctx, p->wifi, "chan_switch", bb.head, + NULL, NULL, 1000); + if (ret) { + dbg("Failed to do the channel switch (ret = %d)\n", ret); + blob_buf_free(&bb); + return -1; + } + blob_buf_free(&bb); + return 0; +} + + int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, struct channel_response *channel_resp, uint32_t *channel_resp_nr) @@ -1946,12 +2108,13 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, /* Here we need to search the operating class in the radio */ for (l = 0; l < radio->num_supp_opclass; l++) { + int process = 0; if (radio->supp_opclass[l].id == op.class_id) { int k; /* Here we reset all the channels preferences * in the operating class as 15 highest - * preference + * preference as per the specs */ trace("op_class : %d channel_nr %d\n", op.class_id, op.num_ch); @@ -1960,7 +2123,7 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, radio->supp_opclass[l].num_supported_channels; k++) radio->supp_opclass[l]. - supp_chanlist[k].pref = 0xff; + supp_chanlist[k].pref = 0x0f; for (k = 0; k < op.num_ch; k++) { int m; @@ -1976,14 +2139,40 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, radio->supp_opclass[l]. supp_chanlist[m].pref = (op.pref & CHANNEL_PREF_MASK) >> 4; - - trace("channel pref is %d\n", + /*Here we should store the highest + *preference in the local variable and then switch + */ + trace("channel pref is NEV %d\n", (op.pref & CHANNEL_PREF_MASK) >> 4); + process = 1; } } } - break; + // break; + // } + //Here the global operating class channels have been assigned prefernces + if(process == 1) { + /* Here we need to see that what is the current operating channel + * and that we want to switch to*/ + int channel = 0; + ret = agent_get_highest_preference(a, radio_id, op.class_id, &channel); + /* The operating class channel preference has been set + * now we want to switch the channel to the max preference */ + if(channel != 0) { + ret = agent_channel_switch(a, radio_id, channel, op.class_id); + if (ret == -1) { + /*Here we need to set the default preference for all the + * channels in that operating class also set the response code as rejected*/ + } + } + /* Here we need to write the corresponding preference in the + * config file to make preference reboot persistent */ + // ret = agent_config_channel_preference(); + process = 0; } + // break; + } + } if ((op.num_ch > 0) && op.chanlist) @@ -1995,6 +2184,33 @@ int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, return ret; } +int agent_process_transmit_power_tlv(struct agent *a, struct tlv_txpower_limit *p) +{ + int l = 0; + struct wifi_radio_element *radio; + uint32_t match = 0; + + trace("tlv radio_id: " MACFMT "\n", + MAC2STR(p->radio)); + for (l = 0; l < a->num_radios; l++) { + radio = a->radios + l; + match = memcmp(radio->macaddr, p->radio, 6); + if (match == 0) { + /* Here we set the + * transmit_power_limit + * of the radio this also needs to be set in + * the wireless file + */ + radio->transmit_power_limit = p->limit; + trace("radio name is %s\n", radio->name); + wifi_set_transmit_power(radio->name, p->limit); + trace("transmit power %d\n", p->limit); + break; + } + } + +} + int handle_channel_sel_request(void *agent, struct cmdu_buff *cmdu) { trace("agent: %s: --->\n", __func__); @@ -2032,6 +2248,9 @@ int handle_channel_sel_request(void *agent, struct cmdu_buff *cmdu) while (tv[1][idx]) { struct tlv_txpower_limit *p = (struct tlv_txpower_limit *)tv[1][idx++]->data; + + ret = agent_process_transmit_power_tlv(agent, p); +#if 0 int l; trace("tlv radio_id: " MACFMT "\n", @@ -2042,12 +2261,14 @@ int handle_channel_sel_request(void *agent, struct cmdu_buff *cmdu) if (match == 0) { /* Here we set the * transmit_power_limit - * of the radio + * of the radio this also needs to be set in + * the wireless file */ radio->transmit_power_limit = p->limit; trace("transmit power %d\n", p->limit); } } +#endif } if (pref_tlv_present == 0) { diff --git a/src/agent_tlv.c b/src/agent_tlv.c index 1ebc04851924580e34df92972c7e3262fed92483..98d4fe1416bbb3ef8fc613f1320b4ab4e9c4def4 100644 --- a/src/agent_tlv.c +++ b/src/agent_tlv.c @@ -519,15 +519,75 @@ int agent_gen_metric_collection_interval(struct agent *a, struct cmdu_buff *cmdu return 0; } +int get_op_class_frm_channel(uint32_t channel, uint32_t bandwidth) +{ + if (bandwidth == 20) { + if (channel >= 1 && channel <= 13) + return 81; + else if (channel == 14) + return 82; + else if (channel == 36 || channel ==40 ||channel == 44|| channel == 48) + return 115; + else if (channel == 52 || channel ==53 ||channel == 60|| channel == 64) + return 118; + else if (channel == 100 || channel == 104 ||channel == 108|| channel == 112 || + channel == 116 || channel == 120 ||channel == 124|| channel == 128 || + channel == 132 || channel == 136 ||channel == 140|| channel == 144) + return 121; + else if (channel == 149 || channel == 153 || channel == 157|| channel == 161) + return 124; + else if (channel == 149 || channel == 153 || channel == 157 || channel == 161 || + channel == 165 || channel == 169) + return 125; + + } else if (bandwidth == 40) { + if (channel >= 1 && channel <= 9) + return 83; + else if (channel >= 5 && channel <= 13) + return 84; + else if (channel == 36 || channel == 44) + return 116; + else if (channel == 40 || channel == 48) + return 117; + else if (channel == 52 || channel == 60) + return 119; + else if (channel == 56 || channel == 64) + return 120; + else if (channel == 100 || channel == 108|| channel == 116 || channel == 124 || + channel == 128 || channel == 136 || channel == 144) + return 122; + else if (channel == 104|| channel == 112 || channel == 120|| channel == 128 || + channel == 136 || channel == 144) + return 123; + else if (channel == 149 || channel == 157) + return 126; + else if (channel == 153 || channel == 161) + return 127; + } else if (bandwidth == 80) { + if (channel == 36 || channel == 52|| channel == 100 || channel == 116 || + channel == 132 || channel == 149) + return 128; + else if (channel == 36|| channel == 52 || channel == 100|| channel == 116 || + channel == 132 || channel == 149) + return 130; + } else if (bandwidth == 160) { + if (channel == 36 && channel == 100) + return 129; + } + return 0; + +} + int agent_gen_oper_channel_report(struct agent *a, - struct cmdu_buff *frm, uint32_t radio_index) + struct cmdu_buff *frm, struct wifi_radio_element *radio, + uint32_t channel, uint32_t bw, uint32_t opclass ) { int j; int ret, offset = 0; int num_opclass = 1; uint8_t txpower = 0; struct tlv *t; - struct wifi_radio_element *radio = a->radios + radio_index; + //struct wifi_radio_element *radio = a->radios + radio_index; t = cmdu_reserve_tlv(frm, 100); if (!t) @@ -538,8 +598,15 @@ int agent_gen_oper_channel_report(struct agent *a, offset += 6; t->data[offset++] = num_opclass; /* num opclass */ for (j = 0; j < num_opclass; j++) { - t->data[offset++] = radio->current_opclass; - t->data[offset++] = radio->current_channel; + if (opclass == 0) { + uint32_t op_class = get_op_class_frm_channel(channel, bw); + if (op_class == 0) + return -1; + t->data[offset++] = op_class; + } else { + t->data[offset++] = opclass; + } + t->data[offset++] = (uint8_t) channel; } /* current transmit power is the (operating class tx power) * @@ -628,9 +695,6 @@ int agent_gen_channel_pref (struct agent *a, for (j = 0; j < supp->num_supported_channels; j++) { struct supp_channel *sch = supp->supp_chanlist + j; - /* TODO/FIXME: channel_pref value; - * as of now, hardcoded value is set for channel preference - */ if (sch->pref != 0x0f) { t->data[offset++] = sch->channel; /* channel */ channel_pref = sch->pref; @@ -658,7 +722,7 @@ int agent_gen_radio_oper_restrict(struct agent *a, { int ret, offset = 0; int i, j; - int num_restrict_opclass = 1; + int num_restrict_opclass = 0; struct tlv *t; struct wifi_radio_element *radio = a->radios + radio_index; @@ -672,7 +736,9 @@ int agent_gen_radio_oper_restrict(struct agent *a, offset += 6; t->data[offset++] = num_restrict_opclass; + //TODO: api to get the restricted operating classes for (i = 0; i < radio->num_supp_opclass; i++) { +#if 0 uint8_t *num_channels; struct wifi_opclass_supported_element *supp = radio->supp_opclass + i; @@ -694,6 +760,7 @@ int agent_gen_radio_oper_restrict(struct agent *a, t->data[offset++] = 0; /* TODO dummy values; min_freq_sep */ (*num_channels)++; } +#endif } t->len = offset; diff --git a/src/agent_tlv.h b/src/agent_tlv.h index fd2ba046395e2bbed3e419355da656bdfe95f028..92be44d7e2c989db42c162714b91de2db38097ea 100644 --- a/src/agent_tlv.h +++ b/src/agent_tlv.h @@ -11,20 +11,6 @@ #define MAPAGENT_TLV_H #define VENDOR_SPECIFIC_TYPE_DEPTH 0x0a -#define TLV_TYPE_VENDOR_SPECIFIC (0x11) -static inline void buf_put_be64(uint8_t *buf, uint64_t val) -{ - buf[0] = (val >> 56) & 0xff; - buf[1] = (val >> 48) & 0xff; - buf[2] = (val >> 40) & 0xff; - buf[3] = (val >> 32) & 0xff; - buf[4] = (val >> 24) & 0xff; - buf[5] = (val >> 16) & 0xff; - buf[6] = (val >> 8) & 0xff; - buf[7] = val & 0xff; -} - -#define BUF_PUT_BE64(b, v) buf_put_be64((uint8_t *)&(b), v) /** TLV: Vendor Specific TLV */ struct tlv_vendor_metric_specific { uint8_t oui[3]; @@ -60,7 +46,8 @@ int agent_gen_wsc(struct agent *a, struct cmdu_buff *cmdu, struct wifi_radio_element *radio); int agent_gen_ch_scan_cap(struct agent *a, struct cmdu_buff *cmdu); int agent_gen_oper_channel_report(struct agent *a, - struct cmdu_buff *frm, uint32_t radio_index); + struct cmdu_buff *frm, struct wifi_radio_element *radio, + uint32_t channel, uint32_t bw, uint32_t opclass ); int agent_gen_channel_selection_resp(struct agent *a, struct cmdu_buff *cmdu, uint8_t *radio_recvd, uint8_t reason_code); int agent_gen_cac_cap(struct agent *a, struct cmdu_buff *cmdu); diff --git a/src/config.c b/src/config.c index 07a6ba010428c862f0c7dd2b0987a18384876008..20c283bf2292a665f33248c947cbeed76fd397f6 100644 --- a/src/config.c +++ b/src/config.c @@ -1858,7 +1858,8 @@ static int agent_config_get_fh_iface(struct agent_config *a, FH_REPORT_UTIL_THRESHOLD, FH_INCLUDE_STA_STATS, FH_INCLUDE_STA_METRIC, - NUM_POLICIES, + FH_MULTI_AP, + NUM_POLICIES }; const struct uci_parse_option opts[] = { { .name = "ifname", .type = UCI_TYPE_STRING }, @@ -1882,7 +1883,8 @@ static int agent_config_get_fh_iface(struct agent_config *a, { .name = "rcpi_hysteresis_margin", .type = UCI_TYPE_STRING }, { .name = "report_util_threshold", .type = UCI_TYPE_STRING }, { .name = "include_sta_stats", .type = UCI_TYPE_STRING }, - { .name = "include_sta_metric", .type = UCI_TYPE_STRING } + { .name = "include_sta_metric", .type = UCI_TYPE_STRING }, + { .name = "multi_ap", .type = UCI_TYPE_STRING } }; struct uci_option *tb[NUM_POLICIES]; struct netif_fhcfg *fh; @@ -2021,6 +2023,10 @@ static int agent_config_get_fh_iface(struct agent_config *a, fh->include_sta_metric = atoi(tb[FH_INCLUDE_STA_METRIC]->v.string); + if (tb[FH_MULTI_AP]) { + fh->multi_ap = atoi(tb[FH_MULTI_AP]->v.string); + } + return 0; } @@ -2811,3 +2817,63 @@ out_pkg: return false; } +struct uci_section *config_get_name_section(struct uci_context *ctx, + struct uci_package *pkg, const char *type, const char *value) +{ + struct uci_element *e; + struct uci_section *section; + int ret = 0; + + trace("Inside %s %d\n", __func__, __LINE__); + + /* get the wet iface section */ + uci_foreach_element(&pkg->sections, e) { + const char *c_value; + + section = uci_to_section(e); + if (strcmp(section->type, type)) + continue; + + ret = strcmp(section->e.name, value); + dbg("Inside %s %d section name %s value %s \n", __func__, __LINE__, section->e.name, value); + if (ret == 0) { + + return section; + } + } + + return NULL; +} + +int wifi_set_transmit_power(uint8_t *ifname, uint32_t tx_power) +{ + struct uci_context *ctx = NULL; + struct uci_package *pkg; + struct uci_section *section; + char txpower_str[18] = {0}; + int ret = -1; + + trace("Inside %s %d\n", __func__, __LINE__); + pkg = uci_load_pkg(&ctx, UCI_WIRELESS); + if (!pkg) + return ret; + + section = config_get_name_section(ctx, pkg, UCI_DEVICE, ifname); + if (!section) + goto out_pkg; + + if (tx_power) + sprintf(txpower_str,"%d",tx_power); + + dbg("|%s:%d| setting tx_power to %s\n", __func__, __LINE__, txpower_str); + + ret = set_value(ctx, pkg, section, "txpower", txpower_str, UCI_TYPE_STRING); + + uci_commit(ctx, &pkg, false); + +out_pkg: + uci_unload(ctx, pkg); + uci_free_context(ctx); + return ret; +} + diff --git a/src/config.h b/src/config.h index 4a21915a9ee6367706d1479c4fa106dccc15ff84..1678f157d76a8439eb3f4e18a86be8b27e447eaa 100644 --- a/src/config.h +++ b/src/config.h @@ -37,6 +37,8 @@ enum steer_action { #define CONTROLLER_SELECT_RETRY_INT 3 /* attempts */ #define CONTROLLER_SELECT_AUTOSTART 0 /* don't start cntlr */ +#define UCI_DEVICE "wifi-device" + struct iop_ext; struct steer_policy { @@ -74,6 +76,7 @@ struct netif_fhcfg { char ssid[33]; char key[65]; char encryption[32]; + uint8_t multi_ap; /* this is parsed from config.c with rest of fh options */ enum wifi_band band; bool enabled; bool sta_steer_enabled;