/*
- * 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:
_(KEEP, "KEEP") \
_(WAITCLOSE, "WAIT CLOSE") \
_(RETRANSMIT_SYN, "RETRANSMIT SYN") \
- _(ESTABLISH, "ESTABLISH")
+ _(ESTABLISH, "ESTABLISH") \
+ _(ESTABLISH_AO, "ESTABLISH_AO") \
typedef enum _tcp_timers
{
#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 */
#define TCP_RTT_MAX 30 * THZ /* 30s (probably too much) */
#define TCP_RTO_SYN_RETRIES 3 /* SYN retries without doubling RTO */
#define TCP_RTO_INIT 1 * THZ /* Initial retransmit timer */
+#define TCP_RTO_BOFF_MAX 8 /* Max number of retries before reset */
/** TCP connection flags */
#define foreach_tcp_connection_flag \
_(SNDACK, "Send ACK") \
_(FINSNT, "FIN sent") \
- _(SENT_RCV_WND0, "Sent 0 rcv_wnd") \
_(RECOVERY, "Recovery") \
_(FAST_RECOVERY, "Fast Recovery") \
_(DCNT_PENDING, "Disconnect pending") \
_(FRXT_PENDING, "Fast-retransmit pending") \
_(FRXT_FIRST, "Fast-retransmit first again") \
_(DEQ_PENDING, "Pending dequeue acked") \
- _(PSH_PENDING, "Pending psh packet") \
+ _(PSH_PENDING, "PSH pending") \
+ _(FINRCVD, "FIN received") \
typedef enum _tcp_connection_flag_bits
{
TCP_CONN_N_FLAGS
} tcp_connection_flags_e;
-/** TCP buffer flags */
-#define foreach_tcp_buf_flag \
- _ (ACK) /**< Sending ACK. */ \
- _ (DUPACK) /**< Sending DUPACK. */ \
-
-enum
-{
-#define _(f) TCP_BUF_BIT_##f,
- foreach_tcp_buf_flag
-#undef _
- TCP_N_BUF_BITS,
-};
-
-enum
-{
-#define _(f) TCP_BUF_FLAG_##f = 1 << TCP_BUF_BIT_##f,
- foreach_tcp_buf_flag
-#undef _
-};
-
#define TCP_SCOREBOARD_TRACE (0)
#define TCP_MAX_SACK_BLOCKS 256 /**< Max number of SACK blocks stored */
#define TCP_INVALID_SACK_HOLE_INDEX ((u32)~0)
{
TCP_CC_NEWRENO,
TCP_CC_CUBIC,
+ TCP_CC_LAST = TCP_CC_CUBIC
} tcp_cc_algorithm_type_e;
typedef struct _tcp_cc_algorithm tcp_cc_algorithm_t;
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 */
u32 tx_fifo_size; /**< Tx fifo size. Used to constrain cwnd */
u32 psh_seq; /**< Add psh header for seg that includes this */
+ u32 next_node_index; /**< Can be used to control next node in output */
+ u32 next_node_opaque; /**< Opaque to pass to next node */
} tcp_connection_t;
/* *INDENT-OFF* */
void (*congestion) (tcp_connection_t * tc);
void (*recovered) (tcp_connection_t * tc);
void (*init) (tcp_connection_t * tc);
+ void (*cleanup) (tcp_connection_t * tc);
};
/* *INDENT-ON* */
} 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 */
tcp_connection_t *half_open_connections;
clib_spinlock_t half_open_lock;
+ /** vlib buffer size */
+ u32 bytes_per_buffer;
+
+ /* Seed used to generate random iss */
+ tcp_iss_seed_t iss_seed;
+
/* Congestion control algorithms registered */
tcp_cc_algorithm_t *cc_algos;
- /** vlib buffer size */
- u32 bytes_per_buffer;
+ /** Hash table of cc algorithms by name */
+ uword *cc_algo_by_name;
+
+ /** Last cc algo registered */
+ tcp_cc_algorithm_type_e cc_last_type;
/*
* Configuration
* rfc 7323 window scaling factor */
u32 max_rx_fifo;
+ /** Default MTU to be used when establishing connections */
+ u16 default_mtu;
+
/** Number of preallocated connections */
u32 preallocated_connections;
u32 preallocated_half_open_connections;
/** Default congestion control algorithm type */
tcp_cc_algorithm_type_e cc_algo;
-
} tcp_main_t;
extern tcp_main_t tcp_main;
extern vlib_node_registration_t tcp6_input_node;
extern vlib_node_registration_t tcp4_output_node;
extern vlib_node_registration_t tcp6_output_node;
+extern vlib_node_registration_t tcp4_established_node;
+extern vlib_node_registration_t tcp6_established_node;
+extern vlib_node_registration_t tcp4_syn_sent_node;
+extern vlib_node_registration_t tcp6_syn_sent_node;
+extern vlib_node_registration_t tcp4_rcv_process_node;
+extern vlib_node_registration_t tcp6_rcv_process_node;
+extern vlib_node_registration_t tcp4_listen_node;
+extern vlib_node_registration_t tcp6_listen_node;
always_inline tcp_main_t *
vnet_get_tcp_main ()
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);
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);
{
int flight_size;
- flight_size = (int) (tc->snd_una_max - tc->snd_una) - tcp_bytes_out (tc)
+ flight_size = (int) (tc->snd_nxt - tc->snd_una) - tcp_bytes_out (tc)
+ tc->snd_rxt_bytes;
if (flight_size < 0)
return wrk->time_now;
}
-u32 tcp_push_header (tcp_connection_t * tconn, vlib_buffer_t * b);
+u32 tcp_session_push_header (transport_connection_t * tconn,
+ vlib_buffer_t * b);
void tcp_connection_timers_init (tcp_connection_t * tc);
void tcp_connection_timers_reset (tcp_connection_t * tc);
always_inline void
tcp_retransmit_timer_update (tcp_connection_t * tc)
{
- if (tc->snd_una == tc->snd_una_max)
+ if (tc->snd_una == tc->snd_nxt)
{
tcp_retransmit_timer_reset (tc);
if (tc->snd_wnd < tc->snd_mss)
#define tcp_validate_txf_size(_tc, _a) \
ASSERT(_tc->state != TCP_STATE_ESTABLISHED \
- || session_tx_fifo_max_dequeue (&_tc->connection) >= _a)
+ || transport_max_tx_dequeue (&_tc->connection) >= _a)
void tcp_rcv_sacks (tcp_connection_t * tc, u32 ack);
u8 *tcp_scoreboard_replay (u8 * s, tcp_connection_t * tc, u8 verbose);
+/**
+ * Register exiting cc algo type
+ */
void tcp_cc_algo_register (tcp_cc_algorithm_type_e type,
const tcp_cc_algorithm_t * vft);
+/**
+ * Register new cc algo type
+ */
+tcp_cc_algorithm_type_e tcp_cc_algo_new_type (const tcp_cc_algorithm_t * vft);
tcp_cc_algorithm_t *tcp_cc_algo_get (tcp_cc_algorithm_type_e type);
static inline void *