X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ftcp%2Ftcp.c;h=df3d61db48decd1af6a13d347d7d6777e04f7056;hb=e57df7c6771906ce9e1b373028755eabc4764c0f;hp=2ac938a1b1e03427704f1e2a0f902d2be8d0859b;hpb=999840cf805f26a490e8e6b8acc1fe7a7c21a181;p=vpp.git diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c index 2ac938a1b1e..df3d61db48d 100644 --- a/src/vnet/tcp/tcp.c +++ b/src/vnet/tcp/tcp.c @@ -186,7 +186,7 @@ tcp_session_get_listener (u32 listener_index) * */ 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); @@ -208,11 +208,16 @@ tcp_half_open_connection_del (tcp_connection_t * tc) 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; } @@ -354,6 +359,8 @@ tcp_program_cleanup (tcp_worker_ctx_t * wrk, tcp_connection_t * tc) 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 */ @@ -368,7 +375,8 @@ tcp_connection_close (tcp_connection_t * tc) 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 */ @@ -379,7 +387,7 @@ tcp_connection_close (tcp_connection_t * tc) 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)) @@ -390,7 +398,8 @@ tcp_connection_close (tcp_connection_t * tc) /* 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)) @@ -398,13 +407,15 @@ tcp_connection_close (tcp_connection_t * tc) 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 */ @@ -433,6 +444,18 @@ tcp_session_cleanup (u32 conn_index, u32 thread_index) 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) { @@ -469,11 +492,11 @@ tcp_connection_timers_init (tcp_connection_t * tc) 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 @@ -728,10 +751,7 @@ tcp_alloc_custom_local_endpoint (tcp_main_t * tm, ip46_address_t * lcl_addr, } 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; } @@ -757,7 +777,20 @@ tcp_session_open (transport_endpoint_cfg_t * rmt) 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 @@ -956,7 +989,7 @@ tcp_timer_waitclose_handler (tcp_connection_t * 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_closewait, 1); + tcp_worker_stats_inc (wrk, to_closewait, 1); break; } @@ -969,8 +1002,9 @@ tcp_timer_waitclose_handler (tcp_connection_t * tc) 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; @@ -992,21 +1026,21 @@ tcp_timer_waitclose_handler (tcp_connection_t * tc) 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); @@ -1014,7 +1048,7 @@ tcp_timer_waitclose_handler (tcp_connection_t * 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); @@ -1127,6 +1161,7 @@ const static transport_proto_vft_t tcp_proto = { .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, @@ -1186,7 +1221,7 @@ tcp_expired_timers_dispatch (u32 * expired_timers) 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); /* @@ -1386,7 +1421,7 @@ tcp_configuration_init (void) 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 */