diff options
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/bcast.c | 14 | ||||
| -rw-r--r-- | net/tipc/bcast.h | 3 | ||||
| -rw-r--r-- | net/tipc/link.c | 2 | ||||
| -rw-r--r-- | net/tipc/msg.h | 17 | ||||
| -rw-r--r-- | net/tipc/name_distr.c | 1 | ||||
| -rw-r--r-- | net/tipc/node.c | 2 | 
6 files changed, 33 insertions, 6 deletions
| diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 753f774cb46f..aa1babbea385 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -247,11 +247,17 @@ int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb)   *   * RCU is locked, no other locks set   */ -void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked) +void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, +			struct tipc_msg *hdr)  {  	struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq; +	u16 acked = msg_bcast_ack(hdr);  	struct sk_buff_head xmitq; +	/* Ignore bc acks sent by peer before bcast synch point was received */ +	if (msg_bc_ack_invalid(hdr)) +		return; +  	__skb_queue_head_init(&xmitq);  	tipc_bcast_lock(net); @@ -279,11 +285,11 @@ int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,  	__skb_queue_head_init(&xmitq);  	tipc_bcast_lock(net); -	if (msg_type(hdr) == STATE_MSG) { +	if (msg_type(hdr) != STATE_MSG) { +		tipc_link_bc_init_rcv(l, hdr); +	} else if (!msg_bc_ack_invalid(hdr)) {  		tipc_link_bc_ack_rcv(l, msg_bcast_ack(hdr), &xmitq);  		rc = tipc_link_bc_sync_rcv(l, hdr, &xmitq); -	} else { -		tipc_link_bc_init_rcv(l, hdr);  	}  	tipc_bcast_unlock(net); diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 5ffe34472ccd..855d53c64ab3 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -55,7 +55,8 @@ void tipc_bcast_dec_bearer_dst_cnt(struct net *net, int bearer_id);  int  tipc_bcast_get_mtu(struct net *net);  int tipc_bcast_xmit(struct net *net, struct sk_buff_head *list);  int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb); -void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked); +void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, +			struct tipc_msg *hdr);  int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,  			struct tipc_msg *hdr);  int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg); diff --git a/net/tipc/link.c b/net/tipc/link.c index b36e16cdc945..1055164c6232 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1312,6 +1312,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,  	msg_set_next_sent(hdr, l->snd_nxt);  	msg_set_ack(hdr, l->rcv_nxt - 1);  	msg_set_bcast_ack(hdr, bcl->rcv_nxt - 1); +	msg_set_bc_ack_invalid(hdr, !node_up);  	msg_set_last_bcast(hdr, l->bc_sndlink->snd_nxt - 1);  	msg_set_link_tolerance(hdr, tolerance);  	msg_set_linkprio(hdr, priority); @@ -1574,6 +1575,7 @@ static void tipc_link_build_bc_init_msg(struct tipc_link *l,  	__skb_queue_head_init(&list);  	if (!tipc_link_build_bc_proto_msg(l->bc_rcvlink, false, 0, &list))  		return; +	msg_set_bc_ack_invalid(buf_msg(skb_peek(&list)), true);  	tipc_link_xmit(l, &list, xmitq);  } diff --git a/net/tipc/msg.h b/net/tipc/msg.h index c3832cdf2278..50a739860d37 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -714,6 +714,23 @@ static inline void msg_set_peer_stopping(struct tipc_msg *m, u32 s)  	msg_set_bits(m, 5, 13, 0x1, s);  } +static inline bool msg_bc_ack_invalid(struct tipc_msg *m) +{ +	switch (msg_user(m)) { +	case BCAST_PROTOCOL: +	case NAME_DISTRIBUTOR: +	case LINK_PROTOCOL: +		return msg_bits(m, 5, 14, 0x1); +	default: +		return false; +	} +} + +static inline void msg_set_bc_ack_invalid(struct tipc_msg *m, bool invalid) +{ +	msg_set_bits(m, 5, 14, 0x1, invalid); +} +  static inline char *msg_media_addr(struct tipc_msg *m)  {  	return (char *)&m->hdr[TIPC_MEDIA_INFO_OFFSET]; diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index a04fe9be1c60..c1cfd92de17a 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -156,6 +156,7 @@ static void named_distribute(struct net *net, struct sk_buff_head *list,  				pr_warn("Bulk publication failure\n");  				return;  			} +			msg_set_bc_ack_invalid(buf_msg(skb), true);  			item = (struct distr_item *)msg_data(buf_msg(skb));  		} diff --git a/net/tipc/node.c b/net/tipc/node.c index 7ef14e2d2356..9d2f4c2b08ab 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1535,7 +1535,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)  	if (unlikely(usr == LINK_PROTOCOL))  		tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq);  	else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack)) -		tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack); +		tipc_bcast_ack_rcv(net, n->bc_entry.link, hdr);  	/* Receive packet directly if conditions permit */  	tipc_node_read_lock(n); |