aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/group.c87
-rw-r--r--net/tipc/socket.c2
2 files changed, 74 insertions, 15 deletions
diff --git a/net/tipc/group.c b/net/tipc/group.c
index ffac2f33fce2..985e0ce32e8e 100644
--- a/net/tipc/group.c
+++ b/net/tipc/group.c
@@ -62,6 +62,7 @@ struct tipc_member {
62 struct list_head list; 62 struct list_head list;
63 struct list_head congested; 63 struct list_head congested;
64 struct sk_buff *event_msg; 64 struct sk_buff *event_msg;
65 struct sk_buff_head deferredq;
65 struct tipc_group *group; 66 struct tipc_group *group;
66 u32 node; 67 u32 node;
67 u32 port; 68 u32 port;
@@ -253,6 +254,7 @@ static struct tipc_member *tipc_group_create_member(struct tipc_group *grp,
253 return NULL; 254 return NULL;
254 INIT_LIST_HEAD(&m->list); 255 INIT_LIST_HEAD(&m->list);
255 INIT_LIST_HEAD(&m->congested); 256 INIT_LIST_HEAD(&m->congested);
257 __skb_queue_head_init(&m->deferredq);
256 m->group = grp; 258 m->group = grp;
257 m->node = node; 259 m->node = node;
258 m->port = port; 260 m->port = port;
@@ -380,29 +382,54 @@ bool tipc_group_bc_cong(struct tipc_group *grp, int len)
380 return tipc_group_cong(grp, m->node, m->port, len, &m); 382 return tipc_group_cong(grp, m->node, m->port, len, &m);
381} 383}
382 384
385/* tipc_group_sort_msg() - sort msg into queue by bcast sequence number
386 */
387static void tipc_group_sort_msg(struct sk_buff *skb, struct sk_buff_head *defq)
388{
389 struct tipc_msg *_hdr, *hdr = buf_msg(skb);
390 u16 bc_seqno = msg_grp_bc_seqno(hdr);
391 struct sk_buff *_skb, *tmp;
392 int mtyp = msg_type(hdr);
393
394 /* Bcast may be bypassed by unicast, - sort it in */
395 if (mtyp == TIPC_GRP_BCAST_MSG || mtyp == TIPC_GRP_MCAST_MSG) {
396 skb_queue_walk_safe(defq, _skb, tmp) {
397 _hdr = buf_msg(_skb);
398 if (!less(bc_seqno, msg_grp_bc_seqno(_hdr)))
399 continue;
400 __skb_queue_before(defq, _skb, skb);
401 return;
402 }
403 /* Bcast was not bypassed, - add to tail */
404 }
405 /* Unicasts are never bypassed, - always add to tail */
406 __skb_queue_tail(defq, skb);
407}
408
383/* tipc_group_filter_msg() - determine if we should accept arriving message 409/* tipc_group_filter_msg() - determine if we should accept arriving message
384 */ 410 */
385void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq, 411void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,
386 struct sk_buff_head *xmitq) 412 struct sk_buff_head *xmitq)
387{ 413{
388 struct sk_buff *skb = __skb_dequeue(inputq); 414 struct sk_buff *skb = __skb_dequeue(inputq);
415 struct sk_buff_head *defq;
389 struct tipc_member *m; 416 struct tipc_member *m;
390 struct tipc_msg *hdr; 417 struct tipc_msg *hdr;
418 bool deliver, update;
391 u32 node, port; 419 u32 node, port;
392 int mtyp; 420 int mtyp, blks;
393 421
394 if (!skb) 422 if (!skb)
395 return; 423 return;
396 424
397 hdr = buf_msg(skb); 425 hdr = buf_msg(skb);
398 mtyp = msg_type(hdr);
399 node = msg_orignode(hdr); 426 node = msg_orignode(hdr);
400 port = msg_origport(hdr); 427 port = msg_origport(hdr);
401 428
402 if (!msg_in_group(hdr)) 429 if (!msg_in_group(hdr))
403 goto drop; 430 goto drop;
404 431
405 if (mtyp == TIPC_GRP_MEMBER_EVT) { 432 if (msg_is_grp_evt(hdr)) {
406 if (!grp->events) 433 if (!grp->events)
407 goto drop; 434 goto drop;
408 __skb_queue_tail(inputq, skb); 435 __skb_queue_tail(inputq, skb);
@@ -413,22 +440,52 @@ void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,
413 if (!tipc_group_is_receiver(m)) 440 if (!tipc_group_is_receiver(m))
414 goto drop; 441 goto drop;
415 442
416 m->bc_rcv_nxt = msg_grp_bc_seqno(hdr) + 1; 443 if (less(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
444 goto drop;
417 445
418 /* Drop multicast here if not for this member */ 446 TIPC_SKB_CB(skb)->orig_member = m->instance;
419 if (mtyp == TIPC_GRP_MCAST_MSG) { 447 defq = &m->deferredq;
420 if (msg_nameinst(hdr) != grp->instance) { 448 tipc_group_sort_msg(skb, defq);
421 m->bc_rcv_nxt = msg_grp_bc_seqno(hdr) + 1; 449
422 tipc_group_update_rcv_win(grp, msg_blocks(hdr), 450 while ((skb = skb_peek(defq))) {
423 node, port, xmitq); 451 hdr = buf_msg(skb);
424 kfree_skb(skb); 452 mtyp = msg_type(hdr);
425 return; 453 deliver = true;
454 update = false;
455
456 if (more(msg_grp_bc_seqno(hdr), m->bc_rcv_nxt))
457 break;
458
459 /* Decide what to do with message */
460 switch (mtyp) {
461 case TIPC_GRP_MCAST_MSG:
462 if (msg_nameinst(hdr) != grp->instance) {
463 update = true;
464 deliver = false;
465 }
466 /* Fall thru */
467 case TIPC_GRP_BCAST_MSG:
468 m->bc_rcv_nxt++;
469 break;
470 case TIPC_GRP_UCAST_MSG:
471 break;
472 default:
473 break;
426 } 474 }
427 }
428 475
429 TIPC_SKB_CB(skb)->orig_member = m->instance; 476 /* Execute decisions */
430 __skb_queue_tail(inputq, skb); 477 __skb_dequeue(defq);
478 if (deliver)
479 __skb_queue_tail(inputq, skb);
480 else
481 kfree_skb(skb);
482
483 if (!update)
484 continue;
431 485
486 blks = msg_blocks(hdr);
487 tipc_group_update_rcv_win(grp, blks, node, port, xmitq);
488 }
432 return; 489 return;
433drop: 490drop:
434 kfree_skb(skb); 491 kfree_skb(skb);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 8fdd969e12bd..3276b7a0d445 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -830,6 +830,7 @@ static int tipc_send_group_msg(struct net *net, struct tipc_sock *tsk,
830 struct msghdr *m, struct tipc_member *mb, 830 struct msghdr *m, struct tipc_member *mb,
831 u32 dnode, u32 dport, int dlen) 831 u32 dnode, u32 dport, int dlen)
832{ 832{
833 u16 bc_snd_nxt = tipc_group_bc_snd_nxt(tsk->group);
833 int blks = tsk_blocks(GROUP_H_SIZE + dlen); 834 int blks = tsk_blocks(GROUP_H_SIZE + dlen);
834 struct tipc_msg *hdr = &tsk->phdr; 835 struct tipc_msg *hdr = &tsk->phdr;
835 struct sk_buff_head pkts; 836 struct sk_buff_head pkts;
@@ -840,6 +841,7 @@ static int tipc_send_group_msg(struct net *net, struct tipc_sock *tsk,
840 msg_set_hdr_sz(hdr, GROUP_H_SIZE); 841 msg_set_hdr_sz(hdr, GROUP_H_SIZE);
841 msg_set_destport(hdr, dport); 842 msg_set_destport(hdr, dport);
842 msg_set_destnode(hdr, dnode); 843 msg_set_destnode(hdr, dnode);
844 msg_set_grp_bc_seqno(hdr, bc_snd_nxt);
843 845
844 /* Build message as chain of buffers */ 846 /* Build message as chain of buffers */
845 skb_queue_head_init(&pkts); 847 skb_queue_head_init(&pkts);