remote: close file on usteer_init_local_id fread fail
[project/usteer.git] / band_steering.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) 2022 David Bauer <mail@david-bauer.net>
16 */
17
18 #include "usteer.h"
19 #include "node.h"
20
21 void usteer_band_steering_sta_update(struct sta_info *si)
22 {
23 if (si->signal < usteer_snr_to_signal(si->node, config.band_steering_min_snr))
24 si->band_steering.below_snr = true;
25 }
26
27 bool usteer_band_steering_is_target(struct usteer_local_node *ln, struct usteer_node *node)
28 {
29 if (&ln->node == node)
30 return false;
31
32 if (strcmp(ln->node.ssid, node->ssid))
33 return false;
34
35 if (node->freq < 4000)
36 return false;
37
38 if (!usteer_policy_node_below_max_assoc(node))
39 return false;
40
41 /* ToDo: Skip nodes with active load-kick */
42
43 return true;
44 }
45
46
47 static bool usteer_band_steering_has_target_iface(struct usteer_local_node *ln)
48 {
49 struct usteer_node *node;
50
51 for_each_local_node(node) {
52 if (usteer_band_steering_is_target(ln, node))
53 return true;
54 }
55
56 return false;
57 }
58
59 void usteer_band_steering_perform_steer(struct usteer_local_node *ln)
60 {
61 unsigned int min_count = DIV_ROUND_UP(config.band_steering_interval, config.local_sta_update);
62 struct sta_info *si;
63
64 if (!config.band_steering_interval)
65 return;
66
67 /* Band-Steering is only available on 2.4 GHz interfaces */
68 if (ln->node.freq > 4000)
69 return;
70
71 /* Check if we have an interface we can steer to */
72 if (!usteer_band_steering_has_target_iface(ln))
73 return;
74
75 /* Only steer every interval */
76 if (ln->band_steering_interval < min_count) {
77 ln->band_steering_interval++;
78 return;
79 }
80
81 ln->band_steering_interval = 0;
82
83 list_for_each_entry(si, &ln->node.sta_info, node_list) {
84 /* Check if client is eligable to be steerd */
85 if (!usteer_policy_can_perform_roam(si))
86 continue;
87
88 /* Skip clients with insufficient SNR-state */
89 if (si->band_steering.below_snr) {
90 si->band_steering.below_snr = false;
91 continue;
92 }
93
94 if (si->bss_transition)
95 usteer_ubus_band_steering_request(si);
96
97 si->band_steering.below_snr = false;
98 }
99 }