policy: only send preferred candidate with transition request
[project/usteer.git] / usteer.h
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
20 #ifndef __APMGR_H
21 #define __APMGR_H
22
23 #include <libubox/avl.h>
24 #include <libubox/blobmsg.h>
25 #include <libubox/uloop.h>
26 #include <libubox/utils.h>
27 #include <libubox/kvlist.h>
28 #include <libubus.h>
29 #include "utils.h"
30 #include "timeout.h"
31
32 #define NO_SIGNAL 0xff
33
34 #define __STR(x) #x
35 #define _STR(x) __STR(x)
36
37 #define APMGR_V6_MCAST_GROUP "ff02::4150"
38
39 #define APMGR_PORT 16720 /* AP */
40 #define APMGR_PORT_STR _STR(APMGR_PORT)
41 #define APMGR_BUFLEN (64 * 1024)
42
43 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
44
45 enum usteer_event_type {
46 EVENT_TYPE_PROBE,
47 EVENT_TYPE_ASSOC,
48 EVENT_TYPE_AUTH,
49 __EVENT_TYPE_MAX,
50 };
51
52 enum usteer_node_type {
53 NODE_TYPE_LOCAL,
54 NODE_TYPE_REMOTE,
55 };
56
57 enum usteer_sta_connection_state {
58 STA_NOT_CONNECTED = 0,
59 STA_CONNECTED = 1,
60 STA_DISCONNECTED = 2,
61 };
62
63 enum usteer_beacon_measurement_mode {
64 BEACON_MEASUREMENT_PASSIVE = 0,
65 BEACON_MEASUREMENT_ACTIVE = 1,
66 BEACON_MEASUREMENT_TABLE = 2,
67 };
68
69 struct sta_info;
70 struct usteer_local_node;
71 struct usteer_remote_host;
72
73 struct usteer_node {
74 struct avl_node avl;
75 struct list_head sta_info;
76 struct list_head measurements;
77
78 enum usteer_node_type type;
79
80 struct blob_attr *rrm_nr;
81 struct blob_attr *node_info;
82 char ssid[33];
83 uint8_t bssid[6];
84
85 bool disabled;
86 int freq;
87 int channel;
88 int op_class;
89 int noise;
90 int n_assoc;
91 int max_assoc;
92 int load;
93
94 struct {
95 int source;
96 int target;
97 } roam_events;
98
99 uint64_t created;
100 };
101
102 struct usteer_scan_request {
103 int n_freq;
104 int *freq;
105
106 bool passive;
107 };
108
109 struct usteer_scan_result {
110 uint8_t bssid[6];
111 char ssid[33];
112
113 int freq;
114 int signal;
115 };
116
117 struct usteer_survey_data {
118 uint16_t freq;
119 int8_t noise;
120
121 uint64_t time;
122 uint64_t time_busy;
123 };
124
125 struct usteer_freq_data {
126 uint16_t freq;
127
128 uint8_t txpower;
129 bool dfs;
130 };
131
132 struct usteer_node_handler {
133 struct list_head list;
134
135 void (*init_node)(struct usteer_node *);
136 void (*free_node)(struct usteer_node *);
137 void (*update_node)(struct usteer_node *);
138 void (*update_sta)(struct usteer_node *, struct sta_info *);
139 void (*get_survey)(struct usteer_node *, void *,
140 void (*cb)(void *priv, struct usteer_survey_data *d));
141 void (*get_freqlist)(struct usteer_node *, void *,
142 void (*cb)(void *priv, struct usteer_freq_data *f));
143 int (*scan)(struct usteer_node *, struct usteer_scan_request *,
144 void *, void (*cb)(void *priv, struct usteer_scan_result *r));
145 };
146
147 struct usteer_config {
148 bool syslog;
149 uint32_t debug_level;
150
151 bool ipv6;
152 bool local_mode;
153
154 uint32_t sta_block_timeout;
155 uint32_t local_sta_timeout;
156 uint32_t local_sta_update;
157
158 uint32_t max_retry_band;
159 uint32_t seen_policy_timeout;
160 uint32_t measurement_report_timeout;
161
162 bool assoc_steering;
163
164 uint32_t max_neighbor_reports;
165
166 uint32_t band_steering_threshold;
167 uint32_t load_balancing_threshold;
168
169 uint32_t remote_update_interval;
170 uint32_t remote_node_timeout;
171
172 int32_t min_snr;
173 uint32_t min_snr_kick_delay;
174 int32_t min_connect_snr;
175 uint32_t signal_diff_threshold;
176
177 uint32_t steer_reject_timeout;
178
179 int32_t roam_scan_snr;
180 uint32_t roam_process_timeout;
181
182 uint32_t roam_scan_tries;
183 uint32_t roam_scan_timeout;
184 uint32_t roam_scan_interval;
185
186 int32_t roam_trigger_snr;
187 uint32_t roam_trigger_interval;
188
189 uint32_t roam_kick_delay;
190
191 uint32_t band_steering_interval;
192 int32_t band_steering_min_snr;
193
194 uint32_t link_measurement_interval;
195
196 uint32_t initial_connect_delay;
197
198 bool load_kick_enabled;
199 uint32_t load_kick_threshold;
200 uint32_t load_kick_delay;
201 uint32_t load_kick_min_clients;
202 uint32_t load_kick_reason_code;
203
204 const char *node_up_script;
205 uint32_t event_log_mask;
206
207 struct blob_attr *ssid_list;
208 };
209
210 struct usteer_bss_tm_query {
211 struct list_head list;
212
213 /* Can't use sta_info here, as the STA might already be deleted */
214 uint8_t sta_addr[6];
215 uint8_t dialog_token;
216 };
217
218 struct sta_info_stats {
219 uint32_t requests;
220 uint32_t blocked_cur;
221 uint32_t blocked_total;
222 uint32_t blocked_last_time;
223 };
224
225 enum roam_trigger_state {
226 ROAM_TRIGGER_IDLE,
227 ROAM_TRIGGER_SCAN,
228 ROAM_TRIGGER_SCAN_DONE,
229 };
230
231 struct sta_info {
232 struct list_head list;
233 struct list_head node_list;
234
235 struct usteer_node *node;
236 struct sta *sta;
237
238 struct usteer_timeout timeout;
239
240 struct sta_info_stats stats[__EVENT_TYPE_MAX];
241 uint64_t created;
242 uint64_t seen;
243 uint64_t last_connected;
244 int signal;
245
246 uint8_t rrm;
247 bool bss_transition;
248
249 enum roam_trigger_state roam_state;
250 uint8_t roam_tries;
251 uint64_t roam_event;
252 uint64_t roam_kick;
253 uint64_t roam_scan_start;
254 uint64_t roam_scan_timeout_start;
255
256 struct {
257 uint8_t status_code;
258 uint64_t timestamp;
259 } bss_transition_response;
260
261 struct {
262 bool below_snr;
263 } band_steering;
264
265 uint64_t kick_time;
266
267 int kick_count;
268
269 uint32_t below_min_snr;
270
271 uint8_t scan_band : 1;
272 uint8_t connected : 2;
273 };
274
275 struct sta {
276 struct avl_node avl;
277 struct list_head nodes;
278 struct list_head measurements;
279
280 uint8_t seen_2ghz : 1;
281 uint8_t seen_5ghz : 1;
282
283 uint8_t addr[6];
284 };
285
286 struct usteer_measurement_report {
287 struct usteer_timeout timeout;
288
289 struct list_head list;
290
291 struct usteer_node *node;
292 struct list_head node_list;
293
294 struct sta *sta;
295 struct list_head sta_list;
296
297 uint64_t timestamp;
298
299 uint8_t rcpi;
300 uint8_t rsni;
301 };
302
303 extern struct ubus_context *ubus_ctx;
304 extern struct usteer_config config;
305 extern struct list_head node_handlers;
306 extern struct avl_tree stations;
307 extern struct ubus_object usteer_obj;
308 extern uint64_t current_time;
309 extern const char * const event_types[__EVENT_TYPE_MAX];
310 extern struct blob_attr *host_info_blob;
311
312 void usteer_update_time(void);
313 void usteer_init_defaults(void);
314 bool usteer_handle_sta_event(struct usteer_node *node, const uint8_t *addr,
315 enum usteer_event_type type, int freq, int signal);
316
317 int usteer_snr_to_signal(struct usteer_node *node, int snr);
318
319 void usteer_local_nodes_init(struct ubus_context *ctx);
320 void usteer_local_node_kick(struct usteer_local_node *ln);
321
322 int usteer_local_node_get_beacon_interval(struct usteer_local_node *ln);
323
324 bool usteer_policy_node_below_max_assoc(struct usteer_node *node);
325
326 void usteer_band_steering_perform_steer(struct usteer_local_node *ln);
327 void usteer_band_steering_sta_update(struct sta_info *si);
328 bool usteer_band_steering_is_target(struct usteer_local_node *ln, struct usteer_node *node);
329
330 void usteer_ubus_init(struct ubus_context *ctx);
331 void usteer_ubus_kick_client(struct sta_info *si);
332 int usteer_ubus_trigger_client_scan(struct sta_info *si);
333 int usteer_ubus_notify_client_disassoc(struct sta_info *si);
334 int usteer_ubus_band_steering_request(struct sta_info *si);
335 int usteer_ubus_bss_transition_request(struct sta_info *si,
336 uint8_t dialog_token,
337 bool disassoc_imminent,
338 bool abridged,
339 uint8_t validity_period,
340 struct usteer_node *target_node);
341
342 struct sta *usteer_sta_get(const uint8_t *addr, bool create);
343 struct sta_info *usteer_sta_info_get(struct sta *sta, struct usteer_node *node, bool *create);
344
345 bool usteer_sta_supports_beacon_measurement_mode(struct sta_info *si, enum usteer_beacon_measurement_mode mode);
346 bool usteer_sta_supports_link_measurement(struct sta_info *si);
347
348 void usteer_sta_disconnected(struct sta_info *si);
349 void usteer_sta_info_update_timeout(struct sta_info *si, int timeout);
350 void usteer_sta_info_update(struct sta_info *si, int signal, bool avg);
351
352 static inline const char *usteer_node_name(struct usteer_node *node)
353 {
354 return node->avl.key;
355 }
356 void usteer_node_set_blob(struct blob_attr **dest, struct blob_attr *val);
357
358 struct usteer_local_node *usteer_local_node_by_bssid(uint8_t *bssid);
359 struct usteer_remote_node *usteer_remote_node_by_bssid(uint8_t *bssid);
360 struct usteer_node *usteer_node_by_bssid(uint8_t *bssid);
361
362 struct usteer_node *usteer_node_get_next_neighbor(struct usteer_node *current_node, struct usteer_node *last);
363 bool usteer_check_request(struct sta_info *si, enum usteer_event_type type);
364
365 void config_set_interfaces(struct blob_attr *data);
366 void config_get_interfaces(struct blob_buf *buf);
367
368 void config_set_node_up_script(struct blob_attr *data);
369 void config_get_node_up_script(struct blob_buf *buf);
370
371 void config_set_ssid_list(struct blob_attr *data);
372 void config_get_ssid_list(struct blob_buf *buf);
373
374 int usteer_interface_init(void);
375 void usteer_interface_add(const char *name);
376 void usteer_sta_node_cleanup(struct usteer_node *node);
377 void usteer_send_sta_update(struct sta_info *si);
378
379 int usteer_lua_init(void);
380 int usteer_lua_ubus_init(void);
381 void usteer_run_hook(const char *name, const char *arg);
382
383 void usteer_dump_node(struct blob_buf *buf, struct usteer_node *node);
384 void usteer_dump_host(struct blob_buf *buf, struct usteer_remote_host *host);
385
386 struct usteer_measurement_report * usteer_measurement_report_get(struct sta *sta, struct usteer_node *node, bool create);
387 void usteer_measurement_report_node_cleanup(struct usteer_node *node);
388 void usteer_measurement_report_sta_cleanup(struct sta *sta);
389 void usteer_measurement_report_del(struct usteer_measurement_report *mr);
390
391 struct usteer_measurement_report *
392 usteer_measurement_report_add(struct sta *sta, struct usteer_node *node, uint8_t rcpi, uint8_t rsni, uint64_t timestamp);
393
394
395 int usteer_ubus_trigger_link_measurement(struct sta_info *si);
396 #endif