summaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2017-10-13 11:04:32 +0200
committerDavid S. Miller <davem@davemloft.net>2017-10-13 08:46:01 -0700
commit399574d41963285e72ba28dd46783c96316a81d1 (patch)
tree43385ba22e204883b790a6a8344fcba4b203b2b1 /net/tipc/link.c
parent2f487712b89376fce267223bbb0db93d393d4b09 (diff)
downloadlinux-399574d41963285e72ba28dd46783c96316a81d1.tar.bz2
tipc: guarantee delivery of UP event before first broadcast
The following scenario is possible: - A user joins a group, and immediately sends out a broadcast message to its members. - The broadcast message, following a different data path than the initial JOIN message sent out during the joining procedure, arrives to a receiver before the latter.. - The receiver drops the message, since it is not ready to accept any messages until the JOIN has arrived. We avoid this by treating group protocol JOIN messages like unicast messages. - We let them pass through the recipient's multicast input queue, just like ordinary unicasts. - We force the first following broadacst to be sent as replicated unicast and being acknowledged by the recipient before accepting any more broadcast transmissions. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 70a21499804d..723dd6998684 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1039,6 +1039,7 @@ int tipc_link_retrans(struct tipc_link *l, struct tipc_link *nacker,
static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
struct sk_buff_head *inputq)
{
+ struct sk_buff_head *mc_inputq = l->bc_rcvlink->inputq;
struct tipc_msg *hdr = buf_msg(skb);
switch (msg_user(hdr)) {
@@ -1047,12 +1048,14 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
case TIPC_HIGH_IMPORTANCE:
case TIPC_CRITICAL_IMPORTANCE:
if (unlikely(msg_in_group(hdr) || msg_mcast(hdr))) {
- skb_queue_tail(l->bc_rcvlink->inputq, skb);
+ skb_queue_tail(mc_inputq, skb);
return true;
}
- case GROUP_PROTOCOL:
case CONN_MANAGER:
return true;
+ case GROUP_PROTOCOL:
+ skb_queue_tail(mc_inputq, skb);
+ return true;
case NAME_DISTRIBUTOR:
l->bc_rcvlink->state = LINK_ESTABLISHED;
skb_queue_tail(l->namedq, skb);