diff --git a/src/core/cntlr_map_debug.c b/src/core/cntlr_map_debug.c index 919586fe9d1c2d034f7f035cd3e52ba3aed1f074..d0fe81513a4dae296d23ee0811f248207c5f61a3 100644 --- a/src/core/cntlr_map_debug.c +++ b/src/core/cntlr_map_debug.c @@ -437,7 +437,47 @@ int debug_sta_steer_complete(void *cntlr, struct cmdu_cstruct *cmdu) int debug_backhaul_sta_steer_response(void *cntlr, struct cmdu_cstruct *cmdu) { + int i; + uint8_t *tlv = NULL; + trace("%s: --->\n", __func__); + trace("parsing backhaul sta steer response of |%s:" MACFMT "|\n", + cmdu->intf_name, MAC2STR(cmdu->origin)); + + for (i = 0; i < cmdu->num_tlvs; i++) { + tlv = cmdu->tlvs[i]; + trace("CMDU type: %s\n", map_stringify_tlv_type(*tlv)); + switch (*tlv) { + case MAP_TLV_BACKHAUL_STEERING_RESPONSE: + { + struct tlv_backhaul_steer_resp *p = + (struct tlv_backhaul_steer_resp *)tlv; + + trace("\tbssid: " MACFMT "\n", + MAC2STR(p->bssid)); + trace("\taddr: " MACFMT "\n", + MAC2STR(p->addr)); + + trace("\tres_code: 0x%02x\n", p->res_code); + + break; + } + case MAP_TLV_ERROR_CODE: + { + struct tlv_error_code *p = + (struct tlv_error_code *)tlv; + + trace("\treason_code: 0x%02x\n", p->reason_code); + break; + } + default: + fprintf(stdout, "unknown TLV in CMDU:|%s|", + map_stringify_cmdu_type(cmdu->message_type)); + break; + } + trace("\n"); + } + return 0; } diff --git a/src/core/cntlr_ubus.c b/src/core/cntlr_ubus.c index 1bcffc90823922a3cd49ba8dd1e3707bc8c5dc85..cd4110b5ab334243a8551089c5bbec661c5b9e47 100644 --- a/src/core/cntlr_ubus.c +++ b/src/core/cntlr_ubus.c @@ -92,6 +92,22 @@ static const struct blobmsg_policy reconfig_policy_params[__RECFG_POLICY_MAX] = [RECFG_POLICY_AGENT] = { .name = "agent", .type = BLOBMSG_TYPE_STRING }, }; +enum { + BK_STEER_POLICY_AGENT, + BK_STEER_POLICY_BSSID, + BK_STEER_POLICY_CHANNEL, + BK_STEER_POLICY_OP_CLASS, + BK_STEER_POLICY_STA_MAC, + __BK_STEER_POLICY_MAX, +}; + +static const struct blobmsg_policy bk_steer_policy_params[__BK_STEER_POLICY_MAX] = { + [BK_STEER_POLICY_AGENT] = { .name = "agent", .type = BLOBMSG_TYPE_STRING }, + [BK_STEER_POLICY_BSSID] = { .name = "bssid", .type = BLOBMSG_TYPE_STRING }, + [BK_STEER_POLICY_CHANNEL] = { .name = "channel", .type = BLOBMSG_TYPE_INT32 }, + [BK_STEER_POLICY_OP_CLASS] = { .name = "op_class", .type = BLOBMSG_TYPE_INT32 }, + [BK_STEER_POLICY_STA_MAC] = { .name = "bksta", .type = BLOBMSG_TYPE_STRING }, +}; void send_cmdu_cb(struct ubus_request *req, int type, struct blob_attr *msg) @@ -668,16 +684,98 @@ fail_cmdu: return UBUS_STATUS_UNKNOWN_ERROR; } +static int cntlr_bk_steer(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__BK_STEER_POLICY_MAX]; + struct tlv_backhaul_steer_req *p; + struct controller *c = container_of(obj, struct controller, obj); + char agent[18] = {0}, bssid[18] = {0}, bkhaul[18] = {0}; + struct cmdu_cstruct *cmdu; + + blobmsg_parse(bk_steer_policy_params, __BK_STEER_POLICY_MAX, tb, + blob_data(msg), blob_len(msg)); + + if (!tb[BK_STEER_POLICY_BSSID] || !tb[BK_STEER_POLICY_CHANNEL] || + !tb[BK_STEER_POLICY_OP_CLASS] || + !tb[BK_STEER_POLICY_STA_MAC]) { + fprintf(stderr, "BSSID, channel and op class required!\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + strncpy(bssid, blobmsg_data(tb[BK_STEER_POLICY_BSSID]), + sizeof(bssid) - 1); + strncpy(bkhaul, blobmsg_data(tb[BK_STEER_POLICY_STA_MAC]), + sizeof(bkhaul) - 1); + + cmdu = (struct cmdu_cstruct *)calloc(1, + sizeof(struct cmdu_cstruct)); + if (!cmdu) { + fprintf(stderr, "failed to malloc cmdu\n"); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + if (tb[AP_POLICY_AGENT]) { + strncpy(agent, blobmsg_data(tb[AP_POLICY_AGENT]), + sizeof(agent) - 1); + if (!hwaddr_aton(agent, cmdu->origin)) + goto fail_cmdu; + } + + cmdu->message_type = CMDU_BACKHAUL_STEER_REQUEST; + + p = calloc(1, sizeof(struct tlv_client_info)); + if (!p) { + fprintf(stderr, "failed to malloc cmdu\n"); + goto fail_cmdu; + } + + cmdu->num_tlvs++; + + if (!hwaddr_aton(bssid, p->bssid)) { + fprintf(stderr, "BSSID must be in format 11:22:33...\n"); + goto fail_p; + } + + if (!hwaddr_aton(bkhaul, p->addr)) { + fprintf(stderr, "Backhaul must be in format 11:22:33...\n"); + goto fail_p; + } + + p->channel = blobmsg_get_u8(tb[BK_STEER_POLICY_CHANNEL]); + p->op_class = blobmsg_get_u8(tb[BK_STEER_POLICY_OP_CLASS]); + p->tlv_type = MAP_TLV_BACKHAUL_STEERING_REQUEST; + + cmdu->tlvs = (uint8_t **)calloc(cmdu->num_tlvs, + sizeof(uint8_t *)); + + if (cmdu->tlvs) + cmdu->tlvs[0] = (uint8_t *)p; + + send_cmdu(c, cmdu); + map_free_cmdu(cmdu); + + return 0; +fail_p: + map_free_tlv_cstruct((uint8_t *) p); +fail_cmdu: + free(cmdu); + return UBUS_STATUS_UNKNOWN_ERROR; +} + 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[4] = { + struct ubus_method m[5] = { 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), - UBUS_METHOD("channels", cntlr_channel_pref, channel_pref_policy_params) + UBUS_METHOD("channels", cntlr_channel_pref, + channel_pref_policy_params), + UBUS_METHOD("bk_steer", cntlr_bk_steer, bk_steer_policy_params) /* UBUS_METHOD("teardown_ap", cntlr_teardown_ap, config_policy_params),