aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/tipc/link.c38
-rw-r--r--net/tipc/link.h7
-rw-r--r--net/tipc/msg.h1
3 files changed, 34 insertions, 12 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index f0cf768a59f3..dfc738e5cff9 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -221,6 +221,7 @@ bool tipc_link_create(struct tipc_node *n, char *if_name, int bearer_id,
221 l->mtu = mtu; 221 l->mtu = mtu;
222 l->priority = priority; 222 l->priority = priority;
223 tipc_link_set_queue_limits(l, window); 223 tipc_link_set_queue_limits(l, window);
224 l->ackers = 1;
224 l->inputq = inputq; 225 l->inputq = inputq;
225 l->namedq = namedq; 226 l->namedq = namedq;
226 l->state = LINK_RESETTING; 227 l->state = LINK_RESETTING;
@@ -647,6 +648,7 @@ void tipc_link_reset(struct tipc_link *l)
647 l->rcv_unacked = 0; 648 l->rcv_unacked = 0;
648 l->snd_nxt = 1; 649 l->snd_nxt = 1;
649 l->rcv_nxt = 1; 650 l->rcv_nxt = 1;
651 l->acked = 0;
650 l->silent_intv_cnt = 0; 652 l->silent_intv_cnt = 0;
651 l->stats.recv_info = 0; 653 l->stats.recv_info = 0;
652 l->stale_count = 0; 654 l->stale_count = 0;
@@ -769,6 +771,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
769 __skb_dequeue(list); 771 __skb_dequeue(list);
770 __skb_queue_tail(transmq, skb); 772 __skb_queue_tail(transmq, skb);
771 __skb_queue_tail(xmitq, _skb); 773 __skb_queue_tail(xmitq, _skb);
774 TIPC_SKB_CB(skb)->ackers = l->ackers;
772 l->rcv_unacked = 0; 775 l->rcv_unacked = 0;
773 seqno++; 776 seqno++;
774 continue; 777 continue;
@@ -829,6 +832,7 @@ void tipc_link_push_packets(struct tipc_link *link)
829 skb = __skb_dequeue(&link->backlogq); 832 skb = __skb_dequeue(&link->backlogq);
830 if (!skb) 833 if (!skb)
831 break; 834 break;
835 TIPC_SKB_CB(skb)->ackers = link->ackers;
832 msg = buf_msg(skb); 836 msg = buf_msg(skb);
833 link->backlog[msg_importance(msg)].len--; 837 link->backlog[msg_importance(msg)].len--;
834 msg_set_ack(msg, ack); 838 msg_set_ack(msg, ack);
@@ -862,6 +866,7 @@ void tipc_link_advance_backlog(struct tipc_link *l, struct sk_buff_head *xmitq)
862 l->backlog[msg_importance(hdr)].len--; 866 l->backlog[msg_importance(hdr)].len--;
863 __skb_queue_tail(&l->transmq, skb); 867 __skb_queue_tail(&l->transmq, skb);
864 __skb_queue_tail(xmitq, _skb); 868 __skb_queue_tail(xmitq, _skb);
869 TIPC_SKB_CB(skb)->ackers = l->ackers;
865 msg_set_ack(hdr, ack); 870 msg_set_ack(hdr, ack);
866 msg_set_seqno(hdr, seqno); 871 msg_set_seqno(hdr, seqno);
867 msg_set_bcast_ack(hdr, l->owner->bclink.last_in); 872 msg_set_bcast_ack(hdr, l->owner->bclink.last_in);
@@ -947,11 +952,13 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *skb,
947 } 952 }
948} 953}
949 954
950static int tipc_link_retransm(struct tipc_link *l, int retransm, 955int tipc_link_retrans(struct tipc_link *l, u16 from, u16 to,
951 struct sk_buff_head *xmitq) 956 struct sk_buff_head *xmitq)
952{ 957{
953 struct sk_buff *_skb, *skb = skb_peek(&l->transmq); 958 struct sk_buff *_skb, *skb = skb_peek(&l->transmq);
954 struct tipc_msg *hdr; 959 struct tipc_msg *hdr;
960 u16 ack = l->rcv_nxt - 1;
961 u16 bc_ack = l->owner->bclink.last_in;
955 962
956 if (!skb) 963 if (!skb)
957 return 0; 964 return 0;
@@ -964,19 +971,25 @@ static int tipc_link_retransm(struct tipc_link *l, int retransm,
964 link_retransmit_failure(l, skb); 971 link_retransmit_failure(l, skb);
965 return tipc_link_fsm_evt(l, LINK_FAILURE_EVT); 972 return tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
966 } 973 }
974
975 /* Move forward to where retransmission should start */
967 skb_queue_walk(&l->transmq, skb) { 976 skb_queue_walk(&l->transmq, skb) {
968 if (!retransm) 977 if (!less(buf_seqno(skb), from))
969 return 0; 978 break;
979 }
980
981 skb_queue_walk_from(&l->transmq, skb) {
982 if (more(buf_seqno(skb), to))
983 break;
970 hdr = buf_msg(skb); 984 hdr = buf_msg(skb);
971 _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC); 985 _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC);
972 if (!_skb) 986 if (!_skb)
973 return 0; 987 return 0;
974 hdr = buf_msg(_skb); 988 hdr = buf_msg(_skb);
975 msg_set_ack(hdr, l->rcv_nxt - 1); 989 msg_set_ack(hdr, ack);
976 msg_set_bcast_ack(hdr, l->owner->bclink.last_in); 990 msg_set_bcast_ack(hdr, bc_ack);
977 _skb->priority = TC_PRIO_CONTROL; 991 _skb->priority = TC_PRIO_CONTROL;
978 __skb_queue_tail(xmitq, _skb); 992 __skb_queue_tail(xmitq, _skb);
979 retransm--;
980 l->stats.retransmitted++; 993 l->stats.retransmitted++;
981 } 994 }
982 return 0; 995 return 0;
@@ -1390,7 +1403,8 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1390{ 1403{
1391 struct tipc_msg *hdr = buf_msg(skb); 1404 struct tipc_msg *hdr = buf_msg(skb);
1392 u16 rcvgap = 0; 1405 u16 rcvgap = 0;
1393 u16 nacked_gap = msg_seq_gap(hdr); 1406 u16 ack = msg_ack(hdr);
1407 u16 gap = msg_seq_gap(hdr);
1394 u16 peers_snd_nxt = msg_next_sent(hdr); 1408 u16 peers_snd_nxt = msg_next_sent(hdr);
1395 u16 peers_tol = msg_link_tolerance(hdr); 1409 u16 peers_tol = msg_link_tolerance(hdr);
1396 u16 peers_prio = msg_linkprio(hdr); 1410 u16 peers_prio = msg_linkprio(hdr);
@@ -1469,11 +1483,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1469 if (rcvgap || (msg_probe(hdr))) 1483 if (rcvgap || (msg_probe(hdr)))
1470 tipc_link_build_proto_msg(l, STATE_MSG, 0, rcvgap, 1484 tipc_link_build_proto_msg(l, STATE_MSG, 0, rcvgap,
1471 0, 0, xmitq); 1485 0, 0, xmitq);
1472 tipc_link_release_pkts(l, msg_ack(hdr)); 1486 tipc_link_release_pkts(l, ack);
1473 1487
1474 /* If NACK, retransmit will now start at right position */ 1488 /* If NACK, retransmit will now start at right position */
1475 if (nacked_gap) { 1489 if (gap) {
1476 rc = tipc_link_retransm(l, nacked_gap, xmitq); 1490 rc = tipc_link_retrans(l, ack + 1, ack + gap, xmitq);
1477 l->stats.recv_nacks++; 1491 l->stats.recv_nacks++;
1478 } 1492 }
1479 1493
@@ -1550,7 +1564,7 @@ static void link_reset_statistics(struct tipc_link *l_ptr)
1550static void link_print(struct tipc_link *l, const char *str) 1564static void link_print(struct tipc_link *l, const char *str)
1551{ 1565{
1552 struct sk_buff *hskb = skb_peek(&l->transmq); 1566 struct sk_buff *hskb = skb_peek(&l->transmq);
1553 u16 head = hskb ? msg_seqno(buf_msg(hskb)) : l->snd_nxt; 1567 u16 head = hskb ? msg_seqno(buf_msg(hskb)) : l->snd_nxt - 1;
1554 u16 tail = l->snd_nxt - 1; 1568 u16 tail = l->snd_nxt - 1;
1555 1569
1556 pr_info("%s Link <%s> state %x\n", str, l->name, l->state); 1570 pr_info("%s Link <%s> state %x\n", str, l->name, l->state);
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 9e4e3673da76..be24d1fd5132 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -134,6 +134,8 @@ struct tipc_stats {
134 * @snt_nxt: next sequence number to use for outbound messages 134 * @snt_nxt: next sequence number to use for outbound messages
135 * @last_retransmitted: sequence number of most recently retransmitted message 135 * @last_retransmitted: sequence number of most recently retransmitted message
136 * @stale_count: # of identical retransmit requests made by peer 136 * @stale_count: # of identical retransmit requests made by peer
137 * @ackers: # of peers that needs to ack each packet before it can be released
138 * @acked: # last packet acked by a certain peer. Used for broadcast.
137 * @rcv_nxt: next sequence number to expect for inbound messages 139 * @rcv_nxt: next sequence number to expect for inbound messages
138 * @deferred_queue: deferred queue saved OOS b'cast message received from node 140 * @deferred_queue: deferred queue saved OOS b'cast message received from node
139 * @unacked_window: # of inbound messages rx'd without ack'ing back to peer 141 * @unacked_window: # of inbound messages rx'd without ack'ing back to peer
@@ -143,6 +145,7 @@ struct tipc_stats {
143 * @wakeupq: linked list of wakeup msgs waiting for link congestion to abate 145 * @wakeupq: linked list of wakeup msgs waiting for link congestion to abate
144 * @long_msg_seq_no: next identifier to use for outbound fragmented messages 146 * @long_msg_seq_no: next identifier to use for outbound fragmented messages
145 * @reasm_buf: head of partially reassembled inbound message fragments 147 * @reasm_buf: head of partially reassembled inbound message fragments
148 * @bc_rcvr: marks that this is a broadcast receiver link
146 * @stats: collects statistics regarding link activity 149 * @stats: collects statistics regarding link activity
147 */ 150 */
148struct tipc_link { 151struct tipc_link {
@@ -201,6 +204,10 @@ struct tipc_link {
201 /* Fragmentation/reassembly */ 204 /* Fragmentation/reassembly */
202 struct sk_buff *reasm_buf; 205 struct sk_buff *reasm_buf;
203 206
207 /* Broadcast */
208 u16 ackers;
209 u16 acked;
210
204 /* Statistics */ 211 /* Statistics */
205 struct tipc_stats stats; 212 struct tipc_stats stats;
206}; 213};
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 9f0ef54be612..799782c47f6c 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -112,6 +112,7 @@ struct tipc_skb_cb {
112 bool wakeup_pending; 112 bool wakeup_pending;
113 u16 chain_sz; 113 u16 chain_sz;
114 u16 chain_imp; 114 u16 chain_imp;
115 u16 ackers;
115}; 116};
116 117
117#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) 118#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))