|
@@ -899,12 +899,29 @@ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb)
|
|
|
tp->retransmit_high = TCP_SKB_CB(skb)->end_seq;
|
|
|
}
|
|
|
|
|
|
+/* Sum the number of packets on the wire we have marked as lost.
|
|
|
+ * There are two cases we care about here:
|
|
|
+ * a) Packet hasn't been marked lost (nor retransmitted),
|
|
|
+ * and this is the first loss.
|
|
|
+ * b) Packet has been marked both lost and retransmitted,
|
|
|
+ * and this means we think it was lost again.
|
|
|
+ */
|
|
|
+static void tcp_sum_lost(struct tcp_sock *tp, struct sk_buff *skb)
|
|
|
+{
|
|
|
+ __u8 sacked = TCP_SKB_CB(skb)->sacked;
|
|
|
+
|
|
|
+ if (!(sacked & TCPCB_LOST) ||
|
|
|
+ ((sacked & TCPCB_LOST) && (sacked & TCPCB_SACKED_RETRANS)))
|
|
|
+ tp->lost += tcp_skb_pcount(skb);
|
|
|
+}
|
|
|
+
|
|
|
static void tcp_skb_mark_lost(struct tcp_sock *tp, struct sk_buff *skb)
|
|
|
{
|
|
|
if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) {
|
|
|
tcp_verify_retransmit_hint(tp, skb);
|
|
|
|
|
|
tp->lost_out += tcp_skb_pcount(skb);
|
|
|
+ tcp_sum_lost(tp, skb);
|
|
|
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
|
|
|
}
|
|
|
}
|
|
@@ -913,6 +930,7 @@ void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb)
|
|
|
{
|
|
|
tcp_verify_retransmit_hint(tp, skb);
|
|
|
|
|
|
+ tcp_sum_lost(tp, skb);
|
|
|
if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) {
|
|
|
tp->lost_out += tcp_skb_pcount(skb);
|
|
|
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
|
|
@@ -1890,6 +1908,7 @@ void tcp_enter_loss(struct sock *sk)
|
|
|
struct sk_buff *skb;
|
|
|
bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery;
|
|
|
bool is_reneg; /* is receiver reneging on SACKs? */
|
|
|
+ bool mark_lost;
|
|
|
|
|
|
/* Reduce ssthresh if it has not yet been made inside this window. */
|
|
|
if (icsk->icsk_ca_state <= TCP_CA_Disorder ||
|
|
@@ -1923,8 +1942,12 @@ void tcp_enter_loss(struct sock *sk)
|
|
|
if (skb == tcp_send_head(sk))
|
|
|
break;
|
|
|
|
|
|
+ mark_lost = (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED) ||
|
|
|
+ is_reneg);
|
|
|
+ if (mark_lost)
|
|
|
+ tcp_sum_lost(tp, skb);
|
|
|
TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
|
|
|
- if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || is_reneg) {
|
|
|
+ if (mark_lost) {
|
|
|
TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
|
|
|
TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
|
|
|
tp->lost_out += tcp_skb_pcount(skb);
|