tcp: basic cubic implementation
[vpp.git] / src / vnet / tcp / tcp.h
index 71af461..4626297 100644 (file)
@@ -30,6 +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_DUPACK_THRESHOLD   3
 #define TCP_MAX_RX_FIFO_SIZE   32 << 20
@@ -122,6 +123,7 @@ extern timer_expiration_handler tcp_timer_retransmit_syn_handler;
   _(FINPNDG, "FIN pending")                    \
   _(FRXT_PENDING, "Fast-retransmit pending")   \
   _(FRXT_FIRST, "Fast-retransmit first again") \
+  _(DEQ_PENDING, "Pending dequeue acked")      \
 
 typedef enum _tcp_connection_flag_bits
 {
@@ -248,6 +250,7 @@ u8 *format_tcp_scoreboard (u8 * s, va_list * args);
 typedef enum _tcp_cc_algorithm_type
 {
   TCP_CC_NEWRENO,
+  TCP_CC_CUBIC,
 } tcp_cc_algorithm_type_e;
 
 typedef struct _tcp_cc_algorithm tcp_cc_algorithm_t;
@@ -261,6 +264,7 @@ typedef enum _tcp_cc_ack_t
 
 typedef struct _tcp_connection
 {
+  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
   transport_connection_t connection;  /**< Common transport data. First! */
 
   u8 state;                    /**< TCP state as per tcp_state_t */
@@ -299,7 +303,7 @@ typedef struct _tcp_connection
   sack_scoreboard_t sack_sb;   /**< SACK "scoreboard" that tracks holes */
 
   u16 rcv_dupacks;     /**< Number of DUPACKs received */
-  u8 snt_dupacks;      /**< Number of DUPACKs sent in a burst */
+  u8 pending_dupacks;  /**< Number of DUPACKs to be sent */
 
   /* Congestion control */
   u32 cwnd;            /**< Congestion window */
@@ -308,11 +312,13 @@ typedef struct _tcp_connection
   u32 prev_ssthresh;   /**< ssthresh before congestion */
   u32 prev_cwnd;       /**< ssthresh before congestion */
   u32 bytes_acked;     /**< Bytes acknowledged by current segment */
+  u32 burst_acked;     /**< Bytes acknowledged in current burst */
   u32 snd_rxt_bytes;   /**< Retransmitted bytes */
   u32 snd_rxt_ts;      /**< Timestamp when first packet is retransmitted */
   u32 tsecr_last_ack;  /**< Timestamp echoed to us in last healthy ACK */
   u32 snd_congestion;  /**< snd_una_max when congestion is detected */
   tcp_cc_algorithm_t *cc_algo; /**< Congestion control algorithm */
+  u8 cc_data[TCP_CC_DATA_SZ];  /**< Congestion control algo private data */
 
   /* RTT and RTO */
   u32 rto;             /**< Retransmission timeout */
@@ -327,6 +333,7 @@ typedef struct _tcp_connection
   u32 limited_transmit;        /**< snd_nxt when limited transmit starts */
   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 */
 } tcp_connection_t;
 
 struct _tcp_cc_algorithm
@@ -392,6 +399,8 @@ typedef struct tcp_worker_ctx_
                                                     now doing fast rxt */
   u32 *postponed_fast_rxt;                     /**< vector of connections
                                                     that will do fast rxt */
+  u32 *pending_deq_acked;
+  u32 *pending_acks;
   vlib_main_t *vm;                             /**< pointer to vm */
 
     CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
@@ -456,6 +465,8 @@ typedef struct _tcp_main
 
   /** fault-injection */
   f64 buffer_fail_fraction;
+
+  u8 cc_algo;
 } tcp_main_t;
 
 extern tcp_main_t tcp_main;
@@ -561,6 +572,7 @@ void tcp_send_reset_w_pkt (tcp_connection_t * tc, vlib_buffer_t * pkt,
                           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);
 void tcp_send_fin (tcp_connection_t * tc);
 void tcp_init_mss (tcp_connection_t * tc);
 void tcp_update_burst_snd_vars (tcp_connection_t * tc);
@@ -571,6 +583,10 @@ void tcp_program_fastretransmit (tcp_worker_ctx_t * wrk,
                                 tcp_connection_t * tc);
 void tcp_do_fastretransmits (tcp_worker_ctx_t * wrk);
 
+void tcp_program_ack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc);
+void tcp_program_dupack (tcp_worker_ctx_t * wrk, tcp_connection_t * tc);
+void tcp_send_acks (tcp_worker_ctx_t * wrk);
+
 always_inline u32
 tcp_end_seq (tcp_header_t * th, u32 len)
 {
@@ -639,6 +655,25 @@ tcp_initial_cwnd (const tcp_connection_t * tc)
     return 4 * tc->snd_mss;
 }
 
+/*
+ * Accumulate acked bytes for cwnd increase
+ *
+ * Once threshold bytes are accumulated, snd_mss bytes are added
+ * to the cwnd.
+ */
+always_inline void
+tcp_cwnd_accumulate (tcp_connection_t * tc, u32 thresh, u32 bytes)
+{
+  tc->cwnd_acc_bytes += bytes;
+  if (tc->cwnd_acc_bytes >= thresh)
+    {
+      u32 inc = tc->cwnd_acc_bytes / thresh;
+      tc->cwnd_acc_bytes -= inc * thresh;
+      tc->cwnd += inc * tc->snd_mss;
+      tc->cwnd = clib_min (tc->cwnd, tc->tx_fifo_size);
+    }
+}
+
 always_inline u32
 tcp_loss_wnd (const tcp_connection_t * tc)
 {
@@ -735,22 +770,15 @@ void tcp_connection_timers_init (tcp_connection_t * tc);
 void tcp_connection_timers_reset (tcp_connection_t * tc);
 void tcp_init_snd_vars (tcp_connection_t * tc);
 void tcp_connection_init_vars (tcp_connection_t * tc);
-void tcp_update_pacer (tcp_connection_t * tc);
+void tcp_connection_tx_pacer_update (tcp_connection_t * tc);
+void tcp_connection_tx_pacer_reset (tcp_connection_t * tc, u32 window,
+                                   u32 start_bucket);
 
 always_inline void
 tcp_cc_rcv_ack (tcp_connection_t * tc)
 {
   tc->cc_algo->rcv_ack (tc);
   tc->tsecr_last_ack = tc->rcv_opts.tsecr;
-  tcp_update_pacer (tc);
-}
-
-always_inline void
-tcp_connection_force_ack (tcp_connection_t * tc, vlib_buffer_t * b)
-{
-  /* Reset flags, make sure ack is sent */
-  tc->flags = TCP_CONN_SNDACK;
-  vnet_buffer (b)->tcp.flags &= ~TCP_BUF_FLAG_DUPACK;
 }
 
 always_inline void
@@ -868,6 +896,14 @@ void tcp_cc_algo_register (tcp_cc_algorithm_type_e type,
 
 tcp_cc_algorithm_t *tcp_cc_algo_get (tcp_cc_algorithm_type_e type);
 
+static inline void *
+tcp_cc_data (tcp_connection_t * tc)
+{
+  return (void *) tc->cc_data;
+}
+
+void newreno_rcv_cong_ack (tcp_connection_t * tc, tcp_cc_ack_t ack_type);
+
 /**
  * Push TCP header to buffer
  *