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>
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>
32 #define NO_SIGNAL 0xff
35 #define _STR(x) __STR(x)
37 #define APMGR_V6_MCAST_GROUP "ff02::4150"
39 #define APMGR_PORT 16720 /* AP */
40 #define APMGR_PORT_STR _STR(APMGR_PORT)
41 #define APMGR_BUFLEN (64 * 1024)
43 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
45 enum usteer_event_type
{
52 enum usteer_node_type
{
57 enum usteer_sta_connection_state
{
58 STA_NOT_CONNECTED
= 0,
63 enum usteer_beacon_measurement_mode
{
64 BEACON_MEASUREMENT_PASSIVE
= 0,
65 BEACON_MEASUREMENT_ACTIVE
= 1,
66 BEACON_MEASUREMENT_TABLE
= 2,
70 struct usteer_local_node
;
71 struct usteer_remote_host
;
75 struct list_head sta_info
;
76 struct list_head measurements
;
78 enum usteer_node_type type
;
80 struct blob_attr
*rrm_nr
;
81 struct blob_attr
*node_info
;
102 struct usteer_scan_request
{
109 struct usteer_scan_result
{
117 struct usteer_survey_data
{
125 struct usteer_freq_data
{
132 struct usteer_node_handler
{
133 struct list_head list
;
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
));
147 struct usteer_config
{
149 uint32_t debug_level
;
154 uint32_t sta_block_timeout
;
155 uint32_t local_sta_timeout
;
156 uint32_t local_sta_update
;
158 uint32_t max_retry_band
;
159 uint32_t seen_policy_timeout
;
160 uint32_t measurement_report_timeout
;
164 uint32_t max_neighbor_reports
;
166 uint32_t band_steering_threshold
;
167 uint32_t load_balancing_threshold
;
169 uint32_t remote_update_interval
;
170 uint32_t remote_node_timeout
;
173 uint32_t min_snr_kick_delay
;
174 int32_t min_connect_snr
;
175 uint32_t signal_diff_threshold
;
177 uint32_t steer_reject_timeout
;
179 int32_t roam_scan_snr
;
180 uint32_t roam_process_timeout
;
182 uint32_t roam_scan_tries
;
183 uint32_t roam_scan_timeout
;
184 uint32_t roam_scan_interval
;
186 int32_t roam_trigger_snr
;
187 uint32_t roam_trigger_interval
;
189 uint32_t roam_kick_delay
;
191 uint32_t band_steering_interval
;
192 int32_t band_steering_min_snr
;
194 uint32_t link_measurement_interval
;
196 uint32_t initial_connect_delay
;
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
;
204 const char *node_up_script
;
205 uint32_t event_log_mask
;
207 struct blob_attr
*ssid_list
;
210 struct usteer_bss_tm_query
{
211 struct list_head list
;
213 /* Can't use sta_info here, as the STA might already be deleted */
215 uint8_t dialog_token
;
218 struct sta_info_stats
{
220 uint32_t blocked_cur
;
221 uint32_t blocked_total
;
222 uint32_t blocked_last_time
;
225 enum roam_trigger_state
{
228 ROAM_TRIGGER_SCAN_DONE
,
232 struct list_head list
;
233 struct list_head node_list
;
235 struct usteer_node
*node
;
238 struct usteer_timeout timeout
;
240 struct sta_info_stats stats
[__EVENT_TYPE_MAX
];
243 uint64_t last_connected
;
249 enum roam_trigger_state roam_state
;
253 uint64_t roam_scan_start
;
254 uint64_t roam_scan_timeout_start
;
259 } bss_transition_response
;
269 uint32_t below_min_snr
;
271 uint8_t scan_band
: 1;
272 uint8_t connected
: 2;
277 struct list_head nodes
;
278 struct list_head measurements
;
280 uint8_t seen_2ghz
: 1;
281 uint8_t seen_5ghz
: 1;
286 struct usteer_measurement_report
{
287 struct usteer_timeout timeout
;
289 struct list_head list
;
291 struct usteer_node
*node
;
292 struct list_head node_list
;
295 struct list_head sta_list
;
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
;
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
);
317 int usteer_snr_to_signal(struct usteer_node
*node
, int snr
);
319 void usteer_local_nodes_init(struct ubus_context
*ctx
);
320 void usteer_local_node_kick(struct usteer_local_node
*ln
);
322 int usteer_local_node_get_beacon_interval(struct usteer_local_node
*ln
);
324 bool usteer_policy_node_below_max_assoc(struct usteer_node
*node
);
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
);
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_band_steering_request(struct sta_info
*si
);
334 int usteer_ubus_bss_transition_request(struct sta_info
*si
,
335 uint8_t dialog_token
,
336 bool disassoc_imminent
,
338 uint8_t validity_period
,
339 struct usteer_node
*target_node
);
341 struct sta
*usteer_sta_get(const uint8_t *addr
, bool create
);
342 struct sta_info
*usteer_sta_info_get(struct sta
*sta
, struct usteer_node
*node
, bool *create
);
344 bool usteer_sta_supports_beacon_measurement_mode(struct sta_info
*si
, enum usteer_beacon_measurement_mode mode
);
345 bool usteer_sta_supports_link_measurement(struct sta_info
*si
);
347 void usteer_sta_disconnected(struct sta_info
*si
);
348 void usteer_sta_info_update_timeout(struct sta_info
*si
, int timeout
);
349 void usteer_sta_info_update(struct sta_info
*si
, int signal
, bool avg
);
351 static inline const char *usteer_node_name(struct usteer_node
*node
)
353 return node
->avl
.key
;
355 void usteer_node_set_blob(struct blob_attr
**dest
, struct blob_attr
*val
);
357 struct usteer_local_node
*usteer_local_node_by_bssid(uint8_t *bssid
);
358 struct usteer_remote_node
*usteer_remote_node_by_bssid(uint8_t *bssid
);
359 struct usteer_node
*usteer_node_by_bssid(uint8_t *bssid
);
361 struct usteer_node
*usteer_node_get_next_neighbor(struct usteer_node
*current_node
, struct usteer_node
*last
);
362 bool usteer_check_request(struct sta_info
*si
, enum usteer_event_type type
);
364 void config_set_interfaces(struct blob_attr
*data
);
365 void config_get_interfaces(struct blob_buf
*buf
);
367 void config_set_node_up_script(struct blob_attr
*data
);
368 void config_get_node_up_script(struct blob_buf
*buf
);
370 void config_set_ssid_list(struct blob_attr
*data
);
371 void config_get_ssid_list(struct blob_buf
*buf
);
373 int usteer_interface_init(void);
374 void usteer_interface_add(const char *name
);
375 void usteer_sta_node_cleanup(struct usteer_node
*node
);
376 void usteer_send_sta_update(struct sta_info
*si
);
378 int usteer_lua_init(void);
379 int usteer_lua_ubus_init(void);
380 void usteer_run_hook(const char *name
, const char *arg
);
382 void usteer_dump_node(struct blob_buf
*buf
, struct usteer_node
*node
);
383 void usteer_dump_host(struct blob_buf
*buf
, struct usteer_remote_host
*host
);
385 struct usteer_measurement_report
* usteer_measurement_report_get(struct sta
*sta
, struct usteer_node
*node
, bool create
);
386 void usteer_measurement_report_node_cleanup(struct usteer_node
*node
);
387 void usteer_measurement_report_sta_cleanup(struct sta
*sta
);
388 void usteer_measurement_report_del(struct usteer_measurement_report
*mr
);
390 struct usteer_measurement_report
*
391 usteer_measurement_report_add(struct sta
*sta
, struct usteer_node
*node
, uint8_t rcpi
, uint8_t rsni
, uint64_t timestamp
);
394 int usteer_ubus_trigger_link_measurement(struct sta_info
*si
);