A little ugly, but I have no better idea at the moment. Acked-by: Jon
> -----Original Message----- > From: Tuong Lien <tuong.t.l...@dektech.com.au> > Sent: 25-Nov-19 23:07 > To: tipc-discussion@lists.sourceforge.net; Jon Maloy > <jon.ma...@ericsson.com>; ma...@donjonn.com; > ying....@windriver.com > Subject: [PATCH RFC] tipc: fix potential hanging after b/rcast changing > > In commit c55c8edafa91 ("tipc: smooth change between replicast and > broadcast"), we allow instant switching between replicast and broadcast > by sending a dummy 'SYN' packet on the last used link to synchronize > packets on the links. The 'SYN' message is an object of link congestion > also, so if that happens, a 'SOCK_WAKEUP' will be scheduled to be sent > back to the socket... > However, in that commit, we simply use the same socket 'cong_link_cnt' > counter for both the 'SYN' & normal payload message sending. Therefore, > if both the replicast & broadcast links are congested, the counter will > be not updated correctly but overwritten by the latter congestion. > Later on, when the 'SOCK_WAKEUP' messages are processed, the counter is > reduced one by one and eventually overflowed. Consequently, further > activities on the socket will only wait for the false congestion signal > to disappear but never been met. > > Because sending the 'SYN' message is vital for the mechanism, it should > be done anyway. This commit fixes the issue by marking the message with > an error code e.g. 'TIPC_ERR_NO_PORT', so its sending should not face a > link congestion, there is no need to touch the socket 'cong_link_cnt' > either. In addition, in the event of any error (e.g. -ENOBUFS), we will > purge the entire payload message queue and make a return immediately. > > Fixes: c55c8edafa91 ("tipc: smooth change between replicast and broadcast") > Signed-off-by: Tuong Lien <tuong.t.l...@dektech.com.au> > --- > net/tipc/bcast.c | 24 +++++++++++++++--------- > 1 file changed, 15 insertions(+), 9 deletions(-) > > diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c > index 55aeba681cf4..656ebc79c64e 100644 > --- a/net/tipc/bcast.c > +++ b/net/tipc/bcast.c > @@ -305,17 +305,17 @@ static int tipc_rcast_xmit(struct net *net, struct > sk_buff_head *pkts, > * @skb: socket buffer to copy > * @method: send method to be used > * @dests: destination nodes for message. > - * @cong_link_cnt: returns number of encountered congested destination links > * Returns 0 if success, otherwise errno > */ > static int tipc_mcast_send_sync(struct net *net, struct sk_buff *skb, > struct tipc_mc_method *method, > - struct tipc_nlist *dests, > - u16 *cong_link_cnt) > + struct tipc_nlist *dests) > { > struct tipc_msg *hdr, *_hdr; > struct sk_buff_head tmpq; > struct sk_buff *_skb; > + u16 cong_link_cnt; > + int rc = 0; > > /* Is a cluster supporting with new capabilities ? */ > if (!(tipc_net(net)->capabilities & TIPC_MCAST_RBCTL)) > @@ -343,18 +343,19 @@ static int tipc_mcast_send_sync(struct net *net, struct > sk_buff *skb, > _hdr = buf_msg(_skb); > msg_set_size(_hdr, MCAST_H_SIZE); > msg_set_is_rcast(_hdr, !msg_is_rcast(hdr)); > + msg_set_errcode(_hdr, TIPC_ERR_NO_PORT); > > __skb_queue_head_init(&tmpq); > __skb_queue_tail(&tmpq, _skb); > if (method->rcast) > - tipc_bcast_xmit(net, &tmpq, cong_link_cnt); > + rc = tipc_bcast_xmit(net, &tmpq, &cong_link_cnt); > else > - tipc_rcast_xmit(net, &tmpq, dests, cong_link_cnt); > + rc = tipc_rcast_xmit(net, &tmpq, dests, &cong_link_cnt); > > /* This queue should normally be empty by now */ > __skb_queue_purge(&tmpq); > > - return 0; > + return rc; > } > > /* tipc_mcast_xmit - deliver message to indicated destination nodes > @@ -396,9 +397,14 @@ int tipc_mcast_xmit(struct net *net, struct sk_buff_head > *pkts, > msg_set_is_rcast(hdr, method->rcast); > > /* Switch method ? */ > - if (rcast != method->rcast) > - tipc_mcast_send_sync(net, skb, method, > - dests, cong_link_cnt); > + if (rcast != method->rcast) { > + rc = tipc_mcast_send_sync(net, skb, method, dests); > + if (unlikely(rc)) { > + pr_err("Unable to send SYN: method %d, rc %d\n", > + rcast, rc); > + goto exit; > + } > + } > > if (method->rcast) > rc = tipc_rcast_xmit(net, pkts, dests, cong_link_cnt); > -- > 2.13.7 _______________________________________________ tipc-discussion mailing list tipc-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tipc-discussion