diff --git a/src/core/agent.c b/src/core/agent.c index c55c1928a6b234c27673e7f2512e81a61e01cc06..db8d462294d30d86912952098c45f05de55e183f 100644 --- a/src/core/agent.c +++ b/src/core/agent.c @@ -2977,22 +2977,159 @@ static void parse_bk(struct ubus_request *req, int type, hwaddr_aton(bssid, bk->bssid); } +static void parse_esp_params(struct ubus_request *req, int type, + struct blob_attr *msg) +{ + struct wifi_bss_element *bss = (struct wifi_bss_element *)req->priv; + int rem; + struct blob_attr *cur; + struct blob_attr *data[1]; + static const struct blobmsg_policy beacon_attr[1] = { + [0] = { .name = "beacon-ies", .type = BLOBMSG_TYPE_ARRAY }, + }; + + blobmsg_parse(beacon_attr, 1, data, blob_data(msg), blob_len(msg)); + + if (!data[0]) + return; + + blobmsg_for_each_attr(cur, data[0], rem) { + char *iestr = strdup(blobmsg_get_string(cur)); + + if (!iestr) + return; + + /* + * esp string having this format: "ff xx 0b" + * where xx: 4 or 7 or 10 or 13 + */ + if (!strncmp(iestr, "ff", 2)) { + uint8_t *ie, *ie1; + int i, slen, esp_len; + int ac; /* Access Category */ + + slen = strlen(iestr); + ie = calloc(slen/2, sizeof(uint8_t)); + if (!ie) { + free(iestr); + return; + } + + strtob(iestr, slen, ie); + esp_len = ie[1]; + /* + * esp data payload start after 3 bytes; + * bypass 3 bytes, (1btye: ff, 1 byte: len, 1byte:0b) + */ + ie1 = ie + 3; + for (i = 1; i < esp_len; i += 3) { + ac = (*ie1) & 0x03; + switch (ac) { + case BK: + bss->is_ac_bk = 1; + memcpy(bss->est_wmm_bk, ie1, 3); + break; + case BE: + bss->is_ac_be = 1; + memcpy(bss->est_wmm_be, ie1, 3); + break; + case VI: + bss->is_ac_vi = 1; + memcpy(bss->est_wmm_vi, ie1, 3); + break; + case VO: + bss->is_ac_vo = 1; + memcpy(bss->est_wmm_vo, ie1, 3); + break; + } + ie1 += 3; + } + + free(ie); + free(iestr); + return; + } + + free(iestr); + } +} + +static void parse_ap_stats(struct ubus_request *req, int type, + struct blob_attr *msg) +{ + int bss_index; + struct wifi_radio_element *radio; + struct wifi_bss_element *bss; + struct netif_fh *fh = (struct netif_fh *)req->priv; + struct blob_attr *tb[6]; + static const struct blobmsg_policy ap_stats_attr[6] = { + [0] = { .name = "tx_unicast_packets", .type = BLOBMSG_TYPE_INT64}, + [1] = { .name = "rx_unicast_packets", .type = BLOBMSG_TYPE_INT64}, + [2] = { .name = "tx_multicast_packets", .type = BLOBMSG_TYPE_INT64}, + [3] = { .name = "rx_multicast_packets", .type = BLOBMSG_TYPE_INT64}, + [4] = { .name = "tx_broadcast_packets", .type = BLOBMSG_TYPE_INT64}, + [5] = { .name = "rx_broadcast_packets", .type = BLOBMSG_TYPE_INT64}, + }; + + + radio = wifi_ifname_to_radio_element(fh->agent, fh->name); + if (!radio) + return; + + radio->num_bss++; + radio->bsslist = (struct wifi_bss_element *)realloc(radio->bsslist, + radio->num_bss * sizeof(struct wifi_bss_element)); + if (!radio->bsslist) + return; + + bss_index = radio->num_bss - 1; + bss = radio->bsslist + bss_index; + memset(bss, 0, sizeof(struct wifi_bss_element)); + memcpy(bss->bssid, fh->bssid, 6); + strncpy(bss->ssid, fh->ssid, sizeof(bss->ssid) - 1); + + blobmsg_parse(ap_stats_attr, 6, tb, blob_data(msg), blob_len(msg)); + + if (tb[0]) + bss->tx_ucast_bytes = blobmsg_get_u64(tb[0]); + + if (tb[1]) + bss->rx_ucast_bytes = blobmsg_get_u64(tb[1]); + + if (tb[2]) + bss->tx_mcast_bytes = blobmsg_get_u64(tb[2]); + + if (tb[3]) + bss->rx_mcast_bytes = blobmsg_get_u64(tb[3]); + + if (tb[4]) + bss->tx_bcast_bytes = blobmsg_get_u64(tb[4]); + + if (tb[5]) + bss->rx_bcast_bytes = blobmsg_get_u64(tb[5]); + + /* Fill ESP params for bss */ + ubus_call_object(fh->agent, fh->wifi, "dump_beacon", + parse_esp_params, bss); +} + static void parse_ap(struct ubus_request *req, int type, struct blob_attr *msg) { struct netif_fh *fh = (struct netif_fh *)req->priv; char bssid[18] = { 0 }, ifname[16] = { 0 }; - struct blob_attr *tb[4]; - static const struct blobmsg_policy ap_attr[4] = { + struct blob_attr *tb[5]; + static const struct blobmsg_policy ap_attr[5] = { [0] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING }, [1] = { .name = "bssid", .type = BLOBMSG_TYPE_STRING }, [2] = { .name = "capabilities", .type = BLOBMSG_TYPE_TABLE }, [3] = { .name = "channel", .type = BLOBMSG_TYPE_INT8 }, + [4] = { .name = "ssid", .type = BLOBMSG_TYPE_STRING }, }; - blobmsg_parse(ap_attr, 4, tb, blob_data(msg), blob_len(msg)); + blobmsg_parse(ap_attr, 5, tb, blob_data(msg), blob_len(msg)); - if (!tb[0] || !tb[1] || !tb[2]) + if (!tb[0] || !tb[1] || !tb[2] || !tb[4]) return; strncpy(ifname, blobmsg_data(tb[0]), 15); @@ -3020,7 +3157,8 @@ static void parse_ap(struct ubus_request *req, int type, parse_dot11ac(fh, data[1]); } - + if (tb[4]) + strncpy(fh->ssid, blobmsg_data(tb[4]), sizeof(fh->ssid) - 1); } /* Initialize netif_fh/bk structs from ubus wifi objects */ @@ -3091,6 +3229,7 @@ static int agent_init_interfaces(struct agent *a) ubus_call_object(a, wobj, "status", parse_ap, fn); ubus_call_object(a, wobj, "subscribe_frame", NULL, NULL); + ubus_call_object(a, wobj, "stats", parse_ap_stats, fn); } }