Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[deliverable/linux.git] / net / ipv4 / tcp_input.c
index 42bf89aaf6a5206cf384068a0a50a3130abe2a4e..f9f9e375d7deb176eb65dc977408dadc97fa04e6 100644 (file)
@@ -3115,6 +3115,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
        long ca_rtt_us = -1L;
        struct sk_buff *skb;
        u32 pkts_acked = 0;
+       u32 last_in_flight = 0;
        bool rtt_update;
        int flag = 0;
 
@@ -3154,6 +3155,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
                        if (!first_ackt.v64)
                                first_ackt = last_ackt;
 
+                       last_in_flight = TCP_SKB_CB(skb)->tx.in_flight;
                        reord = min(pkts_acked, reord);
                        if (!after(scb->end_seq, tp->high_seq))
                                flag |= FLAG_ORIG_SACK_ACKED;
@@ -3250,7 +3252,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
 
        if (icsk->icsk_ca_ops->pkts_acked) {
                struct ack_sample sample = { .pkts_acked = pkts_acked,
-                                            .rtt_us = ca_rtt_us };
+                                            .rtt_us = ca_rtt_us,
+                                            .in_flight = last_in_flight };
 
                icsk->icsk_ca_ops->pkts_acked(sk, &sample);
        }
@@ -5169,6 +5172,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
                                  const struct tcphdr *th, int syn_inerr)
 {
        struct tcp_sock *tp = tcp_sk(sk);
+       bool rst_seq_match = false;
 
        /* RFC1323: H1. Apply PAWS check first. */
        if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp &&
@@ -5205,13 +5209,32 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
 
        /* Step 2: check RST bit */
        if (th->rst) {
-               /* RFC 5961 3.2 :
-                * If sequence number exactly matches RCV.NXT, then
+               /* RFC 5961 3.2 (extend to match against SACK too if available):
+                * If seq num matches RCV.NXT or the right-most SACK block,
+                * then
                 *     RESET the connection
                 * else
                 *     Send a challenge ACK
                 */
-               if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt)
+               if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
+                       rst_seq_match = true;
+               } else if (tcp_is_sack(tp) && tp->rx_opt.num_sacks > 0) {
+                       struct tcp_sack_block *sp = &tp->selective_acks[0];
+                       int max_sack = sp[0].end_seq;
+                       int this_sack;
+
+                       for (this_sack = 1; this_sack < tp->rx_opt.num_sacks;
+                            ++this_sack) {
+                               max_sack = after(sp[this_sack].end_seq,
+                                                max_sack) ?
+                                       sp[this_sack].end_seq : max_sack;
+                       }
+
+                       if (TCP_SKB_CB(skb)->seq == max_sack)
+                               rst_seq_match = true;
+               }
+
+               if (rst_seq_match)
                        tcp_reset(sk);
                else
                        tcp_send_challenge_ack(sk, skb);
This page took 0.032562 seconds and 5 git commands to generate.