diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3276b7a0d445..b1f1c3c2b1e2 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -831,6 +831,7 @@ static int tipc_send_group_msg(struct net *net, struct tipc_sock *tsk, | |||
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 | u16 bc_snd_nxt = tipc_group_bc_snd_nxt(tsk->group); |
834 | struct tipc_mc_method *method = &tsk->mc_method; | ||
834 | int blks = tsk_blocks(GROUP_H_SIZE + dlen); | 835 | int blks = tsk_blocks(GROUP_H_SIZE + dlen); |
835 | struct tipc_msg *hdr = &tsk->phdr; | 836 | struct tipc_msg *hdr = &tsk->phdr; |
836 | struct sk_buff_head pkts; | 837 | struct sk_buff_head pkts; |
@@ -857,9 +858,12 @@ static int tipc_send_group_msg(struct net *net, struct tipc_sock *tsk, | |||
857 | tsk->cong_link_cnt++; | 858 | tsk->cong_link_cnt++; |
858 | } | 859 | } |
859 | 860 | ||
860 | /* Update send window and sequence number */ | 861 | /* Update send window */ |
861 | tipc_group_update_member(mb, blks); | 862 | tipc_group_update_member(mb, blks); |
862 | 863 | ||
864 | /* A broadcast sent within next EXPIRE period must follow same path */ | ||
865 | method->rcast = true; | ||
866 | method->mandatory = true; | ||
863 | return dlen; | 867 | return dlen; |
864 | } | 868 | } |
865 | 869 | ||
@@ -1008,6 +1012,7 @@ static int tipc_send_group_bcast(struct socket *sock, struct msghdr *m, | |||
1008 | struct tipc_group *grp = tsk->group; | 1012 | struct tipc_group *grp = tsk->group; |
1009 | struct tipc_nlist *dsts = tipc_group_dests(grp); | 1013 | struct tipc_nlist *dsts = tipc_group_dests(grp); |
1010 | struct tipc_mc_method *method = &tsk->mc_method; | 1014 | struct tipc_mc_method *method = &tsk->mc_method; |
1015 | bool ack = method->mandatory && method->rcast; | ||
1011 | int blks = tsk_blocks(MCAST_H_SIZE + dlen); | 1016 | int blks = tsk_blocks(MCAST_H_SIZE + dlen); |
1012 | struct tipc_msg *hdr = &tsk->phdr; | 1017 | struct tipc_msg *hdr = &tsk->phdr; |
1013 | int mtu = tipc_bcast_get_mtu(net); | 1018 | int mtu = tipc_bcast_get_mtu(net); |
@@ -1036,6 +1041,9 @@ static int tipc_send_group_bcast(struct socket *sock, struct msghdr *m, | |||
1036 | msg_set_destnode(hdr, 0); | 1041 | msg_set_destnode(hdr, 0); |
1037 | msg_set_grp_bc_seqno(hdr, tipc_group_bc_snd_nxt(grp)); | 1042 | msg_set_grp_bc_seqno(hdr, tipc_group_bc_snd_nxt(grp)); |
1038 | 1043 | ||
1044 | /* Avoid getting stuck with repeated forced replicasts */ | ||
1045 | msg_set_grp_bc_ack_req(hdr, ack); | ||
1046 | |||
1039 | /* Build message as chain of buffers */ | 1047 | /* Build message as chain of buffers */ |
1040 | skb_queue_head_init(&pkts); | 1048 | skb_queue_head_init(&pkts); |
1041 | rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts); | 1049 | rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts); |
@@ -1043,13 +1051,17 @@ static int tipc_send_group_bcast(struct socket *sock, struct msghdr *m, | |||
1043 | return rc; | 1051 | return rc; |
1044 | 1052 | ||
1045 | /* Send message */ | 1053 | /* Send message */ |
1046 | rc = tipc_mcast_xmit(net, &pkts, method, dsts, | 1054 | rc = tipc_mcast_xmit(net, &pkts, method, dsts, &tsk->cong_link_cnt); |
1047 | &tsk->cong_link_cnt); | ||
1048 | if (unlikely(rc)) | 1055 | if (unlikely(rc)) |
1049 | return rc; | 1056 | return rc; |
1050 | 1057 | ||
1051 | /* Update broadcast sequence number and send windows */ | 1058 | /* Update broadcast sequence number and send windows */ |
1052 | tipc_group_update_bc_members(tsk->group, blks); | 1059 | tipc_group_update_bc_members(tsk->group, blks, ack); |
1060 | |||
1061 | /* Broadcast link is now free to choose method for next broadcast */ | ||
1062 | method->mandatory = false; | ||
1063 | method->expires = jiffies; | ||
1064 | |||
1053 | return dlen; | 1065 | return dlen; |
1054 | } | 1066 | } |
1055 | 1067 | ||
@@ -1113,7 +1125,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, | |||
1113 | u32 portid, oport, onode; | 1125 | u32 portid, oport, onode; |
1114 | struct list_head dports; | 1126 | struct list_head dports; |
1115 | struct tipc_msg *msg; | 1127 | struct tipc_msg *msg; |
1116 | int hsz; | 1128 | int user, mtyp, hsz; |
1117 | 1129 | ||
1118 | __skb_queue_head_init(&tmpq); | 1130 | __skb_queue_head_init(&tmpq); |
1119 | INIT_LIST_HEAD(&dports); | 1131 | INIT_LIST_HEAD(&dports); |
@@ -1121,6 +1133,18 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, | |||
1121 | skb = tipc_skb_peek(arrvq, &inputq->lock); | 1133 | skb = tipc_skb_peek(arrvq, &inputq->lock); |
1122 | for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { | 1134 | for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) { |
1123 | msg = buf_msg(skb); | 1135 | msg = buf_msg(skb); |
1136 | user = msg_user(msg); | ||
1137 | mtyp = msg_type(msg); | ||
1138 | if (mtyp == TIPC_GRP_UCAST_MSG || user == GROUP_PROTOCOL) { | ||
1139 | spin_lock_bh(&inputq->lock); | ||
1140 | if (skb_peek(arrvq) == skb) { | ||
1141 | __skb_dequeue(arrvq); | ||
1142 | __skb_queue_tail(inputq, skb); | ||
1143 | } | ||
1144 | refcount_dec(&skb->users); | ||
1145 | spin_unlock_bh(&inputq->lock); | ||
1146 | continue; | ||
1147 | } | ||
1124 | hsz = skb_headroom(skb) + msg_hdr_sz(msg); | 1148 | hsz = skb_headroom(skb) + msg_hdr_sz(msg); |
1125 | oport = msg_origport(msg); | 1149 | oport = msg_origport(msg); |
1126 | onode = msg_orignode(msg); | 1150 | onode = msg_orignode(msg); |