int
tcp_half_open_connection_cleanup (tcp_connection_t * tc)
{
+ tcp_worker_ctx_t *wrk;
+
/* Make sure this is the owning thread */
if (tc->c_thread_index != vlib_get_thread_index ())
return 1;
- tcp_timer_reset (tc, TCP_TIMER_RETRANSMIT_SYN);
+
+ wrk = tcp_get_worker (tc->c_thread_index);
+ tcp_timer_reset (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT_SYN);
tcp_half_open_connection_del (tc);
return 0;
}
void
tcp_connection_close (tcp_connection_t * tc)
{
+ tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
+
TCP_EVT (TCP_EVT_CLOSE, tc);
/* Send/Program FIN if needed and switch state */
tcp_connection_timers_reset (tc);
tcp_send_fin (tc);
tcp_connection_set_state (tc, TCP_STATE_FIN_WAIT_1);
- tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.finwait1_time);
break;
case TCP_STATE_ESTABLISHED:
/* If closing with unread data, reset the connection */
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
session_transport_closed_notify (&tc->connection);
tcp_program_cleanup (tcp_get_worker (tc->c_thread_index), tc);
- tcp_worker_stats_inc (tc->c_thread_index, rst_unread, 1);
+ tcp_worker_stats_inc (wrk, rst_unread, 1);
break;
}
if (!transport_max_tx_dequeue (&tc->connection))
/* Set a timer in case the peer stops responding. Otherwise the
* connection will be stuck here forever. */
ASSERT (tc->timers[TCP_TIMER_WAITCLOSE] == TCP_TIMER_HANDLE_INVALID);
- tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time);
+ tcp_timer_set (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.finwait1_time);
break;
case TCP_STATE_CLOSE_WAIT:
if (!transport_max_tx_dequeue (&tc->connection))
tcp_send_fin (tc);
tcp_connection_timers_reset (tc);
tcp_connection_set_state (tc, TCP_STATE_LAST_ACK);
- tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.lastack_time);
}
else
tc->flags |= TCP_CONN_FINPNDG;
break;
case TCP_STATE_FIN_WAIT_1:
- tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait1_time);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.finwait1_time);
break;
case TCP_STATE_CLOSED:
/* Cleanup should've been programmed already */
void
tcp_connection_timers_reset (tcp_connection_t * tc)
{
+ tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
int i;
+
for (i = 0; i < TCP_N_TIMERS; i++)
- {
- tcp_timer_reset (tc, i);
- }
+ tcp_timer_reset (&wrk->timer_wheel, tc, i);
}
#if 0
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
session_transport_closed_notify (&tc->connection);
tcp_program_cleanup (wrk, tc);
- tcp_workerp_stats_inc (wrk, to_closewait, 1);
+ tcp_worker_stats_inc (wrk, to_closewait, 1);
break;
}
session_transport_closed_notify (&tc->connection);
/* Make sure we don't wait in LAST ACK forever */
- tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time);
- tcp_workerp_stats_inc (wrk, to_closewait2, 1);
+ tcp_timer_set (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.lastack_time);
+ tcp_worker_stats_inc (wrk, to_closewait2, 1);
/* Don't delete the connection yet */
break;
tcp_program_cleanup (wrk, tc);
}
session_transport_closed_notify (&tc->connection);
- tcp_workerp_stats_inc (wrk, to_finwait1, 1);
+ tcp_worker_stats_inc (wrk, to_finwait1, 1);
break;
case TCP_STATE_LAST_ACK:
tcp_connection_timers_reset (tc);
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
session_transport_closed_notify (&tc->connection);
tcp_program_cleanup (wrk, tc);
- tcp_workerp_stats_inc (wrk, to_lastack, 1);
+ tcp_worker_stats_inc (wrk, to_lastack, 1);
break;
case TCP_STATE_CLOSING:
tcp_connection_timers_reset (tc);
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
session_transport_closed_notify (&tc->connection);
tcp_program_cleanup (wrk, tc);
- tcp_workerp_stats_inc (wrk, to_closing, 1);
+ tcp_worker_stats_inc (wrk, to_closing, 1);
break;
case TCP_STATE_FIN_WAIT_2:
tcp_send_reset (tc);
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
session_transport_closed_notify (&tc->connection);
tcp_program_cleanup (wrk, tc);
- tcp_workerp_stats_inc (wrk, to_finwait2, 1);
+ tcp_worker_stats_inc (wrk, to_finwait2, 1);
break;
case TCP_STATE_TIME_WAIT:
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
wrk = tcp_get_worker (thread_index);
n_expired = vec_len (expired_timers);
- tcp_workerp_stats_inc (wrk, timer_expirations, n_expired);
+ tcp_worker_stats_inc (wrk, timer_expirations, n_expired);
n_left = clib_fifo_elts (wrk->pending_timers);
/*
tcp_cleanup_req_t *pending_cleanups;
/** worker timer wheel */
- tw_timer_wheel_16t_2w_512sl_t timer_wheel;
+ tcp_timer_wheel_t timer_wheel;
CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
tcp_wrk_stats_t stats;
} tcp_worker_ctx_t;
-#define tcp_worker_stats_inc(_ti,_stat,_val) \
- tcp_main.wrk_ctx[_ti].stats._stat += _val
-
-#define tcp_workerp_stats_inc(_wrk,_stat,_val) \
+#define tcp_worker_stats_inc(_wrk,_stat,_val) \
_wrk->stats._stat += _val
typedef struct tcp_iss_seed_
format_function_t format_tcp_connection;
format_function_t format_tcp_connection_id;
-always_inline void
-tcp_timer_set (tcp_connection_t * tc, u8 timer_id, u32 interval)
-{
- ASSERT (tc->c_thread_index == vlib_get_thread_index ());
- ASSERT (tc->timers[timer_id] == TCP_TIMER_HANDLE_INVALID);
- tc->timers[timer_id] =
- tw_timer_start_16t_2w_512sl (&tcp_main.
- wrk_ctx[tc->c_thread_index].timer_wheel,
- tc->c_c_index, timer_id, interval);
-}
-
-always_inline void
-tcp_timer_reset (tcp_connection_t * tc, u8 timer_id)
-{
- ASSERT (tc->c_thread_index == vlib_get_thread_index ());
- if (tc->timers[timer_id] == TCP_TIMER_HANDLE_INVALID)
- return;
-
- tw_timer_stop_16t_2w_512sl (&tcp_main.
- wrk_ctx[tc->c_thread_index].timer_wheel,
- tc->timers[timer_id]);
- tc->timers[timer_id] = TCP_TIMER_HANDLE_INVALID;
-}
-
-always_inline void
-tcp_timer_update (tcp_connection_t * tc, u8 timer_id, u32 interval)
-{
- ASSERT (tc->c_thread_index == vlib_get_thread_index ());
- if (tc->timers[timer_id] != TCP_TIMER_HANDLE_INVALID)
- tw_timer_update_16t_2w_512sl (&tcp_main.
- wrk_ctx[tc->c_thread_index].timer_wheel,
- tc->timers[timer_id], interval);
- else
- tc->timers[timer_id] =
- tw_timer_start_16t_2w_512sl (&tcp_main.
- wrk_ctx[tc->c_thread_index].timer_wheel,
- tc->c_c_index, timer_id, interval);
-}
-
-always_inline void
-tcp_retransmit_timer_set (tcp_connection_t * tc)
-{
- ASSERT (tc->snd_una != tc->snd_una_max);
- tcp_timer_set (tc, TCP_TIMER_RETRANSMIT,
- clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
-}
-
-always_inline void
-tcp_retransmit_timer_reset (tcp_connection_t * tc)
-{
- tcp_timer_reset (tc, TCP_TIMER_RETRANSMIT);
-}
-
-always_inline void
-tcp_retransmit_timer_force_update (tcp_connection_t * tc)
-{
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT,
- clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
-}
-
-always_inline void
-tcp_persist_timer_set (tcp_connection_t * tc)
-{
- /* Reuse RTO. It's backed off in handler */
- tcp_timer_set (tc, TCP_TIMER_PERSIST,
- clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
-}
-
-always_inline void
-tcp_persist_timer_update (tcp_connection_t * tc)
-{
- u32 interval;
-
- if (seq_leq (tc->snd_una, tc->snd_congestion + tc->burst_acked))
- interval = 1;
- else
- interval = clib_max (tc->rto * TCP_TO_TIMER_TICK, 1);
-
- tcp_timer_update (tc, TCP_TIMER_PERSIST, interval);
-}
-
-always_inline void
-tcp_persist_timer_reset (tcp_connection_t * tc)
-{
- tcp_timer_reset (tc, TCP_TIMER_PERSIST);
-}
-
-always_inline void
-tcp_retransmit_timer_update (tcp_connection_t * tc)
-{
- if (tc->snd_una == tc->snd_nxt)
- {
- tcp_retransmit_timer_reset (tc);
- if (tc->snd_wnd < tc->snd_mss)
- tcp_persist_timer_update (tc);
- }
- else
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT,
- clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
-}
-
-always_inline u8
-tcp_timer_is_active (tcp_connection_t * tc, tcp_timers_e timer)
-{
- return tc->timers[timer] != TCP_TIMER_HANDLE_INVALID;
-}
-
#define tcp_validate_txf_size(_tc, _a) \
ASSERT(_tc->state != TCP_STATE_ESTABLISHED \
|| transport_max_tx_dequeue (&_tc->connection) >= _a)
/* If everything has been acked, stop retransmit timer
* otherwise update. */
- tcp_retransmit_timer_update (tc);
+ tcp_retransmit_timer_update (&wrk->timer_wheel, tc);
/* Update pacer based on our new cwnd estimate */
tcp_connection_tx_pacer_update (tc);
/* Set persist timer if not set and we just got 0 wnd */
if (!tcp_timer_is_active (tc, TCP_TIMER_PERSIST)
&& !tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT))
- tcp_persist_timer_set (tc);
+ {
+ tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
+ tcp_persist_timer_set (&wrk->timer_wheel, tc);
+ }
}
else
{
if (PREDICT_FALSE (tcp_timer_is_active (tc, TCP_TIMER_PERSIST)))
- tcp_persist_timer_reset (tc);
+ {
+ tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
+ tcp_persist_timer_reset (&wrk->timer_wheel, tc);
+ }
if (PREDICT_FALSE (tcp_is_descheduled (tc)))
tcp_reschedule (tc);
* in CLOSE-WAIT, set timer (reuse WAITCLOSE). */
tcp_connection_set_state (tc, TCP_STATE_CLOSE_WAIT);
tcp_program_disconnect (wrk, tc);
- tcp_timer_update (tc, TCP_TIMER_WAITCLOSE, tcp_cfg.closewait_time);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.closewait_time);
TCP_EVT (TCP_EVT_FIN_RCVD, tc);
*error = TCP_ERROR_FIN_RCVD;
}
if (tcp_can_delack (tc))
{
if (!tcp_timer_is_active (tc, TCP_TIMER_DELACK))
- tcp_timer_set (tc, TCP_TIMER_DELACK, tcp_cfg.delack_time);
+ tcp_timer_set (&wrk->timer_wheel, tc, TCP_TIMER_DELACK,
+ tcp_cfg.delack_time);
goto done;
}
tc0->snd_wl2 = vnet_buffer (b0)->tcp.ack_number;
/* Reset SYN-ACK retransmit and SYN_RCV establish timers */
- tcp_retransmit_timer_reset (tc0);
+ tcp_retransmit_timer_reset (&wrk->timer_wheel, tc0);
if (session_stream_accept_notify (&tc0->connection))
{
error0 = TCP_ERROR_MSG_QUEUE_FULL;
tcp_send_fin (tc0);
/* If a fin was received and data was acked extend wait */
else if ((tc0->flags & TCP_CONN_FINRCVD) && tc0->bytes_acked)
- tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE,
+ tcp_timer_update (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
tcp_cfg.closewait_time);
}
/* If FIN is ACKed */
tcp_connection_set_state (tc0, TCP_STATE_FIN_WAIT_2);
/* Enable waitclose because we're willing to wait for peer's
* FIN but not indefinitely. */
- tcp_timer_set (tc0, TCP_TIMER_WAITCLOSE, tcp_cfg.finwait2_time);
+ tcp_timer_set (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.finwait2_time);
/* Don't try to deq the FIN acked */
if (tc0->burst_acked > 1)
tcp_send_fin (tc0);
tcp_connection_timers_reset (tc0);
tcp_connection_set_state (tc0, TCP_STATE_LAST_ACK);
- tcp_timer_set (tc0, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time);
+ tcp_timer_set (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.lastack_time);
break;
case TCP_STATE_CLOSING:
/* In addition to the processing for the ESTABLISHED state, if
tcp_connection_timers_reset (tc0);
tcp_connection_set_state (tc0, TCP_STATE_TIME_WAIT);
- tcp_timer_set (tc0, TCP_TIMER_WAITCLOSE, tcp_cfg.timewait_time);
+ tcp_timer_set (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.timewait_time);
session_transport_closed_notify (&tc0->connection);
goto drop;
goto drop;
tcp_program_ack (tc0);
- tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, tcp_cfg.timewait_time);
+ tcp_timer_update (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.timewait_time);
goto drop;
break;
tcp_program_ack (tc0);
tcp_connection_set_state (tc0, TCP_STATE_CLOSE_WAIT);
tcp_program_disconnect (wrk, tc0);
- tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, tcp_cfg.closewait_time);
+ tcp_timer_update (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.closewait_time);
break;
case TCP_STATE_SYN_RCVD:
/* Send FIN-ACK, enter LAST-ACK and because the app was not
tc0->rcv_nxt += 1;
tcp_send_fin (tc0);
tcp_connection_set_state (tc0, TCP_STATE_LAST_ACK);
- tcp_timer_set (tc0, TCP_TIMER_WAITCLOSE, tcp_cfg.lastack_time);
+ tcp_timer_set (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.lastack_time);
break;
case TCP_STATE_CLOSE_WAIT:
case TCP_STATE_CLOSING:
* sending it. Since we already received a fin, do not wait
* for too long. */
tc0->flags |= TCP_CONN_FINRCVD;
- tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE,
+ tcp_timer_update (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
tcp_cfg.closewait_time);
}
else
tcp_connection_set_state (tc0, TCP_STATE_CLOSING);
tcp_program_ack (tc0);
/* Wait for ACK for our FIN but not forever */
- tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE,
+ tcp_timer_update (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
tcp_cfg.closing_time);
}
break;
tc0->rcv_nxt += 1;
tcp_connection_set_state (tc0, TCP_STATE_TIME_WAIT);
tcp_connection_timers_reset (tc0);
- tcp_timer_set (tc0, TCP_TIMER_WAITCLOSE, tcp_cfg.timewait_time);
+ tcp_timer_set (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.timewait_time);
tcp_program_ack (tc0);
session_transport_closed_notify (&tc0->connection);
break;
/* Remain in the TIME-WAIT state. Restart the time-wait
* timeout.
*/
- tcp_timer_update (tc0, TCP_TIMER_WAITCLOSE, tcp_cfg.timewait_time);
+ tcp_timer_update (&wrk->timer_wheel, tc0, TCP_TIMER_WAITCLOSE,
+ tcp_cfg.timewait_time);
break;
}
error0 = TCP_ERROR_FIN_RCVD;
* Setup retransmit and establish timers before requesting buffer
* such that we can return if we've ran out.
*/
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN,
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT_SYN,
tc->rto * TCP_TO_TIMER_TICK);
if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
{
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN, 1);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT_SYN, 1);
return;
}
vlib_buffer_t *b;
u32 bi;
- tcp_retransmit_timer_force_update (tc);
+ tcp_retransmit_timer_force_update (&wrk->timer_wheel, tc);
if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
{
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT, 1);
return;
}
if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
{
/* Out of buffers so program fin retransmit ASAP */
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT, 1);
if (fin_snt)
tc->snd_nxt += 1;
else
if ((tc->flags & TCP_CONN_SNDACK) && !tc->pending_dupacks)
tc->flags &= ~TCP_CONN_SNDACK;
- tcp_retransmit_timer_force_update (tc);
+ tcp_retransmit_timer_force_update (&wrk->timer_wheel, tc);
b = vlib_get_buffer (vm, bi);
tcp_init_buffer (vm, b);
tcp_make_fin (tc, b);
}
if (PREDICT_FALSE (!tcp_timer_is_active (tc, TCP_TIMER_RETRANSMIT)))
{
- tcp_retransmit_timer_set (tc);
+ tcp_worker_ctx_t *wrk = tcp_get_worker (tc->c_thread_index);
+ tcp_retransmit_timer_set (&wrk->timer_wheel, tc);
tc->rto_boff = 0;
}
tcp_trajectory_add_start (b, 3);
tc->bytes_retrans += n_bytes;
tc->segs_retrans += 1;
- tcp_workerp_stats_inc (wrk, rxt_segs, 1);
+ tcp_worker_stats_inc (wrk, rxt_segs, 1);
TCP_EVT (TCP_EVT_CC_RTX, tc, offset, n_bytes);
return n_bytes;
vlib_buffer_t *b = 0;
u32 bi, n_bytes;
- tcp_workerp_stats_inc (wrk, tr_events, 1);
+ tcp_worker_stats_inc (wrk, tr_events, 1);
/* Should be handled by a different handler */
if (PREDICT_FALSE (tc->state == TCP_STATE_SYN_SENT))
session_transport_closed_notify (&tc->connection);
tcp_connection_timers_reset (tc);
tcp_program_cleanup (wrk, tc);
- tcp_workerp_stats_inc (wrk, tr_abort, 1);
+ tcp_worker_stats_inc (wrk, tr_abort, 1);
return;
}
n_bytes = tcp_prepare_retransmit_segment (wrk, tc, 0, n_bytes, &b);
if (!n_bytes)
{
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT, 1);
return;
}
tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
- tcp_retransmit_timer_force_update (tc);
+ tcp_retransmit_timer_force_update (&wrk->timer_wheel, tc);
tc->rto_boff += 1;
if (tc->rto_boff == 1)
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
tcp_connection_timers_reset (tc);
tcp_program_cleanup (wrk, tc);
- tcp_workerp_stats_inc (wrk, tr_abort, 1);
+ tcp_worker_stats_inc (wrk, tr_abort, 1);
return;
}
if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
{
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT, 1);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT, 1);
return;
}
if (tc->rto_boff > TCP_RTO_SYN_RETRIES)
tc->rto = clib_min (tc->rto << 1, TCP_RTO_MAX);
- tcp_retransmit_timer_force_update (tc);
+ tcp_retransmit_timer_force_update (&wrk->timer_wheel, tc);
b = vlib_get_buffer (vm, bi);
tcp_init_buffer (vm, b);
if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
{
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN, 1);
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT_SYN, 1);
return;
}
tcp_push_ip_hdr (wrk, tc, b);
tcp_enqueue_to_ip_lookup (wrk, b, bi, tc->c_is_ip4, tc->c_fib_index);
- tcp_timer_update (tc, TCP_TIMER_RETRANSMIT_SYN,
+ tcp_timer_update (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT_SYN,
tc->rto * TCP_TO_TIMER_TICK);
}
* next time */
if (!available_bytes)
{
- tcp_persist_timer_set (tc);
+ tcp_persist_timer_set (&wrk->timer_wheel, tc);
return;
}
*/
if (PREDICT_FALSE (!vlib_buffer_alloc (vm, &bi, 1)))
{
- tcp_persist_timer_set (tc);
+ tcp_persist_timer_set (&wrk->timer_wheel, tc);
return;
}
tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4);
/* Just sent new data, enable retransmit */
- tcp_retransmit_timer_update (tc);
+ tcp_retransmit_timer_update (&wrk->timer_wheel, tc);
return;
}
}
- if (!TCP_ALWAYS_ACK)
- tcp_timer_reset (tc0, TCP_TIMER_DELACK);
-
tc0->segs_out += 1;
}
#ifndef __included_tcp_timer_h__
#define __included_tcp_timer_h__
-#include <vppinfra/tw_timer_16t_2w_512sl.h>
-#include <vppinfra/tw_timer_16t_1w_2048sl.h>
+#include <vnet/tcp/tcp_types.h>
+
+always_inline void
+tcp_timer_set (tcp_timer_wheel_t * tw, tcp_connection_t * tc, u8 timer_id,
+ u32 interval)
+{
+ ASSERT (tc->c_thread_index == vlib_get_thread_index ());
+ ASSERT (tc->timers[timer_id] == TCP_TIMER_HANDLE_INVALID);
+ tc->timers[timer_id] = tw_timer_start_16t_2w_512sl (tw, tc->c_c_index,
+ timer_id, interval);
+}
+
+always_inline void
+tcp_timer_reset (tcp_timer_wheel_t * tw, tcp_connection_t * tc, u8 timer_id)
+{
+ ASSERT (tc->c_thread_index == vlib_get_thread_index ());
+ if (tc->timers[timer_id] == TCP_TIMER_HANDLE_INVALID)
+ return;
+
+ tw_timer_stop_16t_2w_512sl (tw, tc->timers[timer_id]);
+ tc->timers[timer_id] = TCP_TIMER_HANDLE_INVALID;
+}
+
+always_inline void
+tcp_timer_update (tcp_timer_wheel_t * tw, tcp_connection_t * tc, u8 timer_id,
+ u32 interval)
+{
+ ASSERT (tc->c_thread_index == vlib_get_thread_index ());
+ if (tc->timers[timer_id] != TCP_TIMER_HANDLE_INVALID)
+ tw_timer_update_16t_2w_512sl (tw, tc->timers[timer_id], interval);
+ else
+ tc->timers[timer_id] = tw_timer_start_16t_2w_512sl (tw, tc->c_c_index,
+ timer_id, interval);
+}
+
+always_inline void
+tcp_retransmit_timer_set (tcp_timer_wheel_t * tw, tcp_connection_t * tc)
+{
+ ASSERT (tc->snd_una != tc->snd_una_max);
+ tcp_timer_set (tw, tc, TCP_TIMER_RETRANSMIT,
+ clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
+}
+
+always_inline void
+tcp_retransmit_timer_reset (tcp_timer_wheel_t * tw, tcp_connection_t * tc)
+{
+ tcp_timer_reset (tw, tc, TCP_TIMER_RETRANSMIT);
+}
+
+always_inline void
+tcp_retransmit_timer_force_update (tcp_timer_wheel_t * tw,
+ tcp_connection_t * tc)
+{
+ tcp_timer_update (tw, tc, TCP_TIMER_RETRANSMIT,
+ clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
+}
+
+always_inline void
+tcp_persist_timer_set (tcp_timer_wheel_t * tw, tcp_connection_t * tc)
+{
+ /* Reuse RTO. It's backed off in handler */
+ tcp_timer_set (tw, tc, TCP_TIMER_PERSIST,
+ clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
+}
+
+always_inline void
+tcp_persist_timer_update (tcp_timer_wheel_t * tw, tcp_connection_t * tc)
+{
+ u32 interval;
+
+ if (seq_leq (tc->snd_una, tc->snd_congestion + tc->burst_acked))
+ interval = 1;
+ else
+ interval = clib_max (tc->rto * TCP_TO_TIMER_TICK, 1);
+
+ tcp_timer_update (tw, tc, TCP_TIMER_PERSIST, interval);
+}
+
+always_inline void
+tcp_persist_timer_reset (tcp_timer_wheel_t * tw, tcp_connection_t * tc)
+{
+ tcp_timer_reset (tw, tc, TCP_TIMER_PERSIST);
+}
+
+always_inline void
+tcp_retransmit_timer_update (tcp_timer_wheel_t * tw, tcp_connection_t * tc)
+{
+ if (tc->snd_una == tc->snd_nxt)
+ {
+ tcp_retransmit_timer_reset (tw, tc);
+ if (tc->snd_wnd < tc->snd_mss)
+ tcp_persist_timer_update (tw, tc);
+ }
+ else
+ tcp_timer_update (tw, tc, TCP_TIMER_RETRANSMIT,
+ clib_max (tc->rto * TCP_TO_TIMER_TICK, 1));
+}
+
+always_inline u8
+tcp_timer_is_active (tcp_connection_t * tc, tcp_timers_e timer)
+{
+ return tc->timers[timer] != TCP_TIMER_HANDLE_INVALID;
+}
#endif /* __included_tcp_timer_h__ */
#include <vppinfra/rbtree.h>
#include <vnet/tcp/tcp_packet.h>
#include <vnet/session/transport.h>
+#include <vppinfra/tw_timer_16t_2w_512sl.h>
#define TCP_TICK 0.001 /**< TCP tick period (s) */
#define THZ (u32) (1/TCP_TICK) /**< TCP tick frequency */
return (tcp_connection_t *) tconn;
}
+typedef tw_timer_wheel_16t_2w_512sl_t tcp_timer_wheel_t;
+
#endif /* SRC_VNET_TCP_TCP_TYPES_H_ */
/*