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