• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/usteer/event.c

  1 /*
  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.
  5  *
  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.
 10  *
 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.
 14  *
 15  *   Copyright (C) 2020 embedd.ch 
 16  *   Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> 
 17  *   Copyright (C) 2020 John Crispin <john@phrozen.org> 
 18  */
 19 #include "usteer.h"
 20 #include "event.h"
 21 
 22 #define UEV_LOG_MAXLEN  256
 23 
 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",
 38 
 39 };
 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",
 46 };
 47 
 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",
 52 };
 53 
 54 static void
 55 usteer_event_add_node_status(struct usteer_node *node)
 56 {
 57         blobmsg_add_u32(&b, "load", node->load);
 58         blobmsg_add_u32(&b, "assoc", node->n_assoc);
 59 }
 60 
 61 static void
 62 usteer_event_send_ubus(struct uevent *ev)
 63 {
 64         void *c;
 65         int i;
 66 
 67         if (!usteer_obj.has_subscribers)
 68                 return;
 69 
 70         blob_buf_init(&b, 0);
 71 
 72         if (ev->node_local)
 73                 blobmsg_add_string(&b, "node", usteer_node_name(ev->node_local));
 74 
 75         if (ev->sta)
 76                 blobmsg_printf(&b, "sta", MAC_ADDR_FMT, MAC_ADDR_DATA(ev->sta->addr));
 77 
 78         if (ev->si_cur)
 79                 blobmsg_add_u32(&b, "signal", (int32_t)ev->si_cur->signal);
 80 
 81         if (ev->reason)
 82                 blobmsg_add_string(&b, "reason", uev_reason[ev->reason]);
 83 
 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);
 89         }
 90 
 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])
 96                                 continue;
 97 
 98                         blobmsg_add_string(&b, NULL, uev_select_reason[i]);
 99                 }
100                 blobmsg_close_array(&b, c);
101         }
102 
103         if (ev->node_cur) {
104                 c = blobmsg_open_table(&b, "local");
105                 usteer_event_add_node_status(ev->node_cur);
106                 blobmsg_close_table(&b, c);
107         }
108 
109         if (ev->node_other) {
110                 c = blobmsg_open_table(&b, "remote");
111                 blobmsg_add_string(&b, "name", usteer_node_name(ev->node_other));
112                 if (ev->si_other)
113                         blobmsg_add_u32(&b, "signal", (int32_t)ev->si_other->signal);
114                 usteer_event_add_node_status(ev->node_other);
115                 blobmsg_close_table(&b, c);
116         }
117 
118         if (ev->count)
119                 blobmsg_add_u32(&b, "count", ev->count);
120 
121         ubus_notify(ubus_ctx, &usteer_obj, uev_name[ev->type], b.head, -1);
122 }
123 
124 static int
125 usteer_event_log_node(char *buf, int len, const char *prefix, struct usteer_node *node)
126 {
127         char *cur = buf;
128         char *end = buf + len;
129 
130         cur += snprintf(cur, end - cur, " %sassoc=%d %sload=%d",
131                         prefix, node->n_assoc,
132                         prefix, node->load);
133 
134         return cur - buf;
135 }
136 
137 static void
138 usteer_event_log(struct uevent *ev)
139 {
140         char *str, *cur, *end;
141         int i;
142 
143         if (!(config.event_log_mask & (1 << ev->type)))
144                 return;
145 
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]);
150         if (ev->node_local)
151                 cur += snprintf(cur, end - cur, " node=%s", usteer_node_name(ev->node_local));
152         if (ev->sta)
153                 cur += snprintf(cur, end - cur, " sta=" MAC_ADDR_FMT, MAC_ADDR_DATA(ev->sta->addr));
154         if (ev->reason)
155                 cur += snprintf(cur, end - cur, " reason=%s", uev_reason[ev->reason]);
156         if (ev->si_cur)
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);
160         if (ev->count)
161                 cur += snprintf(cur, end - cur, " count=%d", ev->count);
162         if (ev->node_cur)
163                 cur += usteer_event_log_node(cur, end - cur, "", ev->node_cur);
164         if (ev->select_reasons) {
165                 bool first = true;
166 
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])
171                                 continue;
172 
173                         cur += snprintf(cur, end - cur, "%c%s", first ? '=' : ',',
174                                                     uev_select_reason[i]);
175                         first = false;
176                 }
177         }
178         if (ev->node_other) {
179                 cur += snprintf(cur, end - cur, " remote=%s", usteer_node_name(ev->node_other));
180                 if (ev->si_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);
184         }
185 
186         log_msg(str);
187 }
188 
189 void usteer_event(struct uevent *ev)
190 {
191         if (ev->type >= ARRAY_SIZE(uev_name) || !uev_name[ev->type])
192                 return;
193 
194         if (ev->reason >= ARRAY_SIZE(uev_reason) || !uev_reason[ev->reason])
195                 return;
196 
197         if (ev->si_cur) {
198                 if (!ev->node_local)
199                         ev->node_local = ev->si_cur->node;
200                 if (!ev->sta)
201                         ev->sta = ev->si_cur->sta;
202         }
203 
204         if (!ev->node_local && ev->node_cur)
205                 ev->node_local = ev->node_cur;
206 
207         if (ev->si_other && ev->node_cur && !ev->node_other)
208                 ev->node_other = ev->si_other->node;
209 
210         usteer_event_send_ubus(ev);
211         usteer_event_log(ev);
212 }
213 
214 void config_set_event_log_types(struct blob_attr *attr)
215 {
216         struct blob_attr *cur;
217         int i, rem;
218 
219         config.event_log_mask = 0;
220         if (!attr) {
221                 static const uint32_t default_log[] = {
222                         [MSG_INFO] =
223                                 (1 << UEV_LOAD_KICK_CLIENT) |
224                                 (1 << UEV_SIGNAL_KICK) |
225                                 (1 << UEV_AUTH_REQ_DENY) |
226                                 (1 << UEV_ASSOC_REQ_DENY),
227                         [MSG_VERBOSE] =
228                                 (1 << UEV_PROBE_REQ_DENY),
229                         [MSG_DEBUG] =
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),
236                 };
237 
238                 if (config.debug_level >= MSG_DEBUG_ALL) {
239                         config.event_log_mask = ~0;
240                         return;
241                 }
242 
243                 for (i = 0; i < ARRAY_SIZE(default_log) && i <= config.debug_level; i++)
244                         config.event_log_mask |= default_log[i];
245 
246                 return;
247         }
248 
249         if (blobmsg_check_array(attr, BLOBMSG_TYPE_STRING) < 0)
250                 return;
251 
252         blobmsg_for_each_attr(cur, attr, rem) {
253                 const char *name = blobmsg_get_string(cur);
254 
255                 for (i = 0; i < ARRAY_SIZE(uev_name); i++) {
256                         if (!uev_name[i] || strcmp(uev_name[i], name) != 0)
257                                 continue;
258 
259                         config.event_log_mask |= (1 << i);
260                         break;
261                 }
262         }
263 }
264 
265 void config_get_event_log_types(struct blob_buf *buf)
266 {
267         uint32_t mask = config.event_log_mask;
268         void *c;
269         int i;
270 
271         c = blobmsg_open_array(buf, "event_log_types");
272         for (i = 0; mask && i < ARRAY_SIZE(uev_name); i++) {
273                 bool cur = mask & 1;
274 
275                 mask >>= 1;
276                 if (!cur)
277                         continue;
278 
279                 blobmsg_add_string(buf, NULL, uev_name[i]);
280         }
281         blobmsg_close_array(buf, c);
282 }
283 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt