Blame view
net/batman-adv/translation-table.c
73.9 KB
0b8739314 batman-adv: updat... |
1 |
/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: |
c6c8fea29 net: Add batman-a... |
2 |
* |
35c133a00 batman-adv: add c... |
3 |
* Marek Lindner, Simon Wunderlich, Antonio Quartulli |
c6c8fea29 net: Add batman-a... |
4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
* * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA |
c6c8fea29 net: Add batman-a... |
18 19 20 21 22 |
*/ #include "main.h" #include "translation-table.h" #include "soft-interface.h" |
32ae9b221 batman-adv: Make ... |
23 |
#include "hard-interface.h" |
a73105b8d batman-adv: impro... |
24 |
#include "send.h" |
c6c8fea29 net: Add batman-a... |
25 26 |
#include "hash.h" #include "originator.h" |
a73105b8d batman-adv: impro... |
27 |
#include "routing.h" |
20ff9d593 batman-adv: don't... |
28 |
#include "bridge_loop_avoidance.h" |
c6c8fea29 net: Add batman-a... |
29 |
|
a73105b8d batman-adv: impro... |
30 |
#include <linux/crc16.h> |
dec05074b batman-adv: Initi... |
31 32 33 |
/* hash class keys */ static struct lock_class_key batadv_tt_local_hash_lock_class_key; static struct lock_class_key batadv_tt_global_hash_lock_class_key; |
56303d34a batman-adv: Prefi... |
34 35 |
static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, struct batadv_orig_node *orig_node); |
a513088d0 batman-adv: Prefi... |
36 37 |
static void batadv_tt_purge(struct work_struct *work); static void |
56303d34a batman-adv: Prefi... |
38 |
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry); |
30cfd02b6 batman-adv: detec... |
39 40 41 42 |
static void batadv_tt_global_del(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, const unsigned char *addr, const char *message, bool roaming); |
c6c8fea29 net: Add batman-a... |
43 |
|
7aadf889e batman-adv: remov... |
44 |
/* returns 1 if they are the same mac addr */ |
a513088d0 batman-adv: Prefi... |
45 |
static int batadv_compare_tt(const struct hlist_node *node, const void *data2) |
7aadf889e batman-adv: remov... |
46 |
{ |
56303d34a batman-adv: Prefi... |
47 |
const void *data1 = container_of(node, struct batadv_tt_common_entry, |
747e4221a batman-adv: Add c... |
48 |
hash_entry); |
7aadf889e batman-adv: remov... |
49 50 51 |
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); } |
56303d34a batman-adv: Prefi... |
52 |
static struct batadv_tt_common_entry * |
5bf74e9ca batman-adv: Prefi... |
53 |
batadv_tt_hash_find(struct batadv_hashtable *hash, const void *data) |
7aadf889e batman-adv: remov... |
54 |
{ |
7aadf889e batman-adv: remov... |
55 |
struct hlist_head *head; |
56303d34a batman-adv: Prefi... |
56 57 |
struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_common_entry *tt_common_entry_tmp = NULL; |
c90681b85 batman-adv: fixed... |
58 |
uint32_t index; |
7aadf889e batman-adv: remov... |
59 60 61 |
if (!hash) return NULL; |
da641193d batman-adv: Prefi... |
62 |
index = batadv_choose_orig(data, hash->size); |
7aadf889e batman-adv: remov... |
63 64 65 |
head = &hash->table[index]; rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
66 |
hlist_for_each_entry_rcu(tt_common_entry, head, hash_entry) { |
1eda58bfc batman-adv: Prefi... |
67 |
if (!batadv_compare_eth(tt_common_entry, data)) |
7aadf889e batman-adv: remov... |
68 |
continue; |
48100bac8 batman-adv: creat... |
69 |
if (!atomic_inc_not_zero(&tt_common_entry->refcount)) |
7683fdc1e batman-adv: prote... |
70 |
continue; |
48100bac8 batman-adv: creat... |
71 |
tt_common_entry_tmp = tt_common_entry; |
7aadf889e batman-adv: remov... |
72 73 74 |
break; } rcu_read_unlock(); |
48100bac8 batman-adv: creat... |
75 |
return tt_common_entry_tmp; |
7aadf889e batman-adv: remov... |
76 |
} |
56303d34a batman-adv: Prefi... |
77 78 |
static struct batadv_tt_local_entry * batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data) |
7aadf889e batman-adv: remov... |
79 |
{ |
56303d34a batman-adv: Prefi... |
80 81 |
struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_local_entry *tt_local_entry = NULL; |
7aadf889e batman-adv: remov... |
82 |
|
807736f6e batman-adv: Split... |
83 |
tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data); |
48100bac8 batman-adv: creat... |
84 85 |
if (tt_common_entry) tt_local_entry = container_of(tt_common_entry, |
56303d34a batman-adv: Prefi... |
86 87 |
struct batadv_tt_local_entry, common); |
48100bac8 batman-adv: creat... |
88 89 |
return tt_local_entry; } |
7aadf889e batman-adv: remov... |
90 |
|
56303d34a batman-adv: Prefi... |
91 92 |
static struct batadv_tt_global_entry * batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data) |
48100bac8 batman-adv: creat... |
93 |
{ |
56303d34a batman-adv: Prefi... |
94 95 |
struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_global_entry *tt_global_entry = NULL; |
7683fdc1e batman-adv: prote... |
96 |
|
807736f6e batman-adv: Split... |
97 |
tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data); |
48100bac8 batman-adv: creat... |
98 99 |
if (tt_common_entry) tt_global_entry = container_of(tt_common_entry, |
56303d34a batman-adv: Prefi... |
100 101 |
struct batadv_tt_global_entry, common); |
48100bac8 batman-adv: creat... |
102 |
return tt_global_entry; |
7aadf889e batman-adv: remov... |
103 |
} |
a513088d0 batman-adv: Prefi... |
104 |
static void |
56303d34a batman-adv: Prefi... |
105 |
batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry) |
7683fdc1e batman-adv: prote... |
106 |
{ |
48100bac8 batman-adv: creat... |
107 108 |
if (atomic_dec_and_test(&tt_local_entry->common.refcount)) kfree_rcu(tt_local_entry, common.rcu); |
7683fdc1e batman-adv: prote... |
109 |
} |
a513088d0 batman-adv: Prefi... |
110 |
static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu) |
531027fcd batman-adv: remov... |
111 |
{ |
56303d34a batman-adv: Prefi... |
112 113 |
struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_global_entry *tt_global_entry; |
531027fcd batman-adv: remov... |
114 |
|
56303d34a batman-adv: Prefi... |
115 116 117 |
tt_common_entry = container_of(rcu, struct batadv_tt_common_entry, rcu); tt_global_entry = container_of(tt_common_entry, struct batadv_tt_global_entry, common); |
531027fcd batman-adv: remov... |
118 |
|
531027fcd batman-adv: remov... |
119 120 |
kfree(tt_global_entry); } |
a513088d0 batman-adv: Prefi... |
121 |
static void |
56303d34a batman-adv: Prefi... |
122 |
batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry) |
7683fdc1e batman-adv: prote... |
123 |
{ |
db08e6e55 batman-adv: allow... |
124 |
if (atomic_dec_and_test(&tt_global_entry->common.refcount)) { |
a513088d0 batman-adv: Prefi... |
125 |
batadv_tt_global_del_orig_list(tt_global_entry); |
48100bac8 batman-adv: creat... |
126 |
call_rcu(&tt_global_entry->common.rcu, |
a513088d0 batman-adv: Prefi... |
127 |
batadv_tt_global_entry_free_rcu); |
db08e6e55 batman-adv: allow... |
128 129 |
} } |
a513088d0 batman-adv: Prefi... |
130 |
static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) |
db08e6e55 batman-adv: allow... |
131 |
{ |
56303d34a batman-adv: Prefi... |
132 |
struct batadv_tt_orig_list_entry *orig_entry; |
db08e6e55 batman-adv: allow... |
133 |
|
56303d34a batman-adv: Prefi... |
134 |
orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu); |
72822225b batman-adv: Fix r... |
135 136 137 138 139 140 |
/* We are in an rcu callback here, therefore we cannot use * batadv_orig_node_free_ref() and its call_rcu(): * An rcu_barrier() wouldn't wait for that to finish */ batadv_orig_node_free_ref_now(orig_entry->orig_node); |
db08e6e55 batman-adv: allow... |
141 142 |
kfree(orig_entry); } |
a513088d0 batman-adv: Prefi... |
143 |
static void |
56303d34a batman-adv: Prefi... |
144 |
batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) |
db08e6e55 batman-adv: allow... |
145 |
{ |
d657e621a batman-adv: add r... |
146 147 |
if (!atomic_dec_and_test(&orig_entry->refcount)) return; |
29cb99de4 batman-adv: fix g... |
148 149 |
/* to avoid race conditions, immediately decrease the tt counter */ atomic_dec(&orig_entry->orig_node->tt_size); |
a513088d0 batman-adv: Prefi... |
150 |
call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); |
7683fdc1e batman-adv: prote... |
151 |
} |
56303d34a batman-adv: Prefi... |
152 |
static void batadv_tt_local_event(struct batadv_priv *bat_priv, |
a513088d0 batman-adv: Prefi... |
153 |
const uint8_t *addr, uint8_t flags) |
a73105b8d batman-adv: impro... |
154 |
{ |
56303d34a batman-adv: Prefi... |
155 |
struct batadv_tt_change_node *tt_change_node, *entry, *safe; |
3b643de54 batman-adv: clear... |
156 157 |
bool event_removed = false; bool del_op_requested, del_op_entry; |
a73105b8d batman-adv: impro... |
158 159 160 161 162 |
tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC); if (!tt_change_node) return; |
ff66c975d batman-adv: pass ... |
163 |
tt_change_node->change.flags = flags; |
a73105b8d batman-adv: impro... |
164 |
memcpy(tt_change_node->change.addr, addr, ETH_ALEN); |
acd34afa8 batman-adv: Prefi... |
165 |
del_op_requested = flags & BATADV_TT_CLIENT_DEL; |
3b643de54 batman-adv: clear... |
166 167 |
/* check for ADD+DEL or DEL+ADD events */ |
807736f6e batman-adv: Split... |
168 169 |
spin_lock_bh(&bat_priv->tt.changes_list_lock); list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, |
3b643de54 batman-adv: clear... |
170 171 172 173 174 175 176 177 178 179 180 |
list) { if (!batadv_compare_eth(entry->change.addr, addr)) continue; /* DEL+ADD in the same orig interval have no effect and can be * removed to avoid silly behaviour on the receiver side. The * other way around (ADD+DEL) can happen in case of roaming of * a client still in the NEW state. Roaming of NEW clients is * now possible due to automatically recognition of "temporary" * clients */ |
acd34afa8 batman-adv: Prefi... |
181 |
del_op_entry = entry->change.flags & BATADV_TT_CLIENT_DEL; |
3b643de54 batman-adv: clear... |
182 183 184 185 186 187 188 189 |
if (!del_op_requested && del_op_entry) goto del; if (del_op_requested && !del_op_entry) goto del; continue; del: list_del(&entry->list); kfree(entry); |
155e4e12b batman-adv: Fix m... |
190 |
kfree(tt_change_node); |
3b643de54 batman-adv: clear... |
191 192 193 |
event_removed = true; goto unlock; } |
a73105b8d batman-adv: impro... |
194 |
/* track the change in the OGMinterval list */ |
807736f6e batman-adv: Split... |
195 |
list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list); |
3b643de54 batman-adv: clear... |
196 197 |
unlock: |
807736f6e batman-adv: Split... |
198 |
spin_unlock_bh(&bat_priv->tt.changes_list_lock); |
a73105b8d batman-adv: impro... |
199 |
|
3b643de54 batman-adv: clear... |
200 |
if (event_removed) |
807736f6e batman-adv: Split... |
201 |
atomic_dec(&bat_priv->tt.local_changes); |
3b643de54 batman-adv: clear... |
202 |
else |
807736f6e batman-adv: Split... |
203 |
atomic_inc(&bat_priv->tt.local_changes); |
a73105b8d batman-adv: impro... |
204 |
} |
08c36d3e8 batman-adv: Prefi... |
205 |
int batadv_tt_len(int changes_num) |
a73105b8d batman-adv: impro... |
206 |
{ |
964126901 batman-adv: Prefi... |
207 |
return changes_num * sizeof(struct batadv_tt_change); |
a73105b8d batman-adv: impro... |
208 |
} |
56303d34a batman-adv: Prefi... |
209 |
static int batadv_tt_local_init(struct batadv_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
210 |
{ |
807736f6e batman-adv: Split... |
211 |
if (bat_priv->tt.local_hash) |
5346c35eb batman-adv: Retur... |
212 |
return 0; |
c6c8fea29 net: Add batman-a... |
213 |
|
807736f6e batman-adv: Split... |
214 |
bat_priv->tt.local_hash = batadv_hash_new(1024); |
c6c8fea29 net: Add batman-a... |
215 |
|
807736f6e batman-adv: Split... |
216 |
if (!bat_priv->tt.local_hash) |
5346c35eb batman-adv: Retur... |
217 |
return -ENOMEM; |
c6c8fea29 net: Add batman-a... |
218 |
|
dec05074b batman-adv: Initi... |
219 220 |
batadv_hash_set_lock_class(bat_priv->tt.local_hash, &batadv_tt_local_hash_lock_class_key); |
5346c35eb batman-adv: Retur... |
221 |
return 0; |
c6c8fea29 net: Add batman-a... |
222 |
} |
068ee6e20 batman-adv: roami... |
223 224 225 226 227 228 229 230 231 232 233 234 |
static void batadv_tt_global_free(struct batadv_priv *bat_priv, struct batadv_tt_global_entry *tt_global, const char *message) { batadv_dbg(BATADV_DBG_TT, bat_priv, "Deleting global tt entry %pM: %s ", tt_global->common.addr, message); batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, batadv_choose_orig, tt_global->common.addr); batadv_tt_global_entry_free_ref(tt_global); |
068ee6e20 batman-adv: roami... |
235 |
} |
08c36d3e8 batman-adv: Prefi... |
236 237 |
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, int ifindex) |
c6c8fea29 net: Add batman-a... |
238 |
{ |
56303d34a batman-adv: Prefi... |
239 |
struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
170173bf3 batman-adv: Remov... |
240 241 |
struct batadv_tt_local_entry *tt_local; struct batadv_tt_global_entry *tt_global; |
db08e6e55 batman-adv: allow... |
242 |
struct hlist_head *head; |
56303d34a batman-adv: Prefi... |
243 |
struct batadv_tt_orig_list_entry *orig_entry; |
80b3f58cf batman-adv: check... |
244 |
int hash_added; |
068ee6e20 batman-adv: roami... |
245 |
bool roamed_back = false; |
c6c8fea29 net: Add batman-a... |
246 |
|
47c94655c batman-adv: refac... |
247 |
tt_local = batadv_tt_local_hash_find(bat_priv, addr); |
068ee6e20 batman-adv: roami... |
248 |
tt_global = batadv_tt_global_hash_find(bat_priv, addr); |
c6c8fea29 net: Add batman-a... |
249 |
|
47c94655c batman-adv: refac... |
250 251 |
if (tt_local) { tt_local->last_seen = jiffies; |
068ee6e20 batman-adv: roami... |
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) { batadv_dbg(BATADV_DBG_TT, bat_priv, "Re-adding pending client %pM ", addr); /* whatever the reason why the PENDING flag was set, * this is a client which was enqueued to be removed in * this orig_interval. Since it popped up again, the * flag can be reset like it was never enqueued */ tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING; goto add_event; } if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) { batadv_dbg(BATADV_DBG_TT, bat_priv, "Roaming client %pM came back to its original location ", addr); /* the ROAM flag is set because this client roamed away * and the node got a roaming_advertisement message. Now * that the client popped up again at its original * location such flag can be unset */ tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM; roamed_back = true; } goto check_roaming; |
c6c8fea29 net: Add batman-a... |
279 |
} |
47c94655c batman-adv: refac... |
280 281 |
tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC); if (!tt_local) |
7683fdc1e batman-adv: prote... |
282 |
goto out; |
a73105b8d batman-adv: impro... |
283 |
|
39c75a51e batman-adv: Prefi... |
284 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
285 286 |
"Creating new local tt entry: %pM (ttvn: %d) ", addr, |
807736f6e batman-adv: Split... |
287 |
(uint8_t)atomic_read(&bat_priv->tt.vn)); |
c6c8fea29 net: Add batman-a... |
288 |
|
47c94655c batman-adv: refac... |
289 |
memcpy(tt_local->common.addr, addr, ETH_ALEN); |
8425ec6ae batman-adv: remov... |
290 291 292 293 294 |
/* The local entry has to be marked as NEW to avoid to send it in * a full table response going out before the next ttvn increment * (consistency check) */ tt_local->common.flags = BATADV_TT_CLIENT_NEW; |
9563877ea batman-adv: Prefi... |
295 |
if (batadv_is_wifi_iface(ifindex)) |
47c94655c batman-adv: refac... |
296 297 298 299 |
tt_local->common.flags |= BATADV_TT_CLIENT_WIFI; atomic_set(&tt_local->common.refcount, 2); tt_local->last_seen = jiffies; tt_local->common.added_at = tt_local->last_seen; |
c6c8fea29 net: Add batman-a... |
300 301 |
/* the batman interface mac address should never be purged */ |
1eda58bfc batman-adv: Prefi... |
302 |
if (batadv_compare_eth(addr, soft_iface->dev_addr)) |
47c94655c batman-adv: refac... |
303 |
tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE; |
c6c8fea29 net: Add batman-a... |
304 |
|
807736f6e batman-adv: Split... |
305 |
hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, |
47c94655c batman-adv: refac... |
306 307 |
batadv_choose_orig, &tt_local->common, &tt_local->common.hash_entry); |
80b3f58cf batman-adv: check... |
308 309 310 |
if (unlikely(hash_added != 0)) { /* remove the reference for the hash */ |
47c94655c batman-adv: refac... |
311 |
batadv_tt_local_entry_free_ref(tt_local); |
80b3f58cf batman-adv: check... |
312 313 |
goto out; } |
068ee6e20 batman-adv: roami... |
314 |
add_event: |
47c94655c batman-adv: refac... |
315 |
batadv_tt_local_event(bat_priv, addr, tt_local->common.flags); |
ff66c975d batman-adv: pass ... |
316 |
|
068ee6e20 batman-adv: roami... |
317 318 319 320 321 |
check_roaming: /* Check whether it is a roaming, but don't do anything if the roaming * process has already been handled */ if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) { |
db08e6e55 batman-adv: allow... |
322 |
/* These node are probably going to update their tt table */ |
47c94655c batman-adv: refac... |
323 |
head = &tt_global->orig_list; |
db08e6e55 batman-adv: allow... |
324 |
rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
325 |
hlist_for_each_entry_rcu(orig_entry, head, list) { |
47c94655c batman-adv: refac... |
326 |
batadv_send_roam_adv(bat_priv, tt_global->common.addr, |
a513088d0 batman-adv: Prefi... |
327 |
orig_entry->orig_node); |
db08e6e55 batman-adv: allow... |
328 329 |
} rcu_read_unlock(); |
068ee6e20 batman-adv: roami... |
330 331 332 333 334 335 336 337 338 339 340 |
if (roamed_back) { batadv_tt_global_free(bat_priv, tt_global, "Roaming canceled"); tt_global = NULL; } else { /* The global entry has to be marked as ROAMING and * has to be kept for consistency purpose */ tt_global->common.flags |= BATADV_TT_CLIENT_ROAM; tt_global->roam_at = jiffies; } |
7683fdc1e batman-adv: prote... |
341 |
} |
068ee6e20 batman-adv: roami... |
342 |
|
7683fdc1e batman-adv: prote... |
343 |
out: |
47c94655c batman-adv: refac... |
344 345 346 347 |
if (tt_local) batadv_tt_local_entry_free_ref(tt_local); if (tt_global) batadv_tt_global_entry_free_ref(tt_global); |
c6c8fea29 net: Add batman-a... |
348 |
} |
a513088d0 batman-adv: Prefi... |
349 350 351 352 |
static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff, int *packet_buff_len, int min_packet_len, int new_packet_len) |
be9aa4c1e batman-adv: turn ... |
353 354 355 356 357 358 359 360 361 362 363 364 365 |
{ unsigned char *new_buff; new_buff = kmalloc(new_packet_len, GFP_ATOMIC); /* keep old buffer if kmalloc should fail */ if (new_buff) { memcpy(new_buff, *packet_buff, min_packet_len); kfree(*packet_buff); *packet_buff = new_buff; *packet_buff_len = new_packet_len; } } |
56303d34a batman-adv: Prefi... |
366 |
static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv, |
a513088d0 batman-adv: Prefi... |
367 368 369 |
unsigned char **packet_buff, int *packet_buff_len, int min_packet_len) |
be9aa4c1e batman-adv: turn ... |
370 |
{ |
be9aa4c1e batman-adv: turn ... |
371 |
int req_len; |
be9aa4c1e batman-adv: turn ... |
372 |
req_len = min_packet_len; |
807736f6e batman-adv: Split... |
373 |
req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes)); |
be9aa4c1e batman-adv: turn ... |
374 375 376 377 |
/* if we have too many changes for one packet don't send any * and wait for the tt table request which will be fragmented */ |
736292c2e batman-adv: repla... |
378 |
if (req_len > bat_priv->soft_iface->mtu) |
be9aa4c1e batman-adv: turn ... |
379 |
req_len = min_packet_len; |
a513088d0 batman-adv: Prefi... |
380 381 |
batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, min_packet_len, req_len); |
be9aa4c1e batman-adv: turn ... |
382 |
} |
56303d34a batman-adv: Prefi... |
383 |
static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv, |
a513088d0 batman-adv: Prefi... |
384 385 386 |
unsigned char **packet_buff, int *packet_buff_len, int min_packet_len) |
c6c8fea29 net: Add batman-a... |
387 |
{ |
56303d34a batman-adv: Prefi... |
388 |
struct batadv_tt_change_node *entry, *safe; |
be9aa4c1e batman-adv: turn ... |
389 390 |
int count = 0, tot_changes = 0, new_len; unsigned char *tt_buff; |
a513088d0 batman-adv: Prefi... |
391 392 |
batadv_tt_prepare_packet_buff(bat_priv, packet_buff, packet_buff_len, min_packet_len); |
c6c8fea29 net: Add batman-a... |
393 |
|
be9aa4c1e batman-adv: turn ... |
394 395 396 397 |
new_len = *packet_buff_len - min_packet_len; tt_buff = *packet_buff + min_packet_len; if (new_len > 0) |
08c36d3e8 batman-adv: Prefi... |
398 |
tot_changes = new_len / batadv_tt_len(1); |
c6c8fea29 net: Add batman-a... |
399 |
|
807736f6e batman-adv: Split... |
400 401 |
spin_lock_bh(&bat_priv->tt.changes_list_lock); atomic_set(&bat_priv->tt.local_changes, 0); |
c6c8fea29 net: Add batman-a... |
402 |
|
807736f6e batman-adv: Split... |
403 |
list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, |
7c64fd98c batman-adv: Fix i... |
404 |
list) { |
a73105b8d batman-adv: impro... |
405 |
if (count < tot_changes) { |
08c36d3e8 batman-adv: Prefi... |
406 |
memcpy(tt_buff + batadv_tt_len(count), |
964126901 batman-adv: Prefi... |
407 |
&entry->change, sizeof(struct batadv_tt_change)); |
c6c8fea29 net: Add batman-a... |
408 409 |
count++; } |
a73105b8d batman-adv: impro... |
410 411 |
list_del(&entry->list); kfree(entry); |
c6c8fea29 net: Add batman-a... |
412 |
} |
807736f6e batman-adv: Split... |
413 |
spin_unlock_bh(&bat_priv->tt.changes_list_lock); |
a73105b8d batman-adv: impro... |
414 415 |
/* Keep the buffer for possible tt_request */ |
807736f6e batman-adv: Split... |
416 417 418 419 |
spin_lock_bh(&bat_priv->tt.last_changeset_lock); kfree(bat_priv->tt.last_changeset); bat_priv->tt.last_changeset_len = 0; bat_priv->tt.last_changeset = NULL; |
be9aa4c1e batman-adv: turn ... |
420 421 422 |
/* check whether this new OGM has no changes due to size problems */ if (new_len > 0) { /* if kmalloc() fails we will reply with the full table |
a73105b8d batman-adv: impro... |
423 424 |
* instead of providing the diff */ |
807736f6e batman-adv: Split... |
425 426 427 428 |
bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC); if (bat_priv->tt.last_changeset) { memcpy(bat_priv->tt.last_changeset, tt_buff, new_len); bat_priv->tt.last_changeset_len = new_len; |
a73105b8d batman-adv: impro... |
429 430 |
} } |
807736f6e batman-adv: Split... |
431 |
spin_unlock_bh(&bat_priv->tt.last_changeset_lock); |
c6c8fea29 net: Add batman-a... |
432 |
|
08ad76ecc batman-adv: retur... |
433 |
return count; |
c6c8fea29 net: Add batman-a... |
434 |
} |
08c36d3e8 batman-adv: Prefi... |
435 |
int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) |
c6c8fea29 net: Add batman-a... |
436 437 |
{ struct net_device *net_dev = (struct net_device *)seq->private; |
56303d34a batman-adv: Prefi... |
438 |
struct batadv_priv *bat_priv = netdev_priv(net_dev); |
807736f6e batman-adv: Split... |
439 |
struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
56303d34a batman-adv: Prefi... |
440 |
struct batadv_tt_common_entry *tt_common_entry; |
85766a820 batman-adv: impro... |
441 |
struct batadv_tt_local_entry *tt_local; |
56303d34a batman-adv: Prefi... |
442 |
struct batadv_hard_iface *primary_if; |
c6c8fea29 net: Add batman-a... |
443 |
struct hlist_head *head; |
c90681b85 batman-adv: fixed... |
444 |
uint32_t i; |
85766a820 batman-adv: impro... |
445 446 447 448 449 |
int last_seen_secs; int last_seen_msecs; unsigned long last_seen_jiffies; bool no_purge; uint16_t np_flag = BATADV_TT_CLIENT_NOPURGE; |
c6c8fea29 net: Add batman-a... |
450 |
|
30da63a6a batman-adv: conso... |
451 452 |
primary_if = batadv_seq_print_text_primary_if_get(seq); if (!primary_if) |
32ae9b221 batman-adv: Make ... |
453 |
goto out; |
c6c8fea29 net: Add batman-a... |
454 |
|
86ceb3605 batman-adv: Ignor... |
455 |
seq_printf(seq, |
f9d8a5378 batman-adv: print... |
456 457 458 459 |
"Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.4x): ", net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn), bat_priv->tt.local_crc); |
85766a820 batman-adv: impro... |
460 461 462 |
seq_printf(seq, " %-13s %-7s %-10s ", "Client", "Flags", "Last seen"); |
c6c8fea29 net: Add batman-a... |
463 |
|
c6c8fea29 net: Add batman-a... |
464 465 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
7aadf889e batman-adv: remov... |
466 |
rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
467 |
hlist_for_each_entry_rcu(tt_common_entry, |
7aadf889e batman-adv: remov... |
468 |
head, hash_entry) { |
85766a820 batman-adv: impro... |
469 470 471 472 473 474 475 476 477 478 479 480 |
tt_local = container_of(tt_common_entry, struct batadv_tt_local_entry, common); last_seen_jiffies = jiffies - tt_local->last_seen; last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); last_seen_secs = last_seen_msecs / 1000; last_seen_msecs = last_seen_msecs % 1000; no_purge = tt_common_entry->flags & np_flag; seq_printf(seq, " * %pM [%c%c%c%c%c] %3u.%03u ", |
7c64fd98c batman-adv: Fix i... |
481 482 |
tt_common_entry->addr, (tt_common_entry->flags & |
acd34afa8 batman-adv: Prefi... |
483 |
BATADV_TT_CLIENT_ROAM ? 'R' : '.'), |
85766a820 batman-adv: impro... |
484 |
no_purge ? 'P' : '.', |
7c64fd98c batman-adv: Fix i... |
485 |
(tt_common_entry->flags & |
acd34afa8 batman-adv: Prefi... |
486 |
BATADV_TT_CLIENT_NEW ? 'N' : '.'), |
7c64fd98c batman-adv: Fix i... |
487 |
(tt_common_entry->flags & |
acd34afa8 batman-adv: Prefi... |
488 |
BATADV_TT_CLIENT_PENDING ? 'X' : '.'), |
7c64fd98c batman-adv: Fix i... |
489 |
(tt_common_entry->flags & |
85766a820 batman-adv: impro... |
490 |
BATADV_TT_CLIENT_WIFI ? 'W' : '.'), |
a7966d908 batman-adv: fix l... |
491 492 |
no_purge ? 0 : last_seen_secs, no_purge ? 0 : last_seen_msecs); |
c6c8fea29 net: Add batman-a... |
493 |
} |
7aadf889e batman-adv: remov... |
494 |
rcu_read_unlock(); |
c6c8fea29 net: Add batman-a... |
495 |
} |
32ae9b221 batman-adv: Make ... |
496 497 |
out: if (primary_if) |
e5d89254b batman-adv: Prefi... |
498 |
batadv_hardif_free_ref(primary_if); |
30da63a6a batman-adv: conso... |
499 |
return 0; |
c6c8fea29 net: Add batman-a... |
500 |
} |
56303d34a batman-adv: Prefi... |
501 502 503 504 |
static void batadv_tt_local_set_pending(struct batadv_priv *bat_priv, struct batadv_tt_local_entry *tt_local_entry, uint16_t flags, const char *message) |
c6c8fea29 net: Add batman-a... |
505 |
{ |
a513088d0 batman-adv: Prefi... |
506 507 |
batadv_tt_local_event(bat_priv, tt_local_entry->common.addr, tt_local_entry->common.flags | flags); |
a73105b8d batman-adv: impro... |
508 |
|
015758d00 batman-adv: corre... |
509 510 |
/* The local client has to be marked as "pending to be removed" but has * to be kept in the table in order to send it in a full table |
9cfc7bd60 batman-adv: Refor... |
511 512 |
* response issued before the net ttvn increment (consistency check) */ |
acd34afa8 batman-adv: Prefi... |
513 |
tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING; |
c566dbbef batman-adv: code ... |
514 |
|
39c75a51e batman-adv: Prefi... |
515 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
516 517 518 |
"Local tt entry (%pM) pending to be removed: %s ", tt_local_entry->common.addr, message); |
c6c8fea29 net: Add batman-a... |
519 |
} |
7f91d06c9 batman-adv: pass ... |
520 521 522 523 524 525 526 527 528 529 530 531 |
/** * batadv_tt_local_remove - logically remove an entry from the local table * @bat_priv: the bat priv with all the soft interface information * @addr: the MAC address of the client to remove * @message: message to append to the log on deletion * @roaming: true if the deletion is due to a roaming event * * Returns the flags assigned to the local entry before being deleted */ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, const uint8_t *addr, const char *message, bool roaming) |
c6c8fea29 net: Add batman-a... |
532 |
{ |
170173bf3 batman-adv: Remov... |
533 |
struct batadv_tt_local_entry *tt_local_entry; |
7f91d06c9 batman-adv: pass ... |
534 |
uint16_t flags, curr_flags = BATADV_NO_FLAGS; |
c6c8fea29 net: Add batman-a... |
535 |
|
a513088d0 batman-adv: Prefi... |
536 |
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); |
7683fdc1e batman-adv: prote... |
537 538 |
if (!tt_local_entry) goto out; |
7f91d06c9 batman-adv: pass ... |
539 |
curr_flags = tt_local_entry->common.flags; |
acd34afa8 batman-adv: Prefi... |
540 |
flags = BATADV_TT_CLIENT_DEL; |
068ee6e20 batman-adv: roami... |
541 542 543 544 |
/* if this global entry addition is due to a roaming, the node has to * mark the local entry as "roamed" in order to correctly reroute * packets later */ |
7c1fd91da batman-adv: subst... |
545 |
if (roaming) { |
acd34afa8 batman-adv: Prefi... |
546 |
flags |= BATADV_TT_CLIENT_ROAM; |
7c1fd91da batman-adv: subst... |
547 548 549 |
/* mark the local client as ROAMed */ tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM; } |
42d0b044b batman-adv: Prefi... |
550 |
|
068ee6e20 batman-adv: roami... |
551 552 553 554 555 556 557 558 559 560 561 562 |
if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) { batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message); goto out; } /* if this client has been added right now, it is possible to * immediately purge it */ batadv_tt_local_event(bat_priv, tt_local_entry->common.addr, curr_flags | BATADV_TT_CLIENT_DEL); hlist_del_rcu(&tt_local_entry->common.hash_entry); batadv_tt_local_entry_free_ref(tt_local_entry); |
7f91d06c9 batman-adv: pass ... |
563 |
|
7683fdc1e batman-adv: prote... |
564 565 |
out: if (tt_local_entry) |
a513088d0 batman-adv: Prefi... |
566 |
batadv_tt_local_entry_free_ref(tt_local_entry); |
7f91d06c9 batman-adv: pass ... |
567 568 |
return curr_flags; |
c6c8fea29 net: Add batman-a... |
569 |
} |
56303d34a batman-adv: Prefi... |
570 |
static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv, |
acd34afa8 batman-adv: Prefi... |
571 |
struct hlist_head *head) |
c6c8fea29 net: Add batman-a... |
572 |
{ |
56303d34a batman-adv: Prefi... |
573 574 |
struct batadv_tt_local_entry *tt_local_entry; struct batadv_tt_common_entry *tt_common_entry; |
b67bfe0d4 hlist: drop the n... |
575 |
struct hlist_node *node_tmp; |
acd34afa8 batman-adv: Prefi... |
576 |
|
b67bfe0d4 hlist: drop the n... |
577 |
hlist_for_each_entry_safe(tt_common_entry, node_tmp, head, |
acd34afa8 batman-adv: Prefi... |
578 579 |
hash_entry) { tt_local_entry = container_of(tt_common_entry, |
56303d34a batman-adv: Prefi... |
580 581 |
struct batadv_tt_local_entry, common); |
acd34afa8 batman-adv: Prefi... |
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 |
if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE) continue; /* entry already marked for deletion */ if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) continue; if (!batadv_has_timed_out(tt_local_entry->last_seen, BATADV_TT_LOCAL_TIMEOUT)) continue; batadv_tt_local_set_pending(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL, "timed out"); } } |
56303d34a batman-adv: Prefi... |
597 |
static void batadv_tt_local_purge(struct batadv_priv *bat_priv) |
acd34afa8 batman-adv: Prefi... |
598 |
{ |
807736f6e batman-adv: Split... |
599 |
struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
c6c8fea29 net: Add batman-a... |
600 |
struct hlist_head *head; |
7683fdc1e batman-adv: prote... |
601 |
spinlock_t *list_lock; /* protects write access to the hash lists */ |
c90681b85 batman-adv: fixed... |
602 |
uint32_t i; |
c6c8fea29 net: Add batman-a... |
603 |
|
c6c8fea29 net: Add batman-a... |
604 605 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
7683fdc1e batman-adv: prote... |
606 |
list_lock = &hash->list_locks[i]; |
c6c8fea29 net: Add batman-a... |
607 |
|
7683fdc1e batman-adv: prote... |
608 |
spin_lock_bh(list_lock); |
acd34afa8 batman-adv: Prefi... |
609 |
batadv_tt_local_purge_list(bat_priv, head); |
7683fdc1e batman-adv: prote... |
610 |
spin_unlock_bh(list_lock); |
c6c8fea29 net: Add batman-a... |
611 |
} |
c6c8fea29 net: Add batman-a... |
612 |
} |
56303d34a batman-adv: Prefi... |
613 |
static void batadv_tt_local_table_free(struct batadv_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
614 |
{ |
5bf74e9ca batman-adv: Prefi... |
615 |
struct batadv_hashtable *hash; |
a73105b8d batman-adv: impro... |
616 |
spinlock_t *list_lock; /* protects write access to the hash lists */ |
56303d34a batman-adv: Prefi... |
617 618 |
struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_local_entry *tt_local; |
b67bfe0d4 hlist: drop the n... |
619 |
struct hlist_node *node_tmp; |
7683fdc1e batman-adv: prote... |
620 |
struct hlist_head *head; |
c90681b85 batman-adv: fixed... |
621 |
uint32_t i; |
a73105b8d batman-adv: impro... |
622 |
|
807736f6e batman-adv: Split... |
623 |
if (!bat_priv->tt.local_hash) |
c6c8fea29 net: Add batman-a... |
624 |
return; |
807736f6e batman-adv: Split... |
625 |
hash = bat_priv->tt.local_hash; |
a73105b8d batman-adv: impro... |
626 627 628 629 630 631 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); |
b67bfe0d4 hlist: drop the n... |
632 |
hlist_for_each_entry_safe(tt_common_entry, node_tmp, |
a73105b8d batman-adv: impro... |
633 |
head, hash_entry) { |
b67bfe0d4 hlist: drop the n... |
634 |
hlist_del_rcu(&tt_common_entry->hash_entry); |
56303d34a batman-adv: Prefi... |
635 636 637 638 |
tt_local = container_of(tt_common_entry, struct batadv_tt_local_entry, common); batadv_tt_local_entry_free_ref(tt_local); |
a73105b8d batman-adv: impro... |
639 640 641 |
} spin_unlock_bh(list_lock); } |
1a8eaf073 batman-adv: Prefi... |
642 |
batadv_hash_destroy(hash); |
a73105b8d batman-adv: impro... |
643 |
|
807736f6e batman-adv: Split... |
644 |
bat_priv->tt.local_hash = NULL; |
c6c8fea29 net: Add batman-a... |
645 |
} |
56303d34a batman-adv: Prefi... |
646 |
static int batadv_tt_global_init(struct batadv_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
647 |
{ |
807736f6e batman-adv: Split... |
648 |
if (bat_priv->tt.global_hash) |
5346c35eb batman-adv: Retur... |
649 |
return 0; |
c6c8fea29 net: Add batman-a... |
650 |
|
807736f6e batman-adv: Split... |
651 |
bat_priv->tt.global_hash = batadv_hash_new(1024); |
c6c8fea29 net: Add batman-a... |
652 |
|
807736f6e batman-adv: Split... |
653 |
if (!bat_priv->tt.global_hash) |
5346c35eb batman-adv: Retur... |
654 |
return -ENOMEM; |
c6c8fea29 net: Add batman-a... |
655 |
|
dec05074b batman-adv: Initi... |
656 657 |
batadv_hash_set_lock_class(bat_priv->tt.global_hash, &batadv_tt_global_hash_lock_class_key); |
5346c35eb batman-adv: Retur... |
658 |
return 0; |
c6c8fea29 net: Add batman-a... |
659 |
} |
56303d34a batman-adv: Prefi... |
660 |
static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
661 |
{ |
56303d34a batman-adv: Prefi... |
662 |
struct batadv_tt_change_node *entry, *safe; |
c6c8fea29 net: Add batman-a... |
663 |
|
807736f6e batman-adv: Split... |
664 |
spin_lock_bh(&bat_priv->tt.changes_list_lock); |
c6c8fea29 net: Add batman-a... |
665 |
|
807736f6e batman-adv: Split... |
666 |
list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, |
a73105b8d batman-adv: impro... |
667 668 669 670 |
list) { list_del(&entry->list); kfree(entry); } |
c6c8fea29 net: Add batman-a... |
671 |
|
807736f6e batman-adv: Split... |
672 673 |
atomic_set(&bat_priv->tt.local_changes, 0); spin_unlock_bh(&bat_priv->tt.changes_list_lock); |
a73105b8d batman-adv: impro... |
674 |
} |
c6c8fea29 net: Add batman-a... |
675 |
|
d657e621a batman-adv: add r... |
676 677 678 679 |
/* retrieves the orig_tt_list_entry belonging to orig_node from the * batadv_tt_global_entry list * * returns it with an increased refcounter, NULL if not found |
db08e6e55 batman-adv: allow... |
680 |
*/ |
d657e621a batman-adv: add r... |
681 682 683 |
static struct batadv_tt_orig_list_entry * batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, const struct batadv_orig_node *orig_node) |
db08e6e55 batman-adv: allow... |
684 |
{ |
d657e621a batman-adv: add r... |
685 |
struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL; |
db08e6e55 batman-adv: allow... |
686 |
const struct hlist_head *head; |
db08e6e55 batman-adv: allow... |
687 688 689 |
rcu_read_lock(); head = &entry->orig_list; |
b67bfe0d4 hlist: drop the n... |
690 |
hlist_for_each_entry_rcu(tmp_orig_entry, head, list) { |
d657e621a batman-adv: add r... |
691 692 693 694 695 696 697 |
if (tmp_orig_entry->orig_node != orig_node) continue; if (!atomic_inc_not_zero(&tmp_orig_entry->refcount)) continue; orig_entry = tmp_orig_entry; break; |
db08e6e55 batman-adv: allow... |
698 699 |
} rcu_read_unlock(); |
d657e621a batman-adv: add r... |
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 |
return orig_entry; } /* find out if an orig_node is already in the list of a tt_global_entry. * returns true if found, false otherwise */ static bool batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, const struct batadv_orig_node *orig_node) { struct batadv_tt_orig_list_entry *orig_entry; bool found = false; orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node); if (orig_entry) { found = true; batadv_tt_orig_list_entry_free_ref(orig_entry); } |
db08e6e55 batman-adv: allow... |
719 720 |
return found; } |
a513088d0 batman-adv: Prefi... |
721 |
static void |
d657e621a batman-adv: add r... |
722 |
batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, |
56303d34a batman-adv: Prefi... |
723 |
struct batadv_orig_node *orig_node, int ttvn) |
db08e6e55 batman-adv: allow... |
724 |
{ |
56303d34a batman-adv: Prefi... |
725 |
struct batadv_tt_orig_list_entry *orig_entry; |
db08e6e55 batman-adv: allow... |
726 |
|
d657e621a batman-adv: add r... |
727 |
orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node); |
30cfd02b6 batman-adv: detec... |
728 729 730 731 732 |
if (orig_entry) { /* refresh the ttvn: the current value could be a bogus one that * was added during a "temporary client detection" */ orig_entry->ttvn = ttvn; |
d657e621a batman-adv: add r... |
733 |
goto out; |
30cfd02b6 batman-adv: detec... |
734 |
} |
d657e621a batman-adv: add r... |
735 |
|
db08e6e55 batman-adv: allow... |
736 737 |
orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC); if (!orig_entry) |
d657e621a batman-adv: add r... |
738 |
goto out; |
db08e6e55 batman-adv: allow... |
739 740 741 742 743 744 |
INIT_HLIST_NODE(&orig_entry->list); atomic_inc(&orig_node->refcount); atomic_inc(&orig_node->tt_size); orig_entry->orig_node = orig_node; orig_entry->ttvn = ttvn; |
d657e621a batman-adv: add r... |
745 |
atomic_set(&orig_entry->refcount, 2); |
db08e6e55 batman-adv: allow... |
746 |
|
d657e621a batman-adv: add r... |
747 |
spin_lock_bh(&tt_global->list_lock); |
db08e6e55 batman-adv: allow... |
748 |
hlist_add_head_rcu(&orig_entry->list, |
d657e621a batman-adv: add r... |
749 750 751 752 753 |
&tt_global->orig_list); spin_unlock_bh(&tt_global->list_lock); out: if (orig_entry) batadv_tt_orig_list_entry_free_ref(orig_entry); |
db08e6e55 batman-adv: allow... |
754 |
} |
a73105b8d batman-adv: impro... |
755 |
/* caller must hold orig_node refcount */ |
56303d34a batman-adv: Prefi... |
756 757 |
int batadv_tt_global_add(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, |
d4f446925 batman-adv: beaut... |
758 759 |
const unsigned char *tt_addr, uint8_t flags, uint8_t ttvn) |
a73105b8d batman-adv: impro... |
760 |
{ |
170173bf3 batman-adv: Remov... |
761 762 |
struct batadv_tt_global_entry *tt_global_entry; struct batadv_tt_local_entry *tt_local_entry; |
7683fdc1e batman-adv: prote... |
763 |
int ret = 0; |
80b3f58cf batman-adv: check... |
764 |
int hash_added; |
56303d34a batman-adv: Prefi... |
765 |
struct batadv_tt_common_entry *common; |
7f91d06c9 batman-adv: pass ... |
766 |
uint16_t local_flags; |
c6c8fea29 net: Add batman-a... |
767 |
|
a513088d0 batman-adv: Prefi... |
768 |
tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr); |
068ee6e20 batman-adv: roami... |
769 770 771 772 773 774 775 776 777 |
tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr); /* if the node already has a local client for this entry, it has to wait * for a roaming advertisement instead of manually messing up the global * table */ if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry && !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) goto out; |
a73105b8d batman-adv: impro... |
778 779 |
if (!tt_global_entry) { |
d4f446925 batman-adv: beaut... |
780 |
tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC); |
a73105b8d batman-adv: impro... |
781 |
if (!tt_global_entry) |
7683fdc1e batman-adv: prote... |
782 |
goto out; |
c0a559295 batman-adv: Prefi... |
783 784 |
common = &tt_global_entry->common; memcpy(common->addr, tt_addr, ETH_ALEN); |
db08e6e55 batman-adv: allow... |
785 |
|
d4f446925 batman-adv: beaut... |
786 |
common->flags = flags; |
cc47f66e6 batman-adv: impro... |
787 |
tt_global_entry->roam_at = 0; |
fdf793205 batman-adv: prope... |
788 789 790 791 792 793 |
/* node must store current time in case of roaming. This is * needed to purge this entry out on timeout (if nobody claims * it) */ if (flags & BATADV_TT_CLIENT_ROAM) tt_global_entry->roam_at = jiffies; |
c0a559295 batman-adv: Prefi... |
794 |
atomic_set(&common->refcount, 2); |
30cfd02b6 batman-adv: detec... |
795 |
common->added_at = jiffies; |
db08e6e55 batman-adv: allow... |
796 797 798 |
INIT_HLIST_HEAD(&tt_global_entry->orig_list); spin_lock_init(&tt_global_entry->list_lock); |
7683fdc1e batman-adv: prote... |
799 |
|
807736f6e batman-adv: Split... |
800 |
hash_added = batadv_hash_add(bat_priv->tt.global_hash, |
a513088d0 batman-adv: Prefi... |
801 802 803 |
batadv_compare_tt, batadv_choose_orig, common, &common->hash_entry); |
80b3f58cf batman-adv: check... |
804 805 806 |
if (unlikely(hash_added != 0)) { /* remove the reference for the hash */ |
a513088d0 batman-adv: Prefi... |
807 |
batadv_tt_global_entry_free_ref(tt_global_entry); |
80b3f58cf batman-adv: check... |
808 809 |
goto out_remove; } |
a73105b8d batman-adv: impro... |
810 |
} else { |
068ee6e20 batman-adv: roami... |
811 |
common = &tt_global_entry->common; |
30cfd02b6 batman-adv: detec... |
812 813 |
/* If there is already a global entry, we can use this one for * our processing. |
068ee6e20 batman-adv: roami... |
814 815 816 817 818 819 820 |
* But if we are trying to add a temporary client then here are * two options at this point: * 1) the global client is not a temporary client: the global * client has to be left as it is, temporary information * should never override any already known client state * 2) the global client is a temporary client: purge the * originator list and add the new one orig_entry |
30cfd02b6 batman-adv: detec... |
821 |
*/ |
068ee6e20 batman-adv: roami... |
822 823 824 825 826 827 828 829 830 |
if (flags & BATADV_TT_CLIENT_TEMP) { if (!(common->flags & BATADV_TT_CLIENT_TEMP)) goto out; if (batadv_tt_global_entry_has_orig(tt_global_entry, orig_node)) goto out_remove; batadv_tt_global_del_orig_list(tt_global_entry); goto add_orig_entry; } |
30cfd02b6 batman-adv: detec... |
831 832 833 834 |
/* if the client was temporary added before receiving the first * OGM announcing it, we have to clear the TEMP flag */ |
068ee6e20 batman-adv: roami... |
835 |
common->flags &= ~BATADV_TT_CLIENT_TEMP; |
db08e6e55 batman-adv: allow... |
836 |
|
e9c00136a batman-adv: fix t... |
837 838 839 840 841 |
/* the change can carry possible "attribute" flags like the * TT_CLIENT_WIFI, therefore they have to be copied in the * client entry */ tt_global_entry->common.flags |= flags; |
acd34afa8 batman-adv: Prefi... |
842 843 |
/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only * one originator left in the list and we previously received a |
db08e6e55 batman-adv: allow... |
844 845 846 847 848 |
* delete + roaming change for this originator. * * We should first delete the old originator before adding the * new one. */ |
068ee6e20 batman-adv: roami... |
849 |
if (common->flags & BATADV_TT_CLIENT_ROAM) { |
a513088d0 batman-adv: Prefi... |
850 |
batadv_tt_global_del_orig_list(tt_global_entry); |
068ee6e20 batman-adv: roami... |
851 |
common->flags &= ~BATADV_TT_CLIENT_ROAM; |
db08e6e55 batman-adv: allow... |
852 |
tt_global_entry->roam_at = 0; |
a73105b8d batman-adv: impro... |
853 854 |
} } |
068ee6e20 batman-adv: roami... |
855 |
add_orig_entry: |
30cfd02b6 batman-adv: detec... |
856 |
/* add the new orig_entry (if needed) or update it */ |
d657e621a batman-adv: add r... |
857 |
batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); |
c6c8fea29 net: Add batman-a... |
858 |
|
39c75a51e batman-adv: Prefi... |
859 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
860 861 |
"Creating new global tt entry: %pM (via %pM) ", |
068ee6e20 batman-adv: roami... |
862 |
common->addr, orig_node->orig); |
c10dba051 batman-adv: retur... |
863 |
ret = 1; |
c6c8fea29 net: Add batman-a... |
864 |
|
80b3f58cf batman-adv: check... |
865 |
out_remove: |
7f91d06c9 batman-adv: pass ... |
866 |
|
a73105b8d batman-adv: impro... |
867 |
/* remove address from local hash if present */ |
7f91d06c9 batman-adv: pass ... |
868 869 |
local_flags = batadv_tt_local_remove(bat_priv, tt_addr, "global tt received", |
c1d07431b batman-adv: don't... |
870 |
flags & BATADV_TT_CLIENT_ROAM); |
7f91d06c9 batman-adv: pass ... |
871 |
tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI; |
068ee6e20 batman-adv: roami... |
872 873 874 875 876 |
if (!(flags & BATADV_TT_CLIENT_ROAM)) /* this is a normal global add. Therefore the client is not in a * roaming state anymore. */ tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; |
7683fdc1e batman-adv: prote... |
877 878 |
out: if (tt_global_entry) |
a513088d0 batman-adv: Prefi... |
879 |
batadv_tt_global_entry_free_ref(tt_global_entry); |
068ee6e20 batman-adv: roami... |
880 881 |
if (tt_local_entry) batadv_tt_local_entry_free_ref(tt_local_entry); |
7683fdc1e batman-adv: prote... |
882 |
return ret; |
c6c8fea29 net: Add batman-a... |
883 |
} |
981d89002 batman-adv: Mark ... |
884 885 886 887 888 889 890 891 892 893 894 |
/* batadv_transtable_best_orig - Get best originator list entry from tt entry * @tt_global_entry: global translation table entry to be analyzed * * This functon assumes the caller holds rcu_read_lock(). * Returns best originator list entry or NULL on errors. */ static struct batadv_tt_orig_list_entry * batadv_transtable_best_orig(struct batadv_tt_global_entry *tt_global_entry) { struct batadv_neigh_node *router = NULL; struct hlist_head *head; |
981d89002 batman-adv: Mark ... |
895 896 897 898 |
struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL; int best_tq = 0; head = &tt_global_entry->orig_list; |
b67bfe0d4 hlist: drop the n... |
899 |
hlist_for_each_entry_rcu(orig_entry, head, list) { |
981d89002 batman-adv: Mark ... |
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 |
router = batadv_orig_node_get_router(orig_entry->orig_node); if (!router) continue; if (router->tq_avg > best_tq) { best_entry = orig_entry; best_tq = router->tq_avg; } batadv_neigh_node_free_ref(router); } return best_entry; } /* batadv_tt_global_print_entry - print all orig nodes who announce the address * for this global entry * @tt_global_entry: global translation table entry to be printed * @seq: debugfs table seq_file struct * * This functon assumes the caller holds rcu_read_lock(). |
db08e6e55 batman-adv: allow... |
921 |
*/ |
a513088d0 batman-adv: Prefi... |
922 |
static void |
56303d34a batman-adv: Prefi... |
923 |
batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry, |
a513088d0 batman-adv: Prefi... |
924 |
struct seq_file *seq) |
db08e6e55 batman-adv: allow... |
925 926 |
{ struct hlist_head *head; |
981d89002 batman-adv: Mark ... |
927 |
struct batadv_tt_orig_list_entry *orig_entry, *best_entry; |
56303d34a batman-adv: Prefi... |
928 |
struct batadv_tt_common_entry *tt_common_entry; |
db08e6e55 batman-adv: allow... |
929 930 931 932 |
uint16_t flags; uint8_t last_ttvn; tt_common_entry = &tt_global_entry->common; |
981d89002 batman-adv: Mark ... |
933 934 935 936 937 |
flags = tt_common_entry->flags; best_entry = batadv_transtable_best_orig(tt_global_entry); if (best_entry) { last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn); |
f9d8a5378 batman-adv: print... |
938 939 940 |
seq_printf(seq, " %c %pM (%3u) via %pM (%3u) (%#.4x) [%c%c%c] ", |
981d89002 batman-adv: Mark ... |
941 942 |
'*', tt_global_entry->common.addr, best_entry->ttvn, best_entry->orig_node->orig, |
f9d8a5378 batman-adv: print... |
943 |
last_ttvn, best_entry->orig_node->tt_crc, |
981d89002 batman-adv: Mark ... |
944 945 946 947 |
(flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); } |
db08e6e55 batman-adv: allow... |
948 949 |
head = &tt_global_entry->orig_list; |
b67bfe0d4 hlist: drop the n... |
950 |
hlist_for_each_entry_rcu(orig_entry, head, list) { |
981d89002 batman-adv: Mark ... |
951 952 |
if (best_entry == orig_entry) continue; |
db08e6e55 batman-adv: allow... |
953 |
last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); |
981d89002 batman-adv: Mark ... |
954 955 956 957 958 |
seq_printf(seq, " %c %pM (%3u) via %pM (%3u) [%c%c%c] ", '+', tt_global_entry->common.addr, orig_entry->ttvn, orig_entry->orig_node->orig, last_ttvn, |
acd34afa8 batman-adv: Prefi... |
959 |
(flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), |
30cfd02b6 batman-adv: detec... |
960 961 |
(flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); |
db08e6e55 batman-adv: allow... |
962 963 |
} } |
08c36d3e8 batman-adv: Prefi... |
964 |
int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset) |
c6c8fea29 net: Add batman-a... |
965 966 |
{ struct net_device *net_dev = (struct net_device *)seq->private; |
56303d34a batman-adv: Prefi... |
967 |
struct batadv_priv *bat_priv = netdev_priv(net_dev); |
807736f6e batman-adv: Split... |
968 |
struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
56303d34a batman-adv: Prefi... |
969 970 971 |
struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_global_entry *tt_global; struct batadv_hard_iface *primary_if; |
c6c8fea29 net: Add batman-a... |
972 |
struct hlist_head *head; |
c90681b85 batman-adv: fixed... |
973 |
uint32_t i; |
c6c8fea29 net: Add batman-a... |
974 |
|
30da63a6a batman-adv: conso... |
975 976 |
primary_if = batadv_seq_print_text_primary_if_get(seq); if (!primary_if) |
32ae9b221 batman-adv: Make ... |
977 |
goto out; |
c6c8fea29 net: Add batman-a... |
978 |
|
2dafb49d8 batman-adv: renam... |
979 980 981 |
seq_printf(seq, "Globally announced TT entries received via the mesh %s ", |
c6c8fea29 net: Add batman-a... |
982 |
net_dev->name); |
f9d8a5378 batman-adv: print... |
983 984 985 986 |
seq_printf(seq, " %-13s %s %-15s %s (%-6s) %s ", "Client", "(TTVN)", "Originator", "(Curr TTVN)", "CRC", "Flags"); |
c6c8fea29 net: Add batman-a... |
987 |
|
c6c8fea29 net: Add batman-a... |
988 989 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
7aadf889e batman-adv: remov... |
990 |
rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
991 |
hlist_for_each_entry_rcu(tt_common_entry, |
7aadf889e batman-adv: remov... |
992 |
head, hash_entry) { |
56303d34a batman-adv: Prefi... |
993 994 995 996 |
tt_global = container_of(tt_common_entry, struct batadv_tt_global_entry, common); batadv_tt_global_print_entry(tt_global, seq); |
c6c8fea29 net: Add batman-a... |
997 |
} |
7aadf889e batman-adv: remov... |
998 |
rcu_read_unlock(); |
c6c8fea29 net: Add batman-a... |
999 |
} |
32ae9b221 batman-adv: Make ... |
1000 1001 |
out: if (primary_if) |
e5d89254b batman-adv: Prefi... |
1002 |
batadv_hardif_free_ref(primary_if); |
30da63a6a batman-adv: conso... |
1003 |
return 0; |
c6c8fea29 net: Add batman-a... |
1004 |
} |
db08e6e55 batman-adv: allow... |
1005 |
/* deletes the orig list of a tt_global_entry */ |
a513088d0 batman-adv: Prefi... |
1006 |
static void |
56303d34a batman-adv: Prefi... |
1007 |
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry) |
c6c8fea29 net: Add batman-a... |
1008 |
{ |
db08e6e55 batman-adv: allow... |
1009 |
struct hlist_head *head; |
b67bfe0d4 hlist: drop the n... |
1010 |
struct hlist_node *safe; |
56303d34a batman-adv: Prefi... |
1011 |
struct batadv_tt_orig_list_entry *orig_entry; |
a73105b8d batman-adv: impro... |
1012 |
|
db08e6e55 batman-adv: allow... |
1013 1014 |
spin_lock_bh(&tt_global_entry->list_lock); head = &tt_global_entry->orig_list; |
b67bfe0d4 hlist: drop the n... |
1015 1016 |
hlist_for_each_entry_safe(orig_entry, safe, head, list) { hlist_del_rcu(&orig_entry->list); |
a513088d0 batman-adv: Prefi... |
1017 |
batadv_tt_orig_list_entry_free_ref(orig_entry); |
db08e6e55 batman-adv: allow... |
1018 1019 |
} spin_unlock_bh(&tt_global_entry->list_lock); |
db08e6e55 batman-adv: allow... |
1020 |
} |
a513088d0 batman-adv: Prefi... |
1021 |
static void |
56303d34a batman-adv: Prefi... |
1022 1023 1024 |
batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, struct batadv_tt_global_entry *tt_global_entry, struct batadv_orig_node *orig_node, |
a513088d0 batman-adv: Prefi... |
1025 |
const char *message) |
db08e6e55 batman-adv: allow... |
1026 1027 |
{ struct hlist_head *head; |
b67bfe0d4 hlist: drop the n... |
1028 |
struct hlist_node *safe; |
56303d34a batman-adv: Prefi... |
1029 |
struct batadv_tt_orig_list_entry *orig_entry; |
db08e6e55 batman-adv: allow... |
1030 1031 1032 |
spin_lock_bh(&tt_global_entry->list_lock); head = &tt_global_entry->orig_list; |
b67bfe0d4 hlist: drop the n... |
1033 |
hlist_for_each_entry_safe(orig_entry, safe, head, list) { |
db08e6e55 batman-adv: allow... |
1034 |
if (orig_entry->orig_node == orig_node) { |
39c75a51e batman-adv: Prefi... |
1035 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
1036 1037 1038 1039 |
"Deleting %pM from global tt entry %pM: %s ", orig_node->orig, tt_global_entry->common.addr, message); |
b67bfe0d4 hlist: drop the n... |
1040 |
hlist_del_rcu(&orig_entry->list); |
a513088d0 batman-adv: Prefi... |
1041 |
batadv_tt_orig_list_entry_free_ref(orig_entry); |
db08e6e55 batman-adv: allow... |
1042 1043 1044 1045 |
} } spin_unlock_bh(&tt_global_entry->list_lock); } |
db08e6e55 batman-adv: allow... |
1046 |
/* If the client is to be deleted, we check if it is the last origantor entry |
acd34afa8 batman-adv: Prefi... |
1047 1048 |
* within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the * timer, otherwise we simply remove the originator scheduled for deletion. |
db08e6e55 batman-adv: allow... |
1049 |
*/ |
a513088d0 batman-adv: Prefi... |
1050 |
static void |
56303d34a batman-adv: Prefi... |
1051 1052 1053 1054 |
batadv_tt_global_del_roaming(struct batadv_priv *bat_priv, struct batadv_tt_global_entry *tt_global_entry, struct batadv_orig_node *orig_node, const char *message) |
db08e6e55 batman-adv: allow... |
1055 1056 1057 |
{ bool last_entry = true; struct hlist_head *head; |
56303d34a batman-adv: Prefi... |
1058 |
struct batadv_tt_orig_list_entry *orig_entry; |
db08e6e55 batman-adv: allow... |
1059 1060 1061 1062 1063 1064 1065 |
/* no local entry exists, case 1: * Check if this is the last one or if other entries exist. */ rcu_read_lock(); head = &tt_global_entry->orig_list; |
b67bfe0d4 hlist: drop the n... |
1066 |
hlist_for_each_entry_rcu(orig_entry, head, list) { |
db08e6e55 batman-adv: allow... |
1067 1068 1069 1070 1071 1072 1073 1074 1075 |
if (orig_entry->orig_node != orig_node) { last_entry = false; break; } } rcu_read_unlock(); if (last_entry) { /* its the last one, mark for roaming. */ |
acd34afa8 batman-adv: Prefi... |
1076 |
tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM; |
db08e6e55 batman-adv: allow... |
1077 1078 1079 1080 1081 |
tt_global_entry->roam_at = jiffies; } else /* there is another entry, we can simply delete this * one and can still use the other one. */ |
a513088d0 batman-adv: Prefi... |
1082 1083 |
batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry, orig_node, message); |
db08e6e55 batman-adv: allow... |
1084 |
} |
56303d34a batman-adv: Prefi... |
1085 1086 |
static void batadv_tt_global_del(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, |
a513088d0 batman-adv: Prefi... |
1087 1088 |
const unsigned char *addr, const char *message, bool roaming) |
a73105b8d batman-adv: impro... |
1089 |
{ |
170173bf3 batman-adv: Remov... |
1090 |
struct batadv_tt_global_entry *tt_global_entry; |
56303d34a batman-adv: Prefi... |
1091 |
struct batadv_tt_local_entry *local_entry = NULL; |
a73105b8d batman-adv: impro... |
1092 |
|
a513088d0 batman-adv: Prefi... |
1093 |
tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); |
db08e6e55 batman-adv: allow... |
1094 |
if (!tt_global_entry) |
7683fdc1e batman-adv: prote... |
1095 |
goto out; |
a73105b8d batman-adv: impro... |
1096 |
|
db08e6e55 batman-adv: allow... |
1097 |
if (!roaming) { |
a513088d0 batman-adv: Prefi... |
1098 1099 |
batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry, orig_node, message); |
db08e6e55 batman-adv: allow... |
1100 1101 |
if (hlist_empty(&tt_global_entry->orig_list)) |
be73b488d batman-adv: refac... |
1102 1103 |
batadv_tt_global_free(bat_priv, tt_global_entry, message); |
db08e6e55 batman-adv: allow... |
1104 1105 1106 |
goto out; } |
92f90f56c batman-adv: refac... |
1107 1108 1109 |
/* if we are deleting a global entry due to a roam * event, there are two possibilities: |
db08e6e55 batman-adv: allow... |
1110 1111 |
* 1) the client roamed from node A to node B => if there * is only one originator left for this client, we mark |
acd34afa8 batman-adv: Prefi... |
1112 |
* it with BATADV_TT_CLIENT_ROAM, we start a timer and we |
92f90f56c batman-adv: refac... |
1113 1114 |
* wait for node B to claim it. In case of timeout * the entry is purged. |
db08e6e55 batman-adv: allow... |
1115 1116 1117 |
* * If there are other originators left, we directly delete * the originator. |
92f90f56c batman-adv: refac... |
1118 |
* 2) the client roamed to us => we can directly delete |
9cfc7bd60 batman-adv: Refor... |
1119 1120 |
* the global entry, since it is useless now. */ |
a513088d0 batman-adv: Prefi... |
1121 1122 1123 |
local_entry = batadv_tt_local_hash_find(bat_priv, tt_global_entry->common.addr); if (local_entry) { |
db08e6e55 batman-adv: allow... |
1124 |
/* local entry exists, case 2: client roamed to us. */ |
a513088d0 batman-adv: Prefi... |
1125 |
batadv_tt_global_del_orig_list(tt_global_entry); |
be73b488d batman-adv: refac... |
1126 |
batadv_tt_global_free(bat_priv, tt_global_entry, message); |
db08e6e55 batman-adv: allow... |
1127 1128 |
} else /* no local entry exists, case 1: check for roaming */ |
a513088d0 batman-adv: Prefi... |
1129 1130 |
batadv_tt_global_del_roaming(bat_priv, tt_global_entry, orig_node, message); |
92f90f56c batman-adv: refac... |
1131 |
|
92f90f56c batman-adv: refac... |
1132 |
|
cc47f66e6 batman-adv: impro... |
1133 |
out: |
7683fdc1e batman-adv: prote... |
1134 |
if (tt_global_entry) |
a513088d0 batman-adv: Prefi... |
1135 1136 1137 |
batadv_tt_global_entry_free_ref(tt_global_entry); if (local_entry) batadv_tt_local_entry_free_ref(local_entry); |
a73105b8d batman-adv: impro... |
1138 |
} |
56303d34a batman-adv: Prefi... |
1139 1140 1141 |
void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, const char *message) |
c6c8fea29 net: Add batman-a... |
1142 |
{ |
56303d34a batman-adv: Prefi... |
1143 1144 |
struct batadv_tt_global_entry *tt_global; struct batadv_tt_common_entry *tt_common_entry; |
c90681b85 batman-adv: fixed... |
1145 |
uint32_t i; |
807736f6e batman-adv: Split... |
1146 |
struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
b67bfe0d4 hlist: drop the n... |
1147 |
struct hlist_node *safe; |
a73105b8d batman-adv: impro... |
1148 |
struct hlist_head *head; |
7683fdc1e batman-adv: prote... |
1149 |
spinlock_t *list_lock; /* protects write access to the hash lists */ |
c6c8fea29 net: Add batman-a... |
1150 |
|
6e8014947 batman-adv: add s... |
1151 1152 |
if (!hash) return; |
a73105b8d batman-adv: impro... |
1153 1154 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
7683fdc1e batman-adv: prote... |
1155 |
list_lock = &hash->list_locks[i]; |
c6c8fea29 net: Add batman-a... |
1156 |
|
7683fdc1e batman-adv: prote... |
1157 |
spin_lock_bh(list_lock); |
b67bfe0d4 hlist: drop the n... |
1158 |
hlist_for_each_entry_safe(tt_common_entry, safe, |
7c64fd98c batman-adv: Fix i... |
1159 |
head, hash_entry) { |
56303d34a batman-adv: Prefi... |
1160 1161 1162 |
tt_global = container_of(tt_common_entry, struct batadv_tt_global_entry, common); |
db08e6e55 batman-adv: allow... |
1163 |
|
56303d34a batman-adv: Prefi... |
1164 |
batadv_tt_global_del_orig_entry(bat_priv, tt_global, |
a513088d0 batman-adv: Prefi... |
1165 |
orig_node, message); |
db08e6e55 batman-adv: allow... |
1166 |
|
56303d34a batman-adv: Prefi... |
1167 |
if (hlist_empty(&tt_global->orig_list)) { |
39c75a51e batman-adv: Prefi... |
1168 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
1169 1170 |
"Deleting global tt entry %pM: %s ", |
56303d34a batman-adv: Prefi... |
1171 |
tt_global->common.addr, message); |
b67bfe0d4 hlist: drop the n... |
1172 |
hlist_del_rcu(&tt_common_entry->hash_entry); |
56303d34a batman-adv: Prefi... |
1173 |
batadv_tt_global_entry_free_ref(tt_global); |
7683fdc1e batman-adv: prote... |
1174 |
} |
a73105b8d batman-adv: impro... |
1175 |
} |
7683fdc1e batman-adv: prote... |
1176 |
spin_unlock_bh(list_lock); |
c6c8fea29 net: Add batman-a... |
1177 |
} |
170715788 batman-adv: add t... |
1178 |
orig_node->tt_initialised = false; |
c6c8fea29 net: Add batman-a... |
1179 |
} |
30cfd02b6 batman-adv: detec... |
1180 1181 |
static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global, char **msg) |
cc47f66e6 batman-adv: impro... |
1182 |
{ |
30cfd02b6 batman-adv: detec... |
1183 1184 1185 |
bool purge = false; unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT; unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT; |
42d0b044b batman-adv: Prefi... |
1186 |
|
30cfd02b6 batman-adv: detec... |
1187 1188 1189 1190 1191 1192 |
if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) && batadv_has_timed_out(tt_global->roam_at, roam_timeout)) { purge = true; *msg = "Roaming timeout "; } |
42d0b044b batman-adv: Prefi... |
1193 |
|
30cfd02b6 batman-adv: detec... |
1194 1195 1196 1197 1198 |
if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) && batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) { purge = true; *msg = "Temporary client timeout "; |
42d0b044b batman-adv: Prefi... |
1199 |
} |
30cfd02b6 batman-adv: detec... |
1200 1201 |
return purge; |
42d0b044b batman-adv: Prefi... |
1202 |
} |
30cfd02b6 batman-adv: detec... |
1203 |
static void batadv_tt_global_purge(struct batadv_priv *bat_priv) |
42d0b044b batman-adv: Prefi... |
1204 |
{ |
807736f6e batman-adv: Split... |
1205 |
struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
cc47f66e6 batman-adv: impro... |
1206 |
struct hlist_head *head; |
b67bfe0d4 hlist: drop the n... |
1207 |
struct hlist_node *node_tmp; |
7683fdc1e batman-adv: prote... |
1208 |
spinlock_t *list_lock; /* protects write access to the hash lists */ |
c90681b85 batman-adv: fixed... |
1209 |
uint32_t i; |
30cfd02b6 batman-adv: detec... |
1210 1211 1212 |
char *msg = NULL; struct batadv_tt_common_entry *tt_common; struct batadv_tt_global_entry *tt_global; |
cc47f66e6 batman-adv: impro... |
1213 |
|
cc47f66e6 batman-adv: impro... |
1214 1215 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
7683fdc1e batman-adv: prote... |
1216 |
list_lock = &hash->list_locks[i]; |
cc47f66e6 batman-adv: impro... |
1217 |
|
7683fdc1e batman-adv: prote... |
1218 |
spin_lock_bh(list_lock); |
b67bfe0d4 hlist: drop the n... |
1219 |
hlist_for_each_entry_safe(tt_common, node_tmp, head, |
30cfd02b6 batman-adv: detec... |
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 |
hash_entry) { tt_global = container_of(tt_common, struct batadv_tt_global_entry, common); if (!batadv_tt_global_to_purge(tt_global, &msg)) continue; batadv_dbg(BATADV_DBG_TT, bat_priv, "Deleting global tt entry (%pM): %s ", tt_global->common.addr, msg); |
b67bfe0d4 hlist: drop the n... |
1232 |
hlist_del_rcu(&tt_common->hash_entry); |
30cfd02b6 batman-adv: detec... |
1233 1234 1235 |
batadv_tt_global_entry_free_ref(tt_global); } |
7683fdc1e batman-adv: prote... |
1236 |
spin_unlock_bh(list_lock); |
cc47f66e6 batman-adv: impro... |
1237 |
} |
cc47f66e6 batman-adv: impro... |
1238 |
} |
56303d34a batman-adv: Prefi... |
1239 |
static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) |
c6c8fea29 net: Add batman-a... |
1240 |
{ |
5bf74e9ca batman-adv: Prefi... |
1241 |
struct batadv_hashtable *hash; |
7683fdc1e batman-adv: prote... |
1242 |
spinlock_t *list_lock; /* protects write access to the hash lists */ |
56303d34a batman-adv: Prefi... |
1243 1244 |
struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_global_entry *tt_global; |
b67bfe0d4 hlist: drop the n... |
1245 |
struct hlist_node *node_tmp; |
7683fdc1e batman-adv: prote... |
1246 |
struct hlist_head *head; |
c90681b85 batman-adv: fixed... |
1247 |
uint32_t i; |
7683fdc1e batman-adv: prote... |
1248 |
|
807736f6e batman-adv: Split... |
1249 |
if (!bat_priv->tt.global_hash) |
c6c8fea29 net: Add batman-a... |
1250 |
return; |
807736f6e batman-adv: Split... |
1251 |
hash = bat_priv->tt.global_hash; |
7683fdc1e batman-adv: prote... |
1252 1253 1254 1255 1256 1257 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); |
b67bfe0d4 hlist: drop the n... |
1258 |
hlist_for_each_entry_safe(tt_common_entry, node_tmp, |
7683fdc1e batman-adv: prote... |
1259 |
head, hash_entry) { |
b67bfe0d4 hlist: drop the n... |
1260 |
hlist_del_rcu(&tt_common_entry->hash_entry); |
56303d34a batman-adv: Prefi... |
1261 1262 1263 1264 |
tt_global = container_of(tt_common_entry, struct batadv_tt_global_entry, common); batadv_tt_global_entry_free_ref(tt_global); |
7683fdc1e batman-adv: prote... |
1265 1266 1267 |
} spin_unlock_bh(list_lock); } |
1a8eaf073 batman-adv: Prefi... |
1268 |
batadv_hash_destroy(hash); |
7683fdc1e batman-adv: prote... |
1269 |
|
807736f6e batman-adv: Split... |
1270 |
bat_priv->tt.global_hash = NULL; |
c6c8fea29 net: Add batman-a... |
1271 |
} |
56303d34a batman-adv: Prefi... |
1272 1273 1274 |
static bool _batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry, struct batadv_tt_global_entry *tt_global_entry) |
59b699cde batman-adv: imple... |
1275 1276 |
{ bool ret = false; |
acd34afa8 batman-adv: Prefi... |
1277 1278 |
if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI && tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI) |
59b699cde batman-adv: imple... |
1279 1280 1281 1282 |
ret = true; return ret; } |
56303d34a batman-adv: Prefi... |
1283 1284 1285 |
struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, const uint8_t *src, const uint8_t *addr) |
c6c8fea29 net: Add batman-a... |
1286 |
{ |
56303d34a batman-adv: Prefi... |
1287 1288 1289 |
struct batadv_tt_local_entry *tt_local_entry = NULL; struct batadv_tt_global_entry *tt_global_entry = NULL; struct batadv_orig_node *orig_node = NULL; |
981d89002 batman-adv: Mark ... |
1290 |
struct batadv_tt_orig_list_entry *best_entry; |
c6c8fea29 net: Add batman-a... |
1291 |
|
3d393e473 batman-adv: imple... |
1292 |
if (src && atomic_read(&bat_priv->ap_isolation)) { |
a513088d0 batman-adv: Prefi... |
1293 |
tt_local_entry = batadv_tt_local_hash_find(bat_priv, src); |
068ee6e20 batman-adv: roami... |
1294 1295 |
if (!tt_local_entry || (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)) |
3d393e473 batman-adv: imple... |
1296 1297 |
goto out; } |
7aadf889e batman-adv: remov... |
1298 |
|
a513088d0 batman-adv: Prefi... |
1299 |
tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); |
2dafb49d8 batman-adv: renam... |
1300 |
if (!tt_global_entry) |
7b36e8eef batman-adv: Corre... |
1301 |
goto out; |
7aadf889e batman-adv: remov... |
1302 |
|
3d393e473 batman-adv: imple... |
1303 |
/* check whether the clients should not communicate due to AP |
9cfc7bd60 batman-adv: Refor... |
1304 1305 |
* isolation */ |
a513088d0 batman-adv: Prefi... |
1306 1307 |
if (tt_local_entry && _batadv_is_ap_isolated(tt_local_entry, tt_global_entry)) |
3d393e473 batman-adv: imple... |
1308 |
goto out; |
db08e6e55 batman-adv: allow... |
1309 |
rcu_read_lock(); |
981d89002 batman-adv: Mark ... |
1310 |
best_entry = batadv_transtable_best_orig(tt_global_entry); |
db08e6e55 batman-adv: allow... |
1311 |
/* found anything? */ |
981d89002 batman-adv: Mark ... |
1312 1313 |
if (best_entry) orig_node = best_entry->orig_node; |
db08e6e55 batman-adv: allow... |
1314 1315 1316 |
if (orig_node && !atomic_inc_not_zero(&orig_node->refcount)) orig_node = NULL; rcu_read_unlock(); |
981d89002 batman-adv: Mark ... |
1317 |
|
7b36e8eef batman-adv: Corre... |
1318 |
out: |
3d393e473 batman-adv: imple... |
1319 |
if (tt_global_entry) |
a513088d0 batman-adv: Prefi... |
1320 |
batadv_tt_global_entry_free_ref(tt_global_entry); |
3d393e473 batman-adv: imple... |
1321 |
if (tt_local_entry) |
a513088d0 batman-adv: Prefi... |
1322 |
batadv_tt_local_entry_free_ref(tt_local_entry); |
3d393e473 batman-adv: imple... |
1323 |
|
7b36e8eef batman-adv: Corre... |
1324 |
return orig_node; |
c6c8fea29 net: Add batman-a... |
1325 |
} |
a73105b8d batman-adv: impro... |
1326 1327 |
/* Calculates the checksum of the local table of a given orig_node */ |
56303d34a batman-adv: Prefi... |
1328 1329 |
static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node) |
a73105b8d batman-adv: impro... |
1330 1331 |
{ uint16_t total = 0, total_one; |
807736f6e batman-adv: Split... |
1332 |
struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
56303d34a batman-adv: Prefi... |
1333 1334 |
struct batadv_tt_common_entry *tt_common; struct batadv_tt_global_entry *tt_global; |
a73105b8d batman-adv: impro... |
1335 |
struct hlist_head *head; |
c90681b85 batman-adv: fixed... |
1336 1337 |
uint32_t i; int j; |
a73105b8d batman-adv: impro... |
1338 1339 1340 1341 1342 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
1343 |
hlist_for_each_entry_rcu(tt_common, head, hash_entry) { |
56303d34a batman-adv: Prefi... |
1344 1345 1346 |
tt_global = container_of(tt_common, struct batadv_tt_global_entry, common); |
db08e6e55 batman-adv: allow... |
1347 1348 1349 1350 1351 |
/* Roaming clients are in the global table for * consistency only. They don't have to be * taken into account while computing the * global crc */ |
acd34afa8 batman-adv: Prefi... |
1352 |
if (tt_common->flags & BATADV_TT_CLIENT_ROAM) |
db08e6e55 batman-adv: allow... |
1353 |
continue; |
30cfd02b6 batman-adv: detec... |
1354 1355 1356 1357 1358 1359 |
/* Temporary clients have not been announced yet, so * they have to be skipped while computing the global * crc */ if (tt_common->flags & BATADV_TT_CLIENT_TEMP) continue; |
db08e6e55 batman-adv: allow... |
1360 1361 1362 1363 |
/* find out if this global entry is announced by this * originator */ |
56303d34a batman-adv: Prefi... |
1364 |
if (!batadv_tt_global_entry_has_orig(tt_global, |
a513088d0 batman-adv: Prefi... |
1365 |
orig_node)) |
db08e6e55 batman-adv: allow... |
1366 1367 1368 1369 1370 |
continue; total_one = 0; for (j = 0; j < ETH_ALEN; j++) total_one = crc16_byte(total_one, |
acd34afa8 batman-adv: Prefi... |
1371 |
tt_common->addr[j]); |
db08e6e55 batman-adv: allow... |
1372 |
total ^= total_one; |
a73105b8d batman-adv: impro... |
1373 1374 1375 1376 1377 1378 1379 1380 |
} rcu_read_unlock(); } return total; } /* Calculates the checksum of the local table */ |
56303d34a batman-adv: Prefi... |
1381 |
static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv) |
a73105b8d batman-adv: impro... |
1382 1383 |
{ uint16_t total = 0, total_one; |
807736f6e batman-adv: Split... |
1384 |
struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
56303d34a batman-adv: Prefi... |
1385 |
struct batadv_tt_common_entry *tt_common; |
a73105b8d batman-adv: impro... |
1386 |
struct hlist_head *head; |
c90681b85 batman-adv: fixed... |
1387 1388 |
uint32_t i; int j; |
a73105b8d batman-adv: impro... |
1389 1390 1391 1392 1393 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
1394 |
hlist_for_each_entry_rcu(tt_common, head, hash_entry) { |
058d0e269 batman-adv: keep ... |
1395 |
/* not yet committed clients have not to be taken into |
9cfc7bd60 batman-adv: Refor... |
1396 1397 |
* account while computing the CRC */ |
acd34afa8 batman-adv: Prefi... |
1398 |
if (tt_common->flags & BATADV_TT_CLIENT_NEW) |
058d0e269 batman-adv: keep ... |
1399 |
continue; |
a73105b8d batman-adv: impro... |
1400 1401 1402 |
total_one = 0; for (j = 0; j < ETH_ALEN; j++) total_one = crc16_byte(total_one, |
acd34afa8 batman-adv: Prefi... |
1403 |
tt_common->addr[j]); |
a73105b8d batman-adv: impro... |
1404 1405 |
total ^= total_one; } |
a73105b8d batman-adv: impro... |
1406 1407 1408 1409 1410 |
rcu_read_unlock(); } return total; } |
56303d34a batman-adv: Prefi... |
1411 |
static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) |
a73105b8d batman-adv: impro... |
1412 |
{ |
56303d34a batman-adv: Prefi... |
1413 |
struct batadv_tt_req_node *node, *safe; |
a73105b8d batman-adv: impro... |
1414 |
|
807736f6e batman-adv: Split... |
1415 |
spin_lock_bh(&bat_priv->tt.req_list_lock); |
a73105b8d batman-adv: impro... |
1416 |
|
807736f6e batman-adv: Split... |
1417 |
list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
a73105b8d batman-adv: impro... |
1418 1419 1420 |
list_del(&node->list); kfree(node); } |
807736f6e batman-adv: Split... |
1421 |
spin_unlock_bh(&bat_priv->tt.req_list_lock); |
a73105b8d batman-adv: impro... |
1422 |
} |
56303d34a batman-adv: Prefi... |
1423 1424 |
static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, |
a513088d0 batman-adv: Prefi... |
1425 1426 |
const unsigned char *tt_buff, uint8_t tt_num_changes) |
a73105b8d batman-adv: impro... |
1427 |
{ |
08c36d3e8 batman-adv: Prefi... |
1428 |
uint16_t tt_buff_len = batadv_tt_len(tt_num_changes); |
a73105b8d batman-adv: impro... |
1429 1430 |
/* Replace the old buffer only if I received something in the |
9cfc7bd60 batman-adv: Refor... |
1431 1432 |
* last OGM (the OGM could carry no changes) */ |
a73105b8d batman-adv: impro... |
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 |
spin_lock_bh(&orig_node->tt_buff_lock); if (tt_buff_len > 0) { kfree(orig_node->tt_buff); orig_node->tt_buff_len = 0; orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC); if (orig_node->tt_buff) { memcpy(orig_node->tt_buff, tt_buff, tt_buff_len); orig_node->tt_buff_len = tt_buff_len; } } spin_unlock_bh(&orig_node->tt_buff_lock); } |
56303d34a batman-adv: Prefi... |
1445 |
static void batadv_tt_req_purge(struct batadv_priv *bat_priv) |
a73105b8d batman-adv: impro... |
1446 |
{ |
56303d34a batman-adv: Prefi... |
1447 |
struct batadv_tt_req_node *node, *safe; |
a73105b8d batman-adv: impro... |
1448 |
|
807736f6e batman-adv: Split... |
1449 1450 |
spin_lock_bh(&bat_priv->tt.req_list_lock); list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
42d0b044b batman-adv: Prefi... |
1451 1452 |
if (batadv_has_timed_out(node->issued_at, BATADV_TT_REQUEST_TIMEOUT)) { |
a73105b8d batman-adv: impro... |
1453 1454 1455 1456 |
list_del(&node->list); kfree(node); } } |
807736f6e batman-adv: Split... |
1457 |
spin_unlock_bh(&bat_priv->tt.req_list_lock); |
a73105b8d batman-adv: impro... |
1458 1459 1460 |
} /* returns the pointer to the new tt_req_node struct if no request |
9cfc7bd60 batman-adv: Refor... |
1461 1462 |
* has already been issued for this orig_node, NULL otherwise */ |
56303d34a batman-adv: Prefi... |
1463 1464 1465 |
static struct batadv_tt_req_node * batadv_new_tt_req_node(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node) |
a73105b8d batman-adv: impro... |
1466 |
{ |
56303d34a batman-adv: Prefi... |
1467 |
struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL; |
a73105b8d batman-adv: impro... |
1468 |
|
807736f6e batman-adv: Split... |
1469 1470 |
spin_lock_bh(&bat_priv->tt.req_list_lock); list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) { |
1eda58bfc batman-adv: Prefi... |
1471 1472 |
if (batadv_compare_eth(tt_req_node_tmp, orig_node) && !batadv_has_timed_out(tt_req_node_tmp->issued_at, |
42d0b044b batman-adv: Prefi... |
1473 |
BATADV_TT_REQUEST_TIMEOUT)) |
a73105b8d batman-adv: impro... |
1474 1475 1476 1477 1478 1479 1480 1481 1482 |
goto unlock; } tt_req_node = kmalloc(sizeof(*tt_req_node), GFP_ATOMIC); if (!tt_req_node) goto unlock; memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN); tt_req_node->issued_at = jiffies; |
807736f6e batman-adv: Split... |
1483 |
list_add(&tt_req_node->list, &bat_priv->tt.req_list); |
a73105b8d batman-adv: impro... |
1484 |
unlock: |
807736f6e batman-adv: Split... |
1485 |
spin_unlock_bh(&bat_priv->tt.req_list_lock); |
a73105b8d batman-adv: impro... |
1486 1487 |
return tt_req_node; } |
058d0e269 batman-adv: keep ... |
1488 |
/* data_ptr is useless here, but has to be kept to respect the prototype */ |
a513088d0 batman-adv: Prefi... |
1489 1490 |
static int batadv_tt_local_valid_entry(const void *entry_ptr, const void *data_ptr) |
058d0e269 batman-adv: keep ... |
1491 |
{ |
56303d34a batman-adv: Prefi... |
1492 |
const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; |
058d0e269 batman-adv: keep ... |
1493 |
|
acd34afa8 batman-adv: Prefi... |
1494 |
if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW) |
058d0e269 batman-adv: keep ... |
1495 1496 1497 |
return 0; return 1; } |
a513088d0 batman-adv: Prefi... |
1498 1499 |
static int batadv_tt_global_valid(const void *entry_ptr, const void *data_ptr) |
a73105b8d batman-adv: impro... |
1500 |
{ |
56303d34a batman-adv: Prefi... |
1501 1502 1503 |
const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; const struct batadv_tt_global_entry *tt_global_entry; const struct batadv_orig_node *orig_node = data_ptr; |
a73105b8d batman-adv: impro... |
1504 |
|
30cfd02b6 batman-adv: detec... |
1505 1506 |
if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM || tt_common_entry->flags & BATADV_TT_CLIENT_TEMP) |
cc47f66e6 batman-adv: impro... |
1507 |
return 0; |
56303d34a batman-adv: Prefi... |
1508 1509 |
tt_global_entry = container_of(tt_common_entry, struct batadv_tt_global_entry, |
48100bac8 batman-adv: creat... |
1510 |
common); |
a513088d0 batman-adv: Prefi... |
1511 |
return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node); |
a73105b8d batman-adv: impro... |
1512 |
} |
a513088d0 batman-adv: Prefi... |
1513 1514 |
static struct sk_buff * batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, |
5bf74e9ca batman-adv: Prefi... |
1515 |
struct batadv_hashtable *hash, |
736292c2e batman-adv: repla... |
1516 |
struct batadv_priv *bat_priv, |
a513088d0 batman-adv: Prefi... |
1517 1518 |
int (*valid_cb)(const void *, const void *), void *cb_data) |
a73105b8d batman-adv: impro... |
1519 |
{ |
56303d34a batman-adv: Prefi... |
1520 |
struct batadv_tt_common_entry *tt_common_entry; |
964126901 batman-adv: Prefi... |
1521 1522 |
struct batadv_tt_query_packet *tt_response; struct batadv_tt_change *tt_change; |
a73105b8d batman-adv: impro... |
1523 1524 1525 |
struct hlist_head *head; struct sk_buff *skb = NULL; uint16_t tt_tot, tt_count; |
964126901 batman-adv: Prefi... |
1526 |
ssize_t tt_query_size = sizeof(struct batadv_tt_query_packet); |
c90681b85 batman-adv: fixed... |
1527 |
uint32_t i; |
964126901 batman-adv: Prefi... |
1528 |
size_t len; |
a73105b8d batman-adv: impro... |
1529 |
|
736292c2e batman-adv: repla... |
1530 1531 |
if (tt_query_size + tt_len > bat_priv->soft_iface->mtu) { tt_len = bat_priv->soft_iface->mtu - tt_query_size; |
964126901 batman-adv: Prefi... |
1532 |
tt_len -= tt_len % sizeof(struct batadv_tt_change); |
a73105b8d batman-adv: impro... |
1533 |
} |
964126901 batman-adv: Prefi... |
1534 |
tt_tot = tt_len / sizeof(struct batadv_tt_change); |
a73105b8d batman-adv: impro... |
1535 |
|
964126901 batman-adv: Prefi... |
1536 |
len = tt_query_size + tt_len; |
5b2465744 batman-adv: Reser... |
1537 |
skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); |
a73105b8d batman-adv: impro... |
1538 1539 |
if (!skb) goto out; |
5b2465744 batman-adv: Reser... |
1540 |
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
964126901 batman-adv: Prefi... |
1541 |
tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len); |
a73105b8d batman-adv: impro... |
1542 |
tt_response->ttvn = ttvn; |
a73105b8d batman-adv: impro... |
1543 |
|
964126901 batman-adv: Prefi... |
1544 |
tt_change = (struct batadv_tt_change *)(skb->data + tt_query_size); |
a73105b8d batman-adv: impro... |
1545 1546 1547 1548 1549 |
tt_count = 0; rcu_read_lock(); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
b67bfe0d4 hlist: drop the n... |
1550 |
hlist_for_each_entry_rcu(tt_common_entry, |
a73105b8d batman-adv: impro... |
1551 1552 1553 |
head, hash_entry) { if (tt_count == tt_tot) break; |
48100bac8 batman-adv: creat... |
1554 |
if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) |
a73105b8d batman-adv: impro... |
1555 |
continue; |
48100bac8 batman-adv: creat... |
1556 1557 |
memcpy(tt_change->addr, tt_common_entry->addr, ETH_ALEN); |
27b37ebfa batman-adv: corre... |
1558 |
tt_change->flags = tt_common_entry->flags; |
a73105b8d batman-adv: impro... |
1559 1560 1561 1562 1563 1564 |
tt_count++; tt_change++; } } rcu_read_unlock(); |
9d8523931 batman-adv: corre... |
1565 |
/* store in the message the number of entries we have successfully |
9cfc7bd60 batman-adv: Refor... |
1566 1567 |
* copied */ |
9d8523931 batman-adv: corre... |
1568 |
tt_response->tt_data = htons(tt_count); |
a73105b8d batman-adv: impro... |
1569 1570 1571 |
out: return skb; } |
56303d34a batman-adv: Prefi... |
1572 1573 |
static int batadv_send_tt_request(struct batadv_priv *bat_priv, struct batadv_orig_node *dst_orig_node, |
a513088d0 batman-adv: Prefi... |
1574 1575 |
uint8_t ttvn, uint16_t tt_crc, bool full_table) |
a73105b8d batman-adv: impro... |
1576 1577 |
{ struct sk_buff *skb = NULL; |
964126901 batman-adv: Prefi... |
1578 |
struct batadv_tt_query_packet *tt_request; |
56303d34a batman-adv: Prefi... |
1579 1580 |
struct batadv_hard_iface *primary_if; struct batadv_tt_req_node *tt_req_node = NULL; |
a73105b8d batman-adv: impro... |
1581 |
int ret = 1; |
964126901 batman-adv: Prefi... |
1582 |
size_t tt_req_len; |
a73105b8d batman-adv: impro... |
1583 |
|
e5d89254b batman-adv: Prefi... |
1584 |
primary_if = batadv_primary_if_get_selected(bat_priv); |
a73105b8d batman-adv: impro... |
1585 1586 1587 1588 |
if (!primary_if) goto out; /* The new tt_req will be issued only if I'm not waiting for a |
9cfc7bd60 batman-adv: Refor... |
1589 1590 |
* reply from the same orig_node yet */ |
a513088d0 batman-adv: Prefi... |
1591 |
tt_req_node = batadv_new_tt_req_node(bat_priv, dst_orig_node); |
a73105b8d batman-adv: impro... |
1592 1593 |
if (!tt_req_node) goto out; |
5b2465744 batman-adv: Reser... |
1594 |
skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN); |
a73105b8d batman-adv: impro... |
1595 1596 |
if (!skb) goto out; |
5b2465744 batman-adv: Reser... |
1597 |
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
a73105b8d batman-adv: impro... |
1598 |
|
964126901 batman-adv: Prefi... |
1599 1600 |
tt_req_len = sizeof(*tt_request); tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len); |
a73105b8d batman-adv: impro... |
1601 |
|
acd34afa8 batman-adv: Prefi... |
1602 |
tt_request->header.packet_type = BATADV_TT_QUERY; |
7e071c79a batman-adv: Prefi... |
1603 |
tt_request->header.version = BATADV_COMPAT_VERSION; |
a73105b8d batman-adv: impro... |
1604 1605 |
memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN); |
42d0b044b batman-adv: Prefi... |
1606 |
tt_request->header.ttl = BATADV_TTL; |
a73105b8d batman-adv: impro... |
1607 |
tt_request->ttvn = ttvn; |
6d2003fc2 batman-adv: conve... |
1608 |
tt_request->tt_data = htons(tt_crc); |
acd34afa8 batman-adv: Prefi... |
1609 |
tt_request->flags = BATADV_TT_REQUEST; |
a73105b8d batman-adv: impro... |
1610 1611 |
if (full_table) |
acd34afa8 batman-adv: Prefi... |
1612 |
tt_request->flags |= BATADV_TT_FULL_TABLE; |
a73105b8d batman-adv: impro... |
1613 |
|
bb351ba0b batman-adv: Add w... |
1614 1615 1616 |
batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c] ", dst_orig_node->orig, (full_table ? 'F' : '.')); |
a73105b8d batman-adv: impro... |
1617 |
|
d69909d2f batman-adv: Prefi... |
1618 |
batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX); |
f8214865a batman-adv: Add g... |
1619 |
|
bb351ba0b batman-adv: Add w... |
1620 1621 |
if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL)) ret = 0; |
a73105b8d batman-adv: impro... |
1622 1623 |
out: |
a73105b8d batman-adv: impro... |
1624 |
if (primary_if) |
e5d89254b batman-adv: Prefi... |
1625 |
batadv_hardif_free_ref(primary_if); |
a73105b8d batman-adv: impro... |
1626 1627 1628 |
if (ret) kfree_skb(skb); if (ret && tt_req_node) { |
807736f6e batman-adv: Split... |
1629 |
spin_lock_bh(&bat_priv->tt.req_list_lock); |
a73105b8d batman-adv: impro... |
1630 |
list_del(&tt_req_node->list); |
807736f6e batman-adv: Split... |
1631 |
spin_unlock_bh(&bat_priv->tt.req_list_lock); |
a73105b8d batman-adv: impro... |
1632 1633 1634 1635 |
kfree(tt_req_node); } return ret; } |
964126901 batman-adv: Prefi... |
1636 |
static bool |
56303d34a batman-adv: Prefi... |
1637 |
batadv_send_other_tt_response(struct batadv_priv *bat_priv, |
964126901 batman-adv: Prefi... |
1638 |
struct batadv_tt_query_packet *tt_request) |
a73105b8d batman-adv: impro... |
1639 |
{ |
170173bf3 batman-adv: Remov... |
1640 |
struct batadv_orig_node *req_dst_orig_node; |
56303d34a batman-adv: Prefi... |
1641 |
struct batadv_orig_node *res_dst_orig_node = NULL; |
a73105b8d batman-adv: impro... |
1642 1643 1644 1645 1646 1647 |
uint8_t orig_ttvn, req_ttvn, ttvn; int ret = false; unsigned char *tt_buff; bool full_table; uint16_t tt_len, tt_tot; struct sk_buff *skb = NULL; |
964126901 batman-adv: Prefi... |
1648 |
struct batadv_tt_query_packet *tt_response; |
c67893d17 batman-adv: Reduc... |
1649 |
uint8_t *packet_pos; |
964126901 batman-adv: Prefi... |
1650 |
size_t len; |
a73105b8d batman-adv: impro... |
1651 |
|
39c75a51e batman-adv: Prefi... |
1652 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
1653 1654 1655 |
"Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c] ", tt_request->src, tt_request->ttvn, tt_request->dst, |
acd34afa8 batman-adv: Prefi... |
1656 |
(tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); |
a73105b8d batman-adv: impro... |
1657 1658 |
/* Let's get the orig node of the REAL destination */ |
da641193d batman-adv: Prefi... |
1659 |
req_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->dst); |
a73105b8d batman-adv: impro... |
1660 1661 |
if (!req_dst_orig_node) goto out; |
da641193d batman-adv: Prefi... |
1662 |
res_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); |
a73105b8d batman-adv: impro... |
1663 1664 |
if (!res_dst_orig_node) goto out; |
a73105b8d batman-adv: impro... |
1665 1666 |
orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); req_ttvn = tt_request->ttvn; |
015758d00 batman-adv: corre... |
1667 |
/* I don't have the requested data */ |
a73105b8d batman-adv: impro... |
1668 |
if (orig_ttvn != req_ttvn || |
f25bd58a9 batman-adv: don't... |
1669 |
tt_request->tt_data != htons(req_dst_orig_node->tt_crc)) |
a73105b8d batman-adv: impro... |
1670 |
goto out; |
015758d00 batman-adv: corre... |
1671 |
/* If the full table has been explicitly requested */ |
acd34afa8 batman-adv: Prefi... |
1672 |
if (tt_request->flags & BATADV_TT_FULL_TABLE || |
a73105b8d batman-adv: impro... |
1673 1674 1675 1676 1677 1678 |
!req_dst_orig_node->tt_buff) full_table = true; else full_table = false; /* In this version, fragmentation is not implemented, then |
9cfc7bd60 batman-adv: Refor... |
1679 1680 |
* I'll send only one packet with as much TT entries as I can */ |
a73105b8d batman-adv: impro... |
1681 1682 1683 |
if (!full_table) { spin_lock_bh(&req_dst_orig_node->tt_buff_lock); tt_len = req_dst_orig_node->tt_buff_len; |
964126901 batman-adv: Prefi... |
1684 |
tt_tot = tt_len / sizeof(struct batadv_tt_change); |
a73105b8d batman-adv: impro... |
1685 |
|
964126901 batman-adv: Prefi... |
1686 |
len = sizeof(*tt_response) + tt_len; |
5b2465744 batman-adv: Reser... |
1687 |
skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); |
a73105b8d batman-adv: impro... |
1688 1689 |
if (!skb) goto unlock; |
5b2465744 batman-adv: Reser... |
1690 |
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
c67893d17 batman-adv: Reduc... |
1691 1692 |
packet_pos = skb_put(skb, len); tt_response = (struct batadv_tt_query_packet *)packet_pos; |
a73105b8d batman-adv: impro... |
1693 1694 |
tt_response->ttvn = req_ttvn; tt_response->tt_data = htons(tt_tot); |
964126901 batman-adv: Prefi... |
1695 |
tt_buff = skb->data + sizeof(*tt_response); |
a73105b8d batman-adv: impro... |
1696 1697 1698 1699 1700 1701 |
/* Copy the last orig_node's OGM buffer */ memcpy(tt_buff, req_dst_orig_node->tt_buff, req_dst_orig_node->tt_buff_len); spin_unlock_bh(&req_dst_orig_node->tt_buff_lock); } else { |
964126901 batman-adv: Prefi... |
1702 1703 |
tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size); tt_len *= sizeof(struct batadv_tt_change); |
a73105b8d batman-adv: impro... |
1704 |
ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); |
a513088d0 batman-adv: Prefi... |
1705 |
skb = batadv_tt_response_fill_table(tt_len, ttvn, |
807736f6e batman-adv: Split... |
1706 |
bat_priv->tt.global_hash, |
736292c2e batman-adv: repla... |
1707 |
bat_priv, |
a513088d0 batman-adv: Prefi... |
1708 1709 |
batadv_tt_global_valid, req_dst_orig_node); |
a73105b8d batman-adv: impro... |
1710 1711 |
if (!skb) goto out; |
964126901 batman-adv: Prefi... |
1712 |
tt_response = (struct batadv_tt_query_packet *)skb->data; |
a73105b8d batman-adv: impro... |
1713 |
} |
acd34afa8 batman-adv: Prefi... |
1714 |
tt_response->header.packet_type = BATADV_TT_QUERY; |
7e071c79a batman-adv: Prefi... |
1715 |
tt_response->header.version = BATADV_COMPAT_VERSION; |
42d0b044b batman-adv: Prefi... |
1716 |
tt_response->header.ttl = BATADV_TTL; |
a73105b8d batman-adv: impro... |
1717 1718 |
memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN); memcpy(tt_response->dst, tt_request->src, ETH_ALEN); |
acd34afa8 batman-adv: Prefi... |
1719 |
tt_response->flags = BATADV_TT_RESPONSE; |
a73105b8d batman-adv: impro... |
1720 1721 |
if (full_table) |
acd34afa8 batman-adv: Prefi... |
1722 |
tt_response->flags |= BATADV_TT_FULL_TABLE; |
a73105b8d batman-adv: impro... |
1723 |
|
39c75a51e batman-adv: Prefi... |
1724 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
bb351ba0b batman-adv: Add w... |
1725 1726 1727 |
"Sending TT_RESPONSE %pM for %pM (ttvn: %u) ", res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn); |
a73105b8d batman-adv: impro... |
1728 |
|
d69909d2f batman-adv: Prefi... |
1729 |
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); |
f8214865a batman-adv: Add g... |
1730 |
|
bb351ba0b batman-adv: Add w... |
1731 1732 |
if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL)) ret = true; |
a73105b8d batman-adv: impro... |
1733 1734 1735 1736 1737 1738 1739 |
goto out; unlock: spin_unlock_bh(&req_dst_orig_node->tt_buff_lock); out: if (res_dst_orig_node) |
7d211efc5 batman-adv: Prefi... |
1740 |
batadv_orig_node_free_ref(res_dst_orig_node); |
a73105b8d batman-adv: impro... |
1741 |
if (req_dst_orig_node) |
7d211efc5 batman-adv: Prefi... |
1742 |
batadv_orig_node_free_ref(req_dst_orig_node); |
a73105b8d batman-adv: impro... |
1743 1744 1745 |
if (!ret) kfree_skb(skb); return ret; |
a73105b8d batman-adv: impro... |
1746 |
} |
964126901 batman-adv: Prefi... |
1747 1748 |
static bool |
56303d34a batman-adv: Prefi... |
1749 |
batadv_send_my_tt_response(struct batadv_priv *bat_priv, |
964126901 batman-adv: Prefi... |
1750 |
struct batadv_tt_query_packet *tt_request) |
a73105b8d batman-adv: impro... |
1751 |
{ |
170173bf3 batman-adv: Remov... |
1752 |
struct batadv_orig_node *orig_node; |
56303d34a batman-adv: Prefi... |
1753 |
struct batadv_hard_iface *primary_if = NULL; |
a73105b8d batman-adv: impro... |
1754 1755 1756 1757 1758 1759 |
uint8_t my_ttvn, req_ttvn, ttvn; int ret = false; unsigned char *tt_buff; bool full_table; uint16_t tt_len, tt_tot; struct sk_buff *skb = NULL; |
964126901 batman-adv: Prefi... |
1760 |
struct batadv_tt_query_packet *tt_response; |
c67893d17 batman-adv: Reduc... |
1761 |
uint8_t *packet_pos; |
964126901 batman-adv: Prefi... |
1762 |
size_t len; |
a73105b8d batman-adv: impro... |
1763 |
|
39c75a51e batman-adv: Prefi... |
1764 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
1765 1766 1767 |
"Received TT_REQUEST from %pM for ttvn: %u (me) [%c] ", tt_request->src, tt_request->ttvn, |
acd34afa8 batman-adv: Prefi... |
1768 |
(tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); |
a73105b8d batman-adv: impro... |
1769 |
|
807736f6e batman-adv: Split... |
1770 |
my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); |
a73105b8d batman-adv: impro... |
1771 |
req_ttvn = tt_request->ttvn; |
da641193d batman-adv: Prefi... |
1772 |
orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); |
a73105b8d batman-adv: impro... |
1773 1774 |
if (!orig_node) goto out; |
e5d89254b batman-adv: Prefi... |
1775 |
primary_if = batadv_primary_if_get_selected(bat_priv); |
a73105b8d batman-adv: impro... |
1776 1777 1778 1779 |
if (!primary_if) goto out; /* If the full table has been explicitly requested or the gap |
9cfc7bd60 batman-adv: Refor... |
1780 1781 |
* is too big send the whole local translation table */ |
acd34afa8 batman-adv: Prefi... |
1782 |
if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || |
807736f6e batman-adv: Split... |
1783 |
!bat_priv->tt.last_changeset) |
a73105b8d batman-adv: impro... |
1784 1785 1786 1787 1788 |
full_table = true; else full_table = false; /* In this version, fragmentation is not implemented, then |
9cfc7bd60 batman-adv: Refor... |
1789 1790 |
* I'll send only one packet with as much TT entries as I can */ |
a73105b8d batman-adv: impro... |
1791 |
if (!full_table) { |
807736f6e batman-adv: Split... |
1792 1793 |
spin_lock_bh(&bat_priv->tt.last_changeset_lock); tt_len = bat_priv->tt.last_changeset_len; |
964126901 batman-adv: Prefi... |
1794 |
tt_tot = tt_len / sizeof(struct batadv_tt_change); |
a73105b8d batman-adv: impro... |
1795 |
|
964126901 batman-adv: Prefi... |
1796 |
len = sizeof(*tt_response) + tt_len; |
5b2465744 batman-adv: Reser... |
1797 |
skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); |
a73105b8d batman-adv: impro... |
1798 1799 |
if (!skb) goto unlock; |
5b2465744 batman-adv: Reser... |
1800 |
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
c67893d17 batman-adv: Reduc... |
1801 1802 |
packet_pos = skb_put(skb, len); tt_response = (struct batadv_tt_query_packet *)packet_pos; |
a73105b8d batman-adv: impro... |
1803 1804 |
tt_response->ttvn = req_ttvn; tt_response->tt_data = htons(tt_tot); |
964126901 batman-adv: Prefi... |
1805 |
tt_buff = skb->data + sizeof(*tt_response); |
807736f6e batman-adv: Split... |
1806 1807 1808 |
memcpy(tt_buff, bat_priv->tt.last_changeset, bat_priv->tt.last_changeset_len); spin_unlock_bh(&bat_priv->tt.last_changeset_lock); |
a73105b8d batman-adv: impro... |
1809 |
} else { |
807736f6e batman-adv: Split... |
1810 |
tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num); |
964126901 batman-adv: Prefi... |
1811 |
tt_len *= sizeof(struct batadv_tt_change); |
807736f6e batman-adv: Split... |
1812 |
ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); |
a73105b8d batman-adv: impro... |
1813 |
|
a513088d0 batman-adv: Prefi... |
1814 |
skb = batadv_tt_response_fill_table(tt_len, ttvn, |
807736f6e batman-adv: Split... |
1815 |
bat_priv->tt.local_hash, |
736292c2e batman-adv: repla... |
1816 |
bat_priv, |
a513088d0 batman-adv: Prefi... |
1817 1818 |
batadv_tt_local_valid_entry, NULL); |
a73105b8d batman-adv: impro... |
1819 1820 |
if (!skb) goto out; |
964126901 batman-adv: Prefi... |
1821 |
tt_response = (struct batadv_tt_query_packet *)skb->data; |
a73105b8d batman-adv: impro... |
1822 |
} |
acd34afa8 batman-adv: Prefi... |
1823 |
tt_response->header.packet_type = BATADV_TT_QUERY; |
7e071c79a batman-adv: Prefi... |
1824 |
tt_response->header.version = BATADV_COMPAT_VERSION; |
42d0b044b batman-adv: Prefi... |
1825 |
tt_response->header.ttl = BATADV_TTL; |
a73105b8d batman-adv: impro... |
1826 1827 |
memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(tt_response->dst, tt_request->src, ETH_ALEN); |
acd34afa8 batman-adv: Prefi... |
1828 |
tt_response->flags = BATADV_TT_RESPONSE; |
a73105b8d batman-adv: impro... |
1829 1830 |
if (full_table) |
acd34afa8 batman-adv: Prefi... |
1831 |
tt_response->flags |= BATADV_TT_FULL_TABLE; |
a73105b8d batman-adv: impro... |
1832 |
|
39c75a51e batman-adv: Prefi... |
1833 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
bb351ba0b batman-adv: Add w... |
1834 1835 1836 |
"Sending TT_RESPONSE to %pM [%c] ", orig_node->orig, |
acd34afa8 batman-adv: Prefi... |
1837 |
(tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); |
a73105b8d batman-adv: impro... |
1838 |
|
d69909d2f batman-adv: Prefi... |
1839 |
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); |
f8214865a batman-adv: Add g... |
1840 |
|
bb351ba0b batman-adv: Add w... |
1841 1842 |
if (batadv_send_skb_to_orig(skb, orig_node, NULL)) ret = true; |
a73105b8d batman-adv: impro... |
1843 1844 1845 |
goto out; unlock: |
807736f6e batman-adv: Split... |
1846 |
spin_unlock_bh(&bat_priv->tt.last_changeset_lock); |
a73105b8d batman-adv: impro... |
1847 1848 |
out: if (orig_node) |
7d211efc5 batman-adv: Prefi... |
1849 |
batadv_orig_node_free_ref(orig_node); |
a73105b8d batman-adv: impro... |
1850 |
if (primary_if) |
e5d89254b batman-adv: Prefi... |
1851 |
batadv_hardif_free_ref(primary_if); |
a73105b8d batman-adv: impro... |
1852 1853 1854 1855 1856 |
if (!ret) kfree_skb(skb); /* This packet was for me, so it doesn't need to be re-routed */ return true; } |
56303d34a batman-adv: Prefi... |
1857 |
bool batadv_send_tt_response(struct batadv_priv *bat_priv, |
964126901 batman-adv: Prefi... |
1858 |
struct batadv_tt_query_packet *tt_request) |
a73105b8d batman-adv: impro... |
1859 |
{ |
fe8a93b95 batman-adv: make ... |
1860 |
if (batadv_is_my_mac(bat_priv, tt_request->dst)) { |
20ff9d593 batman-adv: don't... |
1861 |
/* don't answer backbone gws! */ |
08adf1512 batman-adv: Prefi... |
1862 |
if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_request->src)) |
20ff9d593 batman-adv: don't... |
1863 |
return true; |
a513088d0 batman-adv: Prefi... |
1864 |
return batadv_send_my_tt_response(bat_priv, tt_request); |
20ff9d593 batman-adv: don't... |
1865 |
} else { |
a513088d0 batman-adv: Prefi... |
1866 |
return batadv_send_other_tt_response(bat_priv, tt_request); |
20ff9d593 batman-adv: don't... |
1867 |
} |
a73105b8d batman-adv: impro... |
1868 |
} |
56303d34a batman-adv: Prefi... |
1869 1870 |
static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, |
964126901 batman-adv: Prefi... |
1871 |
struct batadv_tt_change *tt_change, |
a513088d0 batman-adv: Prefi... |
1872 |
uint16_t tt_num_changes, uint8_t ttvn) |
a73105b8d batman-adv: impro... |
1873 1874 |
{ int i; |
a513088d0 batman-adv: Prefi... |
1875 |
int roams; |
a73105b8d batman-adv: impro... |
1876 1877 |
for (i = 0; i < tt_num_changes; i++) { |
acd34afa8 batman-adv: Prefi... |
1878 1879 |
if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) { roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM; |
a513088d0 batman-adv: Prefi... |
1880 1881 |
batadv_tt_global_del(bat_priv, orig_node, (tt_change + i)->addr, |
d4f446925 batman-adv: beaut... |
1882 1883 |
"tt removed by changes", roams); |
08c36d3e8 batman-adv: Prefi... |
1884 |
} else { |
08c36d3e8 batman-adv: Prefi... |
1885 |
if (!batadv_tt_global_add(bat_priv, orig_node, |
d4f446925 batman-adv: beaut... |
1886 1887 |
(tt_change + i)->addr, (tt_change + i)->flags, ttvn)) |
a73105b8d batman-adv: impro... |
1888 1889 1890 1891 1892 1893 1894 |
/* In case of problem while storing a * global_entry, we stop the updating * procedure without committing the * ttvn change. This will avoid to send * corrupted data on tt_request */ return; |
08c36d3e8 batman-adv: Prefi... |
1895 |
} |
a73105b8d batman-adv: impro... |
1896 |
} |
170715788 batman-adv: add t... |
1897 |
orig_node->tt_initialised = true; |
a73105b8d batman-adv: impro... |
1898 |
} |
56303d34a batman-adv: Prefi... |
1899 |
static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, |
964126901 batman-adv: Prefi... |
1900 |
struct batadv_tt_query_packet *tt_response) |
a73105b8d batman-adv: impro... |
1901 |
{ |
170173bf3 batman-adv: Remov... |
1902 |
struct batadv_orig_node *orig_node; |
a73105b8d batman-adv: impro... |
1903 |
|
da641193d batman-adv: Prefi... |
1904 |
orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); |
a73105b8d batman-adv: impro... |
1905 1906 1907 1908 |
if (!orig_node) goto out; /* Purge the old table first.. */ |
08c36d3e8 batman-adv: Prefi... |
1909 |
batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table"); |
a73105b8d batman-adv: impro... |
1910 |
|
a513088d0 batman-adv: Prefi... |
1911 |
_batadv_tt_update_changes(bat_priv, orig_node, |
964126901 batman-adv: Prefi... |
1912 |
(struct batadv_tt_change *)(tt_response + 1), |
a513088d0 batman-adv: Prefi... |
1913 1914 |
ntohs(tt_response->tt_data), tt_response->ttvn); |
a73105b8d batman-adv: impro... |
1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 |
spin_lock_bh(&orig_node->tt_buff_lock); kfree(orig_node->tt_buff); orig_node->tt_buff_len = 0; orig_node->tt_buff = NULL; spin_unlock_bh(&orig_node->tt_buff_lock); atomic_set(&orig_node->last_ttvn, tt_response->ttvn); out: if (orig_node) |
7d211efc5 batman-adv: Prefi... |
1926 |
batadv_orig_node_free_ref(orig_node); |
a73105b8d batman-adv: impro... |
1927 |
} |
56303d34a batman-adv: Prefi... |
1928 1929 |
static void batadv_tt_update_changes(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, |
a513088d0 batman-adv: Prefi... |
1930 |
uint16_t tt_num_changes, uint8_t ttvn, |
964126901 batman-adv: Prefi... |
1931 |
struct batadv_tt_change *tt_change) |
a73105b8d batman-adv: impro... |
1932 |
{ |
a513088d0 batman-adv: Prefi... |
1933 1934 |
_batadv_tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes, ttvn); |
a73105b8d batman-adv: impro... |
1935 |
|
a513088d0 batman-adv: Prefi... |
1936 1937 |
batadv_tt_save_orig_buffer(bat_priv, orig_node, (unsigned char *)tt_change, tt_num_changes); |
a73105b8d batman-adv: impro... |
1938 1939 |
atomic_set(&orig_node->last_ttvn, ttvn); } |
56303d34a batman-adv: Prefi... |
1940 |
bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) |
a73105b8d batman-adv: impro... |
1941 |
{ |
170173bf3 batman-adv: Remov... |
1942 |
struct batadv_tt_local_entry *tt_local_entry; |
7683fdc1e batman-adv: prote... |
1943 |
bool ret = false; |
a73105b8d batman-adv: impro... |
1944 |
|
a513088d0 batman-adv: Prefi... |
1945 |
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); |
7683fdc1e batman-adv: prote... |
1946 1947 |
if (!tt_local_entry) goto out; |
058d0e269 batman-adv: keep ... |
1948 |
/* Check if the client has been logically deleted (but is kept for |
9cfc7bd60 batman-adv: Refor... |
1949 1950 |
* consistency purpose) */ |
7c1fd91da batman-adv: subst... |
1951 1952 |
if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) || (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM)) |
058d0e269 batman-adv: keep ... |
1953 |
goto out; |
7683fdc1e batman-adv: prote... |
1954 1955 |
ret = true; out: |
a73105b8d batman-adv: impro... |
1956 |
if (tt_local_entry) |
a513088d0 batman-adv: Prefi... |
1957 |
batadv_tt_local_entry_free_ref(tt_local_entry); |
7683fdc1e batman-adv: prote... |
1958 |
return ret; |
a73105b8d batman-adv: impro... |
1959 |
} |
56303d34a batman-adv: Prefi... |
1960 |
void batadv_handle_tt_response(struct batadv_priv *bat_priv, |
964126901 batman-adv: Prefi... |
1961 |
struct batadv_tt_query_packet *tt_response) |
a73105b8d batman-adv: impro... |
1962 |
{ |
56303d34a batman-adv: Prefi... |
1963 1964 |
struct batadv_tt_req_node *node, *safe; struct batadv_orig_node *orig_node = NULL; |
964126901 batman-adv: Prefi... |
1965 |
struct batadv_tt_change *tt_change; |
a73105b8d batman-adv: impro... |
1966 |
|
39c75a51e batman-adv: Prefi... |
1967 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
1968 1969 1970 1971 |
"Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c] ", tt_response->src, tt_response->ttvn, ntohs(tt_response->tt_data), |
acd34afa8 batman-adv: Prefi... |
1972 |
(tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); |
a73105b8d batman-adv: impro... |
1973 |
|
20ff9d593 batman-adv: don't... |
1974 |
/* we should have never asked a backbone gw */ |
08adf1512 batman-adv: Prefi... |
1975 |
if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_response->src)) |
20ff9d593 batman-adv: don't... |
1976 |
goto out; |
da641193d batman-adv: Prefi... |
1977 |
orig_node = batadv_orig_hash_find(bat_priv, tt_response->src); |
a73105b8d batman-adv: impro... |
1978 1979 |
if (!orig_node) goto out; |
964126901 batman-adv: Prefi... |
1980 |
if (tt_response->flags & BATADV_TT_FULL_TABLE) { |
a513088d0 batman-adv: Prefi... |
1981 |
batadv_tt_fill_gtable(bat_priv, tt_response); |
964126901 batman-adv: Prefi... |
1982 1983 |
} else { tt_change = (struct batadv_tt_change *)(tt_response + 1); |
a513088d0 batman-adv: Prefi... |
1984 1985 |
batadv_tt_update_changes(bat_priv, orig_node, ntohs(tt_response->tt_data), |
964126901 batman-adv: Prefi... |
1986 1987 |
tt_response->ttvn, tt_change); } |
a73105b8d batman-adv: impro... |
1988 1989 |
/* Delete the tt_req_node from pending tt_requests list */ |
807736f6e batman-adv: Split... |
1990 1991 |
spin_lock_bh(&bat_priv->tt.req_list_lock); list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
1eda58bfc batman-adv: Prefi... |
1992 |
if (!batadv_compare_eth(node->addr, tt_response->src)) |
a73105b8d batman-adv: impro... |
1993 1994 1995 1996 |
continue; list_del(&node->list); kfree(node); } |
807736f6e batman-adv: Split... |
1997 |
spin_unlock_bh(&bat_priv->tt.req_list_lock); |
a73105b8d batman-adv: impro... |
1998 1999 |
/* Recalculate the CRC for this orig_node and store it */ |
a513088d0 batman-adv: Prefi... |
2000 |
orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); |
a73105b8d batman-adv: impro... |
2001 2002 |
out: if (orig_node) |
7d211efc5 batman-adv: Prefi... |
2003 |
batadv_orig_node_free_ref(orig_node); |
a73105b8d batman-adv: impro... |
2004 |
} |
56303d34a batman-adv: Prefi... |
2005 |
int batadv_tt_init(struct batadv_priv *bat_priv) |
a73105b8d batman-adv: impro... |
2006 |
{ |
5346c35eb batman-adv: Retur... |
2007 |
int ret; |
a73105b8d batman-adv: impro... |
2008 |
|
a513088d0 batman-adv: Prefi... |
2009 |
ret = batadv_tt_local_init(bat_priv); |
5346c35eb batman-adv: Retur... |
2010 2011 |
if (ret < 0) return ret; |
a513088d0 batman-adv: Prefi... |
2012 |
ret = batadv_tt_global_init(bat_priv); |
5346c35eb batman-adv: Retur... |
2013 2014 |
if (ret < 0) return ret; |
a73105b8d batman-adv: impro... |
2015 |
|
724144420 batman-adv: a del... |
2016 2017 2018 |
INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge); queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work, msecs_to_jiffies(BATADV_TT_WORK_PERIOD)); |
a73105b8d batman-adv: impro... |
2019 2020 2021 |
return 1; } |
56303d34a batman-adv: Prefi... |
2022 |
static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv) |
a73105b8d batman-adv: impro... |
2023 |
{ |
56303d34a batman-adv: Prefi... |
2024 |
struct batadv_tt_roam_node *node, *safe; |
a73105b8d batman-adv: impro... |
2025 |
|
807736f6e batman-adv: Split... |
2026 |
spin_lock_bh(&bat_priv->tt.roam_list_lock); |
a73105b8d batman-adv: impro... |
2027 |
|
807736f6e batman-adv: Split... |
2028 |
list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) { |
cc47f66e6 batman-adv: impro... |
2029 2030 2031 |
list_del(&node->list); kfree(node); } |
807736f6e batman-adv: Split... |
2032 |
spin_unlock_bh(&bat_priv->tt.roam_list_lock); |
cc47f66e6 batman-adv: impro... |
2033 |
} |
56303d34a batman-adv: Prefi... |
2034 |
static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) |
cc47f66e6 batman-adv: impro... |
2035 |
{ |
56303d34a batman-adv: Prefi... |
2036 |
struct batadv_tt_roam_node *node, *safe; |
cc47f66e6 batman-adv: impro... |
2037 |
|
807736f6e batman-adv: Split... |
2038 2039 |
spin_lock_bh(&bat_priv->tt.roam_list_lock); list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) { |
42d0b044b batman-adv: Prefi... |
2040 2041 |
if (!batadv_has_timed_out(node->first_time, BATADV_ROAMING_MAX_TIME)) |
cc47f66e6 batman-adv: impro... |
2042 2043 2044 2045 2046 |
continue; list_del(&node->list); kfree(node); } |
807736f6e batman-adv: Split... |
2047 |
spin_unlock_bh(&bat_priv->tt.roam_list_lock); |
cc47f66e6 batman-adv: impro... |
2048 2049 2050 2051 2052 2053 |
} /* This function checks whether the client already reached the * maximum number of possible roaming phases. In this case the ROAMING_ADV * will not be sent. * |
9cfc7bd60 batman-adv: Refor... |
2054 2055 |
* returns true if the ROAMING_ADV can be sent, false otherwise */ |
56303d34a batman-adv: Prefi... |
2056 |
static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, |
a513088d0 batman-adv: Prefi... |
2057 |
uint8_t *client) |
cc47f66e6 batman-adv: impro... |
2058 |
{ |
56303d34a batman-adv: Prefi... |
2059 |
struct batadv_tt_roam_node *tt_roam_node; |
cc47f66e6 batman-adv: impro... |
2060 |
bool ret = false; |
807736f6e batman-adv: Split... |
2061 |
spin_lock_bh(&bat_priv->tt.roam_list_lock); |
cc47f66e6 batman-adv: impro... |
2062 |
/* The new tt_req will be issued only if I'm not waiting for a |
9cfc7bd60 batman-adv: Refor... |
2063 2064 |
* reply from the same orig_node yet */ |
807736f6e batman-adv: Split... |
2065 |
list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) { |
1eda58bfc batman-adv: Prefi... |
2066 |
if (!batadv_compare_eth(tt_roam_node->addr, client)) |
cc47f66e6 batman-adv: impro... |
2067 |
continue; |
1eda58bfc batman-adv: Prefi... |
2068 |
if (batadv_has_timed_out(tt_roam_node->first_time, |
42d0b044b batman-adv: Prefi... |
2069 |
BATADV_ROAMING_MAX_TIME)) |
cc47f66e6 batman-adv: impro... |
2070 |
continue; |
3e34819e0 batman-adv: Prefi... |
2071 |
if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter)) |
cc47f66e6 batman-adv: impro... |
2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 |
/* Sorry, you roamed too many times! */ goto unlock; ret = true; break; } if (!ret) { tt_roam_node = kmalloc(sizeof(*tt_roam_node), GFP_ATOMIC); if (!tt_roam_node) goto unlock; tt_roam_node->first_time = jiffies; |
42d0b044b batman-adv: Prefi... |
2084 2085 |
atomic_set(&tt_roam_node->counter, BATADV_ROAMING_MAX_COUNT - 1); |
cc47f66e6 batman-adv: impro... |
2086 |
memcpy(tt_roam_node->addr, client, ETH_ALEN); |
807736f6e batman-adv: Split... |
2087 |
list_add(&tt_roam_node->list, &bat_priv->tt.roam_list); |
cc47f66e6 batman-adv: impro... |
2088 2089 2090 2091 |
ret = true; } unlock: |
807736f6e batman-adv: Split... |
2092 |
spin_unlock_bh(&bat_priv->tt.roam_list_lock); |
cc47f66e6 batman-adv: impro... |
2093 2094 |
return ret; } |
56303d34a batman-adv: Prefi... |
2095 2096 |
static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, struct batadv_orig_node *orig_node) |
cc47f66e6 batman-adv: impro... |
2097 |
{ |
cc47f66e6 batman-adv: impro... |
2098 |
struct sk_buff *skb = NULL; |
964126901 batman-adv: Prefi... |
2099 |
struct batadv_roam_adv_packet *roam_adv_packet; |
cc47f66e6 batman-adv: impro... |
2100 |
int ret = 1; |
56303d34a batman-adv: Prefi... |
2101 |
struct batadv_hard_iface *primary_if; |
964126901 batman-adv: Prefi... |
2102 |
size_t len = sizeof(*roam_adv_packet); |
cc47f66e6 batman-adv: impro... |
2103 2104 |
/* before going on we have to check whether the client has |
9cfc7bd60 batman-adv: Refor... |
2105 2106 |
* already roamed to us too many times */ |
a513088d0 batman-adv: Prefi... |
2107 |
if (!batadv_tt_check_roam_count(bat_priv, client)) |
cc47f66e6 batman-adv: impro... |
2108 |
goto out; |
5b2465744 batman-adv: Reser... |
2109 |
skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN); |
cc47f66e6 batman-adv: impro... |
2110 2111 |
if (!skb) goto out; |
5b2465744 batman-adv: Reser... |
2112 |
skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); |
cc47f66e6 batman-adv: impro... |
2113 |
|
964126901 batman-adv: Prefi... |
2114 |
roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len); |
cc47f66e6 batman-adv: impro... |
2115 |
|
acd34afa8 batman-adv: Prefi... |
2116 |
roam_adv_packet->header.packet_type = BATADV_ROAM_ADV; |
7e071c79a batman-adv: Prefi... |
2117 |
roam_adv_packet->header.version = BATADV_COMPAT_VERSION; |
42d0b044b batman-adv: Prefi... |
2118 |
roam_adv_packet->header.ttl = BATADV_TTL; |
162d549c6 batman-adv: Don't... |
2119 |
roam_adv_packet->reserved = 0; |
e5d89254b batman-adv: Prefi... |
2120 |
primary_if = batadv_primary_if_get_selected(bat_priv); |
cc47f66e6 batman-adv: impro... |
2121 2122 2123 |
if (!primary_if) goto out; memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN); |
e5d89254b batman-adv: Prefi... |
2124 |
batadv_hardif_free_ref(primary_if); |
cc47f66e6 batman-adv: impro... |
2125 2126 |
memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN); memcpy(roam_adv_packet->client, client, ETH_ALEN); |
39c75a51e batman-adv: Prefi... |
2127 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
bb351ba0b batman-adv: Add w... |
2128 2129 2130 |
"Sending ROAMING_ADV to %pM (client %pM) ", orig_node->orig, client); |
cc47f66e6 batman-adv: impro... |
2131 |
|
d69909d2f batman-adv: Prefi... |
2132 |
batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX); |
f8214865a batman-adv: Add g... |
2133 |
|
bb351ba0b batman-adv: Add w... |
2134 2135 |
if (batadv_send_skb_to_orig(skb, orig_node, NULL)) ret = 0; |
cc47f66e6 batman-adv: impro... |
2136 2137 |
out: |
bb351ba0b batman-adv: Add w... |
2138 |
if (ret && skb) |
cc47f66e6 batman-adv: impro... |
2139 2140 |
kfree_skb(skb); return; |
a73105b8d batman-adv: impro... |
2141 |
} |
a513088d0 batman-adv: Prefi... |
2142 |
static void batadv_tt_purge(struct work_struct *work) |
a73105b8d batman-adv: impro... |
2143 |
{ |
56303d34a batman-adv: Prefi... |
2144 |
struct delayed_work *delayed_work; |
807736f6e batman-adv: Split... |
2145 |
struct batadv_priv_tt *priv_tt; |
56303d34a batman-adv: Prefi... |
2146 2147 2148 |
struct batadv_priv *bat_priv; delayed_work = container_of(work, struct delayed_work, work); |
807736f6e batman-adv: Split... |
2149 2150 |
priv_tt = container_of(delayed_work, struct batadv_priv_tt, work); bat_priv = container_of(priv_tt, struct batadv_priv, tt); |
a73105b8d batman-adv: impro... |
2151 |
|
a513088d0 batman-adv: Prefi... |
2152 |
batadv_tt_local_purge(bat_priv); |
30cfd02b6 batman-adv: detec... |
2153 |
batadv_tt_global_purge(bat_priv); |
a513088d0 batman-adv: Prefi... |
2154 2155 |
batadv_tt_req_purge(bat_priv); batadv_tt_roam_purge(bat_priv); |
a73105b8d batman-adv: impro... |
2156 |
|
724144420 batman-adv: a del... |
2157 2158 |
queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work, msecs_to_jiffies(BATADV_TT_WORK_PERIOD)); |
a73105b8d batman-adv: impro... |
2159 |
} |
cc47f66e6 batman-adv: impro... |
2160 |
|
56303d34a batman-adv: Prefi... |
2161 |
void batadv_tt_free(struct batadv_priv *bat_priv) |
cc47f66e6 batman-adv: impro... |
2162 |
{ |
807736f6e batman-adv: Split... |
2163 |
cancel_delayed_work_sync(&bat_priv->tt.work); |
cc47f66e6 batman-adv: impro... |
2164 |
|
a513088d0 batman-adv: Prefi... |
2165 2166 2167 2168 2169 |
batadv_tt_local_table_free(bat_priv); batadv_tt_global_table_free(bat_priv); batadv_tt_req_list_free(bat_priv); batadv_tt_changes_list_free(bat_priv); batadv_tt_roam_list_free(bat_priv); |
cc47f66e6 batman-adv: impro... |
2170 |
|
807736f6e batman-adv: Split... |
2171 |
kfree(bat_priv->tt.last_changeset); |
cc47f66e6 batman-adv: impro... |
2172 |
} |
058d0e269 batman-adv: keep ... |
2173 |
|
697f25314 batman-adv: gener... |
2174 |
/* This function will enable or disable the specified flags for all the entries |
9cfc7bd60 batman-adv: Refor... |
2175 2176 |
* in the given hash table and returns the number of modified entries */ |
5bf74e9ca batman-adv: Prefi... |
2177 2178 |
static uint16_t batadv_tt_set_flags(struct batadv_hashtable *hash, uint16_t flags, bool enable) |
058d0e269 batman-adv: keep ... |
2179 |
{ |
c90681b85 batman-adv: fixed... |
2180 |
uint32_t i; |
697f25314 batman-adv: gener... |
2181 |
uint16_t changed_num = 0; |
058d0e269 batman-adv: keep ... |
2182 |
struct hlist_head *head; |
56303d34a batman-adv: Prefi... |
2183 |
struct batadv_tt_common_entry *tt_common_entry; |
058d0e269 batman-adv: keep ... |
2184 2185 |
if (!hash) |
697f25314 batman-adv: gener... |
2186 |
goto out; |
058d0e269 batman-adv: keep ... |
2187 2188 2189 2190 2191 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
2192 |
hlist_for_each_entry_rcu(tt_common_entry, |
058d0e269 batman-adv: keep ... |
2193 |
head, hash_entry) { |
697f25314 batman-adv: gener... |
2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 |
if (enable) { if ((tt_common_entry->flags & flags) == flags) continue; tt_common_entry->flags |= flags; } else { if (!(tt_common_entry->flags & flags)) continue; tt_common_entry->flags &= ~flags; } changed_num++; |
058d0e269 batman-adv: keep ... |
2204 2205 2206 |
} rcu_read_unlock(); } |
697f25314 batman-adv: gener... |
2207 2208 |
out: return changed_num; |
058d0e269 batman-adv: keep ... |
2209 |
} |
acd34afa8 batman-adv: Prefi... |
2210 |
/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */ |
56303d34a batman-adv: Prefi... |
2211 |
static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) |
058d0e269 batman-adv: keep ... |
2212 |
{ |
807736f6e batman-adv: Split... |
2213 |
struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
56303d34a batman-adv: Prefi... |
2214 2215 |
struct batadv_tt_common_entry *tt_common; struct batadv_tt_local_entry *tt_local; |
b67bfe0d4 hlist: drop the n... |
2216 |
struct hlist_node *node_tmp; |
058d0e269 batman-adv: keep ... |
2217 2218 |
struct hlist_head *head; spinlock_t *list_lock; /* protects write access to the hash lists */ |
c90681b85 batman-adv: fixed... |
2219 |
uint32_t i; |
058d0e269 batman-adv: keep ... |
2220 2221 2222 2223 2224 2225 2226 2227 2228 |
if (!hash) return; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); |
b67bfe0d4 hlist: drop the n... |
2229 |
hlist_for_each_entry_safe(tt_common, node_tmp, head, |
acd34afa8 batman-adv: Prefi... |
2230 2231 |
hash_entry) { if (!(tt_common->flags & BATADV_TT_CLIENT_PENDING)) |
058d0e269 batman-adv: keep ... |
2232 |
continue; |
39c75a51e batman-adv: Prefi... |
2233 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
2234 2235 |
"Deleting local tt entry (%pM): pending ", |
acd34afa8 batman-adv: Prefi... |
2236 |
tt_common->addr); |
058d0e269 batman-adv: keep ... |
2237 |
|
807736f6e batman-adv: Split... |
2238 |
atomic_dec(&bat_priv->tt.local_entry_num); |
b67bfe0d4 hlist: drop the n... |
2239 |
hlist_del_rcu(&tt_common->hash_entry); |
56303d34a batman-adv: Prefi... |
2240 2241 2242 2243 |
tt_local = container_of(tt_common, struct batadv_tt_local_entry, common); batadv_tt_local_entry_free_ref(tt_local); |
058d0e269 batman-adv: keep ... |
2244 2245 2246 |
} spin_unlock_bh(list_lock); } |
058d0e269 batman-adv: keep ... |
2247 |
} |
56303d34a batman-adv: Prefi... |
2248 |
static int batadv_tt_commit_changes(struct batadv_priv *bat_priv, |
a513088d0 batman-adv: Prefi... |
2249 2250 |
unsigned char **packet_buff, int *packet_buff_len, int packet_min_len) |
058d0e269 batman-adv: keep ... |
2251 |
{ |
be9aa4c1e batman-adv: turn ... |
2252 |
uint16_t changed_num = 0; |
807736f6e batman-adv: Split... |
2253 |
if (atomic_read(&bat_priv->tt.local_changes) < 1) |
be9aa4c1e batman-adv: turn ... |
2254 |
return -ENOENT; |
807736f6e batman-adv: Split... |
2255 |
changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash, |
acd34afa8 batman-adv: Prefi... |
2256 |
BATADV_TT_CLIENT_NEW, false); |
be9aa4c1e batman-adv: turn ... |
2257 2258 |
/* all reset entries have to be counted as local entries */ |
807736f6e batman-adv: Split... |
2259 |
atomic_add(changed_num, &bat_priv->tt.local_entry_num); |
a513088d0 batman-adv: Prefi... |
2260 |
batadv_tt_local_purge_pending_clients(bat_priv); |
807736f6e batman-adv: Split... |
2261 |
bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv); |
058d0e269 batman-adv: keep ... |
2262 2263 |
/* Increment the TTVN only once per OGM interval */ |
807736f6e batman-adv: Split... |
2264 |
atomic_inc(&bat_priv->tt.vn); |
39c75a51e batman-adv: Prefi... |
2265 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
1eda58bfc batman-adv: Prefi... |
2266 2267 |
"Local changes committed, updating to ttvn %u ", |
807736f6e batman-adv: Split... |
2268 |
(uint8_t)atomic_read(&bat_priv->tt.vn)); |
be9aa4c1e batman-adv: turn ... |
2269 2270 |
/* reset the sending counter */ |
807736f6e batman-adv: Split... |
2271 |
atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); |
be9aa4c1e batman-adv: turn ... |
2272 |
|
a513088d0 batman-adv: Prefi... |
2273 2274 |
return batadv_tt_changes_fill_buff(bat_priv, packet_buff, packet_buff_len, packet_min_len); |
be9aa4c1e batman-adv: turn ... |
2275 2276 2277 |
} /* when calling this function (hard_iface == primary_if) has to be true */ |
56303d34a batman-adv: Prefi... |
2278 |
int batadv_tt_append_diff(struct batadv_priv *bat_priv, |
be9aa4c1e batman-adv: turn ... |
2279 2280 2281 2282 2283 2284 |
unsigned char **packet_buff, int *packet_buff_len, int packet_min_len) { int tt_num_changes; /* if at least one change happened */ |
a513088d0 batman-adv: Prefi... |
2285 2286 2287 |
tt_num_changes = batadv_tt_commit_changes(bat_priv, packet_buff, packet_buff_len, packet_min_len); |
be9aa4c1e batman-adv: turn ... |
2288 2289 2290 |
/* if the changes have been sent often enough */ if ((tt_num_changes < 0) && |
807736f6e batman-adv: Split... |
2291 |
(!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) { |
a513088d0 batman-adv: Prefi... |
2292 2293 |
batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, packet_min_len, packet_min_len); |
be9aa4c1e batman-adv: turn ... |
2294 2295 2296 2297 |
tt_num_changes = 0; } return tt_num_changes; |
058d0e269 batman-adv: keep ... |
2298 |
} |
59b699cde batman-adv: imple... |
2299 |
|
56303d34a batman-adv: Prefi... |
2300 |
bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, |
08c36d3e8 batman-adv: Prefi... |
2301 |
uint8_t *dst) |
59b699cde batman-adv: imple... |
2302 |
{ |
56303d34a batman-adv: Prefi... |
2303 2304 |
struct batadv_tt_local_entry *tt_local_entry = NULL; struct batadv_tt_global_entry *tt_global_entry = NULL; |
5870adc68 batman-adv: only ... |
2305 |
bool ret = false; |
59b699cde batman-adv: imple... |
2306 2307 |
if (!atomic_read(&bat_priv->ap_isolation)) |
5870adc68 batman-adv: only ... |
2308 |
goto out; |
59b699cde batman-adv: imple... |
2309 |
|
a513088d0 batman-adv: Prefi... |
2310 |
tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst); |
59b699cde batman-adv: imple... |
2311 2312 |
if (!tt_local_entry) goto out; |
a513088d0 batman-adv: Prefi... |
2313 |
tt_global_entry = batadv_tt_global_hash_find(bat_priv, src); |
59b699cde batman-adv: imple... |
2314 2315 |
if (!tt_global_entry) goto out; |
1f129fefd batman-adv: fix c... |
2316 |
if (!_batadv_is_ap_isolated(tt_local_entry, tt_global_entry)) |
59b699cde batman-adv: imple... |
2317 |
goto out; |
5870adc68 batman-adv: only ... |
2318 |
ret = true; |
59b699cde batman-adv: imple... |
2319 2320 2321 |
out: if (tt_global_entry) |
a513088d0 batman-adv: Prefi... |
2322 |
batadv_tt_global_entry_free_ref(tt_global_entry); |
59b699cde batman-adv: imple... |
2323 |
if (tt_local_entry) |
a513088d0 batman-adv: Prefi... |
2324 |
batadv_tt_local_entry_free_ref(tt_local_entry); |
59b699cde batman-adv: imple... |
2325 2326 |
return ret; } |
a943cac14 batman-adv: merge... |
2327 |
|
56303d34a batman-adv: Prefi... |
2328 2329 |
void batadv_tt_update_orig(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, |
08c36d3e8 batman-adv: Prefi... |
2330 2331 |
const unsigned char *tt_buff, uint8_t tt_num_changes, uint8_t ttvn, uint16_t tt_crc) |
a943cac14 batman-adv: merge... |
2332 2333 2334 |
{ uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); bool full_table = true; |
964126901 batman-adv: Prefi... |
2335 |
struct batadv_tt_change *tt_change; |
a943cac14 batman-adv: merge... |
2336 |
|
20ff9d593 batman-adv: don't... |
2337 |
/* don't care about a backbone gateways updates. */ |
08adf1512 batman-adv: Prefi... |
2338 |
if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig)) |
20ff9d593 batman-adv: don't... |
2339 |
return; |
170715788 batman-adv: add t... |
2340 |
/* orig table not initialised AND first diff is in the OGM OR the ttvn |
9cfc7bd60 batman-adv: Refor... |
2341 2342 |
* increased by one -> we can apply the attached changes */ |
170715788 batman-adv: add t... |
2343 2344 |
if ((!orig_node->tt_initialised && ttvn == 1) || ttvn - orig_ttvn == 1) { |
a943cac14 batman-adv: merge... |
2345 |
/* the OGM could not contain the changes due to their size or |
42d0b044b batman-adv: Prefi... |
2346 2347 |
* because they have already been sent BATADV_TT_OGM_APPEND_MAX * times. |
9cfc7bd60 batman-adv: Refor... |
2348 2349 |
* In this case send a tt request */ |
a943cac14 batman-adv: merge... |
2350 2351 2352 2353 |
if (!tt_num_changes) { full_table = false; goto request_table; } |
964126901 batman-adv: Prefi... |
2354 |
tt_change = (struct batadv_tt_change *)tt_buff; |
a513088d0 batman-adv: Prefi... |
2355 |
batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, |
964126901 batman-adv: Prefi... |
2356 |
ttvn, tt_change); |
a943cac14 batman-adv: merge... |
2357 2358 2359 |
/* Even if we received the precomputed crc with the OGM, we * prefer to recompute it to spot any possible inconsistency |
9cfc7bd60 batman-adv: Refor... |
2360 2361 |
* in the global table */ |
a513088d0 batman-adv: Prefi... |
2362 |
orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); |
a943cac14 batman-adv: merge... |
2363 2364 2365 2366 2367 2368 2369 2370 |
/* The ttvn alone is not enough to guarantee consistency * because a single value could represent different states * (due to the wrap around). Thus a node has to check whether * the resulting table (after applying the changes) is still * consistent or not. E.g. a node could disconnect while its * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case * checking the CRC value is mandatory to detect the |
9cfc7bd60 batman-adv: Refor... |
2371 2372 |
* inconsistency */ |
a943cac14 batman-adv: merge... |
2373 2374 |
if (orig_node->tt_crc != tt_crc) goto request_table; |
a943cac14 batman-adv: merge... |
2375 2376 |
} else { /* if we missed more than one change or our tables are not |
9cfc7bd60 batman-adv: Refor... |
2377 2378 |
* in sync anymore -> request fresh tt data */ |
170715788 batman-adv: add t... |
2379 2380 |
if (!orig_node->tt_initialised || ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) { |
a943cac14 batman-adv: merge... |
2381 |
request_table: |
39c75a51e batman-adv: Prefi... |
2382 |
batadv_dbg(BATADV_DBG_TT, bat_priv, |
39a329915 batman-adv: unify... |
2383 2384 |
"TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.4x last_crc: %#.4x num_changes: %u) ", |
1eda58bfc batman-adv: Prefi... |
2385 2386 |
orig_node->orig, ttvn, orig_ttvn, tt_crc, orig_node->tt_crc, tt_num_changes); |
a513088d0 batman-adv: Prefi... |
2387 2388 |
batadv_send_tt_request(bat_priv, orig_node, ttvn, tt_crc, full_table); |
a943cac14 batman-adv: merge... |
2389 2390 2391 2392 |
return; } } } |
3275e7cc8 batman-adv: impro... |
2393 2394 2395 2396 2397 |
/* returns true whether we know that the client has moved from its old * originator to another one. This entry is kept is still kept for consistency * purposes */ |
56303d34a batman-adv: Prefi... |
2398 |
bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, |
08c36d3e8 batman-adv: Prefi... |
2399 |
uint8_t *addr) |
3275e7cc8 batman-adv: impro... |
2400 |
{ |
56303d34a batman-adv: Prefi... |
2401 |
struct batadv_tt_global_entry *tt_global_entry; |
3275e7cc8 batman-adv: impro... |
2402 |
bool ret = false; |
a513088d0 batman-adv: Prefi... |
2403 |
tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); |
3275e7cc8 batman-adv: impro... |
2404 2405 |
if (!tt_global_entry) goto out; |
c1d07431b batman-adv: don't... |
2406 |
ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM; |
a513088d0 batman-adv: Prefi... |
2407 |
batadv_tt_global_entry_free_ref(tt_global_entry); |
3275e7cc8 batman-adv: impro... |
2408 2409 2410 |
out: return ret; } |
30cfd02b6 batman-adv: detec... |
2411 |
|
7c1fd91da batman-adv: subst... |
2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 |
/** * batadv_tt_local_client_is_roaming - tells whether the client is roaming * @bat_priv: the bat priv with all the soft interface information * @addr: the MAC address of the local client to query * * Returns true if the local client is known to be roaming (it is not served by * this node anymore) or not. If yes, the client is still present in the table * to keep the latter consistent with the node TTVN */ bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, uint8_t *addr) { struct batadv_tt_local_entry *tt_local_entry; bool ret = false; tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); if (!tt_local_entry) goto out; ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM; batadv_tt_local_entry_free_ref(tt_local_entry); out: return ret; |
7c1fd91da batman-adv: subst... |
2435 |
} |
30cfd02b6 batman-adv: detec... |
2436 2437 2438 2439 2440 |
bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, const unsigned char *addr) { bool ret = false; |
1f36aebcc batman-adv: don't... |
2441 2442 2443 2444 2445 2446 |
/* if the originator is a backbone node (meaning it belongs to the same * LAN of this node) the temporary client must not be added because to * reach such destination the node must use the LAN instead of the mesh */ if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig)) goto out; |
30cfd02b6 batman-adv: detec... |
2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 |
if (!batadv_tt_global_add(bat_priv, orig_node, addr, BATADV_TT_CLIENT_TEMP, atomic_read(&orig_node->last_ttvn))) goto out; batadv_dbg(BATADV_DBG_TT, bat_priv, "Added temporary global client (addr: %pM orig: %pM) ", addr, orig_node->orig); ret = true; out: return ret; } |