diff --git a/src/core/cntlr_cmdu_generator.c b/src/core/cntlr_cmdu_generator.c index da8aa6747e2bc28809635737484759dcf2c1f1f8..da0562564fc56af2d836da87411231bdb27e8618 100644 --- a/src/core/cntlr_cmdu_generator.c +++ b/src/core/cntlr_cmdu_generator.c @@ -534,3 +534,25 @@ fail_cmdu: free(cmdu); return NULL; } + +struct cmdu_cstruct *cntlr_gen_topology_query(struct controller *c, + uint8_t *origin, char *intf_name) +{ + struct cmdu_cstruct *cmdu; + + cmdu = calloc(1, sizeof(struct cmdu_cstruct)); + if (!cmdu) { + fprintf(stderr, "failed to malloc cmdu\n"); + return NULL; + } + + cmdu_defaults(c, cmdu, origin, intf_name, CMDU_TYPE_TOPOLOGY_QUERY); + + cmdu->num_tlvs = 0; + + return cmdu; + +fail_cmdu: + map_free_cmdu(cmdu); + return NULL; +} diff --git a/src/core/cntlr_map_debug.c b/src/core/cntlr_map_debug.c index 847d061fc2eb2efba64ed9b2719f44bd6bfe8410..fad2834d5f40d39e76e3a24de8a0c80f048263ab 100644 --- a/src/core/cntlr_map_debug.c +++ b/src/core/cntlr_map_debug.c @@ -40,7 +40,173 @@ int debug_topology_notification(void *cntlr, struct cmdu_cstruct *cmdu) int debug_topology_response(void *cntlr, struct cmdu_cstruct *cmdu) { + uint8_t *tlv; + int i, j, k; + trace("%s: --->\n", __func__); + trace("parsing topology response |" MACFMT "|CMDU: %s\n", + MAC2STR(cmdu->origin), + map_stringify_cmdu_type(cmdu->message_type)); + + for (i = 0; i < cmdu->num_tlvs; i++) { + tlv = (uint8_t *)cmdu->tlvs[i]; + trace("TLV: %s\n", map_stringify_tlv_type(*tlv)); + switch (*tlv) { + case TLV_TYPE_DEVICE_INFORMATION_TYPE: + { + struct tlv_device_info *p = + (struct tlv_device_info *)tlv; + + trace("\tal_mac_address: " MACFMT "\n", + MAC2STR(p->al_mac_address)); + trace("\tlocal_interfaces_nr: %d\n", + p->local_interfaces_nr); + for (j = 0; j < p->local_interfaces_nr; j++) { + trace("\t\tmac_address: " MACFMT "\n", + MAC2STR(p->local_interfaces[j].mac_address)); + trace("\t\tmedia_type: 0x%04hx\n", + p->local_interfaces[j].media_type); + trace("\t\tmedia_specific_data_size: %d\n", + p->local_interfaces[j].media_specific_data_size); + if ((p->local_interfaces[j].media_type & 0xff00) == 0x0100) { + /* IEEE 802.11 devices */ + trace("\t\tnetwork_membership: " MACFMT "\n", + MAC2STR(p->local_interfaces[j].media_specific_data.ieee80211.network_membership)); + trace("\t\trole: "); + print_bits(p->local_interfaces[j].media_specific_data.ieee80211.role, + 4, 4); + trace("\t\tap_channel_band: 0x%02hx\n", + p->local_interfaces[j].media_specific_data.ieee80211.ap_channel_band); + trace("\t\tap_ch_freq_1: 0x%02hx\n", + p->local_interfaces[j].media_specific_data.ieee80211.ap_ch_freq_1); + trace("\t\tap_ch_freq_2: 0x%02hx\n", + p->local_interfaces[j].media_specific_data.ieee80211.ap_ch_freq_2); + } + } + break; + } + case TLV_TYPE_DEVICE_BRIDGING_CAPABILITIES: + { + struct tlv_device_bridge_cap *p = + (struct tlv_device_bridge_cap *)tlv; + + trace("\tbridging_tuples_nr: %d\n", + p->bridging_tuples_nr); + for (j = 0; j < p->bridging_tuples_nr; j++) { + trace("\t\tbridging_tuple_macs_nr: %d\n", + p->bridging_tuples[j].bridging_tuple_macs_nr); + for (k = 0; k < p->bridging_tuples[j].bridging_tuple_macs_nr; k++) { + trace("\t\t\tmac_address: " MACFMT "\n", + MAC2STR(p->bridging_tuples[j].bridging_tuple_macs[k].mac_address)); + } + } + break; + } + case TLV_TYPE_NON_1905_NEIGHBOR_DEVICE_LIST: + { + struct tlv_non1905_neighbor *p = + (struct tlv_non1905_neighbor *)tlv; + + trace("\tlocal_mac_address: " MACFMT "\n", + MAC2STR(p->local_mac_address)); + trace("\tnon_1905_neighbors_nr: %d\n", + p->non_1905_neighbors_nr); + for (j = 0; j < p->non_1905_neighbors_nr; j++) { + trace("\t\tmac_address: " MACFMT "\n", + MAC2STR(p->non_1905_neighbors[j].mac_address)); + } + break; + } + case TLV_TYPE_NEIGHBOR_DEVICE_LIST: + { + struct tlv_neighbor_device *p = + (struct tlv_neighbor_device *)tlv; + + trace("\tlocal_mac_address: " MACFMT "\n", + MAC2STR(p->local_mac_address)); + trace("\tneighbors_nr: %d\n", + p->neighbors_nr); + for (j = 0; j < p->neighbors_nr; j++) { + trace("\t\tmac_address: " MACFMT "\n", + MAC2STR(p->neighbors[j].mac_address)); + trace("\t\tbridge_flag: %s\n", + (p->neighbors[j].bridge_flag ? "true" : "false")); + } + break; + } + case MAP_TLV_SUPPORTED_SERVICE: + { + struct tlv_supp_service *p = + (struct tlv_supp_service *)tlv; + + trace("\tsupported_services_list: %d\n", + p->supported_services_list); + for (j = 0; j < p->supported_services_list; j++) { + trace("\t\tservice: %s\n", + (p->supported_services[j].service ? + "Multi-AP Agent" : "Multi-AP Controller")); + } + break; + } + case MAP_TLV_AP_OPERATIONAL_BSS: + { + struct tlv_ap_oper_bss *p = + (struct tlv_ap_oper_bss *)tlv; + + trace("\tradios_nr: %d\n", p->radios_nr); + for (j = 0; j < p->radios_nr; j++) { + trace("\t\tradio_id: " MACFMT "\n", + MAC2STR(p->radio[j].radio_id)); + trace("\t\tbss_nr: %d\n", + p->radio[j].bss_nr); + for (k = 0; k < p->radio[j].bss_nr; k++) { + trace("\t\t\tbssid: " MACFMT "\n", + MAC2STR(p->radio[j].bss[k].bssid)); + trace("\t\t\tssid_len: %d\n", + p->radio[j].bss[k].ssid_len); + trace("\t\t\tssid: %.*s\n", + p->radio[j].bss[k].ssid_len, + p->radio[j].bss[k].ssid); + } + } + break; + } + case MAP_TLV_ASSOCIATED_CLIENTS: + { + struct tlv_assoc_client *p = + (struct tlv_assoc_client *)tlv; + + trace("\tbss_nr: %d\n", p->bss_nr); + for (j = 0; j < p->bss_nr; j++) { + trace("\t\tbssid: " MACFMT "\n", + MAC2STR(p->bss[j].bssid)); + trace("\t\tassoc_clients_nr: %d\n", + p->bss[j].assoc_clients_nr); + for (k = 0; k < p->bss[j].assoc_clients_nr; k++) { + trace("\t\t\tclient_addr: " MACFMT "\n", + MAC2STR(p->bss[j].clients[k].client_addr)); + trace("\t\t\tuptime: 0x%04x\n", + p->bss[j].clients[k].uptime); + } + } + break; + } + case MAP_TLV_MULTIAP_PROFILE: + { + struct tlv_map_profile *p = + (struct tlv_map_profile *)tlv; + + trace("\tprofile: 0x%02hx\n", p->profile); + break; + } + default: + { + trace("unknown TLV\n"); + break; + } + } + trace("\n"); + } return 0; } diff --git a/src/core/cntlr_ubus.c b/src/core/cntlr_ubus.c index 01e5f8d69a4be6985baf68fca1eadd8ba29b55a3..c79d9e54fe59c54e714ef5121e268f1cadedce15 100644 --- a/src/core/cntlr_ubus.c +++ b/src/core/cntlr_ubus.c @@ -37,6 +37,7 @@ #include "cntlr_tlv_generator.h" #include "cntlr_cmdu_generator.h" +#define MULTICAST_ADDR_STR "01:80:c2:00:00:13" enum { AP_POLICY_AGENT, @@ -245,6 +246,15 @@ static const struct blobmsg_policy bk_caps_policy_params[__BK_CAPS_POLICY_MAX] = [BK_CAPS_POLICY_AGENT] = { .name = "agent", .type = BLOBMSG_TYPE_STRING }, }; +enum { + TOPOLOGY_QUERY_AGENT, + __TOPOLOGY_QUERY_MAX, +}; + +static const struct blobmsg_policy topology_query_params[__TOPOLOGY_QUERY_MAX] = { + [TOPOLOGY_QUERY_AGENT] = { .name = "agent", .type = BLOBMSG_TYPE_STRING }, +}; + void send_cmdu_cb(struct ubus_request *req, int type, struct blob_attr *msg) { @@ -1744,6 +1754,39 @@ static int cntlr_bk_caps(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } +static int cntlr_topology_query(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + trace("%s:--->\n", __func__); + struct blob_attr *tb[__TOPOLOGY_QUERY_MAX]; + struct controller *c = container_of(obj, struct controller, obj); + char agent[18] = { 0 }; + uint8_t agent_mac[6] = { 0 }; + struct cmdu_cstruct *cmdu_data; + + blobmsg_parse(topology_query_params, __TOPOLOGY_QUERY_MAX, tb, + blob_data(msg), blob_len(msg)); + + if (tb[TOPOLOGY_QUERY_AGENT]) { + strncpy(agent, blobmsg_data(tb[TOPOLOGY_QUERY_AGENT]), + sizeof(agent) - 1); + } else { + strncpy(agent, MULTICAST_ADDR_STR, sizeof(agent) - 1); + } + if (!hwaddr_aton(agent, agent_mac)) + return UBUS_STATUS_UNKNOWN_ERROR; + + cmdu_data = cntlr_gen_topology_query(c, agent_mac, NULL); + if (!cmdu_data) + return UBUS_STATUS_UNKNOWN_ERROR; + + send_cmdu(c, cmdu_data); + map_free_cmdu(cmdu_data); + + return UBUS_STATUS_OK; +} + void cntlr_notify_event(struct controller *c, void *ev_type, void *ev_data) { struct blob_buf b; @@ -1762,7 +1805,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[14] = { + struct ubus_method m[15] = { UBUS_METHOD_NOARG("status", cntlr_status), UBUS_METHOD("ap_caps", cntlr_ap_caps, ap_caps_policy_params), @@ -1788,6 +1831,8 @@ int cntlr_publish_object(struct controller *c, const char *objname) sta_metric_query_params), UBUS_METHOD("bk_caps", cntlr_bk_caps, bk_caps_policy_params), + UBUS_METHOD("topology_query", cntlr_topology_query, + topology_query_params), /* UBUS_METHOD("teardown_ap", cntlr_teardown_ap, config_policy_params),