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