diff --git a/src/cmdu.c b/src/cmdu.c
index 99d21418a44c45bdd40f663bfc0c42deacd5d3d4..f26026eb1fbdbaa140082d1f0d6b547af41ec364 100644
--- a/src/cmdu.c
+++ b/src/cmdu.c
@@ -3016,7 +3016,6 @@ static int fill_client_capability_from_tlv(struct decollector_private *priv,
struct wifi_sta_element *sta = NULL;
struct wifi_assoc_event *event = NULL;
struct tlv *tlvs[CLIENT_CAPABILITY_REPORT_NUM_OF_TLV_TYPES][TLV_MAXNUM] = {0};
- bool event_present = false;
if (!map_cmdu_validate_parse(resp, tlvs, ARRAY_SIZE(tlvs), dev->map_profile)) {
dbg("%s: map_cmdu_validate_parse failed, err = (%d) '%s'\n",
@@ -3030,19 +3029,8 @@ static int fill_client_capability_from_tlv(struct decollector_private *priv,
struct tlv_client_info *cl_info =
(struct tlv_client_info *)tlvs[CLIENT_CAPABILITY_REPORT_CLIENT_INFO_IDX][0]->data;
- /* check the sta & bssid in the assoc event list */
- /* TODO: why update assoc eventlist? if we have to, then should
- * be from the tail ,) and only for entry missing the capability
- * information.
- */
- list_for_each_entry(event, &dev->ev.assoclist, list) {
- if (hwaddr_equal(event->macaddr, cl_info->macaddr) &&
- hwaddr_equal(event->bssid, cl_info->bssid)) {
- event_present = true;
- break;
- }
- }
-
+ /* check if the sta's last assoc-event is pending for this message */
+ event = find_assoc_event(&dev->ev.assoclist, cl_info->macaddr, cl_info->bssid);
sta = find_sta_in_bss(dev, cl_info->macaddr, cl_info->bssid);
}
@@ -3055,17 +3043,19 @@ static int fill_client_capability_from_tlv(struct decollector_private *priv,
size_t frame_len = BUF_GET_BE16(t->len) - 1;
if (report->result == SUCCESS) {
- if (event_present)
+ if (event) {
fill_assoc_sta_caps(report->frame, frame_len, &event->caps);
+ if (!!(event->pending & WIFI_ASSOC_EVENT_PENDING_CAPS)) {
+ event->pending &= ~WIFI_ASSOC_EVENT_PENDING_CAPS;
+ dev->ev.pending |= WIFI_STA_EV_ASSOC;
+ }
+ }
if (sta) {
fill_assoc_sta_caps(report->frame, frame_len, &sta->caps);
fill_wifi6_caps(report->frame, frame_len, &sta->wifi6caps);
fill_reassoc_frame(report->frame, frame_len, sta);
}
-
- dev->ev.pending |= WIFI_STA_EV_ASSOC;
-
} else if (report->result == FAILURE) {
/* Error Code TLV */
if (tlvs[CLIENT_CAPABILITY_REPORT_ERROR_CODE_IDX][0]) {
@@ -3155,6 +3145,8 @@ static int decollector_handle_topology_notification(struct decollector_private *
memcpy(n->macaddr, p->macaddr, 6);
INIT_LIST_HEAD(&n->meas_reportlist);
+ INIT_LIST_HEAD(&n->tid_qsizelist);
+
list_add_tail(&n->list, &bss->stalist);
bss->num_stations += 1;
get_timestamp(NULL, n->tsp, sizeof(n->tsp));
@@ -3198,10 +3190,8 @@ static int decollector_handle_topology_notification(struct decollector_private *
memcpy(e->bssid, p->bssid, 6);
list_add_tail(&e->list, &dev->ev.assoclist);
dev->ev.num_assoc++;
- //ev->pending |= WIFI_STA_EV_ASSOC;
- /* XXX: notify assoc event after knowing sta capability
- * from following query.
- */
+ /* notify assoc event after knowing sta capability from following query */
+ e->pending |= WIFI_ASSOC_EVENT_PENDING_CAPS;
/* Send client capability query */
ret = prepare_client_cap_query(priv, p->macaddr, p->bssid, resp->origin);
@@ -3244,30 +3234,57 @@ static int decollector_handle_topology_notification(struct decollector_private *
memcpy(e->bssid, p->bssid, 6);
list_add_tail(&e->list, &dev->ev.disassoclist);
dev->ev.num_disassoc++;
- //dev->ev.pending |= WIFI_STA_EV_DISASSOC;
- /* XXX: notify this disassoc event after getting
- * the related Client Disassociation Stats
- * message.
+ /* notify disassoc event after getting the related
+ * Client Disassociation Stats message.
*/
+ e->pending |= WIFI_DISASSOC_EVENT_PENDING_STATS;
}
}
return 0;
}
+struct wifi_assoc_event *find_assoc_event(struct list_head *evlist, uint8_t *sta_macaddr, uint8_t *bssid)
+{
+ struct wifi_assoc_event *e = NULL;
+
+ list_for_each_entry_reverse(e, evlist, list) {
+ if (hwaddr_equal(e->macaddr, sta_macaddr) &&
+ hwaddr_equal(e->bssid, bssid)) {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
+struct wifi_disassoc_event *find_dissassoc_event(struct list_head *evlist, uint8_t *sta_macaddr, uint8_t *bssid)
+{
+ struct wifi_disassoc_event *e = NULL;
+
+ list_for_each_entry_reverse(e, evlist, list) {
+ if (hwaddr_equal(e->macaddr, sta_macaddr) &&
+ hwaddr_equal(e->bssid, bssid)) {
+ return e;
+ }
+ }
+
+ return NULL;
+}
+
static int fill_disassoc_stats(struct decollector_private *priv,
struct wifi_network_device *dev,
struct cmdu_buff *resp)
{
+ struct tlv *tlvs[STA_DISASSOC_STATS_NUM_OF_TLV_TYPES][TLV_MAXNUM] = {0};
+ struct wifi_apmld_element *apmld = NULL;
+ struct tlv_assoc_sta_traffic_stats *t;
struct wifi_disassoc_event *e = NULL;
struct wifi_bss_element *bss = NULL;
- struct wifi_apmld_element *apmld = NULL;
struct wifi_sta_element *sta = NULL;
- struct tlv_assoc_sta_traffic_stats *t;
struct tlv_reason_code *r;
struct tlv_sta_mac *p;
- struct tlv *tlvs[STA_DISASSOC_STATS_NUM_OF_TLV_TYPES][TLV_MAXNUM] = {0};
- uint16_t reason = 0;
+ uint8_t *bssid = NULL;
#if (EASYMESH_VERSION >= 6)
int index = 0;
#endif /* (EASYMESH_VERSION >= 6) */
@@ -3279,39 +3296,44 @@ static int fill_disassoc_stats(struct decollector_private *priv,
return -1;
}
- /* STA MAC ADDRESS TLV */
p = (struct tlv_sta_mac *)tlvs[STA_DISASSOC_STATS_STA_MAC_ADDR_IDX][0]->data;
- /* REASON CODE TLV */
r = (struct tlv_reason_code *)tlvs[STA_DISASSOC_STATS_REASON_CODE_IDX][0]->data;
- /* ASSOCIATED STA TRAFFIC_STATS TLV */
t = (struct tlv_assoc_sta_traffic_stats *)
tlvs[STA_DISASSOC_STATS_ASSOCIATED_STA_TRAFFIC_STATS_IDX][0]->data;
- reason = r->code;
- /* add to sta eventlist */
- e = calloc(1, sizeof(*e));
- if (!e) {
- dbg("%s: error -ENOMEM\n", __func__);
- return -1;
- }
-
bss = find_bssid_sta(dev, p->macaddr);
if (bss) {
- memcpy(e->bssid, bss->bssid, 6);
+ bssid = bss->bssid;
} else {
apmld = find_bssid_stamld(dev, p->macaddr);
if (!apmld) {
dbg("%s: No bssid found\n", __func__);
return -1;
}
- memcpy(e->bssid, apmld->mld_macaddr, 6);
+ bssid = apmld->mld_macaddr;
}
- time(&e->tm);
- get_timestamp(NULL, e->tsp, sizeof(e->tsp));
- memcpy(e->macaddr, p->macaddr, 6);
- memcpy(e->sta.macaddr, p->macaddr, 6);
- e->reason_code = reason;
+ /* add/update event in disassoc eventlist */
+ e = find_dissassoc_event(&dev->ev.disassoclist, p->macaddr, bssid);
+ if (!e) {
+ e = calloc(1, sizeof(*e));
+ if (!e) {
+ dbg("%s: -ENOMEM\n", __func__);
+ return -1;
+ }
+
+ time(&e->tm);
+ get_timestamp(NULL, e->tsp, sizeof(e->tsp));
+ memcpy(e->macaddr, p->macaddr, 6);
+ memcpy(e->sta.macaddr, p->macaddr, 6);
+ memcpy(e->bssid, bssid, 6);
+ e->pending |= WIFI_DISASSOC_EVENT_PENDING_STATS;
+
+ list_add_tail(&e->list, &dev->ev.disassoclist);
+ dev->ev.num_disassoc++;
+ }
+
+ e->reason_code = r->code;
e->sta.tx_bytes = BUF_GET_BE32(t->tx_bytes);
e->sta.rx_bytes = BUF_GET_BE32(t->rx_bytes);
e->sta.tx_pkts = BUF_GET_BE32(t->tx_packets);
@@ -3321,9 +3343,8 @@ static int fill_disassoc_stats(struct decollector_private *priv,
e->sta.rtx_pkts = BUF_GET_BE32(t->rtx_packets);
#if (EASYMESH_VERSION >= 6)
- /* AFFILIATED STA METRICS TLV */
while (index < TLV_MAXNUM &&
- tlvs[STA_DISASSOC_STATS_AFFILIATED_STA_METRICS_IDX][index]) {
+ tlvs[STA_DISASSOC_STATS_AFFILIATED_STA_METRICS_IDX][index]) {
struct tlv_affiliated_sta_metrics *v;
v = (struct tlv_affiliated_sta_metrics *)
@@ -3338,11 +3359,12 @@ static int fill_disassoc_stats(struct decollector_private *priv,
e->num_affiliated_sta = index;
#endif /* (EASYMESH_VERSION >= 6) */
- list_add_tail(&e->list, &dev->ev.disassoclist);
- dev->ev.num_disassoc++;
- dev->ev.pending |= WIFI_STA_EV_DISASSOC;
+ if (!!(e->pending & WIFI_DISASSOC_EVENT_PENDING_STATS)) {
+ e->pending &= ~WIFI_DISASSOC_EVENT_PENDING_STATS;
+ dev->ev.pending |= WIFI_STA_EV_DISASSOC;
+ }
- /* client disassociation */
+ /* remove sta */
sta = find_sta(dev, p->macaddr);
if (sta) {
/* delete sta entry in bss */
diff --git a/src/decollector.h b/src/decollector.h
index dc2ef2b156877b56f5a4e05a47ab3ae907cf0e6e..ab8299ae907830b827e8b5030650089fda400143 100644
--- a/src/decollector.h
+++ b/src/decollector.h
@@ -121,79 +121,82 @@ struct assoc_req_body {
void decollector_start_collection(void *arg);
-extern int decollector_publish_object(struct decollector_private *p, const char *objname);
-extern int decollector_register_events(struct decollector_private *p);
-extern int decollector_subscribe_for_cmdus(struct decollector_private *priv);
-extern uint32_t decollector_lookup_object(struct decollector_private *p, const char *objname);
-
-extern bool is_network_device_alive(struct wifi_network_device *dev);
-extern struct wifi_network_device *find_network_device(struct wifi_data_element *dm, uint8_t *alid);
-extern struct wifi_radio_element *find_radio(const struct wifi_network_device *dev,
+int decollector_publish_object(struct decollector_private *p, const char *objname);
+int decollector_register_events(struct decollector_private *p);
+int decollector_subscribe_for_cmdus(struct decollector_private *priv);
+uint32_t decollector_lookup_object(struct decollector_private *p, const char *objname);
+
+bool is_network_device_alive(struct wifi_network_device *dev);
+struct wifi_network_device *find_network_device(struct wifi_data_element *dm, uint8_t *alid);
+struct wifi_radio_element *find_radio(const struct wifi_network_device *dev,
const uint8_t *macaddr);
-extern int decollector_dump_all(struct decollector_private *p, struct blob_buf *bb);
-extern int decollector_dump2_all(struct decollector_private *p, struct blob_buf *bb);
-extern int decollector_event_dump(struct decollector_private *p, struct blob_buf *bb);
-extern int decollector_notify_events(struct decollector_private *p, struct wifi_network_device *dev);
-extern int decollector_collect_node(struct decollector_private *p, struct wifi_network_device *dev);
-extern struct wifi_network_device *decollector_get_origin_dev(
+struct wifi_assoc_event *find_assoc_event(struct list_head *evlist, uint8_t *sta_macaddr, uint8_t *bssid);
+struct wifi_disassoc_event *find_dissassoc_event(struct list_head *evlist, uint8_t *sta_macaddr, uint8_t *bssid);
+
+int decollector_dump_all(struct decollector_private *p, struct blob_buf *bb);
+int decollector_dump2_all(struct decollector_private *p, struct blob_buf *bb);
+int decollector_event_dump(struct decollector_private *p, struct blob_buf *bb);
+int decollector_notify_events(struct decollector_private *p, struct wifi_network_device *dev);
+int decollector_collect_node(struct decollector_private *p, struct wifi_network_device *dev);
+struct wifi_network_device *decollector_get_origin_dev(
struct decollector_private *p, struct wifi_data_element *dm,
uint8_t *origin);
-extern int decollector_send_cmdu_request(struct decollector_private *priv,
+int decollector_send_cmdu_request(struct decollector_private *priv,
struct cmdu_buff *req, uint8_t *dst);
-extern int decollector_get_deagents(struct decollector_private *p, int *num, uint8_t **macaddrs);
-extern int decollector_get_ieee1905id(struct decollector_private *p);
-extern int decollector_get_network_steer_stats(struct decollector_private *p);
-extern int decollector_get_sta_steer_stats(struct decollector_private *p);
-extern int decollector_get_policy_config(struct decollector_private *p);
-
-
-extern int decollector_alloc_deagents(struct decollector_private *priv);
-extern void decollector_getter_run(void *data);
-extern void decollector_getter_run_init(struct decollector_private *p);
-extern void decollector_refresh_all(struct decollector_private *priv);
-
-extern void decollector_free_dm(struct wifi_data_element *dm);
-extern void free_network_device(struct wifi_network_device *dev);
-extern void free_sta(struct wifi_sta_element *sta);
-extern void free_bss(struct wifi_bss_element *bss);
-extern void free_radio(struct wifi_radio_element *r);
-extern void free_apmld(struct wifi_apmld_element *apmld);
-extern void free_stamld(struct wifi_stamld_element *stamld);
-extern void free_bstamld(struct wifi_network_device *dev);
-extern void free_scanresults(struct wifi_scanres_element *scanres);
-extern void free_anticipated_ch_usagelist(struct wifi_network_device *dev);
-extern void free_wifi_cac_status(struct wifi_cac_status *cac_status);
-extern void free_sta_meas_reportlist(struct wifi_sta_element *sta);
-extern void clear_supported_opclasses(struct wifi_radio_element *radio);
-extern void clear_current_opclasses(struct wifi_radio_element *radio);
-
-extern int prepare_autoconfig_search(struct decollector_private *priv, uint8_t band);
-
-
-extern int decollector_alloc_getter(struct decollector_private *p, struct wifi_network_device *dev);
-extern int decollector_free_getters(struct decollector_private *p);
-extern int decollector_free_getter(struct wifi_network_device *dev);
-extern int decollector_sched_getter(struct decollector_private *p,
+int decollector_get_deagents(struct decollector_private *p, int *num, uint8_t **macaddrs);
+int decollector_get_ieee1905id(struct decollector_private *p);
+int decollector_get_network_steer_stats(struct decollector_private *p);
+int decollector_get_sta_steer_stats(struct decollector_private *p);
+int decollector_get_policy_config(struct decollector_private *p);
+
+
+int decollector_alloc_deagents(struct decollector_private *priv);
+void decollector_getter_run(void *data);
+void decollector_getter_run_init(struct decollector_private *p);
+void decollector_refresh_all(struct decollector_private *priv);
+
+void decollector_free_dm(struct wifi_data_element *dm);
+void free_network_device(struct wifi_network_device *dev);
+void free_sta(struct wifi_sta_element *sta);
+void free_bss(struct wifi_bss_element *bss);
+void free_radio(struct wifi_radio_element *r);
+void free_apmld(struct wifi_apmld_element *apmld);
+void free_stamld(struct wifi_stamld_element *stamld);
+void free_bstamld(struct wifi_network_device *dev);
+void free_scanresults(struct wifi_scanres_element *scanres);
+void free_anticipated_ch_usagelist(struct wifi_network_device *dev);
+void free_wifi_cac_status(struct wifi_cac_status *cac_status);
+void free_sta_meas_reportlist(struct wifi_sta_element *sta);
+void clear_supported_opclasses(struct wifi_radio_element *radio);
+void clear_current_opclasses(struct wifi_radio_element *radio);
+
+int prepare_autoconfig_search(struct decollector_private *priv, uint8_t band);
+
+
+int decollector_alloc_getter(struct decollector_private *p, struct wifi_network_device *dev);
+int decollector_free_getters(struct decollector_private *p);
+int decollector_free_getter(struct wifi_network_device *dev);
+int decollector_sched_getter(struct decollector_private *p,
struct wifi_network_device *dev,
uint32_t after_ms);
-extern void decollector_stop_collection(struct decollector_private *priv);
+void decollector_stop_collection(struct decollector_private *priv);
-extern int decollector_stop_getter(struct decollector_private *p, struct wifi_network_device *dev);
-extern int decollector_reset_getter(struct decollector_private *p, struct wifi_network_device *dev);
-extern void decollector_stop_getter_all(struct decollector_private *p);
-extern int decollector_getter_running(struct decollector_private *p, struct wifi_network_device *dev);
+int decollector_stop_getter(struct decollector_private *p, struct wifi_network_device *dev);
+int decollector_reset_getter(struct decollector_private *p, struct wifi_network_device *dev);
+void decollector_stop_getter_all(struct decollector_private *p);
+int decollector_getter_running(struct decollector_private *p, struct wifi_network_device *dev);
-extern int decollector_getter_get_state(struct decollector_private *p,
+int decollector_getter_get_state(struct decollector_private *p,
struct wifi_network_device *dev, uint8_t *state);
-extern int decollector_getter_set_state(struct decollector_private *p,
+int decollector_getter_set_state(struct decollector_private *p,
struct wifi_network_device *dev, uint8_t state);
-extern int prepare_1905_query(struct decollector_private *priv, uint16_t cmdu_type,
+int prepare_1905_query(struct decollector_private *priv, uint16_t cmdu_type,
struct wifi_network_device *dev, uint8_t *dst);
#endif /* DECOLLECTOR_H */
diff --git a/src/dump.c b/src/dump.c
index cf1d7d5ef447180c4857f556cc243ec92c193a12..8d71af99aa55607411bdcbd8c99621aa82608231 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -552,29 +552,23 @@ int decollector_dump_all(struct decollector_private *p, struct blob_buf *bb)
int decollector_dump_assoc_event(struct wifi_assoc_event *e, struct blob_buf *bb)
{
- char macstr[18] = {0};
- size_t out_len;
unsigned char caps_str[32];
- void *t1, *t2;
unsigned char caps_str1[32];
- int str1_len = sizeof(caps_str1);
int he_caps_len = 0;
+ size_t out_len;
+ void *t1;
blobmsg_add_string(bb, "eventTime", e->tsp);
t1 = blobmsg_open_table(bb, "wfa-dataelements:AssociationEvent");
- t2 = blobmsg_open_table(bb, "AssocData");
- memset(macstr, 0, sizeof(macstr));
- hwaddr_ntoa(e->bssid, macstr);
- blobmsg_add_string(bb, "BSSID", macstr);
- memset(macstr, 0, sizeof(macstr));
- hwaddr_ntoa(e->macaddr, macstr);
- blobmsg_add_string(bb, "MACAddress", macstr);
+ //t2 = blobmsg_open_table(bb, "AssocData");
+ blobmsg_add_macaddr(bb, "BSSID", e->bssid);
+ blobmsg_add_macaddr(bb, "MACAddress", e->macaddr);
blobmsg_add_u32(bb, "StatusCode", e->status_code);
//if (e->caps.valid & HT_CAP_VALID) {
out_len = sizeof(caps_str);
memset(caps_str, 0, sizeof(caps_str));
base64_encode(&e->caps.ht, sizeof(e->caps.ht), caps_str, &out_len);
- remove_spec_char(caps_str1, str1_len, caps_str, out_len);
+ remove_spec_char(caps_str1, sizeof(caps_str1), caps_str, out_len);
blobmsg_add_string(bb, "HTCapabilities", (char *)caps_str1);
//}
@@ -582,7 +576,7 @@ int decollector_dump_assoc_event(struct wifi_assoc_event *e, struct blob_buf *bb
out_len = sizeof(caps_str);
memset(caps_str, 0, sizeof(caps_str));
base64_encode(e->caps.vht, sizeof(e->caps.vht), caps_str, &out_len);
- remove_spec_char(caps_str1, str1_len, caps_str, out_len);
+ remove_spec_char(caps_str1, sizeof(caps_str1), caps_str, out_len);
blobmsg_add_string(bb, "VHTCapabilities", (char *)caps_str1);
//}
@@ -594,30 +588,24 @@ int decollector_dump_assoc_event(struct wifi_assoc_event *e, struct blob_buf *bb
else
he_caps_len = 4;
base64_encode(&e->caps.he[0], he_caps_len, caps_str, &out_len);
- remove_spec_char(caps_str1, str1_len, caps_str, out_len);
+ remove_spec_char(caps_str1, sizeof(caps_str1), caps_str, out_len);
blobmsg_add_string(bb, "HECapabilities", (char *)caps_str1);
//}
+ //blobmsg_close_table(bb, t2);
blobmsg_close_table(bb, t1);
- blobmsg_close_table(bb, t2);
return 0;
}
int decollector_dump_disassoc_event(struct wifi_disassoc_event *e, struct blob_buf *bb)
{
- char macstr[18] = {0};
- void *t1;
- void *arr;
+ void *t1, *arr;
int i;
blobmsg_add_string(bb, "eventTime", e->tsp);
t1 = blobmsg_open_table(bb, "wfa-dataelements:DisassociationEvent.Disassociated");
- memset(macstr, 0, sizeof(macstr));
- hwaddr_ntoa(e->bssid, macstr);
- blobmsg_add_string(bb, "BSSID", macstr);
- memset(macstr, 0, sizeof(macstr));
- hwaddr_ntoa(e->sta.macaddr, macstr);
- blobmsg_add_string(bb, "MACAddress", macstr);
+ blobmsg_add_macaddr(bb, "BSSID", e->bssid);
+ blobmsg_add_macaddr(bb, "MACAddress", e->macaddr);
blobmsg_add_u32(bb, "ReasonCode", e->reason_code);
blobmsg_add_u32(bb, "BytesSent", e->sta.tx_bytes);
blobmsg_add_u32(bb, "BytesReceived", e->sta.rx_bytes);
@@ -640,9 +628,7 @@ int decollector_dump_disassoc_event(struct wifi_disassoc_event *e, struct blob_b
/* Device.WiFi.DataElements.DisassociationEvent.Disassociated.DisassociationLinkStats.{i} */
arr = blobmsg_open_array(bb, "DisassociationLinkStats");
for (i = 0; i < e->num_affiliated_sta; i++) {
- memset(macstr, 0, sizeof(macstr));
- hwaddr_ntoa(e->affsta[i].macaddr, macstr);
- blobmsg_add_string(bb, "MACAddress", macstr);
+ blobmsg_add_macaddr(bb, "MACAddress", e->affsta[i].macaddr);
blobmsg_add_u32(bb, "BytesSent", e->affsta[i].tx_bytes);
blobmsg_add_u32(bb, "BytesReceived", e->affsta[i].rx_bytes);
blobmsg_add_u32(bb, "PacketsSent", e->affsta[i].tx_packets);
@@ -650,7 +636,6 @@ int decollector_dump_disassoc_event(struct wifi_disassoc_event *e, struct blob_b
blobmsg_add_u32(bb, "ErrorsSent", e->affsta[i].tx_errors);
}
blobmsg_close_array(bb, arr); // DisassociationLinkStats
-
blobmsg_close_table(bb, t1);
return 0;
@@ -696,6 +681,7 @@ int decollector_event_dump(struct decollector_private *p, struct blob_buf *bb)
return 0;
}
+/* notify all non-pending events */
int decollector_notify_events(struct decollector_private *p, struct wifi_network_device *dev)
{
struct wifi_sta_events *ev = &dev->ev;
@@ -704,30 +690,53 @@ int decollector_notify_events(struct decollector_private *p, struct wifi_network
if (!!(ev->pending & WIFI_STA_EV_ASSOC)) {
- /* latest event is at the tail */
+ int reset_notify = 1;
+
list_for_each_entry_reverse(ea, &ev->assoclist, list) {
struct blob_buf bb = {0};
+ if (ea->delivered)
+ continue;
+
+ if (ea->pending) {
+ reset_notify = 0;
+ continue;
+ }
+
+ ea->delivered = 1;
blob_buf_init(&bb, 0);
decollector_dump_assoc_event(ea, &bb);
ubus_send_event(p->ctx, "wifi.dataelements.Associated", bb.head);
blob_buf_free(&bb);
- break;
}
- ev->pending &= ~ WIFI_STA_EV_ASSOC;
+
+ if (reset_notify)
+ ev->pending &= ~ WIFI_STA_EV_ASSOC;
}
if (!!(ev->pending & WIFI_STA_EV_DISASSOC)) {
+ int reset_notify = 1;
+
list_for_each_entry_reverse(eb, &ev->disassoclist, list) {
struct blob_buf bb = {0};
+ if (eb->delivered)
+ continue;
+
+ if (eb->pending) {
+ reset_notify = 0;
+ continue;
+ }
+
+ eb->delivered = 1;
blob_buf_init(&bb, 0);
decollector_dump_disassoc_event(eb, &bb);
ubus_send_event(p->ctx, "wifi.dataelements.Disassociated", bb.head);
blob_buf_free(&bb);
- break;
}
- ev->pending &= ~ WIFI_STA_EV_DISASSOC;
+
+ if (reset_notify)
+ ev->pending &= ~ WIFI_STA_EV_DISASSOC;
}
/* Free up the oldest entries, when either max-count reached, or
diff --git a/src/wifi_dataelements.h b/src/wifi_dataelements.h
index 9e03c8c298e49f316612b998db98e8fb1f6dc0ab..a100845908c810e083a5f7e8505a229e5216be56 100644
--- a/src/wifi_dataelements.h
+++ b/src/wifi_dataelements.h
@@ -917,7 +917,12 @@ struct wifi_data_element {
struct wifi_network network;
};
+#define WIFI_ASSOC_EVENT_PENDING_CAPS 0x1
+#define WIFI_DISASSOC_EVENT_PENDING_STATS 0x1
+
struct wifi_assoc_event {
+ uint8_t delivered; /* event delivered */
+ uint8_t pending; /* event data pending */
timestamp_t tsp;
time_t tm;
uint8_t macaddr[6];
@@ -928,6 +933,8 @@ struct wifi_assoc_event {
};
struct wifi_disassoc_event {
+ uint8_t delivered; /* event delivered */
+ uint8_t pending; /* event data pending */
timestamp_t tsp;
time_t tm;
uint8_t macaddr[6];