From 1c54af852b33e0d27509ac444941ba8712e3a617 Mon Sep 17 00:00:00 2001
From: Jakob Olsson <jakob.olsson@iopsys.eu>
Date: Wed, 7 Oct 2020 18:25:41 +0200
Subject: [PATCH] add ap capability handling and request
---
src/core/cntlr_map.c | 82 ++++++++++++++++
src/core/cntlr_ubus.c | 213 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 294 insertions(+), 1 deletion(-)
diff --git a/src/core/cntlr_map.c b/src/core/cntlr_map.c
index cf3b410d..153ac51f 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 29ac9064..176119cd 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;
--
GitLab