2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 * Copyright (C) 2020 embedd.ch
16 * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
17 * Copyright (C) 2020 John Crispin <john@phrozen.org>
22 #define UEV_LOG_MAXLEN 256
24 static struct blob_buf b
;
25 static const char * const uev_name
[] = {
26 [UEV_PROBE_REQ_ACCEPT
] = "probe_req_accept",
27 [UEV_PROBE_REQ_DENY
] = "probe_req_deny",
28 [UEV_AUTH_REQ_ACCEPT
] = "auth_req_accept",
29 [UEV_AUTH_REQ_DENY
] = "auth_req_deny",
30 [UEV_ASSOC_REQ_ACCEPT
] = "assoc_req_accept",
31 [UEV_ASSOC_REQ_DENY
] = "assoc_req_deny",
32 [UEV_LOAD_KICK_TRIGGER
] = "load_kick_trigger",
33 [UEV_LOAD_KICK_RESET
] = "load_kick_reset",
34 [UEV_LOAD_KICK_MIN_CLIENTS
] = "load_kick_min_clients",
35 [UEV_LOAD_KICK_NO_CLIENT
] = "load_kick_no_client",
36 [UEV_LOAD_KICK_CLIENT
] = "load_kick_client",
37 [UEV_SIGNAL_KICK
] = "signal_kick",
40 static const char * const uev_reason
[] = {
41 [UEV_REASON_NONE
] = "none",
42 [UEV_REASON_RETRY_EXCEEDED
] = "retry_exceeded",
43 [UEV_REASON_LOW_SIGNAL
] = "low_signal",
44 [UEV_REASON_CONNECT_DELAY
] = "connect_delay",
45 [UEV_REASON_BETTER_CANDIDATE
] = "better_candidate",
48 static const char * const uev_select_reason
[] = {
49 [UEV_SELECT_REASON_NUM_ASSOC
] = "n_assoc",
50 [UEV_SELECT_REASON_SIGNAL
] = "signal",
51 [UEV_SELECT_REASON_LOAD
] = "load",
55 usteer_event_add_node_info(struct usteer_node
*node
)
57 blobmsg_add_u32(&b
, "load", node
->load
);
58 blobmsg_add_u32(&b
, "assoc", node
->n_assoc
);
62 usteer_event_send_ubus(struct uevent
*ev
)
67 if (!usteer_obj
.has_subscribers
)
73 blobmsg_add_string(&b
, "node", usteer_node_name(ev
->node_local
));
76 blobmsg_printf(&b
, "sta", MAC_ADDR_FMT
, MAC_ADDR_DATA(ev
->sta
->addr
));
79 blobmsg_add_u32(&b
, "signal", (int32_t)ev
->si_cur
->signal
);
82 blobmsg_add_string(&b
, "reason", uev_reason
[ev
->reason
]);
84 if (ev
->threshold
.ref
) {
85 c
= blobmsg_open_array(&b
, "threshold");
86 blobmsg_add_u32(&b
, NULL
, ev
->threshold
.cur
);
87 blobmsg_add_u32(&b
, NULL
, ev
->threshold
.ref
);
88 blobmsg_close_array(&b
, c
);
91 if (ev
->select_reasons
) {
92 c
= blobmsg_open_array(&b
, "select_reason");
93 for (i
= 0; i
< ARRAY_SIZE(uev_select_reason
); i
++) {
94 if (!(ev
->select_reasons
& (1 << i
)) ||
95 !uev_select_reason
[i
])
98 blobmsg_add_string(&b
, NULL
, uev_select_reason
[i
]);
100 blobmsg_close_array(&b
, c
);
104 c
= blobmsg_open_table(&b
, "local");
105 usteer_event_add_node_info(ev
->node_cur
);
106 blobmsg_close_table(&b
, c
);
109 if (ev
->node_other
) {
110 c
= blobmsg_open_table(&b
, "remote");
111 blobmsg_add_string(&b
, "name", usteer_node_name(ev
->node_other
));
113 blobmsg_add_u32(&b
, "signal", (int32_t)ev
->si_other
->signal
);
114 usteer_event_add_node_info(ev
->node_other
);
115 blobmsg_close_table(&b
, c
);
119 blobmsg_add_u32(&b
, "count", ev
->count
);
121 ubus_notify(ubus_ctx
, &usteer_obj
, uev_name
[ev
->type
], b
.head
, -1);
125 usteer_event_log_node(char *buf
, int len
, const char *prefix
, struct usteer_node
*node
)
128 char *end
= buf
+ len
;
130 cur
+= snprintf(cur
, end
- cur
, " %sassoc=%d %sload=%d",
131 prefix
, node
->n_assoc
,
138 usteer_event_log(struct uevent
*ev
)
140 char *str
, *cur
, *end
;
143 if (!(config
.event_log_mask
& (1 << ev
->type
)))
146 blob_buf_init(&b
, 0);
147 cur
= str
= blobmsg_alloc_string_buffer(&b
, NULL
, UEV_LOG_MAXLEN
);
148 end
= str
+ UEV_LOG_MAXLEN
;
149 cur
+= snprintf(cur
, end
- cur
, "usteer event=%s", uev_name
[ev
->type
]);
151 cur
+= snprintf(cur
, end
- cur
, " node=%s", usteer_node_name(ev
->node_local
));
153 cur
+= snprintf(cur
, end
- cur
, " sta=" MAC_ADDR_FMT
, MAC_ADDR_DATA(ev
->sta
->addr
));
155 cur
+= snprintf(cur
, end
- cur
, " reason=%s", uev_reason
[ev
->reason
]);
157 cur
+= snprintf(cur
, end
- cur
, " signal=%d", ev
->si_cur
->signal
);
158 if (ev
->threshold
.ref
)
159 cur
+= snprintf(cur
, end
- cur
, " thr=%d/%d", ev
->threshold
.cur
, ev
->threshold
.ref
);
161 cur
+= snprintf(cur
, end
- cur
, " count=%d", ev
->count
);
163 cur
+= usteer_event_log_node(cur
, end
- cur
, "", ev
->node_cur
);
164 if (ev
->select_reasons
) {
167 cur
+= snprintf(cur
, end
- cur
, " select_reason");
168 for (i
= 0; i
< ARRAY_SIZE(uev_select_reason
); i
++) {
169 if (!(ev
->select_reasons
& (1 << i
)) ||
170 !uev_select_reason
[i
])
173 cur
+= snprintf(cur
, end
- cur
, "%c%s", first
? '=' : ',',
174 uev_select_reason
[i
]);
178 if (ev
->node_other
) {
179 cur
+= snprintf(cur
, end
- cur
, " remote=%s", usteer_node_name(ev
->node_other
));
181 cur
+= snprintf(cur
, end
- cur
, " remote_signal=%d",
182 ev
->si_other
->signal
);
183 cur
+= usteer_event_log_node(cur
, end
- cur
, "remote_", ev
->node_other
);
189 void usteer_event(struct uevent
*ev
)
191 if (ev
->type
>= ARRAY_SIZE(uev_name
) || !uev_name
[ev
->type
])
194 if (ev
->reason
>= ARRAY_SIZE(uev_reason
) || !uev_reason
[ev
->reason
])
199 ev
->node_local
= ev
->si_cur
->node
;
201 ev
->sta
= ev
->si_cur
->sta
;
204 if (!ev
->node_local
&& ev
->node_cur
)
205 ev
->node_local
= ev
->node_cur
;
207 if (ev
->si_other
&& ev
->node_cur
&& !ev
->node_other
)
208 ev
->node_other
= ev
->si_other
->node
;
210 usteer_event_send_ubus(ev
);
211 usteer_event_log(ev
);
214 void config_set_event_log_types(struct blob_attr
*attr
)
216 struct blob_attr
*cur
;
219 config
.event_log_mask
= 0;
221 static const uint32_t default_log
[] = {
223 (1 << UEV_LOAD_KICK_CLIENT
) |
224 (1 << UEV_SIGNAL_KICK
) |
225 (1 << UEV_AUTH_REQ_DENY
) |
226 (1 << UEV_ASSOC_REQ_DENY
),
228 (1 << UEV_PROBE_REQ_DENY
),
230 (1 << UEV_AUTH_REQ_ACCEPT
) |
231 (1 << UEV_ASSOC_REQ_ACCEPT
) |
232 (1 << UEV_LOAD_KICK_TRIGGER
) |
233 (1 << UEV_LOAD_KICK_RESET
) |
234 (1 << UEV_LOAD_KICK_MIN_CLIENTS
) |
235 (1 << UEV_LOAD_KICK_NO_CLIENT
),
238 if (config
.debug_level
>= MSG_DEBUG_ALL
) {
239 config
.event_log_mask
= ~0;
243 for (i
= 0; i
< ARRAY_SIZE(default_log
) && i
<= config
.debug_level
; i
++)
244 config
.event_log_mask
|= default_log
[i
];
249 if (blobmsg_check_array(attr
, BLOBMSG_TYPE_STRING
) < 0)
252 blobmsg_for_each_attr(cur
, attr
, rem
) {
253 const char *name
= blobmsg_get_string(cur
);
255 for (i
= 0; i
< ARRAY_SIZE(uev_name
); i
++) {
256 if (!uev_name
[i
] || strcmp(uev_name
[i
], name
) != 0)
259 config
.event_log_mask
|= (1 << i
);
265 void config_get_event_log_types(struct blob_buf
*buf
)
267 uint32_t mask
= config
.event_log_mask
;
271 c
= blobmsg_open_array(buf
, "event_log_types");
272 for (i
= 0; mask
&& i
< ARRAY_SIZE(uev_name
); i
++) {
279 blobmsg_add_string(buf
, NULL
, uev_name
[i
]);
281 blobmsg_close_array(buf
, c
);