54bcaeb2a5c4e827ed7bcf1dcc7217ac3e860863
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 avl_macaddr_cmp(const void *k1
, const void *k2
, void *ptr
)
25 return memcmp(k1
, k2
, 6);
28 AVL_TREE(stations
, avl_macaddr_cmp
, false, NULL
);
29 static struct usteer_timeout_queue tq
;
32 usteer_sta_del(struct sta
*sta
)
34 MSG(DEBUG
, "Delete station " MAC_ADDR_FMT
"\n",
35 MAC_ADDR_DATA(sta
->addr
));
37 avl_delete(&stations
, &sta
->avl
);
42 usteer_sta_info_del(struct sta_info
*si
)
44 struct sta
*sta
= si
->sta
;
46 MSG(DEBUG
, "Delete station " MAC_ADDR_FMT
" entry for node %s\n",
47 MAC_ADDR_DATA(sta
->addr
), usteer_node_name(si
->node
));
49 usteer_timeout_cancel(&tq
, &si
->timeout
);
51 list_del(&si
->node_list
);
54 if (list_empty(&sta
->nodes
))
59 usteer_sta_node_cleanup(struct usteer_node
*node
)
61 struct sta_info
*si
, *tmp
;
66 list_for_each_entry_safe(si
, tmp
, &node
->sta_info
, node_list
)
67 usteer_sta_info_del(si
);
71 usteer_sta_info_timeout(struct usteer_timeout_queue
*q
, struct usteer_timeout
*t
)
73 struct sta_info
*si
= container_of(t
, struct sta_info
, timeout
);
75 usteer_sta_info_del(si
);
79 usteer_sta_info_get(struct sta
*sta
, struct usteer_node
*node
, bool *create
)
83 list_for_each_entry(si
, &sta
->nodes
, list
) {
96 MSG(DEBUG
, "Create station " MAC_ADDR_FMT
" entry for node %s\n",
97 MAC_ADDR_DATA(sta
->addr
), usteer_node_name(node
));
99 si
= calloc(1, sizeof(*si
));
102 list_add(&si
->list
, &sta
->nodes
);
103 list_add(&si
->node_list
, &node
->sta_info
);
104 si
->created
= current_time
;
107 /* Node is by default not connected. */
108 si
->connected
= STA_NOT_CONNECTED
;
109 usteer_sta_info_update_timeout(si
, config
.local_sta_timeout
);
116 usteer_sta_info_update_timeout(struct sta_info
*si
, int timeout
)
118 if (si
->connected
== STA_CONNECTED
)
119 usteer_timeout_cancel(&tq
, &si
->timeout
);
120 else if (timeout
> 0)
121 usteer_timeout_set(&tq
, &si
->timeout
, timeout
);
123 usteer_sta_info_del(si
);
127 usteer_sta_get(const uint8_t *addr
, bool create
)
131 sta
= avl_find_element(&stations
, addr
, sta
, avl
);
138 MSG(DEBUG
, "Create station entry " MAC_ADDR_FMT
"\n", MAC_ADDR_DATA(addr
));
139 sta
= calloc(1, sizeof(*sta
));
140 memcpy(sta
->addr
, addr
, sizeof(sta
->addr
));
141 sta
->avl
.key
= sta
->addr
;
142 avl_insert(&stations
, &sta
->avl
);
143 INIT_LIST_HEAD(&sta
->nodes
);
149 usteer_sta_info_update(struct sta_info
*si
, int signal
, bool avg
)
151 /* ignore probe request signal when connected */
152 if (si
->connected
== STA_CONNECTED
&& si
->signal
!= NO_SIGNAL
&& !avg
)
155 if (signal
!= NO_SIGNAL
)
158 si
->seen
= current_time
;
159 usteer_sta_info_update_timeout(si
, config
.local_sta_timeout
);
163 usteer_handle_sta_event(struct usteer_node
*node
, const uint8_t *addr
,
164 enum usteer_event_type type
, int freq
, int signal
)
172 sta
= usteer_sta_get(addr
, true);
181 si
= usteer_sta_info_get(sta
, node
, &create
);
182 usteer_sta_info_update(si
, signal
, false);
183 si
->roam_scan_done
= current_time
;
184 si
->stats
[type
].requests
++;
186 diff
= si
->stats
[type
].blocked_last_time
- current_time
;
187 if (diff
> config
.sta_block_timeout
)
188 si
->stats
[type
].blocked_cur
= 0;
190 ret
= usteer_check_request(si
, type
);
192 si
->stats
[type
].blocked_cur
++;
193 si
->stats
[type
].blocked_total
++;
194 si
->stats
[type
].blocked_last_time
= current_time
;
196 si
->stats
[type
].blocked_cur
= 0;
200 usteer_send_sta_update(si
);
205 static void __usteer_init
usteer_sta_init(void)
207 usteer_timeout_init(&tq
);
208 tq
.cb
= usteer_sta_info_timeout
;