aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-02-05 19:00:06 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-05 19:00:06 -0500
commit7d231e3f762b4cbb0d91f284f3aa6d47a8e83e28 (patch)
tree1b1e50e705f4ddd3b36a43ac9067538db3e8233f
parent4134069f3ea6cd96903e426bd3dfb9bb44165357 (diff)
parentcb1b728096f54e7408d60fb571944bed00c5b771 (diff)
Merge branch 'tipc-next'
Jon Maloy says: ==================== tipc: resolve message disordering problem When TIPC receives messages from multi-threaded device drivers it may occasionally deliver messages to their destination sockets in the wrong order. This happens despite correct resequencing at the link layer, because the upcall path from link to socket is not protected by any locks. These commits solve this problem by introducing an 'input' message queue in each link, through which messages must be delivered to the upper layers. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/tipc/bcast.c121
-rw-r--r--net/tipc/bcast.h29
-rw-r--r--net/tipc/discover.c3
-rw-r--r--net/tipc/link.c301
-rw-r--r--net/tipc/link.h14
-rw-r--r--net/tipc/msg.c109
-rw-r--r--net/tipc/msg.h107
-rw-r--r--net/tipc/name_distr.c38
-rw-r--r--net/tipc/name_distr.h2
-rw-r--r--net/tipc/name_table.c44
-rw-r--r--net/tipc/name_table.h20
-rw-r--r--net/tipc/node.c103
-rw-r--r--net/tipc/node.h22
-rw-r--r--net/tipc/socket.c382
-rw-r--r--net/tipc/socket.h8
15 files changed, 740 insertions, 563 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 53f8bf059fec..81b1fef1f5e0 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/bcast.c: TIPC broadcast code 2 * net/tipc/bcast.c: TIPC broadcast code
3 * 3 *
4 * Copyright (c) 2004-2006, 2014, Ericsson AB 4 * Copyright (c) 2004-2006, 2014-2015, Ericsson AB
5 * Copyright (c) 2004, Intel Corporation. 5 * Copyright (c) 2004, Intel Corporation.
6 * Copyright (c) 2005, 2010-2011, Wind River Systems 6 * Copyright (c) 2005, 2010-2011, Wind River Systems
7 * All rights reserved. 7 * All rights reserved.
@@ -79,6 +79,13 @@ static void tipc_bclink_unlock(struct net *net)
79 tipc_link_reset_all(node); 79 tipc_link_reset_all(node);
80} 80}
81 81
82void tipc_bclink_input(struct net *net)
83{
84 struct tipc_net *tn = net_generic(net, tipc_net_id);
85
86 tipc_sk_mcast_rcv(net, &tn->bclink->arrvq, &tn->bclink->inputq);
87}
88
82uint tipc_bclink_get_mtu(void) 89uint tipc_bclink_get_mtu(void)
83{ 90{
84 return MAX_PKT_DEFAULT_MCAST; 91 return MAX_PKT_DEFAULT_MCAST;
@@ -189,10 +196,8 @@ static void bclink_retransmit_pkt(struct tipc_net *tn, u32 after, u32 to)
189void tipc_bclink_wakeup_users(struct net *net) 196void tipc_bclink_wakeup_users(struct net *net)
190{ 197{
191 struct tipc_net *tn = net_generic(net, tipc_net_id); 198 struct tipc_net *tn = net_generic(net, tipc_net_id);
192 struct sk_buff *skb;
193 199
194 while ((skb = skb_dequeue(&tn->bclink->link.waiting_sks))) 200 tipc_sk_rcv(net, &tn->bclink->link.wakeupq);
195 tipc_sk_rcv(net, skb);
196} 201}
197 202
198/** 203/**
@@ -271,9 +276,8 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked)
271 tipc_link_push_packets(tn->bcl); 276 tipc_link_push_packets(tn->bcl);
272 bclink_set_last_sent(net); 277 bclink_set_last_sent(net);
273 } 278 }
274 if (unlikely(released && !skb_queue_empty(&tn->bcl->waiting_sks))) 279 if (unlikely(released && !skb_queue_empty(&tn->bcl->wakeupq)))
275 n_ptr->action_flags |= TIPC_WAKEUP_BCAST_USERS; 280 n_ptr->action_flags |= TIPC_WAKEUP_BCAST_USERS;
276
277exit: 281exit:
278 tipc_bclink_unlock(net); 282 tipc_bclink_unlock(net);
279} 283}
@@ -283,10 +287,11 @@ exit:
283 * 287 *
284 * RCU and node lock set 288 * RCU and node lock set
285 */ 289 */
286void tipc_bclink_update_link_state(struct net *net, struct tipc_node *n_ptr, 290void tipc_bclink_update_link_state(struct tipc_node *n_ptr,
287 u32 last_sent) 291 u32 last_sent)
288{ 292{
289 struct sk_buff *buf; 293 struct sk_buff *buf;
294 struct net *net = n_ptr->net;
290 struct tipc_net *tn = net_generic(net, tipc_net_id); 295 struct tipc_net *tn = net_generic(net, tipc_net_id);
291 296
292 /* Ignore "stale" link state info */ 297 /* Ignore "stale" link state info */
@@ -317,7 +322,7 @@ void tipc_bclink_update_link_state(struct net *net, struct tipc_node *n_ptr,
317 struct sk_buff *skb = skb_peek(&n_ptr->bclink.deferred_queue); 322 struct sk_buff *skb = skb_peek(&n_ptr->bclink.deferred_queue);
318 u32 to = skb ? buf_seqno(skb) - 1 : n_ptr->bclink.last_sent; 323 u32 to = skb ? buf_seqno(skb) - 1 : n_ptr->bclink.last_sent;
319 324
320 tipc_msg_init(net, msg, BCAST_PROTOCOL, STATE_MSG, 325 tipc_msg_init(tn->own_addr, msg, BCAST_PROTOCOL, STATE_MSG,
321 INT_H_SIZE, n_ptr->addr); 326 INT_H_SIZE, n_ptr->addr);
322 msg_set_non_seq(msg, 1); 327 msg_set_non_seq(msg, 1);
323 msg_set_mc_netid(msg, tn->net_id); 328 msg_set_mc_netid(msg, tn->net_id);
@@ -358,7 +363,7 @@ static void bclink_peek_nack(struct net *net, struct tipc_msg *msg)
358 tipc_node_unlock(n_ptr); 363 tipc_node_unlock(n_ptr);
359} 364}
360 365
361/* tipc_bclink_xmit - broadcast buffer chain to all nodes in cluster 366/* tipc_bclink_xmit - deliver buffer chain to all nodes in cluster
362 * and to identified node local sockets 367 * and to identified node local sockets
363 * @net: the applicable net namespace 368 * @net: the applicable net namespace
364 * @list: chain of buffers containing message 369 * @list: chain of buffers containing message
@@ -373,6 +378,8 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list)
373 int rc = 0; 378 int rc = 0;
374 int bc = 0; 379 int bc = 0;
375 struct sk_buff *skb; 380 struct sk_buff *skb;
381 struct sk_buff_head arrvq;
382 struct sk_buff_head inputq;
376 383
377 /* Prepare clone of message for local node */ 384 /* Prepare clone of message for local node */
378 skb = tipc_msg_reassemble(list); 385 skb = tipc_msg_reassemble(list);
@@ -381,7 +388,7 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list)
381 return -EHOSTUNREACH; 388 return -EHOSTUNREACH;
382 } 389 }
383 390
384 /* Broadcast to all other nodes */ 391 /* Broadcast to all nodes */
385 if (likely(bclink)) { 392 if (likely(bclink)) {
386 tipc_bclink_lock(net); 393 tipc_bclink_lock(net);
387 if (likely(bclink->bcast_nodes.count)) { 394 if (likely(bclink->bcast_nodes.count)) {
@@ -401,12 +408,15 @@ int tipc_bclink_xmit(struct net *net, struct sk_buff_head *list)
401 if (unlikely(!bc)) 408 if (unlikely(!bc))
402 __skb_queue_purge(list); 409 __skb_queue_purge(list);
403 410
404 /* Deliver message clone */ 411 if (unlikely(rc)) {
405 if (likely(!rc))
406 tipc_sk_mcast_rcv(net, skb);
407 else
408 kfree_skb(skb); 412 kfree_skb(skb);
409 413 return rc;
414 }
415 /* Deliver message clone */
416 __skb_queue_head_init(&arrvq);
417 skb_queue_head_init(&inputq);
418 __skb_queue_tail(&arrvq, skb);
419 tipc_sk_mcast_rcv(net, &arrvq, &inputq);
410 return rc; 420 return rc;
411} 421}
412 422
@@ -449,6 +459,9 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf)
449 u32 next_in; 459 u32 next_in;
450 u32 seqno; 460 u32 seqno;
451 int deferred = 0; 461 int deferred = 0;
462 int pos = 0;
463 struct sk_buff *iskb;
464 struct sk_buff_head *arrvq, *inputq;
452 465
453 /* Screen out unwanted broadcast messages */ 466 /* Screen out unwanted broadcast messages */
454 if (msg_mc_netid(msg) != tn->net_id) 467 if (msg_mc_netid(msg) != tn->net_id)
@@ -485,6 +498,8 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf)
485 /* Handle in-sequence broadcast message */ 498 /* Handle in-sequence broadcast message */
486 seqno = msg_seqno(msg); 499 seqno = msg_seqno(msg);
487 next_in = mod(node->bclink.last_in + 1); 500 next_in = mod(node->bclink.last_in + 1);
501 arrvq = &tn->bclink->arrvq;
502 inputq = &tn->bclink->inputq;
488 503
489 if (likely(seqno == next_in)) { 504 if (likely(seqno == next_in)) {
490receive: 505receive:
@@ -492,20 +507,26 @@ receive:
492 if (likely(msg_isdata(msg))) { 507 if (likely(msg_isdata(msg))) {
493 tipc_bclink_lock(net); 508 tipc_bclink_lock(net);
494 bclink_accept_pkt(node, seqno); 509 bclink_accept_pkt(node, seqno);
510 spin_lock_bh(&inputq->lock);
511 __skb_queue_tail(arrvq, buf);
512 spin_unlock_bh(&inputq->lock);
513 node->action_flags |= TIPC_BCAST_MSG_EVT;
495 tipc_bclink_unlock(net); 514 tipc_bclink_unlock(net);
496 tipc_node_unlock(node);