Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/net/ipv4/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 210 kB image not shown  

Quelle  tcp_input.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * INET An implementation of the TCP/IP protocol suite for the LINUX
 * operating system.  INET is implemented using the  BSD Socket
 * interface as the means of communication with the user level.
 *
 * Implementation of the Transmission Control Protocol(TCP).
 *
 * Authors: Ross Biro
 * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 * Mark Evans, <evansmp@uhura.aston.ac.uk>
 * Corey Minyard <wf-rch!minyard@relay.EU.net>
 * Florian La Roche, <flla@stud.uni-sb.de>
 * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
 * Linus Torvalds, <torvalds@cs.helsinki.fi>
 * Alan Cox, <gw4pts@gw4pts.ampr.org>
 * Matthew Dillon, <dillon@apollo.west.oic.com>
 * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
 * Jorge Cwik, <jorge@laser.satlink.net>
 */


/*
 * Changes:
 * Pedro Roque : Fast Retransmit/Recovery.
 * Two receive queues.
 * Retransmit queue handled by TCP.
 * Better retransmit timer handling.
 * New congestion avoidance.
 * Header prediction.
 * Variable renaming.
 *
 * Eric : Fast Retransmit.
 * Randy Scott : MSS option defines.
 * Eric Schenk : Fixes to slow start algorithm.
 * Eric Schenk : Yet another double ACK bug.
 * Eric Schenk : Delayed ACK bug fixes.
 * Eric Schenk : Floyd style fast retrans war avoidance.
 * David S. Miller : Don't allow zero congestion window.
 * Eric Schenk : Fix retransmitter so that it sends
 * next packet on ack of previous packet.
 * Andi Kleen : Moved open_request checking here
 * and process RSTs for open_requests.
 * Andi Kleen : Better prune_queue, and other fixes.
 * Andrey Savochkin: Fix RTT measurements in the presence of
 * timestamps.
 * Andrey Savochkin: Check sequence numbers correctly when
 * removing SACKs due to in sequence incoming
 * data segments.
 * Andi Kleen: Make sure we never ack data there is not
 * enough room for. Also make this condition
 * a fatal error if it might still happen.
 * Andi Kleen: Add tcp_measure_rcv_mss to make
 * connections with MSS<min(MTU,ann. MSS)
 * work without delayed acks.
 * Andi Kleen: Process packets with PSH set in the
 * fast path.
 * J Hadi Salim: ECN support
 *   Andrei Gurtov,
 * Pasi Sarolahti,
 * Panu Kuhlberg: Experimental audit of TCP (re)transmission
 * engine. Lots of bugs are found.
 * Pasi Sarolahti: F-RTO for dealing with spurious RTOs
 */


#define pr_fmt(fmt) "TCP: " fmt

#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/sysctl.h>
#include <linux/kernel.h>
#include <linux/prefetch.h>
#include <net/dst.h>
#include <net/tcp.h>
#include <net/proto_memory.h>
#include <net/inet_common.h>
#include <linux/ipsec.h>
#include <linux/unaligned.h>
#include <linux/errqueue.h>
#include <trace/events/tcp.h>
#include <linux/jump_label_ratelimit.h>
#include <net/busy_poll.h>
#include <net/mptcp.h>

int sysctl_tcp_max_orphans __read_mostly = NR_FILE;

#define FLAG_DATA  0x01 /* Incoming frame contained data. */
#define FLAG_WIN_UPDATE  0x02 /* Incoming ACK was a window update. */
#define FLAG_DATA_ACKED  0x04 /* This ACK acknowledged new data. */
#define FLAG_RETRANS_DATA_ACKED 0x08 /* "" "" some of which was retransmitted. */
#define FLAG_SYN_ACKED  0x10 /* This ACK acknowledged SYN. */
#define FLAG_DATA_SACKED 0x20 /* New SACK. */
#define FLAG_ECE  0x40 /* ECE in this ACK */
#define FLAG_LOST_RETRANS 0x80 /* This ACK marks some retransmission lost */
#define FLAG_SLOWPATH  0x100 /* Do not skip RFC checks for window update.*/
#define FLAG_ORIG_SACK_ACKED 0x200 /* Never retransmitted data are (s)acked */
#define FLAG_SND_UNA_ADVANCED 0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
#define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */
#define FLAG_SET_XMIT_TIMER 0x1000 /* Set TLP or RTO timer */
#define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */
#define FLAG_UPDATE_TS_RECENT 0x4000 /* tcp_replace_ts_recent() */
#define FLAG_NO_CHALLENGE_ACK 0x8000 /* do not call tcp_send_challenge_ack() */
#define FLAG_ACK_MAYBE_DELAYED 0x10000 /* Likely a delayed ACK */
#define FLAG_DSACK_TLP  0x20000 /* DSACK for tail loss probe */
#define FLAG_TS_PROGRESS 0x40000 /* Positive timestamp delta */

#define FLAG_ACKED  (FLAG_DATA_ACKED|FLAG_SYN_ACKED)
#define FLAG_NOT_DUP  (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
#define FLAG_CA_ALERT  (FLAG_DATA_SACKED|FLAG_ECE|FLAG_DSACKING_ACK)
#define FLAG_FORWARD_PROGRESS (FLAG_ACKED|FLAG_DATA_SACKED)

#define TCP_REMNANT (TCP_FLAG_FIN|TCP_FLAG_URG|TCP_FLAG_SYN|TCP_FLAG_PSH)
#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH))

#define REXMIT_NONE 0 /* no loss recovery to do */
#define REXMIT_LOST 1 /* retransmit packets marked lost */
#define REXMIT_NEW 2 /* FRTO-style transmit of unsent/new packets */

#if IS_ENABLED(CONFIG_TLS_DEVICE)
static DEFINE_STATIC_KEY_DEFERRED_FALSE(clean_acked_data_enabled, HZ);

void clean_acked_data_enable(struct tcp_sock *tp,
        void (*cad)(struct sock *sk, u32 ack_seq))
{
 tp->tcp_clean_acked = cad;
 static_branch_deferred_inc(&clean_acked_data_enabled);
}
EXPORT_SYMBOL_GPL(clean_acked_data_enable);

void clean_acked_data_disable(struct tcp_sock *tp)
{
 static_branch_slow_dec_deferred(&clean_acked_data_enabled);
 tp->tcp_clean_acked = NULL;
}
EXPORT_SYMBOL_GPL(clean_acked_data_disable);

void clean_acked_data_flush(void)
{
 static_key_deferred_flush(&clean_acked_data_enabled);
}
EXPORT_SYMBOL_GPL(clean_acked_data_flush);
#endif

#ifdef CONFIG_CGROUP_BPF
static void bpf_skops_parse_hdr(struct sock *sk, struct sk_buff *skb)
{
 bool unknown_opt = tcp_sk(sk)->rx_opt.saw_unknown &&
  BPF_SOCK_OPS_TEST_FLAG(tcp_sk(sk),
           BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG);
 bool parse_all_opt = BPF_SOCK_OPS_TEST_FLAG(tcp_sk(sk),
          BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG);
 struct bpf_sock_ops_kern sock_ops;

 if (likely(!unknown_opt && !parse_all_opt))
  return;

 /* The skb will be handled in the
 * bpf_skops_established() or
 * bpf_skops_write_hdr_opt().
 */

 switch (sk->sk_state) {
 case TCP_SYN_RECV:
 case TCP_SYN_SENT:
 case TCP_LISTEN:
  return;
 }

 sock_owned_by_me(sk);

 memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp));
 sock_ops.op = BPF_SOCK_OPS_PARSE_HDR_OPT_CB;
 sock_ops.is_fullsock = 1;
 sock_ops.is_locked_tcp_sock = 1;
 sock_ops.sk = sk;
 bpf_skops_init_skb(&sock_ops, skb, tcp_hdrlen(skb));

 BPF_CGROUP_RUN_PROG_SOCK_OPS(&sock_ops);
}

static void bpf_skops_established(struct sock *sk, int bpf_op,
      struct sk_buff *skb)
{
 struct bpf_sock_ops_kern sock_ops;

 sock_owned_by_me(sk);

 memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp));
 sock_ops.op = bpf_op;
 sock_ops.is_fullsock = 1;
 sock_ops.is_locked_tcp_sock = 1;
 sock_ops.sk = sk;
 /* sk with TCP_REPAIR_ON does not have skb in tcp_finish_connect */
 if (skb)
  bpf_skops_init_skb(&sock_ops, skb, tcp_hdrlen(skb));

 BPF_CGROUP_RUN_PROG_SOCK_OPS(&sock_ops);
}
#else
static void bpf_skops_parse_hdr(struct sock *sk, struct sk_buff *skb)
{
}

static void bpf_skops_established(struct sock *sk, int bpf_op,
      struct sk_buff *skb)
{
}
#endif

static __cold void tcp_gro_dev_warn(const struct sock *sk, const struct sk_buff *skb,
        unsigned int len)
{
 struct net_device *dev;

 rcu_read_lock();
 dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif);
 if (!dev || len >= READ_ONCE(dev->mtu))
  pr_warn("%s: Driver has suspect GRO implementation, TCP performance may be compromised.\n",
   dev ? dev->name : "Unknown driver");
 rcu_read_unlock();
}

/* Adapt the MSS value used to make delayed ack decision to the
 * real world.
 */

static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
{
 struct inet_connection_sock *icsk = inet_csk(sk);
 const unsigned int lss = icsk->icsk_ack.last_seg_size;
 unsigned int len;

 icsk->icsk_ack.last_seg_size = 0;

 /* skb->len may jitter because of SACKs, even if peer
 * sends good full-sized frames.
 */

 len = skb_shinfo(skb)->gso_size ? : skb->len;
 if (len >= icsk->icsk_ack.rcv_mss) {
  /* Note: divides are still a bit expensive.
 * For the moment, only adjust scaling_ratio
 * when we update icsk_ack.rcv_mss.
 */

  if (unlikely(len != icsk->icsk_ack.rcv_mss)) {
   u64 val = (u64)skb->len << TCP_RMEM_TO_WIN_SCALE;
   u8 old_ratio = tcp_sk(sk)->scaling_ratio;

   do_div(val, skb->truesize);
   tcp_sk(sk)->scaling_ratio = val ? val : 1;

   if (old_ratio != tcp_sk(sk)->scaling_ratio) {
    struct tcp_sock *tp = tcp_sk(sk);

    val = tcp_win_from_space(sk, sk->sk_rcvbuf);
    tcp_set_window_clamp(sk, val);

    if (tp->window_clamp < tp->rcvq_space.space)
     tp->rcvq_space.space = tp->window_clamp;
   }
  }
  icsk->icsk_ack.rcv_mss = min_t(unsigned int, len,
            tcp_sk(sk)->advmss);
  /* Account for possibly-removed options */
  DO_ONCE_LITE_IF(len > icsk->icsk_ack.rcv_mss + MAX_TCP_OPTION_SPACE,
    tcp_gro_dev_warn, sk, skb, len);
  /* If the skb has a len of exactly 1*MSS and has the PSH bit
 * set then it is likely the end of an application write. So
 * more data may not be arriving soon, and yet the data sender
 * may be waiting for an ACK if cwnd-bound or using TX zero
 * copy. So we set ICSK_ACK_PUSHED here so that
 * tcp_cleanup_rbuf() will send an ACK immediately if the app
 * reads all of the data and is not ping-pong. If len > MSS
 * then this logic does not matter (and does not hurt) because
 * tcp_cleanup_rbuf() will always ACK immediately if the app
 * reads data and there is more than an MSS of unACKed data.
 */

  if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_PSH)
   icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
 } else {
  /* Otherwise, we make more careful check taking into account,
 * that SACKs block is variable.
 *
 * "len" is invariant segment length, including TCP header.
 */

  len += skb->data - skb_transport_header(skb);
  if (len >= TCP_MSS_DEFAULT + sizeof(struct tcphdr) ||
      /* If PSH is not set, packet should be
     * full sized, provided peer TCP is not badly broken.
     * This observation (if it is correct 8)) allows
     * to handle super-low mtu links fairly.
     */

      (len >= TCP_MIN_MSS + sizeof(struct tcphdr) &&
       !(tcp_flag_word(tcp_hdr(skb)) & TCP_REMNANT))) {
   /* Subtract also invariant (if peer is RFC compliant),
 * tcp header plus fixed timestamp option length.
 * Resulting "len" is MSS free of SACK jitter.
 */

   len -= tcp_sk(sk)->tcp_header_len;
   icsk->icsk_ack.last_seg_size = len;
   if (len == lss) {
    icsk->icsk_ack.rcv_mss = len;
    return;
   }
  }
  if (icsk->icsk_ack.pending & ICSK_ACK_PUSHED)
   icsk->icsk_ack.pending |= ICSK_ACK_PUSHED2;
  icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
 }
}

static void tcp_incr_quickack(struct sock *sk, unsigned int max_quickacks)
{
 struct inet_connection_sock *icsk = inet_csk(sk);
 unsigned int quickacks = tcp_sk(sk)->rcv_wnd / (2 * icsk->icsk_ack.rcv_mss);

 if (quickacks == 0)
  quickacks = 2;
 quickacks = min(quickacks, max_quickacks);
 if (quickacks > icsk->icsk_ack.quick)
  icsk->icsk_ack.quick = quickacks;
}

static void tcp_enter_quickack_mode(struct sock *sk, unsigned int max_quickacks)
{
 struct inet_connection_sock *icsk = inet_csk(sk);

 tcp_incr_quickack(sk, max_quickacks);
 inet_csk_exit_pingpong_mode(sk);
 icsk->icsk_ack.ato = TCP_ATO_MIN;
}

/* Send ACKs quickly, if "quick" count is not exhausted
 * and the session is not interactive.
 */


static bool tcp_in_quickack_mode(struct sock *sk)
{
 const struct inet_connection_sock *icsk = inet_csk(sk);

 return icsk->icsk_ack.dst_quick_ack ||
  (icsk->icsk_ack.quick && !inet_csk_in_pingpong_mode(sk));
}

static void tcp_ecn_queue_cwr(struct tcp_sock *tp)
{
 if (tcp_ecn_mode_rfc3168(tp))
  tp->ecn_flags |= TCP_ECN_QUEUE_CWR;
}

static void tcp_ecn_accept_cwr(struct sock *sk, const struct sk_buff *skb)
{
 if (tcp_hdr(skb)->cwr) {
  tcp_sk(sk)->ecn_flags &= ~TCP_ECN_DEMAND_CWR;

  /* If the sender is telling us it has entered CWR, then its
 * cwnd may be very low (even just 1 packet), so we should ACK
 * immediately.
 */

  if (TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq)
   inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
 }
}

static void tcp_ecn_withdraw_cwr(struct tcp_sock *tp)
{
 tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR;
}

static void tcp_data_ecn_check(struct sock *sk, const struct sk_buff *skb)
{
 struct tcp_sock *tp = tcp_sk(sk);

 if (tcp_ecn_disabled(tp))
  return;

 switch (TCP_SKB_CB(skb)->ip_dsfield & INET_ECN_MASK) {
 case INET_ECN_NOT_ECT:
  /* Funny extension: if ECT is not set on a segment,
 * and we already seen ECT on a previous segment,
 * it is probably a retransmit.
 */

  if (tp->ecn_flags & TCP_ECN_SEEN)
   tcp_enter_quickack_mode(sk, 2);
  break;
 case INET_ECN_CE:
  if (tcp_ca_needs_ecn(sk))
   tcp_ca_event(sk, CA_EVENT_ECN_IS_CE);

  if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) {
   /* Better not delay acks, sender can have a very low cwnd */
   tcp_enter_quickack_mode(sk, 2);
   tp->ecn_flags |= TCP_ECN_DEMAND_CWR;
  }
  tp->ecn_flags |= TCP_ECN_SEEN;
  break;
 default:
  if (tcp_ca_needs_ecn(sk))
   tcp_ca_event(sk, CA_EVENT_ECN_NO_CE);
  tp->ecn_flags |= TCP_ECN_SEEN;
  break;
 }
}

static void tcp_ecn_rcv_synack(struct tcp_sock *tp, const struct tcphdr *th)
{
 if (tcp_ecn_mode_rfc3168(tp) && (!th->ece || th->cwr))
  tcp_ecn_mode_set(tp, TCP_ECN_DISABLED);
}

static void tcp_ecn_rcv_syn(struct tcp_sock *tp, const struct tcphdr *th)
{
 if (tcp_ecn_mode_rfc3168(tp) && (!th->ece || !th->cwr))
  tcp_ecn_mode_set(tp, TCP_ECN_DISABLED);
}

static bool tcp_ecn_rcv_ecn_echo(const struct tcp_sock *tp, const struct tcphdr *th)
{
 if (th->ece && !th->syn && tcp_ecn_mode_rfc3168(tp))
  return true;
 return false;
}

static void tcp_count_delivered_ce(struct tcp_sock *tp, u32 ecn_count)
{
 tp->delivered_ce += ecn_count;
}

/* Updates the delivered and delivered_ce counts */
static void tcp_count_delivered(struct tcp_sock *tp, u32 delivered,
    bool ece_ack)
{
 tp->delivered += delivered;
 if (ece_ack)
  tcp_count_delivered_ce(tp, delivered);
}

/* Buffer size and advertised window tuning.
 *
 * 1. Tuning sk->sk_sndbuf, when connection enters established state.
 */


static void tcp_sndbuf_expand(struct sock *sk)
{
 const struct tcp_sock *tp = tcp_sk(sk);
 const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops;
 int sndmem, per_mss;
 u32 nr_segs;

 /* Worst case is non GSO/TSO : each frame consumes one skb
 * and skb->head is kmalloced using power of two area of memory
 */

 per_mss = max_t(u32, tp->rx_opt.mss_clamp, tp->mss_cache) +
    MAX_TCP_HEADER +
    SKB_DATA_ALIGN(sizeof(struct skb_shared_info));

 per_mss = roundup_pow_of_two(per_mss) +
    SKB_DATA_ALIGN(sizeof(struct sk_buff));

 nr_segs = max_t(u32, TCP_INIT_CWND, tcp_snd_cwnd(tp));
 nr_segs = max_t(u32, nr_segs, tp->reordering + 1);

 /* Fast Recovery (RFC 5681 3.2) :
 * Cubic needs 1.7 factor, rounded to 2 to include
 * extra cushion (application might react slowly to EPOLLOUT)
 */

 sndmem = ca_ops->sndbuf_expand ? ca_ops->sndbuf_expand(sk) : 2;
 sndmem *= nr_segs * per_mss;

 if (sk->sk_sndbuf < sndmem)
  WRITE_ONCE(sk->sk_sndbuf,
      min(sndmem, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_wmem[2])));
}

/* 2. Tuning advertised window (window_clamp, rcv_ssthresh)
 *
 * All tcp_full_space() is split to two parts: "network" buffer, allocated
 * forward and advertised in receiver window (tp->rcv_wnd) and
 * "application buffer", required to isolate scheduling/application
 * latencies from network.
 * window_clamp is maximal advertised window. It can be less than
 * tcp_full_space(), in this case tcp_full_space() - window_clamp
 * is reserved for "application" buffer. The less window_clamp is
 * the smoother our behaviour from viewpoint of network, but the lower
 * throughput and the higher sensitivity of the connection to losses. 8)
 *
 * rcv_ssthresh is more strict window_clamp used at "slow start"
 * phase to predict further behaviour of this connection.
 * It is used for two goals:
 * - to enforce header prediction at sender, even when application
 *   requires some significant "application buffer". It is check #1.
 * - to prevent pruning of receive queue because of misprediction
 *   of receiver window. Check #2.
 *
 * The scheme does not work when sender sends good segments opening
 * window and then starts to feed us spaghetti. But it should work
 * in common situations. Otherwise, we have to rely on queue collapsing.
 */


/* Slow part of check#2. */
static int __tcp_grow_window(const struct sock *sk, const struct sk_buff *skb,
        unsigned int skbtruesize)
{
 const struct tcp_sock *tp = tcp_sk(sk);
 /* Optimize this! */
 int truesize = tcp_win_from_space(sk, skbtruesize) >> 1;
 int window = tcp_win_from_space(sk, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2])) >> 1;

 while (tp->rcv_ssthresh <= window) {
  if (truesize <= skb->len)
   return 2 * inet_csk(sk)->icsk_ack.rcv_mss;

  truesize >>= 1;
  window >>= 1;
 }
 return 0;
}

/* Even if skb appears to have a bad len/truesize ratio, TCP coalescing
 * can play nice with us, as sk_buff and skb->head might be either
 * freed or shared with up to MAX_SKB_FRAGS segments.
 * Only give a boost to drivers using page frag(s) to hold the frame(s),
 * and if no payload was pulled in skb->head before reaching us.
 */

static u32 truesize_adjust(bool adjust, const struct sk_buff *skb)
{
 u32 truesize = skb->truesize;

 if (adjust && !skb_headlen(skb)) {
  truesize -= SKB_TRUESIZE(skb_end_offset(skb));
  /* paranoid check, some drivers might be buggy */
  if (unlikely((int)truesize < (int)skb->len))
   truesize = skb->truesize;
 }
 return truesize;
}

static void tcp_grow_window(struct sock *sk, const struct sk_buff *skb,
       bool adjust)
{
 struct tcp_sock *tp = tcp_sk(sk);
 int room;

 room = min_t(int, tp->window_clamp, tcp_space(sk)) - tp->rcv_ssthresh;

 if (room <= 0)
  return;

 /* Check #1 */
 if (!tcp_under_memory_pressure(sk)) {
  unsigned int truesize = truesize_adjust(adjust, skb);
  int incr;

  /* Check #2. Increase window, if skb with such overhead
 * will fit to rcvbuf in future.
 */

  if (tcp_win_from_space(sk, truesize) <= skb->len)
   incr = 2 * tp->advmss;
  else
   incr = __tcp_grow_window(sk, skb, truesize);

  if (incr) {
   incr = max_t(int, incr, 2 * skb->len);
   tp->rcv_ssthresh += min(room, incr);
   inet_csk(sk)->icsk_ack.quick |= 1;
  }
 } else {
  /* Under pressure:
 * Adjust rcv_ssthresh according to reserved mem
 */

  tcp_adjust_rcv_ssthresh(sk);
 }
}

/* 3. Try to fixup all. It is made immediately after connection enters
 *    established state.
 */

static void tcp_init_buffer_space(struct sock *sk)
{
 int tcp_app_win = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_app_win);
 struct tcp_sock *tp = tcp_sk(sk);
 int maxwin;

 if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK))
  tcp_sndbuf_expand(sk);

 tcp_mstamp_refresh(tp);
 tp->rcvq_space.time = tp->tcp_mstamp;
 tp->rcvq_space.seq = tp->copied_seq;

 maxwin = tcp_full_space(sk);

 if (tp->window_clamp >= maxwin) {
  WRITE_ONCE(tp->window_clamp, maxwin);

  if (tcp_app_win && maxwin > 4 * tp->advmss)
   WRITE_ONCE(tp->window_clamp,
       max(maxwin - (maxwin >> tcp_app_win),
           4 * tp->advmss));
 }

 /* Force reservation of one segment. */
 if (tcp_app_win &&
     tp->window_clamp > 2 * tp->advmss &&
     tp->window_clamp + tp->advmss > maxwin)
  WRITE_ONCE(tp->window_clamp,
      max(2 * tp->advmss, maxwin - tp->advmss));

 tp->rcv_ssthresh = min(tp->rcv_ssthresh, tp->window_clamp);
 tp->snd_cwnd_stamp = tcp_jiffies32;
 tp->rcvq_space.space = min3(tp->rcv_ssthresh, tp->rcv_wnd,
        (u32)TCP_INIT_CWND * tp->advmss);
}

/* 4. Recalculate window clamp after socket hit its memory bounds. */
static void tcp_clamp_window(struct sock *sk)
{
 struct tcp_sock *tp = tcp_sk(sk);
 struct inet_connection_sock *icsk = inet_csk(sk);
 struct net *net = sock_net(sk);
 int rmem2;

 icsk->icsk_ack.quick = 0;
 rmem2 = READ_ONCE(net->ipv4.sysctl_tcp_rmem[2]);

 if (sk->sk_rcvbuf < rmem2 &&
     !(sk->sk_userlocks & SOCK_RCVBUF_LOCK) &&
     !tcp_under_memory_pressure(sk) &&
     sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)) {
  WRITE_ONCE(sk->sk_rcvbuf,
      min(atomic_read(&sk->sk_rmem_alloc), rmem2));
 }
 if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
  tp->rcv_ssthresh = min(tp->window_clamp, 2U * tp->advmss);
}

/* Initialize RCV_MSS value.
 * RCV_MSS is an our guess about MSS used by the peer.
 * We haven't any direct information about the MSS.
 * It's better to underestimate the RCV_MSS rather than overestimate.
 * Overestimations make us ACKing less frequently than needed.
 * Underestimations are more easy to detect and fix by tcp_measure_rcv_mss().
 */

void tcp_initialize_rcv_mss(struct sock *sk)
{
 const struct tcp_sock *tp = tcp_sk(sk);
 unsigned int hint = min_t(unsigned int, tp->advmss, tp->mss_cache);

 hint = min(hint, tp->rcv_wnd / 2);
 hint = min(hint, TCP_MSS_DEFAULT);
 hint = max(hint, TCP_MIN_MSS);

 inet_csk(sk)->icsk_ack.rcv_mss = hint;
}
EXPORT_IPV6_MOD(tcp_initialize_rcv_mss);

/* Receiver "autotuning" code.
 *
 * The algorithm for RTT estimation w/o timestamps is based on
 * Dynamic Right-Sizing (DRS) by Wu Feng and Mike Fisk of LANL.
 * <https://public.lanl.gov/radiant/pubs.html#DRS>
 *
 * More detail on this code can be found at
 * <http://staff.psc.edu/jheffner/>,
 * though this reference is out of date.  A new paper
 * is pending.
 */

static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep)
{
 u32 new_sample, old_sample = tp->rcv_rtt_est.rtt_us;
 long m = sample << 3;

 if (old_sample == 0 || m < old_sample) {
  new_sample = m;
 } else {
  /* If we sample in larger samples in the non-timestamp
 * case, we could grossly overestimate the RTT especially
 * with chatty applications or bulk transfer apps which
 * are stalled on filesystem I/O.
 *
 * Also, since we are only going for a minimum in the
 * non-timestamp case, we do not smooth things out
 * else with timestamps disabled convergence takes too
 * long.
 */

  if (win_dep)
   return;
  /* Do not use this sample if receive queue is not empty. */
  if (tp->rcv_nxt != tp->copied_seq)
   return;
  new_sample = old_sample - (old_sample >> 3) + sample;
 }

 tp->rcv_rtt_est.rtt_us = new_sample;
}

static inline void tcp_rcv_rtt_measure(struct tcp_sock *tp)
{
 u32 delta_us;

 if (tp->rcv_rtt_est.time == 0)
  goto new_measure;
 if (before(tp->rcv_nxt, tp->rcv_rtt_est.seq))
  return;
 delta_us = tcp_stamp_us_delta(tp->tcp_mstamp, tp->rcv_rtt_est.time);
 if (!delta_us)
  delta_us = 1;
 tcp_rcv_rtt_update(tp, delta_us, 1);

new_measure:
 tp->rcv_rtt_est.seq = tp->rcv_nxt + tp->rcv_wnd;
 tp->rcv_rtt_est.time = tp->tcp_mstamp;
}

static s32 tcp_rtt_tsopt_us(const struct tcp_sock *tp, u32 min_delta)
{
 u32 delta, delta_us;

 delta = tcp_time_stamp_ts(tp) - tp->rx_opt.rcv_tsecr;
 if (tp->tcp_usec_ts)
  return delta;

 if (likely(delta < INT_MAX / (USEC_PER_SEC / TCP_TS_HZ))) {
  if (!delta)
   delta = min_delta;
  delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
  return delta_us;
 }
 return -1;
}

static inline void tcp_rcv_rtt_measure_ts(struct sock *sk,
       const struct sk_buff *skb)
{
 struct tcp_sock *tp = tcp_sk(sk);

 if (tp->rx_opt.rcv_tsecr == tp->rcv_rtt_last_tsecr)
  return;
 tp->rcv_rtt_last_tsecr = tp->rx_opt.rcv_tsecr;

 if (TCP_SKB_CB(skb)->end_seq -
     TCP_SKB_CB(skb)->seq >= inet_csk(sk)->icsk_ack.rcv_mss) {
  s32 delta = tcp_rtt_tsopt_us(tp, 0);

  if (delta > 0)
   tcp_rcv_rtt_update(tp, delta, 0);
 }
}

static void tcp_rcvbuf_grow(struct sock *sk)
{
 const struct net *net = sock_net(sk);
 struct tcp_sock *tp = tcp_sk(sk);
 int rcvwin, rcvbuf, cap;

 if (!READ_ONCE(net->ipv4.sysctl_tcp_moderate_rcvbuf) ||
     (sk->sk_userlocks & SOCK_RCVBUF_LOCK))
  return;

 /* slow start: allow the sender to double its rate. */
 rcvwin = tp->rcvq_space.space << 1;

 if (!RB_EMPTY_ROOT(&tp->out_of_order_queue))
  rcvwin += TCP_SKB_CB(tp->ooo_last_skb)->end_seq - tp->rcv_nxt;

 cap = READ_ONCE(net->ipv4.sysctl_tcp_rmem[2]);

 rcvbuf = min_t(u32, tcp_space_from_win(sk, rcvwin), cap);
 if (rcvbuf > sk->sk_rcvbuf) {
  WRITE_ONCE(sk->sk_rcvbuf, rcvbuf);
  /* Make the window clamp follow along.  */
  WRITE_ONCE(tp->window_clamp,
      tcp_win_from_space(sk, rcvbuf));
 }
}
/*
 * This function should be called every time data is copied to user space.
 * It calculates the appropriate TCP receive buffer space.
 */

void tcp_rcv_space_adjust(struct sock *sk)
{
 struct tcp_sock *tp = tcp_sk(sk);
 int time, inq, copied;

 trace_tcp_rcv_space_adjust(sk);

 tcp_mstamp_refresh(tp);
 time = tcp_stamp_us_delta(tp->tcp_mstamp, tp->rcvq_space.time);
 if (time < (tp->rcv_rtt_est.rtt_us >> 3) || tp->rcv_rtt_est.rtt_us == 0)
  return;

 /* Number of bytes copied to user in last RTT */
 copied = tp->copied_seq - tp->rcvq_space.seq;
 /* Number of bytes in receive queue. */
 inq = tp->rcv_nxt - tp->copied_seq;
 copied -= inq;
 if (copied <= tp->rcvq_space.space)
  goto new_measure;

 trace_tcp_rcvbuf_grow(sk, time);

 tp->rcvq_space.space = copied;

 tcp_rcvbuf_grow(sk);

new_measure:
 tp->rcvq_space.seq = tp->copied_seq;
 tp->rcvq_space.time = tp->tcp_mstamp;
}

static void tcp_save_lrcv_flowlabel(struct sock *sk, const struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_IPV6)
 struct inet_connection_sock *icsk = inet_csk(sk);

 if (skb->protocol == htons(ETH_P_IPV6))
  icsk->icsk_ack.lrcv_flowlabel = ntohl(ip6_flowlabel(ipv6_hdr(skb)));
#endif
}

/* There is something which you must keep in mind when you analyze the
 * behavior of the tp->ato delayed ack timeout interval.  When a
 * connection starts up, we want to ack as quickly as possible.  The
 * problem is that "good" TCP's do slow start at the beginning of data
 * transmission.  The means that until we send the first few ACK's the
 * sender will sit on his end and only queue most of his data, because
 * he can only send snd_cwnd unacked packets at any given time.  For
 * each ACK we send, he increments snd_cwnd and transmits more of his
 * queue.  -DaveM
 */

static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb)
{
 struct tcp_sock *tp = tcp_sk(sk);
 struct inet_connection_sock *icsk = inet_csk(sk);
 u32 now;

 inet_csk_schedule_ack(sk);

 tcp_measure_rcv_mss(sk, skb);

 tcp_rcv_rtt_measure(tp);

 now = tcp_jiffies32;

 if (!icsk->icsk_ack.ato) {
  /* The _first_ data packet received, initialize
 * delayed ACK engine.
 */

  tcp_incr_quickack(sk, TCP_MAX_QUICKACKS);
  icsk->icsk_ack.ato = TCP_ATO_MIN;
 } else {
  int m = now - icsk->icsk_ack.lrcvtime;

  if (m <= TCP_ATO_MIN / 2) {
   /* The fastest case is the first. */
   icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + TCP_ATO_MIN / 2;
  } else if (m < icsk->icsk_ack.ato) {
   icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + m;
   if (icsk->icsk_ack.ato > icsk->icsk_rto)
    icsk->icsk_ack.ato = icsk->icsk_rto;
  } else if (m > icsk->icsk_rto) {
   /* Too long gap. Apparently sender failed to
 * restart window, so that we send ACKs quickly.
 */

   tcp_incr_quickack(sk, TCP_MAX_QUICKACKS);
  }
 }
 icsk->icsk_ack.lrcvtime = now;
 tcp_save_lrcv_flowlabel(sk, skb);

 tcp_data_ecn_check(sk, skb);

 if (skb->len >= 128)
  tcp_grow_window(sk, skb, true);
}

/* Called to compute a smoothed rtt estimate. The data fed to this
 * routine either comes from timestamps, or from segments that were
 * known _not_ to have been retransmitted [see Karn/Partridge
 * Proceedings SIGCOMM 87]. The algorithm is from the SIGCOMM 88
 * piece by Van Jacobson.
 * NOTE: the next three routines used to be one big routine.
 * To save cycles in the RFC 1323 implementation it was better to break
 * it up into three procedures. -- erics
 */

static void tcp_rtt_estimator(struct sock *sk, long mrtt_us)
{
 struct tcp_sock *tp = tcp_sk(sk);
 long m = mrtt_us; /* RTT */
 u32 srtt = tp->srtt_us;

 /* The following amusing code comes from Jacobson's
 * article in SIGCOMM '88.  Note that rtt and mdev
 * are scaled versions of rtt and mean deviation.
 * This is designed to be as fast as possible
 * m stands for "measurement".
 *
 * On a 1990 paper the rto value is changed to:
 * RTO = rtt + 4 * mdev
 *
 * Funny. This algorithm seems to be very broken.
 * These formulae increase RTO, when it should be decreased, increase
 * too slowly, when it should be increased quickly, decrease too quickly
 * etc. I guess in BSD RTO takes ONE value, so that it is absolutely
 * does not matter how to _calculate_ it. Seems, it was trap
 * that VJ failed to avoid. 8)
 */

 if (srtt != 0) {
  m -= (srtt >> 3); /* m is now error in rtt est */
  srtt += m;  /* rtt = 7/8 rtt + 1/8 new */
  if (m < 0) {
   m = -m;  /* m is now abs(error) */
   m -= (tp->mdev_us >> 2);   /* similar update on mdev */
   /* This is similar to one of Eifel findings.
 * Eifel blocks mdev updates when rtt decreases.
 * This solution is a bit different: we use finer gain
 * for mdev in this case (alpha*beta).
 * Like Eifel it also prevents growth of rto,
 * but also it limits too fast rto decreases,
 * happening in pure Eifel.
 */

   if (m > 0)
    m >>= 3;
  } else {
   m -= (tp->mdev_us >> 2);   /* similar update on mdev */
  }
  tp->mdev_us += m;  /* mdev = 3/4 mdev + 1/4 new */
  if (tp->mdev_us > tp->mdev_max_us) {
   tp->mdev_max_us = tp->mdev_us;
   if (tp->mdev_max_us > tp->rttvar_us)
    tp->rttvar_us = tp->mdev_max_us;
  }
  if (after(tp->snd_una, tp->rtt_seq)) {
   if (tp->mdev_max_us < tp->rttvar_us)
    tp->rttvar_us -= (tp->rttvar_us - tp->mdev_max_us) >> 2;
   tp->rtt_seq = tp->snd_nxt;
   tp->mdev_max_us = tcp_rto_min_us(sk);

   tcp_bpf_rtt(sk, mrtt_us, srtt);
  }
 } else {
  /* no previous measure. */
  srtt = m << 3;  /* take the measured time to be rtt */
  tp->mdev_us = m << 1; /* make sure rto = 3*rtt */
  tp->rttvar_us = max(tp->mdev_us, tcp_rto_min_us(sk));
  tp->mdev_max_us = tp->rttvar_us;
  tp->rtt_seq = tp->snd_nxt;

  tcp_bpf_rtt(sk, mrtt_us, srtt);
 }
 tp->srtt_us = max(1U, srtt);
}

static void tcp_update_pacing_rate(struct sock *sk)
{
 const struct tcp_sock *tp = tcp_sk(sk);
 u64 rate;

 /* set sk_pacing_rate to 200 % of current rate (mss * cwnd / srtt) */
 rate = (u64)tp->mss_cache * ((USEC_PER_SEC / 100) << 3);

 /* current rate is (cwnd * mss) / srtt
 * In Slow Start [1], set sk_pacing_rate to 200 % the current rate.
 * In Congestion Avoidance phase, set it to 120 % the current rate.
 *
 * [1] : Normal Slow Start condition is (tp->snd_cwnd < tp->snd_ssthresh)
 *  If snd_cwnd >= (tp->snd_ssthresh / 2), we are approaching
 *  end of slow start and should slow down.
 */

 if (tcp_snd_cwnd(tp) < tp->snd_ssthresh / 2)
  rate *= READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_pacing_ss_ratio);
 else
  rate *= READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_pacing_ca_ratio);

 rate *= max(tcp_snd_cwnd(tp), tp->packets_out);

 if (likely(tp->srtt_us))
  do_div(rate, tp->srtt_us);

 /* WRITE_ONCE() is needed because sch_fq fetches sk_pacing_rate
 * without any lock. We want to make sure compiler wont store
 * intermediate values in this location.
 */

 WRITE_ONCE(sk->sk_pacing_rate,
     min_t(u64, rate, READ_ONCE(sk->sk_max_pacing_rate)));
}

/* Calculate rto without backoff.  This is the second half of Van Jacobson's
 * routine referred to above.
 */

static void tcp_set_rto(struct sock *sk)
{
 const struct tcp_sock *tp = tcp_sk(sk);
 /* Old crap is replaced with new one. 8)
 *
 * More seriously:
 * 1. If rtt variance happened to be less 50msec, it is hallucination.
 *    It cannot be less due to utterly erratic ACK generation made
 *    at least by solaris and freebsd. "Erratic ACKs" has _nothing_
 *    to do with delayed acks, because at cwnd>2 true delack timeout
 *    is invisible. Actually, Linux-2.4 also generates erratic
 *    ACKs in some circumstances.
 */

 inet_csk(sk)->icsk_rto = __tcp_set_rto(tp);

 /* 2. Fixups made earlier cannot be right.
 *    If we do not estimate RTO correctly without them,
 *    all the algo is pure shit and should be replaced
 *    with correct one. It is exactly, which we pretend to do.
 */


 /* NOTE: clamping at TCP_RTO_MIN is not required, current algo
 * guarantees that rto is higher.
 */

 tcp_bound_rto(sk);
}

__u32 tcp_init_cwnd(const struct tcp_sock *tp, const struct dst_entry *dst)
{
 __u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0);

 if (!cwnd)
  cwnd = TCP_INIT_CWND;
 return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
}

struct tcp_sacktag_state {
 /* Timestamps for earliest and latest never-retransmitted segment
 * that was SACKed. RTO needs the earliest RTT to stay conservative,
 * but congestion control should still get an accurate delay signal.
 */

 u64 first_sackt;
 u64 last_sackt;
 u32 reord;
 u32 sack_delivered;
 int flag;
 unsigned int mss_now;
 struct rate_sample *rate;
};

/* Take a notice that peer is sending D-SACKs. Skip update of data delivery
 * and spurious retransmission information if this DSACK is unlikely caused by
 * sender's action:
 * - DSACKed sequence range is larger than maximum receiver's window.
 * - Total no. of DSACKed segments exceed the total no. of retransmitted segs.
 */

static u32 tcp_dsack_seen(struct tcp_sock *tp, u32 start_seq,
     u32 end_seq, struct tcp_sacktag_state *state)
{
 u32 seq_len, dup_segs = 1;

 if (!before(start_seq, end_seq))
  return 0;

 seq_len = end_seq - start_seq;
 /* Dubious DSACK: DSACKed range greater than maximum advertised rwnd */
 if (seq_len > tp->max_window)
  return 0;
 if (seq_len > tp->mss_cache)
  dup_segs = DIV_ROUND_UP(seq_len, tp->mss_cache);
 else if (tp->tlp_high_seq && tp->tlp_high_seq == end_seq)
  state->flag |= FLAG_DSACK_TLP;

 tp->dsack_dups += dup_segs;
 /* Skip the DSACK if dup segs weren't retransmitted by sender */
 if (tp->dsack_dups > tp->total_retrans)
  return 0;

 tp->rx_opt.sack_ok |= TCP_DSACK_SEEN;
 /* We increase the RACK ordering window in rounds where we receive
 * DSACKs that may have been due to reordering causing RACK to trigger
 * a spurious fast recovery. Thus RACK ignores DSACKs that happen
 * without having seen reordering, or that match TLP probes (TLP
 * is timer-driven, not triggered by RACK).
 */

 if (tp->reord_seen && !(state->flag & FLAG_DSACK_TLP))
  tp->rack.dsack_seen = 1;

 state->flag |= FLAG_DSACKING_ACK;
 /* A spurious retransmission is delivered */
 state->sack_delivered += dup_segs;

 return dup_segs;
}

/* It's reordering when higher sequence was delivered (i.e. sacked) before
 * some lower never-retransmitted sequence ("low_seq"). The maximum reordering
 * distance is approximated in full-mss packet distance ("reordering").
 */

static void tcp_check_sack_reordering(struct sock *sk, const u32 low_seq,
          const int ts)
{
 struct tcp_sock *tp = tcp_sk(sk);
 const u32 mss = tp->mss_cache;
 u32 fack, metric;

 fack = tcp_highest_sack_seq(tp);
 if (!before(low_seq, fack))
  return;

 metric = fack - low_seq;
 if ((metric > tp->reordering * mss) && mss) {
#if FASTRETRANS_DEBUG > 1
  pr_debug("Disorder%d %d %u f%u s%u rr%d\n",
    tp->rx_opt.sack_ok, inet_csk(sk)->icsk_ca_state,
    tp->reordering,
    0,
    tp->sacked_out,
    tp->undo_marker ? tp->undo_retrans : 0);
#endif
  tp->reordering = min_t(u32, (metric + mss - 1) / mss,
           READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_max_reordering));
 }

 /* This exciting event is worth to be remembered. 8) */
 tp->reord_seen++;
 NET_INC_STATS(sock_net(sk),
        ts ? LINUX_MIB_TCPTSREORDER : LINUX_MIB_TCPSACKREORDER);
}

 /* This must be called before lost_out or retrans_out are updated
  * on a new loss, because we want to know if all skbs previously
  * known to be lost have already been retransmitted, indicating
  * that this newly lost skb is our next skb to retransmit.
  */

static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb)
{
 if ((!tp->retransmit_skb_hint && tp->retrans_out >= tp->lost_out) ||
     (tp->retransmit_skb_hint &&
      before(TCP_SKB_CB(skb)->seq,
      TCP_SKB_CB(tp->retransmit_skb_hint)->seq)))
  tp->retransmit_skb_hint = skb;
}

/* Sum the number of packets on the wire we have marked as lost, and
 * notify the congestion control module that the given skb was marked lost.
 */

static void tcp_notify_skb_loss_event(struct tcp_sock *tp, const struct sk_buff *skb)
{
 tp->lost += tcp_skb_pcount(skb);
}

void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb)
{
 __u8 sacked = TCP_SKB_CB(skb)->sacked;
 struct tcp_sock *tp = tcp_sk(sk);

 if (sacked & TCPCB_SACKED_ACKED)
  return;

 tcp_verify_retransmit_hint(tp, skb);
 if (sacked & TCPCB_LOST) {
  if (sacked & TCPCB_SACKED_RETRANS) {
   /* Account for retransmits that are lost again */
   TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
   tp->retrans_out -= tcp_skb_pcount(skb);
   NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPLOSTRETRANSMIT,
          tcp_skb_pcount(skb));
   tcp_notify_skb_loss_event(tp, skb);
  }
 } else {
  tp->lost_out += tcp_skb_pcount(skb);
  TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
  tcp_notify_skb_loss_event(tp, skb);
 }
}

/* This procedure tags the retransmission queue when SACKs arrive.
 *
 * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L).
 * Packets in queue with these bits set are counted in variables
 * sacked_out, retrans_out and lost_out, correspondingly.
 *
 * Valid combinations are:
 * Tag  InFlight Description
 * 0 1 - orig segment is in flight.
 * S 0 - nothing flies, orig reached receiver.
 * L 0 - nothing flies, orig lost by net.
 * R 2 - both orig and retransmit are in flight.
 * L|R 1 - orig is lost, retransmit is in flight.
 * S|R  1 - orig reached receiver, retrans is still in flight.
 * (L|S|R is logically valid, it could occur when L|R is sacked,
 *  but it is equivalent to plain S and code short-circuits it to S.
 *  L|S is logically invalid, it would mean -1 packet in flight 8))
 *
 * These 6 states form finite state machine, controlled by the following events:
 * 1. New ACK (+SACK) arrives. (tcp_sacktag_write_queue())
 * 2. Retransmission. (tcp_retransmit_skb(), tcp_xmit_retransmit_queue())
 * 3. Loss detection event of two flavors:
 * A. Scoreboard estimator decided the packet is lost.
 *    A'. Reno "three dupacks" marks head of queue lost.
 * B. SACK arrives sacking SND.NXT at the moment, when the
 *    segment was retransmitted.
 * 4. D-SACK added new rule: D-SACK changes any tag to S.
 *
 * It is pleasant to note, that state diagram turns out to be commutative,
 * so that we are allowed not to be bothered by order of our actions,
 * when multiple events arrive simultaneously. (see the function below).
 *
 * Reordering detection.
 * --------------------
 * Reordering metric is maximal distance, which a packet can be displaced
 * in packet stream. With SACKs we can estimate it:
 *
 * 1. SACK fills old hole and the corresponding segment was not
 *    ever retransmitted -> reordering. Alas, we cannot use it
 *    when segment was retransmitted.
 * 2. The last flaw is solved with D-SACK. D-SACK arrives
 *    for retransmitted and already SACKed segment -> reordering..
 * Both of these heuristics are not used in Loss state, when we cannot
 * account for retransmits accurately.
 *
 * SACK block validation.
 * ----------------------
 *
 * SACK block range validation checks that the received SACK block fits to
 * the expected sequence limits, i.e., it is between SND.UNA and SND.NXT.
 * Note that SND.UNA is not included to the range though being valid because
 * it means that the receiver is rather inconsistent with itself reporting
 * SACK reneging when it should advance SND.UNA. Such SACK block this is
 * perfectly valid, however, in light of RFC2018 which explicitly states
 * that "SACK block MUST reflect the newest segment.  Even if the newest
 * segment is going to be discarded ...", not that it looks very clever
 * in case of head skb. Due to potentional receiver driven attacks, we
 * choose to avoid immediate execution of a walk in write queue due to
 * reneging and defer head skb's loss recovery to standard loss recovery
 * procedure that will eventually trigger (nothing forbids us doing this).
 *
 * Implements also blockage to start_seq wrap-around. Problem lies in the
 * fact that though start_seq (s) is before end_seq (i.e., not reversed),
 * there's no guarantee that it will be before snd_nxt (n). The problem
 * happens when start_seq resides between end_seq wrap (e_w) and snd_nxt
 * wrap (s_w):
 *
 *         <- outs wnd ->                          <- wrapzone ->
 *         u     e      n                         u_w   e_w  s n_w
 *         |     |      |                          |     |   |  |
 * |<------------+------+----- TCP seqno space --------------+---------->|
 * ...-- <2^31 ->|                                           |<--------...
 * ...---- >2^31 ------>|                                    |<--------...
 *
 * Current code wouldn't be vulnerable but it's better still to discard such
 * crazy SACK blocks. Doing this check for start_seq alone closes somewhat
 * similar case (end_seq after snd_nxt wrap) as earlier reversed check in
 * snd_nxt wrap -> snd_una region will then become "well defined", i.e.,
 * equal to the ideal case (infinite seqno space without wrap caused issues).
 *
 * With D-SACK the lower bound is extended to cover sequence space below
 * SND.UNA down to undo_marker, which is the last point of interest. Yet
 * again, D-SACK block must not to go across snd_una (for the same reason as
 * for the normal SACK blocks, explained above). But there all simplicity
 * ends, TCP might receive valid D-SACKs below that. As long as they reside
 * fully below undo_marker they do not affect behavior in anyway and can
 * therefore be safely ignored. In rare cases (which are more or less
 * theoretical ones), the D-SACK will nicely cross that boundary due to skb
 * fragmentation and packet reordering past skb's retransmission. To consider
 * them correctly, the acceptable range must be extended even more though
 * the exact amount is rather hard to quantify. However, tp->max_window can
 * be used as an exaggerated estimate.
 */

static bool tcp_is_sackblock_valid(struct tcp_sock *tp, bool is_dsack,
       u32 start_seq, u32 end_seq)
{
 /* Too far in future, or reversed (interpretation is ambiguous) */
 if (after(end_seq, tp->snd_nxt) || !before(start_seq, end_seq))
  return false;

 /* Nasty start_seq wrap-around check (see comments above) */
 if (!before(start_seq, tp->snd_nxt))
  return false;

 /* In outstanding window? ...This is valid exit for D-SACKs too.
 * start_seq == snd_una is non-sensical (see comments above)
 */

 if (after(start_seq, tp->snd_una))
  return true;

 if (!is_dsack || !tp->undo_marker)
  return false;

 /* ...Then it's D-SACK, and must reside below snd_una completely */
 if (after(end_seq, tp->snd_una))
  return false;

 if (!before(start_seq, tp->undo_marker))
  return true;

 /* Too old */
 if (!after(end_seq, tp->undo_marker))
  return false;

 /* Undo_marker boundary crossing (overestimates a lot). Known already:
 *   start_seq < undo_marker and end_seq >= undo_marker.
 */

 return !before(start_seq, end_seq - tp->max_window);
}

static bool tcp_check_dsack(struct sock *sk, const struct sk_buff *ack_skb,
       struct tcp_sack_block_wire *sp, int num_sacks,
       u32 prior_snd_una, struct tcp_sacktag_state *state)
{
 struct tcp_sock *tp = tcp_sk(sk);
 u32 start_seq_0 = get_unaligned_be32(&sp[0].start_seq);
 u32 end_seq_0 = get_unaligned_be32(&sp[0].end_seq);
 u32 dup_segs;

 if (before(start_seq_0, TCP_SKB_CB(ack_skb)->ack_seq)) {
  NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDSACKRECV);
 } else if (num_sacks > 1) {
  u32 end_seq_1 = get_unaligned_be32(&sp[1].end_seq);
  u32 start_seq_1 = get_unaligned_be32(&sp[1].start_seq);

  if (after(end_seq_0, end_seq_1) || before(start_seq_0, start_seq_1))
   return false;
  NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDSACKOFORECV);
 } else {
  return false;
 }

 dup_segs = tcp_dsack_seen(tp, start_seq_0, end_seq_0, state);
 if (!dup_segs) { /* Skip dubious DSACK */
  NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDSACKIGNOREDDUBIOUS);
  return false;
 }

 NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPDSACKRECVSEGS, dup_segs);

 /* D-SACK for already forgotten data... Do dumb counting. */
 if (tp->undo_marker && tp->undo_retrans > 0 &&
     !after(end_seq_0, prior_snd_una) &&
     after(end_seq_0, tp->undo_marker))
  tp->undo_retrans = max_t(int, 0, tp->undo_retrans - dup_segs);

 return true;
}

/* Check if skb is fully within the SACK block. In presence of GSO skbs,
 * the incoming SACK may not exactly match but we can find smaller MSS
 * aligned portion of it that matches. Therefore we might need to fragment
 * which may fail and creates some hassle (caller must handle error case
 * returns).
 *
 * FIXME: this could be merged to shift decision code
 */

static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
      u32 start_seq, u32 end_seq)
{
 int err;
 bool in_sack;
 unsigned int pkt_len;
 unsigned int mss;

 in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
    !before(end_seq, TCP_SKB_CB(skb)->end_seq);

 if (tcp_skb_pcount(skb) > 1 && !in_sack &&
     after(TCP_SKB_CB(skb)->end_seq, start_seq)) {
  mss = tcp_skb_mss(skb);
  in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq);

  if (!in_sack) {
   pkt_len = start_seq - TCP_SKB_CB(skb)->seq;
   if (pkt_len < mss)
    pkt_len = mss;
  } else {
   pkt_len = end_seq - TCP_SKB_CB(skb)->seq;
   if (pkt_len < mss)
    return -EINVAL;
  }

  /* Round if necessary so that SACKs cover only full MSSes
 * and/or the remaining small portion (if present)
 */

  if (pkt_len > mss) {
   unsigned int new_len = (pkt_len / mss) * mss;
   if (!in_sack && new_len < pkt_len)
    new_len += mss;
   pkt_len = new_len;
  }

  if (pkt_len >= skb->len && !in_sack)
   return 0;

  err = tcp_fragment(sk, TCP_FRAG_IN_RTX_QUEUE, skb,
       pkt_len, mss, GFP_ATOMIC);
  if (err < 0)
   return err;
 }

 return in_sack;
}

/* Mark the given newly-SACKed range as such, adjusting counters and hints. */
static u8 tcp_sacktag_one(struct sock *sk,
     struct tcp_sacktag_state *state, u8 sacked,
     u32 start_seq, u32 end_seq,
     int dup_sack, int pcount,
     u64 xmit_time)
{
 struct tcp_sock *tp = tcp_sk(sk);

 /* Account D-SACK for retransmitted packet. */
 if (dup_sack && (sacked & TCPCB_RETRANS)) {
  if (tp->undo_marker && tp->undo_retrans > 0 &&
      after(end_seq, tp->undo_marker))
   tp->undo_retrans = max_t(int, 0, tp->undo_retrans - pcount);
  if ((sacked & TCPCB_SACKED_ACKED) &&
      before(start_seq, state->reord))
    state->reord = start_seq;
 }

 /* Nothing to do; acked frame is about to be dropped (was ACKed). */
 if (!after(end_seq, tp->snd_una))
  return sacked;

 if (!(sacked & TCPCB_SACKED_ACKED)) {
  tcp_rack_advance(tp, sacked, end_seq, xmit_time);

  if (sacked & TCPCB_SACKED_RETRANS) {
   /* If the segment is not tagged as lost,
 * we do not clear RETRANS, believing
 * that retransmission is still in flight.
 */

   if (sacked & TCPCB_LOST) {
    sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS);
    tp->lost_out -= pcount;
    tp->retrans_out -= pcount;
   }
  } else {
   if (!(sacked & TCPCB_RETRANS)) {
    /* New sack for not retransmitted frame,
 * which was in hole. It is reordering.
 */

    if (before(start_seq,
        tcp_highest_sack_seq(tp)) &&
        before(start_seq, state->reord))
     state->reord = start_seq;

    if (!after(end_seq, tp->high_seq))
     state->flag |= FLAG_ORIG_SACK_ACKED;
    if (state->first_sackt == 0)
     state->first_sackt = xmit_time;
    state->last_sackt = xmit_time;
   }

   if (sacked & TCPCB_LOST) {
    sacked &= ~TCPCB_LOST;
    tp->lost_out -= pcount;
   }
  }

  sacked |= TCPCB_SACKED_ACKED;
  state->flag |= FLAG_DATA_SACKED;
  tp->sacked_out += pcount;
  /* Out-of-order packets delivered */
  state->sack_delivered += pcount;
 }

 /* D-SACK. We can detect redundant retransmission in S|R and plain R
 * frames and clear it. undo_retrans is decreased above, L|R frames
 * are accounted above as well.
 */

 if (dup_sack && (sacked & TCPCB_SACKED_RETRANS)) {
  sacked &= ~TCPCB_SACKED_RETRANS;
  tp->retrans_out -= pcount;
 }

 return sacked;
}

/* Shift newly-SACKed bytes from this skb to the immediately previous
 * already-SACKed sk_buff. Mark the newly-SACKed bytes as such.
 */

static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *prev,
       struct sk_buff *skb,
       struct tcp_sacktag_state *state,
       unsigned int pcount, int shifted, int mss,
       bool dup_sack)
{
 struct tcp_sock *tp = tcp_sk(sk);
 u32 start_seq = TCP_SKB_CB(skb)->seq; /* start of newly-SACKed */
 u32 end_seq = start_seq + shifted; /* end of newly-SACKed */

 BUG_ON(!pcount);

 /* Adjust counters and hints for the newly sacked sequence
 * range but discard the return value since prev is already
 * marked. We must tag the range first because the seq
 * advancement below implicitly advances
 * tcp_highest_sack_seq() when skb is highest_sack.
 */

 tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked,
   start_seq, end_seq, dup_sack, pcount,
   tcp_skb_timestamp_us(skb));
 tcp_rate_skb_delivered(sk, skb, state->rate);

 TCP_SKB_CB(prev)->end_seq += shifted;
 TCP_SKB_CB(skb)->seq += shifted;

 tcp_skb_pcount_add(prev, pcount);
 WARN_ON_ONCE(tcp_skb_pcount(skb) < pcount);
 tcp_skb_pcount_add(skb, -pcount);

 /* When we're adding to gso_segs == 1, gso_size will be zero,
 * in theory this shouldn't be necessary but as long as DSACK
 * code can come after this skb later on it's better to keep
 * setting gso_size to something.
 */

 if (!TCP_SKB_CB(prev)->tcp_gso_size)
  TCP_SKB_CB(prev)->tcp_gso_size = mss;

 /* CHECKME: To clear or not to clear? Mimics normal skb currently */
 if (tcp_skb_pcount(skb) <= 1)
  TCP_SKB_CB(skb)->tcp_gso_size = 0;

 /* Difference in this won't matter, both ACKed by the same cumul. ACK */
 TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS);

 if (skb->len > 0) {
  BUG_ON(!tcp_skb_pcount(skb));
  NET_INC_STATS(sock_net(sk), LINUX_MIB_SACKSHIFTED);
  return false;
 }

 /* Whole SKB was eaten :-) */

 if (skb == tp->retransmit_skb_hint)
  tp->retransmit_skb_hint = prev;

 TCP_SKB_CB(prev)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags;
 TCP_SKB_CB(prev)->eor = TCP_SKB_CB(skb)->eor;
 if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
  TCP_SKB_CB(prev)->end_seq++;

 if (skb == tcp_highest_sack(sk))
  tcp_advance_highest_sack(sk, skb);

 tcp_skb_collapse_tstamp(prev, skb);
 if (unlikely(TCP_SKB_CB(prev)->tx.delivered_mstamp))
  TCP_SKB_CB(prev)->tx.delivered_mstamp = 0;

 tcp_rtx_queue_unlink_and_free(skb, sk);

 NET_INC_STATS(sock_net(sk), LINUX_MIB_SACKMERGED);

 return true;
}

/* I wish gso_size would have a bit more sane initialization than
 * something-or-zero which complicates things
 */

static int tcp_skb_seglen(const struct sk_buff *skb)
{
 return tcp_skb_pcount(skb) == 1 ? skb->len : tcp_skb_mss(skb);
}

/* Shifting pages past head area doesn't work */
static int skb_can_shift(const struct sk_buff *skb)
{
 return !skb_headlen(skb) && skb_is_nonlinear(skb);
}

int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from,
    int pcount, int shiftlen)
{
 /* TCP min gso_size is 8 bytes (TCP_MIN_GSO_SIZE)
 * Since TCP_SKB_CB(skb)->tcp_gso_segs is 16 bits, we need
 * to make sure not storing more than 65535 * 8 bytes per skb,
 * even if current MSS is bigger.
 */

 if (unlikely(to->len + shiftlen >= 65535 * TCP_MIN_GSO_SIZE))
  return 0;
 if (unlikely(tcp_skb_pcount(to) + pcount > 65535))
  return 0;
 return skb_shift(to, from, shiftlen);
}

/* Try collapsing SACK blocks spanning across multiple skbs to a single
 * skb.
 */

static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
       struct tcp_sacktag_state *state,
       u32 start_seq, u32 end_seq,
       bool dup_sack)
{
 struct tcp_sock *tp = tcp_sk(sk);
 struct sk_buff *prev;
 int mss;
 int pcount = 0;
 int len;
 int in_sack;

 /* Normally R but no L won't result in plain S */
 if (!dup_sack &&
     (TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_RETRANS)) == TCPCB_SACKED_RETRANS)
  goto fallback;
 if (!skb_can_shift(skb))
  goto fallback;
 /* This frame is about to be dropped (was ACKed). */
 if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
  goto fallback;

 /* Can only happen with delayed DSACK + discard craziness */
 prev = skb_rb_prev(skb);
 if (!prev)
  goto fallback;

 if ((TCP_SKB_CB(prev)->sacked & TCPCB_TAGBITS) != TCPCB_SACKED_ACKED)
  goto fallback;

 if (!tcp_skb_can_collapse(prev, skb))
  goto fallback;

 in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
    !before(end_seq, TCP_SKB_CB(skb)->end_seq);

 if (in_sack) {
  len = skb->len;
  pcount = tcp_skb_pcount(skb);
  mss = tcp_skb_seglen(skb);

  /* TODO: Fix DSACKs to not fragment already SACKed and we can
 * drop this restriction as unnecessary
 */

  if (mss != tcp_skb_seglen(prev))
   goto fallback;
 } else {
  if (!after(TCP_SKB_CB(skb)->end_seq, start_seq))
   goto noop;
  /* CHECKME: This is non-MSS split case only?, this will
 * cause skipped skbs due to advancing loop btw, original
 * has that feature too
 */

  if (tcp_skb_pcount(skb) <= 1)
   goto noop;

  in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq);
  if (!in_sack) {
   /* TODO: head merge to next could be attempted here
 * if (!after(TCP_SKB_CB(skb)->end_seq, end_seq)),
 * though it might not be worth of the additional hassle
 *
 * ...we can probably just fallback to what was done
 * previously. We could try merging non-SACKed ones
 * as well but it probably isn't going to buy off
 * because later SACKs might again split them, and
 * it would make skb timestamp tracking considerably
 * harder problem.
 */

   goto fallback;
  }

  len = end_seq - TCP_SKB_CB(skb)->seq;
  BUG_ON(len < 0);
  BUG_ON(len > skb->len);

  /* MSS boundaries should be honoured or else pcount will
 * severely break even though it makes things bit trickier.
 * Optimize common case to avoid most of the divides
 */

  mss = tcp_skb_mss(skb);

  /* TODO: Fix DSACKs to not fragment already SACKed and we can
 * drop this restriction as unnecessary
 */

  if (mss != tcp_skb_seglen(prev))
   goto fallback;

  if (len == mss) {
   pcount = 1;
  } else if (len < mss) {
   goto noop;
  } else {
   pcount = len / mss;
   len = pcount * mss;
  }
 }

 /* tcp_sacktag_one() won't SACK-tag ranges below snd_una */
 if (!after(TCP_SKB_CB(skb)->seq + len, tp->snd_una))
  goto fallback;

 if (!tcp_skb_shift(prev, skb, pcount, len))
  goto fallback;
 if (!tcp_shifted_skb(sk, prev, skb, state, pcount, len, mss, dup_sack))
  goto out;

 /* Hole filled allows collapsing with the next as well, this is very
 * useful when hole on every nth skb pattern happens
 */

 skb = skb_rb_next(prev);
 if (!skb)
  goto out;

 if (!skb_can_shift(skb) ||
     ((TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS) != TCPCB_SACKED_ACKED) ||
     (mss != tcp_skb_seglen(skb)))
  goto out;

 if (!tcp_skb_can_collapse(prev, skb))
  goto out;
 len = skb->len;
 pcount = tcp_skb_pcount(skb);
 if (tcp_skb_shift(prev, skb, pcount, len))
  tcp_shifted_skb(sk, prev, skb, state, pcount,
    len, mss, 0);

out:
 return prev;

noop:
 return skb;

fallback:
 NET_INC_STATS(sock_net(sk), LINUX_MIB_SACKSHIFTFALLBACK);
 return NULL;
}

static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk,
     struct tcp_sack_block *next_dup,
     struct tcp_sacktag_state *state,
     u32 start_seq, u32 end_seq,
     bool dup_sack_in)
{
 struct tcp_sock *tp = tcp_sk(sk);
 struct sk_buff *tmp;

 skb_rbtree_walk_from(skb) {
  int in_sack = 0;
  bool dup_sack = dup_sack_in;

  /* queue is in-order => we can short-circuit the walk early */
  if (!before(TCP_SKB_CB(skb)->seq, end_seq))
   break;

  if (next_dup  &&
      before(TCP_SKB_CB(skb)->seq, next_dup->end_seq)) {
   in_sack = tcp_match_skb_to_sack(sk, skb,
       next_dup->start_seq,
       next_dup->end_seq);
   if (in_sack > 0)
    dup_sack = true;
  }

  /* skb reference here is a bit tricky to get right, since
 * shifting can eat and free both this skb and the next,
 * so not even _safe variant of the loop is enough.
 */

  if (in_sack <= 0) {
   tmp = tcp_shift_skb_data(sk, skb, state,
       start_seq, end_seq, dup_sack);
   if (tmp) {
    if (tmp != skb) {
     skb = tmp;
     continue;
    }

    in_sack = 0;
   } else {
    in_sack = tcp_match_skb_to_sack(sk, skb,
        start_seq,
        end_seq);
   }
  }

  if (unlikely(in_sack < 0))
   break;

  if (in_sack) {
   TCP_SKB_CB(skb)->sacked =
    tcp_sacktag_one(sk,
      state,
      TCP_SKB_CB(skb)->sacked,
      TCP_SKB_CB(skb)->seq,
      TCP_SKB_CB(skb)->end_seq,
      dup_sack,
      tcp_skb_pcount(skb),
      tcp_skb_timestamp_us(skb));
   tcp_rate_skb_delivered(sk, skb, state->rate);
   if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
    list_del_init(&skb->tcp_tsorted_anchor);

   if (!before(TCP_SKB_CB(skb)->seq,
        tcp_highest_sack_seq(tp)))
    tcp_advance_highest_sack(sk, skb);
  }
 }
 return skb;
}

static struct sk_buff *tcp_sacktag_bsearch(struct sock *sk, u32 seq)
{
 struct rb_node *parent, **p = &sk->tcp_rtx_queue.rb_node;
 struct sk_buff *skb;

 while (*p) {
  parent = *p;
  skb = rb_to_skb(parent);
  if (before(seq, TCP_SKB_CB(skb)->seq)) {
   p = &parent->rb_left;
   continue;
  }
  if (!before(seq, TCP_SKB_CB(skb)->end_seq)) {
   p = &parent->rb_right;
   continue;
  }
  return skb;
 }
 return NULL;
}

static struct sk_buff *tcp_sacktag_skip(struct sk_buff *skb, struct sock *sk,
     u32 skip_to_seq)
{
 if (skb && after(TCP_SKB_CB(skb)->seq, skip_to_seq))
  return skb;

 return tcp_sacktag_bsearch(sk, skip_to_seq);
}

static struct sk_buff *tcp_maybe_skipping_dsack(struct sk_buff *skb,
      struct sock *sk,
      struct tcp_sack_block *next_dup,
      struct tcp_sacktag_state *state,
      u32 skip_to_seq)
{
 if (!next_dup)
  return skb;

 if (before(next_dup->start_seq, skip_to_seq)) {
  skb = tcp_sacktag_skip(skb, sk, next_dup->start_seq);
  skb = tcp_sacktag_walk(skb, sk, NULL, state,
           next_dup->start_seq, next_dup->end_seq,
           1);
 }

 return skb;
}

static int tcp_sack_cache_ok(const struct tcp_sock *tp, const struct tcp_sack_block *cache)
{
 return cache < tp->recv_sack_cache + ARRAY_SIZE(tp->recv_sack_cache);
}

static int
tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
   u32 prior_snd_una, struct tcp_sacktag_state *state)
{
 struct tcp_sock *tp = tcp_sk(sk);
 const unsigned char *ptr = (skb_transport_header(ack_skb) +
        TCP_SKB_CB(ack_skb)->sacked);
 struct tcp_sack_block_wire *sp_wire = (struct tcp_sack_block_wire *)(ptr+2);
 struct tcp_sack_block sp[TCP_NUM_SACKS];
 struct tcp_sack_block *cache;
 struct sk_buff *skb;
 int num_sacks = min(TCP_NUM_SACKS, (ptr[1] - TCPOLEN_SACK_BASE) >> 3);
 int used_sacks;
 bool found_dup_sack = false;
 int i, j;
 int first_sack_index;

 state->flag = 0;
 state->reord = tp->snd_nxt;

 if (!tp->sacked_out)
  tcp_highest_sack_reset(sk);

 found_dup_sack = tcp_check_dsack(sk, ack_skb, sp_wire,
      num_sacks, prior_snd_una, state);

 /* Eliminate too old ACKs, but take into
 * account more or less fresh ones, they can
 * contain valid SACK info.
 */

 if (before(TCP_SKB_CB(ack_skb)->ack_seq, prior_snd_una - tp->max_window))
  return 0;

 if (!tp->packets_out)
  goto out;

 used_sacks = 0;
 first_sack_index = 0;
 for (i = 0; i < num_sacks; i++) {
  bool dup_sack = !i && found_dup_sack;

  sp[used_sacks].start_seq = get_unaligned_be32(&sp_wire[i].start_seq);
  sp[used_sacks].end_seq = get_unaligned_be32(&sp_wire[i].end_seq);

  if (!tcp_is_sackblock_valid(tp, dup_sack,
         sp[used_sacks].start_seq,
         sp[used_sacks].end_seq)) {
   int mib_idx;

   if (dup_sack) {
    if (!tp->undo_marker)
     mib_idx = LINUX_MIB_TCPDSACKIGNOREDNOUNDO;
    else
     mib_idx = LINUX_MIB_TCPDSACKIGNOREDOLD;
   } else {
    /* Don't count olds caused by ACK reordering */
    if ((TCP_SKB_CB(ack_skb)->ack_seq != tp->snd_una) &&
        !after(sp[used_sacks].end_seq, tp->snd_una))
     continue;
    mib_idx = LINUX_MIB_TCPSACKDISCARD;
   }

   NET_INC_STATS(sock_net(sk), mib_idx);
   if (i == 0)
    first_sack_index = -1;
   continue;
  }

  /* Ignore very old stuff early */
  if (!after(sp[used_sacks].end_seq, prior_snd_una)) {
   if (i == 0)
    first_sack_index = -1;
   continue;
  }

  used_sacks++;
 }

 /* order SACK blocks to allow in order walk of the retrans queue */
 for (i = used_sacks - 1; i > 0; i--) {
  for (j = 0; j < i; j++) {
   if (after(sp[j].start_seq, sp[j + 1].start_seq)) {
    swap(sp[j], sp[j + 1]);

    /* Track where the first SACK block goes to */
    if (j == first_sack_index)
     first_sack_index = j + 1;
   }
  }
 }

 state->mss_now = tcp_current_mss(sk);
 skb = NULL;
 i = 0;

 if (!tp->sacked_out) {
  /* It's already past, so skip checking against it */
  cache = tp->recv_sack_cache + ARRAY_SIZE(tp->recv_sack_cache);
 } else {
  cache = tp->recv_sack_cache;
  /* Skip empty blocks in at head of the cache */
  while (tcp_sack_cache_ok(tp, cache) && !cache->start_seq &&
         !cache->end_seq)
   cache++;
 }

 while (i < used_sacks) {
  u32 start_seq = sp[i].start_seq;
  u32 end_seq = sp[i].end_seq;
  bool dup_sack = (found_dup_sack && (i == first_sack_index));
  struct tcp_sack_block *next_dup = NULL;

  if (found_dup_sack && ((i + 1) == first_sack_index))
   next_dup = &sp[i + 1];

  /* Skip too early cached blocks */
  while (tcp_sack_cache_ok(tp, cache) &&
         !before(start_seq, cache->end_seq))
   cache++;

  /* Can skip some work by looking recv_sack_cache? */
  if (tcp_sack_cache_ok(tp, cache) && !dup_sack &&
      after(end_seq, cache->start_seq)) {

   /* Head todo? */
   if (before(start_seq, cache->start_seq)) {
    skb = tcp_sacktag_skip(skb, sk, start_seq);
    skb = tcp_sacktag_walk(skb, sk, next_dup,
             state,
             start_seq,
             cache->start_seq,
             dup_sack);
   }

   /* Rest of the block already fully processed? */
   if (!after(end_seq, cache->end_seq))
    goto advance_sp;

   skb = tcp_maybe_skipping_dsack(skb, sk, next_dup,
             state,
             cache->end_seq);

   /* ...tail remains todo... */
   if (tcp_highest_sack_seq(tp) == cache->end_seq) {
    /* ...but better entrypoint exists! */
    skb = tcp_highest_sack(sk);
    if (!skb)
     break;
    cache++;
    goto walk;
   }

   skb = tcp_sacktag_skip(skb, sk, cache->end_seq);
   /* Check overlap against next cached too (past this one already) */
   cache++;
   continue;
  }

  if (!before(start_seq, tcp_highest_sack_seq(tp))) {
   skb = tcp_highest_sack(sk);
   if (!skb)
    break;
  }
  skb = tcp_sacktag_skip(skb, sk, start_seq);

walk:
  skb = tcp_sacktag_walk(skb, sk, next_dup, state,
           start_seq, end_seq, dup_sack);

advance_sp:
  i++;
 }

 /* Clear the head of the cache sack blocks so we can skip it next time */
 for (i = 0; i < ARRAY_SIZE(tp->recv_sack_cache) - used_sacks; i++) {
  tp->recv_sack_cache[i].start_seq = 0;
  tp->recv_sack_cache[i].end_seq = 0;
 }
 for (j = 0; j < used_sacks; j++)
  tp->recv_sack_cache[i++] = sp[j];

 if (inet_csk(sk)->icsk_ca_state != TCP_CA_Loss || tp->undo_marker)
  tcp_check_sack_reordering(sk, state->reord, 0);

 tcp_verify_left_out(tp);
out:

#if FASTRETRANS_DEBUG > 0
 WARN_ON((int)tp->sacked_out < 0);
 WARN_ON((int)tp->lost_out < 0);
 WARN_ON((int)tp->retrans_out < 0);
 WARN_ON((int)tcp_packets_in_flight(tp) < 0);
#endif
 return state->flag;
}

/* Limits sacked_out so that sum with lost_out isn't ever larger than
 * packets_out. Returns false if sacked_out adjustement wasn't necessary.
 */

static bool tcp_limit_reno_sacked(struct tcp_sock *tp)
{
 u32 holes;

 holes = max(tp->lost_out, 1U);
 holes = min(holes, tp->packets_out);

 if ((tp->sacked_out + holes) > tp->packets_out) {
  tp->sacked_out = tp->packets_out - holes;
  return true;
 }
 return false;
}

/* If we receive more dupacks than we expected counting segments
 * in assumption of absent reordering, interpret this as reordering.
 * The only another reason could be bug in receiver TCP.
 */

static void tcp_check_reno_reordering(struct sock *sk, const int addend)
{
 struct tcp_sock *tp = tcp_sk(sk);

 if (!tcp_limit_reno_sacked(tp))
  return;

 tp->reordering = min_t(u32, tp->packets_out + addend,
          READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_max_reordering));
 tp->reord_seen++;
 NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRENOREORDER);
}

/* Emulate SACKs for SACKless connection: account for a new dupack. */

static void tcp_add_reno_sack(struct sock *sk, int num_dupack, bool ece_ack)
{
 if (num_dupack) {
  struct tcp_sock *tp = tcp_sk(sk);
  u32 prior_sacked = tp->sacked_out;
  s32 delivered;

  tp->sacked_out += num_dupack;
  tcp_check_reno_reordering(sk, 0);
  delivered = tp->sacked_out - prior_sacked;
  if (delivered > 0)
   tcp_count_delivered(tp, delivered, ece_ack);
  tcp_verify_left_out(tp);
 }
}

/* Account for ACK, ACKing some data in Reno Recovery phase. */

static void tcp_remove_reno_sacks(struct sock *sk, int acked, bool ece_ack)
{
 struct tcp_sock *tp = tcp_sk(sk);

 if (acked > 0) {
  /* One ACK acked hole. The rest eat duplicate ACKs. */
  tcp_count_delivered(tp, max_t(int, acked - tp->sacked_out, 1),
        ece_ack);
  if (acked - 1 >= tp->sacked_out)
   tp->sacked_out = 0;
  else
   tp->sacked_out -= acked - 1;
 }
 tcp_check_reno_reordering(sk, acked);
 tcp_verify_left_out(tp);
}

--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.30 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.