diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bcast.c | 111 | ||||
-rw-r--r-- | net/tipc/bcast.h | 1 | ||||
-rw-r--r-- | net/tipc/bearer.c | 8 | ||||
-rw-r--r-- | net/tipc/bearer.h | 4 | ||||
-rw-r--r-- | net/tipc/config.h | 1 | ||||
-rw-r--r-- | net/tipc/discover.c | 6 | ||||
-rw-r--r-- | net/tipc/eth_media.c | 32 | ||||
-rw-r--r-- | net/tipc/link.c | 111 | ||||
-rw-r--r-- | net/tipc/link.h | 1 | ||||
-rw-r--r-- | net/tipc/name_distr.c | 35 | ||||
-rw-r--r-- | net/tipc/net.c | 11 | ||||
-rw-r--r-- | net/tipc/node.c | 45 | ||||
-rw-r--r-- | net/tipc/node.h | 10 | ||||
-rw-r--r-- | net/tipc/socket.c | 51 | ||||
-rw-r--r-- | net/tipc/subscr.c | 3 | ||||
-rw-r--r-- | net/tipc/subscr.h | 6 |
16 files changed, 239 insertions, 197 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 759b318b5ffb..28908f54459e 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include "link.h" | 39 | #include "link.h" |
40 | #include "port.h" | 40 | #include "port.h" |
41 | #include "bcast.h" | 41 | #include "bcast.h" |
42 | #include "name_distr.h" | ||
42 | 43 | ||
43 | #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ | 44 | #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ |
44 | 45 | ||
@@ -298,14 +299,9 @@ static void bclink_send_nack(struct tipc_node *n_ptr) | |||
298 | msg_set_bcgap_to(msg, n_ptr->bclink.gap_to); | 299 | msg_set_bcgap_to(msg, n_ptr->bclink.gap_to); |
299 | msg_set_bcast_tag(msg, tipc_own_tag); | 300 | msg_set_bcast_tag(msg, tipc_own_tag); |
300 | 301 | ||
301 | if (tipc_bearer_send(&bcbearer->bearer, buf, NULL)) { | 302 | tipc_bearer_send(&bcbearer->bearer, buf, NULL); |
302 | bcl->stats.sent_nacks++; | 303 | bcl->stats.sent_nacks++; |
303 | buf_discard(buf); | 304 | buf_discard(buf); |
304 | } else { | ||
305 | tipc_bearer_schedule(bcl->b_ptr, bcl); | ||
306 | bcl->proto_msg_queue = buf; | ||
307 | bcl->stats.bearer_congs++; | ||
308 | } | ||
309 | 305 | ||
310 | /* | 306 | /* |
311 | * Ensure we doesn't send another NACK msg to the node | 307 | * Ensure we doesn't send another NACK msg to the node |
@@ -426,20 +422,28 @@ int tipc_bclink_send_msg(struct sk_buff *buf) | |||
426 | void tipc_bclink_recv_pkt(struct sk_buff *buf) | 422 | void tipc_bclink_recv_pkt(struct sk_buff *buf) |
427 | { | 423 | { |
428 | struct tipc_msg *msg = buf_msg(buf); | 424 | struct tipc_msg *msg = buf_msg(buf); |
429 | struct tipc_node *node = tipc_node_find(msg_prevnode(msg)); | 425 | struct tipc_node *node; |
430 | u32 next_in; | 426 | u32 next_in; |
431 | u32 seqno; | 427 | u32 seqno; |
432 | struct sk_buff *deferred; | 428 | struct sk_buff *deferred; |
433 | 429 | ||
434 | if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported || | 430 | /* Screen out unwanted broadcast messages */ |
435 | (msg_mc_netid(msg) != tipc_net_id))) { | 431 | |
436 | buf_discard(buf); | 432 | if (msg_mc_netid(msg) != tipc_net_id) |
437 | return; | 433 | goto exit; |
438 | } | 434 | |
435 | node = tipc_node_find(msg_prevnode(msg)); | ||
436 | if (unlikely(!node)) | ||
437 | goto exit; | ||
438 | |||
439 | tipc_node_lock(node); | ||
440 | if (unlikely(!node->bclink.supported)) | ||
441 | goto unlock; | ||
439 | 442 | ||
440 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { | 443 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { |
444 | if (msg_type(msg) != STATE_MSG) | ||
445 | goto unlock; | ||
441 | if (msg_destnode(msg) == tipc_own_addr) { | 446 | if (msg_destnode(msg) == tipc_own_addr) { |
442 | tipc_node_lock(node); | ||
443 | tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); | 447 | tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); |
444 | tipc_node_unlock(node); | 448 | tipc_node_unlock(node); |
445 | spin_lock_bh(&bc_lock); | 449 | spin_lock_bh(&bc_lock); |
@@ -449,18 +453,18 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) | |||
449 | msg_bcgap_to(msg)); | 453 | msg_bcgap_to(msg)); |
450 | spin_unlock_bh(&bc_lock); | 454 | spin_unlock_bh(&bc_lock); |
451 | } else { | 455 | } else { |
456 | tipc_node_unlock(node); | ||
452 | tipc_bclink_peek_nack(msg_destnode(msg), | 457 | tipc_bclink_peek_nack(msg_destnode(msg), |
453 | msg_bcast_tag(msg), | 458 | msg_bcast_tag(msg), |
454 | msg_bcgap_after(msg), | 459 | msg_bcgap_after(msg), |
455 | msg_bcgap_to(msg)); | 460 | msg_bcgap_to(msg)); |
456 | } | 461 | } |
457 | buf_discard(buf); | 462 | goto exit; |
458 | return; | ||
459 | } | 463 | } |
460 | 464 | ||
461 | tipc_node_lock(node); | 465 | /* Handle in-sequence broadcast message */ |
466 | |||
462 | receive: | 467 | receive: |
463 | deferred = node->bclink.deferred_head; | ||
464 | next_in = mod(node->bclink.last_in + 1); | 468 | next_in = mod(node->bclink.last_in + 1); |
465 | seqno = msg_seqno(msg); | 469 | seqno = msg_seqno(msg); |
466 | 470 | ||
@@ -474,7 +478,10 @@ receive: | |||
474 | } | 478 | } |
475 | if (likely(msg_isdata(msg))) { | 479 | if (likely(msg_isdata(msg))) { |
476 | tipc_node_unlock(node); | 480 | tipc_node_unlock(node); |
477 | tipc_port_recv_mcast(buf, NULL); | 481 | if (likely(msg_mcast(msg))) |
482 | tipc_port_recv_mcast(buf, NULL); | ||
483 | else | ||
484 | buf_discard(buf); | ||
478 | } else if (msg_user(msg) == MSG_BUNDLER) { | 485 | } else if (msg_user(msg) == MSG_BUNDLER) { |
479 | bcl->stats.recv_bundles++; | 486 | bcl->stats.recv_bundles++; |
480 | bcl->stats.recv_bundled += msg_msgcnt(msg); | 487 | bcl->stats.recv_bundled += msg_msgcnt(msg); |
@@ -487,18 +494,22 @@ receive: | |||
487 | bcl->stats.recv_fragmented++; | 494 | bcl->stats.recv_fragmented++; |
488 | tipc_node_unlock(node); | 495 | tipc_node_unlock(node); |
489 | tipc_net_route_msg(buf); | 496 | tipc_net_route_msg(buf); |
497 | } else if (msg_user(msg) == NAME_DISTRIBUTOR) { | ||
498 | tipc_node_unlock(node); | ||
499 | tipc_named_recv(buf); | ||
490 | } else { | 500 | } else { |
491 | tipc_node_unlock(node); | 501 | tipc_node_unlock(node); |
492 | tipc_net_route_msg(buf); | 502 | buf_discard(buf); |
493 | } | 503 | } |
504 | buf = NULL; | ||
505 | tipc_node_lock(node); | ||
506 | deferred = node->bclink.deferred_head; | ||
494 | if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { | 507 | if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { |
495 | tipc_node_lock(node); | ||
496 | buf = deferred; | 508 | buf = deferred; |
497 | msg = buf_msg(buf); | 509 | msg = buf_msg(buf); |
498 | node->bclink.deferred_head = deferred->next; | 510 | node->bclink.deferred_head = deferred->next; |
499 | goto receive; | 511 | goto receive; |
500 | } | 512 | } |
501 | return; | ||
502 | } else if (less(next_in, seqno)) { | 513 | } else if (less(next_in, seqno)) { |
503 | u32 gap_after = node->bclink.gap_after; | 514 | u32 gap_after = node->bclink.gap_after; |
504 | u32 gap_to = node->bclink.gap_to; | 515 | u32 gap_to = node->bclink.gap_to; |
@@ -513,6 +524,7 @@ receive: | |||
513 | else if (less(gap_after, seqno) && less(seqno, gap_to)) | 524 | else if (less(gap_after, seqno) && less(seqno, gap_to)) |
514 | node->bclink.gap_to = seqno; | 525 | node->bclink.gap_to = seqno; |
515 | } | 526 | } |
527 | buf = NULL; | ||
516 | if (bclink_ack_allowed(node->bclink.nack_sync)) { | 528 | if (bclink_ack_allowed(node->bclink.nack_sync)) { |
517 | if (gap_to != gap_after) | 529 | if (gap_to != gap_after) |
518 | bclink_send_nack(node); | 530 | bclink_send_nack(node); |
@@ -520,9 +532,11 @@ receive: | |||
520 | } | 532 | } |
521 | } else { | 533 | } else { |
522 | bcl->stats.duplicates++; | 534 | bcl->stats.duplicates++; |
523 | buf_discard(buf); | ||
524 | } | 535 | } |
536 | unlock: | ||
525 | tipc_node_unlock(node); | 537 | tipc_node_unlock(node); |
538 | exit: | ||
539 | buf_discard(buf); | ||
526 | } | 540 | } |
527 | 541 | ||
528 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) | 542 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) |
@@ -535,10 +549,11 @@ u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) | |||
535 | /** | 549 | /** |
536 | * tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer | 550 | * tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer |
537 | * | 551 | * |
538 | * Send through as many bearers as necessary to reach all nodes | 552 | * Send packet over as many bearers as necessary to reach all nodes |
539 | * that support TIPC multicasting. | 553 | * that have joined the broadcast link. |
540 | * | 554 | * |
541 | * Returns 0 if packet sent successfully, non-zero if not | 555 | * Returns 0 (packet sent successfully) under all circumstances, |
556 | * since the broadcast link's pseudo-bearer never blocks | ||
542 | */ | 557 | */ |
543 | 558 | ||
544 | static int tipc_bcbearer_send(struct sk_buff *buf, | 559 | static int tipc_bcbearer_send(struct sk_buff *buf, |
@@ -547,7 +562,12 @@ static int tipc_bcbearer_send(struct sk_buff *buf, | |||
547 | { | 562 | { |
548 | int bp_index; | 563 | int bp_index; |
549 | 564 | ||
550 | /* Prepare buffer for broadcasting (if first time trying to send it) */ | 565 | /* |
566 | * Prepare broadcast link message for reliable transmission, | ||
567 | * if first time trying to send it; | ||
568 | * preparation is skipped for broadcast link protocol messages | ||
569 | * since they are sent in an unreliable manner and don't need it | ||
570 | */ | ||
551 | 571 | ||
552 | if (likely(!msg_non_seq(buf_msg(buf)))) { | 572 | if (likely(!msg_non_seq(buf_msg(buf)))) { |
553 | struct tipc_msg *msg; | 573 | struct tipc_msg *msg; |
@@ -596,18 +616,12 @@ static int tipc_bcbearer_send(struct sk_buff *buf, | |||
596 | } | 616 | } |
597 | 617 | ||
598 | if (bcbearer->remains_new.count == 0) | 618 | if (bcbearer->remains_new.count == 0) |
599 | return 0; | 619 | break; /* all targets reached */ |
600 | 620 | ||
601 | bcbearer->remains = bcbearer->remains_new; | 621 | bcbearer->remains = bcbearer->remains_new; |
602 | } | 622 | } |
603 | 623 | ||
604 | /* | 624 | return 0; |
605 | * Unable to reach all targets (indicate success, since currently | ||
606 | * there isn't code in place to properly block & unblock the | ||
607 | * pseudo-bearer used by the broadcast link) | ||
608 | */ | ||
609 | |||
610 | return TIPC_OK; | ||
611 | } | 625 | } |
612 | 626 | ||
613 | /** | 627 | /** |
@@ -667,27 +681,6 @@ void tipc_bcbearer_sort(void) | |||
667 | spin_unlock_bh(&bc_lock); | 681 | spin_unlock_bh(&bc_lock); |
668 | } | 682 | } |
669 | 683 | ||
670 | /** | ||
671 | * tipc_bcbearer_push - resolve bearer congestion | ||
672 | * | ||
673 | * Forces bclink to push out any unsent packets, until all packets are gone | ||
674 | * or congestion reoccurs. | ||
675 | * No locks set when function called | ||
676 | */ | ||
677 | |||
678 | void tipc_bcbearer_push(void) | ||
679 | { | ||
680 | struct tipc_bearer *b_ptr; | ||
681 | |||
682 | spin_lock_bh(&bc_lock); | ||
683 | b_ptr = &bcbearer->bearer; | ||
684 | if (b_ptr->blocked) { | ||
685 | b_ptr->blocked = 0; | ||
686 | tipc_bearer_lock_push(b_ptr); | ||
687 | } | ||
688 | spin_unlock_bh(&bc_lock); | ||
689 | } | ||
690 | |||
691 | 684 | ||
692 | int tipc_bclink_stats(char *buf, const u32 buf_size) | 685 | int tipc_bclink_stats(char *buf, const u32 buf_size) |
693 | { | 686 | { |
@@ -764,7 +757,7 @@ int tipc_bclink_init(void) | |||
764 | bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC); | 757 | bcbearer = kzalloc(sizeof(*bcbearer), GFP_ATOMIC); |
765 | bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC); | 758 | bclink = kzalloc(sizeof(*bclink), GFP_ATOMIC); |
766 | if (!bcbearer || !bclink) { | 759 | if (!bcbearer || !bclink) { |
767 | warn("Multicast link creation failed, no memory\n"); | 760 | warn("Broadcast link creation failed, no memory\n"); |
768 | kfree(bcbearer); | 761 | kfree(bcbearer); |
769 | bcbearer = NULL; | 762 | bcbearer = NULL; |
770 | kfree(bclink); | 763 | kfree(bclink); |
@@ -775,7 +768,7 @@ int tipc_bclink_init(void) | |||
775 | INIT_LIST_HEAD(&bcbearer->bearer.cong_links); | 768 | INIT_LIST_HEAD(&bcbearer->bearer.cong_links); |
776 | bcbearer->bearer.media = &bcbearer->media; | 769 | bcbearer->bearer.media = &bcbearer->media; |
777 | bcbearer->media.send_msg = tipc_bcbearer_send; | 770 | bcbearer->media.send_msg = tipc_bcbearer_send; |
778 | sprintf(bcbearer->media.name, "tipc-multicast"); | 771 | sprintf(bcbearer->media.name, "tipc-broadcast"); |
779 | 772 | ||
780 | bcl = &bclink->link; | 773 | bcl = &bclink->link; |
781 | INIT_LIST_HEAD(&bcl->waiting_ports); | 774 | INIT_LIST_HEAD(&bcl->waiting_ports); |
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 500c97f1c859..06740da5ae61 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
@@ -101,6 +101,5 @@ int tipc_bclink_stats(char *stats_buf, const u32 buf_size); | |||
101 | int tipc_bclink_reset_stats(void); | 101 | int tipc_bclink_reset_stats(void); |
102 | int tipc_bclink_set_queue_limits(u32 limit); | 102 | int tipc_bclink_set_queue_limits(u32 limit); |
103 | void tipc_bcbearer_sort(void); | 103 | void tipc_bcbearer_sort(void); |
104 | void tipc_bcbearer_push(void); | ||
105 | 104 | ||
106 | #endif | 105 | #endif |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 85eba9c08ee9..e2202de3d93e 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -385,13 +385,9 @@ static int bearer_push(struct tipc_bearer *b_ptr) | |||
385 | 385 | ||
386 | void tipc_bearer_lock_push(struct tipc_bearer *b_ptr) | 386 | void tipc_bearer_lock_push(struct tipc_bearer *b_ptr) |
387 | { | 387 | { |
388 | int res; | ||
389 | |||
390 | spin_lock_bh(&b_ptr->lock); | 388 | spin_lock_bh(&b_ptr->lock); |
391 | res = bearer_push(b_ptr); | 389 | bearer_push(b_ptr); |
392 | spin_unlock_bh(&b_ptr->lock); | 390 | spin_unlock_bh(&b_ptr->lock); |
393 | if (res) | ||
394 | tipc_bcbearer_push(); | ||
395 | } | 391 | } |
396 | 392 | ||
397 | 393 | ||
@@ -608,6 +604,7 @@ int tipc_block_bearer(const char *name) | |||
608 | info("Blocking bearer <%s>\n", name); | 604 | info("Blocking bearer <%s>\n", name); |
609 | spin_lock_bh(&b_ptr->lock); | 605 | spin_lock_bh(&b_ptr->lock); |
610 | b_ptr->blocked = 1; | 606 | b_ptr->blocked = 1; |
607 | list_splice_init(&b_ptr->cong_links, &b_ptr->links); | ||
611 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 608 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
612 | struct tipc_node *n_ptr = l_ptr->owner; | 609 | struct tipc_node *n_ptr = l_ptr->owner; |
613 | 610 | ||
@@ -635,6 +632,7 @@ static void bearer_disable(struct tipc_bearer *b_ptr) | |||
635 | spin_lock_bh(&b_ptr->lock); | 632 | spin_lock_bh(&b_ptr->lock); |
636 | b_ptr->blocked = 1; | 633 | b_ptr->blocked = 1; |
637 | b_ptr->media->disable_bearer(b_ptr); | 634 | b_ptr->media->disable_bearer(b_ptr); |
635 | list_splice_init(&b_ptr->cong_links, &b_ptr->links); | ||
638 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 636 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
639 | tipc_link_delete(l_ptr); | 637 | tipc_link_delete(l_ptr); |
640 | } | 638 | } |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 5ad70eff1ebf..d696f9e414e3 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
@@ -39,8 +39,8 @@ | |||
39 | 39 | ||
40 | #include "bcast.h" | 40 | #include "bcast.h" |
41 | 41 | ||
42 | #define MAX_BEARERS 8 | 42 | #define MAX_BEARERS 2 |
43 | #define MAX_MEDIA 4 | 43 | #define MAX_MEDIA 2 |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Identifiers of supported TIPC media types | 46 | * Identifiers of supported TIPC media types |
diff --git a/net/tipc/config.h b/net/tipc/config.h index 443159a166fd..80da6ebc2785 100644 --- a/net/tipc/config.h +++ b/net/tipc/config.h | |||
@@ -65,7 +65,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, | |||
65 | const void *req_tlv_area, int req_tlv_space, | 65 | const void *req_tlv_area, int req_tlv_space, |
66 | int headroom); | 66 | int headroom); |
67 | 67 | ||
68 | void tipc_cfg_link_event(u32 addr, char *name, int up); | ||
69 | int tipc_cfg_init(void); | 68 | int tipc_cfg_init(void); |
70 | void tipc_cfg_stop(void); | 69 | void tipc_cfg_stop(void); |
71 | 70 | ||
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 0987933155b9..f2fb96e86ee8 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -159,12 +159,6 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
159 | } | 159 | } |
160 | tipc_node_lock(n_ptr); | 160 | tipc_node_lock(n_ptr); |
161 | 161 | ||
162 | /* Don't talk to neighbor during cleanup after last session */ | ||
163 | if (n_ptr->cleanup_required) { | ||
164 | tipc_node_unlock(n_ptr); | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | link = n_ptr->links[b_ptr->identity]; | 162 | link = n_ptr->links[b_ptr->identity]; |
169 | 163 | ||
170 | /* Create a link endpoint for this bearer, if necessary */ | 164 | /* Create a link endpoint for this bearer, if necessary */ |
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index b69092eb95d8..e728d4ce2a1b 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/eth_media.c: Ethernet bearer support for TIPC | 2 | * net/tipc/eth_media.c: Ethernet bearer support for TIPC |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2007, Ericsson AB | 4 | * Copyright (c) 2001-2007, Ericsson AB |
5 | * Copyright (c) 2005-2007, Wind River Systems | 5 | * Copyright (c) 2005-2008, 2011, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -37,7 +37,7 @@ | |||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "bearer.h" | 38 | #include "bearer.h" |
39 | 39 | ||
40 | #define MAX_ETH_BEARERS 2 | 40 | #define MAX_ETH_BEARERS MAX_BEARERS |
41 | #define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI | 41 | #define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI |
42 | #define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL | 42 | #define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL |
43 | #define ETH_LINK_WINDOW TIPC_DEF_LINK_WIN | 43 | #define ETH_LINK_WINDOW TIPC_DEF_LINK_WIN |
@@ -144,31 +144,27 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) | |||
144 | 144 | ||
145 | /* Find device with specified name */ | 145 | /* Find device with specified name */ |
146 | 146 | ||
147 | read_lock(&dev_base_lock); | ||
147 | for_each_netdev(&init_net, pdev) { | 148 | for_each_netdev(&init_net, pdev) { |
148 | if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) { | 149 | if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) { |
149 | dev = pdev; | 150 | dev = pdev; |
151 | dev_hold(dev); | ||
150 | break; | 152 | break; |
151 | } | 153 | } |
152 | } | 154 | } |
155 | read_unlock(&dev_base_lock); | ||
153 | if (!dev) | 156 | if (!dev) |
154 | return -ENODEV; | 157 | return -ENODEV; |
155 | 158 | ||
156 | /* Find Ethernet bearer for device (or create one) */ | 159 | /* Create Ethernet bearer for device */ |
157 | 160 | ||
158 | while ((eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev)) | 161 | eb_ptr->dev = dev; |
159 | eb_ptr++; | 162 | eb_ptr->tipc_packet_type.type = htons(ETH_P_TIPC); |
160 | if (eb_ptr == stop) | 163 | eb_ptr->tipc_packet_type.dev = dev; |
161 | return -EDQUOT; | 164 | eb_ptr->tipc_packet_type.func = recv_msg; |
162 | if (!eb_ptr->dev) { | 165 | eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; |
163 | eb_ptr->dev = dev; | 166 | INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); |
164 | eb_ptr->tipc_packet_type.type = htons(ETH_P_TIPC); | 167 | dev_add_pack(&eb_ptr->tipc_packet_type); |
165 | eb_ptr->tipc_packet_type.dev = dev; | ||
166 | eb_ptr->tipc_packet_type.func = recv_msg; | ||
167 | eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; | ||
168 | INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); | ||
169 | dev_hold(dev); | ||
170 | dev_add_pack(&eb_ptr->tipc_packet_type); | ||
171 | } | ||
172 | 168 | ||
173 | /* Associate TIPC bearer with Ethernet bearer */ | 169 | /* Associate TIPC bearer with Ethernet bearer */ |
174 | 170 | ||
diff --git a/net/tipc/link.c b/net/tipc/link.c index f89570c54f54..ae98a72da11a 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -332,15 +332,16 @@ struct link *tipc_link_create(struct tipc_node *n_ptr, | |||
332 | 332 | ||
333 | l_ptr->addr = peer; | 333 | l_ptr->addr = peer; |
334 | if_name = strchr(b_ptr->name, ':') + 1; | 334 | if_name = strchr(b_ptr->name, ':') + 1; |
335 | sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:", | 335 | sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:unknown", |
336 | tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), | 336 | tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), |
337 | tipc_node(tipc_own_addr), | 337 | tipc_node(tipc_own_addr), |
338 | if_name, | 338 | if_name, |
339 | tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); | 339 | tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); |
340 | /* note: peer i/f is appended to link name by reset/activate */ | 340 | /* note: peer i/f name is updated by reset/activate message */ |
341 | memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); | 341 | memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); |
342 | l_ptr->owner = n_ptr; | 342 | l_ptr->owner = n_ptr; |
343 | l_ptr->checkpoint = 1; | 343 | l_ptr->checkpoint = 1; |
344 | l_ptr->peer_session = INVALID_SESSION; | ||
344 | l_ptr->b_ptr = b_ptr; | 345 | l_ptr->b_ptr = b_ptr; |
345 | link_set_supervision_props(l_ptr, b_ptr->media->tolerance); | 346 | link_set_supervision_props(l_ptr, b_ptr->media->tolerance); |
346 | l_ptr->state = RESET_UNKNOWN; | 347 | l_ptr->state = RESET_UNKNOWN; |
@@ -536,9 +537,6 @@ void tipc_link_stop(struct link *l_ptr) | |||
536 | l_ptr->proto_msg_queue = NULL; | 537 | l_ptr->proto_msg_queue = NULL; |
537 | } | 538 | } |
538 | 539 | ||
539 | /* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ | ||
540 | #define link_send_event(fcn, l_ptr, up) do { } while (0) | ||
541 | |||
542 | void tipc_link_reset(struct link *l_ptr) | 540 | void tipc_link_reset(struct link *l_ptr) |
543 | { | 541 | { |
544 | struct sk_buff *buf; | 542 | struct sk_buff *buf; |
@@ -596,10 +594,6 @@ void tipc_link_reset(struct link *l_ptr) | |||
596 | l_ptr->fsm_msg_cnt = 0; | 594 | l_ptr->fsm_msg_cnt = 0; |
597 | l_ptr->stale_count = 0; | 595 | l_ptr->stale_count = 0; |
598 | link_reset_statistics(l_ptr); | 596 | link_reset_statistics(l_ptr); |
599 | |||
600 | link_send_event(tipc_cfg_link_event, l_ptr, 0); | ||
601 | if (!in_own_cluster(l_ptr->addr)) | ||
602 | link_send_event(tipc_disc_link_event, l_ptr, 0); | ||
603 | } | 597 | } |
604 | 598 | ||
605 | 599 | ||
@@ -608,9 +602,6 @@ static void link_activate(struct link *l_ptr) | |||
608 | l_ptr->next_in_no = l_ptr->stats.recv_info = 1; | 602 | l_ptr->next_in_no = l_ptr->stats.recv_info = 1; |
609 | tipc_node_link_up(l_ptr->owner, l_ptr); | 603 | tipc_node_link_up(l_ptr->owner, l_ptr); |
610 | tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); | 604 | tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); |
611 | link_send_event(tipc_cfg_link_event, l_ptr, 1); | ||
612 | if (!in_own_cluster(l_ptr->addr)) | ||
613 | link_send_event(tipc_disc_link_event, l_ptr, 1); | ||
614 | } | 605 | } |
615 | 606 | ||
616 | /** | 607 | /** |
@@ -985,6 +976,51 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) | |||
985 | } | 976 | } |
986 | 977 | ||
987 | /* | 978 | /* |
979 | * tipc_link_send_names - send name table entries to new neighbor | ||
980 | * | ||
981 | * Send routine for bulk delivery of name table messages when contact | ||
982 | * with a new neighbor occurs. No link congestion checking is performed | ||
983 | * because name table messages *must* be delivered. The messages must be | ||
984 | * small enough not to require fragmentation. | ||
985 | * Called without any locks held. | ||
986 | */ | ||
987 | |||
988 | void tipc_link_send_names(struct list_head *message_list, u32 dest) | ||
989 | { | ||
990 | struct tipc_node *n_ptr; | ||
991 | struct link *l_ptr; | ||
992 | struct sk_buff *buf; | ||
993 | struct sk_buff *temp_buf; | ||
994 | |||
995 | if (list_empty(message_list)) | ||
996 | return; | ||
997 | |||
998 | read_lock_bh(&tipc_net_lock); | ||
999 | n_ptr = tipc_node_find(dest); | ||
1000 | if (n_ptr) { | ||
1001 | tipc_node_lock(n_ptr); | ||
1002 | l_ptr = n_ptr->active_links[0]; | ||
1003 | if (l_ptr) { | ||
1004 | /* convert circular list to linear list */ | ||
1005 | ((struct sk_buff *)message_list->prev)->next = NULL; | ||
1006 | link_add_chain_to_outqueue(l_ptr, | ||
1007 | (struct sk_buff *)message_list->next, 0); | ||
1008 | tipc_link_push_queue(l_ptr); | ||
1009 | INIT_LIST_HEAD(message_list); | ||
1010 | } | ||
1011 | tipc_node_unlock(n_ptr); | ||
1012 | } | ||
1013 | read_unlock_bh(&tipc_net_lock); | ||
1014 | |||
1015 | /* discard the messages if they couldn't be sent */ | ||
1016 | |||
1017 | list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) { | ||
1018 | list_del((struct list_head *)buf); | ||
1019 | buf_discard(buf); | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | /* | ||
988 | * link_send_buf_fast: Entry for data messages where the | 1024 | * link_send_buf_fast: Entry for data messages where the |
989 | * destination link is known and the header is complete, | 1025 | * destination link is known and the header is complete, |
990 | * inclusive total message length. Very time critical. | 1026 | * inclusive total message length. Very time critical. |
@@ -1031,9 +1067,6 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) | |||
1031 | u32 selector = msg_origport(buf_msg(buf)) & 1; | 1067 | u32 selector = msg_origport(buf_msg(buf)) & 1; |
1032 | u32 dummy; | 1068 | u32 dummy; |
1033 | 1069 | ||
1034 | if (destnode == tipc_own_addr) | ||
1035 | return tipc_port_recv_msg(buf); | ||
1036 | |||
1037 | read_lock_bh(&tipc_net_lock); | 1070 | read_lock_bh(&tipc_net_lock); |
1038 | n_ptr = tipc_node_find(destnode); | 1071 | n_ptr = tipc_node_find(destnode); |
1039 | if (likely(n_ptr)) { | 1072 | if (likely(n_ptr)) { |
@@ -1658,19 +1691,12 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1658 | continue; | 1691 | continue; |
1659 | } | 1692 | } |
1660 | 1693 | ||
1694 | /* Discard unicast link messages destined for another node */ | ||
1695 | |||
1661 | if (unlikely(!msg_short(msg) && | 1696 | if (unlikely(!msg_short(msg) && |
1662 | (msg_destnode(msg) != tipc_own_addr))) | 1697 | (msg_destnode(msg) != tipc_own_addr))) |
1663 | goto cont; | 1698 | goto cont; |
1664 | 1699 | ||
1665 | /* Discard non-routeable messages destined for another node */ | ||
1666 | |||
1667 | if (unlikely(!msg_isdata(msg) && | ||
1668 | (msg_destnode(msg) != tipc_own_addr))) { | ||
1669 | if ((msg_user(msg) != CONN_MANAGER) && | ||
1670 | (msg_user(msg) != MSG_FRAGMENTER)) | ||
1671 | goto cont; | ||
1672 | } | ||
1673 | |||
1674 | /* Locate neighboring node that sent message */ | 1700 | /* Locate neighboring node that sent message */ |
1675 | 1701 | ||
1676 | n_ptr = tipc_node_find(msg_prevnode(msg)); | 1702 | n_ptr = tipc_node_find(msg_prevnode(msg)); |
@@ -1678,17 +1704,24 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1678 | goto cont; | 1704 | goto cont; |
1679 | tipc_node_lock(n_ptr); | 1705 | tipc_node_lock(n_ptr); |
1680 | 1706 | ||
1681 | /* Don't talk to neighbor during cleanup after last session */ | 1707 | /* Locate unicast link endpoint that should handle message */ |
1682 | 1708 | ||
1683 | if (n_ptr->cleanup_required) { | 1709 | l_ptr = n_ptr->links[b_ptr->identity]; |
1710 | if (unlikely(!l_ptr)) { | ||
1684 | tipc_node_unlock(n_ptr); | 1711 | tipc_node_unlock(n_ptr); |
1685 | goto cont; | 1712 | goto cont; |
1686 | } | 1713 | } |
1687 | 1714 | ||
1688 | /* Locate unicast link endpoint that should handle message */ | 1715 | /* Verify that communication with node is currently allowed */ |
1689 | 1716 | ||
1690 | l_ptr = n_ptr->links[b_ptr->identity]; | 1717 | if ((n_ptr->block_setup & WAIT_PEER_DOWN) && |
1691 | if (unlikely(!l_ptr)) { | 1718 | msg_user(msg) == LINK_PROTOCOL && |
1719 | (msg_type(msg) == RESET_MSG || | ||
1720 | msg_type(msg) == ACTIVATE_MSG) && | ||
1721 | !msg_redundant_link(msg)) | ||
1722 | n_ptr->block_setup &= ~WAIT_PEER_DOWN; | ||
1723 | |||
1724 | if (n_ptr->block_setup) { | ||
1692 | tipc_node_unlock(n_ptr); | 1725 | tipc_node_unlock(n_ptr); |
1693 | goto cont; | 1726 | goto cont; |
1694 | } | 1727 | } |
@@ -1923,6 +1956,12 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, | |||
1923 | 1956 | ||
1924 | if (link_blocked(l_ptr)) | 1957 | if (link_blocked(l_ptr)) |
1925 | return; | 1958 | return; |
1959 | |||
1960 | /* Abort non-RESET send if communication with node is prohibited */ | ||
1961 | |||
1962 | if ((l_ptr->owner->block_setup) && (msg_typ != RESET_MSG)) | ||
1963 | return; | ||
1964 | |||
1926 | msg_set_type(msg, msg_typ); | 1965 | msg_set_type(msg, msg_typ); |
1927 | msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); | 1966 | msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); |
1928 | msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); | 1967 | msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); |
@@ -2051,9 +2090,19 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) | |||
2051 | case RESET_MSG: | 2090 | case RESET_MSG: |
2052 | if (!link_working_unknown(l_ptr) && | 2091 | if (!link_working_unknown(l_ptr) && |
2053 | (l_ptr->peer_session != INVALID_SESSION)) { | 2092 | (l_ptr->peer_session != INVALID_SESSION)) { |
2054 | if (msg_session(msg) == l_ptr->peer_session) | 2093 | if (less_eq(msg_session(msg), l_ptr->peer_session)) |
2055 | break; /* duplicate: ignore */ | 2094 | break; /* duplicate or old reset: ignore */ |
2095 | } | ||
2096 | |||
2097 | if (!msg_redundant_link(msg) && (link_working_working(l_ptr) || | ||
2098 | link_working_unknown(l_ptr))) { | ||
2099 | /* | ||
2100 | * peer has lost contact -- don't allow peer's links | ||
2101 | * to reactivate before we recognize loss & clean up | ||
2102 | */ | ||
2103 | l_ptr->owner->block_setup = WAIT_NODE_DOWN; | ||
2056 | } | 2104 | } |
2105 | |||
2057 | /* fall thru' */ | 2106 | /* fall thru' */ |
2058 | case ACTIVATE_MSG: | 2107 | case ACTIVATE_MSG: |
2059 | /* Update link settings according other endpoint's values */ | 2108 | /* Update link settings according other endpoint's values */ |
diff --git a/net/tipc/link.h b/net/tipc/link.h index 74fbecab1ea0..e56cb532913e 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -223,6 +223,7 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_s | |||
223 | struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space); | 223 | struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space); |
224 | void tipc_link_reset(struct link *l_ptr); | 224 | void tipc_link_reset(struct link *l_ptr); |
225 | int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector); | 225 | int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector); |
226 | void tipc_link_send_names(struct list_head *message_list, u32 dest); | ||
226 | int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf); | 227 | int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf); |
227 | u32 tipc_link_get_max_pkt(u32 dest, u32 selector); | 228 | u32 tipc_link_get_max_pkt(u32 dest, u32 selector); |
228 | int tipc_link_send_sections_fast(struct tipc_port *sender, | 229 | int tipc_link_send_sections_fast(struct tipc_port *sender, |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index cd356e504332..b7ca1bd7b151 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -173,18 +173,40 @@ void tipc_named_withdraw(struct publication *publ) | |||
173 | * tipc_named_node_up - tell specified node about all publications by this node | 173 | * tipc_named_node_up - tell specified node about all publications by this node |
174 | */ | 174 | */ |
175 | 175 | ||
176 | void tipc_named_node_up(unsigned long node) | 176 | void tipc_named_node_up(unsigned long nodearg) |
177 | { | 177 | { |
178 | struct tipc_node *n_ptr; | ||
179 | struct link *l_ptr; | ||
178 | struct publication *publ; | 180 | struct publication *publ; |
179 | struct distr_item *item = NULL; | 181 | struct distr_item *item = NULL; |
180 | struct sk_buff *buf = NULL; | 182 | struct sk_buff *buf = NULL; |
183 | struct list_head message_list; | ||
184 | u32 node = (u32)nodearg; | ||
181 | u32 left = 0; | 185 | u32 left = 0; |
182 | u32 rest; | 186 | u32 rest; |
183 | u32 max_item_buf; | 187 | u32 max_item_buf = 0; |
188 | |||
189 | /* compute maximum amount of publication data to send per message */ | ||
190 | |||
191 | read_lock_bh(&tipc_net_lock); | ||
192 | n_ptr = tipc_node_find(node); | ||
193 | if (n_ptr) { | ||
194 | tipc_node_lock(n_ptr); | ||
195 | l_ptr = n_ptr->active_links[0]; | ||
196 | if (l_ptr) | ||
197 | max_item_buf = ((l_ptr->max_pkt - INT_H_SIZE) / | ||
198 | ITEM_SIZE) * ITEM_SIZE; | ||
199 | tipc_node_unlock(n_ptr); | ||
200 | } | ||
201 | read_unlock_bh(&tipc_net_lock); | ||
202 | if (!max_item_buf) | ||
203 | return; | ||
204 | |||
205 | /* create list of publication messages, then send them as a unit */ | ||
206 | |||
207 | INIT_LIST_HEAD(&message_list); | ||
184 | 208 | ||
185 | read_lock_bh(&tipc_nametbl_lock); | 209 | read_lock_bh(&tipc_nametbl_lock); |
186 | max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE; | ||
187 | max_item_buf *= ITEM_SIZE; | ||
188 | rest = publ_cnt * ITEM_SIZE; | 210 | rest = publ_cnt * ITEM_SIZE; |
189 | 211 | ||
190 | list_for_each_entry(publ, &publ_root, local_list) { | 212 | list_for_each_entry(publ, &publ_root, local_list) { |
@@ -202,13 +224,14 @@ void tipc_named_node_up(unsigned long node) | |||
202 | item++; | 224 | item++; |
203 | left -= ITEM_SIZE; | 225 | left -= ITEM_SIZE; |
204 | if (!left) { | 226 | if (!left) { |
205 | msg_set_link_selector(buf_msg(buf), node); | 227 | list_add_tail((struct list_head *)buf, &message_list); |
206 | tipc_link_send(buf, node, node); | ||
207 | buf = NULL; | 228 | buf = NULL; |
208 | } | 229 | } |
209 | } | 230 | } |
210 | exit: | 231 | exit: |
211 | read_unlock_bh(&tipc_nametbl_lock); | 232 | read_unlock_bh(&tipc_nametbl_lock); |
233 | |||
234 | tipc_link_send_names(&message_list, (u32)node); | ||
212 | } | 235 | } |
213 | 236 | ||
214 | /** | 237 | /** |
diff --git a/net/tipc/net.c b/net/tipc/net.c index 68b3dd637291..fafef6c3c0f6 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -141,17 +141,6 @@ void tipc_net_route_msg(struct sk_buff *buf) | |||
141 | return; | 141 | return; |
142 | msg = buf_msg(buf); | 142 | msg = buf_msg(buf); |
143 | 143 | ||
144 | msg_incr_reroute_cnt(msg); | ||
145 | if (msg_reroute_cnt(msg) > 6) { | ||
146 | if (msg_errcode(msg)) { | ||
147 | buf_discard(buf); | ||
148 | } else { | ||
149 | tipc_reject_msg(buf, msg_destport(msg) ? | ||
150 | TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME); | ||
151 | } | ||
152 | return; | ||
153 | } | ||
154 | |||
155 | /* Handle message for this node */ | 144 | /* Handle message for this node */ |
156 | dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); | 145 | dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); |
157 | if (tipc_in_scope(dnode, tipc_own_addr)) { | 146 | if (tipc_in_scope(dnode, tipc_own_addr)) { |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 2d106ef4fa4c..27b4bb0cca6c 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -112,6 +112,7 @@ struct tipc_node *tipc_node_create(u32 addr) | |||
112 | break; | 112 | break; |
113 | } | 113 | } |
114 | list_add_tail(&n_ptr->list, &temp_node->list); | 114 | list_add_tail(&n_ptr->list, &temp_node->list); |
115 | n_ptr->block_setup = WAIT_PEER_DOWN; | ||
115 | 116 | ||
116 | tipc_num_nodes++; | 117 | tipc_num_nodes++; |
117 | 118 | ||
@@ -312,7 +313,7 @@ static void node_established_contact(struct tipc_node *n_ptr) | |||
312 | } | 313 | } |
313 | } | 314 | } |
314 | 315 | ||
315 | static void node_cleanup_finished(unsigned long node_addr) | 316 | static void node_name_purge_complete(unsigned long node_addr) |
316 | { | 317 | { |
317 | struct tipc_node *n_ptr; | 318 | struct tipc_node *n_ptr; |
318 | 319 | ||
@@ -320,7 +321,7 @@ static void node_cleanup_finished(unsigned long node_addr) | |||
320 | n_ptr = tipc_node_find(node_addr); | 321 | n_ptr = tipc_node_find(node_addr); |
321 | if (n_ptr) { | 322 | if (n_ptr) { |
322 | tipc_node_lock(n_ptr); | 323 | tipc_node_lock(n_ptr); |
323 | n_ptr->cleanup_required = 0; | 324 | n_ptr->block_setup &= ~WAIT_NAMES_GONE; |
324 | tipc_node_unlock(n_ptr); | 325 | tipc_node_unlock(n_ptr); |
325 | } | 326 | } |
326 | read_unlock_bh(&tipc_net_lock); | 327 | read_unlock_bh(&tipc_net_lock); |
@@ -331,28 +332,32 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
331 | char addr_string[16]; | 332 | char addr_string[16]; |
332 | u32 i; | 333 | u32 i; |
333 | 334 | ||
334 | /* Clean up broadcast reception remains */ | 335 | info("Lost contact with %s\n", |
335 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; | 336 | tipc_addr_string_fill(addr_string, n_ptr->addr)); |
336 | while (n_ptr->bclink.deferred_head) { | 337 | |
337 | struct sk_buff *buf = n_ptr->bclink.deferred_head; | 338 | /* Flush broadcast link info associated with lost node */ |
338 | n_ptr->bclink.deferred_head = buf->next; | ||
339 | buf_discard(buf); | ||
340 | } | ||
341 | if (n_ptr->bclink.defragm) { | ||
342 | buf_discard(n_ptr->bclink.defragm); | ||
343 | n_ptr->bclink.defragm = NULL; | ||
344 | } | ||
345 | 339 | ||
346 | if (n_ptr->bclink.supported) { | 340 | if (n_ptr->bclink.supported) { |
341 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; | ||
342 | while (n_ptr->bclink.deferred_head) { | ||
343 | struct sk_buff *buf = n_ptr->bclink.deferred_head; | ||
344 | n_ptr->bclink.deferred_head = buf->next; | ||
345 | buf_discard(buf); | ||
346 | } | ||
347 | |||
348 | if (n_ptr->bclink.defragm) { | ||
349 | buf_discard(n_ptr->bclink.defragm); | ||
350 | n_ptr->bclink.defragm = NULL; | ||
351 | } | ||
352 | |||
353 | tipc_nmap_remove(&tipc_bcast_nmap, n_ptr->addr); | ||
347 | tipc_bclink_acknowledge(n_ptr, | 354 | tipc_bclink_acknowledge(n_ptr, |
348 | mod(n_ptr->bclink.acked + 10000)); | 355 | mod(n_ptr->bclink.acked + 10000)); |
349 | tipc_nmap_remove(&tipc_bcast_nmap, n_ptr->addr); | ||
350 | if (n_ptr->addr < tipc_own_addr) | 356 | if (n_ptr->addr < tipc_own_addr) |
351 | tipc_own_tag--; | 357 | tipc_own_tag--; |
352 | } | ||
353 | 358 | ||
354 | info("Lost contact with %s\n", | 359 | n_ptr->bclink.supported = 0; |
355 | tipc_addr_string_fill(addr_string, n_ptr->addr)); | 360 | } |
356 | 361 | ||
357 | /* Abort link changeover */ | 362 | /* Abort link changeover */ |
358 | for (i = 0; i < MAX_BEARERS; i++) { | 363 | for (i = 0; i < MAX_BEARERS; i++) { |
@@ -367,10 +372,10 @@ static void node_lost_contact(struct tipc_node *n_ptr) | |||
367 | /* Notify subscribers */ | 372 | /* Notify subscribers */ |
368 | tipc_nodesub_notify(n_ptr); | 373 | tipc_nodesub_notify(n_ptr); |
369 | 374 | ||
370 | /* Prevent re-contact with node until all cleanup is done */ | 375 | /* Prevent re-contact with node until cleanup is done */ |
371 | 376 | ||
372 | n_ptr->cleanup_required = 1; | 377 | n_ptr->block_setup = WAIT_PEER_DOWN | WAIT_NAMES_GONE; |
373 | tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); | 378 | tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr); |
374 | } | 379 | } |
375 | 380 | ||
376 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | 381 | struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 5c61afc7a0b9..4f15cb40aaa4 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -42,6 +42,12 @@ | |||
42 | #include "net.h" | 42 | #include "net.h" |
43 | #include "bearer.h" | 43 | #include "bearer.h" |
44 | 44 | ||
45 | /* Flags used to block (re)establishment of contact with a neighboring node */ | ||
46 | |||
47 | #define WAIT_PEER_DOWN 0x0001 /* wait to see that peer's links are down */ | ||
48 | #define WAIT_NAMES_GONE 0x0002 /* wait for peer's publications to be purged */ | ||
49 | #define WAIT_NODE_DOWN 0x0004 /* wait until peer node is declared down */ | ||
50 | |||
45 | /** | 51 | /** |
46 | * struct tipc_node - TIPC node structure | 52 | * struct tipc_node - TIPC node structure |
47 | * @addr: network address of node | 53 | * @addr: network address of node |
@@ -52,7 +58,7 @@ | |||
52 | * @active_links: pointers to active links to node | 58 | * @active_links: pointers to active links to node |
53 | * @links: pointers to all links to node | 59 | * @links: pointers to all links to node |
54 | * @working_links: number of working links to node (both active and standby) | 60 | * @working_links: number of working links to node (both active and standby) |
55 | * @cleanup_required: non-zero if cleaning up after a prior loss of contact | 61 | * @block_setup: bit mask of conditions preventing link establishment to node |
56 | * @link_cnt: number of links to node | 62 | * @link_cnt: number of links to node |
57 | * @permit_changeover: non-zero if node has redundant links to this system | 63 | * @permit_changeover: non-zero if node has redundant links to this system |
58 | * @bclink: broadcast-related info | 64 | * @bclink: broadcast-related info |
@@ -77,7 +83,7 @@ struct tipc_node { | |||
77 | struct link *links[MAX_BEARERS]; | 83 | struct link *links[MAX_BEARERS]; |
78 | int link_cnt; | 84 | int link_cnt; |
79 | int working_links; | 85 | int working_links; |
80 | int cleanup_required; | 86 | int block_setup; |
81 | int permit_changeover; | 87 | int permit_changeover; |
82 | struct { | 88 | struct { |
83 | int supported; | 89 | int supported; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index adb2eff4a102..9440a3d48ca0 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -49,7 +49,7 @@ struct tipc_sock { | |||
49 | struct sock sk; | 49 | struct sock sk; |
50 | struct tipc_port *p; | 50 | struct tipc_port *p; |
51 | struct tipc_portid peer_name; | 51 | struct tipc_portid peer_name; |
52 | long conn_timeout; | 52 | unsigned int conn_timeout; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | #define tipc_sk(sk) ((struct tipc_sock *)(sk)) | 55 | #define tipc_sk(sk) ((struct tipc_sock *)(sk)) |
@@ -231,7 +231,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol, | |||
231 | sock_init_data(sock, sk); | 231 | sock_init_data(sock, sk); |
232 | sk->sk_backlog_rcv = backlog_rcv; | 232 | sk->sk_backlog_rcv = backlog_rcv; |
233 | tipc_sk(sk)->p = tp_ptr; | 233 | tipc_sk(sk)->p = tp_ptr; |
234 | tipc_sk(sk)->conn_timeout = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT); | 234 | tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT; |
235 | 235 | ||
236 | spin_unlock_bh(tp_ptr->lock); | 236 | spin_unlock_bh(tp_ptr->lock); |
237 | 237 | ||
@@ -525,6 +525,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
525 | struct tipc_port *tport = tipc_sk_port(sk); | 525 | struct tipc_port *tport = tipc_sk_port(sk); |
526 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 526 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; |
527 | int needs_conn; | 527 | int needs_conn; |
528 | long timeout_val; | ||
528 | int res = -EINVAL; | 529 | int res = -EINVAL; |
529 | 530 | ||
530 | if (unlikely(!dest)) | 531 | if (unlikely(!dest)) |
@@ -564,6 +565,8 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
564 | reject_rx_queue(sk); | 565 | reject_rx_queue(sk); |
565 | } | 566 | } |
566 | 567 | ||
568 | timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | ||
569 | |||
567 | do { | 570 | do { |
568 | if (dest->addrtype == TIPC_ADDR_NAME) { | 571 | if (dest->addrtype == TIPC_ADDR_NAME) { |
569 | res = dest_name_check(dest, m); | 572 | res = dest_name_check(dest, m); |
@@ -600,16 +603,14 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
600 | sock->state = SS_CONNECTING; | 603 | sock->state = SS_CONNECTING; |
601 | break; | 604 | break; |
602 | } | 605 | } |
603 | if (m->msg_flags & MSG_DONTWAIT) { | 606 | if (timeout_val <= 0L) { |
604 | res = -EWOULDBLOCK; | 607 | res = timeout_val ? timeout_val : -EWOULDBLOCK; |
605 | break; | 608 | break; |
606 | } | 609 | } |
607 | release_sock(sk); | 610 | release_sock(sk); |
608 | res = wait_event_interruptible(*sk_sleep(sk), | 611 | timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), |
609 | !tport->congested); | 612 | !tport->congested, timeout_val); |
610 | lock_sock(sk); | 613 | lock_sock(sk); |
611 | if (res) | ||
612 | break; | ||
613 | } while (1); | 614 | } while (1); |
614 | 615 | ||
615 | exit: | 616 | exit: |
@@ -636,6 +637,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
636 | struct sock *sk = sock->sk; | 637 | struct sock *sk = sock->sk; |
637 | struct tipc_port *tport = tipc_sk_port(sk); | 638 | struct tipc_port *tport = tipc_sk_port(sk); |
638 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | 639 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; |
640 | long timeout_val; | ||
639 | int res; | 641 | int res; |
640 | 642 | ||
641 | /* Handle implied connection establishment */ | 643 | /* Handle implied connection establishment */ |
@@ -650,6 +652,8 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
650 | if (iocb) | 652 | if (iocb) |
651 | lock_sock(sk); | 653 | lock_sock(sk); |
652 | 654 | ||
655 | timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | ||
656 | |||
653 | do { | 657 | do { |
654 | if (unlikely(sock->state != SS_CONNECTED)) { | 658 | if (unlikely(sock->state != SS_CONNECTED)) { |
655 | if (sock->state == SS_DISCONNECTING) | 659 | if (sock->state == SS_DISCONNECTING) |
@@ -663,16 +667,14 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
663 | total_len); | 667 | total_len); |
664 | if (likely(res != -ELINKCONG)) | 668 | if (likely(res != -ELINKCONG)) |
665 | break; | 669 | break; |
666 | if (m->msg_flags & MSG_DONTWAIT) { | 670 | if (timeout_val <= 0L) { |
667 | res = -EWOULDBLOCK; | 671 | res = timeout_val ? timeout_val : -EWOULDBLOCK; |
668 | break; | 672 | break; |
669 | } | 673 | } |
670 | release_sock(sk); | 674 | release_sock(sk); |
671 | res = wait_event_interruptible(*sk_sleep(sk), | 675 | timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk), |
672 | (!tport->congested || !tport->connected)); | 676 | (!tport->congested || !tport->connected), timeout_val); |
673 | lock_sock(sk); | 677 | lock_sock(sk); |
674 | if (res) | ||
675 | break; | ||
676 | } while (1); | 678 | } while (1); |
677 | 679 | ||
678 | if (iocb) | 680 | if (iocb) |
@@ -1369,7 +1371,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1369 | struct msghdr m = {NULL,}; | 1371 | struct msghdr m = {NULL,}; |
1370 | struct sk_buff *buf; | 1372 | struct sk_buff *buf; |
1371 | struct tipc_msg *msg; | 1373 | struct tipc_msg *msg; |
1372 | long timeout; | 1374 | unsigned int timeout; |
1373 | int res; | 1375 | int res; |
1374 | 1376 | ||
1375 | lock_sock(sk); | 1377 | lock_sock(sk); |
@@ -1434,7 +1436,8 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1434 | res = wait_event_interruptible_timeout(*sk_sleep(sk), | 1436 | res = wait_event_interruptible_timeout(*sk_sleep(sk), |
1435 | (!skb_queue_empty(&sk->sk_receive_queue) || | 1437 | (!skb_queue_empty(&sk->sk_receive_queue) || |
1436 | (sock->state != SS_CONNECTING)), | 1438 | (sock->state != SS_CONNECTING)), |
1437 | timeout ? timeout : MAX_SCHEDULE_TIMEOUT); | 1439 | timeout ? (long)msecs_to_jiffies(timeout) |
1440 | : MAX_SCHEDULE_TIMEOUT); | ||
1438 | lock_sock(sk); | 1441 | lock_sock(sk); |
1439 | 1442 | ||
1440 | if (res > 0) { | 1443 | if (res > 0) { |
@@ -1480,9 +1483,7 @@ static int listen(struct socket *sock, int len) | |||
1480 | 1483 | ||
1481 | lock_sock(sk); | 1484 | lock_sock(sk); |
1482 | 1485 | ||
1483 | if (sock->state == SS_READY) | 1486 | if (sock->state != SS_UNCONNECTED) |
1484 | res = -EOPNOTSUPP; | ||
1485 | else if (sock->state != SS_UNCONNECTED) | ||
1486 | res = -EINVAL; | 1487 | res = -EINVAL; |
1487 | else { | 1488 | else { |
1488 | sock->state = SS_LISTENING; | 1489 | sock->state = SS_LISTENING; |
@@ -1510,10 +1511,6 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
1510 | 1511 | ||
1511 | lock_sock(sk); | 1512 | lock_sock(sk); |
1512 | 1513 | ||
1513 | if (sock->state == SS_READY) { | ||
1514 | res = -EOPNOTSUPP; | ||
1515 | goto exit; | ||
1516 | } | ||
1517 | if (sock->state != SS_LISTENING) { | 1514 | if (sock->state != SS_LISTENING) { |
1518 | res = -EINVAL; | 1515 | res = -EINVAL; |
1519 | goto exit; | 1516 | goto exit; |
@@ -1696,7 +1693,7 @@ static int setsockopt(struct socket *sock, | |||
1696 | res = tipc_set_portunreturnable(tport->ref, value); | 1693 | res = tipc_set_portunreturnable(tport->ref, value); |
1697 | break; | 1694 | break; |
1698 | case TIPC_CONN_TIMEOUT: | 1695 | case TIPC_CONN_TIMEOUT: |
1699 | tipc_sk(sk)->conn_timeout = msecs_to_jiffies(value); | 1696 | tipc_sk(sk)->conn_timeout = value; |
1700 | /* no need to set "res", since already 0 at this point */ | 1697 | /* no need to set "res", since already 0 at this point */ |
1701 | break; | 1698 | break; |
1702 | default: | 1699 | default: |
@@ -1752,7 +1749,7 @@ static int getsockopt(struct socket *sock, | |||
1752 | res = tipc_portunreturnable(tport->ref, &value); | 1749 | res = tipc_portunreturnable(tport->ref, &value); |
1753 | break; | 1750 | break; |
1754 | case TIPC_CONN_TIMEOUT: | 1751 | case TIPC_CONN_TIMEOUT: |
1755 | value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout); | 1752 | value = tipc_sk(sk)->conn_timeout; |
1756 | /* no need to set "res", since already 0 at this point */ | 1753 | /* no need to set "res", since already 0 at this point */ |
1757 | break; | 1754 | break; |
1758 | case TIPC_NODE_RECVQ_DEPTH: | 1755 | case TIPC_NODE_RECVQ_DEPTH: |
@@ -1790,11 +1787,11 @@ static const struct proto_ops msg_ops = { | |||
1790 | .bind = bind, | 1787 | .bind = bind, |
1791 | .connect = connect, | 1788 | .connect = connect, |
1792 | .socketpair = sock_no_socketpair, | 1789 | .socketpair = sock_no_socketpair, |
1793 | .accept = accept, | 1790 | .accept = sock_no_accept, |
1794 | .getname = get_name, | 1791 | .getname = get_name, |
1795 | .poll = poll, | 1792 | .poll = poll, |
1796 | .ioctl = sock_no_ioctl, | 1793 | .ioctl = sock_no_ioctl, |
1797 | .listen = listen, | 1794 | .listen = sock_no_listen, |
1798 | .shutdown = shutdown, | 1795 | .shutdown = shutdown, |
1799 | .setsockopt = setsockopt, | 1796 | .setsockopt = setsockopt, |
1800 | .getsockopt = getsockopt, | 1797 | .getsockopt = getsockopt, |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 6cf726863485..198371723b41 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -151,7 +151,7 @@ void tipc_subscr_report_overlap(struct subscription *sub, | |||
151 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) | 151 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) |
152 | return; | 152 | return; |
153 | 153 | ||
154 | sub->event_cb(sub, found_lower, found_upper, event, port_ref, node); | 154 | subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); |
155 | } | 155 | } |
156 | 156 | ||
157 | /** | 157 | /** |
@@ -365,7 +365,6 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s, | |||
365 | subscr_terminate(subscriber); | 365 | subscr_terminate(subscriber); |
366 | return NULL; | 366 | return NULL; |
367 | } | 367 | } |
368 | sub->event_cb = subscr_send_event; | ||
369 | INIT_LIST_HEAD(&sub->nameseq_list); | 368 | INIT_LIST_HEAD(&sub->nameseq_list); |
370 | list_add(&sub->subscription_list, &subscriber->subscription_list); | 369 | list_add(&sub->subscription_list, &subscriber->subscription_list); |
371 | sub->server_ref = subscriber->port_ref; | 370 | sub->server_ref = subscriber->port_ref; |
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 45d89bf4d202..4b06ef6f8401 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h | |||
@@ -39,16 +39,11 @@ | |||
39 | 39 | ||
40 | struct subscription; | 40 | struct subscription; |
41 | 41 | ||
42 | typedef void (*tipc_subscr_event) (struct subscription *sub, | ||
43 | u32 found_lower, u32 found_upper, | ||
44 | u32 event, u32 port_ref, u32 node); | ||
45 | |||
46 | /** | 42 | /** |
47 | * struct subscription - TIPC network topology subscription object | 43 | * struct subscription - TIPC network topology subscription object |
48 | * @seq: name sequence associated with subscription | 44 | * @seq: name sequence associated with subscription |
49 | * @timeout: duration of subscription (in ms) | 45 | * @timeout: duration of subscription (in ms) |
50 | * @filter: event filtering to be done for subscription | 46 | * @filter: event filtering to be done for subscription |
51 | * @event_cb: routine invoked when a subscription event is detected | ||
52 | * @timer: timer governing subscription duration (optional) | 47 | * @timer: timer governing subscription duration (optional) |
53 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list | 48 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list |
54 | * @subscription_list: adjacent subscriptions in subscriber's subscription list | 49 | * @subscription_list: adjacent subscriptions in subscriber's subscription list |
@@ -61,7 +56,6 @@ struct subscription { | |||
61 | struct tipc_name_seq seq; | 56 | struct tipc_name_seq seq; |
62 | u32 timeout; | 57 | u32 timeout; |
63 | u32 filter; | 58 | u32 filter; |
64 | tipc_subscr_event event_cb; | ||
65 | struct timer_list timer; | 59 | struct timer_list timer; |
66 | struct list_head nameseq_list; | 60 | struct list_head nameseq_list; |
67 | struct list_head subscription_list; | 61 | struct list_head subscription_list; |