aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2016-09-01 13:52:50 -0400
committerDavid S. Miller <davem@davemloft.net>2016-09-02 20:10:24 -0400
commit7c4a54b963b68eee5ef3bd7ca740630d965616e2 (patch)
tree47d208204080540e4c117a72d0790a64509b49bd /net/tipc
parent02d11ca20091fcef904f05defda80c53e5b4e793 (diff)
tipc: rate limit broadcast retransmissions
As cluster sizes grow, so does the amount of identical or overlapping broadcast NACKs generated by the packet receivers. This often leads to 'NACK crunches' resulting in huge numbers of redundant retransmissions of the same packet ranges. In this commit, we introduce rate control of broadcast retransmissions, so that a retransmitted range cannot be retransmitted again until after at least 10 ms. This reduces the frequency of duplicate, redundant retransmissions by an order of magnitude, while having a significant positive impact on overall throughput and scalability. Reviewed-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>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/link.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 136316fb37ec..58bb44d95f95 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -181,7 +181,10 @@ struct tipc_link {
181 u16 acked; 181 u16 acked;
182 struct tipc_link *bc_rcvlink; 182 struct tipc_link *bc_rcvlink;
183 struct tipc_link *bc_sndlink; 183 struct tipc_link *bc_sndlink;
184 int nack_state; 184 unsigned long prev_retr;
185 u16 prev_from;
186 u16 prev_to;
187 u8 nack_state;
185 bool bc_peer_is_up; 188 bool bc_peer_is_up;
186 189
187 /* Statistics */ 190 /* Statistics */
@@ -202,6 +205,8 @@ enum {
202 BC_NACK_SND_SUPPRESS, 205 BC_NACK_SND_SUPPRESS,
203}; 206};
204 207
208#define TIPC_BC_RETR_LIMIT 10 /* [ms] */
209
205/* 210/*
206 * Interval between NACKs when packets arrive out of order 211 * Interval between NACKs when packets arrive out of order
207 */ 212 */
@@ -1590,11 +1595,48 @@ void tipc_link_bc_init_rcv(struct tipc_link *l, struct tipc_msg *hdr)
1590 l->rcv_nxt = peers_snd_nxt; 1595 l->rcv_nxt = peers_snd_nxt;
1591} 1596}
1592 1597
1598/* link_bc_retr eval()- check if the indicated range can be retransmitted now
1599 * - Adjust permitted range if there is overlap with previous retransmission
1600 */
1601static bool link_bc_retr_eval(struct tipc_link *l, u16 *from, u16 *to)
1602{
1603 unsigned long elapsed = jiffies_to_msecs(jiffies - l->prev_retr);
1604
1605 if (less(*to, *from))
1606 return false;
1607
1608 /* New retransmission request */
1609 if ((elapsed > TIPC_BC_RETR_LIMIT) ||
1610 less(*to, l->prev_from) || more(*from, l->prev_to)) {
1611 l->prev_from = *from;
1612 l->prev_to = *to;
1613 l->prev_retr = jiffies;
1614 return true;
1615 }
1616
1617 /* Inside range of previous retransmit */
1618 if (!less(*from, l->prev_from) && !more(*to, l->prev_to))
1619 return false;
1620
1621 /* Fully or partially outside previous range => exclude overlap */
1622 if (less(*from, l->prev_from)) {
1623 *to = l->prev_from - 1;
1624 l->prev_from = *from;
1625 }
1626 if (more(*to, l->prev_to)) {
1627 *from = l->prev_to + 1;
1628 l->prev_to = *to;
1629 }
1630 l->prev_retr = jiffies;
1631 return true;
1632}
1633
1593/* tipc_link_bc_sync_rcv - update rcv link according to peer's send state 1634/* tipc_link_bc_sync_rcv - update rcv link according to peer's send state
1594 */ 1635 */
1595int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr, 1636int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
1596 struct sk_buff_head *xmitq) 1637 struct sk_buff_head *xmitq)
1597{ 1638{
1639 struct tipc_link *snd_l = l->bc_sndlink;
1598 u16 peers_snd_nxt = msg_bc_snd_nxt(hdr); 1640 u16 peers_snd_nxt = msg_bc_snd_nxt(hdr);
1599 u16 from = msg_bcast_ack(hdr) + 1; 1641 u16 from = msg_bcast_ack(hdr) + 1;
1600 u16 to = from + msg_bc_gap(hdr) - 1; 1642 u16 to = from + msg_bc_gap(hdr) - 1;
@@ -1613,14 +1655,14 @@ int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
1613 if (!l->bc_peer_is_up) 1655 if (!l->bc_peer_is_up)
1614 return rc; 1656 return rc;
1615 1657
1658 l->stats.recv_nacks++;
1659
1616 /* Ignore if peers_snd_nxt goes beyond receive window */ 1660 /* Ignore if peers_snd_nxt goes beyond receive window */
1617 if (more(peers_snd_nxt, l->rcv_nxt + l->window)) 1661 if (more(peers_snd_nxt, l->rcv_nxt + l->window))
1618 return rc; 1662 return rc;
1619 1663
1620 if (!less(to, from)) { 1664 if (link_bc_retr_eval(snd_l, &from, &to))
1621 rc = tipc_link_retrans(l->bc_sndlink, from, to, xmitq); 1665 rc = tipc_link_retrans(snd_l, from, to, xmitq);
1622 l->stats.recv_nacks++;
1623 }
1624 1666
1625 l->snd_nxt = peers_snd_nxt; 1667 l->snd_nxt = peers_snd_nxt;
1626 if (link_bc_rcv_gap(l)) 1668 if (link_bc_rcv_gap(l))