aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
authorTuong Lien <tuong.t.lien@dektech.com.au>2019-04-04 00:09:52 -0400
committerDavid S. Miller <davem@davemloft.net>2019-04-04 21:29:25 -0400
commit382f598fb66b14a8451f2794abf70ea7b5826c96 (patch)
tree5d25199c0053b40e74a797c16c2d17dfe29d4479 /net/tipc/link.c
parent9195948fbf3406f75b1f133ddb57304169c44341 (diff)
tipc: reduce duplicate packets for unicast traffic
For unicast transmission, the current NACK sending althorithm is over- active that forces the sending side to retransmit a packet that is not really lost but just arrived at the receiving side with some delay, or even retransmit same packets that have already been retransmitted before. As a result, many duplicates are observed also under normal condition, ie. without packet loss. One example case is: node1 transmits 1 2 3 4 10 5 6 7 8 9, when node2 receives packet #10, it puts into the deferdq. When the packet #5 comes it sends NACK with gap [6 - 9]. However, shortly after that, when packet #6 arrives, it pulls out packet #10 from the deferfq, but it is still out of order, so it makes another NACK with gap [7 - 9] and so on ... Finally, node1 has to retransmit the packets 5 6 7 8 9 a number of times, but in fact all the packets are not lost at all, so duplicates! This commit reduces duplicates by changing the condition to send NACK, also restricting the retransmissions on individual packets via a timer of about 1ms. However, it also needs to say that too tricky condition for NACKs or too long timeout value for retransmissions will result in performance reducing! The criterias in this commit are found to be effective for both the requirements to reduce duplicates but not affect performance. The tipc_link_rcv() is also improved to only dequeue skb from the link deferdq if it is expected (ie. its seqno <= rcv_nxt). Acked-by: Ying Xue <ying.xue@windriver.com> Acked-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: Tuong Lien <tuong.t.lien@dektech.com.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 5aee1ed23ba9..1f2cde0d025f 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -209,6 +209,7 @@ enum {
209}; 209};
210 210
211#define TIPC_BC_RETR_LIM msecs_to_jiffies(10) /* [ms] */ 211#define TIPC_BC_RETR_LIM msecs_to_jiffies(10) /* [ms] */
212#define TIPC_UC_RETR_TIME (jiffies + msecs_to_jiffies(1))
212 213
213/* 214/*
214 * Interval between NACKs when packets arrive out of order 215 * Interval between NACKs when packets arrive out of order
@@ -1305,6 +1306,10 @@ next_gap_ack:
1305 kfree_skb(skb); 1306 kfree_skb(skb);
1306 } else if (less_eq(seqno, acked + gap)) { 1307 } else if (less_eq(seqno, acked + gap)) {
1307 /* retransmit skb */ 1308 /* retransmit skb */
1309 if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr))
1310 continue;
1311 TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME;
1312
1308 _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC); 1313 _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC);
1309 if (!_skb) 1314 if (!_skb)
1310 continue; 1315 continue;
@@ -1380,6 +1385,7 @@ static int tipc_link_build_nack_msg(struct tipc_link *l,
1380 struct sk_buff_head *xmitq) 1385 struct sk_buff_head *xmitq)
1381{ 1386{
1382 u32 def_cnt = ++l->stats.deferred_recv; 1387 u32 def_cnt = ++l->stats.deferred_recv;
1388 u32 defq_len = skb_queue_len(&l->deferdq);
1383 int match1, match2; 1389 int match1, match2;
1384 1390
1385 if (link_is_bc_rcvlink(l)) { 1391 if (link_is_bc_rcvlink(l)) {
@@ -1390,7 +1396,7 @@ static int tipc_link_build_nack_msg(struct tipc_link *l,
1390 return 0; 1396 return 0;
1391 } 1397 }
1392 1398
1393 if ((skb_queue_len(&l->deferdq) == 1) || !(def_cnt % TIPC_NACK_INTV)) 1399 if (defq_len >= 3 && !((defq_len - 3) % 16))
1394 tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, 0, xmitq); 1400 tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, 0, xmitq);
1395 return 0; 1401 return 0;
1396} 1402}
@@ -1404,29 +1410,29 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
1404 struct sk_buff_head *xmitq) 1410 struct sk_buff_head *xmitq)
1405{ 1411{
1406 struct sk_buff_head *defq = &l->deferdq; 1412 struct sk_buff_head *defq = &l->deferdq;
1407 struct tipc_msg *hdr; 1413 struct tipc_msg *hdr = buf_msg(skb);
1408 u16 seqno, rcv_nxt, win_lim; 1414 u16 seqno, rcv_nxt, win_lim;
1409 int rc = 0; 1415 int rc = 0;
1410 1416
1417 /* Verify and update link state */
1418 if (unlikely(msg_user(hdr) == LINK_PROTOCOL))
1419 return tipc_link_proto_rcv(l, skb, xmitq);
1420
1421 /* Don't send probe at next timeout expiration */
1422 l->silent_intv_cnt = 0;
1423
1411 do { 1424 do {
1412 hdr = buf_msg(skb); 1425 hdr = buf_msg(skb);
1413 seqno = msg_seqno(hdr); 1426 seqno = msg_seqno(hdr);
1414 rcv_nxt = l->rcv_nxt; 1427 rcv_nxt = l->rcv_nxt;
1415 win_lim = rcv_nxt + TIPC_MAX_LINK_WIN; 1428 win_lim = rcv_nxt + TIPC_MAX_LINK_WIN;
1416 1429
1417 /* Verify and update link state */
1418 if (unlikely(msg_user(hdr) == LINK_PROTOCOL))
1419 return tipc_link_proto_rcv(l, skb, xmitq);
1420
1421 if (unlikely(!link_is_up(l))) { 1430 if (unlikely(!link_is_up(l))) {
1422 if (l->state == LINK_ESTABLISHING) 1431 if (l->state == LINK_ESTABLISHING)
1423 rc = TIPC_LINK_UP_EVT; 1432 rc = TIPC_LINK_UP_EVT;
1424 goto drop; 1433 goto drop;
1425 } 1434 }
1426 1435
1427 /* Don't send probe at next timeout expiration */
1428 l->silent_intv_cnt = 0;
1429
1430 /* Drop if outside receive window */ 1436 /* Drop if outside receive window */
1431 if (unlikely(less(seqno, rcv_nxt) || more(seqno, win_lim))) { 1437 if (unlikely(less(seqno, rcv_nxt) || more(seqno, win_lim))) {
1432 l->stats.duplicates++; 1438 l->stats.duplicates++;
@@ -1457,7 +1463,7 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
1457 rc |= tipc_link_build_state_msg(l, xmitq); 1463 rc |= tipc_link_build_state_msg(l, xmitq);
1458 if (unlikely(rc & ~TIPC_LINK_SND_STATE)) 1464 if (unlikely(rc & ~TIPC_LINK_SND_STATE))
1459 break; 1465 break;
1460 } while ((skb = __skb_dequeue(defq))); 1466 } while ((skb = __tipc_skb_dequeue(defq, l->rcv_nxt)));
1461 1467
1462 return rc; 1468 return rc;
1463drop: 1469drop: