diff options
Diffstat (limited to 'net/tipc/port.c')
| -rw-r--r-- | net/tipc/port.c | 440 | 
1 files changed, 28 insertions, 412 deletions
diff --git a/net/tipc/port.c b/net/tipc/port.c index 5fd7acce01ea..7e096a5e7701 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -42,8 +42,6 @@  /* Connection management: */  #define PROBING_INTERVAL 3600000	/* [ms] => 1 h */ -#define CONFIRMED 0 -#define PROBING 1  #define MAX_REJECT_SIZE 1024 @@ -76,124 +74,6 @@ int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg)  		(!peernode && (orignode == tipc_own_addr));  } -/** - * tipc_port_mcast_xmit - send a multicast message to local and remote - * destinations - */ -int tipc_port_mcast_xmit(struct tipc_port *oport, -			 struct tipc_name_seq const *seq, -			 struct iovec const *msg_sect, -			 unsigned int len) -{ -	struct tipc_msg *hdr; -	struct sk_buff *buf; -	struct sk_buff *ibuf = NULL; -	struct tipc_port_list dports = {0, NULL, }; -	int ext_targets; -	int res; - -	/* Create multicast message */ -	hdr = &oport->phdr; -	msg_set_type(hdr, TIPC_MCAST_MSG); -	msg_set_lookup_scope(hdr, TIPC_CLUSTER_SCOPE); -	msg_set_destport(hdr, 0); -	msg_set_destnode(hdr, 0); -	msg_set_nametype(hdr, seq->type); -	msg_set_namelower(hdr, seq->lower); -	msg_set_nameupper(hdr, seq->upper); -	msg_set_hdr_sz(hdr, MCAST_H_SIZE); -	res = tipc_msg_build(hdr, msg_sect, len, MAX_MSG_SIZE, &buf); -	if (unlikely(!buf)) -		return res; - -	/* Figure out where to send multicast message */ -	ext_targets = tipc_nametbl_mc_translate(seq->type, seq->lower, seq->upper, -						TIPC_NODE_SCOPE, &dports); - -	/* Send message to destinations (duplicate it only if necessary) */ -	if (ext_targets) { -		if (dports.count != 0) { -			ibuf = skb_copy(buf, GFP_ATOMIC); -			if (ibuf == NULL) { -				tipc_port_list_free(&dports); -				kfree_skb(buf); -				return -ENOMEM; -			} -		} -		res = tipc_bclink_xmit(buf); -		if ((res < 0) && (dports.count != 0)) -			kfree_skb(ibuf); -	} else { -		ibuf = buf; -	} - -	if (res >= 0) { -		if (ibuf) -			tipc_port_mcast_rcv(ibuf, &dports); -	} else { -		tipc_port_list_free(&dports); -	} -	return res; -} - -/** - * tipc_port_mcast_rcv - deliver multicast message to all destination ports - * - * If there is no port list, perform a lookup to create one - */ -void tipc_port_mcast_rcv(struct sk_buff *buf, struct tipc_port_list *dp) -{ -	struct tipc_msg *msg; -	struct tipc_port_list dports = {0, NULL, }; -	struct tipc_port_list *item = dp; -	int cnt = 0; - -	msg = buf_msg(buf); - -	/* Create destination port list, if one wasn't supplied */ -	if (dp == NULL) { -		tipc_nametbl_mc_translate(msg_nametype(msg), -				     msg_namelower(msg), -				     msg_nameupper(msg), -				     TIPC_CLUSTER_SCOPE, -				     &dports); -		item = dp = &dports; -	} - -	/* Deliver a copy of message to each destination port */ -	if (dp->count != 0) { -		msg_set_destnode(msg, tipc_own_addr); -		if (dp->count == 1) { -			msg_set_destport(msg, dp->ports[0]); -			tipc_sk_rcv(buf); -			tipc_port_list_free(dp); -			return; -		} -		for (; cnt < dp->count; cnt++) { -			int index = cnt % PLSIZE; -			struct sk_buff *b = skb_clone(buf, GFP_ATOMIC); - -			if (b == NULL) { -				pr_warn("Unable to deliver multicast message(s)\n"); -				goto exit; -			} -			if ((index == 0) && (cnt != 0)) -				item = item->next; -			msg_set_destport(buf_msg(b), item->ports[index]); -			tipc_sk_rcv(b); -		} -	} -exit: -	kfree_skb(buf); -	tipc_port_list_free(dp); -} - - -void tipc_port_wakeup(struct tipc_port *port) -{ -	tipc_sock_wakeup(tipc_port_to_sock(port)); -} -  /* tipc_port_init - intiate TIPC port and lock it   *   * Returns obtained reference if initialization is successful, zero otherwise @@ -235,6 +115,8 @@ u32 tipc_port_init(struct tipc_port *p_ptr,  void tipc_port_destroy(struct tipc_port *p_ptr)  {  	struct sk_buff *buf = NULL; +	struct tipc_msg *msg = NULL; +	u32 peer;  	tipc_withdraw(p_ptr, 0, NULL); @@ -246,14 +128,15 @@ void tipc_port_destroy(struct tipc_port *p_ptr)  	if (p_ptr->connected) {  		buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT);  		tipc_nodesub_unsubscribe(&p_ptr->subscription); +		msg = buf_msg(buf); +		peer = msg_destnode(msg); +		tipc_link_xmit(buf, peer, msg_link_selector(msg));  	} -  	spin_lock_bh(&tipc_port_list_lock);  	list_del(&p_ptr->port_list);  	list_del(&p_ptr->wait_list);  	spin_unlock_bh(&tipc_port_list_lock);  	k_term_timer(&p_ptr->timer); -	tipc_net_route_msg(buf);  }  /* @@ -275,100 +158,16 @@ static struct sk_buff *port_build_proto_msg(struct tipc_port *p_ptr,  		msg_set_destport(msg, tipc_port_peerport(p_ptr));  		msg_set_origport(msg, p_ptr->ref);  		msg_set_msgcnt(msg, ack); +		buf->next = NULL;  	}  	return buf;  } -int tipc_reject_msg(struct sk_buff *buf, u32 err) -{ -	struct tipc_msg *msg = buf_msg(buf); -	struct sk_buff *rbuf; -	struct tipc_msg *rmsg; -	int hdr_sz; -	u32 imp; -	u32 data_sz = msg_data_sz(msg); -	u32 src_node; -	u32 rmsg_sz; - -	/* discard rejected message if it shouldn't be returned to sender */ -	if (WARN(!msg_isdata(msg), -		 "attempt to reject message with user=%u", msg_user(msg))) { -		dump_stack(); -		goto exit; -	} -	if (msg_errcode(msg) || msg_dest_droppable(msg)) -		goto exit; - -	/* -	 * construct returned message by copying rejected message header and -	 * data (or subset), then updating header fields that need adjusting -	 */ -	hdr_sz = msg_hdr_sz(msg); -	rmsg_sz = hdr_sz + min_t(u32, data_sz, MAX_REJECT_SIZE); - -	rbuf = tipc_buf_acquire(rmsg_sz); -	if (rbuf == NULL) -		goto exit; - -	rmsg = buf_msg(rbuf); -	skb_copy_to_linear_data(rbuf, msg, rmsg_sz); - -	if (msg_connected(rmsg)) { -		imp = msg_importance(rmsg); -		if (imp < TIPC_CRITICAL_IMPORTANCE) -			msg_set_importance(rmsg, ++imp); -	} -	msg_set_non_seq(rmsg, 0); -	msg_set_size(rmsg, rmsg_sz); -	msg_set_errcode(rmsg, err); -	msg_set_prevnode(rmsg, tipc_own_addr); -	msg_swap_words(rmsg, 4, 5); -	if (!msg_short(rmsg)) -		msg_swap_words(rmsg, 6, 7); - -	/* send self-abort message when rejecting on a connected port */ -	if (msg_connected(msg)) { -		struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); - -		if (p_ptr) { -			struct sk_buff *abuf = NULL; - -			if (p_ptr->connected) -				abuf = port_build_self_abort_msg(p_ptr, err); -			tipc_port_unlock(p_ptr); -			tipc_net_route_msg(abuf); -		} -	} - -	/* send returned message & dispose of rejected message */ -	src_node = msg_prevnode(msg); -	if (in_own_node(src_node)) -		tipc_sk_rcv(rbuf); -	else -		tipc_link_xmit(rbuf, src_node, msg_link_selector(rmsg)); -exit: -	kfree_skb(buf); -	return data_sz; -} - -int tipc_port_iovec_reject(struct tipc_port *p_ptr, struct tipc_msg *hdr, -			   struct iovec const *msg_sect, unsigned int len, -			   int err) -{ -	struct sk_buff *buf; -	int res; - -	res = tipc_msg_build(hdr, msg_sect, len, MAX_MSG_SIZE, &buf); -	if (!buf) -		return res; - -	return tipc_reject_msg(buf, err); -} -  static void port_timeout(unsigned long ref)  {  	struct tipc_port *p_ptr = tipc_port_lock(ref);  	struct sk_buff *buf = NULL; +	struct tipc_msg *msg = NULL;  	if (!p_ptr)  		return; @@ -379,15 +178,16 @@ static void port_timeout(unsigned long ref)  	}  	/* Last probe answered ? */ -	if (p_ptr->probing_state == PROBING) { +	if (p_ptr->probing_state == TIPC_CONN_PROBING) {  		buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);  	} else {  		buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0); -		p_ptr->probing_state = PROBING; +		p_ptr->probing_state = TIPC_CONN_PROBING;  		k_start_timer(&p_ptr->timer, p_ptr->probing_interval);  	}  	tipc_port_unlock(p_ptr); -	tipc_net_route_msg(buf); +	msg = buf_msg(buf); +	tipc_link_xmit(buf, msg_destnode(msg),	msg_link_selector(msg));  } @@ -395,12 +195,14 @@ static void port_handle_node_down(unsigned long ref)  {  	struct tipc_port *p_ptr = tipc_port_lock(ref);  	struct sk_buff *buf = NULL; +	struct tipc_msg *msg = NULL;  	if (!p_ptr)  		return;  	buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE);  	tipc_port_unlock(p_ptr); -	tipc_net_route_msg(buf); +	msg = buf_msg(buf); +	tipc_link_xmit(buf, msg_destnode(msg),	msg_link_selector(msg));  } @@ -412,6 +214,7 @@ static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 er  		struct tipc_msg *msg = buf_msg(buf);  		msg_swap_words(msg, 4, 5);  		msg_swap_words(msg, 6, 7); +		buf->next = NULL;  	}  	return buf;  } @@ -436,60 +239,11 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er  		if (imp < TIPC_CRITICAL_IMPORTANCE)  			msg_set_importance(msg, ++imp);  		msg_set_errcode(msg, err); +		buf->next = NULL;  	}  	return buf;  } -void tipc_port_proto_rcv(struct sk_buff *buf) -{ -	struct tipc_msg *msg = buf_msg(buf); -	struct tipc_port *p_ptr; -	struct sk_buff *r_buf = NULL; -	u32 destport = msg_destport(msg); -	int wakeable; - -	/* Validate connection */ -	p_ptr = tipc_port_lock(destport); -	if (!p_ptr || !p_ptr->connected || !tipc_port_peer_msg(p_ptr, msg)) { -		r_buf = tipc_buf_acquire(BASIC_H_SIZE); -		if (r_buf) { -			msg = buf_msg(r_buf); -			tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG, -				      BASIC_H_SIZE, msg_orignode(msg)); -			msg_set_errcode(msg, TIPC_ERR_NO_PORT); -			msg_set_origport(msg, destport); -			msg_set_destport(msg, msg_origport(msg)); -		} -		if (p_ptr) -			tipc_port_unlock(p_ptr); -		goto exit; -	} - -	/* Process protocol message sent by peer */ -	switch (msg_type(msg)) { -	case CONN_ACK: -		wakeable = tipc_port_congested(p_ptr) && p_ptr->congested; -		p_ptr->acked += msg_msgcnt(msg); -		if (!tipc_port_congested(p_ptr)) { -			p_ptr->congested = 0; -			if (wakeable) -				tipc_port_wakeup(p_ptr); -		} -		break; -	case CONN_PROBE: -		r_buf = port_build_proto_msg(p_ptr, CONN_PROBE_REPLY, 0); -		break; -	default: -		/* CONN_PROBE_REPLY or unrecognized - no action required */ -		break; -	} -	p_ptr->probing_state = CONFIRMED; -	tipc_port_unlock(p_ptr); -exit: -	tipc_net_route_msg(r_buf); -	kfree_skb(buf); -} -  static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id)  {  	struct publication *publ; @@ -581,16 +335,19 @@ void tipc_acknowledge(u32 ref, u32 ack)  {  	struct tipc_port *p_ptr;  	struct sk_buff *buf = NULL; +	struct tipc_msg *msg;  	p_ptr = tipc_port_lock(ref);  	if (!p_ptr)  		return; -	if (p_ptr->connected) { -		p_ptr->conn_unacked -= ack; +	if (p_ptr->connected)  		buf = port_build_proto_msg(p_ptr, CONN_ACK, ack); -	} +  	tipc_port_unlock(p_ptr); -	tipc_net_route_msg(buf); +	if (!buf) +		return; +	msg = buf_msg(buf); +	tipc_link_xmit(buf, msg_destnode(msg),	msg_link_selector(msg));  }  int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, @@ -689,7 +446,7 @@ int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr,  	msg_set_hdr_sz(msg, SHORT_H_SIZE);  	p_ptr->probing_interval = PROBING_INTERVAL; -	p_ptr->probing_state = CONFIRMED; +	p_ptr->probing_state = TIPC_CONN_OK;  	p_ptr->connected = 1;  	k_start_timer(&p_ptr->timer, p_ptr->probing_interval); @@ -698,7 +455,7 @@ int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr,  			  (net_ev_handler)port_handle_node_down);  	res = 0;  exit: -	p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref); +	p_ptr->max_pkt = tipc_node_get_mtu(peer->node, ref);  	return res;  } @@ -741,6 +498,7 @@ int tipc_port_disconnect(u32 ref)   */  int tipc_port_shutdown(u32 ref)  { +	struct tipc_msg *msg;  	struct tipc_port *p_ptr;  	struct sk_buff *buf = NULL; @@ -750,149 +508,7 @@ int tipc_port_shutdown(u32 ref)  	buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN);  	tipc_port_unlock(p_ptr); -	tipc_net_route_msg(buf); +	msg = buf_msg(buf); +	tipc_link_xmit(buf, msg_destnode(msg),	msg_link_selector(msg));  	return tipc_port_disconnect(ref);  } - -/* - *  tipc_port_iovec_rcv: Concatenate and deliver sectioned - *                       message for this node. - */ -static int tipc_port_iovec_rcv(struct tipc_port *sender, -			       struct iovec const *msg_sect, -			       unsigned int len) -{ -	struct sk_buff *buf; -	int res; - -	res = tipc_msg_build(&sender->phdr, msg_sect, len, MAX_MSG_SIZE, &buf); -	if (likely(buf)) -		tipc_sk_rcv(buf); -	return res; -} - -/** - * tipc_send - send message sections on connection - */ -int tipc_send(struct tipc_port *p_ptr, -	      struct iovec const *msg_sect, -	      unsigned int len) -{ -	u32 destnode; -	int res; - -	if (!p_ptr->connected) -		return -EINVAL; - -	p_ptr->congested = 1; -	if (!tipc_port_congested(p_ptr)) { -		destnode = tipc_port_peernode(p_ptr); -		if (likely(!in_own_node(destnode))) -			res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len, -							destnode); -		else -			res = tipc_port_iovec_rcv(p_ptr, msg_sect, len); - -		if (likely(res != -ELINKCONG)) { -			p_ptr->congested = 0; -			if (res > 0) -				p_ptr->sent++; -			return res; -		} -	} -	if (tipc_port_unreliable(p_ptr)) { -		p_ptr->congested = 0; -		return len; -	} -	return -ELINKCONG; -} - -/** - * tipc_send2name - send message sections to port name - */ -int tipc_send2name(struct tipc_port *p_ptr, -		   struct tipc_name const *name, -		   unsigned int domain, -		   struct iovec const *msg_sect, -		   unsigned int len) -{ -	struct tipc_msg *msg; -	u32 destnode = domain; -	u32 destport; -	int res; - -	if (p_ptr->connected) -		return -EINVAL; - -	msg = &p_ptr->phdr; -	msg_set_type(msg, TIPC_NAMED_MSG); -	msg_set_hdr_sz(msg, NAMED_H_SIZE); -	msg_set_nametype(msg, name->type); -	msg_set_nameinst(msg, name->instance); -	msg_set_lookup_scope(msg, tipc_addr_scope(domain)); -	destport = tipc_nametbl_translate(name->type, name->instance, &destnode); -	msg_set_destnode(msg, destnode); -	msg_set_destport(msg, destport); - -	if (likely(destport || destnode)) { -		if (likely(in_own_node(destnode))) -			res = tipc_port_iovec_rcv(p_ptr, msg_sect, len); -		else if (tipc_own_addr) -			res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len, -							destnode); -		else -			res = tipc_port_iovec_reject(p_ptr, msg, msg_sect, -						     len, TIPC_ERR_NO_NODE); -		if (likely(res != -ELINKCONG)) { -			if (res > 0) -				p_ptr->sent++; -			return res; -		} -		if (tipc_port_unreliable(p_ptr)) -			return len; - -		return -ELINKCONG; -	} -	return tipc_port_iovec_reject(p_ptr, msg, msg_sect, len, -				      TIPC_ERR_NO_NAME); -} - -/** - * tipc_send2port - send message sections to port identity - */ -int tipc_send2port(struct tipc_port *p_ptr, -		   struct tipc_portid const *dest, -		   struct iovec const *msg_sect, -		   unsigned int len) -{ -	struct tipc_msg *msg; -	int res; - -	if (p_ptr->connected) -		return -EINVAL; - -	msg = &p_ptr->phdr; -	msg_set_type(msg, TIPC_DIRECT_MSG); -	msg_set_lookup_scope(msg, 0); -	msg_set_destnode(msg, dest->node); -	msg_set_destport(msg, dest->ref); -	msg_set_hdr_sz(msg, BASIC_H_SIZE); - -	if (in_own_node(dest->node)) -		res =  tipc_port_iovec_rcv(p_ptr, msg_sect, len); -	else if (tipc_own_addr) -		res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len, -						dest->node); -	else -		res = tipc_port_iovec_reject(p_ptr, msg, msg_sect, len, -						TIPC_ERR_NO_NODE); -	if (likely(res != -ELINKCONG)) { -		if (res > 0) -			p_ptr->sent++; -		return res; -	} -	if (tipc_port_unreliable(p_ptr)) -		return len; - -	return -ELINKCONG; -}  | 
