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