Changeset 1579
- Timestamp:
- 03/04/10 11:28:10 (5 months ago)
- Location:
- trunk/batman-adv-kernelland
- Files:
-
- 2 modified
Legend:
- Unmodified
- Added
- Removed
-
trunk/batman-adv-kernelland/vis.c
r1557 r1579 31 31 struct hashtable_t *vis_hash; 32 32 DEFINE_SPINLOCK(vis_hash_lock); 33 static DEFINE_SPINLOCK(recv_list_lock); 33 34 static struct vis_info *my_vis_info; 34 35 static struct list_head send_list; /* always locked with vis_hash_lock */ … … 37 38 38 39 /* free the info */ 39 static void free_info( void *data)40 { 41 struct vis_info *info = data;40 static void free_info(struct kref *ref) 41 { 42 struct vis_info *info = container_of(ref, struct vis_info, refcount); 42 43 struct recvlist_node *entry, *tmp; 44 unsigned long flags; 43 45 44 46 list_del_init(&info->send_list); 47 spin_lock_irqsave(&recv_list_lock, flags); 45 48 list_for_each_entry_safe(entry, tmp, &info->recv_list, list) { 46 49 list_del(&entry->list); 47 50 kfree(entry); 48 51 } 52 spin_unlock_irqrestore(&recv_list_lock, flags); 49 53 kfree(info); 50 54 } … … 144 148 } 145 149 150 /* add the info packet to the send list, if it was not 151 * already linked in. */ 152 static void send_list_add(struct vis_info *info) 153 { 154 if (list_empty(&info->send_list)) { 155 kref_get(&info->refcount); 156 list_add_tail(&info->send_list, &send_list); 157 } 158 } 159 160 /* delete the info packet from the send list, if it was 161 * linked in. */ 162 static void send_list_del(struct vis_info *info) 163 { 164 if (!list_empty(&info->send_list)) { 165 list_del_init(&info->send_list); 166 kref_put(&info->refcount, free_info); 167 } 168 } 169 146 170 /* tries to add one entry to the receive list. */ 147 171 static void recv_list_add(struct list_head *recv_list, char *mac) 148 172 { 149 173 struct recvlist_node *entry; 174 unsigned long flags; 175 150 176 entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC); 151 177 if (!entry) … … 153 179 154 180 memcpy(entry->mac, mac, ETH_ALEN); 181 spin_lock_irqsave(&recv_list_lock, flags); 155 182 list_add_tail(&entry->list, recv_list); 183 spin_unlock_irqrestore(&recv_list_lock, flags); 156 184 } 157 185 … … 160 188 { 161 189 struct recvlist_node *entry; 162 190 unsigned long flags; 191 192 spin_lock_irqsave(&recv_list_lock, flags); 163 193 list_for_each_entry(entry, recv_list, list) { 164 if (memcmp(entry->mac, mac, ETH_ALEN) == 0) 194 if (memcmp(entry->mac, mac, ETH_ALEN) == 0) { 195 spin_unlock_irqrestore(&recv_list_lock, flags); 165 196 return 1; 166 } 167 197 } 198 } 199 spin_unlock_irqrestore(&recv_list_lock, flags); 168 200 return 0; 169 201 } 170 202 171 203 /* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old, 172 * broken.. ). vis hash must be locked outside. is_new is set when the packet204 * broken.. ). vis hash must be locked outside. is_new is set when the packet 173 205 * is newer than old entries in the hash. */ 174 206 static struct vis_info *add_packet(struct vis_packet *vis_packet, 175 int vis_info_len, int *is_new) 207 int vis_info_len, int *is_new, 208 int make_broadcast) 176 209 { 177 210 struct vis_info *info, *old_info; … … 200 233 /* remove old entry */ 201 234 hash_remove(vis_hash, old_info); 202 free_info(old_info); 235 send_list_del(old_info); 236 kref_put(&old_info->refcount, free_info); 203 237 } 204 238 … … 207 241 return NULL; 208 242 243 kref_init(&info->refcount); 209 244 INIT_LIST_HEAD(&info->send_list); 210 245 INIT_LIST_HEAD(&info->recv_list); … … 216 251 *is_new = 1; 217 252 253 /* Make it a broadcast packet, if required */ 254 if (make_broadcast) 255 memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); 256 218 257 /* repair if entries is longer than packet. */ 219 258 if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len) 220 info->packet.entries = vis_info_len / sizeof(struct vis_info_entry); 259 info->packet.entries = vis_info_len / 260 sizeof(struct vis_info_entry); 221 261 222 262 recv_list_add(&info->recv_list, info->packet.sender_orig); … … 225 265 if (hash_add(vis_hash, info) < 0) { 226 266 /* did not work (for some reason) */ 227 free_info(info);267 kref_put(&old_info->refcount, free_info); 228 268 info = NULL; 229 269 } … … 236 276 { 237 277 struct vis_info *info; 238 int is_new ;278 int is_new, make_broadcast; 239 279 unsigned long flags; 240 280 int vis_server = atomic_read(&vis_mode); 241 281 282 make_broadcast = (vis_server == VIS_TYPE_SERVER_SYNC); 283 242 284 spin_lock_irqsave(&vis_hash_lock, flags); 243 info = add_packet(vis_packet, vis_info_len, &is_new );285 info = add_packet(vis_packet, vis_info_len, &is_new, make_broadcast); 244 286 if (info == NULL) 245 287 goto end; … … 247 289 /* only if we are server ourselves and packet is newer than the one in 248 290 * hash.*/ 249 if (vis_server == VIS_TYPE_SERVER_SYNC && is_new) { 250 memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); 251 if (list_empty(&info->send_list)) 252 list_add_tail(&info->send_list, &send_list); 253 } 291 if (vis_server == VIS_TYPE_SERVER_SYNC && is_new) 292 send_list_add(info); 254 293 end: 255 294 spin_unlock_irqrestore(&vis_hash_lock, flags); … … 264 303 unsigned long flags; 265 304 int vis_server = atomic_read(&vis_mode); 305 int are_target = 0; 266 306 267 307 /* clients shall not broadcast. */ … … 269 309 return; 270 310 311 /* Are we the target for this VIS packet? */ 312 if (vis_server == VIS_TYPE_SERVER_SYNC && 313 is_my_mac(vis_packet->target_orig)) 314 are_target = 1; 315 271 316 spin_lock_irqsave(&vis_hash_lock, flags); 272 info = add_packet(vis_packet, vis_info_len, &is_new );317 info = add_packet(vis_packet, vis_info_len, &is_new, are_target); 273 318 if (info == NULL) 274 319 goto end; … … 277 322 278 323 /* send only if we're the target server or ... */ 279 if (vis_server == VIS_TYPE_SERVER_SYNC && 280 is_my_mac(info->packet.target_orig) && 281 is_new) { 324 if (are_target && is_new) { 282 325 info->packet.vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */ 283 memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); 284 if (list_empty(&info->send_list)) 285 list_add_tail(&info->send_list, &send_list); 326 send_list_add(info); 286 327 287 328 /* ... we're not the recipient (and thus need to forward). */ 288 329 } else if (!is_my_mac(info->packet.target_orig)) { 289 if (list_empty(&info->send_list)) 290 list_add_tail(&info->send_list, &send_list); 330 send_list_add(info); 291 331 } 292 332 end: … … 363 403 orig_node = hashit_global.bucket->data; 364 404 if (orig_node->router != NULL 365 && compare_orig(orig_node->router->addr, orig_node->orig) 405 && compare_orig(orig_node->router->addr, 406 orig_node->orig) 366 407 && orig_node->batman_if 367 408 && (orig_node->batman_if->if_active == IF_ACTIVE) … … 370 411 /* fill one entry into buffer. */ 371 412 entry = &entry_array[info->packet.entries]; 372 memcpy(entry->src, orig_node->batman_if->net_dev->dev_addr, ETH_ALEN); 413 memcpy(entry->src, 414 orig_node->batman_if->net_dev->dev_addr, 415 ETH_ALEN); 373 416 memcpy(entry->dest, orig_node->orig, ETH_ALEN); 374 417 entry->quality = orig_node->router->tq_avg; … … 402 445 } 403 446 447 /* free old vis packets. Must be called with this vis_hash_lock 448 * held */ 404 449 static void purge_vis_packets(void) 405 450 { … … 414 459 info->first_seen + (VIS_TIMEOUT*HZ)/1000)) { 415 460 hash_remove_bucket(vis_hash, &hashit); 416 free_info(info); 461 send_list_del(info); 462 kref_put(&info->refcount, free_info); 417 463 } 418 464 } … … 424 470 struct orig_node *orig_node; 425 471 unsigned long flags; 472 struct batman_if *batman_if; 473 uint8_t dstaddr[ETH_ALEN]; 426 474 427 475 spin_lock_irqsave(&orig_hash_lock, flags); … … 432 480 433 481 /* if it's a vis server and reachable, send it. */ 434 if (orig_node && 435 (orig_node->flags & VIS_SERVER) && 436 orig_node->batman_if && 437 orig_node->router) { 438 439 /* don't send it if we already received the packet from 440 * this node. */ 441 if (recv_list_is_in(&info->recv_list, orig_node->orig)) 442 continue; 443 444 memcpy(info->packet.target_orig, 445 orig_node->orig, ETH_ALEN); 446 447 send_raw_packet((unsigned char *) &info->packet, 448 packet_length, 449 orig_node->batman_if, 450 orig_node->router->addr); 451 } 452 } 482 if ((!orig_node) || (!orig_node->batman_if) || 483 (!orig_node->router)) 484 continue; 485 if (!(orig_node->flags & VIS_SERVER)) 486 continue; 487 /* don't send it if we already received the packet from 488 * this node. */ 489 if (recv_list_is_in(&info->recv_list, orig_node->orig)) 490 continue; 491 492 memcpy(info->packet.target_orig, orig_node->orig, ETH_ALEN); 493 batman_if = orig_node->batman_if; 494 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); 495 spin_unlock_irqrestore(&orig_hash_lock, flags); 496 497 send_raw_packet((unsigned char *)&info->packet, 498 packet_length, batman_if, dstaddr); 499 500 spin_lock_irqsave(&orig_hash_lock, flags); 501 502 } 503 spin_unlock_irqrestore(&orig_hash_lock, flags); 453 504 memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); 454 spin_unlock_irqrestore(&orig_hash_lock, flags);455 505 } 456 506 … … 459 509 struct orig_node *orig_node; 460 510 unsigned long flags; 511 struct batman_if *batman_if; 512 uint8_t dstaddr[ETH_ALEN]; 461 513 462 514 spin_lock_irqsave(&orig_hash_lock, flags); … … 464 516 hash_find(orig_hash, info->packet.target_orig)); 465 517 466 if ((orig_node != NULL) && 467 (orig_node->batman_if != NULL) && 468 (orig_node->router != NULL)) { 469 send_raw_packet((unsigned char *) &info->packet, packet_length, 470 orig_node->batman_if, 471 orig_node->router->addr); 472 } 518 if ((!orig_node) || (!orig_node->batman_if) || (!orig_node->router)) 519 goto out; 520 521 /* don't lock while sending the packets ... we therefore 522 * copy the required data before sending */ 523 batman_if = orig_node->batman_if; 524 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); 525 spin_unlock_irqrestore(&orig_hash_lock, flags); 526 527 send_raw_packet((unsigned char *)&info->packet, 528 packet_length, batman_if, dstaddr); 529 return; 530 531 out: 473 532 spin_unlock_irqrestore(&orig_hash_lock, flags); 474 533 } … … 504 563 505 564 spin_lock_irqsave(&vis_hash_lock, flags); 565 506 566 purge_vis_packets(); 507 567 508 if (generate_vis_packet() == 0) 568 if (generate_vis_packet() == 0) { 509 569 /* schedule if generation was successful */ 510 list_add_tail(&my_vis_info->send_list, &send_list); 570 send_list_add(my_vis_info); 571 } 511 572 512 573 list_for_each_entry_safe(info, temp, &send_list, send_list) { 513 list_del_init(&info->send_list); 574 575 kref_get(&info->refcount); 576 spin_unlock_irqrestore(&vis_hash_lock, flags); 577 514 578 send_vis_packet(info); 579 580 spin_lock_irqsave(&vis_hash_lock, flags); 581 send_list_del(info); 582 kref_put(&info->refcount, free_info); 515 583 } 516 584 spin_unlock_irqrestore(&vis_hash_lock, flags); … … 545 613 INIT_LIST_HEAD(&my_vis_info->recv_list); 546 614 INIT_LIST_HEAD(&my_vis_info->send_list); 615 kref_init(&my_vis_info->refcount); 547 616 my_vis_info->packet.version = COMPAT_VERSION; 548 617 my_vis_info->packet.packet_type = BAT_VIS; … … 558 627 if (hash_add(vis_hash, my_vis_info) < 0) { 559 628 printk(KERN_ERR 560 "batman-adv:Can't add own vis packet into hash\n");561 free_info(my_vis_info); /* not in hash, need to remove it562 * manually. */629 "batman-adv:Can't add own vis packet into hash\n"); 630 /* not in hash, need to remove it manually. */ 631 kref_put(&my_vis_info->refcount, free_info); 563 632 goto err; 564 633 } … … 574 643 } 575 644 645 /* Decrease the reference count on a hash item info */ 646 static void free_info_ref(void *data) 647 { 648 struct vis_info *info = data; 649 650 send_list_del(info); 651 kref_put(&info->refcount, free_info); 652 } 653 576 654 /* shutdown vis-server */ 577 655 void vis_quit(void) … … 585 663 spin_lock_irqsave(&vis_hash_lock, flags); 586 664 /* properly remove, kill timers ... */ 587 hash_delete(vis_hash, free_info );665 hash_delete(vis_hash, free_info_ref); 588 666 vis_hash = NULL; 589 667 my_vis_info = NULL; … … 595 673 { 596 674 queue_delayed_work(bat_event_workqueue, &vis_timer_wq, 597 (atomic_read(&vis_interval) * HZ ) / 1000);598 } 675 (atomic_read(&vis_interval) * HZ) / 1000); 676 } -
trunk/batman-adv-kernelland/vis.h
r1557 r1579 30 30 * from. we should not reply to them. */ 31 31 struct list_head send_list; 32 struct kref refcount; 32 33 /* this packet might be part of the vis send queue. */ 33 34 struct vis_packet packet;
