Skip to content

Commit dca4a17

Browse files
Tuong Liendavem330
authored andcommitted
tipc: fix potential hanging after b/rcast changing
In commit c55c8ed ("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: c55c8ed ("tipc: smooth change between replicast and broadcast") Acked-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: Tuong Lien <tuong.t.lien@dektech.com.au> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d5162f3 commit dca4a17

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

net/tipc/bcast.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -305,17 +305,17 @@ static int tipc_rcast_xmit(struct net *net, struct sk_buff_head *pkts,
305305
* @skb: socket buffer to copy
306306
* @method: send method to be used
307307
* @dests: destination nodes for message.
308-
* @cong_link_cnt: returns number of encountered congested destination links
309308
* Returns 0 if success, otherwise errno
310309
*/
311310
static int tipc_mcast_send_sync(struct net *net, struct sk_buff *skb,
312311
struct tipc_mc_method *method,
313-
struct tipc_nlist *dests,
314-
u16 *cong_link_cnt)
312+
struct tipc_nlist *dests)
315313
{
316314
struct tipc_msg *hdr, *_hdr;
317315
struct sk_buff_head tmpq;
318316
struct sk_buff *_skb;
317+
u16 cong_link_cnt;
318+
int rc = 0;
319319

320320
/* Is a cluster supporting with new capabilities ? */
321321
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,
343343
_hdr = buf_msg(_skb);
344344
msg_set_size(_hdr, MCAST_H_SIZE);
345345
msg_set_is_rcast(_hdr, !msg_is_rcast(hdr));
346+
msg_set_errcode(_hdr, TIPC_ERR_NO_PORT);
346347

347348
__skb_queue_head_init(&tmpq);
348349
__skb_queue_tail(&tmpq, _skb);
349350
if (method->rcast)
350-
tipc_bcast_xmit(net, &tmpq, cong_link_cnt);
351+
rc = tipc_bcast_xmit(net, &tmpq, &cong_link_cnt);
351352
else
352-
tipc_rcast_xmit(net, &tmpq, dests, cong_link_cnt);
353+
rc = tipc_rcast_xmit(net, &tmpq, dests, &cong_link_cnt);
353354

354355
/* This queue should normally be empty by now */
355356
__skb_queue_purge(&tmpq);
356357

357-
return 0;
358+
return rc;
358359
}
359360

360361
/* 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,
396397
msg_set_is_rcast(hdr, method->rcast);
397398

398399
/* Switch method ? */
399-
if (rcast != method->rcast)
400-
tipc_mcast_send_sync(net, skb, method,
401-
dests, cong_link_cnt);
400+
if (rcast != method->rcast) {
401+
rc = tipc_mcast_send_sync(net, skb, method, dests);
402+
if (unlikely(rc)) {
403+
pr_err("Unable to send SYN: method %d, rc %d\n",
404+
rcast, rc);
405+
goto exit;
406+
}
407+
}
402408

403409
if (method->rcast)
404410
rc = tipc_rcast_xmit(net, pkts, dests, cong_link_cnt);

0 commit comments

Comments
 (0)