From be751fda0762c68bb8b64e7ab8d33b432dca7068 Mon Sep 17 00:00:00 2001 From: "nevadita.chatterjee" <nevadita.chatterjee@iopsys.eu> Date: Thu, 7 Jan 2021 17:46:35 +0530 Subject: [PATCH] map-controller: Added Steering STA code --- src/core/cntlr_map_debug.c | 37 +++++ src/core/cntlr_ubus.c | 306 ++++++++++++++++++++++++++++++++++++- 2 files changed, 341 insertions(+), 2 deletions(-) diff --git a/src/core/cntlr_map_debug.c b/src/core/cntlr_map_debug.c index f4fc3a9d..d047abc1 100644 --- a/src/core/cntlr_map_debug.c +++ b/src/core/cntlr_map_debug.c @@ -587,12 +587,49 @@ int debug_beacon_metrics_response(void *cntlr, struct cmdu_cstruct *cmdu) int debug_sta_steer_btm_report(void *cntlr, struct cmdu_cstruct *cmdu) { trace("%s: --->\n", __func__); + trace("parsing steer btm report of |%s:" MACFMT "|\n", + cmdu->intf_name, + MAC2STR(cmdu->origin)); + + int i, j; + uint8_t *tlv = NULL; + + for (i = 0; i < cmdu->num_tlvs; i++) { + tlv = (uint8_t *) cmdu->tlvs[i]; + trace("CMDU type: %s\n", map_stringify_tlv_type(*tlv)); + switch (*tlv) { + case MAP_TLV_STEERING_BTM_REPORT: + { + struct tlv_steer_btm_report *p = + (struct tlv_steer_btm_report *)tlv; + + trace("\tbssid: " MACFMT "\n", + MAC2STR(p->bssid)); + trace("\tsta_macaddr: " MACFMT "\n", + MAC2STR(p->sta_mac_addr)); + trace("\tstatus_code: %d\n", + p->status_code); + if (p->status_code == 0x00) + trace("\ttarget_bbsid: " MACFMT "\n", + MAC2STR(p->target_bssid)); + break; + } + default: + fprintf(stdout, "unknown TLV in CMDU:|%s|", + map_stringify_cmdu_type(cmdu->message_type)); + break; + } + trace("\n"); + } return 0; } int debug_sta_steer_complete(void *cntlr, struct cmdu_cstruct *cmdu) { trace("%s: --->\n", __func__); + trace("parsing sta steer complete of |%s:" MACFMT "|\n", + cmdu->intf_name, + MAC2STR(cmdu->origin)); return 0; } diff --git a/src/core/cntlr_ubus.c b/src/core/cntlr_ubus.c index ed10aaa9..709c3d44 100644 --- a/src/core/cntlr_ubus.c +++ b/src/core/cntlr_ubus.c @@ -142,6 +142,35 @@ static const struct blobmsg_policy ap_policy_config_params[__AP_POLICY_CONFIG_MA [AP_POLICY_CONFIG_BSS] = { .name = "bsslist", .type = BLOBMSG_TYPE_ARRAY }, }; +enum { + STEERING_POLICY_AGENT, + STEERING_POLICY_FROM_BSSID, + STEERING_POLICY_STA, + STEERING_POLICY_TARGET_BSSID, + STEERING_POLICY_STEER_TIMEOUT, + STEERING_POLICY_BTM_TIMEOUT, + STEERING_POLICY_REQUEST_MODE, +#if profile2 + STEERING_POLICY_TARGET_BSSID_MULTIBAND, + STEERING_POLICY_STA_MULTIBAND, +#endif + __STEERING_POLICY_MAX, +}; + +static const struct blobmsg_policy client_steering_policy_params[__STEERING_POLICY_MAX] = { + [STEERING_POLICY_AGENT] = { .name = "agent", .type = BLOBMSG_TYPE_STRING }, + [STEERING_POLICY_FROM_BSSID] = { .name = "from_bssid", .type = BLOBMSG_TYPE_STRING }, + [STEERING_POLICY_STA] = { .name = "sta", .type = BLOBMSG_TYPE_ARRAY}, + [STEERING_POLICY_TARGET_BSSID] = { .name = "target_bssid", .type = BLOBMSG_TYPE_ARRAY }, + [STEERING_POLICY_STEER_TIMEOUT] = { .name = "steer_timeout", .type = BLOBMSG_TYPE_INT32 }, + [STEERING_POLICY_BTM_TIMEOUT] = { .name = "btm_timeout", .type = BLOBMSG_TYPE_INT32 }, + [STEERING_POLICY_REQUEST_MODE] = { .name = "steer_req_mode", .type = BLOBMSG_TYPE_BOOL }, +#if profile2 + [STEERING_POLICY_TARGET_BSSID_MULTIBAND] = { .name = "target_bssid_multiband", .type = BLOBMSG_TYPE_ARRAY }, + [STEERING_POLICY_STA_MULTIBAND] = { .name = "sta_multiband", .type = BLOBMSG_TYPE_ARRAY }, +#endif +}; + void send_cmdu_cb(struct ubus_request *req, int type, struct blob_attr *msg) { @@ -576,6 +605,278 @@ fail_cmdu: return UBUS_STATUS_UNKNOWN_ERROR; } +static int cntlr_client_steering(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__STEERING_POLICY_MAX]; + struct controller *c = container_of(obj, struct controller, obj); + char agent[18] = {0}; + char bss_id[18] = {0}; + char sta_id[30][18] = {0}; + char sta_multi_id[30][18] = {0}; + char target_bbsid[30][18] = {0}; + char target_bbsid_multi[30][18] = {0}; + char to_id[18] = {0}; + struct cmdu_cstruct *cmdu_data; + uint32_t timeout = 0; + struct tlv_steer_Req *p; + struct tlv_profile2_steer_req *p1; + uint32_t sta_nr = 0, bssid_nr = 0, sta_multi_nr = 0, bssid_multi_nr = 0; + uint32_t request_mode = 0, request_mode_present = -1, tlv_index = 0; + uint32_t sta_present = -1, sta_multi_present = -1, bssid_present = -1; + uint32_t target_bssid_present = -1, target_bssid_multi_present = -1; + struct blob_attr *cur; + int rem, l = 0, j = 0, count = 0; + uint32_t steer_timeout = 0, btm_timeout = 0; + + cmdu_data = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); + if (!cmdu_data) { + fprintf(stderr, "failed to malloc cmdu\n"); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + blobmsg_parse(client_steering_policy_params, __STEERING_POLICY_MAX, tb, + blob_data(msg), blob_len(msg)); + + if (tb[STEERING_POLICY_AGENT]) { + strncpy(agent, blobmsg_data(tb[STEERING_POLICY_AGENT]), + sizeof(agent) - 1); + if (!hwaddr_aton(agent, cmdu_data->origin)) + return UBUS_STATUS_UNKNOWN_ERROR; + } + + // TODO: ff:ff:ff:ff:ff:ff = send to all agents + + if (tb[STEERING_POLICY_FROM_BSSID]) { + strncpy(bss_id, blobmsg_data(tb[STEERING_POLICY_FROM_BSSID]), + sizeof(bss_id) - 1); + bssid_present = 1; + } + + if (tb[STEERING_POLICY_STA]) { + sta_present = 1; + sta_nr = blobmsg_check_array(tb[STEERING_POLICY_STA], + BLOBMSG_TYPE_STRING); + l = 0; + blobmsg_for_each_attr(cur, tb[STEERING_POLICY_STA], rem) + strncpy(sta_id[l++], blobmsg_get_string(cur), 18); + } + + if (tb[STEERING_POLICY_TARGET_BSSID]) { + target_bssid_present = 1; + bssid_nr = blobmsg_check_array(tb[STEERING_POLICY_TARGET_BSSID], + BLOBMSG_TYPE_STRING); + l = 0; + blobmsg_for_each_attr(cur, tb[STEERING_POLICY_TARGET_BSSID], rem) + strncpy(target_bbsid[l++], blobmsg_get_string(cur), 18); + } + + if (tb[STEERING_POLICY_STEER_TIMEOUT]) + steer_timeout = (int) blobmsg_get_u32(tb[STEERING_POLICY_STEER_TIMEOUT]); + + if (tb[STEERING_POLICY_REQUEST_MODE]) { + request_mode = blobmsg_get_bool(tb[STEERING_POLICY_REQUEST_MODE]); + request_mode_present = 1; + } + + if (tb[STEERING_POLICY_BTM_TIMEOUT]) + btm_timeout = (int) blobmsg_get_u32(tb[STEERING_POLICY_BTM_TIMEOUT]); +#if profile2 + + if (tb[STEERING_POLICY_TARGET_BSSID_MULTIBAND]) { + target_bssid_multi_present = 1; + bssid_multi_nr = blobmsg_check_array(tb[STEERING_POLICY_TARGET_BSSID_MULTIBAND], + BLOBMSG_TYPE_INT32); + l = 0; + blobmsg_for_each_attr(cur, tb[STEERING_POLICY_TARGET_BSSID_MULTIBAND], rem) + strncpy(target_bbsid_multi[l++], blobmsg_get_string(cur), 18); + } + + if (tb[STEERING_POLICY_STA_MULTIBAND]) { + sta_multi_present = 1; + sta_multi_nr = blobmsg_check_array(tb[STEERING_POLICY_STA_MULTIBAND], + BLOBMSG_TYPE_INT32); + l = 0; + blobmsg_for_each_attr(cur, tb[STEERING_POLICY_STA_MULTIBAND], rem) + strncpy(sta__multi_id[l++], blobmsg_get_string(cur), 18); + } + +#endif + + cmdu_data->message_type = CMDU_CLIENT_STEERING_REQUEST; + + if (bssid_present == 1 && request_mode_present == 1) { + fprintf(stderr, "The values are requestmode %d timeout %d sta_cnt %d, bssid_nr %d\n", request_mode, timeout, sta_nr, bssid_nr); + + p = calloc(1, sizeof(struct tlv_steer_Req)); + if (!p) { + fprintf(stderr, "failed to malloc cmdu\n"); + goto fail_cmdu; + } + + p->tlv_type = MAP_TLV_STEERING_REQUEST; + + hwaddr_aton(bss_id, p->bssid); + + //Here we need to know if the this is for + //STA mandate or a STA opportunity + + if (request_mode == 1) { + p->request_mode = 0x01; + p->steer_opp_window = 0x00; + } + else { + p->request_mode = 0x00; + p->steer_opp_window = steer_timeout; + p->target_bssid_list_cnt = 0x00; //pg 82 If Request Mode bit is 0, then this field is set to zero + p->steering_req_target_bssids = NULL; + } + + //Here we need to fill the BTM bits + p->btm_disassoc_imminent = 0x00; //TODO default value + p->btm_abridged = 0x00; //TODO default value + p->reserved = 0x00; + p->btm_disassoc_timer = 0x00; //TODO default value + p->sta_list_cnt = (uint8_t) sta_nr; + + if (p->sta_list_cnt > 0) { + p->steering_req_macs = calloc(p->sta_list_cnt, + sizeof(*p->steering_req_macs)); + if (!p->steering_req_macs) { + fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + p->sta_list_cnt = 0; + goto fail_p; + } + } + + for (j = 0; j < p->sta_list_cnt; j++) { + hwaddr_aton(sta_id[j] ,p->steering_req_macs[j].addr); + } + + p->target_bssid_list_cnt = (uint8_t) bssid_nr; + + if (p->target_bssid_list_cnt > 0) { + p->steering_req_target_bssids = calloc(p->target_bssid_list_cnt, + sizeof(*p->steering_req_target_bssids)); + + if (!p->steering_req_target_bssids) { + fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + p->target_bssid_list_cnt = 0; + goto fail_p; + } + } + + for (j = 0; j < p->target_bssid_list_cnt; j++) { + hwaddr_aton(target_bbsid[j],p->steering_req_target_bssids[j].bssid); + p->steering_req_target_bssids[j].op_class = 0x00; //TODO filled as a default value now + p->steering_req_target_bssids[j].channel = 0x00; //TODO filled as a default value now + + } + count++; + } + +#if profile2 + //Here we need to add tlv for 17.2.57 + if (bssid_present == 1 && request_mode_present !- -1 && + (target_bssid_multi_present != -1 || sta_multi_present != -1)) { + + p1 = calloc(1, sizeof(struct tlv_profile2_steer_req)); + if (!p1) { + fprintf(stderr, "failed to malloc cmdu\n"); + goto fail_cmdu; + } + + p1->tlv_type = MAP_TLV_PROFILE2_STEERING_REQ; + + hwaddr_aton(bss_id, p1->bssid); + + //Here we need to know if the this is for + //STA mandate or a STA opportunity + + if (request_mode == 1) { + p1->req_mode = 0x01; + p1->steering_opt_win = 0x00; + } + else { + p1->req_mode = 0x00; + p1->steering_opt_win = timeout; + p1->target_bssid_count = 0x00; + p1->target_data = NULL; + } + + //Here we need to fill the BTM bits + p1->btm_imminent_bit = 0x00; //TODO default value + p1->btm_abridged_bit = 0x00; //TODO default value + p1->btm_dis_timer = 0x00; //TODO default value + p1->sta_list_count = (uint8_t) sta_multi_nr; + + if (p1->sta_list_count > 0) + p1->sta_mac = calloc(p1->sta_list_count, + sizeof(*p1->sta_mac)); + if (!p1->sta_mac) { + fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + p1->sta_list_count = 0; + goto fail_p; + } + + for (j = 0; j < p1->sta_list_count; j++) { + hwaddr_aton(sta_multi_id[j] ,p1->sta_mac[j].mac); + } + + //Here we also need the bssid mapped to the STAs + if (p1->target_bssid_count > 0) + p1->target_data = calloc(p1->target_bssid_count, + sizeof(*p1->target_data)); + + if (!p1->target_data) { + fprintf(stderr, "|%s:%d| out of memory!\n", __func__, __LINE__); + p1->target_bssid_count = 0; + goto fail_p; + } + + for (j = 0; j < p1->target_bssid_count; j++) { + hwaddr_aton(target_bbsid_multi[j],p1->target_data[j].bssid); + p1->target_data[j].bss_op_class = 0x00; //TODO filled as a default value now + p1->target_data[j].bss_ch = 0x00; //TODO filled as a default value now + + } + count++; + } +#endif + + cmdu_data->num_tlvs = count; +#ifndef profile2 + //Here we need to check that in profile 1 atleast 1 tlv + //should be there to send the CMDU + if (cmdu_data->num_tlvs == 0) { + fprintf(stderr, "|%s:%d| No TLvs\n", __func__, __LINE__); + return UBUS_STATUS_UNKNOWN_ERROR; + } +#endif + + cmdu_data->tlvs = (uint8_t **)calloc(cmdu_data->num_tlvs, + sizeof(uint8_t *)); + if (cmdu_data->tlvs && p != NULL) + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p; + if (cmdu_data->tlvs && p1 != NULL) + cmdu_data->tlvs[tlv_index++] = (uint8_t *)p1; + send_cmdu(c, cmdu_data); + map_free_cmdu(cmdu_data); + return 0; +fail_p: + if(p != NULL) + map_free_tlv_cstruct((uint8_t *) p); + if(p1 !=NULL) + map_free_tlv_cstruct((uint8_t *) p1); +fail_cmdu: + map_free_cmdu(cmdu_data); + return UBUS_STATUS_UNKNOWN_ERROR; +} + + + static int cntlr_sta_caps(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) @@ -1147,7 +1448,7 @@ int cntlr_publish_object(struct controller *c, const char *objname) struct ubus_object *obj; struct ubus_object_type *obj_type; struct ubus_method *obj_methods; - struct ubus_method m[7] = { + struct ubus_method m[8] = { UBUS_METHOD_NOARG("status", cntlr_status), UBUS_METHOD("ap_caps", cntlr_ap_caps, ap_caps_policy_params), UBUS_METHOD("sta_caps", cntlr_sta_caps, sta_caps_policy_params), @@ -1155,7 +1456,8 @@ int cntlr_publish_object(struct controller *c, const char *objname) channel_pref_policy_params), UBUS_METHOD("bk_steer", cntlr_bk_steer, bk_steer_policy_params), UBUS_METHOD("agent_policy", cntlr_ap_policy_config, ap_policy_config_params), - UBUS_METHOD("channel", cntlr_channel_select, channel_select_policy_params) + UBUS_METHOD("channel", cntlr_channel_select, channel_select_policy_params), + UBUS_METHOD("client_steering", cntlr_client_steering, client_steering_policy_params) /* UBUS_METHOD("teardown_ap", cntlr_teardown_ap, config_policy_params), -- GitLab