*
*/
static void
-tcp_half_open_connection_del (tcp_connection_t * tc)
+tcp_half_open_connection_free (tcp_connection_t * tc)
{
tcp_main_t *tm = vnet_get_tcp_main ();
clib_spinlock_lock_if_init (&tm->half_open_lock);
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);
- tcp_half_open_connection_del (tc);
+
+ session_half_open_delete_notify (TRANSPORT_PROTO_TCP, tc->c_s_ho_handle);
+ wrk = tcp_get_worker (tc->c_thread_index);
+ tcp_timer_reset (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT_SYN);
+ tcp_half_open_connection_free (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 */
tcp_connection_cleanup (tc);
}
+static void
+tcp_session_cleanup_ho (u32 conn_index)
+{
+ tcp_worker_ctx_t *wrk;
+ tcp_connection_t *tc;
+
+ tc = tcp_half_open_connection_get (conn_index);
+ wrk = tcp_get_worker (tc->c_thread_index);
+ tcp_timer_reset (&wrk->timer_wheel, tc, TCP_TIMER_RETRANSMIT_SYN);
+ tcp_half_open_connection_free (tc);
+}
+
static void
tcp_session_reset (u32 conn_index, u32 thread_index)
{
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
}
port = transport_alloc_local_port (TRANSPORT_PROTO_TCP, lcl_addr);
if (port < 1)
- {
- clib_warning ("Failed to allocate src port");
- return -1;
- }
+ return SESSION_E_NOPORT;
*lcl_port = port;
return 0;
}
rmt, &lcl_addr, &lcl_port);
if (rv)
- return -1;
+ {
+ if (rv != SESSION_E_PORTINUSE)
+ return rv;
+
+ if (session_lookup_connection (rmt->fib_index, &lcl_addr, &rmt->ip,
+ lcl_port, rmt->port, TRANSPORT_PROTO_UDP,
+ rmt->is_ip4))
+ return SESSION_E_PORTINUSE;
+
+ /* 5-tuple is available so increase lcl endpoint refcount and proceed
+ * with connection allocation */
+ transport_share_local_endpoint (TRANSPORT_PROTO_UDP, &lcl_addr,
+ lcl_port);
+ }
/*
* Create connection and send SYN
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);
.connect = tcp_session_open,
.close = tcp_session_close,
.cleanup = tcp_session_cleanup,
+ .cleanup_ho = tcp_session_cleanup_ho,
.reset = tcp_session_reset,
.send_params = tcp_session_send_params,
.update_time = tcp_update_time,
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_cfg.enable_tx_pacing = 1;
tcp_cfg.allow_tso = 0;
tcp_cfg.csum_offload = 1;
- tcp_cfg.cc_algo = TCP_CC_NEWRENO;
+ tcp_cfg.cc_algo = TCP_CC_CUBIC;
tcp_cfg.rwnd_min_update_ack = 1;
/* Time constants defined as timer tick (100ms) multiples */