diff --git a/src/core/agent.c b/src/core/agent.c index 44a1cb2c1261af2f3de2b8351e63492192e32b02..6b84b84ca5ecf746b13a9a5fb2be7e760175526d 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -2386,8 +2386,8 @@ static void parse_radio(struct ubus_request *req, int type, struct blob_attr *msg) { struct wifi_radio_element *re = (struct wifi_radio_element *)req->priv; - struct blob_attr *tb[9]; - static const struct blobmsg_policy radio_attr[9] = { + struct blob_attr *tb[10]; + static const struct blobmsg_policy radio_attr[10] = { [0] = { .name = "isup", .type = BLOBMSG_TYPE_BOOL }, [1] = { .name = "band", .type = BLOBMSG_TYPE_STRING }, [2] = { .name = "noise", .type = BLOBMSG_TYPE_INT32 }, @@ -2397,9 +2397,10 @@ static void parse_radio(struct ubus_request *req, int type, [6] = { .name = "opclass", .type = BLOBMSG_TYPE_INT32 }, [7] = { .name = "channel", .type = BLOBMSG_TYPE_INT32 }, [8] = { .name = "regdomain", .type = BLOBMSG_TYPE_STRING }, + [9] = { .name = "txpower", .type = BLOBMSG_TYPE_INT32 }, }; - blobmsg_parse(radio_attr, 9, tb, blob_data(msg), blob_len(msg)); + blobmsg_parse(radio_attr, 10, tb, blob_data(msg), blob_len(msg)); if (tb[0]) re->enabled = blobmsg_get_bool(tb[0]); @@ -2460,15 +2461,17 @@ static void parse_radio(struct ubus_request *req, int type, if (data[2]) re->supp_opclass[i].num_supported_channels = blobmsg_check_array(data[2], BLOBMSG_TYPE_INT32); - re->supp_opclass[i].supp_chanlist = calloc(re->supp_opclass[i].num_supported_channels, sizeof(uint8_t)); + re->supp_opclass[i].supp_chanlist = calloc(re->supp_opclass[i].num_supported_channels, sizeof(struct supp_channel)); if (!re->supp_opclass[i].supp_chanlist) { fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); return; } - blobmsg_for_each_attr(cur1, data[2], rem1) - re->supp_opclass[i].supp_chanlist[k++] = blobmsg_get_u32(cur1); - + blobmsg_for_each_attr(cur1, data[2], rem1) { + re->supp_opclass[i].supp_chanlist[k].channel = blobmsg_get_u32(cur1); + re->supp_opclass[i].supp_chanlist[k].pref = 0xff; + k++; + } re->supp_opclass[i].num_exclude_channels = 1; if (re->supp_opclass[i].num_exclude_channels > 0) { re->supp_opclass[i].exclude_chanlist = @@ -2492,6 +2495,9 @@ static void parse_radio(struct ubus_request *req, int type, if (tb[8]) memcpy(re->country_code, blobmsg_data(tb[8]), 2); + + if (tb[9]) + re->current_txpower_percent = (uint8_t) blobmsg_get_u32(tb[9]); } static void _enumerate_wifi_objects(struct ubus_request *req, int type, @@ -3142,8 +3148,10 @@ void agent_free_radios(struct agent *a) re = &a->radios[i]; - for (j = 0; j < re->num_supp_opclass; j++) + for (j = 0; j < re->num_supp_opclass; j++) { + free(re->supp_opclass[j].supp_chanlist); free(re->supp_opclass[j].exclude_chanlist); + } free(re->supp_opclass); diff --git a/src/core/agent.h b/src/core/agent.h index 25831d27adaf11027af151dec443fbbb2f194a89..1216e6521685bc7cfaf349494af41dbc40961c1d 100644 --- a/src/core/agent.h +++ b/src/core/agent.h @@ -221,13 +221,18 @@ enum { WIFI_IFACE_BK, }; +struct supp_channel { + uint8_t channel; + uint8_t pref; +}; + struct wifi_opclass_supported_element { uint8_t id; /* class number */ int8_t max_txpower; uint32_t num_exclude_channels; uint8_t *exclude_chanlist; /* list of non-operable channels */ uint32_t num_supported_channels; - uint8_t *supp_chanlist; /*list of supporting channels for each class*/ + struct supp_channel *supp_chanlist; /*list of supporting channels for each class*/ }; struct wifi_opclass_current_element { @@ -340,8 +345,11 @@ struct wifi_radio_element { uint8_t tx_streams; uint8_t current_opclass; uint8_t current_channel; + uint8_t current_txpower_percent; + uint8_t transmit_power_limit; /* set in the channel selection message */ uint8_t max_bss; + uint32_t num_supp_opclass; uint32_t num_curr_opclass; uint32_t num_unassoc_sta; diff --git a/src/core/agent_map.c b/src/core/agent_map.c index 6a134c1f015938c3aade44be9bb224a2ee1550ab..c3630d219dd541da79ef516bccae542ff44f03d0 100644 --- a/src/core/agent_map.c +++ b/src/core/agent_map.c @@ -57,6 +57,12 @@ #define UBUS_TIMEOUT 1000 +#define MAX_RADIO 20 +struct channel_response { + uint8_t radio_id[6]; + uint8_t response; +}; + #define for_each_tlv(e, _buf, _len) \ for ((e) = (struct tlv *)(_buf); \ (e)->len && (_buf) + (_len) - (uint8_t *)(e) - 3 - (e)->len >= 0; \ @@ -219,14 +225,49 @@ int send_channel_pref_report(void *agent, struct cmdu_cstruct *cmdu) return 0; } -int send_channel_sel_response(void *agent, struct cmdu_cstruct *cmdu) +int send_oper_channel_report(void *agent, struct cmdu_cstruct *rec_cmdu) { - return 0; -} + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + uint16_t tlv_index = 0; + uint32_t j; + struct cmdu_cstruct *cmdu_data; + int ret = 0; -int send_oper_channel_report(void *agent, struct cmdu_cstruct *cmdu) -{ - return 0; + cmdu_data = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); + + if (!cmdu_data) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } + + cmdu_data->message_type = CMDU_OPERATING_CHANNEL_REPORT; + memcpy(cmdu_data->origin, rec_cmdu->origin, 6); + cmdu_data->message_id = 10; + strcpy(cmdu_data->intf_name, rec_cmdu->intf_name); + + cmdu_data->num_tlvs = 1 * a->num_radios; /* (Operating Channel report) */ + cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, + sizeof(uint8_t *)); + if (!cmdu_data->tlvs) { + map_free_cmdu(cmdu_data); + return -1; + } + + /* Operating Channel Report TLV 17.2.17 */ + for (j = 0; j < a->num_radios; j++) { + struct tlv_oper_ch_report *p = + p = agent_gen_operate_channel_report(a, rec_cmdu, j); + if (!p) + continue; + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; + } + + ret = agent_send_cmdu(a, cmdu_data); + map_free_cmdu(cmdu_data); + + return ret; } int send_sta_caps_report(void *agent, struct cmdu_cstruct *cmdu) @@ -308,7 +349,7 @@ static const map_cmdu_sendfunc_t agent_maptxftable[] = { [0x00] = send_1905_ack, [0x02] = send_ap_caps_report, [0x05] = send_channel_pref_report, - [0x07] = send_channel_sel_response, + //[0x07] = send_channel_sel_response, [0x08] = send_oper_channel_report, [0x0a] = send_sta_caps_report, [0x0c] = send_ap_metrics_response, @@ -780,115 +821,6 @@ int handle_map_policy_config(void *agent, struct cmdu_cstruct *cmdu) return 0; } -static void get_radio_channel_preference(struct agent *a, - struct tlv_channel_pref *p, - uint32_t radio_index) -{ - uint32_t j; - struct wifi_radio_element *radio = a->radios + radio_index; - - trace("%s -----> parsing radio %s\n", __func__, radio->name); - - memcpy(p->radio_id, radio->macaddr, 6); - p->ch_preference_op_class_nr = radio->num_supp_opclass; - - if (p->ch_preference_op_class_nr > 0) - p->op_class = calloc(p->ch_preference_op_class_nr, - sizeof(*p->op_class)); - if (!p->op_class) { - fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); - p->ch_preference_op_class_nr = 0; - return; - } - - for (j = 0; j < p->ch_preference_op_class_nr; j++) { - p->op_class[j].op_class = radio->supp_opclass[j].id; - p->op_class[j].channel_nr = 0; - p->op_class[j].channel_list = NULL; - p->op_class[j].preference = 0xff; - p->op_class[j].preference_reason = 0x00; - } -} - -static void get_radio_restrict_channel(struct agent *a, - struct tlv_radio_oper_restrict *p, - uint32_t radio_index) -{ - uint32_t j, k, l, m; - struct wifi_radio_element *radio = a->radios + radio_index; - - trace("%s -----> parsing radio %s\n", __func__, radio->name); - - memcpy(p->radio_id, radio->macaddr, 6); - p->op_restricted_op_class_nr = 1; - - if (p->op_restricted_op_class_nr > 0) - p->restricted_op_class = calloc(p->op_restricted_op_class_nr, - sizeof(*p->restricted_op_class)); - if (!p->restricted_op_class) { - fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); - p->op_restricted_op_class_nr = 0; - return; - } - - for (j = 0, m = 0; j < radio->num_supp_opclass; j++) { - if (radio->supp_opclass[j].id != radio->current_opclass) - continue; - p->restricted_op_class[m].op_class = radio->current_opclass; - p->restricted_op_class[m].channel_nr = (radio->supp_opclass[j].num_supported_channels) - 1; - - if (p->restricted_op_class[m].channel_nr > 0) - p->restricted_op_class[m].restricted_channels = calloc(p->restricted_op_class[j].channel_nr, - sizeof(*p->restricted_op_class[m].restricted_channels)); - - if (!p->restricted_op_class[m].restricted_channels) { - fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); - p->restricted_op_class[m].channel_nr = 0; - return; - } - - for (k = 0, l = 0; k < radio->supp_opclass[j].num_supported_channels; k++) { - if (radio->supp_opclass[j].supp_chanlist[k] == radio->current_channel) - continue; - p->restricted_op_class[m].restricted_channels[l].channel = - radio->supp_opclass[j].supp_chanlist[k]; - p->restricted_op_class[m].restricted_channels[l].min_freq_sep = 0; //TODO dummy value - l++; - } - m++; - } -} - -static void get_cac_comp_report(struct agent *a, - struct tlv_cac_comp_report *p) -{ - uint32_t j; - struct wifi_radio_element *radio = NULL; - - trace("%s -----> Inside\n", __func__); - p->nbr_radios = a->num_radios; - - if (p->nbr_radios > 0) - p->radio_data = calloc(p->nbr_radios, - sizeof(*p->radio_data)); - if (!p->radio_data) { - fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); - p->nbr_radios = 0; - return; - } - - for (j = 0; j < a->num_radios; j++) { - radio = a->radios + j; - memcpy(p->radio_data[j].radio_id, radio->macaddr, 6); - - p->radio_data[j].op_class = 0x01; //dummy value TODO - p->radio_data[j].ch = 0x01; // dummy value TODO - - p->radio_data[j].completion_status = 0x05;// dummy value TODO - p->radio_data[j].nbr_pairs = 0; //dummy value TODO - } -} - int handle_channel_pref_query(void *agent, struct cmdu_cstruct *rec_cmdu) { trace("%s: --->\n", __func__); @@ -925,7 +857,7 @@ int handle_channel_pref_query(void *agent, struct cmdu_cstruct *rec_cmdu) sizeof(struct tlv_channel_pref)); if (p) { p->tlv_type = MAP_TLV_CHANNEL_PREFERENCE; - get_radio_channel_preference(a, p, j); + agent_gen_radio_channel_preference(a, p, j); cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; } } @@ -937,7 +869,7 @@ int handle_channel_pref_query(void *agent, struct cmdu_cstruct *rec_cmdu) sizeof(struct tlv_radio_oper_restrict)); if (p1) { p1->tlv_type = MAP_TLV_RADIO_OPERATION_RESTRICTION; - get_radio_restrict_channel(a, p1, j); + agent_gen_radio_restrict_channel(a, p1, j); cmdu_data->tlvs[tlv_index++] = (uint8_t *)p1; } } @@ -950,7 +882,7 @@ int handle_channel_pref_query(void *agent, struct cmdu_cstruct *rec_cmdu) sizeof(struct tlv_cac_comp_report)); if (p2) { p2->tlv_type = MAP_TLV_CAC_COMPLETION_REPORT; - get_cac_comp_report(a, p2); + agent_gen_cac_comp_report(a, p2); cmdu_data->tlvs[tlv_index++] = (uint8_t *)p2; } @@ -977,10 +909,233 @@ int handle_channel_pref_query(void *agent, struct cmdu_cstruct *rec_cmdu) int handle_channel_sel_request(void *agent, struct cmdu_cstruct *cmdu) { - trace("%s: --->\n", __func__); + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + int ret = 0; + struct channel_response channel_resp[MAX_RADIO]; + uint32_t channel_resp_nr = 0, match = 0, found = 0; + int i, j, k, l, m; + uint8_t *tlv = NULL; + struct wifi_radio_element *radio; + uint32_t pref_tlv_present = 0; + + //Here we first need to update the channel preference values + //from the channel selection request + //then send the CMDU for channel selection response + + if (cmdu->num_tlvs != 0) { + for (i = 0; i < cmdu->num_tlvs; i++) { + tlv = (uint8_t *) cmdu->tlvs[i]; + switch (*tlv) { + case MAP_TLV_CHANNEL_PREFERENCE: + { + struct tlv_channel_pref *p = + (struct tlv_channel_pref *)tlv; + pref_tlv_present = 1; + + ret = agent_process_channel_pref_tlv + (agent, p, channel_resp, + &channel_resp_nr); + } + case MAP_TLV_TRANSMIT_POWER_LIMIT: + { + struct tlv_tx_power_limit *p = + (struct tlv_tx_power_limit *)tlv; + + trace("tlv radio_id: " MACFMT "\n", + MAC2STR(p->radio_id)); + for (l = 0; l < a->num_radios; l++) { + radio = a->radios + l; + match = memcmp(radio->macaddr, p->radio_id, 6); + if (match == 0) { + //Here we set the + //transmit_power_limit of the radio + radio->transmit_power_limit = + p->tx_power_limit; + trace("transmit power %d\n", + p->tx_power_limit); + break; + } + } + } + default: + break; + } + } + } + + if (cmdu->num_tlvs == 0 || pref_tlv_present == 0) { + //Here the condition is that the + //channel selection request have no tlvs or only transmit power tlv + //so we need to set all the prefernce in all radios to max 15 + agent_fill_radio_max_preference(agent, + channel_resp, &channel_resp_nr); + } + + ret = send_channel_sel_response(agent, cmdu, + channel_resp, channel_resp_nr); + + return ret; +} + +int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, + struct channel_response *channel_resp, + uint32_t *channel_resp_nr) +{ + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + int ret = 0; + uint32_t match = 0, found = 0; + int i, j, k, l, m; + struct wifi_radio_element *radio; + uint32_t pref_tlv_present = 0; + + trace("\tradio_id: " MACFMT "\n", + MAC2STR(p->radio_id)); + for (l = 0; l < a->num_radios; l++) { + radio = a->radios + l; + match = memcmp(radio->macaddr, p->radio_id, 6); + if (match == 0) { + found = 1; + memcpy(channel_resp[*channel_resp_nr].radio_id, + radio->macaddr, 6); + channel_resp[*channel_resp_nr].response = 0x00; + break; + } + } + if (found == 0) { + memcpy(channel_resp[*channel_resp_nr].radio_id, + p->radio_id, 6); + //Here response code is a Reserved code + //to decline the request + channel_resp[*channel_resp_nr].response = 0x04; + *channel_resp_nr = *channel_resp_nr + 1; + return ret; + } + trace("ch_preference_op_class_nr: %d\n", + p->ch_preference_op_class_nr); + + for (j = 0; j < p->ch_preference_op_class_nr; j++) { + //Here we need to search the operating class in the radio + for (l = 0; l < radio->num_supp_opclass; l++) { + if (radio->supp_opclass[l].id == p->op_class[j].op_class) { + //Here we reset all the channels preferences in the + //operating class as 15 highest prefernce + trace("op_class : %d channel_nr %d\n", + p->op_class[j].op_class, + p->op_class[j].channel_nr); + + for (k = 0; k < + radio->supp_opclass[l].num_supported_channels; + k++) + radio->supp_opclass[l]. + supp_chanlist[k].pref = 0xff; + + for (k = 0; k < p->op_class[j].channel_nr; k++) { + for (m = 0; m < + radio->supp_opclass[l]. + num_supported_channels ; m++) { + trace("channel %d\n", + p->op_class[j].channel_list[k]); + if (p->op_class[j].channel_list[k] == + radio->supp_opclass[l]. + supp_chanlist[m].channel) { + radio->supp_opclass[l]. + supp_chanlist[m].pref = + p->op_class[j].preference; + + trace("channel pref is %d\n", + p->op_class[j].preference); + } + } + } + break; + } + } + } + *channel_resp_nr = *channel_resp_nr + 1; + return ret; +} + +int agent_fill_radio_max_preference(void *agent, + struct channel_response *channel_resp, + uint32_t *channel_response_nr) +{ + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + uint32_t j = 0, k = 0, l = 0; + struct wifi_radio_element *radio = NULL; + + *channel_response_nr = a->num_radios; + + for (j = 0; j < a->num_radios; j++) { + radio = a->radios + j; + memcpy(channel_resp[j].radio_id, radio->macaddr, 6); + + for (k = 0; k < radio->num_supp_opclass; k++) { + for (l = 0; l < radio->supp_opclass[k]. + num_supported_channels; l++) + radio->supp_opclass[k].supp_chanlist[l].pref = + 0xff; + } + channel_resp[j].response = 0x00; + } return 0; } +int send_channel_sel_response(void *agent, struct cmdu_cstruct *rec_cmdu, + struct channel_response *channel_resp, + uint32_t channel_response_nr) +{ + trace("agent: %s: --->\n", __func__); + struct agent *a = (struct agent *) agent; + uint16_t tlv_index = 0; + uint32_t j, ret = 0; + struct cmdu_cstruct *cmdu_data; + + cmdu_data = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); + + if (!cmdu_data) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } + + cmdu_data->message_type = CMDU_CHANNEL_SELECTION_RESPONSE; + memcpy(cmdu_data->origin, rec_cmdu->origin, 6); + cmdu_data->message_id = rec_cmdu->message_id; + strcpy(cmdu_data->intf_name, rec_cmdu->intf_name); + + cmdu_data->num_tlvs = 1 * channel_response_nr; /* (channel selection response) */ + cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, + sizeof(uint8_t *)); + + if (!cmdu_data->tlvs) { + map_free_cmdu(cmdu_data); + return -1; + } + + /* Operating Channel Response TLV 17.2.16 */ + for (j = 0; j < channel_response_nr; j++) { + struct tlv_ch_selection_resp *p = NULL; + //Here we need to check that the radio + //response is for the radio for which we get request + p = agent_gen_operate_channel_response(a, rec_cmdu, + channel_resp[j].radio_id, channel_resp[j].response); + if (!p) + continue; + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; + } + ret = agent_send_cmdu(a, cmdu_data); + map_free_cmdu(cmdu_data); + + //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, rec_cmdu); + return ret; +} + int handle_sta_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) { struct agent *a = (struct agent *) agent; diff --git a/src/core/agent_map.h b/src/core/agent_map.h index c9159b0ebb17b88fcd089cf70304b017a96b0119..af1033a8126c5b6623478119e5eeaac4e23f88b8 100644 --- a/src/core/agent_map.h +++ b/src/core/agent_map.h @@ -15,6 +15,13 @@ extern int agent_handle_map_event(struct agent *a, uint16_t cmdutype, int build_ap_autoconfig_wsc(void *agent, uint8_t *hwaddr, struct wifi_radio_element *radio, int idx); int agent_send_cmdu(struct agent *a, struct cmdu_cstruct *cmdu); +int send_channel_sel_response(void *agent, struct cmdu_cstruct *cmdu, + struct channel_response *rec_cmdu, uint32_t channel_response_nr); +int agent_fill_radio_max_preference(void *agent, + struct channel_response *channel_resp, uint32_t *channel_response_nr); +int agent_process_channel_pref_tlv(void *agent, struct tlv_channel_pref *p, + struct channel_response *channel_resp, + uint32_t *channel_response_nr); #endif /* AGENT_MAP_H */ diff --git a/src/core/agent_tlv_generator.c b/src/core/agent_tlv_generator.c index aec2636f6a5036d1f82f6feb6c693c71c492f143..5f8a77a08ebdf7da1827d2a7601e0f6697c8c0dc 100644 --- a/src/core/agent_tlv_generator.c +++ b/src/core/agent_tlv_generator.c @@ -310,7 +310,7 @@ struct tlv_ch_scan_cap *agent_gen_ch_scan_cap(struct agent *a) continue; for (k = 0; k < p->radio[i].op_class[j].nbr_ch; k++) - p->radio[i].op_class[j].ch[k] = opclass->supp_chanlist[k]; + p->radio[i].op_class[j].ch[k] = opclass->supp_chanlist[k].channel; } } @@ -387,7 +387,7 @@ struct tlv_cac_cap *agent_gen_cac_cap(struct agent *a) continue; p->radio_data[i].cac_data[j].op_class_data[k].ch = - calloc(opclass->num_supported_channels, sizeof(uint8_t)); + calloc(opclass->num_supported_channels, sizeof(struct supp_channel)); if (!p->radio_data[i].cac_data[j].op_class_data[k].ch) continue; @@ -395,7 +395,7 @@ struct tlv_cac_cap *agent_gen_cac_cap(struct agent *a) for (l = 0; l < opclass->num_supported_channels; l++) { uint8_t ch; - p->radio_data[i].cac_data[j].op_class_data[k].ch[l] = opclass->supp_chanlist[l]; + p->radio_data[i].cac_data[j].op_class_data[k].ch[l] = opclass->supp_chanlist[l].channel; ch = p->radio_data[i].cac_data[j].op_class_data[k].ch[l]; if (ch == 120 || ch == 124 || ch == 128) @@ -422,4 +422,211 @@ struct tlv_metric_collection_interval *agent_gen_metric_collection_interval(stru p->collection_interval = AP_COLLECTION_INTERVAL; return p; -} \ No newline at end of file +} + +struct tlv_oper_ch_report *agent_gen_operate_channel_report(struct agent *a, + struct cmdu_cstruct *cmdu, uint32_t radio_index) +{ + struct tlv_oper_ch_report *p; + struct wifi_radio_element *radio; + uint32_t j = 0; + + radio = a->radios + radio_index; + + p = (struct tlv_oper_ch_report *)calloc(1, + sizeof(struct tlv_oper_ch_report)); + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_OPERATING_CHANNEL_REPORT; + memcpy(p->radio_id, radio->macaddr, 6); + p->op_ch_op_class_nr = 1; + + if (p->op_ch_op_class_nr > 0) + p->op_ch_op_class = calloc(p->op_ch_op_class_nr, + sizeof(*p->op_ch_op_class)); + + if (!p->op_ch_op_class) { + fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + p->op_ch_op_class_nr = 0; + return; + } + + for (j = 0; j < p->op_ch_op_class_nr; j++) { + p->op_ch_op_class[j].op_class = radio->current_opclass; + p->op_ch_op_class[j].channel = radio->current_channel; + } + + //current transmit power is the (operating class tx power) * + // (current_tx_power_percent)/100 + for (j = 0; j < radio->num_supp_opclass; j++) { + if (radio->supp_opclass[j].id == radio->current_opclass) + p->curr_tx_power = + radio->supp_opclass[j].max_txpower * + ((radio->current_txpower_percent)/100); + } + return p; +} + +struct tlv_ch_selection_resp *agent_gen_operate_channel_response(struct agent *a, + struct cmdu_cstruct *cmdu, uint8_t *radio_recvd, uint8_t reason_code) +{ + struct tlv_ch_selection_resp *p; + + p = (struct tlv_ch_selection_resp *)calloc(1, + sizeof(struct tlv_ch_selection_resp)); + + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_CHANNEL_SELECTION_RESPONSE; + memcpy(p->radio_id, radio_recvd, 6); + p->response_code = reason_code; + + return p; +} + +void agent_gen_radio_channel_preference(struct agent *a, + struct tlv_channel_pref *p, + uint32_t radio_index) +{ + uint32_t j = 0, k = 0, count = 0, l = 0; + struct wifi_radio_element *radio = a->radios + radio_index; + + trace("%s -----> parsing radio %s\n", __func__, radio->name); + + memcpy(p->radio_id, radio->macaddr, 6); + p->ch_preference_op_class_nr = radio->num_supp_opclass; + + if (p->ch_preference_op_class_nr > 0) + p->op_class = calloc(p->ch_preference_op_class_nr, + sizeof(*p->op_class)); + if (!p->op_class) { + fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + p->ch_preference_op_class_nr = 0; + return; + } + + for (j = 0; j < p->ch_preference_op_class_nr; j++) { + + p->op_class[j].op_class = radio->supp_opclass[j].id; + count = 0; + + //Here we fill all the channels that are not having max preference 15 + for (k = 0; k < radio->supp_opclass[j].num_supported_channels; k++) { + if (radio->supp_opclass[j].supp_chanlist[k].pref != 0xff) + count++; + } + p->op_class[j].channel_nr = count; + + if (p->op_class[j].channel_nr > 0) { + p->op_class[j].channel_list = calloc(p->op_class[j].channel_nr, + sizeof(*p->op_class[j].channel_list)); + + if (!p->op_class[j].channel_list) { + fprintf(stderr, "|%s:%d| out of memory!\n", + __func__, __LINE__); + p->op_class[j].channel_nr = 0; + return; + } + l = 0; + + for (k = 0; k < radio->supp_opclass[j].num_supported_channels; k++) { + if (radio->supp_opclass[j].supp_chanlist[k].pref != 0xff) { + p->op_class[j].channel_list[l] = + radio->supp_opclass[j].supp_chanlist[k].channel; + p->op_class[j].preference = + radio->supp_opclass[j].supp_chanlist[k].pref; + l++; + } + } + + p->op_class[j].preference_reason = 0x00; + } else { + p->op_class[j].channel_list = NULL; + p->op_class[j].preference = 0xff; + p->op_class[j].preference_reason = 0x00; + } + } +} + +void agent_gen_radio_restrict_channel(struct agent *a, + struct tlv_radio_oper_restrict *p, + uint32_t radio_index) +{ + uint32_t j, k, l, m; + struct wifi_radio_element *radio = a->radios + radio_index; + + trace("%s -----> parsing radio %s\n", __func__, radio->name); + + memcpy(p->radio_id, radio->macaddr, 6); + p->op_restricted_op_class_nr = 1; + + if (p->op_restricted_op_class_nr > 0) + p->restricted_op_class = calloc(p->op_restricted_op_class_nr, + sizeof(*p->restricted_op_class)); + if (!p->restricted_op_class) { + fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + p->op_restricted_op_class_nr = 0; + return; + } + + for (j = 0, m = 0; j < radio->num_supp_opclass; j++) { + if (radio->supp_opclass[j].id != radio->current_opclass) + continue; + p->restricted_op_class[m].op_class = radio->current_opclass; + p->restricted_op_class[m].channel_nr = (radio->supp_opclass[j].num_supported_channels) - 1; + + if (p->restricted_op_class[m].channel_nr > 0) + p->restricted_op_class[m].restricted_channels = + calloc(p->restricted_op_class[j].channel_nr, + sizeof(*p->restricted_op_class[m].restricted_channels)); + + if (!p->restricted_op_class[m].restricted_channels) { + fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + p->restricted_op_class[m].channel_nr = 0; + return; + } + + for (k = 0, l = 0; k < radio->supp_opclass[j].num_supported_channels; k++) { + if (radio->supp_opclass[j].supp_chanlist[k].channel == radio->current_channel) + continue; + p->restricted_op_class[m].restricted_channels[l].channel = + radio->supp_opclass[j].supp_chanlist[k].channel; + p->restricted_op_class[m].restricted_channels[l].min_freq_sep = 0; //TODO dummy value + l++; + } + m++; + } +} + +void agent_gen_cac_comp_report(struct agent *a, + struct tlv_cac_comp_report *p) +{ + uint32_t j; + struct wifi_radio_element *radio = NULL; + + trace("%s -----> Inside\n", __func__); + p->nbr_radios = a->num_radios; + + if (p->nbr_radios > 0) + p->radio_data = calloc(p->nbr_radios, + sizeof(*p->radio_data)); + + if (!p->radio_data) { + fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + p->nbr_radios = 0; + return; + } + + for (j = 0; j < a->num_radios; j++) { + radio = a->radios + j; + memcpy(p->radio_data[j].radio_id, radio->macaddr, 6); + + p->radio_data[j].op_class = 0x01; //dummy value TODO + p->radio_data[j].ch = 0x01; // dummy value TODO + + p->radio_data[j].completion_status = 0x05;// dummy value TODO + p->radio_data[j].nbr_pairs = 0; //dummy value TODO + } +} diff --git a/src/core/agent_tlv_generator.h b/src/core/agent_tlv_generator.h index 0c289e2dd834c98af2bb67a7f4fd93247dda8eb7..d14c63a778f4770ee3669f2d7fe10775d5ccf86a 100644 --- a/src/core/agent_tlv_generator.h +++ b/src/core/agent_tlv_generator.h @@ -26,5 +26,16 @@ struct tlv_wsc *agent_gen_wsc(struct agent *a, struct cmdu_cstruct *cmdu, struct tlv_ch_scan_cap *agent_gen_ch_scan_cap(struct agent *a); struct tlv_cac_cap *agent_gen_cac_cap(struct agent *a); struct tlv_metric_collection_interval *agent_gen_metric_collection_interval(struct agent *a); - +struct tlv_oper_ch_report *agent_gen_operate_channel_report(struct agent *a, + struct cmdu_cstruct *cmdu, uint32_t radio_index); +struct tlv_ch_selection_resp *agent_gen_operate_channel_response(struct agent *a, + struct cmdu_cstruct *cmdu, uint8_t *radio_recvd, uint8_t reason_code); +void agent_gen_radio_channel_preference(struct agent *a, + struct tlv_channel_pref *p, + uint32_t radio_index); +void agent_gen_radio_restrict_channel(struct agent *a, + struct tlv_radio_oper_restrict *p, + uint32_t radio_index); +void agent_gen_cac_comp_report(struct agent *a, + struct tlv_cac_comp_report *p); #endif