rework log handling
- make logging events more structured - add fine grained control over log events - make it possible to receive more detailed events via ubus Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
282
event.c
Normal file
282
event.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Copyright (C) 2020 embedd.ch
|
||||
* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
|
||||
* Copyright (C) 2020 John Crispin <john@phrozen.org>
|
||||
*/
|
||||
#include "usteer.h"
|
||||
#include "event.h"
|
||||
|
||||
#define UEV_LOG_MAXLEN 256
|
||||
|
||||
static struct blob_buf b;
|
||||
static const char * const uev_name[] = {
|
||||
[UEV_PROBE_REQ_ACCEPT] = "probe_req_accept",
|
||||
[UEV_PROBE_REQ_DENY] = "probe_req_deny",
|
||||
[UEV_AUTH_REQ_ACCEPT] = "auth_req_accept",
|
||||
[UEV_AUTH_REQ_DENY] = "auth_req_deny",
|
||||
[UEV_ASSOC_REQ_ACCEPT] = "assoc_req_accept",
|
||||
[UEV_ASSOC_REQ_DENY] = "assoc_req_deny",
|
||||
[UEV_LOAD_KICK_TRIGGER] = "load_kick_trigger",
|
||||
[UEV_LOAD_KICK_RESET] = "load_kick_reset",
|
||||
[UEV_LOAD_KICK_MIN_CLIENTS] = "load_kick_min_clients",
|
||||
[UEV_LOAD_KICK_NO_CLIENT] = "load_kick_no_client",
|
||||
[UEV_LOAD_KICK_CLIENT] = "load_kick_client",
|
||||
[UEV_SIGNAL_KICK] = "signal_kick",
|
||||
|
||||
};
|
||||
static const char * const uev_reason[] = {
|
||||
[UEV_REASON_NONE] = "none",
|
||||
[UEV_REASON_RETRY_EXCEEDED] = "retry_exceeded",
|
||||
[UEV_REASON_LOW_SIGNAL] = "low_signal",
|
||||
[UEV_REASON_CONNECT_DELAY] = "connect_delay",
|
||||
[UEV_REASON_BETTER_CANDIDATE] = "better_candidate",
|
||||
};
|
||||
|
||||
static const char * const uev_select_reason[] = {
|
||||
[UEV_SELECT_REASON_NUM_ASSOC] = "n_assoc",
|
||||
[UEV_SELECT_REASON_SIGNAL] = "signal",
|
||||
[UEV_SELECT_REASON_LOAD] = "load",
|
||||
};
|
||||
|
||||
static void
|
||||
usteer_event_add_node_info(struct usteer_node *node)
|
||||
{
|
||||
blobmsg_add_u32(&b, "load", node->load);
|
||||
blobmsg_add_u32(&b, "assoc", node->n_assoc);
|
||||
}
|
||||
|
||||
static void
|
||||
usteer_event_send_ubus(struct uevent *ev)
|
||||
{
|
||||
void *c;
|
||||
int i;
|
||||
|
||||
if (!usteer_obj.has_subscribers)
|
||||
return;
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
|
||||
if (ev->node_local)
|
||||
blobmsg_add_string(&b, "node", usteer_node_name(ev->node_local));
|
||||
|
||||
if (ev->sta)
|
||||
blobmsg_printf(&b, "sta", MAC_ADDR_FMT, MAC_ADDR_DATA(ev->sta->addr));
|
||||
|
||||
if (ev->si_cur)
|
||||
blobmsg_add_u32(&b, "signal", (int32_t)ev->si_cur->signal);
|
||||
|
||||
if (ev->reason)
|
||||
blobmsg_add_string(&b, "reason", uev_reason[ev->reason]);
|
||||
|
||||
if (ev->threshold.ref) {
|
||||
c = blobmsg_open_array(&b, "threshold");
|
||||
blobmsg_add_u32(&b, NULL, ev->threshold.cur);
|
||||
blobmsg_add_u32(&b, NULL, ev->threshold.ref);
|
||||
blobmsg_close_array(&b, c);
|
||||
}
|
||||
|
||||
if (ev->select_reasons) {
|
||||
c = blobmsg_open_array(&b, "select_reason");
|
||||
for (i = 0; i < ARRAY_SIZE(uev_select_reason); i++) {
|
||||
if (!(ev->select_reasons & (1 << i)) ||
|
||||
!uev_select_reason[i])
|
||||
continue;
|
||||
|
||||
blobmsg_add_string(&b, NULL, uev_select_reason[i]);
|
||||
}
|
||||
blobmsg_close_array(&b, c);
|
||||
}
|
||||
|
||||
if (ev->node_cur) {
|
||||
c = blobmsg_open_table(&b, "local");
|
||||
usteer_event_add_node_info(ev->node_cur);
|
||||
blobmsg_close_table(&b, c);
|
||||
}
|
||||
|
||||
if (ev->node_other) {
|
||||
c = blobmsg_open_table(&b, "remote");
|
||||
blobmsg_add_string(&b, "name", usteer_node_name(ev->node_other));
|
||||
if (ev->si_other)
|
||||
blobmsg_add_u32(&b, "signal", (int32_t)ev->si_other->signal);
|
||||
usteer_event_add_node_info(ev->node_other);
|
||||
blobmsg_close_table(&b, c);
|
||||
}
|
||||
|
||||
if (ev->count)
|
||||
blobmsg_add_u32(&b, "count", ev->count);
|
||||
|
||||
ubus_notify(ubus_ctx, &usteer_obj, uev_name[ev->type], b.head, -1);
|
||||
}
|
||||
|
||||
static int
|
||||
usteer_event_log_node(char *buf, int len, const char *prefix, struct usteer_node *node)
|
||||
{
|
||||
char *cur = buf;
|
||||
char *end = buf + len;
|
||||
|
||||
cur += snprintf(cur, end - cur, " %sassoc=%d %sload=%d",
|
||||
prefix, node->n_assoc,
|
||||
prefix, node->load);
|
||||
|
||||
return cur - buf;
|
||||
}
|
||||
|
||||
static void
|
||||
usteer_event_log(struct uevent *ev)
|
||||
{
|
||||
char *str, *cur, *end;
|
||||
int i;
|
||||
|
||||
if (!(config.event_log_mask & (1 << ev->type)))
|
||||
return;
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
cur = str = blobmsg_alloc_string_buffer(&b, NULL, UEV_LOG_MAXLEN);
|
||||
end = str + UEV_LOG_MAXLEN;
|
||||
cur += snprintf(cur, end - cur, "usteer event=%s", uev_name[ev->type]);
|
||||
if (ev->node_local)
|
||||
cur += snprintf(cur, end - cur, " node=%s", usteer_node_name(ev->node_local));
|
||||
if (ev->sta)
|
||||
cur += snprintf(cur, end - cur, " sta=" MAC_ADDR_FMT, MAC_ADDR_DATA(ev->sta->addr));
|
||||
if (ev->reason)
|
||||
cur += snprintf(cur, end - cur, " reason=%s", uev_reason[ev->reason]);
|
||||
if (ev->si_cur)
|
||||
cur += snprintf(cur, end - cur, " signal=%d", ev->si_cur->signal);
|
||||
if (ev->threshold.ref)
|
||||
cur += snprintf(cur, end - cur, " thr=%d/%d", ev->threshold.cur, ev->threshold.ref);
|
||||
if (ev->count)
|
||||
cur += snprintf(cur, end - cur, " count=%d", ev->count);
|
||||
if (ev->node_cur)
|
||||
cur += usteer_event_log_node(cur, end - cur, "", ev->node_cur);
|
||||
if (ev->select_reasons) {
|
||||
bool first = true;
|
||||
|
||||
cur += snprintf(cur, end - cur, " select_reason");
|
||||
for (i = 0; i < ARRAY_SIZE(uev_select_reason); i++) {
|
||||
if (!(ev->select_reasons & (1 << i)) ||
|
||||
!uev_select_reason[i])
|
||||
continue;
|
||||
|
||||
cur += snprintf(cur, end - cur, "%c%s", first ? '=' : ',',
|
||||
uev_select_reason[i]);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
if (ev->node_other) {
|
||||
cur += snprintf(cur, end - cur, " remote=%s", usteer_node_name(ev->node_other));
|
||||
if (ev->si_other)
|
||||
cur += snprintf(cur, end - cur, " remote_signal=%d",
|
||||
ev->si_other->signal);
|
||||
cur += usteer_event_log_node(cur, end - cur, "remote_", ev->node_other);
|
||||
}
|
||||
|
||||
log_msg(str);
|
||||
}
|
||||
|
||||
void usteer_event(struct uevent *ev)
|
||||
{
|
||||
if (ev->type >= ARRAY_SIZE(uev_name) || !uev_name[ev->type])
|
||||
return;
|
||||
|
||||
if (ev->reason >= ARRAY_SIZE(uev_reason) || !uev_reason[ev->reason])
|
||||
return;
|
||||
|
||||
if (ev->si_cur) {
|
||||
if (!ev->node_local)
|
||||
ev->node_local = ev->si_cur->node;
|
||||
if (!ev->sta)
|
||||
ev->sta = ev->si_cur->sta;
|
||||
}
|
||||
|
||||
if (!ev->node_local && ev->node_cur)
|
||||
ev->node_local = ev->node_cur;
|
||||
|
||||
if (ev->si_other && ev->node_cur && !ev->node_other)
|
||||
ev->node_other = ev->si_other->node;
|
||||
|
||||
usteer_event_send_ubus(ev);
|
||||
usteer_event_log(ev);
|
||||
}
|
||||
|
||||
void config_set_event_log_types(struct blob_attr *attr)
|
||||
{
|
||||
struct blob_attr *cur;
|
||||
int i, rem;
|
||||
|
||||
config.event_log_mask = 0;
|
||||
if (!attr) {
|
||||
static const uint32_t default_log[] = {
|
||||
[MSG_INFO] =
|
||||
(1 << UEV_LOAD_KICK_CLIENT) |
|
||||
(1 << UEV_SIGNAL_KICK) |
|
||||
(1 << UEV_AUTH_REQ_DENY) |
|
||||
(1 << UEV_ASSOC_REQ_DENY),
|
||||
[MSG_VERBOSE] =
|
||||
(1 << UEV_PROBE_REQ_DENY),
|
||||
[MSG_DEBUG] =
|
||||
(1 << UEV_AUTH_REQ_ACCEPT) |
|
||||
(1 << UEV_ASSOC_REQ_ACCEPT) |
|
||||
(1 << UEV_LOAD_KICK_TRIGGER) |
|
||||
(1 << UEV_LOAD_KICK_RESET) |
|
||||
(1 << UEV_LOAD_KICK_MIN_CLIENTS) |
|
||||
(1 << UEV_LOAD_KICK_NO_CLIENT),
|
||||
};
|
||||
|
||||
if (config.debug_level >= MSG_DEBUG_ALL) {
|
||||
config.event_log_mask = ~0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(default_log) && i <= config.debug_level; i++)
|
||||
config.event_log_mask |= default_log[i];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (blobmsg_check_array(attr, BLOBMSG_TYPE_STRING) < 0)
|
||||
return;
|
||||
|
||||
blobmsg_for_each_attr(cur, attr, rem) {
|
||||
const char *name = blobmsg_get_string(cur);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(uev_name); i++) {
|
||||
if (!uev_name[i] || strcmp(uev_name[i], name) != 0)
|
||||
continue;
|
||||
|
||||
config.event_log_mask |= (1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void config_get_event_log_types(struct blob_buf *buf)
|
||||
{
|
||||
uint32_t mask = config.event_log_mask;
|
||||
void *c;
|
||||
int i;
|
||||
|
||||
c = blobmsg_open_array(buf, "event_log_types");
|
||||
for (i = 0; mask && i < ARRAY_SIZE(uev_name); i++) {
|
||||
bool cur = mask & 1;
|
||||
|
||||
mask >>= 1;
|
||||
if (!cur)
|
||||
continue;
|
||||
|
||||
blobmsg_add_string(buf, NULL, uev_name[i]);
|
||||
}
|
||||
blobmsg_close_array(buf, c);
|
||||
}
|
Reference in New Issue
Block a user