1/* 2 * Copyright (C) 2008-2010 B.A.T.M.A.N. contributors: 3 * 4 * 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 "send.h" 24#include "translation-table.h" 25#include "vis.h" 26#include "soft-interface.h" 27#include "hard-interface.h" 28#include "hash.h" 29 30/* Returns the smallest signed integer in two's complement with the sizeof x */ 31#define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u))) 32 33/* Checks if a sequence number x is a predecessor/successor of y. 34 they handle overflows/underflows and can correctly check for a 35 predecessor/successor unless the variable sequence number has grown by 36 more then 2**(bitwidth(x)-1)-1. 37 This means that for a uint8_t with the maximum value 255, it would think: 38 * when adding nothing - it is neither a predecessor nor a successor 39 * before adding more than 127 to the starting value - it is a predecessor, 40 * when adding 128 - it is neither a predecessor nor a successor, 41 * after adding more than 127 to the starting value - it is a successor */ 42#define seq_before(x, y) ({typeof(x) _dummy = (x - y); \ 43 _dummy > smallest_signed_int(_dummy); }) 44#define seq_after(x, y) seq_before(y, x) 45 46static struct hashtable_t *vis_hash; 47static DEFINE_SPINLOCK(vis_hash_lock); 48static DEFINE_SPINLOCK(recv_list_lock); 49static struct vis_info *my_vis_info; 50static struct list_head send_list; /* always locked with vis_hash_lock */ 51 52static void start_vis_timer(void); 53 54/* free the info */ 55static void free_info(struct kref *ref) 56{ 57 struct vis_info *info = container_of(ref, struct vis_info, refcount); 58 struct recvlist_node *entry, *tmp; 59 unsigned long flags; 60 61 list_del_init(&info->send_list); 62 spin_lock_irqsave(&recv_list_lock, flags); 63 list_for_each_entry_safe(entry, tmp, &info->recv_list, list) { 64 list_del(&entry->list); 65 kfree(entry); 66 } 67 spin_unlock_irqrestore(&recv_list_lock, flags); 68 kfree(info); 69} 70 71/* Compare two vis packets, used by the hashing algorithm */ 72static int vis_info_cmp(void *data1, void *data2) 73{ 74 struct vis_info *d1, *d2; 75 d1 = data1; 76 d2 = data2; 77 return compare_orig(d1->packet.vis_orig, d2->packet.vis_orig); 78} 79 80/* hash function to choose an entry in a hash table of given size */ 81/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ 82static int vis_info_choose(void *data, int size) 83{ 84 struct vis_info *vis_info = data; 85 unsigned char *key; 86 uint32_t hash = 0; 87 size_t i; 88 89 key = vis_info->packet.vis_orig; 90 for (i = 0; i < ETH_ALEN; i++) { 91 hash += key[i]; 92 hash += (hash << 10); 93 hash ^= (hash >> 6); 94 } 95 96 hash += (hash << 3); 97 hash ^= (hash >> 11); 98 hash += (hash << 15); 99 100 return hash % size; 101} 102 103/* insert interface to the list of interfaces of one originator, if it 104 * does not already exist in the list */ 105static void vis_data_insert_interface(const uint8_t *interface, 106 struct hlist_head *if_list, 107 bool primary) 108{ 109 struct if_list_entry *entry; 110 struct hlist_node *pos; 111 112 hlist_for_each_entry(entry, pos, if_list, list) { 113 if (compare_orig(entry->addr, (void *)interface)) 114 return; 115 } 116 117 /* its a new address, add it to the list */ 118 entry = kmalloc(sizeof(*entry), GFP_ATOMIC); 119 if (!entry) 120 return; 121 memcpy(entry->addr, interface, ETH_ALEN); 122 entry->primary = primary; 123 hlist_add_head(&entry->list, if_list); 124} 125 126static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list) 127{ 128 struct if_list_entry *entry; 129 struct hlist_node *pos; 130 char tmp_addr_str[ETH_STR_LEN]; 131 size_t len = 0; 132 133 hlist_for_each_entry(entry, pos, if_list, list) { 134 if (entry->primary) 135 len += sprintf(buff + len, "PRIMARY, "); 136 else { 137 addr_to_string(tmp_addr_str, entry->addr); 138 len += sprintf(buff + len, "SEC %s, ", tmp_addr_str); 139 } 140 } 141 142 return len; 143} 144 145static size_t vis_data_count_prim_sec(struct hlist_head *if_list) 146{ 147 struct if_list_entry *entry; 148 struct hlist_node *pos; 149 size_t count = 0; 150 151 hlist_for_each_entry(entry, pos, if_list, list) { 152 if (entry->primary) 153 count += 9; 154 else 155 count += 23; 156 } 157 158 return count; 159} 160 161/* read an entry */ 162static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, 163 uint8_t *src, bool primary) 164{ 165 char to[18]; 166 167 /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ 168 addr_to_string(to, entry->dest); 169 if (primary && entry->quality == 0) 170 return sprintf(buff, "HNA %s, ", to); 171 else if (compare_orig(entry->src, src)) 172 return sprintf(buff, "TQ %s %d, ", to, entry->quality); 173 174 return 0; 175} 176 177int vis_seq_print_text(struct seq_file *seq, void *offset) 178{ 179 HASHIT(hashit); 180 HASHIT(hashit_count); 181 struct vis_info *info; 182 struct vis_info_entry *entries; 183 struct net_device *net_dev = (struct net_device *)seq->private; 184 struct bat_priv *bat_priv = netdev_priv(net_dev); 185 HLIST_HEAD(vis_if_list); 186 struct if_list_entry *entry; 187 struct hlist_node *pos, *n; 188 int i; 189 char tmp_addr_str[ETH_STR_LEN]; 190 unsigned long flags; 191 int vis_server = atomic_read(&bat_priv->vis_mode); 192 size_t buff_pos, buf_size; 193 char *buff; 194 195 if ((!bat_priv->primary_if) || 196 (vis_server == VIS_TYPE_CLIENT_UPDATE)) 197 return 0; 198 199 buf_size = 1; 200 /* Estimate length */ 201 spin_lock_irqsave(&vis_hash_lock, flags); 202 while (hash_iterate(vis_hash, &hashit_count)) { 203 info = hashit_count.bucket->data; 204 entries = (struct vis_info_entry *) 205 ((char *)info + sizeof(struct vis_info)); 206 207 for (i = 0; i < info->packet.entries; i++) { 208 if (entries[i].quality == 0) 209 continue; 210 vis_data_insert_interface(entries[i].src, &vis_if_list, 211 compare_orig(entries[i].src, 212 info->packet.vis_orig)); 213 } 214 215 hlist_for_each_entry(entry, pos, &vis_if_list, list) { 216 buf_size += 18 + 26 * info->packet.entries; 217 218 /* add primary/secondary records */ 219 if (compare_orig(entry->addr, info->packet.vis_orig)) 220 buf_size += 221 vis_data_count_prim_sec(&vis_if_list); 222 223 buf_size += 1; 224 } 225 226 hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { 227 hlist_del(&entry->list); 228 kfree(entry); 229 } 230 } 231 232 buff = kmalloc(buf_size, GFP_ATOMIC); 233 if (!buff) { 234 spin_unlock_irqrestore(&vis_hash_lock, flags); 235 return -ENOMEM; 236 } 237 buff[0] = '\0'; 238 buff_pos = 0; 239 240 while (hash_iterate(vis_hash, &hashit)) { 241 info = hashit.bucket->data; 242 entries = (struct vis_info_entry *) 243 ((char *)info + sizeof(struct vis_info)); 244 245 for (i = 0; i < info->packet.entries; i++) { 246 if (entries[i].quality == 0) 247 continue; 248 vis_data_insert_interface(entries[i].src, &vis_if_list, 249 compare_orig(entries[i].src, 250 info->packet.vis_orig)); 251 } 252 253 hlist_for_each_entry(entry, pos, &vis_if_list, list) { 254 addr_to_string(tmp_addr_str, entry->addr); 255 buff_pos += sprintf(buff + buff_pos, "%s,", 256 tmp_addr_str); 257 258 for (i = 0; i < info->packet.entries; i++) 259 buff_pos += vis_data_read_entry(buff + buff_pos, 260 &entries[i], 261 entry->addr, 262 entry->primary); 263 264 /* add primary/secondary records */ 265 if (compare_orig(entry->addr, info->packet.vis_orig)) 266 buff_pos += 267 vis_data_read_prim_sec(buff + buff_pos, 268 &vis_if_list); 269 270 buff_pos += sprintf(buff + buff_pos, "\n"); 271 } 272 273 hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { 274 hlist_del(&entry->list); 275 kfree(entry); 276 } 277 } 278 279 spin_unlock_irqrestore(&vis_hash_lock, flags); 280 281 seq_printf(seq, "%s", buff); 282 kfree(buff); 283 284 return 0; 285} 286 287/* add the info packet to the send list, if it was not 288 * already linked in. */ 289static void send_list_add(struct vis_info *info) 290{ 291 if (list_empty(&info->send_list)) { 292 kref_get(&info->refcount); 293 list_add_tail(&info->send_list, &send_list); 294 } 295} 296 297/* delete the info packet from the send list, if it was 298 * linked in. */ 299static void send_list_del(struct vis_info *info) 300{ 301 if (!list_empty(&info->send_list)) { 302 list_del_init(&info->send_list); 303 kref_put(&info->refcount, free_info); 304 } 305} 306 307/* tries to add one entry to the receive list. */ 308static void recv_list_add(struct list_head *recv_list, char *mac) 309{ 310 struct recvlist_node *entry; 311 unsigned long flags; 312 313 entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC); 314 if (!entry) 315 return; 316 317 memcpy(entry->mac, mac, ETH_ALEN); 318 spin_lock_irqsave(&recv_list_lock, flags); 319 list_add_tail(&entry->list, recv_list); 320 spin_unlock_irqrestore(&recv_list_lock, flags); 321} 322 323/* returns 1 if this mac is in the recv_list */ 324static int recv_list_is_in(struct list_head *recv_list, char *mac) 325{ 326 struct recvlist_node *entry; 327 unsigned long flags; 328 329 spin_lock_irqsave(&recv_list_lock, flags); 330 list_for_each_entry(entry, recv_list, list) { 331 if (memcmp(entry->mac, mac, ETH_ALEN) == 0) { 332 spin_unlock_irqrestore(&recv_list_lock, flags); 333 return 1; 334 } 335 } 336 spin_unlock_irqrestore(&recv_list_lock, flags); 337 return 0; 338} 339 340/* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old, 341 * broken.. ). vis hash must be locked outside. is_new is set when the packet 342 * is newer than old entries in the hash. */ 343static struct vis_info *add_packet(struct vis_packet *vis_packet, 344 int vis_info_len, int *is_new, 345 int make_broadcast) 346{ 347 struct vis_info *info, *old_info; 348 struct vis_info search_elem; 349 350 *is_new = 0; 351 /* sanity check */ 352 if (vis_hash == NULL) 353 return NULL; 354 355 /* see if the packet is already in vis_hash */ 356 memcpy(search_elem.packet.vis_orig, vis_packet->vis_orig, ETH_ALEN); 357 old_info = hash_find(vis_hash, &search_elem); 358 359 if (old_info != NULL) { 360 if (!seq_after(ntohl(vis_packet->seqno), 361 ntohl(old_info->packet.seqno))) { 362 if (old_info->packet.seqno == vis_packet->seqno) { 363 recv_list_add(&old_info->recv_list, 364 vis_packet->sender_orig); 365 return old_info; 366 } else { 367 /* newer packet is already in hash. */ 368 return NULL; 369 } 370 } 371 /* remove old entry */ 372 hash_remove(vis_hash, old_info); 373 send_list_del(old_info); 374 kref_put(&old_info->refcount, free_info); 375 } 376 377 info = kmalloc(sizeof(struct vis_info) + vis_info_len, GFP_ATOMIC); 378 if (info == NULL) 379 return NULL; 380 381 kref_init(&info->refcount); 382 INIT_LIST_HEAD(&info->send_list); 383 INIT_LIST_HEAD(&info->recv_list); 384 info->first_seen = jiffies; 385 memcpy(&info->packet, vis_packet, 386 sizeof(struct vis_packet) + vis_info_len); 387 388 /* initialize and add new packet. */ 389 *is_new = 1; 390 391 /* Make it a broadcast packet, if required */ 392 if (make_broadcast) 393 memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN); 394 395 /* repair if entries is longer than packet. */ 396 if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len) 397 info->packet.entries = vis_info_len / 398 sizeof(struct vis_info_entry); 399 400 recv_list_add(&info->recv_list, info->packet.sender_orig); 401 402 /* try to add it */ 403 if (hash_add(vis_hash, info) < 0) { 404 /* did not work (for some reason) */ 405 kref_put(&old_info->refcount, free_info); 406 info = NULL; 407 } 408 409 return info; 410} 411 412/* handle the server sync packet, forward if needed. */ 413void receive_server_sync_packet(struct bat_priv *bat_priv, 414 struct vis_packet *vis_packet, 415 int vis_info_len) 416{ 417 struct vis_info *info; 418 int is_new, make_broadcast; 419 unsigned long flags; 420 int vis_server = atomic_read(&bat_priv->vis_mode); 421 422 make_broadcast = (vis_server == VIS_TYPE_SERVER_SYNC); 423 424 spin_lock_irqsave(&vis_hash_lock, flags); 425 info = add_packet(vis_packet, vis_info_len, &is_new, make_broadcast); 426 if (info == NULL) 427 goto end; 428 429 /* only if we are server ourselves and packet is newer than the one in 430 * hash.*/ 431 if (vis_server == VIS_TYPE_SERVER_SYNC && is_new) 432 send_list_add(info); 433end: 434 spin_unlock_irqrestore(&vis_hash_lock, flags); 435} 436 437/* handle an incoming client update packet and schedule forward if needed. */ 438void receive_client_update_packet(struct bat_priv *bat_priv, 439 struct vis_packet *vis_packet, 440 int vis_info_len) 441{ 442 struct vis_info *info; 443 int is_new; 444 unsigned long flags; 445 int vis_server = atomic_read(&bat_priv->vis_mode); 446 int are_target = 0; 447 448 /* clients shall not broadcast. */ 449 if (is_bcast(vis_packet->target_orig)) 450 return; 451 452 /* Are we the target for this VIS packet? */ 453 if (vis_server == VIS_TYPE_SERVER_SYNC && 454 is_my_mac(vis_packet->target_orig)) 455 are_target = 1; 456 457 spin_lock_irqsave(&vis_hash_lock, flags); 458 info = add_packet(vis_packet, vis_info_len, &is_new, are_target); 459 if (info == NULL) 460 goto end; 461 /* note that outdated packets will be dropped at this point. */ 462 463 464 /* send only if we're the target server or ... */ 465 if (are_target && is_new) { 466 info->packet.vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */ 467 send_list_add(info); 468 469 /* ... we're not the recipient (and thus need to forward). */ 470 } else if (!is_my_mac(info->packet.target_orig)) { 471 send_list_add(info); 472 } 473end: 474 spin_unlock_irqrestore(&vis_hash_lock, flags); 475} 476 477/* Walk the originators and find the VIS server with the best tq. Set the packet 478 * address to its address and return the best_tq. 479 * 480 * Must be called with the originator hash locked */ 481static int find_best_vis_server(struct vis_info *info) 482{ 483 HASHIT(hashit); 484 struct orig_node *orig_node; 485 int best_tq = -1; 486 487 while (hash_iterate(orig_hash, &hashit)) { 488 orig_node = hashit.bucket->data; 489 if ((orig_node != NULL) && 490 (orig_node->router != NULL) && 491 (orig_node->flags & VIS_SERVER) && 492 (orig_node->router->tq_avg > best_tq)) { 493 best_tq = orig_node->router->tq_avg; 494 memcpy(info->packet.target_orig, orig_node->orig, 495 ETH_ALEN); 496 } 497 } 498 return best_tq; 499} 500 501/* Return true if the vis packet is full. */ 502static bool vis_packet_full(struct vis_info *info) 503{ 504 if (info->packet.entries + 1 > 505 (1000 - sizeof(struct vis_info)) / sizeof(struct vis_info_entry)) 506 return true; 507 return false; 508} 509 510/* generates a packet of own vis data, 511 * returns 0 on success, -1 if no packet could be generated */ 512static int generate_vis_packet(struct bat_priv *bat_priv) 513{ 514 HASHIT(hashit_local); 515 HASHIT(hashit_global); 516 struct orig_node *orig_node; 517 struct vis_info *info = (struct vis_info *)my_vis_info; 518 struct vis_info_entry *entry, *entry_array; 519 struct hna_local_entry *hna_local_entry; 520 int best_tq = -1; 521 unsigned long flags; 522 523 info->first_seen = jiffies; 524 info->packet.vis_type = atomic_read(&bat_priv->vis_mode); 525 526 spin_lock_irqsave(&orig_hash_lock, flags); 527 memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN); 528 info->packet.ttl = TTL; 529 info->packet.seqno = htonl(ntohl(info->packet.seqno) + 1); 530 info->packet.entries = 0; 531 532 if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) { 533 best_tq = find_best_vis_server(info); 534 if (best_tq < 0) { 535 spin_unlock_irqrestore(&orig_hash_lock, flags); 536 return -1; 537 } 538 } 539 540 entry_array = (struct vis_info_entry *) 541 ((char *)info + sizeof(struct vis_info)); 542 543 while (hash_iterate(orig_hash, &hashit_global)) { 544 orig_node = hashit_global.bucket->data; 545 if (orig_node->router != NULL 546 && compare_orig(orig_node->router->addr, 547 orig_node->orig) 548 && (orig_node->router->if_incoming->if_status == 549 IF_ACTIVE) 550 && orig_node->router->tq_avg > 0) { 551 552 /* fill one entry into buffer. */ 553 entry = &entry_array[info->packet.entries]; 554 memcpy(entry->src, 555 orig_node->router->if_incoming->net_dev->dev_addr, 556 ETH_ALEN); 557 memcpy(entry->dest, orig_node->orig, ETH_ALEN); 558 entry->quality = orig_node->router->tq_avg; 559 info->packet.entries++; 560 561 if (vis_packet_full(info)) { 562 spin_unlock_irqrestore(&orig_hash_lock, flags); 563 return 0; 564 } 565 } 566 } 567 568 spin_unlock_irqrestore(&orig_hash_lock, flags); 569 570 spin_lock_irqsave(&hna_local_hash_lock, flags); 571 while (hash_iterate(hna_local_hash, &hashit_local)) { 572 hna_local_entry = hashit_local.bucket->data; 573 entry = &entry_array[info->packet.entries]; 574 memset(entry->src, 0, ETH_ALEN); 575 memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); 576 entry->quality = 0; /* 0 means HNA */ 577 info->packet.entries++; 578 579 if (vis_packet_full(info)) { 580 spin_unlock_irqrestore(&hna_local_hash_lock, flags); 581 return 0; 582 } 583 } 584 spin_unlock_irqrestore(&hna_local_hash_lock, flags); 585 return 0; 586} 587 588/* free old vis packets. Must be called with this vis_hash_lock 589 * held */ 590static void purge_vis_packets(void) 591{ 592 HASHIT(hashit); 593 struct vis_info *info; 594 595 while (hash_iterate(vis_hash, &hashit)) { 596 info = hashit.bucket->data; 597 if (info == my_vis_info) /* never purge own data. */ 598 continue; 599 if (time_after(jiffies, 600 info->first_seen + VIS_TIMEOUT * HZ)) { 601 hash_remove_bucket(vis_hash, &hashit); 602 send_list_del(info); 603 kref_put(&info->refcount, free_info); 604 } 605 } 606} 607 608static void broadcast_vis_packet(struct vis_info *info, int packet_length) 609{ 610 HASHIT(hashit); 611 struct orig_node *orig_node; 612 unsigned long flags; 613 struct batman_if *batman_if; 614 uint8_t dstaddr[ETH_ALEN]; 615 616 spin_lock_irqsave(&orig_hash_lock, flags); 617 618 /* send to all routers in range. */ 619 while (hash_iterate(orig_hash, &hashit)) { 620 orig_node = hashit.bucket->data; 621 622 /* if it's a vis server and reachable, send it. */ 623 if ((!orig_node) || (!orig_node->router)) 624 continue; 625 if (!(orig_node->flags & VIS_SERVER)) 626 continue; 627 /* don't send it if we already received the packet from 628 * this node. */ 629 if (recv_list_is_in(&info->recv_list, orig_node->orig)) 630 continue; 631 632 memcpy(info->packet.target_orig, orig_node->orig, ETH_ALEN); 633 batman_if = orig_node->router->if_incoming; 634 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); 635 spin_unlock_irqrestore(&orig_hash_lock, flags); 636 637 send_raw_packet((unsigned char *)&info->packet, 638 packet_length, batman_if, dstaddr); 639 640 spin_lock_irqsave(&orig_hash_lock, flags); 641 642 } 643 spin_unlock_irqrestore(&orig_hash_lock, flags); 644 memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN); 645} 646 647static void unicast_vis_packet(struct vis_info *info, int packet_length) 648{ 649 struct orig_node *orig_node; 650 unsigned long flags; 651 struct batman_if *batman_if; 652 uint8_t dstaddr[ETH_ALEN]; 653 654 spin_lock_irqsave(&orig_hash_lock, flags); 655 orig_node = ((struct orig_node *) 656 hash_find(orig_hash, info->packet.target_orig)); 657 658 if ((!orig_node) || (!orig_node->router)) 659 goto out; 660 661 /* don't lock while sending the packets ... we therefore 662 * copy the required data before sending */ 663 batman_if = orig_node->router->if_incoming; 664 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); 665 spin_unlock_irqrestore(&orig_hash_lock, flags); 666 667 send_raw_packet((unsigned char *)&info->packet, 668 packet_length, batman_if, dstaddr); 669 return; 670 671out: 672 spin_unlock_irqrestore(&orig_hash_lock, flags); 673} 674 675/* only send one vis packet. called from send_vis_packets() */ 676static void send_vis_packet(struct vis_info *info) 677{ 678 int packet_length; 679 680 if (info->packet.ttl < 2) { 681 pr_warning("Error - can't send vis packet: ttl exceeded\n"); 682 return; 683 } 684 685 memcpy(info->packet.sender_orig, main_if_addr, ETH_ALEN); 686 info->packet.ttl--; 687 688 packet_length = sizeof(struct vis_packet) + 689 info->packet.entries * sizeof(struct vis_info_entry); 690 691 if (is_bcast(info->packet.target_orig)) 692 broadcast_vis_packet(info, packet_length); 693 else 694 unicast_vis_packet(info, packet_length); 695 info->packet.ttl++; /* restore TTL */ 696} 697 698/* called from timer; send (and maybe generate) vis packet. */ 699static void send_vis_packets(struct work_struct *work) 700{ 701 struct vis_info *info, *temp; 702 unsigned long flags; 703 struct bat_priv *bat_priv = netdev_priv(soft_device); 704 705 spin_lock_irqsave(&vis_hash_lock, flags); 706 707 purge_vis_packets(); 708 709 if (generate_vis_packet(bat_priv) == 0) { 710 /* schedule if generation was successful */ 711 send_list_add(my_vis_info); 712 } 713 714 list_for_each_entry_safe(info, temp, &send_list, send_list) { 715 716 kref_get(&info->refcount); 717 spin_unlock_irqrestore(&vis_hash_lock, flags); 718 719 send_vis_packet(info); 720 721 spin_lock_irqsave(&vis_hash_lock, flags); 722 send_list_del(info); 723 kref_put(&info->refcount, free_info); 724 } 725 spin_unlock_irqrestore(&vis_hash_lock, flags); 726 start_vis_timer(); 727} 728static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets); 729 730/* init the vis server. this may only be called when if_list is already 731 * initialized (e.g. bat0 is initialized, interfaces have been added) */ 732int vis_init(void) 733{ 734 unsigned long flags; 735 if (vis_hash) 736 return 1; 737 738 spin_lock_irqsave(&vis_hash_lock, flags); 739 740 vis_hash = hash_new(256, vis_info_cmp, vis_info_choose); 741 if (!vis_hash) { 742 pr_err("Can't initialize vis_hash\n"); 743 goto err; 744 } 745 746 my_vis_info = kmalloc(1000, GFP_ATOMIC); 747 if (!my_vis_info) { 748 pr_err("Can't initialize vis packet\n"); 749 goto err; 750 } 751 752 /* prefill the vis info */ 753 my_vis_info->first_seen = jiffies - msecs_to_jiffies(VIS_INTERVAL); 754 INIT_LIST_HEAD(&my_vis_info->recv_list); 755 INIT_LIST_HEAD(&my_vis_info->send_list); 756 kref_init(&my_vis_info->refcount); 757 my_vis_info->packet.version = COMPAT_VERSION; 758 my_vis_info->packet.packet_type = BAT_VIS; 759 my_vis_info->packet.ttl = TTL; 760 my_vis_info->packet.seqno = 0; 761 my_vis_info->packet.entries = 0; 762 763 INIT_LIST_HEAD(&send_list); 764 765 memcpy(my_vis_info->packet.vis_orig, main_if_addr, ETH_ALEN); 766 memcpy(my_vis_info->packet.sender_orig, main_if_addr, ETH_ALEN); 767 768 if (hash_add(vis_hash, my_vis_info) < 0) { 769 pr_err("Can't add own vis packet into hash\n"); 770 /* not in hash, need to remove it manually. */ 771 kref_put(&my_vis_info->refcount, free_info); 772 goto err; 773 } 774 775 spin_unlock_irqrestore(&vis_hash_lock, flags); 776 start_vis_timer(); 777 return 1; 778 779err: 780 spin_unlock_irqrestore(&vis_hash_lock, flags); 781 vis_quit(); 782 return 0; 783} 784 785/* Decrease the reference count on a hash item info */ 786static void free_info_ref(void *data) 787{ 788 struct vis_info *info = data; 789 790 send_list_del(info); 791 kref_put(&info->refcount, free_info); 792} 793 794/* shutdown vis-server */ 795void vis_quit(void) 796{ 797 unsigned long flags; 798 if (!vis_hash) 799 return; 800 801 cancel_delayed_work_sync(&vis_timer_wq); 802 803 spin_lock_irqsave(&vis_hash_lock, flags); 804 /* properly remove, kill timers ... */ 805 hash_delete(vis_hash, free_info_ref); 806 vis_hash = NULL; 807 my_vis_info = NULL; 808 spin_unlock_irqrestore(&vis_hash_lock, flags); 809} 810 811/* schedule packets for (re)transmission */ 812static void start_vis_timer(void) 813{ 814 queue_delayed_work(bat_event_workqueue, &vis_timer_wq, 815 (VIS_INTERVAL * HZ) / 1000); 816} 817