2 * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
4 * Marek Lindner, Simon Wunderlich
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include "translation-table.h"
24 #include "soft-interface.h"
25 #include "hard-interface.h"
27 #include "originator.h"
29 static void tt_local_purge(struct work_struct
*work
);
30 static void _tt_global_del_orig(struct bat_priv
*bat_priv
,
31 struct tt_global_entry
*tt_global_entry
,
34 /* returns 1 if they are the same mac addr */
35 static int compare_ltt(const struct hlist_node
*node
, const void *data2
)
37 const void *data1
= container_of(node
, struct tt_local_entry
,
40 return (memcmp(data1
, data2
, ETH_ALEN
) == 0 ? 1 : 0);
43 /* returns 1 if they are the same mac addr */
44 static int compare_gtt(const struct hlist_node
*node
, const void *data2
)
46 const void *data1
= container_of(node
, struct tt_global_entry
,
49 return (memcmp(data1
, data2
, ETH_ALEN
) == 0 ? 1 : 0);
52 static void tt_local_start_timer(struct bat_priv
*bat_priv
)
54 INIT_DELAYED_WORK(&bat_priv
->tt_work
, tt_local_purge
);
55 queue_delayed_work(bat_event_workqueue
, &bat_priv
->tt_work
, 10 * HZ
);
58 static struct tt_local_entry
*tt_local_hash_find(struct bat_priv
*bat_priv
,
61 struct hashtable_t
*hash
= bat_priv
->tt_local_hash
;
62 struct hlist_head
*head
;
63 struct hlist_node
*node
;
64 struct tt_local_entry
*tt_local_entry
, *tt_local_entry_tmp
= NULL
;
70 index
= choose_orig(data
, hash
->size
);
71 head
= &hash
->table
[index
];
74 hlist_for_each_entry_rcu(tt_local_entry
, node
, head
, hash_entry
) {
75 if (!compare_eth(tt_local_entry
, data
))
78 tt_local_entry_tmp
= tt_local_entry
;
83 return tt_local_entry_tmp
;
86 static struct tt_global_entry
*tt_global_hash_find(struct bat_priv
*bat_priv
,
89 struct hashtable_t
*hash
= bat_priv
->tt_global_hash
;
90 struct hlist_head
*head
;
91 struct hlist_node
*node
;
92 struct tt_global_entry
*tt_global_entry
;
93 struct tt_global_entry
*tt_global_entry_tmp
= NULL
;
99 index
= choose_orig(data
, hash
->size
);
100 head
= &hash
->table
[index
];
103 hlist_for_each_entry_rcu(tt_global_entry
, node
, head
, hash_entry
) {
104 if (!compare_eth(tt_global_entry
, data
))
107 tt_global_entry_tmp
= tt_global_entry
;
112 return tt_global_entry_tmp
;
115 int tt_local_init(struct bat_priv
*bat_priv
)
117 if (bat_priv
->tt_local_hash
)
120 bat_priv
->tt_local_hash
= hash_new(1024);
122 if (!bat_priv
->tt_local_hash
)
125 atomic_set(&bat_priv
->tt_local_changed
, 0);
126 tt_local_start_timer(bat_priv
);
131 void tt_local_add(struct net_device
*soft_iface
, const uint8_t *addr
)
133 struct bat_priv
*bat_priv
= netdev_priv(soft_iface
);
134 struct tt_local_entry
*tt_local_entry
;
135 struct tt_global_entry
*tt_global_entry
;
138 spin_lock_bh(&bat_priv
->tt_lhash_lock
);
139 tt_local_entry
= tt_local_hash_find(bat_priv
, addr
);
140 spin_unlock_bh(&bat_priv
->tt_lhash_lock
);
142 if (tt_local_entry
) {
143 tt_local_entry
->last_seen
= jiffies
;
147 /* only announce as many hosts as possible in the batman-packet and
148 space in batman_packet->num_tt That also should give a limit to
150 required_bytes
= (bat_priv
->num_local_tt
+ 1) * ETH_ALEN
;
151 required_bytes
+= BAT_PACKET_LEN
;
153 if ((required_bytes
> ETH_DATA_LEN
) ||
154 (atomic_read(&bat_priv
->aggregated_ogms
) &&
155 required_bytes
> MAX_AGGREGATION_BYTES
) ||
156 (bat_priv
->num_local_tt
+ 1 > 255)) {
157 bat_dbg(DBG_ROUTES
, bat_priv
,
158 "Can't add new local tt entry (%pM): "
159 "number of local tt entries exceeds packet size\n",
164 bat_dbg(DBG_ROUTES
, bat_priv
,
165 "Creating new local tt entry: %pM\n", addr
);
167 tt_local_entry
= kmalloc(sizeof(*tt_local_entry
), GFP_ATOMIC
);
171 memcpy(tt_local_entry
->addr
, addr
, ETH_ALEN
);
172 tt_local_entry
->last_seen
= jiffies
;
174 /* the batman interface mac address should never be purged */
175 if (compare_eth(addr
, soft_iface
->dev_addr
))
176 tt_local_entry
->never_purge
= 1;
178 tt_local_entry
->never_purge
= 0;
180 spin_lock_bh(&bat_priv
->tt_lhash_lock
);
182 hash_add(bat_priv
->tt_local_hash
, compare_ltt
, choose_orig
,
183 tt_local_entry
, &tt_local_entry
->hash_entry
);
184 bat_priv
->num_local_tt
++;
185 atomic_set(&bat_priv
->tt_local_changed
, 1);
187 spin_unlock_bh(&bat_priv
->tt_lhash_lock
);
189 /* remove address from global hash if present */
190 spin_lock_bh(&bat_priv
->tt_ghash_lock
);
192 tt_global_entry
= tt_global_hash_find(bat_priv
, addr
);
195 _tt_global_del_orig(bat_priv
, tt_global_entry
,
196 "local tt received");
198 spin_unlock_bh(&bat_priv
->tt_ghash_lock
);
201 int tt_local_fill_buffer(struct bat_priv
*bat_priv
,
202 unsigned char *buff
, int buff_len
)
204 struct hashtable_t
*hash
= bat_priv
->tt_local_hash
;
205 struct tt_local_entry
*tt_local_entry
;
206 struct hlist_node
*node
;
207 struct hlist_head
*head
;
210 spin_lock_bh(&bat_priv
->tt_lhash_lock
);
212 for (i
= 0; i
< hash
->size
; i
++) {
213 head
= &hash
->table
[i
];
216 hlist_for_each_entry_rcu(tt_local_entry
, node
,
218 if (buff_len
< (count
+ 1) * ETH_ALEN
)
221 memcpy(buff
+ (count
* ETH_ALEN
), tt_local_entry
->addr
,
229 /* if we did not get all new local tts see you next time ;-) */
230 if (count
== bat_priv
->num_local_tt
)
231 atomic_set(&bat_priv
->tt_local_changed
, 0);
233 spin_unlock_bh(&bat_priv
->tt_lhash_lock
);
237 int tt_local_seq_print_text(struct seq_file
*seq
, void *offset
)
239 struct net_device
*net_dev
= (struct net_device
*)seq
->private;
240 struct bat_priv
*bat_priv
= netdev_priv(net_dev
);
241 struct hashtable_t
*hash
= bat_priv
->tt_local_hash
;
242 struct tt_local_entry
*tt_local_entry
;
243 struct hard_iface
*primary_if
;
244 struct hlist_node
*node
;
245 struct hlist_head
*head
;
246 size_t buf_size
, pos
;
250 primary_if
= primary_if_get_selected(bat_priv
);
252 ret
= seq_printf(seq
, "BATMAN mesh %s disabled - "
253 "please specify interfaces to enable it\n",
258 if (primary_if
->if_status
!= IF_ACTIVE
) {
259 ret
= seq_printf(seq
, "BATMAN mesh %s disabled - "
260 "primary interface not active\n",
265 seq_printf(seq
, "Locally retrieved addresses (from %s) "
266 "announced via TT:\n",
269 spin_lock_bh(&bat_priv
->tt_lhash_lock
);
272 /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
273 for (i
= 0; i
< hash
->size
; i
++) {
274 head
= &hash
->table
[i
];
277 __hlist_for_each_rcu(node
, head
)
282 buff
= kmalloc(buf_size
, GFP_ATOMIC
);
284 spin_unlock_bh(&bat_priv
->tt_lhash_lock
);
292 for (i
= 0; i
< hash
->size
; i
++) {
293 head
= &hash
->table
[i
];
296 hlist_for_each_entry_rcu(tt_local_entry
, node
,
298 pos
+= snprintf(buff
+ pos
, 22, " * %pM\n",
299 tt_local_entry
->addr
);
304 spin_unlock_bh(&bat_priv
->tt_lhash_lock
);
306 seq_printf(seq
, "%s", buff
);
310 hardif_free_ref(primary_if
);
314 static void _tt_local_del(struct hlist_node
*node
, void *arg
)
316 struct bat_priv
*bat_priv
= arg
;
317 void *data
= container_of(node
, struct tt_local_entry
, hash_entry
);
320 bat_priv
->num_local_tt
--;
321 atomic_set(&bat_priv
->tt_local_changed
, 1);
324 static void tt_local_del(struct bat_priv
*bat_priv
,
325 struct tt_local_entry
*tt_local_entry
,
328 bat_dbg(DBG_ROUTES
, bat_priv
, "Deleting local tt entry (%pM): %s\n",
329 tt_local_entry
->addr
, message
);
331 hash_remove(bat_priv
->tt_local_hash
, compare_ltt
, choose_orig
,
332 tt_local_entry
->addr
);
333 _tt_local_del(&tt_local_entry
->hash_entry
, bat_priv
);
336 void tt_local_remove(struct bat_priv
*bat_priv
,
337 const uint8_t *addr
, const char *message
)
339 struct tt_local_entry
*tt_local_entry
;
341 spin_lock_bh(&bat_priv
->tt_lhash_lock
);
343 tt_local_entry
= tt_local_hash_find(bat_priv
, addr
);
346 tt_local_del(bat_priv
, tt_local_entry
, message
);
348 spin_unlock_bh(&bat_priv
->tt_lhash_lock
);
351 static void tt_local_purge(struct work_struct
*work
)
353 struct delayed_work
*delayed_work
=
354 container_of(work
, struct delayed_work
, work
);
355 struct bat_priv
*bat_priv
=
356 container_of(delayed_work
, struct bat_priv
, tt_work
);
357 struct hashtable_t
*hash
= bat_priv
->tt_local_hash
;
358 struct tt_local_entry
*tt_local_entry
;
359 struct hlist_node
*node
, *node_tmp
;
360 struct hlist_head
*head
;
361 unsigned long timeout
;
364 spin_lock_bh(&bat_priv
->tt_lhash_lock
);
366 for (i
= 0; i
< hash
->size
; i
++) {
367 head
= &hash
->table
[i
];
369 hlist_for_each_entry_safe(tt_local_entry
, node
, node_tmp
,
371 if (tt_local_entry
->never_purge
)
374 timeout
= tt_local_entry
->last_seen
;
375 timeout
+= TT_LOCAL_TIMEOUT
* HZ
;
377 if (time_before(jiffies
, timeout
))
380 tt_local_del(bat_priv
, tt_local_entry
,
381 "address timed out");
385 spin_unlock_bh(&bat_priv
->tt_lhash_lock
);
386 tt_local_start_timer(bat_priv
);
389 void tt_local_free(struct bat_priv
*bat_priv
)
391 if (!bat_priv
->tt_local_hash
)
394 cancel_delayed_work_sync(&bat_priv
->tt_work
);
395 hash_delete(bat_priv
->tt_local_hash
, _tt_local_del
, bat_priv
);
396 bat_priv
->tt_local_hash
= NULL
;
399 int tt_global_init(struct bat_priv
*bat_priv
)
401 if (bat_priv
->tt_global_hash
)
404 bat_priv
->tt_global_hash
= hash_new(1024);
406 if (!bat_priv
->tt_global_hash
)
412 void tt_global_add_orig(struct bat_priv
*bat_priv
,
413 struct orig_node
*orig_node
,
414 const unsigned char *tt_buff
, int tt_buff_len
)
416 struct tt_global_entry
*tt_global_entry
;
417 struct tt_local_entry
*tt_local_entry
;
418 int tt_buff_count
= 0;
419 const unsigned char *tt_ptr
;
421 while ((tt_buff_count
+ 1) * ETH_ALEN
<= tt_buff_len
) {
422 spin_lock_bh(&bat_priv
->tt_ghash_lock
);
424 tt_ptr
= tt_buff
+ (tt_buff_count
* ETH_ALEN
);
425 tt_global_entry
= tt_global_hash_find(bat_priv
, tt_ptr
);
427 if (!tt_global_entry
) {
428 spin_unlock_bh(&bat_priv
->tt_ghash_lock
);
430 tt_global_entry
= kmalloc(sizeof(*tt_global_entry
),
433 if (!tt_global_entry
)
436 memcpy(tt_global_entry
->addr
, tt_ptr
, ETH_ALEN
);
438 bat_dbg(DBG_ROUTES
, bat_priv
,
439 "Creating new global tt entry: "
441 tt_global_entry
->addr
, orig_node
->orig
);
443 spin_lock_bh(&bat_priv
->tt_ghash_lock
);
444 hash_add(bat_priv
->tt_global_hash
, compare_gtt
,
445 choose_orig
, tt_global_entry
,
446 &tt_global_entry
->hash_entry
);
450 tt_global_entry
->orig_node
= orig_node
;
451 spin_unlock_bh(&bat_priv
->tt_ghash_lock
);
453 /* remove address from local hash if present */
454 spin_lock_bh(&bat_priv
->tt_lhash_lock
);
456 tt_ptr
= tt_buff
+ (tt_buff_count
* ETH_ALEN
);
457 tt_local_entry
= tt_local_hash_find(bat_priv
, tt_ptr
);
460 tt_local_del(bat_priv
, tt_local_entry
,
461 "global tt received");
463 spin_unlock_bh(&bat_priv
->tt_lhash_lock
);
468 /* initialize, and overwrite if malloc succeeds */
469 orig_node
->tt_buff
= NULL
;
470 orig_node
->tt_buff_len
= 0;
472 if (tt_buff_len
> 0) {
473 orig_node
->tt_buff
= kmalloc(tt_buff_len
, GFP_ATOMIC
);
474 if (orig_node
->tt_buff
) {
475 memcpy(orig_node
->tt_buff
, tt_buff
, tt_buff_len
);
476 orig_node
->tt_buff_len
= tt_buff_len
;
481 int tt_global_seq_print_text(struct seq_file
*seq
, void *offset
)
483 struct net_device
*net_dev
= (struct net_device
*)seq
->private;
484 struct bat_priv
*bat_priv
= netdev_priv(net_dev
);
485 struct hashtable_t
*hash
= bat_priv
->tt_global_hash
;
486 struct tt_global_entry
*tt_global_entry
;
487 struct hard_iface
*primary_if
;
488 struct hlist_node
*node
;
489 struct hlist_head
*head
;
490 size_t buf_size
, pos
;
494 primary_if
= primary_if_get_selected(bat_priv
);
496 ret
= seq_printf(seq
, "BATMAN mesh %s disabled - please "
497 "specify interfaces to enable it\n",
502 if (primary_if
->if_status
!= IF_ACTIVE
) {
503 ret
= seq_printf(seq
, "BATMAN mesh %s disabled - "
504 "primary interface not active\n",
510 "Globally announced TT entries received via the mesh %s\n",
513 spin_lock_bh(&bat_priv
->tt_ghash_lock
);
516 /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/
517 for (i
= 0; i
< hash
->size
; i
++) {
518 head
= &hash
->table
[i
];
521 __hlist_for_each_rcu(node
, head
)
526 buff
= kmalloc(buf_size
, GFP_ATOMIC
);
528 spin_unlock_bh(&bat_priv
->tt_ghash_lock
);
535 for (i
= 0; i
< hash
->size
; i
++) {
536 head
= &hash
->table
[i
];
539 hlist_for_each_entry_rcu(tt_global_entry
, node
,
541 pos
+= snprintf(buff
+ pos
, 44,
543 tt_global_entry
->addr
,
544 tt_global_entry
->orig_node
->orig
);
549 spin_unlock_bh(&bat_priv
->tt_ghash_lock
);
551 seq_printf(seq
, "%s", buff
);
555 hardif_free_ref(primary_if
);
559 static void _tt_global_del_orig(struct bat_priv
*bat_priv
,
560 struct tt_global_entry
*tt_global_entry
,
563 bat_dbg(DBG_ROUTES
, bat_priv
,
564 "Deleting global tt entry %pM (via %pM): %s\n",
565 tt_global_entry
->addr
, tt_global_entry
->orig_node
->orig
,
568 hash_remove(bat_priv
->tt_global_hash
, compare_gtt
, choose_orig
,
569 tt_global_entry
->addr
);
570 kfree(tt_global_entry
);
573 void tt_global_del_orig(struct bat_priv
*bat_priv
,
574 struct orig_node
*orig_node
, const char *message
)
576 struct tt_global_entry
*tt_global_entry
;
577 int tt_buff_count
= 0;
578 unsigned char *tt_ptr
;
580 if (orig_node
->tt_buff_len
== 0)
583 spin_lock_bh(&bat_priv
->tt_ghash_lock
);
585 while ((tt_buff_count
+ 1) * ETH_ALEN
<= orig_node
->tt_buff_len
) {
586 tt_ptr
= orig_node
->tt_buff
+ (tt_buff_count
* ETH_ALEN
);
587 tt_global_entry
= tt_global_hash_find(bat_priv
, tt_ptr
);
589 if ((tt_global_entry
) &&
590 (tt_global_entry
->orig_node
== orig_node
))
591 _tt_global_del_orig(bat_priv
, tt_global_entry
,
597 spin_unlock_bh(&bat_priv
->tt_ghash_lock
);
599 orig_node
->tt_buff_len
= 0;
600 kfree(orig_node
->tt_buff
);
601 orig_node
->tt_buff
= NULL
;
604 static void tt_global_del(struct hlist_node
*node
, void *arg
)
606 void *data
= container_of(node
, struct tt_global_entry
, hash_entry
);
611 void tt_global_free(struct bat_priv
*bat_priv
)
613 if (!bat_priv
->tt_global_hash
)
616 hash_delete(bat_priv
->tt_global_hash
, tt_global_del
, NULL
);
617 bat_priv
->tt_global_hash
= NULL
;
620 struct orig_node
*transtable_search(struct bat_priv
*bat_priv
,
623 struct tt_global_entry
*tt_global_entry
;
624 struct orig_node
*orig_node
= NULL
;
626 spin_lock_bh(&bat_priv
->tt_ghash_lock
);
627 tt_global_entry
= tt_global_hash_find(bat_priv
, addr
);
629 if (!tt_global_entry
)
632 if (!atomic_inc_not_zero(&tt_global_entry
->orig_node
->refcount
))
635 orig_node
= tt_global_entry
->orig_node
;
638 spin_unlock_bh(&bat_priv
->tt_ghash_lock
);
This page took 0.054886 seconds and 5 git commands to generate.