diff options
| author | Jon Paul Maloy <jon.maloy@ericsson.com> | 2015-07-30 18:24:22 -0400 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-07-30 17:25:14 -0700 | 
| commit | cf148816acb6def45474001302368eb472995e62 (patch) | |
| tree | 1960bba9cffec1d73c8c5108e270cfe03580d940 /net/tipc | |
| parent | 662921cd0a53db4504838dfbb7d996f9e6e94001 (diff) | |
tipc: move received discovery data evaluation inside node.c
The node lock is currently grabbed and and released in the function
tipc_disc_rcv() in the file discover.c. As a preparation for the next
commits, we need to move this node lock handling, along with the code
area it is covering, to node.c.
This commit introduces this change.
Tested-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/discover.c | 116 | ||||
| -rw-r--r-- | net/tipc/node.c | 123 | ||||
| -rw-r--r-- | net/tipc/node.h | 11 | 
3 files changed, 127 insertions, 123 deletions
| diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 164d08907d6f..d14e0a4aa9af 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -120,29 +120,24 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,   * @buf: buffer containing message   * @bearer: bearer that message arrived on   */ -void tipc_disc_rcv(struct net *net, struct sk_buff *buf, +void tipc_disc_rcv(struct net *net, struct sk_buff *skb,  		   struct tipc_bearer *bearer)  {  	struct tipc_net *tn = net_generic(net, tipc_net_id); -	struct tipc_node *node;  	struct tipc_media_addr maddr; -	struct sk_buff *rbuf; -	struct tipc_msg *msg = buf_msg(buf); -	u32 ddom = msg_dest_domain(msg); -	u32 onode = msg_prevnode(msg); -	u32 net_id = msg_bc_netid(msg); -	u32 mtyp = msg_type(msg); -	u32 signature = msg_node_sig(msg); -	u16 caps = msg_node_capabilities(msg); -	bool addr_match = false; -	bool sign_match = false; -	bool link_up = false; -	bool accept_addr = false; -	bool accept_sign = false; +	struct sk_buff *rskb; +	struct tipc_msg *hdr = buf_msg(skb); +	u32 ddom = msg_dest_domain(hdr); +	u32 onode = msg_prevnode(hdr); +	u32 net_id = msg_bc_netid(hdr); +	u32 mtyp = msg_type(hdr); +	u32 signature = msg_node_sig(hdr); +	u16 caps = msg_node_capabilities(hdr);  	bool respond = false; +	bool dupl_addr = false; -	bearer->media->msg2addr(bearer, &maddr, msg_media_addr(msg)); -	kfree_skb(buf); +	bearer->media->msg2addr(bearer, &maddr, msg_media_addr(hdr)); +	kfree_skb(skb);  	/* Ensure message from node is valid and communication is permitted */  	if (net_id != tn->net_id) @@ -164,91 +159,20 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,  	if (!tipc_in_scope(bearer->domain, onode))  		return; -	node = tipc_node_create(net, onode); -	if (!node) -		return; -	tipc_node_lock(node); -	node->capabilities = caps; - -	/* Prepare to validate requesting node's signature and media address */ -	sign_match = (signature == node->signature); -	tipc_node_check_dest(node, bearer, &link_up, &addr_match, &maddr); - -	/* These three flags give us eight permutations: */ - -	if (sign_match && addr_match && link_up) { -		/* All is fine. Do nothing. */ -	} else if (sign_match && addr_match && !link_up) { -		/* Respond. The link will come up in due time */ -		respond = true; -	} else if (sign_match && !addr_match && link_up) { -		/* Peer has changed i/f address without rebooting. -		 * If so, the link will reset soon, and the next -		 * discovery will be accepted. So we can ignore it. -		 * It may also be an cloned or malicious peer having -		 * chosen the same node address and signature as an -		 * existing one. -		 * Ignore requests until the link goes down, if ever. -		 */ +	tipc_node_check_dest(net, onode, bearer, caps, signature, +			     &maddr, &respond, &dupl_addr); +	if (dupl_addr)  		disc_dupl_alert(bearer, onode, &maddr); -	} else if (sign_match && !addr_match && !link_up) { -		/* Peer link has changed i/f address without rebooting. -		 * It may also be a cloned or malicious peer; we can't -		 * distinguish between the two. -		 * The signature is correct, so we must accept. -		 */ -		accept_addr = true; -		respond = true; -	} else if (!sign_match && addr_match && link_up) { -		/* Peer node rebooted. Two possibilities: -		 *  - Delayed re-discovery; this link endpoint has already -		 *    reset and re-established contact with the peer, before -		 *    receiving a discovery message from that node. -		 *    (The peer happened to receive one from this node first). -		 *  - The peer came back so fast that our side has not -		 *    discovered it yet. Probing from this side will soon -		 *    reset the link, since there can be no working link -		 *    endpoint at the peer end, and the link will re-establish. -		 *  Accept the signature, since it comes from a known peer. -		 */ -		accept_sign = true; -	} else if (!sign_match && addr_match && !link_up) { -		/*  The peer node has rebooted. -		 *  Accept signature, since it is a known peer. -		 */ -		accept_sign = true; -		respond = true; -	} else if (!sign_match && !addr_match && link_up) { -		/* Peer rebooted with new address, or a new/duplicate peer. -		 * Ignore until the link goes down, if ever. -		 */ -		disc_dupl_alert(bearer, onode, &maddr); -	} else if (!sign_match && !addr_match && !link_up) { -		/* Peer rebooted with new address, or it is a new peer. -		 * Accept signature and address. -		*/ -		accept_sign = true; -		accept_addr = true; -		respond = true; -	} - -	if (accept_sign) -		node->signature = signature; - -	if (accept_addr && !tipc_node_update_dest(node, bearer, &maddr)) -		respond = false;  	/* Send response, if necessary */  	if (respond && (mtyp == DSC_REQ_MSG)) { -		rbuf = tipc_buf_acquire(MAX_H_SIZE); -		if (rbuf) { -			tipc_disc_init_msg(net, rbuf, DSC_RESP_MSG, bearer); -			tipc_bearer_send(net, bearer->identity, rbuf, &maddr); -			kfree_skb(rbuf); +		rskb = tipc_buf_acquire(MAX_H_SIZE); +		if (rskb) { +			tipc_disc_init_msg(net, rskb, DSC_RESP_MSG, bearer); +			tipc_bearer_send(net, bearer->identity, rskb, &maddr); +			kfree_skb(rskb);  		}  	} -	tipc_node_unlock(node); -	tipc_node_put(node);  }  /** diff --git a/net/tipc/node.c b/net/tipc/node.c index a3ceeda2a80a..d03e88f2273b 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -138,7 +138,7 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr)  	return NULL;  } -struct tipc_node *tipc_node_create(struct net *net, u32 addr) +struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 capabilities)  {  	struct tipc_net *tn = net_generic(net, tipc_net_id);  	struct tipc_node *n_ptr, *temp_node; @@ -154,6 +154,7 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)  	}  	n_ptr->addr = addr;  	n_ptr->net = net; +	n_ptr->capabilities = capabilities;  	kref_init(&n_ptr->kref);  	spin_lock_init(&n_ptr->lock);  	INIT_HLIST_NODE(&n_ptr->hash); @@ -422,38 +423,118 @@ bool tipc_node_is_up(struct tipc_node *n)  	return n->active_links[0] != INVALID_BEARER_ID;  } -void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *b, -			  bool *link_up, bool *addr_match, -			  struct tipc_media_addr *maddr) +void tipc_node_check_dest(struct net *net, u32 onode, +			  struct tipc_bearer *b, +			  u16 capabilities, u32 signature, +			  struct tipc_media_addr *maddr, +			  bool *respond, bool *dupl_addr)  { -	struct tipc_link *l = n->links[b->identity].link; -	struct tipc_media_addr *curr = &n->links[b->identity].maddr; +	struct tipc_node *n; +	struct tipc_link *l; +	struct tipc_media_addr *curr_maddr; +	struct sk_buff_head *inputq; +	bool addr_match = false; +	bool sign_match = false; +	bool link_up = false; +	bool accept_addr = false; + +	*dupl_addr = false; +	*respond = false; + +	n = tipc_node_create(net, onode, capabilities); +	if (!n) +		return; -	*link_up = l && tipc_link_is_up(l); -	*addr_match = l && !memcmp(curr, maddr, sizeof(*maddr)); -} +	tipc_node_lock(n); -bool tipc_node_update_dest(struct tipc_node *n,  struct tipc_bearer *b, -			   struct tipc_media_addr *maddr) -{ -	struct tipc_link *l = n->links[b->identity].link; -	struct tipc_media_addr *curr = &n->links[b->identity].maddr; -	struct sk_buff_head *inputq = &n->links[b->identity].inputq; +	curr_maddr = &n->links[b->identity].maddr; +	inputq = &n->links[b->identity].inputq; + +	/* Prepare to validate requesting node's signature and media address */ +	l = n->links[b->identity].link; +	link_up = l && tipc_link_is_up(l); +	addr_match = l && !memcmp(curr_maddr, maddr, sizeof(*maddr)); +	sign_match = (signature == n->signature); + +	/* These three flags give us eight permutations: */ + +	if (sign_match && addr_match && link_up) { +		/* All is fine. Do nothing. */ +	} else if (sign_match && addr_match && !link_up) { +		/* Respond. The link will come up in due time */ +		*respond = true; +	} else if (sign_match && !addr_match && link_up) { +		/* Peer has changed i/f address without rebooting. +		 * If so, the link will reset soon, and the next +		 * discovery will be accepted. So we can ignore it. +		 * It may also be an cloned or malicious peer having +		 * chosen the same node address and signature as an +		 * existing one. +		 * Ignore requests until the link goes down, if ever. +		 */ +		*dupl_addr = true; +	} else if (sign_match && !addr_match && !link_up) { +		/* Peer link has changed i/f address without rebooting. +		 * It may also be a cloned or malicious peer; we can't +		 * distinguish between the two. +		 * The signature is correct, so we must accept. +		 */ +		accept_addr = true; +		*respond = true; +	} else if (!sign_match && addr_match && link_up) { +		/* Peer node rebooted. Two possibilities: +		 *  - Delayed re-discovery; this link endpoint has already +		 *    reset and re-established contact with the peer, before +		 *    receiving a discovery message from that node. +		 *    (The peer happened to receive one from this node first). +		 *  - The peer came back so fast that our side has not +		 *    discovered it yet. Probing from this side will soon +		 *    reset the link, since there can be no working link +		 *    endpoint at the peer end, and the link will re-establish. +		 *  Accept the signature, since it comes from a known peer. +		 */ +		n->signature = signature; +	} else if (!sign_match && addr_match && !link_up) { +		/*  The peer node has rebooted. +		 *  Accept signature, since it is a known peer. +		 */ +		n->signature = signature; +		*respond = true; +	} else if (!sign_match && !addr_match && link_up) { +		/* Peer rebooted with new address, or a new/duplicate peer. +		 * Ignore until the link goes down, if ever. +		 */ +		*dupl_addr = true; +	} else if (!sign_match && !addr_match && !link_up) { +		/* Peer rebooted with new address, or it is a new peer. +		 * Accept signature and address. +		 */ +		n->signature = signature; +		accept_addr = true; +		*respond = true; +	} + +	if (!accept_addr) +		goto exit; +	/* Now create new link if not already existing */  	if (!l) {  		l = tipc_link_create(n, b, maddr, inputq, &n->bclink.namedq); -		if (!l) -			return false; +		if (!l) { +			*respond = false; +			goto exit; +		}  		tipc_node_calculate_timer(n, l); -		if (n->link_cnt == 1) { +		if (n->link_cnt == 1)  			if (!mod_timer(&n->timer, jiffies + n->keepalive_intv))  				tipc_node_get(n); -		}  	}  	memcpy(&l->media_addr, maddr, sizeof(*maddr)); -	memcpy(curr, maddr, sizeof(*maddr)); +	memcpy(curr_maddr, maddr, sizeof(*maddr));  	tipc_node_link_down(n, b->identity); -	return true; +exit: +	tipc_node_unlock(n); +	tipc_node_put(n);  }  void tipc_node_delete_links(struct net *net, int bearer_id) diff --git a/net/tipc/node.h b/net/tipc/node.h index 406c6fe0dbb2..9a977467fc46 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -147,13 +147,12 @@ struct tipc_node {  struct tipc_node *tipc_node_find(struct net *net, u32 addr);  void tipc_node_put(struct tipc_node *node); -struct tipc_node *tipc_node_create(struct net *net, u32 addr);  void tipc_node_stop(struct net *net); -void tipc_node_check_dest(struct tipc_node *n, struct tipc_bearer *bearer, -			  bool *link_up, bool *addr_match, -			  struct tipc_media_addr *maddr); -bool tipc_node_update_dest(struct tipc_node *n, struct tipc_bearer *bearer, -			   struct tipc_media_addr *maddr); +void tipc_node_check_dest(struct net *net, u32 onode, +			  struct tipc_bearer *bearer, +			  u16 capabilities, u32 signature, +			  struct tipc_media_addr *maddr, +			  bool *respond, bool *dupl_addr);  void tipc_node_delete_links(struct net *net, int bearer_id);  void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr);  void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | 
