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