c46b1407c885c9426e842421d79b6eedb8777865
[linux-drm-fsl-dcu.git] / net / batman-adv / translation-table.c
1 /*
2  * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
3  *
4  * Marek Lindner, Simon Wunderlich
5  *
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.
9  *
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.
14  *
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
18  * 02110-1301, USA
19  *
20  */
21
22 #include "main.h"
23 #include "translation-table.h"
24 #include "soft-interface.h"
25 #include "hard-interface.h"
26 #include "send.h"
27 #include "hash.h"
28 #include "originator.h"
29 #include "routing.h"
30
31 #include <linux/crc16.h>
32
33 static void _tt_global_del(struct bat_priv *bat_priv,
34                            struct tt_global_entry *tt_global_entry,
35                            const char *message);
36 static void tt_purge(struct work_struct *work);
37
38 /* returns 1 if they are the same mac addr */
39 static int compare_ltt(const struct hlist_node *node, const void *data2)
40 {
41         const void *data1 = container_of(node, struct tt_local_entry,
42                                          hash_entry);
43
44         return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
45 }
46
47 /* returns 1 if they are the same mac addr */
48 static int compare_gtt(const struct hlist_node *node, const void *data2)
49 {
50         const void *data1 = container_of(node, struct tt_global_entry,
51                                          hash_entry);
52
53         return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
54 }
55
56 static void tt_start_timer(struct bat_priv *bat_priv)
57 {
58         INIT_DELAYED_WORK(&bat_priv->tt_work, tt_purge);
59         queue_delayed_work(bat_event_workqueue, &bat_priv->tt_work,
60                            msecs_to_jiffies(5000));
61 }
62
63 static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
64                                                  const void *data)
65 {
66         struct hashtable_t *hash = bat_priv->tt_local_hash;
67         struct hlist_head *head;
68         struct hlist_node *node;
69         struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL;
70         int index;
71
72         if (!hash)
73                 return NULL;
74
75         index = choose_orig(data, hash->size);
76         head = &hash->table[index];
77
78         rcu_read_lock();
79         hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) {
80                 if (!compare_eth(tt_local_entry, data))
81                         continue;
82
83                 if (!atomic_inc_not_zero(&tt_local_entry->refcount))
84                         continue;
85
86                 tt_local_entry_tmp = tt_local_entry;
87                 break;
88         }
89         rcu_read_unlock();
90
91         return tt_local_entry_tmp;
92 }
93
94 static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
95                                                    const void *data)
96 {
97         struct hashtable_t *hash = bat_priv->tt_global_hash;
98         struct hlist_head *head;
99         struct hlist_node *node;
100         struct tt_global_entry *tt_global_entry;
101         struct tt_global_entry *tt_global_entry_tmp = NULL;
102         int index;
103
104         if (!hash)
105                 return NULL;
106
107         index = choose_orig(data, hash->size);
108         head = &hash->table[index];
109
110         rcu_read_lock();
111         hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) {
112                 if (!compare_eth(tt_global_entry, data))
113                         continue;
114
115                 if (!atomic_inc_not_zero(&tt_global_entry->refcount))
116                         continue;
117
118                 tt_global_entry_tmp = tt_global_entry;
119                 break;
120         }
121         rcu_read_unlock();
122
123         return tt_global_entry_tmp;
124 }
125
126 static bool is_out_of_time(unsigned long starting_time, unsigned long timeout)
127 {
128         unsigned long deadline;
129         deadline = starting_time + msecs_to_jiffies(timeout);
130
131         return time_after(jiffies, deadline);
132 }
133
134 static void tt_local_entry_free_ref(struct tt_local_entry *tt_local_entry)
135 {
136         if (atomic_dec_and_test(&tt_local_entry->refcount))
137                 kfree_rcu(tt_local_entry, rcu);
138 }
139
140 static void tt_global_entry_free_rcu(struct rcu_head *rcu)
141 {
142         struct tt_global_entry *tt_global_entry;
143
144         tt_global_entry = container_of(rcu, struct tt_global_entry, rcu);
145
146         if (tt_global_entry->orig_node)
147                 orig_node_free_ref(tt_global_entry->orig_node);
148
149         kfree(tt_global_entry);
150 }
151
152 static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry)
153 {
154         if (atomic_dec_and_test(&tt_global_entry->refcount))
155                 call_rcu(&tt_global_entry->rcu, tt_global_entry_free_rcu);
156 }
157
158 static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr,
159                            uint8_t flags)
160 {
161         struct tt_change_node *tt_change_node;
162
163         tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC);
164
165         if (!tt_change_node)
166                 return;
167
168         tt_change_node->change.flags = flags;
169         memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
170
171         spin_lock_bh(&bat_priv->tt_changes_list_lock);
172         /* track the change in the OGMinterval list */
173         list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list);
174         atomic_inc(&bat_priv->tt_local_changes);
175         spin_unlock_bh(&bat_priv->tt_changes_list_lock);
176
177         atomic_set(&bat_priv->tt_ogm_append_cnt, 0);
178 }
179
180 int tt_len(int changes_num)
181 {
182         return changes_num * sizeof(struct tt_change);
183 }
184
185 static int tt_local_init(struct bat_priv *bat_priv)
186 {
187         if (bat_priv->tt_local_hash)
188                 return 1;
189
190         bat_priv->tt_local_hash = hash_new(1024);
191
192         if (!bat_priv->tt_local_hash)
193                 return 0;
194
195         return 1;
196 }
197
198 void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
199                   int ifindex)
200 {
201         struct bat_priv *bat_priv = netdev_priv(soft_iface);
202         struct tt_local_entry *tt_local_entry = NULL;
203         struct tt_global_entry *tt_global_entry = NULL;
204
205         tt_local_entry = tt_local_hash_find(bat_priv, addr);
206
207         if (tt_local_entry) {
208                 tt_local_entry->last_seen = jiffies;
209                 goto out;
210         }
211
212         tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC);
213         if (!tt_local_entry)
214                 goto out;
215
216         bat_dbg(DBG_TT, bat_priv,
217                 "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
218                 (uint8_t)atomic_read(&bat_priv->ttvn));
219
220         memcpy(tt_local_entry->addr, addr, ETH_ALEN);
221         tt_local_entry->last_seen = jiffies;
222         tt_local_entry->flags = NO_FLAGS;
223         if (is_wifi_iface(ifindex))
224                 tt_local_entry->flags |= TT_CLIENT_WIFI;
225         atomic_set(&tt_local_entry->refcount, 2);
226
227         /* the batman interface mac address should never be purged */
228         if (compare_eth(addr, soft_iface->dev_addr))
229                 tt_local_entry->flags |= TT_CLIENT_NOPURGE;
230
231         tt_local_event(bat_priv, addr, tt_local_entry->flags);
232
233         /* The local entry has to be marked as NEW to avoid to send it in
234          * a full table response going out before the next ttvn increment
235          * (consistency check) */
236         tt_local_entry->flags |= TT_CLIENT_NEW;
237
238         hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig,
239                  tt_local_entry, &tt_local_entry->hash_entry);
240
241         /* remove address from global hash if present */
242         tt_global_entry = tt_global_hash_find(bat_priv, addr);
243
244         /* Check whether it is a roaming! */
245         if (tt_global_entry) {
246                 /* This node is probably going to update its tt table */
247                 tt_global_entry->orig_node->tt_poss_change = true;
248                 /* The global entry has to be marked as ROAMING and has to be
249                  * kept for consistency purpose */
250                 tt_global_entry->flags |= TT_CLIENT_ROAM;
251                 tt_global_entry->roam_at = jiffies;
252
253                 send_roam_adv(bat_priv, tt_global_entry->addr,
254                               tt_global_entry->orig_node);
255         }
256 out:
257         if (tt_local_entry)
258                 tt_local_entry_free_ref(tt_local_entry);
259         if (tt_global_entry)
260                 tt_global_entry_free_ref(tt_global_entry);
261 }
262
263 int tt_changes_fill_buffer(struct bat_priv *bat_priv,
264                            unsigned char *buff, int buff_len)
265 {
266         int count = 0, tot_changes = 0;
267         struct tt_change_node *entry, *safe;
268
269         if (buff_len > 0)
270                 tot_changes = buff_len / tt_len(1);
271
272         spin_lock_bh(&bat_priv->tt_changes_list_lock);
273         atomic_set(&bat_priv->tt_local_changes, 0);
274
275         list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
276                         list) {
277                 if (count < tot_changes) {
278                         memcpy(buff + tt_len(count),
279                                &entry->change, sizeof(struct tt_change));
280                         count++;
281                 }
282                 list_del(&entry->list);
283                 kfree(entry);
284         }
285         spin_unlock_bh(&bat_priv->tt_changes_list_lock);
286
287         /* Keep the buffer for possible tt_request */
288         spin_lock_bh(&bat_priv->tt_buff_lock);
289         kfree(bat_priv->tt_buff);
290         bat_priv->tt_buff_len = 0;
291         bat_priv->tt_buff = NULL;
292         /* We check whether this new OGM has no changes due to size
293          * problems */
294         if (buff_len > 0) {
295                 /**
296                  * if kmalloc() fails we will reply with the full table
297                  * instead of providing the diff
298                  */
299                 bat_priv->tt_buff = kmalloc(buff_len, GFP_ATOMIC);
300                 if (bat_priv->tt_buff) {
301                         memcpy(bat_priv->tt_buff, buff, buff_len);
302                         bat_priv->tt_buff_len = buff_len;
303                 }
304         }
305         spin_unlock_bh(&bat_priv->tt_buff_lock);
306
307         return tot_changes;
308 }
309
310 int tt_local_seq_print_text(struct seq_file *seq, void *offset)
311 {
312         struct net_device *net_dev = (struct net_device *)seq->private;
313         struct bat_priv *bat_priv = netdev_priv(net_dev);
314         struct hashtable_t *hash = bat_priv->tt_local_hash;
315         struct tt_local_entry *tt_local_entry;
316         struct hard_iface *primary_if;
317         struct hlist_node *node;
318         struct hlist_head *head;
319         size_t buf_size, pos;
320         char *buff;
321         int i, ret = 0;
322
323         primary_if = primary_if_get_selected(bat_priv);
324         if (!primary_if) {
325                 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
326                                  "please specify interfaces to enable it\n",
327                                  net_dev->name);
328                 goto out;
329         }
330
331         if (primary_if->if_status != IF_ACTIVE) {
332                 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
333                                  "primary interface not active\n",
334                                  net_dev->name);
335                 goto out;
336         }
337
338         seq_printf(seq, "Locally retrieved addresses (from %s) "
339                    "announced via TT (TTVN: %u):\n",
340                    net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn));
341
342         buf_size = 1;
343         /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
344         for (i = 0; i < hash->size; i++) {
345                 head = &hash->table[i];
346
347                 rcu_read_lock();
348                 __hlist_for_each_rcu(node, head)
349                         buf_size += 29;
350                 rcu_read_unlock();
351         }
352
353         buff = kmalloc(buf_size, GFP_ATOMIC);
354         if (!buff) {
355                 ret = -ENOMEM;
356                 goto out;
357         }
358
359         buff[0] = '\0';
360         pos = 0;
361
362         for (i = 0; i < hash->size; i++) {
363                 head = &hash->table[i];
364
365                 rcu_read_lock();
366                 hlist_for_each_entry_rcu(tt_local_entry, node,
367                                          head, hash_entry) {
368                         pos += snprintf(buff + pos, 30, " * %pM "
369                                         "[%c%c%c%c%c]\n",
370                                         tt_local_entry->addr,
371                                         (tt_local_entry->flags &
372                                          TT_CLIENT_ROAM ? 'R' : '.'),
373                                         (tt_local_entry->flags &
374                                          TT_CLIENT_NOPURGE ? 'P' : '.'),
375                                         (tt_local_entry->flags &
376                                          TT_CLIENT_NEW ? 'N' : '.'),
377                                         (tt_local_entry->flags &
378                                          TT_CLIENT_PENDING ? 'X' : '.'),
379                                         (tt_local_entry->flags &
380                                          TT_CLIENT_WIFI ? 'W' : '.'));
381                 }
382                 rcu_read_unlock();
383         }
384
385         seq_printf(seq, "%s", buff);
386         kfree(buff);
387 out:
388         if (primary_if)
389                 hardif_free_ref(primary_if);
390         return ret;
391 }
392
393 static void tt_local_set_pending(struct bat_priv *bat_priv,
394                                  struct tt_local_entry *tt_local_entry,
395                                  uint16_t flags)
396 {
397         tt_local_event(bat_priv, tt_local_entry->addr,
398                        tt_local_entry->flags | flags);
399
400         /* The local client has to be marked as "pending to be removed" but has
401          * to be kept in the table in order to send it in a full table
402          * response issued before the net ttvn increment (consistency check) */
403         tt_local_entry->flags |= TT_CLIENT_PENDING;
404 }
405
406 void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr,
407                      const char *message, bool roaming)
408 {
409         struct tt_local_entry *tt_local_entry = NULL;
410
411         tt_local_entry = tt_local_hash_find(bat_priv, addr);
412         if (!tt_local_entry)
413                 goto out;
414
415         tt_local_set_pending(bat_priv, tt_local_entry, TT_CLIENT_DEL |
416                              (roaming ? TT_CLIENT_ROAM : NO_FLAGS));
417
418         bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) pending to be removed: "
419                 "%s\n", tt_local_entry->addr, message);
420 out:
421         if (tt_local_entry)
422                 tt_local_entry_free_ref(tt_local_entry);
423 }
424
425 static void tt_local_purge(struct bat_priv *bat_priv)
426 {
427         struct hashtable_t *hash = bat_priv->tt_local_hash;
428         struct tt_local_entry *tt_local_entry;
429         struct hlist_node *node, *node_tmp;
430         struct hlist_head *head;
431         spinlock_t *list_lock; /* protects write access to the hash lists */
432         int i;
433
434         for (i = 0; i < hash->size; i++) {
435                 head = &hash->table[i];
436                 list_lock = &hash->list_locks[i];
437
438                 spin_lock_bh(list_lock);
439                 hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
440                                           head, hash_entry) {
441                         if (tt_local_entry->flags & TT_CLIENT_NOPURGE)
442                                 continue;
443
444                         /* entry already marked for deletion */
445                         if (tt_local_entry->flags & TT_CLIENT_PENDING)
446                                 continue;
447
448                         if (!is_out_of_time(tt_local_entry->last_seen,
449                                             TT_LOCAL_TIMEOUT * 1000))
450                                 continue;
451
452                         tt_local_set_pending(bat_priv, tt_local_entry,
453                                              TT_CLIENT_DEL);
454                         bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) "
455                                 "pending to be removed: timed out\n",
456                                 tt_local_entry->addr);
457                 }
458                 spin_unlock_bh(list_lock);
459         }
460
461 }
462
463 static void tt_local_table_free(struct bat_priv *bat_priv)
464 {
465         struct hashtable_t *hash;
466         spinlock_t *list_lock; /* protects write access to the hash lists */
467         struct tt_local_entry *tt_local_entry;
468         struct hlist_node *node, *node_tmp;
469         struct hlist_head *head;
470         int i;
471
472         if (!bat_priv->tt_local_hash)
473                 return;
474
475         hash = bat_priv->tt_local_hash;
476
477         for (i = 0; i < hash->size; i++) {
478                 head = &hash->table[i];
479                 list_lock = &hash->list_locks[i];
480
481                 spin_lock_bh(list_lock);
482                 hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
483                                           head, hash_entry) {
484                         hlist_del_rcu(node);
485                         tt_local_entry_free_ref(tt_local_entry);
486                 }
487                 spin_unlock_bh(list_lock);
488         }
489
490         hash_destroy(hash);
491
492         bat_priv->tt_local_hash = NULL;
493 }
494
495 static int tt_global_init(struct bat_priv *bat_priv)
496 {
497         if (bat_priv->tt_global_hash)
498                 return 1;
499
500         bat_priv->tt_global_hash = hash_new(1024);
501
502         if (!bat_priv->tt_global_hash)
503                 return 0;
504
505         return 1;
506 }
507
508 static void tt_changes_list_free(struct bat_priv *bat_priv)
509 {
510         struct tt_change_node *entry, *safe;
511
512         spin_lock_bh(&bat_priv->tt_changes_list_lock);
513
514         list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
515                                  list) {
516                 list_del(&entry->list);
517                 kfree(entry);
518         }
519
520         atomic_set(&bat_priv->tt_local_changes, 0);
521         spin_unlock_bh(&bat_priv->tt_changes_list_lock);
522 }
523
524 /* caller must hold orig_node refcount */
525 int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
526                   const unsigned char *tt_addr, uint8_t ttvn, bool roaming,
527                   bool wifi)
528 {
529         struct tt_global_entry *tt_global_entry;
530         struct orig_node *orig_node_tmp;
531         int ret = 0;
532
533         tt_global_entry = tt_global_hash_find(bat_priv, tt_addr);
534
535         if (!tt_global_entry) {
536                 tt_global_entry =
537                         kmalloc(sizeof(*tt_global_entry),
538                                 GFP_ATOMIC);
539                 if (!tt_global_entry)
540                         goto out;
541
542                 memcpy(tt_global_entry->addr, tt_addr, ETH_ALEN);
543                 /* Assign the new orig_node */
544                 atomic_inc(&orig_node->refcount);
545                 tt_global_entry->orig_node = orig_node;
546                 tt_global_entry->ttvn = ttvn;
547                 tt_global_entry->flags = NO_FLAGS;
548                 tt_global_entry->roam_at = 0;
549                 atomic_set(&tt_global_entry->refcount, 2);
550
551                 hash_add(bat_priv->tt_global_hash, compare_gtt,
552                          choose_orig, tt_global_entry,
553                          &tt_global_entry->hash_entry);
554                 atomic_inc(&orig_node->tt_size);
555         } else {
556                 if (tt_global_entry->orig_node != orig_node) {
557                         atomic_dec(&tt_global_entry->orig_node->tt_size);
558                         orig_node_tmp = tt_global_entry->orig_node;
559                         atomic_inc(&orig_node->refcount);
560                         tt_global_entry->orig_node = orig_node;
561                         orig_node_free_ref(orig_node_tmp);
562                         atomic_inc(&orig_node->tt_size);
563                 }
564                 tt_global_entry->ttvn = ttvn;
565                 tt_global_entry->flags = NO_FLAGS;
566                 tt_global_entry->roam_at = 0;
567         }
568
569         if (wifi)
570                 tt_global_entry->flags |= TT_CLIENT_WIFI;
571
572         bat_dbg(DBG_TT, bat_priv,
573                 "Creating new global tt entry: %pM (via %pM)\n",
574                 tt_global_entry->addr, orig_node->orig);
575
576         /* remove address from local hash if present */
577         tt_local_remove(bat_priv, tt_global_entry->addr,
578                         "global tt received", roaming);
579         ret = 1;
580 out:
581         if (tt_global_entry)
582                 tt_global_entry_free_ref(tt_global_entry);
583         return ret;
584 }
585
586 int tt_global_seq_print_text(struct seq_file *seq, void *offset)
587 {
588         struct net_device *net_dev = (struct net_device *)seq->private;
589         struct bat_priv *bat_priv = netdev_priv(net_dev);
590         struct hashtable_t *hash = bat_priv->tt_global_hash;
591         struct tt_global_entry *tt_global_entry;
592         struct hard_iface *primary_if;
593         struct hlist_node *node;
594         struct hlist_head *head;
595         size_t buf_size, pos;
596         char *buff;
597         int i, ret = 0;
598
599         primary_if = primary_if_get_selected(bat_priv);
600         if (!primary_if) {
601                 ret = seq_printf(seq, "BATMAN mesh %s disabled - please "
602                                  "specify interfaces to enable it\n",
603                                  net_dev->name);
604                 goto out;
605         }
606
607         if (primary_if->if_status != IF_ACTIVE) {
608                 ret = seq_printf(seq, "BATMAN mesh %s disabled - "
609                                  "primary interface not active\n",
610                                  net_dev->name);
611                 goto out;
612         }
613
614         seq_printf(seq,
615                    "Globally announced TT entries received via the mesh %s\n",
616                    net_dev->name);
617         seq_printf(seq, "       %-13s %s       %-15s %s %s\n",
618                    "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags");
619
620         buf_size = 1;
621         /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
622          * xx:xx:xx:xx:xx:xx (cur_ttvn)\n"*/
623         for (i = 0; i < hash->size; i++) {
624                 head = &hash->table[i];
625
626                 rcu_read_lock();
627                 __hlist_for_each_rcu(node, head)
628                         buf_size += 67;
629                 rcu_read_unlock();
630         }
631
632         buff = kmalloc(buf_size, GFP_ATOMIC);
633         if (!buff) {
634                 ret = -ENOMEM;
635                 goto out;
636         }
637
638         buff[0] = '\0';
639         pos = 0;
640
641         for (i = 0; i < hash->size; i++) {
642                 head = &hash->table[i];
643
644                 rcu_read_lock();
645                 hlist_for_each_entry_rcu(tt_global_entry, node,
646                                          head, hash_entry) {
647                         pos += snprintf(buff + pos, 69,
648                                         " * %pM  (%3u) via %pM     (%3u)   "
649                                         "[%c%c%c]\n", tt_global_entry->addr,
650                                         tt_global_entry->ttvn,
651                                         tt_global_entry->orig_node->orig,
652                                         (uint8_t) atomic_read(
653                                                 &tt_global_entry->orig_node->
654                                                 last_ttvn),
655                                         (tt_global_entry->flags &
656                                          TT_CLIENT_ROAM ? 'R' : '.'),
657                                         (tt_global_entry->flags &
658                                          TT_CLIENT_PENDING ? 'X' : '.'),
659                                         (tt_global_entry->flags &
660                                          TT_CLIENT_WIFI ? 'W' : '.'));
661                 }
662                 rcu_read_unlock();
663         }
664
665         seq_printf(seq, "%s", buff);
666         kfree(buff);
667 out:
668         if (primary_if)
669                 hardif_free_ref(primary_if);
670         return ret;
671 }
672
673 static void _tt_global_del(struct bat_priv *bat_priv,
674                            struct tt_global_entry *tt_global_entry,
675                            const char *message)
676 {
677         if (!tt_global_entry)
678                 goto out;
679
680         bat_dbg(DBG_TT, bat_priv,
681                 "Deleting global tt entry %pM (via %pM): %s\n",
682                 tt_global_entry->addr, tt_global_entry->orig_node->orig,
683                 message);
684
685         atomic_dec(&tt_global_entry->orig_node->tt_size);
686
687         hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig,
688                     tt_global_entry->addr);
689 out:
690         if (tt_global_entry)
691                 tt_global_entry_free_ref(tt_global_entry);
692 }
693
694 void tt_global_del(struct bat_priv *bat_priv,
695                    struct orig_node *orig_node, const unsigned char *addr,
696                    const char *message, bool roaming)
697 {
698         struct tt_global_entry *tt_global_entry = NULL;
699
700         tt_global_entry = tt_global_hash_find(bat_priv, addr);
701         if (!tt_global_entry)
702                 goto out;
703
704         if (tt_global_entry->orig_node == orig_node) {
705                 if (roaming) {
706                         tt_global_entry->flags |= TT_CLIENT_ROAM;
707                         tt_global_entry->roam_at = jiffies;
708                         goto out;
709                 }
710                 _tt_global_del(bat_priv, tt_global_entry, message);
711         }
712 out:
713         if (tt_global_entry)
714                 tt_global_entry_free_ref(tt_global_entry);
715 }
716
717 void tt_global_del_orig(struct bat_priv *bat_priv,
718                         struct orig_node *orig_node, const char *message)
719 {
720         struct tt_global_entry *tt_global_entry;
721         int i;
722         struct hashtable_t *hash = bat_priv->tt_global_hash;
723         struct hlist_node *node, *safe;
724         struct hlist_head *head;
725         spinlock_t *list_lock; /* protects write access to the hash lists */
726
727         if (!hash)
728                 return;
729
730         for (i = 0; i < hash->size; i++) {
731                 head = &hash->table[i];
732                 list_lock = &hash->list_locks[i];
733
734                 spin_lock_bh(list_lock);
735                 hlist_for_each_entry_safe(tt_global_entry, node, safe,
736                                          head, hash_entry) {
737                         if (tt_global_entry->orig_node == orig_node) {
738                                 bat_dbg(DBG_TT, bat_priv,
739                                         "Deleting global tt entry %pM "
740                                         "(via %pM): originator time out\n",
741                                         tt_global_entry->addr,
742                                         tt_global_entry->orig_node->orig);
743                                 hlist_del_rcu(node);
744                                 tt_global_entry_free_ref(tt_global_entry);
745                         }
746                 }
747                 spin_unlock_bh(list_lock);
748         }
749         atomic_set(&orig_node->tt_size, 0);
750 }
751
752 static void tt_global_roam_purge(struct bat_priv *bat_priv)
753 {
754         struct hashtable_t *hash = bat_priv->tt_global_hash;
755         struct tt_global_entry *tt_global_entry;
756         struct hlist_node *node, *node_tmp;
757         struct hlist_head *head;
758         spinlock_t *list_lock; /* protects write access to the hash lists */
759         int i;
760
761         for (i = 0; i < hash->size; i++) {
762                 head = &hash->table[i];
763                 list_lock = &hash->list_locks[i];
764
765                 spin_lock_bh(list_lock);
766                 hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
767                                           head, hash_entry) {
768                         if (!(tt_global_entry->flags & TT_CLIENT_ROAM))
769                                 continue;
770                         if (!is_out_of_time(tt_global_entry->roam_at,
771                                             TT_CLIENT_ROAM_TIMEOUT * 1000))
772                                 continue;
773
774                         bat_dbg(DBG_TT, bat_priv, "Deleting global "
775                                 "tt entry (%pM): Roaming timeout\n",
776                                 tt_global_entry->addr);
777                         atomic_dec(&tt_global_entry->orig_node->tt_size);
778                         hlist_del_rcu(node);
779                         tt_global_entry_free_ref(tt_global_entry);
780                 }
781                 spin_unlock_bh(list_lock);
782         }
783
784 }
785
786 static void tt_global_table_free(struct bat_priv *bat_priv)
787 {
788         struct hashtable_t *hash;
789         spinlock_t *list_lock; /* protects write access to the hash lists */
790         struct tt_global_entry *tt_global_entry;
791         struct hlist_node *node, *node_tmp;
792         struct hlist_head *head;
793         int i;
794
795         if (!bat_priv->tt_global_hash)
796                 return;
797
798         hash = bat_priv->tt_global_hash;
799
800         for (i = 0; i < hash->size; i++) {
801                 head = &hash->table[i];
802                 list_lock = &hash->list_locks[i];
803
804                 spin_lock_bh(list_lock);
805                 hlist_for_each_entry_safe(tt_global_entry, node, node_tmp,
806                                           head, hash_entry) {
807                         hlist_del_rcu(node);
808                         tt_global_entry_free_ref(tt_global_entry);
809                 }
810                 spin_unlock_bh(list_lock);
811         }
812
813         hash_destroy(hash);
814
815         bat_priv->tt_global_hash = NULL;
816 }
817
818 static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry,
819                             struct tt_global_entry *tt_global_entry)
820 {
821         bool ret = false;
822
823         if (tt_local_entry->flags & TT_CLIENT_WIFI &&
824             tt_global_entry->flags & TT_CLIENT_WIFI)
825                 ret = true;
826
827         return ret;
828 }
829
830 struct orig_node *transtable_search(struct bat_priv *bat_priv,
831                                     const uint8_t *src, const uint8_t *addr)
832 {
833         struct tt_local_entry *tt_local_entry = NULL;
834         struct tt_global_entry *tt_global_entry = NULL;
835         struct orig_node *orig_node = NULL;
836
837         if (src && atomic_read(&bat_priv->ap_isolation)) {
838                 tt_local_entry = tt_local_hash_find(bat_priv, src);
839                 if (!tt_local_entry)
840                         goto out;
841         }
842
843         tt_global_entry = tt_global_hash_find(bat_priv, addr);
844         if (!tt_global_entry)
845                 goto out;
846
847         /* check whether the clients should not communicate due to AP
848          * isolation */
849         if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry))
850                 goto out;
851
852         if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount))
853                 goto out;
854
855         /* A global client marked as PENDING has already moved from that
856          * originator */
857         if (tt_global_entry->flags & TT_CLIENT_PENDING)
858                 goto out;
859
860         orig_node = tt_global_entry->orig_node;
861
862 out:
863         if (tt_global_entry)
864                 tt_global_entry_free_ref(tt_global_entry);
865         if (tt_local_entry)
866                 tt_local_entry_free_ref(tt_local_entry);
867
868         return orig_node;
869 }
870
871 /* Calculates the checksum of the local table of a given orig_node */
872 uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node)
873 {
874         uint16_t total = 0, total_one;
875         struct hashtable_t *hash = bat_priv->tt_global_hash;
876         struct tt_global_entry *tt_global_entry;
877         struct hlist_node *node;
878         struct hlist_head *head;
879         int i, j;
880
881         for (i = 0; i < hash->size; i++) {
882                 head = &hash->table[i];
883
884                 rcu_read_lock();
885                 hlist_for_each_entry_rcu(tt_global_entry, node,
886                                          head, hash_entry) {
887                         if (compare_eth(tt_global_entry->orig_node,
888                                         orig_node)) {
889                                 /* Roaming clients are in the global table for
890                                  * consistency only. They don't have to be
891                                  * taken into account while computing the
892                                  * global crc */
893                                 if (tt_global_entry->flags & TT_CLIENT_ROAM)
894                                         continue;
895                                 total_one = 0;
896                                 for (j = 0; j < ETH_ALEN; j++)
897                                         total_one = crc16_byte(total_one,
898                                                 tt_global_entry->addr[j]);
899                                 total ^= total_one;
900                         }
901                 }
902                 rcu_read_unlock();
903         }
904
905         return total;
906 }
907
908 /* Calculates the checksum of the local table */
909 uint16_t tt_local_crc(struct bat_priv *bat_priv)
910 {
911         uint16_t total = 0, total_one;
912         struct hashtable_t *hash = bat_priv->tt_local_hash;
913         struct tt_local_entry *tt_local_entry;
914         struct hlist_node *node;
915         struct hlist_head *head;
916         int i, j;
917
918         for (i = 0; i < hash->size; i++) {
919                 head = &hash->table[i];
920
921                 rcu_read_lock();
922                 hlist_for_each_entry_rcu(tt_local_entry, node,
923                                          head, hash_entry) {
924                         /* not yet committed clients have not to be taken into
925                          * account while computing the CRC */
926                         if (tt_local_entry->flags & TT_CLIENT_NEW)
927                                 continue;
928                         total_one = 0;
929                         for (j = 0; j < ETH_ALEN; j++)
930                                 total_one = crc16_byte(total_one,
931                                                    tt_local_entry->addr[j]);
932                         total ^= total_one;
933                 }
934                 rcu_read_unlock();
935         }
936
937         return total;
938 }
939
940 static void tt_req_list_free(struct bat_priv *bat_priv)
941 {
942         struct tt_req_node *node, *safe;
943
944         spin_lock_bh(&bat_priv->tt_req_list_lock);
945
946         list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
947                 list_del(&node->list);
948                 kfree(node);
949         }
950
951         spin_unlock_bh(&bat_priv->tt_req_list_lock);
952 }
953
954 void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
955                          const unsigned char *tt_buff, uint8_t tt_num_changes)
956 {
957         uint16_t tt_buff_len = tt_len(tt_num_changes);
958
959         /* Replace the old buffer only if I received something in the
960          * last OGM (the OGM could carry no changes) */
961         spin_lock_bh(&orig_node->tt_buff_lock);
962         if (tt_buff_len > 0) {
963                 kfree(orig_node->tt_buff);
964                 orig_node->tt_buff_len = 0;
965                 orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
966                 if (orig_node->tt_buff) {
967                         memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
968                         orig_node->tt_buff_len = tt_buff_len;
969                 }
970         }
971         spin_unlock_bh(&orig_node->tt_buff_lock);
972 }
973
974 static void tt_req_purge(struct bat_priv *bat_priv)
975 {
976         struct tt_req_node *node, *safe;
977
978         spin_lock_bh(&bat_priv->tt_req_list_lock);
979         list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
980                 if (is_out_of_time(node->issued_at,
981                     TT_REQUEST_TIMEOUT * 1000)) {
982                         list_del(&node->list);
983                         kfree(node);
984                 }
985         }
986         spin_unlock_bh(&bat_priv->tt_req_list_lock);
987 }
988
989 /* returns the pointer to the new tt_req_node struct if no request
990  * has already been issued for this orig_node, NULL otherwise */
991 static struct tt_req_node *new_tt_req_node(struct bat_priv *bat_priv,
992                                           struct orig_node *orig_node)
993 {
994         struct tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
995
996         spin_lock_bh(&bat_priv->tt_req_list_lock);
997         list_for_each_entry(tt_req_node_tmp, &bat_priv->tt_req_list, list) {
998                 if (compare_eth(tt_req_node_tmp, orig_node) &&
999                     !is_out_of_time(tt_req_node_tmp->issued_at,
1000                                     TT_REQUEST_TIMEOUT * 1000))
1001                         goto unlock;
1002         }
1003
1004         tt_req_node = kmalloc(sizeof(*tt_req_node), GFP_ATOMIC);
1005         if (!tt_req_node)
1006                 goto unlock;
1007
1008         memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN);
1009         tt_req_node->issued_at = jiffies;
1010
1011         list_add(&tt_req_node->list, &bat_priv->tt_req_list);
1012 unlock:
1013         spin_unlock_bh(&bat_priv->tt_req_list_lock);
1014         return tt_req_node;
1015 }
1016
1017 /* data_ptr is useless here, but has to be kept to respect the prototype */
1018 static int tt_local_valid_entry(const void *entry_ptr, const void *data_ptr)
1019 {
1020         const struct tt_local_entry *tt_local_entry = entry_ptr;
1021
1022         if (tt_local_entry->flags & TT_CLIENT_NEW)
1023                 return 0;
1024         return 1;
1025 }
1026
1027 static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr)
1028 {
1029         const struct tt_global_entry *tt_global_entry = entry_ptr;
1030         const struct orig_node *orig_node = data_ptr;
1031
1032         if (tt_global_entry->flags & TT_CLIENT_ROAM)
1033                 return 0;
1034
1035         return (tt_global_entry->orig_node == orig_node);
1036 }
1037
1038 static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
1039                                               struct hashtable_t *hash,
1040                                               struct hard_iface *primary_if,
1041                                               int (*valid_cb)(const void *,
1042                                                               const void *),
1043                                               void *cb_data)
1044 {
1045         struct tt_local_entry *tt_local_entry;
1046         struct tt_query_packet *tt_response;
1047         struct tt_change *tt_change;
1048         struct hlist_node *node;
1049         struct hlist_head *head;
1050         struct sk_buff *skb = NULL;
1051         uint16_t tt_tot, tt_count;
1052         ssize_t tt_query_size = sizeof(struct tt_query_packet);
1053         int i;
1054
1055         if (tt_query_size + tt_len > primary_if->soft_iface->mtu) {
1056                 tt_len = primary_if->soft_iface->mtu - tt_query_size;
1057                 tt_len -= tt_len % sizeof(struct tt_change);
1058         }
1059         tt_tot = tt_len / sizeof(struct tt_change);
1060
1061         skb = dev_alloc_skb(tt_query_size + tt_len + ETH_HLEN);
1062         if (!skb)
1063                 goto out;
1064
1065         skb_reserve(skb, ETH_HLEN);
1066         tt_response = (struct tt_query_packet *)skb_put(skb,
1067                                                      tt_query_size + tt_len);
1068         tt_response->ttvn = ttvn;
1069
1070         tt_change = (struct tt_change *)(skb->data + tt_query_size);
1071         tt_count = 0;
1072
1073         rcu_read_lock();
1074         for (i = 0; i < hash->size; i++) {
1075                 head = &hash->table[i];
1076
1077                 hlist_for_each_entry_rcu(tt_local_entry, node,
1078                                          head, hash_entry) {
1079                         if (tt_count == tt_tot)
1080                                 break;
1081
1082                         if ((valid_cb) && (!valid_cb(tt_local_entry, cb_data)))
1083                                 continue;
1084
1085                         memcpy(tt_change->addr, tt_local_entry->addr, ETH_ALEN);
1086                         tt_change->flags = NO_FLAGS;
1087
1088                         tt_count++;
1089                         tt_change++;
1090                 }
1091         }
1092         rcu_read_unlock();
1093
1094         /* store in the message the number of entries we have successfully
1095          * copied */
1096         tt_response->tt_data = htons(tt_count);
1097
1098 out:
1099         return skb;
1100 }
1101
1102 static int send_tt_request(struct bat_priv *bat_priv,
1103                            struct orig_node *dst_orig_node,
1104                            uint8_t ttvn, uint16_t tt_crc, bool full_table)
1105 {
1106         struct sk_buff *skb = NULL;
1107         struct tt_query_packet *tt_request;
1108         struct neigh_node *neigh_node = NULL;
1109         struct hard_iface *primary_if;
1110         struct tt_req_node *tt_req_node = NULL;
1111         int ret = 1;
1112
1113         primary_if = primary_if_get_selected(bat_priv);
1114         if (!primary_if)
1115                 goto out;
1116
1117         /* The new tt_req will be issued only if I'm not waiting for a
1118          * reply from the same orig_node yet */
1119         tt_req_node = new_tt_req_node(bat_priv, dst_orig_node);
1120         if (!tt_req_node)
1121                 goto out;
1122
1123         skb = dev_alloc_skb(sizeof(struct tt_query_packet) + ETH_HLEN);
1124         if (!skb)
1125                 goto out;
1126
1127         skb_reserve(skb, ETH_HLEN);
1128
1129         tt_request = (struct tt_query_packet *)skb_put(skb,
1130                                 sizeof(struct tt_query_packet));
1131
1132         tt_request->packet_type = BAT_TT_QUERY;
1133         tt_request->version = COMPAT_VERSION;
1134         memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN);
1135         memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN);
1136         tt_request->ttl = TTL;
1137         tt_request->ttvn = ttvn;
1138         tt_request->tt_data = tt_crc;
1139         tt_request->flags = TT_REQUEST;
1140
1141         if (full_table)
1142                 tt_request->flags |= TT_FULL_TABLE;
1143
1144         neigh_node = orig_node_get_router(dst_orig_node);
1145         if (!neigh_node)
1146                 goto out;
1147
1148         bat_dbg(DBG_TT, bat_priv, "Sending TT_REQUEST to %pM via %pM "
1149                 "[%c]\n", dst_orig_node->orig, neigh_node->addr,
1150                 (full_table ? 'F' : '.'));
1151
1152         send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1153         ret = 0;
1154
1155 out:
1156         if (neigh_node)
1157                 neigh_node_free_ref(neigh_node);
1158         if (primary_if)
1159                 hardif_free_ref(primary_if);
1160         if (ret)
1161                 kfree_skb(skb);
1162         if (ret && tt_req_node) {
1163                 spin_lock_bh(&bat_priv->tt_req_list_lock);
1164                 list_del(&tt_req_node->list);
1165                 spin_unlock_bh(&bat_priv->tt_req_list_lock);
1166                 kfree(tt_req_node);
1167         }
1168         return ret;
1169 }
1170
1171 static bool send_other_tt_response(struct bat_priv *bat_priv,
1172                                    struct tt_query_packet *tt_request)
1173 {
1174         struct orig_node *req_dst_orig_node = NULL, *res_dst_orig_node = NULL;
1175         struct neigh_node *neigh_node = NULL;
1176         struct hard_iface *primary_if = NULL;
1177         uint8_t orig_ttvn, req_ttvn, ttvn;
1178         int ret = false;
1179         unsigned char *tt_buff;
1180         bool full_table;
1181         uint16_t tt_len, tt_tot;
1182         struct sk_buff *skb = NULL;
1183         struct tt_query_packet *tt_response;
1184
1185         bat_dbg(DBG_TT, bat_priv,
1186                 "Received TT_REQUEST from %pM for "
1187                 "ttvn: %u (%pM) [%c]\n", tt_request->src,
1188                 tt_request->ttvn, tt_request->dst,
1189                 (tt_request->flags & TT_FULL_TABLE ? 'F' : '.'));
1190
1191         /* Let's get the orig node of the REAL destination */
1192         req_dst_orig_node = get_orig_node(bat_priv, tt_request->dst);
1193         if (!req_dst_orig_node)
1194                 goto out;
1195
1196         res_dst_orig_node = get_orig_node(bat_priv, tt_request->src);
1197         if (!res_dst_orig_node)
1198                 goto out;
1199
1200         neigh_node = orig_node_get_router(res_dst_orig_node);
1201         if (!neigh_node)
1202                 goto out;
1203
1204         primary_if = primary_if_get_selected(bat_priv);
1205         if (!primary_if)
1206                 goto out;
1207
1208         orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1209         req_ttvn = tt_request->ttvn;
1210
1211         /* I don't have the requested data */
1212         if (orig_ttvn != req_ttvn ||
1213             tt_request->tt_data != req_dst_orig_node->tt_crc)
1214                 goto out;
1215
1216         /* If the full table has been explicitly requested */
1217         if (tt_request->flags & TT_FULL_TABLE ||
1218             !req_dst_orig_node->tt_buff)
1219                 full_table = true;
1220         else
1221                 full_table = false;
1222
1223         /* In this version, fragmentation is not implemented, then
1224          * I'll send only one packet with as much TT entries as I can */
1225         if (!full_table) {
1226                 spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
1227                 tt_len = req_dst_orig_node->tt_buff_len;
1228                 tt_tot = tt_len / sizeof(struct tt_change);
1229
1230                 skb = dev_alloc_skb(sizeof(struct tt_query_packet) +
1231                                     tt_len + ETH_HLEN);
1232                 if (!skb)
1233                         goto unlock;
1234
1235                 skb_reserve(skb, ETH_HLEN);
1236                 tt_response = (struct tt_query_packet *)skb_put(skb,
1237                                 sizeof(struct tt_query_packet) + tt_len);
1238                 tt_response->ttvn = req_ttvn;
1239                 tt_response->tt_data = htons(tt_tot);
1240
1241                 tt_buff = skb->data + sizeof(struct tt_query_packet);
1242                 /* Copy the last orig_node's OGM buffer */
1243                 memcpy(tt_buff, req_dst_orig_node->tt_buff,
1244                        req_dst_orig_node->tt_buff_len);
1245
1246                 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
1247         } else {
1248                 tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size) *
1249                                                 sizeof(struct tt_change);
1250                 ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1251
1252                 skb = tt_response_fill_table(tt_len, ttvn,
1253                                              bat_priv->tt_global_hash,
1254                                              primary_if, tt_global_valid_entry,
1255                                              req_dst_orig_node);
1256                 if (!skb)
1257                         goto out;
1258
1259                 tt_response = (struct tt_query_packet *)skb->data;
1260         }
1261
1262         tt_response->packet_type = BAT_TT_QUERY;
1263         tt_response->version = COMPAT_VERSION;
1264         tt_response->ttl = TTL;
1265         memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN);
1266         memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1267         tt_response->flags = TT_RESPONSE;
1268
1269         if (full_table)
1270                 tt_response->flags |= TT_FULL_TABLE;
1271
1272         bat_dbg(DBG_TT, bat_priv,
1273                 "Sending TT_RESPONSE %pM via %pM for %pM (ttvn: %u)\n",
1274                 res_dst_orig_node->orig, neigh_node->addr,
1275                 req_dst_orig_node->orig, req_ttvn);
1276
1277         send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1278         ret = true;
1279         goto out;
1280
1281 unlock:
1282         spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
1283
1284 out:
1285         if (res_dst_orig_node)
1286                 orig_node_free_ref(res_dst_orig_node);
1287         if (req_dst_orig_node)
1288                 orig_node_free_ref(req_dst_orig_node);
1289         if (neigh_node)
1290                 neigh_node_free_ref(neigh_node);
1291         if (primary_if)
1292                 hardif_free_ref(primary_if);
1293         if (!ret)
1294                 kfree_skb(skb);
1295         return ret;
1296
1297 }
1298 static bool send_my_tt_response(struct bat_priv *bat_priv,
1299                                 struct tt_query_packet *tt_request)
1300 {
1301         struct orig_node *orig_node = NULL;
1302         struct neigh_node *neigh_node = NULL;
1303         struct hard_iface *primary_if = NULL;
1304         uint8_t my_ttvn, req_ttvn, ttvn;
1305         int ret = false;
1306         unsigned char *tt_buff;
1307         bool full_table;
1308         uint16_t tt_len, tt_tot;
1309         struct sk_buff *skb = NULL;
1310         struct tt_query_packet *tt_response;
1311
1312         bat_dbg(DBG_TT, bat_priv,
1313                 "Received TT_REQUEST from %pM for "
1314                 "ttvn: %u (me) [%c]\n", tt_request->src,
1315                 tt_request->ttvn,
1316                 (tt_request->flags & TT_FULL_TABLE ? 'F' : '.'));
1317
1318
1319         my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
1320         req_ttvn = tt_request->ttvn;
1321
1322         orig_node = get_orig_node(bat_priv, tt_request->src);
1323         if (!orig_node)
1324                 goto out;
1325
1326         neigh_node = orig_node_get_router(orig_node);
1327         if (!neigh_node)
1328                 goto out;
1329
1330         primary_if = primary_if_get_selected(bat_priv);
1331         if (!primary_if)
1332                 goto out;
1333
1334         /* If the full table has been explicitly requested or the gap
1335          * is too big send the whole local translation table */
1336         if (tt_request->flags & TT_FULL_TABLE || my_ttvn != req_ttvn ||
1337             !bat_priv->tt_buff)
1338                 full_table = true;
1339         else
1340                 full_table = false;
1341
1342         /* In this version, fragmentation is not implemented, then
1343          * I'll send only one packet with as much TT entries as I can */
1344         if (!full_table) {
1345                 spin_lock_bh(&bat_priv->tt_buff_lock);
1346                 tt_len = bat_priv->tt_buff_len;
1347                 tt_tot = tt_len / sizeof(struct tt_change);
1348
1349                 skb = dev_alloc_skb(sizeof(struct tt_query_packet) +
1350                                     tt_len + ETH_HLEN);
1351                 if (!skb)
1352                         goto unlock;
1353
1354                 skb_reserve(skb, ETH_HLEN);
1355                 tt_response = (struct tt_query_packet *)skb_put(skb,
1356                                 sizeof(struct tt_query_packet) + tt_len);
1357                 tt_response->ttvn = req_ttvn;
1358                 tt_response->tt_data = htons(tt_tot);
1359
1360                 tt_buff = skb->data + sizeof(struct tt_query_packet);
1361                 memcpy(tt_buff, bat_priv->tt_buff,
1362                        bat_priv->tt_buff_len);
1363                 spin_unlock_bh(&bat_priv->tt_buff_lock);
1364         } else {
1365                 tt_len = (uint16_t)atomic_read(&bat_priv->num_local_tt) *
1366                                                 sizeof(struct tt_change);
1367                 ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
1368
1369                 skb = tt_response_fill_table(tt_len, ttvn,
1370                                              bat_priv->tt_local_hash,
1371                                              primary_if, tt_local_valid_entry,
1372                                              NULL);
1373                 if (!skb)
1374                         goto out;
1375
1376                 tt_response = (struct tt_query_packet *)skb->data;
1377         }
1378
1379         tt_response->packet_type = BAT_TT_QUERY;
1380         tt_response->version = COMPAT_VERSION;
1381         tt_response->ttl = TTL;
1382         memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN);
1383         memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1384         tt_response->flags = TT_RESPONSE;
1385
1386         if (full_table)
1387                 tt_response->flags |= TT_FULL_TABLE;
1388
1389         bat_dbg(DBG_TT, bat_priv,
1390                 "Sending TT_RESPONSE to %pM via %pM [%c]\n",
1391                 orig_node->orig, neigh_node->addr,
1392                 (tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
1393
1394         send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1395         ret = true;
1396         goto out;
1397
1398 unlock:
1399         spin_unlock_bh(&bat_priv->tt_buff_lock);
1400 out:
1401         if (orig_node)
1402                 orig_node_free_ref(orig_node);
1403         if (neigh_node)
1404                 neigh_node_free_ref(neigh_node);
1405         if (primary_if)
1406                 hardif_free_ref(primary_if);
1407         if (!ret)
1408                 kfree_skb(skb);
1409         /* This packet was for me, so it doesn't need to be re-routed */
1410         return true;
1411 }
1412
1413 bool send_tt_response(struct bat_priv *bat_priv,
1414                       struct tt_query_packet *tt_request)
1415 {
1416         if (is_my_mac(tt_request->dst))
1417                 return send_my_tt_response(bat_priv, tt_request);
1418         else
1419                 return send_other_tt_response(bat_priv, tt_request);
1420 }
1421
1422 static void _tt_update_changes(struct bat_priv *bat_priv,
1423                                struct orig_node *orig_node,
1424                                struct tt_change *tt_change,
1425                                uint16_t tt_num_changes, uint8_t ttvn)
1426 {
1427         int i;
1428
1429         for (i = 0; i < tt_num_changes; i++) {
1430                 if ((tt_change + i)->flags & TT_CLIENT_DEL)
1431                         tt_global_del(bat_priv, orig_node,
1432                                       (tt_change + i)->addr,
1433                                       "tt removed by changes",
1434                                       (tt_change + i)->flags & TT_CLIENT_ROAM);
1435                 else
1436                         if (!tt_global_add(bat_priv, orig_node,
1437                                            (tt_change + i)->addr, ttvn, false,
1438                                            (tt_change + i)->flags &
1439                                                         TT_CLIENT_WIFI))
1440                                 /* In case of problem while storing a
1441                                  * global_entry, we stop the updating
1442                                  * procedure without committing the
1443                                  * ttvn change. This will avoid to send
1444                                  * corrupted data on tt_request
1445                                  */
1446                                 return;
1447         }
1448 }
1449
1450 static void tt_fill_gtable(struct bat_priv *bat_priv,
1451                            struct tt_query_packet *tt_response)
1452 {
1453         struct orig_node *orig_node = NULL;
1454
1455         orig_node = orig_hash_find(bat_priv, tt_response->src);
1456         if (!orig_node)
1457                 goto out;
1458
1459         /* Purge the old table first.. */
1460         tt_global_del_orig(bat_priv, orig_node, "Received full table");
1461
1462         _tt_update_changes(bat_priv, orig_node,
1463                            (struct tt_change *)(tt_response + 1),
1464                            tt_response->tt_data, tt_response->ttvn);
1465
1466         spin_lock_bh(&orig_node->tt_buff_lock);
1467         kfree(orig_node->tt_buff);
1468         orig_node->tt_buff_len = 0;
1469         orig_node->tt_buff = NULL;
1470         spin_unlock_bh(&orig_node->tt_buff_lock);
1471
1472         atomic_set(&orig_node->last_ttvn, tt_response->ttvn);
1473
1474 out:
1475         if (orig_node)
1476                 orig_node_free_ref(orig_node);
1477 }
1478
1479 static void tt_update_changes(struct bat_priv *bat_priv,
1480                               struct orig_node *orig_node,
1481                               uint16_t tt_num_changes, uint8_t ttvn,
1482                               struct tt_change *tt_change)
1483 {
1484         _tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes,
1485                            ttvn);
1486
1487         tt_save_orig_buffer(bat_priv, orig_node, (unsigned char *)tt_change,
1488                             tt_num_changes);
1489         atomic_set(&orig_node->last_ttvn, ttvn);
1490 }
1491
1492 bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr)
1493 {
1494         struct tt_local_entry *tt_local_entry = NULL;
1495         bool ret = false;
1496
1497         tt_local_entry = tt_local_hash_find(bat_priv, addr);
1498         if (!tt_local_entry)
1499                 goto out;
1500         /* Check if the client has been logically deleted (but is kept for
1501          * consistency purpose) */
1502         if (tt_local_entry->flags & TT_CLIENT_PENDING)
1503                 goto out;
1504         ret = true;
1505 out:
1506         if (tt_local_entry)
1507                 tt_local_entry_free_ref(tt_local_entry);
1508         return ret;
1509 }
1510
1511 void handle_tt_response(struct bat_priv *bat_priv,
1512                         struct tt_query_packet *tt_response)
1513 {
1514         struct tt_req_node *node, *safe;
1515         struct orig_node *orig_node = NULL;
1516
1517         bat_dbg(DBG_TT, bat_priv, "Received TT_RESPONSE from %pM for "
1518                 "ttvn %d t_size: %d [%c]\n",
1519                 tt_response->src, tt_response->ttvn,
1520                 tt_response->tt_data,
1521                 (tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
1522
1523         orig_node = orig_hash_find(bat_priv, tt_response->src);
1524         if (!orig_node)
1525                 goto out;
1526
1527         if (tt_response->flags & TT_FULL_TABLE)
1528                 tt_fill_gtable(bat_priv, tt_response);
1529         else
1530                 tt_update_changes(bat_priv, orig_node, tt_response->tt_data,
1531                                   tt_response->ttvn,
1532                                   (struct tt_change *)(tt_response + 1));
1533
1534         /* Delete the tt_req_node from pending tt_requests list */
1535         spin_lock_bh(&bat_priv->tt_req_list_lock);
1536         list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) {
1537                 if (!compare_eth(node->addr, tt_response->src))
1538                         continue;
1539                 list_del(&node->list);
1540                 kfree(node);
1541         }
1542         spin_unlock_bh(&bat_priv->tt_req_list_lock);
1543
1544         /* Recalculate the CRC for this orig_node and store it */
1545         orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
1546         /* Roaming phase is over: tables are in sync again. I can
1547          * unset the flag */
1548         orig_node->tt_poss_change = false;
1549 out:
1550         if (orig_node)
1551                 orig_node_free_ref(orig_node);
1552 }
1553
1554 int tt_init(struct bat_priv *bat_priv)
1555 {
1556         if (!tt_local_init(bat_priv))
1557                 return 0;
1558
1559         if (!tt_global_init(bat_priv))
1560                 return 0;
1561
1562         tt_start_timer(bat_priv);
1563
1564         return 1;
1565 }
1566
1567 static void tt_roam_list_free(struct bat_priv *bat_priv)
1568 {
1569         struct tt_roam_node *node, *safe;
1570
1571         spin_lock_bh(&bat_priv->tt_roam_list_lock);
1572
1573         list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
1574                 list_del(&node->list);
1575                 kfree(node);
1576         }
1577
1578         spin_unlock_bh(&bat_priv->tt_roam_list_lock);
1579 }
1580
1581 static void tt_roam_purge(struct bat_priv *bat_priv)
1582 {
1583         struct tt_roam_node *node, *safe;
1584
1585         spin_lock_bh(&bat_priv->tt_roam_list_lock);
1586         list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) {
1587                 if (!is_out_of_time(node->first_time,
1588                                     ROAMING_MAX_TIME * 1000))
1589                         continue;
1590
1591                 list_del(&node->list);
1592                 kfree(node);
1593         }
1594         spin_unlock_bh(&bat_priv->tt_roam_list_lock);
1595 }
1596
1597 /* This function checks whether the client already reached the
1598  * maximum number of possible roaming phases. In this case the ROAMING_ADV
1599  * will not be sent.
1600  *
1601  * returns true if the ROAMING_ADV can be sent, false otherwise */
1602 static bool tt_check_roam_count(struct bat_priv *bat_priv,
1603                                 uint8_t *client)
1604 {
1605         struct tt_roam_node *tt_roam_node;
1606         bool ret = false;
1607
1608         spin_lock_bh(&bat_priv->tt_roam_list_lock);
1609         /* The new tt_req will be issued only if I'm not waiting for a
1610          * reply from the same orig_node yet */
1611         list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) {
1612                 if (!compare_eth(tt_roam_node->addr, client))
1613                         continue;
1614
1615                 if (is_out_of_time(tt_roam_node->first_time,
1616                                    ROAMING_MAX_TIME * 1000))
1617                         continue;
1618
1619                 if (!atomic_dec_not_zero(&tt_roam_node->counter))
1620                         /* Sorry, you roamed too many times! */
1621                         goto unlock;
1622                 ret = true;
1623                 break;
1624         }
1625
1626         if (!ret) {
1627                 tt_roam_node = kmalloc(sizeof(*tt_roam_node), GFP_ATOMIC);
1628                 if (!tt_roam_node)
1629                         goto unlock;
1630
1631                 tt_roam_node->first_time = jiffies;
1632                 atomic_set(&tt_roam_node->counter, ROAMING_MAX_COUNT - 1);
1633                 memcpy(tt_roam_node->addr, client, ETH_ALEN);
1634
1635                 list_add(&tt_roam_node->list, &bat_priv->tt_roam_list);
1636                 ret = true;
1637         }
1638
1639 unlock:
1640         spin_unlock_bh(&bat_priv->tt_roam_list_lock);
1641         return ret;
1642 }
1643
1644 void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
1645                    struct orig_node *orig_node)
1646 {
1647         struct neigh_node *neigh_node = NULL;
1648         struct sk_buff *skb = NULL;
1649         struct roam_adv_packet *roam_adv_packet;
1650         int ret = 1;
1651         struct hard_iface *primary_if;
1652
1653         /* before going on we have to check whether the client has
1654          * already roamed to us too many times */
1655         if (!tt_check_roam_count(bat_priv, client))
1656                 goto out;
1657
1658         skb = dev_alloc_skb(sizeof(struct roam_adv_packet) + ETH_HLEN);
1659         if (!skb)
1660                 goto out;
1661
1662         skb_reserve(skb, ETH_HLEN);
1663
1664         roam_adv_packet = (struct roam_adv_packet *)skb_put(skb,
1665                                         sizeof(struct roam_adv_packet));
1666
1667         roam_adv_packet->packet_type = BAT_ROAM_ADV;
1668         roam_adv_packet->version = COMPAT_VERSION;
1669         roam_adv_packet->ttl = TTL;
1670         primary_if = primary_if_get_selected(bat_priv);
1671         if (!primary_if)
1672                 goto out;
1673         memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
1674         hardif_free_ref(primary_if);
1675         memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
1676         memcpy(roam_adv_packet->client, client, ETH_ALEN);
1677
1678         neigh_node = orig_node_get_router(orig_node);
1679         if (!neigh_node)
1680                 goto out;
1681
1682         bat_dbg(DBG_TT, bat_priv,
1683                 "Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
1684                 orig_node->orig, client, neigh_node->addr);
1685
1686         send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1687         ret = 0;
1688
1689 out:
1690         if (neigh_node)
1691                 neigh_node_free_ref(neigh_node);
1692         if (ret)
1693                 kfree_skb(skb);
1694         return;
1695 }
1696
1697 static void tt_purge(struct work_struct *work)
1698 {
1699         struct delayed_work *delayed_work =
1700                 container_of(work, struct delayed_work, work);
1701         struct bat_priv *bat_priv =
1702                 container_of(delayed_work, struct bat_priv, tt_work);
1703
1704         tt_local_purge(bat_priv);
1705         tt_global_roam_purge(bat_priv);
1706         tt_req_purge(bat_priv);
1707         tt_roam_purge(bat_priv);
1708
1709         tt_start_timer(bat_priv);
1710 }
1711
1712 void tt_free(struct bat_priv *bat_priv)
1713 {
1714         cancel_delayed_work_sync(&bat_priv->tt_work);
1715
1716         tt_local_table_free(bat_priv);
1717         tt_global_table_free(bat_priv);
1718         tt_req_list_free(bat_priv);
1719         tt_changes_list_free(bat_priv);
1720         tt_roam_list_free(bat_priv);
1721
1722         kfree(bat_priv->tt_buff);
1723 }
1724
1725 /* This function will reset the specified flags from all the entries in
1726  * the given hash table and will increment num_local_tt for each involved
1727  * entry */
1728 static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags)
1729 {
1730         int i;
1731         struct hashtable_t *hash = bat_priv->tt_local_hash;
1732         struct hlist_head *head;
1733         struct hlist_node *node;
1734         struct tt_local_entry *tt_local_entry;
1735
1736         if (!hash)
1737                 return;
1738
1739         for (i = 0; i < hash->size; i++) {
1740                 head = &hash->table[i];
1741
1742                 rcu_read_lock();
1743                 hlist_for_each_entry_rcu(tt_local_entry, node,
1744                                          head, hash_entry) {
1745                         if (!(tt_local_entry->flags & flags))
1746                                 continue;
1747                         tt_local_entry->flags &= ~flags;
1748                         atomic_inc(&bat_priv->num_local_tt);
1749                 }
1750                 rcu_read_unlock();
1751         }
1752
1753 }
1754
1755 /* Purge out all the tt local entries marked with TT_CLIENT_PENDING */
1756 static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
1757 {
1758         struct hashtable_t *hash = bat_priv->tt_local_hash;
1759         struct tt_local_entry *tt_local_entry;
1760         struct hlist_node *node, *node_tmp;
1761         struct hlist_head *head;
1762         spinlock_t *list_lock; /* protects write access to the hash lists */
1763         int i;
1764
1765         if (!hash)
1766                 return;
1767
1768         for (i = 0; i < hash->size; i++) {
1769                 head = &hash->table[i];
1770                 list_lock = &hash->list_locks[i];
1771
1772                 spin_lock_bh(list_lock);
1773                 hlist_for_each_entry_safe(tt_local_entry, node, node_tmp,
1774                                           head, hash_entry) {
1775                         if (!(tt_local_entry->flags & TT_CLIENT_PENDING))
1776                                 continue;
1777
1778                         bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry "
1779                                 "(%pM): pending\n", tt_local_entry->addr);
1780
1781                         atomic_dec(&bat_priv->num_local_tt);
1782                         hlist_del_rcu(node);
1783                         tt_local_entry_free_ref(tt_local_entry);
1784                 }
1785                 spin_unlock_bh(list_lock);
1786         }
1787
1788 }
1789
1790 void tt_commit_changes(struct bat_priv *bat_priv)
1791 {
1792         tt_local_reset_flags(bat_priv, TT_CLIENT_NEW);
1793         tt_local_purge_pending_clients(bat_priv);
1794
1795         /* Increment the TTVN only once per OGM interval */
1796         atomic_inc(&bat_priv->ttvn);
1797         bat_priv->tt_poss_change = false;
1798 }
1799
1800 bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
1801 {
1802         struct tt_local_entry *tt_local_entry = NULL;
1803         struct tt_global_entry *tt_global_entry = NULL;
1804         bool ret = true;
1805
1806         if (!atomic_read(&bat_priv->ap_isolation))
1807                 return false;
1808
1809         tt_local_entry = tt_local_hash_find(bat_priv, dst);
1810         if (!tt_local_entry)
1811                 goto out;
1812
1813         tt_global_entry = tt_global_hash_find(bat_priv, src);
1814         if (!tt_global_entry)
1815                 goto out;
1816
1817         if (_is_ap_isolated(tt_local_entry, tt_global_entry))
1818                 goto out;
1819
1820         ret = false;
1821
1822 out:
1823         if (tt_global_entry)
1824                 tt_global_entry_free_ref(tt_global_entry);
1825         if (tt_local_entry)
1826                 tt_local_entry_free_ref(tt_local_entry);
1827         return ret;
1828 }
1829
1830 void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
1831                     const unsigned char *tt_buff, uint8_t tt_num_changes,
1832                     uint8_t ttvn, uint16_t tt_crc)
1833 {
1834         uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
1835         bool full_table = true;
1836
1837         /* the ttvn increased by one -> we can apply the attached changes */
1838         if (ttvn - orig_ttvn == 1) {
1839                 /* the OGM could not contain the changes due to their size or
1840                  * because they have already been sent TT_OGM_APPEND_MAX times.
1841                  * In this case send a tt request */
1842                 if (!tt_num_changes) {
1843                         full_table = false;
1844                         goto request_table;
1845                 }
1846
1847                 tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
1848                                   (struct tt_change *)tt_buff);
1849
1850                 /* Even if we received the precomputed crc with the OGM, we
1851                  * prefer to recompute it to spot any possible inconsistency
1852                  * in the global table */
1853                 orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
1854
1855                 /* The ttvn alone is not enough to guarantee consistency
1856                  * because a single value could represent different states
1857                  * (due to the wrap around). Thus a node has to check whether
1858                  * the resulting table (after applying the changes) is still
1859                  * consistent or not. E.g. a node could disconnect while its
1860                  * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
1861                  * checking the CRC value is mandatory to detect the
1862                  * inconsistency */
1863                 if (orig_node->tt_crc != tt_crc)
1864                         goto request_table;
1865
1866                 /* Roaming phase is over: tables are in sync again. I can
1867                  * unset the flag */
1868                 orig_node->tt_poss_change = false;
1869         } else {
1870                 /* if we missed more than one change or our tables are not
1871                  * in sync anymore -> request fresh tt data */
1872                 if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
1873 request_table:
1874                         bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
1875                                 "Need to retrieve the correct information "
1876                                 "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
1877                                 "%u num_changes: %u)\n", orig_node->orig, ttvn,
1878                                 orig_ttvn, tt_crc, orig_node->tt_crc,
1879                                 tt_num_changes);
1880                         send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
1881                                         full_table);
1882                         return;
1883                 }
1884         }
1885 }