sizeof (args));
}
+static void
+tcp_cc_init (tcp_connection_t * tc)
+{
+ tc->cc_algo = tcp_cc_algo_get (tcp_main.cc_algo);
+ tc->cc_algo->init (tc);
+}
+
+static void
+tcp_cc_cleanup (tcp_connection_t * tc)
+{
+ if (tc->cc_algo->cleanup)
+ tc->cc_algo->cleanup (tc);
+}
+
+void
+tcp_cc_algo_register (tcp_cc_algorithm_type_e type,
+ const tcp_cc_algorithm_t * vft)
+{
+ tcp_main_t *tm = vnet_get_tcp_main ();
+ vec_validate (tm->cc_algos, type);
+
+ tm->cc_algos[type] = *vft;
+ hash_set_mem (tm->cc_algo_by_name, vft->name, type);
+}
+
+tcp_cc_algorithm_t *
+tcp_cc_algo_get (tcp_cc_algorithm_type_e type)
+{
+ tcp_main_t *tm = vnet_get_tcp_main ();
+ return &tm->cc_algos[type];
+}
+
+tcp_cc_algorithm_type_e
+tcp_cc_algo_new_type (const tcp_cc_algorithm_t * vft)
+{
+ tcp_main_t *tm = vnet_get_tcp_main ();
+ tcp_cc_algo_register (++tm->cc_last_type, vft);
+ return tm->cc_last_type;
+}
+
static u32
tcp_connection_bind (u32 session_index, transport_endpoint_t * lcl)
{
if (!tc->c_is_ip4 && ip6_address_is_link_local_unicast (&tc->c_rmt_ip6))
tcp_add_del_adjacency (tc, 0);
+ tcp_cc_cleanup (tc);
vec_free (tc->snd_sacks);
vec_free (tc->snd_sacks_fl);
+ if (tc->flags & TCP_CONN_RATE_SAMPLE)
+ tcp_bt_cleanup (tc);
+
/* Poison the entry */
if (CLIB_DEBUG > 0)
clib_memset (tc, 0xFA, sizeof (*tc));
tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
session_transport_reset_notify (&tc->connection);
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
+ session_transport_closed_notify (&tc->connection);
break;
case TCP_STATE_CLOSE_WAIT:
case TCP_STATE_FIN_WAIT_1:
tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
/* Make sure we mark the session as closed. In some states we may
* be still trying to send data */
- session_transport_closed_notify (&tc->connection);
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
+ session_transport_closed_notify (&tc->connection);
break;
case TCP_STATE_CLOSED:
case TCP_STATE_TIME_WAIT:
tcp_connection_timers_reset (tc);
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLOSEWAIT_TIME);
+ session_transport_closed_notify (&tc->connection);
break;
}
if (!transport_max_tx_dequeue (&tc->connection))
}
#endif /* 0 */
-static void
-tcp_cc_init (tcp_connection_t * tc)
-{
- tc->cc_algo = tcp_cc_algo_get (tcp_main.cc_algo);
- tc->cc_algo->init (tc);
-}
-
-void
-tcp_cc_algo_register (tcp_cc_algorithm_type_e type,
- const tcp_cc_algorithm_t * vft)
-{
- tcp_main_t *tm = vnet_get_tcp_main ();
- vec_validate (tm->cc_algos, type);
-
- tm->cc_algos[type] = *vft;
- hash_set_mem (tm->cc_algo_by_name, vft->name, type);
-}
-
-tcp_cc_algorithm_t *
-tcp_cc_algo_get (tcp_cc_algorithm_type_e type)
-{
- tcp_main_t *tm = vnet_get_tcp_main ();
- return &tm->cc_algos[type];
-}
-
/**
* Generate random iss as per rfc6528
*/
if (transport_connection_is_tx_paced (&tc->connection)
|| tcp_main.tx_pacing)
tcp_enable_pacing (tc);
+
+ if (tc->flags & TCP_CONN_RATE_SAMPLE)
+ tcp_bt_init (tc);
}
static int
format_tcp_listener_session (u8 * s, va_list * args)
{
u32 tci = va_arg (*args, u32);
+ u32 __clib_unused thread_index = va_arg (*args, u32);
u32 verbose = va_arg (*args, u32);
tcp_connection_t *tc = tcp_listener_get (tci);
s = format (s, "%-50U", format_tcp_connection_id, tc);
format_tcp_half_open_session (u8 * s, va_list * args)
{
u32 tci = va_arg (*args, u32);
+ u32 __clib_unused thread_index = va_arg (*args, u32);
tcp_connection_t *tc = tcp_half_open_connection_get (tci);
return format (s, "%U", format_tcp_connection_id, tc);
}
tcp_set_time_now (wrk);
tw_timer_expire_timers_16t_2w_512sl (&wrk->timer_wheel, now);
- tcp_do_fastretransmits (wrk);
- tcp_send_acks (wrk);
tcp_flush_frames_to_output (wrk);
}
.update_time = tcp_update_time,
.tx_fifo_offset = tcp_session_tx_fifo_offset,
.flush_data = tcp_session_flush_data,
+ .custom_tx = tcp_session_custom_tx,
.format_connection = format_tcp_session,
.format_listener = format_tcp_listener_session,
.format_half_open = format_tcp_half_open_session,
- .tx_type = TRANSPORT_TX_PEEK,
- .service_type = TRANSPORT_SERVICE_VC,
+ .transport_options = {
+ .tx_type = TRANSPORT_TX_PEEK,
+ .service_type = TRANSPORT_SERVICE_VC,
+ },
};
/* *INDENT-ON* */
break;
case TCP_STATE_FIN_WAIT_1:
tcp_connection_timers_reset (tc);
+ session_transport_closed_notify (&tc->connection);
if (tc->flags & TCP_CONN_FINPNDG)
{
/* If FIN pending, we haven't sent everything, but we did try.
* Notify session layer that transport is closed. */
tcp_connection_set_state (tc, TCP_STATE_CLOSED);
- session_transport_closed_notify (&tc->connection);
tcp_send_reset (tc);
tcp_timer_set (tc, TCP_TIMER_WAITCLOSE, TCP_CLEANUP_TIME);
}
for (thread = 0; thread < num_threads; thread++)
{
- vec_validate (tm->wrk_ctx[thread].pending_fast_rxt, 255);
- vec_validate (tm->wrk_ctx[thread].ongoing_fast_rxt, 255);
- vec_validate (tm->wrk_ctx[thread].postponed_fast_rxt, 255);
vec_validate (tm->wrk_ctx[thread].pending_deq_acked, 255);
- vec_validate (tm->wrk_ctx[thread].pending_acks, 255);
vec_validate (tm->wrk_ctx[thread].pending_disconnects, 255);
- vec_reset_length (tm->wrk_ctx[thread].pending_fast_rxt);
- vec_reset_length (tm->wrk_ctx[thread].ongoing_fast_rxt);
- vec_reset_length (tm->wrk_ctx[thread].postponed_fast_rxt);
vec_reset_length (tm->wrk_ctx[thread].pending_deq_acked);
- vec_reset_length (tm->wrk_ctx[thread].pending_acks);
vec_reset_length (tm->wrk_ctx[thread].pending_disconnects);
tm->wrk_ctx[thread].vm = vlib_mains[thread];
tcp_initialize_iss_seed (tm);
tm->bytes_per_buffer = vlib_buffer_get_default_data_size (vm);
-
+ tm->cc_last_type = TCP_CC_LAST;
return error;
}
tm->tx_pacing = 1;
tm->cc_algo = TCP_CC_NEWRENO;
tm->default_mtu = 1460;
+ tm->initial_cwnd_multiplier = 0;
return 0;
}
;
else if (unformat (input, "mtu %d", &tm->default_mtu))
;
+ else if (unformat (input, "initial-cwnd-multiplier %d",
+ &tm->initial_cwnd_multiplier))
+ ;
else if (unformat (input, "no-tx-pacing"))
tm->tx_pacing = 0;
else if (unformat (input, "cc-algo %U", unformat_tcp_cc_algo,