diff --git a/src/core/cntlr_map.c b/src/core/cntlr_map.c index cf3b410dbbe14a76dfb630774e7af266f0dde852..153ac51f6f7c3945533d4f381193fde4d836f4d6 100644 --- a/src/core/cntlr_map.c +++ b/src/core/cntlr_map.c @@ -27,6 +27,7 @@ #include <libubox/utils.h> #include <libubus.h> +#include <easy/easy.h> #include "map_module.h" #include "utils.h" @@ -88,8 +89,88 @@ int handle_1905_ack(void *cntlr, struct cmdu_cstruct *cmdu) return 0; } + +static bool ap_caps_info_from_tlv(struct controller *c, + struct cmdu_cstruct *cmdu_data) +{ + int i, j, k; + int radio_index, bss_index; + uint8_t *tlv = NULL; + + for (i = 0; i < cmdu_data->num_tlvs; i++) { + tlv = cmdu_data->tlvs[i]; + trace("CMDU type: %s\n", map_stringify_tlv_type(*tlv)); + switch (*tlv) { + case MAP_TLV_AP_CAPABILITY: + { + struct tlv_ap_cap *p = (struct tlv_ap_cap *)tlv; + + trace("\top_ch_metric_reporting: %d\n", p->op_ch_metric_reporting); + trace("\tnon_op_ch_metric_reporting: %d\n", p->non_op_ch_metric_reporting); + trace("\tagent_init_rcpi_steering: %d\n", p->agent_init_rcpi_steering); + break; + } + case MAP_TLV_AP_RADIO_BASIC_CAPABILITIES: + { + struct tlv_ap_radio_basic_cap *p = (struct tlv_ap_radio_basic_cap *)tlv; + + trace("\tradio_id: " MACFMT "\n", MAC2STR(p->radio_id)); + trace("\tmax_bss_nr: %d\n", p->max_bss_nr); + trace("\toperating_classes_nr: %d\n", p->operating_classes_nr); + for (j = 0; j < p->operating_classes_nr; j++) { + trace("\t\top_class: %d\n", p->operating_class[j].op_class); + trace("\t\tmax_tx_power: %d\n", p->operating_class[j].max_tx_power); + trace("\t\tnon_op_ch_nr: %d\n", p->operating_class[j].non_op_ch_nr); + + for (k = 0; k < p->operating_class[j].non_op_ch_nr; k++) + trace("\t\t\tchannel: %d\n", p->operating_class[j].channel[k]); + } + break; + } + case MAP_TLV_AP_HT_CAPABILITIES: + { + struct tlv_ap_ht_cap *p = (struct tlv_ap_ht_cap *)tlv; + + trace("\tradio_id: " MACFMT "\n", MAC2STR(p->radio_id)); + trace("\tmax_tx_streams_supported: %02x\n", p->max_tx_streams_supported); + trace("\tmax_rx_streams_supported: %02x\n", p->max_rx_streams_supported); + trace("\tgi_20_support: %s\n", (p->gi_20_support ? "true" : "false")); + trace("\tgi_40_support: %s\n", (p->gi_40_support ? "true" : "false")); + trace("\tht_40_support: %s\n", (p->ht_40_support ? "true" : "false")); + break; + } + case MAP_TLV_AP_VHT_CAPABILITIES: + { + struct tlv_ap_vht_cap *p = (struct tlv_ap_vht_cap *)tlv; + + trace("\tradio_id: " MACFMT "\n", MAC2STR(p->radio_id)); + trace("\tvht_tx_mcs_supported: %04x\n", p->vht_tx_mcs_supported); + trace("\tvht_rx_mcs_supported: %04x\n", p->vht_rx_mcs_supported); + trace("\tmax_tx_streams_supported: %02x\n", p->max_tx_streams_supported); + trace("\tmax_rx_streams_supported: %02x\n", p->max_rx_streams_supported); + trace("\tgi_80_support: %s\n", (p->gi_80_support ? "true" : "false")); + trace("\tgi_160_support: %s\n", (p->gi_160_support ? "true" : "false")); + trace("\tvht160_support: %s\n", (p->vht_160_support ? "true" : "false")); + trace("\tsu_beamformer_capable: %s\n", (p->su_beamformer_capable ? "true" : "false")); + trace("\tmu_beamformer_capable: %s\n", (p->mu_beamformer_capable ? "true" : "false")); + break; + } + default: + fprintf(stdout, "unknown TLV in CMDU:|%s|", map_stringify_cmdu_type(cmdu_data->message_type)); + break; + } + trace("\n"); + } + + return 0; +} + int handle_ap_caps_report(void *cntlr, struct cmdu_cstruct *cmdu) { + trace("%s: --->\n", __func__); + trace("parsing AP capabilities of |%s:" MACFMT "|\n", cmdu->intf_name, MAC2STR(cmdu->origin)); + + ap_caps_info_from_tlv(cntlr, cmdu); return 0; } @@ -115,6 +196,7 @@ int handle_oper_channel_report(void *cntlr, struct cmdu_cstruct *cmdu) int handle_sta_caps_report(void *cntlr, struct cmdu_cstruct *cmdu) { + trace("received sta caps report!\n"); return 0; } diff --git a/src/core/cntlr_ubus.c b/src/core/cntlr_ubus.c index 29ac9064e4a853456cd386eb8d91d05edca119b2..176119cd447af0d73ef8700a8652489c795add59 100644 --- a/src/core/cntlr_ubus.c +++ b/src/core/cntlr_ubus.c @@ -31,6 +31,150 @@ #include "map_module.h" +#include <map1905/map2.h> +#include <map1905/maputils.h> + +enum { + AP_POLICY_AGENT, + //AP_POLICY_BSSID, + __AP_POLICY_MAX, +}; + +static const struct blobmsg_policy ap_caps_policy_params[__AP_POLICY_MAX] = { + [AP_POLICY_AGENT] = { .name = "agent", .type = BLOBMSG_TYPE_STRING }, // agent = ieee1905 AL macaddress of an agent, agent = "ff:ff:ff:ff:ff:ff" means all agents + //[AP_POLICY_BSSID] = { .name = "bssid", .type = BLOBMSG_TYPE_STRING } +}; + + +static void send_cmdu_cb(struct ubus_request *req, + int type, struct blob_attr *msg) +{ + struct json_object *jobj = NULL; + struct json_object *tmp; + uint16_t *mid; + char *str; + + if (!msg || !req->priv) { + fprintf(stderr, "%s:Message recieved is NULL\n", __func__); + return; + } + + mid = (uint16_t *)req->priv; + + str = (char *)blobmsg_format_json_indent(msg, true, -1); + if (str) { + jobj = json_tokener_parse(str); + free(str); + } + + if (jobj == NULL) + return; + + if (json_object_object_get_ex(jobj, "mid", &tmp)) { + *mid = json_object_get_int(tmp); + fprintf(stdout, "%s:%d map-mid:%d\n", __func__, __LINE__, *mid); + } + + json_object_put(jobj); +} + +static int send_cmdu(struct controller *c, + struct cmdu_cstruct *cmdu_data) +{ + char *tlv_data = NULL; + uint16_t tlv_data_len = 1; + uint16_t tlv_str_len = 0; + int copy_index; + struct blob_buf b = { 0 }; + char dst_addr[18] = { 0 }; + char tlv_str[512] = { 0 }; + uint8_t is_store_mid = 1; + uint8_t *ss = NULL; + uint16_t msgid = 0; + uint16_t len; + int ret = 0; + size_t i; + uint32_t id; + struct ieee1905_cmdu_msg *cmsg = NULL; + + fprintf(stdout, "|%s:%d| Entry \n", __func__, __LINE__); + + memset(&b, 0, sizeof(struct blob_buf)); + blob_buf_init(&b, 0); + + blobmsg_add_u32(&b, "type", cmdu_data->message_type); + blobmsg_add_string(&b, "egress", cmdu_data->intf_name); + + blobmsg_add_u32(&b, "mid", cmdu_data->message_id); + + hwaddr_ntoa(cmdu_data->origin, dst_addr); + blobmsg_add_string(&b, "dst_macaddr", dst_addr); + + fprintf(stdout, "|%s:%d|cmdu:%s|dst:%s|\n", __func__, __LINE__, + map_stringify_cmdu_type(cmdu_data->message_type), dst_addr); + + if (cmdu_data->num_tlvs > 0) { + for (i = 0; i < cmdu_data->num_tlvs; i++) { + len = 0; + ss = map_put_tlv_cstruct(cmdu_data->tlvs[i], &len); + if (ss) { + btostr(ss, len, tlv_str); + tlv_str_len = 2 * len; + tlv_data_len += tlv_str_len; + tlv_data = realloc(tlv_data, tlv_data_len * sizeof(char)); + if (!tlv_data) { + fprintf(stderr, "%s:%d out of memory.!\n", __func__, __LINE__); + free(ss); + goto out; + } + + copy_index = tlv_data_len - tlv_str_len - 1; + memcpy(tlv_data + copy_index, tlv_str, tlv_str_len); + memset(tlv_str, 0, sizeof(tlv_str)); + free(ss); + } + } + + tlv_data[tlv_data_len - 1] = '\0'; + blobmsg_add_string(&b, "data", tlv_data); + if (tlv_data) + free(tlv_data); + } + + + if (ubus_lookup_id(c->ubus_ctx, "map.1905", &id)) { + fprintf(stderr, "[%s:%d] not present", __func__, __LINE__); + goto out; + } + + ret = ubus_invoke(c->ubus_ctx, id, "send", + b.head, send_cmdu_cb, + (void *)&msgid, + 1000); + if (ret) { + fprintf(stderr, "[%s:%d] ubus call failed for |map.1905 send|", + __func__, __LINE__); + goto out; + } + + //TODO: improve ///////////////////////// +// if (is_store_mid) { +// cmsg = &priv->cmsg; +// for (i = 0; i < MAX_CMDU_MSG; i++) { +// if (cmsg->msg_id[i] == -1) { +// cmsg->msg_id[i] = msgid; +// cmsg->msg_ts[i] = time(NULL); +// break; +// } +// } +// } + ///////////////////////////////////////// + +out: + blob_buf_free(&b); + + return ret; +} static int cntlr_status(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, @@ -118,13 +262,80 @@ static int cntlr_status(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } +static int cntlr_req_cap(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct cmdu_cstruct *cmdu_data; + uint32_t total_bss = 0; + uint32_t k = 0; + uint32_t i, j; + + cmdu_data = (struct cmdu_cstruct *)calloc(1, sizeof(struct cmdu_cstruct)); + if (!cmdu_data) { + fprintf(stderr, "failed to malloc cmdu\n"); + return -1; + } + + cmdu_data->message_type = CMDU_CLIENT_CAPABILITY_QUERY; + cmdu_data->message_id = 1; + + fprintf(stderr, "map.1905 egress interface:|%s|\n", cmdu_data->intf_name); + + send_cmdu(NULL, cmdu_data); + + return 0; +} + +static int cntlr_ap_caps(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__AP_POLICY_MAX]; + struct controller *c = container_of(obj, struct controller, obj); + char mac[18] = {0}; + struct cmdu_cstruct *cmdu_data; + uint32_t total_bss = 0; + uint32_t k = 0; + uint32_t i, j; + + 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(ap_caps_policy_params, __AP_POLICY_MAX, tb, blob_data(msg), blob_len(msg)); + + + if (tb[AP_POLICY_AGENT]) { + strncpy(mac, blobmsg_data(tb[AP_POLICY_AGENT]), sizeof(mac) - 1); + printf("mac = %s\n", mac); + if (!hwaddr_aton(mac, cmdu_data->origin)) + return UBUS_STATUS_UNKNOWN_ERROR; + } + + // TODO: ff:ff:ff:ff:ff:ff = send to all agents + + cmdu_data->message_type = CMDU_AP_CAPABILITY_QUERY; + cmdu_data->message_id = 1; + + cmdu_data->num_tlvs = 0; + + send_cmdu(c, cmdu_data); + + return 0; +} + 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[2] = { + struct ubus_method m[3] = { UBUS_METHOD_NOARG("status", cntlr_status), + UBUS_METHOD_NOARG("req_cap", cntlr_req_cap), + UBUS_METHOD("ap_caps", cntlr_ap_caps, ap_caps_policy_params), }; int num_methods = ARRAY_SIZE(m); int ret;