diff --git a/src/core/agent.c b/src/core/agent.c index 0cd3ec4fb4722f0500f5bd0765b86807a9b2e9e4..bf771b526de12016a5a66d7f75f32e21434b34f6 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -2383,8 +2383,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[8]; - static const struct blobmsg_policy radio_attr[8] = { + struct blob_attr *tb[9]; + static const struct blobmsg_policy radio_attr[9] = { [0] = { .name = "isup", .type = BLOBMSG_TYPE_BOOL }, [1] = { .name = "band", .type = BLOBMSG_TYPE_STRING }, [2] = { .name = "noise", .type = BLOBMSG_TYPE_INT32 }, @@ -2393,9 +2393,10 @@ static void parse_radio(struct ubus_request *req, int type, [5] = { .name = "supp_channels", .type = BLOBMSG_TYPE_ARRAY }, [6] = { .name = "opclass", .type = BLOBMSG_TYPE_INT32 }, [7] = { .name = "channel", .type = BLOBMSG_TYPE_INT32 }, + [8] = { .name = "regdomain", .type = BLOBMSG_TYPE_STRING }, }; - blobmsg_parse(radio_attr, 8, tb, blob_data(msg), blob_len(msg)); + blobmsg_parse(radio_attr, 9, tb, blob_data(msg), blob_len(msg)); if (tb[0]) re->enabled = blobmsg_get_bool(tb[0]); @@ -2485,6 +2486,9 @@ static void parse_radio(struct ubus_request *req, int type, if (tb[7]) re->current_channel = (uint8_t) blobmsg_get_u32(tb[7]); + + if (tb[8]) + memcpy(re->country_code, blobmsg_data(tb[8]), 2); } static void _enumerate_wifi_objects(struct ubus_request *req, int type, diff --git a/src/core/agent.h b/src/core/agent.h index 3f03cf13b487e87cfd4aab017a04cc5a5885c8f1..25831d27adaf11027af151dec443fbbb2f194a89 100644 --- a/src/core/agent.h +++ b/src/core/agent.h @@ -328,6 +328,7 @@ struct wifi_unassoc_sta_element { struct wifi_radio_element { char name[16]; uint8_t macaddr[6]; + uint8_t country_code[2]; enum wifi_band band; bool enabled; int anpi; @@ -339,7 +340,6 @@ struct wifi_radio_element { uint8_t tx_streams; uint8_t current_opclass; uint8_t current_channel; - uint8_t max_bss; uint32_t num_supp_opclass; diff --git a/src/core/agent_map.c b/src/core/agent_map.c index 9c798e0f0f1405200365982ee9fae09a82c05e1c..6a134c1f015938c3aade44be9bb224a2ee1550ab 100644 --- a/src/core/agent_map.c +++ b/src/core/agent_map.c @@ -133,7 +133,7 @@ int build_ap_autoconfig_wsc(void *agent, struct cmdu_cstruct *rec_cmdu, goto fail_cmdu; cmdu->num_tlvs++; - p1 = agent_gen_profile2_ap_cap(a, cmdu); + p1 = agent_gen_profile2_ap_cap(a); if (!p1) goto fail_p; cmdu->num_tlvs++; @@ -608,6 +608,10 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) uint32_t j; struct cmdu_cstruct *cmdu; struct tlv_ap_cap *p2; + struct tlv_ch_scan_cap *p5; + struct tlv_cac_cap *p6; + struct tlv_profile2_ap_cap *p7; + struct tlv_metric_collection_interval *p8; int ret; cmdu = (struct cmdu_cstruct *)calloc(1, @@ -622,9 +626,12 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) cmdu->message_id = rec_cmdu->message_id; cmdu->num_tlvs = 3 * a->num_radios + 1; /* (Radio basic, HT, VHT capability per radio) */ - cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, - sizeof(uint8_t *)); +//#ifdef PROFILE2 + cmdu->num_tlvs += 1 + 1 + 1 + 1; /* Channel scan, CAC, profile-2 AP capabilities and metric collection interval TLV */ +//#endif PROFILE2 + + cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, sizeof(uint8_t *)); if (!cmdu->tlvs) { map_free_cmdu(cmdu); return -1; @@ -641,23 +648,13 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) cmdu->tlvs[tlv_index++] = (uint8_t *)p; } - /* Collection Interval TLV*/ -/* struct tlv_metric_collection_interval *p1 = - * (struct tlv_metric_collection_interval *)calloc(1, - * sizeof(struct tlv_metric_collection_interval)); - * if (p1) { - * p1->tlv_type = MAP_TLV_METRIC_COLLECTION_INTERVAL; - * get_collection_interval(a, p1); - * cmdu->tlvs[tlv_index++] = (uint8_t *)p1; - * } - */ /* AP capability TLV */ p2 = agent_gen_ap_caps(a, cmdu); if (!p2) - return -1; + goto fail; + cmdu->tlvs[tlv_index++] = (uint8_t *)p2; - //cmdu->num_tlvs++; /* HT Capability */ for (j = 0; j < a->num_radios; j++) { @@ -672,23 +669,54 @@ int handle_ap_caps_query(void *agent, struct cmdu_cstruct *rec_cmdu) cmdu->tlvs[tlv_index++] = (uint8_t *)p3; } - /*VHT Capability */ + /* VHT Capability */ for (j = 0; j < a->num_radios; j++) { struct tlv_ap_vht_cap *p4; p4 = agent_gen_ap_vht_caps(a, cmdu, j); if (!p4) continue; - //cmdu->num_tlvs++; - cmdu->tlvs[tlv_index++] = (uint8_t *)p4; } +//#ifdef PROFILE2 + /* Channel Scan Capability */ + p5 = agent_gen_ch_scan_cap(a); + if (!p5) + goto fail; + + cmdu->tlvs[tlv_index++] = (uint8_t *)p5; + + /* CAC Capability */ + p6 = agent_gen_cac_cap(a); + if (!p6) + goto fail; + + cmdu->tlvs[tlv_index++] = (uint8_t *)p6; + + /* Profile Capability */ + p7 = agent_gen_profile2_ap_cap(a); + if (!p7) + goto fail; + + cmdu->tlvs[tlv_index++] = (uint8_t *)p7; + + /* Metric Collection Interval */ + p8 = agent_gen_metric_collection_interval(a); + if (!p8) + goto fail; + + cmdu->tlvs[tlv_index++] = (uint8_t *)p8; +//#endif PROFILE2 + ret = agent_send_cmdu(a, cmdu); map_free_cmdu(cmdu); return ret; +fail: + map_free_cmdu(cmdu); + return -1; } int handle_map_policy_config(void *agent, struct cmdu_cstruct *cmdu) diff --git a/src/core/agent_tlv_generator.c b/src/core/agent_tlv_generator.c index f85a1bca3d4a1712373db52841de35553314cf92..aec2636f6a5036d1f82f6feb6c693c71c492f143 100644 --- a/src/core/agent_tlv_generator.c +++ b/src/core/agent_tlv_generator.c @@ -45,6 +45,8 @@ //#include "platform_interfaces.h" #include "agent_tlv_generator.h" +#define AP_COLLECTION_INTERVAL (10 * 1000) + struct tlv_ap_ht_cap *agent_gen_ap_ht_caps(struct agent *a, struct cmdu_cstruct *cmdu, uint32_t radio_index) { @@ -173,8 +175,7 @@ struct tlv_ap_vht_cap *agent_gen_ap_vht_caps(struct agent *a, return p; } -struct tlv_profile2_ap_cap *agent_gen_profile2_ap_cap(struct agent *a, - struct cmdu_cstruct *cmdu) +struct tlv_profile2_ap_cap *agent_gen_profile2_ap_cap(struct agent *a) { struct tlv_profile2_ap_cap *p; @@ -251,4 +252,174 @@ fail_key: fail_p: map_free_tlv_cstruct((uint8_t *) p); return NULL; +} + +struct tlv_ch_scan_cap *agent_gen_ch_scan_cap(struct agent *a) +{ + struct tlv_ch_scan_cap *p; + int i; + + if (a->num_radios <= 0) + return NULL; + + p = (struct tlv_ch_scan_cap *) calloc(1, sizeof(*p)); + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_CHANNEL_SCAN_CAPABILITY; + p->nbr_radios = a->num_radios; + + p->radio = calloc(p->nbr_radios, sizeof(*p->radio)); + if (!p->radio) + goto fail_p; + + for (i = 0; i < p->nbr_radios; i++) { + struct wifi_radio_element *radio; + struct wifi_opclass_supported_element *opclass; + int j; + + radio = a->radios + i; + + memcpy(p->radio[i].radio_id, radio->macaddr, 6); + p->radio[i].on_boot = 0; // TODO: Dummy values + p->radio[i].scan_impact = 0x01; // TODO: Dummy values + p->radio[i].min_scan_interval = 300; // TODO: Dummy values + p->radio[i].nbr_op_classes = radio->num_supp_opclass; + + if (p->radio[i].nbr_op_classes <= 0) + continue; + + p->radio[i].op_class = calloc(p->radio[i].nbr_op_classes, + sizeof(*p->radio[i].op_class)); + if (!p->radio[i].op_class) + continue; + + for (j = 0; j < p->radio[i].nbr_op_classes; j++) { + int k; + + opclass = radio->supp_opclass + j; + p->radio[i].op_class[j].op_class = opclass->id; + p->radio[i].op_class[j].nbr_ch = opclass->num_supported_channels; // Scan on all channels + + if (p->radio[i].op_class[j].nbr_ch <= 0) + continue; + + p->radio[i].op_class[j].ch = calloc(p->radio[i].op_class[j].nbr_ch, + sizeof(*p->radio[i].op_class[j].ch)); + if (!p->radio[i].op_class[j].ch) + 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]; + } + } + + return p; +fail_p: + map_free_tlv_cstruct((uint8_t *) p); + return NULL; +} + +struct tlv_cac_cap *agent_gen_cac_cap(struct agent *a) +{ + struct tlv_cac_cap *p; + struct wifi_radio_element *radio = NULL; + struct wifi_opclass_supported_element *opclass = NULL; + int i; + + p = (struct tlv_cac_cap *) calloc(1, sizeof(*p)); + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_CAC_CAPABILITY; + memcpy(p->country_code, a->radios[0].country_code, 2); + p->nbr_radios = a->num_radios; + + p->radio_data = calloc(p->nbr_radios, sizeof(*p->radio_data)); + if (!p->radio_data) + goto fail_p; + + for (i = 0; i < p->nbr_radios; i++) { + struct wifi_radio_element *radio; + struct wifi_opclass_supported_element *opclass; + int j; + + radio = a->radios + i; + + memcpy(p->radio_data[i].radio_id, radio->macaddr, 6); + p->radio_data[i].nbr_cac_types = 1; + + if (p->radio_data[i].nbr_cac_types <= 0) + continue; + + p->radio_data[i].cac_data = calloc(p->radio_data[i].nbr_cac_types, + sizeof(*p->radio_data[i].cac_data)); + if (!p->radio_data[i].cac_data) + continue; + + for (j = 0; j < p->radio_data[i].nbr_cac_types; j++) { + int k; + + p->radio_data[i].cac_data[j].cac_method_supported = CAC_CAP_METHOD_CONTI_CAC; + p->radio_data[i].cac_data[j].duration = 60; //Default duration is 60, 600 for channels (120, 124 & 128) + // TODO: Assumption, All the supporting op_class supported continuous CAC method, + // Currently no parmaeter/method to classify the same. + p->radio_data[i].cac_data[j].nbr_op_classes = radio->num_supp_opclass; + + if (p->radio_data[i].cac_data[j].nbr_op_classes <= 0) + continue; + + p->radio_data[i].cac_data[j].op_class_data = + calloc(radio->num_supp_opclass, + sizeof(*p->radio_data[i].cac_data[j].op_class_data)); + + if (!p->radio_data[i].cac_data[j].op_class_data) + continue; + + for (k = 0; k < radio->num_supp_opclass; k++) { + int l; + + opclass = radio->supp_opclass + k; + p->radio_data[i].cac_data[j].op_class_data[k].op_class = opclass->id; + p->radio_data[i].cac_data[j].op_class_data[k].nbr_ch = opclass->num_supported_channels; + + if (opclass->num_supported_channels <= 0) + continue; + + p->radio_data[i].cac_data[j].op_class_data[k].ch = + calloc(opclass->num_supported_channels, sizeof(uint8_t)); + + if (!p->radio_data[i].cac_data[j].op_class_data[k].ch) + continue; + + 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]; + + ch = p->radio_data[i].cac_data[j].op_class_data[k].ch[l]; + if (ch == 120 || ch == 124 || ch == 128) + p->radio_data[i].cac_data[j].duration = 600; + } + } + } + } + return p; +fail_p: + map_free_tlv_cstruct((uint8_t *) p); + return NULL; +} + +struct tlv_metric_collection_interval *agent_gen_metric_collection_interval(struct agent *a) +{ + struct tlv_metric_collection_interval *p; + + p = (struct tlv_metric_collection_interval *) calloc(1, sizeof(*p)); + if (!p) + return NULL; + + p->tlv_type = MAP_TLV_METRIC_COLLECTION_INTERVAL; + p->collection_interval = AP_COLLECTION_INTERVAL; + + return p; } \ No newline at end of file diff --git a/src/core/agent_tlv_generator.h b/src/core/agent_tlv_generator.h index 5c400bfdbc9fc003c4daac32db13e3713ea16a50..0c289e2dd834c98af2bb67a7f4fd93247dda8eb7 100644 --- a/src/core/agent_tlv_generator.h +++ b/src/core/agent_tlv_generator.h @@ -18,10 +18,13 @@ struct tlv_ap_radio_basic_cap *agent_gen_ap_radio_basic_cap(struct agent *a, struct cmdu_cstruct *cmdu, uint32_t radio_index); struct tlv_ap_vht_cap *agent_gen_ap_vht_caps(struct agent *a, struct cmdu_cstruct *cmdu, uint32_t radio_index); -struct tlv_profile2_ap_cap *agent_gen_profile2_ap_cap(struct agent *a, - struct cmdu_cstruct *cmdu); +struct tlv_profile2_ap_cap *agent_gen_profile2_ap_cap(struct agent *a); struct tlv_ap_radio_adv_cap *agent_gen_ap_radio_adv_cap(struct agent *a, struct cmdu_cstruct *cmdu, struct wifi_radio_element *radio); struct tlv_wsc *agent_gen_wsc(struct agent *a, struct cmdu_cstruct *cmdu, struct wifi_radio_element *radio); +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); + #endif