diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/link.c | 52 |
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 | */ | ||
1601 | static 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 | */ |
1595 | int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr, | 1636 | int 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)) |