27 #define TCP_TICK 10e-3 28 #define THZ 1/TCP_TICK 29 #define TCP_TSTAMP_RESOLUTION TCP_TICK 30 #define TCP_PAWS_IDLE 24 * 24 * 60 * 60 * THZ 31 #define TCP_MAX_OPTION_SPACE 40 33 #define TCP_DUPACK_THRESHOLD 3 34 #define TCP_MAX_RX_FIFO_SIZE 2 << 20 35 #define TCP_IW_N_SEGMENTS 10 38 #define foreach_tcp_fsm_state \ 41 _(SYN_SENT, "SYN_SENT") \ 42 _(SYN_RCVD, "SYN_RCVD") \ 43 _(ESTABLISHED, "ESTABLISHED") \ 44 _(CLOSE_WAIT, "CLOSE_WAIT") \ 45 _(FIN_WAIT_1, "FIN_WAIT_1") \ 46 _(LAST_ACK, "LAST_ACK") \ 47 _(CLOSING, "CLOSING") \ 48 _(FIN_WAIT_2, "FIN_WAIT_2") \ 49 _(TIME_WAIT, "TIME_WAIT") 51 typedef enum _tcp_state
53 #define _(sym, str) TCP_STATE_##sym, 62 #define foreach_tcp_timer \ 63 _(RETRANSMIT, "RETRANSMIT") \ 64 _(DELACK, "DELAYED ACK") \ 65 _(PERSIST, "PERSIST") \ 67 _(WAITCLOSE, "WAIT CLOSE") \ 68 _(RETRANSMIT_SYN, "RETRANSMIT SYN") \ 69 _(ESTABLISH, "ESTABLISH") 71 typedef enum _tcp_timers
73 #define _(sym, str) TCP_TIMER_##sym, 85 #define TCP_TIMER_HANDLE_INVALID ((u32) ~0) 88 #define TCP_TO_TIMER_TICK TCP_TICK*10 90 #define TCP_DELACK_TIME 1 91 #define TCP_ESTABLISH_TIME 750 92 #define TCP_2MSL_TIME 300 93 #define TCP_CLOSEWAIT_TIME 1 94 #define TCP_CLEANUP_TIME 5 96 #define TCP_RTO_MAX 60 * THZ 97 #define TCP_RTT_MAX 30 * THZ 98 #define TCP_RTO_SYN_RETRIES 3 99 #define TCP_RTO_INIT 1 * THZ 104 #define foreach_tcp_connection_flag \ 105 _(DELACK, "Delay ACK") \ 106 _(SNDACK, "Send ACK") \ 107 _(BURSTACK, "Burst ACK set") \ 108 _(FINSNT, "FIN sent") \ 109 _(SENT_RCV_WND0, "Sent 0 receive window") \ 110 _(RECOVERY, "Recovery on") \ 111 _(FAST_RECOVERY, "Fast Recovery on") 113 typedef enum _tcp_connection_flag_bits
115 #define _(sym, str) TCP_CONN_##sym##_BIT, 121 typedef enum _tcp_connection_flag
123 #define _(sym, str) TCP_CONN_##sym = 1 << TCP_CONN_##sym##_BIT, 130 #define foreach_tcp_buf_flag \ 136 #define _(f) TCP_BUF_BIT_##f, 144 #define _(f) TCP_BUF_FLAG_##f = 1 << TCP_BUF_BIT_##f, 149 #define TCP_MAX_SACK_BLOCKS 5 150 #define TCP_INVALID_SACK_HOLE_INDEX ((u32)~0) 152 typedef struct _sack_scoreboard_hole
160 typedef struct _sack_scoreboard
167 typedef enum _tcp_cc_algorithm_type
174 typedef enum _tcp_cc_ack_t
181 typedef struct _tcp_connection
212 u32 tsval_recent_age;
240 struct _tcp_cc_algorithm
249 #define tcp_fastrecovery_on(tc) (tc)->flags |= TCP_CONN_FAST_RECOVERY 250 #define tcp_fastrecovery_off(tc) (tc)->flags &= ~TCP_CONN_FAST_RECOVERY 251 #define tcp_in_fastrecovery(tc) ((tc)->flags & TCP_CONN_FAST_RECOVERY) 252 #define tcp_in_recovery(tc) ((tc)->flags & (TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY)) 253 #define tcp_recovery_off(tc) ((tc)->flags &= ~(TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY)) 254 #define tcp_in_slowstart(tc) (tc->cwnd < tc->ssthresh) 263 typedef enum _tcp_error
265 #define tcp_error(n,s) TCP_ERROR_##n, 271 typedef struct _tcp_lookup_dispatch
276 typedef struct _tcp_main
287 u8 log2_tstamp_clocks_per_tick;
288 f64 tstamp_ticks_per_clock;
294 tw_timer_wheel_16t_2w_512sl_t *timer_wheels;
297 u32 **delack_connections;
346 if (
tcp_main.connections[thread_index] == 0)
388 #define seq_lt(_s1, _s2) ((i32)((_s1)-(_s2)) < 0) 389 #define seq_leq(_s1, _s2) ((i32)((_s1)-(_s2)) <= 0) 390 #define seq_gt(_s1, _s2) ((i32)((_s1)-(_s2)) > 0) 391 #define seq_geq(_s1, _s2) ((i32)((_s1)-(_s2)) >= 0) 394 #define timestamp_lt(_t1, _t2) ((i32)((_t1)-(_t2)) < 0) 395 #define timestamp_leq(_t1, _t2) ((i32)((_t1)-(_t2)) <= 0) 400 return tc->snd_una_max - tc->snd_una - tc->sack_sb.sacked_bytes
410 if (tc->snd_mss > 2190)
411 return 2 * tc->snd_mss;
412 else if (tc->snd_mss > 1095)
413 return 3 * tc->snd_mss;
415 return 4 * tc->snd_mss;
427 return clib_min (tc->cwnd, tc->snd_wnd);
436 if (available_wnd <= flight_size)
439 return available_wnd - flight_size;
467 tc->flags = TCP_CONN_SNDACK;
468 vnet_buffer (b)->tcp.flags &= ~TCP_BUF_FLAG_DUPACK;
475 = tw_timer_start_16t_2w_512sl (&
tcp_main.timer_wheels[tc->c_thread_index],
476 tc->c_c_index, timer_id, interval);
493 tw_timer_stop_16t_2w_512sl (&
tcp_main.timer_wheels[tc->c_thread_index],
494 tc->timers[timer_id]);
502 tw_timer_stop_16t_2w_512sl (&
tcp_main.timer_wheels[tc->c_thread_index],
503 tc->timers[timer_id]);
504 tc->timers[timer_id] =
505 tw_timer_start_16t_2w_512sl (&
tcp_main.timer_wheels[tc->c_thread_index],
506 tc->c_c_index, timer_id, interval);
548 return hole->end - hole->start;
558 tm->cc_algos[type] = *vft;
565 return &tm->cc_algos[type];
596 th->seq_number = seq;
597 th->ack_number = ack;
598 th->data_offset_and_reserved = (tcp_hdr_opts_len >> 2) << 4;
602 th->urgent_pointer = 0;
625 clib_host_to_net_u32 (seq),
626 clib_host_to_net_u32 (ack),
627 tcp_hdr_opts_len,
flags,
628 clib_host_to_net_u16 (wnd));
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
u32 tcp_prepare_retransmit_segment(tcp_connection_t *tc, vlib_buffer_t *b, u32 max_bytes)
Build a retransmit segment.
static void tcp_retransmit_timer_set(tcp_connection_t *tc)
static u32 tcp_available_wnd(const tcp_connection_t *tc)
void tcp_make_fin(tcp_connection_t *tc, vlib_buffer_t *b)
Convert buffer to FIN-ACK.
void tcp_send_reset(vlib_buffer_t *pkt, u8 is_ip4)
Send reset without reusing existing buffer.
struct _sack_block sack_block_t
void tcp_connection_timers_reset(tcp_connection_t *tc)
Stop all connection timers.
struct _transport_connection transport_connection_t
#define TCP_TO_TIMER_TICK
vlib_node_registration_t tcp4_output_node
(constructor) VLIB_REGISTER_NODE (tcp4_output_node)
void tcp_fast_retransmit(tcp_connection_t *tc)
static tcp_connection_t * tcp_connection_get_if_valid(u32 conn_index, u32 thread_index)
void tcp_connection_del(tcp_connection_t *tc)
Connection removal.
struct _sack_scoreboard sack_scoreboard_t
static tcp_connection_t * tcp_half_open_connection_get(u32 conn_index)
struct _tcp_main tcp_main_t
vlib_node_registration_t tcp6_output_node
(constructor) VLIB_REGISTER_NODE (tcp6_output_node)
static u64 clib_cpu_time_now(void)
timer_expiration_handler tcp_timer_retransmit_handler
struct _vlib_node_registration vlib_node_registration_t
struct _tcp_lookup_dispatch tcp_lookup_dispatch_t
struct _tcp_connection tcp_connection_t
void tcp_connection_cleanup(tcp_connection_t *tc)
Cleans up connection state.
static void scoreboard_clear(sack_scoreboard_t *sb)
struct _tcp_header tcp_header_t
static u32 tcp_available_snd_space(const tcp_connection_t *tc)
void tcp_connection_reset(tcp_connection_t *tc)
Notify session that connection has been reset.
struct _sack_scoreboard_hole sack_scoreboard_hole_t
static timer_callback_t * timers
enum _tcp_state tcp_state_t
timer_expiration_handler tcp_timer_retransmit_syn_handler
static u32 tcp_time_now(void)
static tcp_cc_algorithm_t * tcp_cc_algo_get(tcp_cc_algorithm_type_e type)
static u32 scoreboard_hole_bytes(sack_scoreboard_hole_t *hole)
static void tcp_timer_set(tcp_connection_t *tc, u8 timer_id, u32 interval)
#define TCP_INVALID_SACK_HOLE_INDEX
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
u8 * format_tcp_connection_verbose(u8 *s, va_list *args)
static void * vlib_buffer_push_tcp_net_order(vlib_buffer_t *b, u16 sp, u16 dp, u32 seq, u32 ack, u8 tcp_hdr_opts_len, u8 flags, u16 wnd)
Push TCP header to buffer.
void tcp_retransmit_first_unacked(tcp_connection_t *tc)
Retansmit first unacked segment.
clib_error_t * vnet_tcp_enable_disable(vlib_main_t *vm, u8 is_en)
void tcp_send_syn(tcp_connection_t *tc)
Send SYN.
static sack_scoreboard_hole_t * scoreboard_next_hole(sack_scoreboard_t *sb, sack_scoreboard_hole_t *hole)
#define TCP_TIMER_HANDLE_INVALID
static u32 tcp_flight_size(const tcp_connection_t *tc)
u32 tcp_push_header(transport_connection_t *tconn, vlib_buffer_t *b)
void( timer_expiration_handler)(u32 index)
enum _tcp_cc_ack_t tcp_cc_ack_t
static void tcp_timer_reset(tcp_connection_t *tc, u8 timer_id)
static sack_scoreboard_hole_t * scoreboard_first_hole(sack_scoreboard_t *sb)
enum _tcp_error tcp_error_t
static void * vlib_buffer_push_tcp(vlib_buffer_t *b, u16 sp_net, u16 dp_net, u32 seq, u32 ack, u8 tcp_hdr_opts_len, u8 flags, u16 wnd)
Push TCP header to buffer.
void tcp_cc_init(tcp_connection_t *tc)
clib_bihash_24_8_t transport_endpoint_table_t
void tcp_update_time(f64 now, u32 thread_index)
format_function_t format_tcp_state
void tcp_set_snd_mss(tcp_connection_t *tc)
enum _tcp_timers tcp_timers_e
static void tcp_connection_force_ack(tcp_connection_t *tc, vlib_buffer_t *b)
void tcp_connection_timers_init(tcp_connection_t *tc)
Initialize all connection timers as invalid.
void tcp_make_synack(tcp_connection_t *ts, vlib_buffer_t *b)
Convert buffer to SYN-ACK.
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
vlib_node_registration_t tcp6_input_node
(constructor) VLIB_REGISTER_NODE (tcp6_input_node)
void tcp_make_ack(tcp_connection_t *ts, vlib_buffer_t *b)
Convert buffer to ACK.
static void tcp_timer_update(tcp_connection_t *tc, u8 timer_id, u32 interval)
int vlib_main(vlib_main_t *volatile vm, unformat_input_t *input)
enum _tcp_cc_algorithm_type tcp_cc_algorithm_type_e
enum _tcp_connection_flag_bits tcp_connection_flag_bits_e
vhost_vring_state_t state
void tcp_connection_init_vars(tcp_connection_t *tc)
Initialize tcp connection variables.
u8 * format_tcp_connection(u8 *s, va_list *args)
static u32 tcp_end_seq(tcp_header_t *th, u32 len)
struct _tcp_cc_algorithm tcp_cc_algorithm_t
void scoreboard_remove_hole(sack_scoreboard_t *sb, sack_scoreboard_hole_t *hole)
static void * vlib_buffer_push_uninit(vlib_buffer_t *b, u8 size)
Prepend uninitialized data to buffer.
vlib_node_registration_t tcp4_input_node
(constructor) VLIB_REGISTER_NODE (tcp4_input_node)
static u32 tcp_initial_cwnd(const tcp_connection_t *tc)
Initial cwnd as per RFC5681.
#define foreach_tcp_fsm_state
TCP FSM state definitions as per RFC793.
void tcp_send_fin(tcp_connection_t *tc)
Send FIN.
#define foreach_tcp_connection_flag
TCP connection flags.
#define foreach_tcp_timer
TCP timers.
struct _transport_endpoint transport_endpoint_t
void tcp_connection_close(tcp_connection_t *tc)
Begin connection closing procedure.
static tcp_connection_t * tcp_connection_get(u32 conn_index, u32 thread_index)
ip4_main_t ip4_main
Global ip4 main structure.
static void tcp_cc_algo_register(tcp_cc_algorithm_type_e type, const tcp_cc_algorithm_t *vft)
#define foreach_tcp_buf_flag
TCP buffer flags.
enum _tcp_connection_flag tcp_connection_flags_e
static u32 tcp_loss_wnd(const tcp_connection_t *tc)
static tcp_main_t * vnet_get_tcp_main()
timer_expiration_handler tcp_timer_delack_handler
static u8 tcp_timer_is_active(tcp_connection_t *tc, tcp_timers_e timer)
static tcp_connection_t * tcp_listener_get(u32 tli)