Skip to content

Commit 0228824

Browse files
Jon Maloydavem330
authored andcommitted
tipc: eliminate gap indicator from ACK messages
When we increase the link send window we sometimes observe the following scenario: 1) A packet #N arrives out of order far ahead of a sequence of older packets which are still under way. The packet is added to the deferred queue. 2) The missing packets arrive in sequence, and for each 16th of them an ACK is sent back to the receiver, as it should be. 3) When building those ACK messages, it is checked if there is a gap between the link's 'rcv_nxt' and the first packet in the deferred queue. This is always the case until packet number #N-1 arrives, and a 'gap' indicator is added, effectively turning them into NACK messages. 4) When those NACKs arrive at the sender, all the requested retransmissions are done, since it is a first-time request. This sometimes leads to a huge amount of redundant retransmissions, causing a drop in max throughput. This problem gets worse when we in a later commit introduce variable window congestion control, since it drops the link back to 'fast recovery' much more often than necessary. We now fix this by not sending any 'gap' indicator in regular ACK messages. We already have a mechanism for sending explicit NACKs in place, and this is sufficient to keep up the packet flow. Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 08cbc75 commit 0228824

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

net/tipc/link.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,7 +1521,8 @@ static int tipc_link_build_nack_msg(struct tipc_link *l,
15211521
struct sk_buff_head *xmitq)
15221522
{
15231523
u32 def_cnt = ++l->stats.deferred_recv;
1524-
u32 defq_len = skb_queue_len(&l->deferdq);
1524+
struct sk_buff_head *dfq = &l->deferdq;
1525+
u32 defq_len = skb_queue_len(dfq);
15251526
int match1, match2;
15261527

15271528
if (link_is_bc_rcvlink(l)) {
@@ -1532,8 +1533,12 @@ static int tipc_link_build_nack_msg(struct tipc_link *l,
15321533
return 0;
15331534
}
15341535

1535-
if (defq_len >= 3 && !((defq_len - 3) % 16))
1536-
tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, 0, xmitq);
1536+
if (defq_len >= 3 && !((defq_len - 3) % 16)) {
1537+
u16 rcvgap = buf_seqno(skb_peek(dfq)) - l->rcv_nxt;
1538+
1539+
tipc_link_build_proto_msg(l, STATE_MSG, 0, 0,
1540+
rcvgap, 0, 0, xmitq);
1541+
}
15371542
return 0;
15381543
}
15391544

@@ -1631,7 +1636,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
16311636
if (!tipc_link_is_up(l) && (mtyp == STATE_MSG))
16321637
return;
16331638

1634-
if (!skb_queue_empty(dfq))
1639+
if ((probe || probe_reply) && !skb_queue_empty(dfq))
16351640
rcvgap = buf_seqno(skb_peek(dfq)) - l->rcv_nxt;
16361641

16371642
skb = tipc_msg_create(LINK_PROTOCOL, mtyp, INT_H_SIZE,
@@ -2079,7 +2084,6 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
20792084
if (rcvgap || reply)
20802085
tipc_link_build_proto_msg(l, STATE_MSG, 0, reply,
20812086
rcvgap, 0, 0, xmitq);
2082-
20832087
rc |= tipc_link_advance_transmq(l, ack, gap, ga, xmitq);
20842088

20852089
/* If NACK, retransmit will now start at right position */

0 commit comments

Comments
 (0)