diff options
-rw-r--r-- | net/tipc/discover.c | 6 | ||||
-rw-r--r-- | net/tipc/link.c | 33 | ||||
-rw-r--r-- | net/tipc/node.c | 11 | ||||
-rw-r--r-- | net/tipc/node.h | 10 |
4 files changed, 42 insertions, 18 deletions
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) } tipc_node_lock(n_ptr); - /* Don't talk to neighbor during cleanup after last session */ - if (n_ptr->cleanup_required) { - tipc_node_unlock(n_ptr); - return; - } - link = n_ptr->links[b_ptr->identity]; /* Create a link endpoint for this bearer, if necessary */ diff --git a/net/tipc/link.c b/net/tipc/link.c index bc655f456495..74126db45972 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1669,17 +1669,24 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr) goto cont; tipc_node_lock(n_ptr); - /* Don't talk to neighbor during cleanup after last session */ + /* Locate unicast link endpoint that should handle message */ - if (n_ptr->cleanup_required) { + l_ptr = n_ptr->links[b_ptr->identity]; + if (unlikely(!l_ptr)) { tipc_node_unlock(n_ptr); goto cont; } - /* Locate unicast link endpoint that should handle message */ + /* Verify that communication with node is currently allowed */ - l_ptr = n_ptr->links[b_ptr->identity]; - if (unlikely(!l_ptr)) { + if ((n_ptr->block_setup & WAIT_PEER_DOWN) && + msg_user(msg) == LINK_PROTOCOL && + (msg_type(msg) == RESET_MSG || + msg_type(msg) == ACTIVATE_MSG) && + !msg_redundant_link(msg)) + n_ptr->block_setup &= ~WAIT_PEER_DOWN; + + if (n_ptr->block_setup) { tipc_node_unlock(n_ptr); goto cont; } @@ -1914,6 +1921,12 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, if (link_blocked(l_ptr)) return; + + /* Abort non-RESET send if communication with node is prohibited */ + + if ((l_ptr->owner->block_setup) && (msg_typ != RESET_MSG)) + return; + msg_set_type(msg, msg_typ); msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); @@ -2045,6 +2058,16 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) if (less_eq(msg_session(msg), l_ptr->peer_session)) break; /* duplicate or old reset: ignore */ } + + if (!msg_redundant_link(msg) && (link_working_working(l_ptr) || + link_working_unknown(l_ptr))) { + /* + * peer has lost contact -- don't allow peer's links + * to reactivate before we recognize loss & clean up + */ + l_ptr->owner->block_setup = WAIT_NODE_DOWN; + } + /* fall thru' */ case ACTIVATE_MSG: /* Update link settings according other endpoint's values */ diff --git a/net/tipc/node.c b/net/tipc/node.c index d75432f5e726..27b4bb0cca6c 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -112,6 +112,7 @@ struct tipc_node *tipc_node_create(u32 addr) break; } list_add_tail(&n_ptr->list, &temp_node->list); + n_ptr->block_setup = WAIT_PEER_DOWN; tipc_num_nodes++; @@ -312,7 +313,7 @@ static void node_established_contact(struct tipc_node *n_ptr) } } -static void node_cleanup_finished(unsigned long node_addr) +static void node_name_purge_complete(unsigned long node_addr) { struct tipc_node *n_ptr; @@ -320,7 +321,7 @@ static void node_cleanup_finished(unsigned long node_addr) n_ptr = tipc_node_find(node_addr); if (n_ptr) { tipc_node_lock(n_ptr); - n_ptr->cleanup_required = 0; + n_ptr->block_setup &= ~WAIT_NAMES_GONE; tipc_node_unlock(n_ptr); } read_unlock_bh(&tipc_net_lock); @@ -371,10 +372,10 @@ static void node_lost_contact(struct tipc_node *n_ptr) /* Notify subscribers */ tipc_nodesub_notify(n_ptr); - /* Prevent re-contact with node until all cleanup is done */ + /* Prevent re-contact with node until cleanup is done */ - n_ptr->cleanup_required = 1; - tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr); + n_ptr->block_setup = WAIT_PEER_DOWN | WAIT_NAMES_GONE; + tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr); } 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 @@ #include "net.h" #include "bearer.h" +/* Flags used to block (re)establishment of contact with a neighboring node */ + +#define WAIT_PEER_DOWN 0x0001 /* wait to see that peer's links are down */ +#define WAIT_NAMES_GONE 0x0002 /* wait for peer's publications to be purged */ +#define WAIT_NODE_DOWN 0x0004 /* wait until peer node is declared down */ + /** * struct tipc_node - TIPC node structure * @addr: network address of node @@ -52,7 +58,7 @@ * @active_links: pointers to active links to node * @links: pointers to all links to node * @working_links: number of working links to node (both active and standby) - * @cleanup_required: non-zero if cleaning up after a prior loss of contact + * @block_setup: bit mask of conditions preventing link establishment to node * @link_cnt: number of links to node * @permit_changeover: non-zero if node has redundant links to this system * @bclink: broadcast-related info @@ -77,7 +83,7 @@ struct tipc_node { struct link *links[MAX_BEARERS]; int link_cnt; int working_links; - int cleanup_required; + int block_setup; int permit_changeover; struct { int supported; |