tcp: keep snd sack block free list
[vpp.git] / src / vnet / tcp / tcp.h
index 4626297..65182c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Copyright (c) 2016-2019 Cisco and/or its affiliates.
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
@@ -30,7 +30,7 @@
 #define TCP_PAWS_IDLE 24 * 24 * 60 * 60 * THZ /**< 24 days */
 #define TCP_FIB_RECHECK_PERIOD 1 * THZ /**< Recheck every 1s */
 #define TCP_MAX_OPTION_SPACE 40
-#define TCP_CC_DATA_SZ 20
+#define TCP_CC_DATA_SZ 24
 
 #define TCP_DUPACK_THRESHOLD   3
 #define TCP_MAX_RX_FIFO_SIZE   32 << 20
@@ -74,7 +74,8 @@ format_function_t format_tcp_rcv_sacks;
   _(KEEP, "KEEP")                       \
   _(WAITCLOSE, "WAIT CLOSE")            \
   _(RETRANSMIT_SYN, "RETRANSMIT SYN")   \
-  _(ESTABLISH, "ESTABLISH")
+  _(ESTABLISH, "ESTABLISH")            \
+  _(ESTABLISH_AO, "ESTABLISH_AO")      \
 
 typedef enum _tcp_timers
 {
@@ -102,7 +103,8 @@ extern timer_expiration_handler tcp_timer_retransmit_syn_handler;
 #define TCP_2MSL_TIME           300    /* 30s */
 #define TCP_CLOSEWAIT_TIME     20      /* 2s */
 #define TCP_TIMEWAIT_TIME      100     /* 10s */
-#define TCP_CLEANUP_TIME       10      /* 1s Time to wait before cleanup */
+#define TCP_FINWAIT1_TIME      600     /* 60s */
+#define TCP_CLEANUP_TIME       1       /* 0.1s */
 #define TCP_TIMER_PERSIST_MIN  2       /* 0.2s */
 
 #define TCP_RTO_MAX 60 * THZ   /* Min max RTO (60s) as per RFC6298 */
@@ -118,12 +120,13 @@ extern timer_expiration_handler tcp_timer_retransmit_syn_handler;
   _(SENT_RCV_WND0, "Sent 0 rcv_wnd")           \
   _(RECOVERY, "Recovery")                      \
   _(FAST_RECOVERY, "Fast Recovery")            \
-  _(FR_1_SMSS, "Sent 1 SMSS")                  \
+  _(DCNT_PENDING, "Disconnect pending")                \
   _(HALF_OPEN_DONE, "Half-open completed")     \
   _(FINPNDG, "FIN pending")                    \
   _(FRXT_PENDING, "Fast-retransmit pending")   \
   _(FRXT_FIRST, "Fast-retransmit first again") \
   _(DEQ_PENDING, "Pending dequeue acked")      \
+  _(PSH_PENDING, "PSH pending")                        \
 
 typedef enum _tcp_connection_flag_bits
 {
@@ -300,6 +303,8 @@ typedef struct _tcp_connection
   tcp_options_t rcv_opts;      /**< Rx options for connection */
 
   sack_block_t *snd_sacks;     /**< Vector of SACKs to send. XXX Fixed size? */
+  u8 snd_sack_pos;             /**< Position in vec of first block to send */
+  sack_block_t *snd_sacks_fl;  /**< Vector for building new list */
   sack_scoreboard_t sack_sb;   /**< SACK "scoreboard" that tracks holes */
 
   u16 rcv_dupacks;     /**< Number of DUPACKs received */
@@ -334,16 +339,22 @@ typedef struct _tcp_connection
   u32 last_fib_check;  /**< Last time we checked fib route for peer */
   u32 sw_if_index;     /**< Interface for the connection */
   u32 tx_fifo_size;    /**< Tx fifo size. Used to constrain cwnd */
+
+  u32 psh_seq;         /**< Add psh header for seg that includes this */
 } tcp_connection_t;
 
+/* *INDENT-OFF* */
 struct _tcp_cc_algorithm
 {
+  const char *name;
+  uword (*unformat_cfg) (unformat_input_t * input);
   void (*rcv_ack) (tcp_connection_t * tc);
   void (*rcv_cong_ack) (tcp_connection_t * tc, tcp_cc_ack_t ack);
   void (*congestion) (tcp_connection_t * tc);
   void (*recovered) (tcp_connection_t * tc);
   void (*init) (tcp_connection_t * tc);
 };
+/* *INDENT-ON* */
 
 #define tcp_fastrecovery_on(tc) (tc)->flags |= TCP_CONN_FAST_RECOVERY
 #define tcp_fastrecovery_off(tc) (tc)->flags &= ~TCP_CONN_FAST_RECOVERY
@@ -352,9 +363,9 @@ struct _tcp_cc_algorithm
 #define tcp_in_fastrecovery(tc) ((tc)->flags & TCP_CONN_FAST_RECOVERY)
 #define tcp_in_recovery(tc) ((tc)->flags & (TCP_CONN_RECOVERY))
 #define tcp_in_slowstart(tc) (tc->cwnd < tc->ssthresh)
-#define tcp_fastrecovery_sent_1_smss(tc) ((tc)->flags & TCP_CONN_FR_1_SMSS)
-#define tcp_fastrecovery_1_smss_on(tc) ((tc)->flags |= TCP_CONN_FR_1_SMSS)
-#define tcp_fastrecovery_1_smss_off(tc) ((tc)->flags &= ~TCP_CONN_FR_1_SMSS)
+#define tcp_disconnect_pending(tc) ((tc)->flags & TCP_CONN_DCNT_PENDING)
+#define tcp_disconnect_pending_on(tc) ((tc)->flags |= TCP_CONN_DCNT_PENDING)
+#define tcp_disconnect_pending_off(tc) ((tc)->flags &= ~TCP_CONN_DCNT_PENDING)
 #define tcp_fastrecovery_first(tc) ((tc)->flags & TCP_CONN_FRXT_FIRST)
 #define tcp_fastrecovery_first_on(tc) ((tc)->flags |= TCP_CONN_FRXT_FIRST)
 #define tcp_fastrecovery_first_off(tc) ((tc)->flags &= ~TCP_CONN_FRXT_FIRST)
@@ -366,7 +377,6 @@ always_inline void
 tcp_cong_recovery_off (tcp_connection_t * tc)
 {
   tc->flags &= ~(TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY);
-  tcp_fastrecovery_1_smss_off (tc);
   tcp_fastrecovery_first_off (tc);
 }
 
@@ -386,29 +396,55 @@ typedef struct _tcp_lookup_dispatch
 typedef struct tcp_worker_ctx_
 {
   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
-  u32 time_now;                                        /**< worker time */
-  tw_timer_wheel_16t_2w_512sl_t timer_wheel;   /**< worker timer wheel */
-  u32 *tx_buffers;                             /**< tx buffer free list */
-  vlib_frame_t *tx_frames[2];                  /**< tx frames for tcp 4/6
-                                                    output nodes */
-  vlib_frame_t *ip_lookup_tx_frames[2];                /**< tx frames for ip 4/6
-                                                    lookup nodes */
-  u32 *pending_fast_rxt;                       /**< vector of connections
-                                                    needing fast rxt */
-  u32 *ongoing_fast_rxt;                       /**< vector of connections
-                                                    now doing fast rxt */
-  u32 *postponed_fast_rxt;                     /**< vector of connections
-                                                    that will do fast rxt */
+  /** worker time */
+  u32 time_now;
+
+  /** worker timer wheel */
+  tw_timer_wheel_16t_2w_512sl_t timer_wheel;
+
+  /** tx buffer free list */
+  u32 *tx_buffers;
+
+  /** tx frames for tcp 4/6 output nodes */
+  vlib_frame_t *tx_frames[2];
+
+  /** tx frames for ip 4/6 lookup nodes */
+  vlib_frame_t *ip_lookup_tx_frames[2];
+
+  /** vector of connections needing fast rxt */
+  u32 *pending_fast_rxt;
+
+  /** vector of connections now doing fast rxt */
+  u32 *ongoing_fast_rxt;
+
+  /** vector of connections that will do fast rxt */
+  u32 *postponed_fast_rxt;
+
+  /** vector of pending ack dequeues */
   u32 *pending_deq_acked;
+
+  /** vector of pending acks */
   u32 *pending_acks;
-  vlib_main_t *vm;                             /**< pointer to vm */
+
+  /** vector of pending disconnect notifications */
+  u32 *pending_disconnects;
+
+  /** convenience pointer to this thread's vlib main */
+  vlib_main_t *vm;
 
     CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
-  u8 cached_opts[40];                          /**< cached 'on the wire'
-                                                    options for bursts */
+
+  /** cached 'on the wire' options for bursts */
+  u8 cached_opts[40];
 
 } tcp_worker_ctx_t;
 
+typedef struct tcp_iss_seed_
+{
+  u64 first;
+  u64 second;
+} tcp_iss_seed_t;
+
 typedef struct _tcp_main
 {
   /* Per-worker thread tcp connection pools */
@@ -436,6 +472,9 @@ typedef struct _tcp_main
   /** vlib buffer size */
   u32 bytes_per_buffer;
 
+  /* Seed used to generate random iss */
+  tcp_iss_seed_t iss_seed;
+
   /*
    * Configuration
    */
@@ -466,7 +505,9 @@ typedef struct _tcp_main
   /** fault-injection */
   f64 buffer_fail_fraction;
 
-  u8 cc_algo;
+  /** Default congestion control algorithm type */
+  tcp_cc_algorithm_type_e cc_algo;
+
 } tcp_main_t;
 
 extern tcp_main_t tcp_main;
@@ -533,11 +574,19 @@ tcp_get_connection_from_transport (transport_connection_t * tconn)
   return (tcp_connection_t *) tconn;
 }
 
+always_inline void
+tcp_connection_set_state (tcp_connection_t * tc, tcp_state_t state)
+{
+  tc->state = state;
+  TCP_EVT_DBG (TCP_EVT_STATE_CHANGE, tc);
+}
+
 void tcp_connection_close (tcp_connection_t * tc);
 void tcp_connection_cleanup (tcp_connection_t * tc);
 void tcp_connection_del (tcp_connection_t * tc);
 int tcp_half_open_connection_cleanup (tcp_connection_t * tc);
-tcp_connection_t *tcp_connection_new (u8 thread_index);
+tcp_connection_t *tcp_connection_alloc (u8 thread_index);
+void tcp_connection_free (tcp_connection_t * tc);
 void tcp_connection_reset (tcp_connection_t * tc);
 int tcp_configure_v4_source_address_range (vlib_main_t * vm,
                                           ip4_address_t * start,
@@ -565,11 +614,10 @@ tcp_half_open_connection_get (u32 conn_index)
   return tc;
 }
 
-void tcp_make_ack (tcp_connection_t * ts, vlib_buffer_t * b);
 void tcp_make_fin (tcp_connection_t * tc, vlib_buffer_t * b);
 void tcp_make_synack (tcp_connection_t * ts, vlib_buffer_t * b);
 void tcp_send_reset_w_pkt (tcp_connection_t * tc, vlib_buffer_t * pkt,
-                          u8 is_ip4);
+                          u32 thread_index, u8 is_ip4);
 void tcp_send_reset (tcp_connection_t * tc);
 void tcp_send_syn (tcp_connection_t * tc);
 void tcp_send_synack (tcp_connection_t * tc);