opensync: add "event" stats_type support for SM

* oveschema update included in this commit

Signed-off-by: Damir Franusic <damir.franusic@netexperience.com>
This commit is contained in:
Damir Franusic 2020-10-13 10:52:36 +02:00 committed by John Crispin
parent be01395414
commit 518721589b
3 changed files with 7062 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,455 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#ifndef DPP_EVENTS_H_INCLUDED
#define DPP_EVENTS_H_INCLUDED
#include "ds.h"
#include "ds_dlist.h"
#include "dpp_types.h"
/* string limits */
#define DPP_REASON_STR_LEN 129
#define DPP_CLT_ID_LEN 129
#define MAC_ADDRESS_STRING_LEN 17
/* proto: EventType */
typedef enum {
ET_CLIENT_ASSOC = 0,
ET_CLIENT_AUTH,
ET_CLIENT_DISCONNECT,
ET_CLIENT_FAILURE,
ET_CLIENT_FIRST_DATA,
ET_CLIENT_ID,
ET_CLIENT_IP,
ET_CLIENT_TIMEOUT
} event_type_t;
/* proto: AssocType */
typedef enum { AT_ASSOC = 0, AT_REASSOC } assoc_type_t;
/* proto: DeviceType */
typedef enum { DT_AP = 0, DT_STA } device_type_t;
/* proto: FrameType */
typedef enum { FT_DEAUTH = 0, FT_DISASSOC } frame_type_t;
/* proto: CTReasonType */
typedef enum { CTR_IDLE_TOO_LONG = 0, CTR_PROBE_FAIL } ct_reason_t;
/* proto: SecurityType */
typedef enum { SEC_OPEN = 0, SEC_RADIUS, SEC_PSK } sec_type_t;
/* proto: ClientAssocEvent */
typedef struct {
char __barrier[46];
char sta_mac[MAC_ADDRESS_STRING_LEN + 1];
uint64_t session_id;
radio_essid_t ssid;
uint32_t timestamp;
radio_type_t band;
assoc_type_t assoc_type;
uint32_t status;
int32_t rssi;
uint32_t internal_sc;
bool using11k;
bool using11r;
bool using11v;
ds_dlist_node_t node;
} dpp_event_record_assoc_t;
/* proto: ClientAuthEvent */
typedef struct {
char __barrier[46];
char sta_mac[MAC_ADDRESS_STRING_LEN + 1];
uint64_t session_id;
uint32_t timestamp;
radio_essid_t ssid;
radio_type_t band;
uint32_t auth_status;
ds_dlist_node_t node;
} dpp_event_record_auth_t;
/* proto: ClientDisconnectEvent */
typedef struct {
char __barrier[46];
char sta_mac[MAC_ADDRESS_STRING_LEN + 1];
uint64_t session_id;
uint32_t timestamp;
uint32_t reason;
device_type_t dev_type;
frame_type_t fr_type;
uint64_t last_sent_up_ts_in_us;
uint64_t last_recv_up_ts_in_us;
uint32_t internal_rc;
int32_t rssi;
radio_essid_t ssid;
radio_type_t band;
ds_dlist_node_t node;
} dpp_event_record_disconnect_t;
/* proto: ClientConnectEvent */
typedef struct {
char __barrier[46];
char sta_mac[MAC_ADDRESS_STRING_LEN + 1];
uint64_t session_id;
uint32_t timestamp;
radio_type_t band;
assoc_type_t assoc_type;
radio_essid_t ssid;
sec_type_t sec_type;
bool fbt_used;
uint8_t ip_addr[16];
char clt_id[DPP_CLT_ID_LEN];
int64_t ev_time_bootup_in_us_auth;
int64_t ev_time_bootup_in_us_assoc;
int64_t ev_time_bootup_in_us_eapol;
int64_t ev_time_bootup_in_us_port_enable;
int64_t ev_time_bootup_in_us_first_rx;
int64_t ev_time_bootup_in_us_first_tx;
bool using11k;
bool using11r;
bool using11v;
int64_t ev_time_bootup_in_us_ip;
int32_t assoc_rssi;
ds_dlist_node_t node;
} dpp_event_record_connect_t;
/* proto: ClientFailureEvent */
typedef struct {
char __barrier[46];
char sta_mac[MAC_ADDRESS_STRING_LEN + 1];
uint64_t session_id;
uint32_t timestamp;
radio_essid_t ssid;
int32_t reason;
char reason_str[DPP_REASON_STR_LEN];
ds_dlist_node_t node;
} dpp_event_record_failure_t;
/* proto: ClientFirstDataEvent */
typedef struct {
char __barrier[46];
char sta_mac[MAC_ADDRESS_STRING_LEN + 1];
uint64_t session_id;
uint32_t timestamp;
uint64_t fdata_tx_up_ts_in_us;
uint64_t fdata_rx_up_ts_in_us;
ds_dlist_node_t node;
} dpp_event_record_first_data_t;
/* proto: ClientIdEvent */
typedef struct {
char __barrier[46];
mac_address_t clt_mac;
uint64_t session_id;
char clt_id[DPP_CLT_ID_LEN];
ds_dlist_node_t node;
} dpp_event_record_id_t;
/* proto: ClientIpEvent */
typedef struct {
char __barrier[46];
char sta_mac[MAC_ADDRESS_STRING_LEN + 1];
uint64_t session_id;
uint32_t timestamp;
uint8_t ip_addr[16];
ds_dlist_node_t node;
} dpp_event_record_ip_t;
/* proto: ClientTimeoutEvent */
typedef struct {
char __barrier[46];
char sta_mac[MAC_ADDRESS_STRING_LEN + 1];
uint64_t session_id;
uint32_t timestamp;
ct_reason_t r_code;
uint64_t last_sent_up_ts_in_us;
uint64_t last_recv_up_ts_in_us;
ds_dlist_node_t node;
} dpp_event_record_timeout_t;
/* proto: ClientSession */
typedef struct {
uint64_t session_id;
ds_dlist_t assoc_list; /* dpp_event_record_assoc_t */
ds_dlist_t auth_list; /* dpp_event_record_auth_t */
ds_dlist_t disconnect_list; /* dpp_event_record_disconnect_t */
ds_dlist_t failure_list; /* dpp_event_record_failure_t */
ds_dlist_t first_data_list; /* dpp_event_record_first_data_t */
ds_dlist_t id_list; /* dpp_event_record_id_t */
ds_dlist_t ip_list; /* dpp_event_record_ip_t */
ds_dlist_t timeout_list; /* dpp_event_record_timeout_t */
ds_dlist_t connect_list; /* dpp_event_record_connect_t */
ds_dlist_node_t node;
} dpp_event_record_session_t;
/* event record */
typedef struct {
ds_dlist_t client_session; /* dpp_event_record_session_t */
ds_dlist_node_t node;
} dpp_event_record_t;
/*******************************/
/* ClientAssocEvent alloc/free */
/*******************************/
/* alloc */
static inline dpp_event_record_assoc_t *dpp_event_client_assoc_record_alloc()
{
dpp_event_record_assoc_t *record = NULL;
record = malloc(sizeof(dpp_event_record_assoc_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_assoc_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_assoc_record_free(dpp_event_record_assoc_t *record)
{
if (NULL != record) {
free(record);
}
}
/******************************/
/* ClientAuthEvent alloc/free */
/******************************/
/* alloc */
static inline dpp_event_record_auth_t *dpp_event_client_auth_record_alloc()
{
dpp_event_record_auth_t *record = NULL;
record = malloc(sizeof(dpp_event_record_auth_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_auth_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_auth_record_free(dpp_event_record_auth_t *record)
{
if (NULL != record) {
free(record);
}
}
/************************************/
/* ClientDisconnectEvent alloc/free */
/************************************/
/* alloc */
static inline dpp_event_record_disconnect_t *
dpp_event_client_disconnect_record_alloc()
{
dpp_event_record_disconnect_t *record = NULL;
record = malloc(sizeof(dpp_event_record_disconnect_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_disconnect_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_disconnect_record_free(dpp_event_record_disconnect_t *record)
{
if (NULL != record) {
free(record);
}
}
/************************************/
/* ClientConnectEvent alloc/free */
/************************************/
/* alloc */
static inline dpp_event_record_connect_t *
dpp_event_client_connect_record_alloc()
{
dpp_event_record_connect_t *record = NULL;
record = malloc(sizeof(dpp_event_record_connect_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_connect_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_connect_record_free(dpp_event_record_connect_t *record)
{
if (NULL != record) {
free(record);
}
}
/*********************************/
/* ClientFailureEvent alloc/free */
/*********************************/
/* alloc */
static inline dpp_event_record_failure_t *
dpp_event_client_failure_record_alloc()
{
dpp_event_record_failure_t *record = NULL;
record = malloc(sizeof(dpp_event_record_failure_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_failure_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_failure_record_free(dpp_event_record_failure_t *record)
{
if (NULL != record) {
free(record);
}
}
/***********************************/
/* ClientFirstDataEvent alloc/free */
/***********************************/
/* alloc */
static inline dpp_event_record_first_data_t *
dpp_event_client_first_data_record_alloc()
{
dpp_event_record_first_data_t *record = NULL;
record = malloc(sizeof(dpp_event_record_first_data_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_first_data_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_first_data_record_free(dpp_event_record_first_data_t *record)
{
if (NULL != record) {
free(record);
}
}
/****************************/
/* ClientIdEvent alloc/free */
/****************************/
/* alloc */
static inline dpp_event_record_id_t *dpp_event_client_id_record_alloc()
{
dpp_event_record_id_t *record = NULL;
record = malloc(sizeof(dpp_event_record_id_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_id_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_id_record_free(dpp_event_record_id_t *record)
{
if (NULL != record) {
free(record);
}
}
/****************************/
/* ClientIpEvent alloc/free */
/****************************/
/* alloc */
static inline dpp_event_record_ip_t *dpp_event_client_ip_record_alloc()
{
dpp_event_record_ip_t *record = NULL;
record = malloc(sizeof(dpp_event_record_ip_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_ip_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_ip_record_free(dpp_event_record_ip_t *record)
{
if (NULL != record) {
free(record);
}
}
/*********************************/
/* ClientTimeoutEvent alloc/free */
/*********************************/
/* alloc */
static inline dpp_event_record_timeout_t *
dpp_event_client_timeout_record_alloc()
{
dpp_event_record_timeout_t *record = NULL;
record = malloc(sizeof(dpp_event_record_timeout_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_timeout_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_timeout_record_free(dpp_event_record_timeout_t *record)
{
if (NULL != record) {
free(record);
}
}
/*********************************/
/* ClientSession alloc/free */
/*********************************/
/* alloc */
static inline dpp_event_record_session_t *
dpp_event_client_session_record_alloc()
{
dpp_event_record_session_t *record = NULL;
record = malloc(sizeof(dpp_event_record_session_t));
if (record) {
memset(record, 0, sizeof(dpp_event_record_session_t));
}
return record;
}
/* free */
static inline void
dpp_event_client_session_record_free(dpp_event_record_session_t *record)
{
if (NULL != record) {
free(record);
}
}
/* Events report type */
typedef struct {
ds_dlist_t list; /* dpp_event_record_t */
} dpp_event_report_data_t;
#endif /* DPP_EVENTS_H_INCLUDED */

View File

@ -0,0 +1,176 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#define _GNU_SOURCE
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <net/if.h>
#include <sys/types.h>
#include <ev.h>
#include <syslog.h>
#include <unl.h>
#include "sm.h"
#include "ubus_collector.h"
#define MODULE_ID LOG_MODULE_ID_MAIN
/* global list populated by ubus_collector */
extern dpp_event_report_data_t g_report_data;
/* new part */
typedef struct {
bool initialized;
/* Internal structure used to lower layer radio selection */
radio_entry_t *radio_cfg;
/* Internal structure used to lower layer radio selection */
ev_timer report_timer;
/* Structure containing cloud request timer params */
sm_stats_request_t request;
/* Structure pointing to upper layer events storage */
dpp_event_report_data_t report;
/* event list (only one for now) */
ds_dlist_t record_list;
/* Reporting start timestamp used for reporting timestamp calculation */
uint64_t report_ts;
} sm_events_ctx_t;
/* Common place holder for all events stat report contexts */
sm_events_ctx_t g_sm_events_ctx;
/******************************************************************************
* PROTECTED definitions
*****************************************************************************/
static bool dpp_events_report_timer_set(ev_timer *timer, bool enable)
{
if (enable) {
ev_timer_again(EV_DEFAULT, timer);
} else {
ev_timer_stop(EV_DEFAULT, timer);
}
return true;
}
static bool dpp_events_report_timer_restart(ev_timer *timer)
{
sm_events_ctx_t *events_ctx = (sm_events_ctx_t *)timer->data;
sm_stats_request_t *request_ctx = &events_ctx->request;
if (request_ctx->reporting_count) {
request_ctx->reporting_count--;
LOG(DEBUG, "Updated events reporting count=%d",
request_ctx->reporting_count);
/* If reporting_count becomes zero, then stop reporting */
if (0 == request_ctx->reporting_count) {
dpp_events_report_timer_set(timer, false);
LOG(DEBUG, "Stopped events reporting (count expired)");
return true;
}
}
return true;
}
static void sm_events_report(EV_P_ ev_timer *w, int revents)
{
sm_events_ctx_t *events_ctx = (sm_events_ctx_t *)w->data;
dpp_event_report_data_t *report_ctx = &events_ctx->report;
ev_timer *report_timer = &events_ctx->report_timer;
dpp_events_report_timer_restart(report_timer);
memcpy(report_ctx, &g_report_data, sizeof(dpp_event_report_data_t));
while (!ds_dlist_is_empty(&g_report_data.list)) {
ds_dlist_remove_head(&g_report_data.list);
}
LOG(INFO, "Sending events report...");
if (!ds_dlist_is_empty(&report_ctx->list)) {
dpp_put_events(report_ctx);
}
}
/******************************************************************************
* PUBLIC API definitions
*****************************************************************************/
bool sm_events_report_request(radio_entry_t *radio_cfg,
sm_stats_request_t *request)
{
sm_events_ctx_t *events_ctx = &g_sm_events_ctx;
sm_stats_request_t *request_ctx = &events_ctx->request;
dpp_event_report_data_t *report_ctx = &events_ctx->report;
ev_timer *report_timer = &events_ctx->report_timer;
// save radio cfg
events_ctx->radio_cfg = radio_cfg;
if (NULL == request) {
LOG(ERR, "Initializing events reporting "
"(Invalid request config)");
return false;
}
/* Initialize global stats only once */
if (!events_ctx->initialized) {
memset(request_ctx, 0, sizeof(*request_ctx));
memset(report_ctx, 0, sizeof(*report_ctx));
LOG(INFO, "Initializing events reporting");
/* Initialize report list */
ds_dlist_init(&report_ctx->list, dpp_event_record_t, node);
/* Initialize event list */
ds_dlist_init(&events_ctx->record_list, dpp_event_record_t,
node);
/* Initialize event lib timers and pass the global
internal cache
*/
ev_init(report_timer, sm_events_report);
report_timer->data = events_ctx;
events_ctx->initialized = true;
}
/* Store and compare every request parameter ...
memcpy would be easier but we want some debug info
*/
REQUEST_VAL_UPDATE("event", reporting_count, "%d");
REQUEST_VAL_UPDATE("event", reporting_interval, "%d");
REQUEST_VAL_UPDATE("event", reporting_timestamp, "%" PRIu64 "");
/* Restart timers with new parameters */
dpp_events_report_timer_set(report_timer, false);
if (request_ctx->reporting_interval) {
events_ctx->report_ts = get_timestamp();
report_timer->repeat = request_ctx->reporting_interval;
dpp_events_report_timer_set(report_timer, true);
LOG(INFO, "Started events reporting");
} else {
LOG(INFO, "Stopped events reporting");
memset(request_ctx, 0, sizeof(*request_ctx));
}
return true;
}