From 2a7ea2ee92d6dc4800ee21323d3324a9e8449dcf Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Wed, 16 Oct 2019 22:06:08 -0700 Subject: [PATCH] session tcp: infra for transports to send buffers Type: feature Add infra that allows transpors to enqueue pending buffers without the need to build and manage their own pending frames. An important benefit is the fact that buffer wire/tx ordering is ensured by session layer. Change-Id: I764fd1693d610b321a1d0c84b648a314f14583db Signed-off-by: Florin Coras --- src/vnet/session/session.h | 15 ++++++++++ src/vnet/session/session_node.c | 14 +++++++++ src/vnet/tcp/tcp.h | 4 --- src/vnet/tcp/tcp_output.c | 63 +++++------------------------------------ 4 files changed, 36 insertions(+), 60 deletions(-) diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h index 1d3ae0ca4b2..f738f3957e2 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -116,6 +116,12 @@ typedef struct session_worker_ /** Peekers rw lock */ clib_rwlock_t peekers_rw_locks; + /** Vector of buffers to be sent */ + u32 *pending_tx_buffers; + + /** Vector of nexts for the pending tx buffers */ + u16 *pending_tx_nexts; + #if SESSION_DEBUG /** last event poll time by thread */ f64 last_event_poll; @@ -611,6 +617,15 @@ do { \ int session_main_flush_enqueue_events (u8 proto, u32 thread_index); int session_main_flush_all_enqueue_events (u8 transport_proto); void session_flush_frames_main_thread (vlib_main_t * vm); + +always_inline void +session_add_pending_tx_buffer (session_type_t st, u32 thread_index, u32 bi) +{ + session_worker_t *wrk = session_main_get_worker (thread_index); + vec_add1 (wrk->pending_tx_buffers, bi); + vec_add1 (wrk->pending_tx_nexts, session_main.session_type_to_next[st]); +} + ssvm_private_t *session_main_get_evt_q_segment (void); void session_node_enable_disable (u8 is_en); clib_error_t *vnet_session_enable_disable (vlib_main_t * vm, u8 is_en); diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c index f51b892736a..a32abb07f90 100644 --- a/src/vnet/session/session_node.c +++ b/src/vnet/session/session_node.c @@ -1235,6 +1235,17 @@ session_evt_add_to_list (session_worker_t * wrk, session_event_t * evt) } } +static void +session_flush_pending_tx_buffers (session_worker_t * wrk, + vlib_node_runtime_t * node) +{ + vlib_buffer_enqueue_to_next (wrk->vm, node, wrk->pending_tx_buffers, + wrk->pending_tx_nexts, + vec_len (wrk->pending_tx_nexts)); + vec_reset_length (wrk->pending_tx_buffers); + vec_reset_length (wrk->pending_tx_nexts); +} + static uword session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) @@ -1337,6 +1348,9 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, break; }; + if (vec_len (wrk->pending_tx_buffers)) + session_flush_pending_tx_buffers (wrk, node); + vlib_node_increment_counter (vm, session_queue_node.index, SESSION_QUEUE_ERROR_TX, n_tx_packets); diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h index 825099a276d..75046ae8155 100644 --- a/src/vnet/tcp/tcp.h +++ b/src/vnet/tcp/tcp.h @@ -510,9 +510,6 @@ typedef struct tcp_worker_ctx_ /** tx buffer free list */ u32 *tx_buffers; - /** tx frames for tcp 4/6 output nodes */ - vlib_frame_t *tx_frames[2]; - /** tx frames for ip 4/6 lookup nodes */ vlib_frame_t *ip_lookup_tx_frames[2]; @@ -789,7 +786,6 @@ void tcp_send_fin (tcp_connection_t * tc); void tcp_send_ack (tcp_connection_t * tc); void tcp_update_burst_snd_vars (tcp_connection_t * tc); void tcp_update_rto (tcp_connection_t * tc); -void tcp_flush_frame_to_output (tcp_worker_ctx_t * wrk, u8 is_ip4); void tcp_flush_frames_to_output (tcp_worker_ctx_t * wrk); void tcp_send_window_update_ack (tcp_connection_t * tc); diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index 6ba0ee28f13..e3228c07fa1 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -674,51 +674,19 @@ tcp_enqueue_to_ip_lookup (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi, session_flush_frames_main_thread (wrk->vm); } -always_inline void -tcp_enqueue_to_output_i (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi, - u8 is_ip4, u8 flush) +static void +tcp_enqueue_to_output (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi, + u8 is_ip4) { - u32 *to_next, next_index; - vlib_frame_t *f; + session_type_t st; b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; b->error = 0; - /* Decide where to send the packet */ - next_index = is_ip4 ? tcp4_output_node.index : tcp6_output_node.index; - tcp_trajectory_add_start (b, 2); - - /* Get frame to v4/6 output node */ - f = wrk->tx_frames[!is_ip4]; - if (!f) - { - f = vlib_get_frame_to_node (wrk->vm, next_index); - ASSERT (f); - wrk->tx_frames[!is_ip4] = f; - } - to_next = vlib_frame_vector_args (f); - to_next[f->n_vectors] = bi; - f->n_vectors += 1; - if (flush || f->n_vectors == VLIB_FRAME_SIZE) - { - vlib_put_frame_to_node (wrk->vm, next_index, f); - wrk->tx_frames[!is_ip4] = 0; - } -} - -static void -tcp_enqueue_to_output (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi, - u8 is_ip4) -{ - tcp_enqueue_to_output_i (wrk, b, bi, is_ip4, 0); + st = session_type_from_proto_and_ip (TRANSPORT_PROTO_TCP, is_ip4); + session_add_pending_tx_buffer (st, wrk->vm->thread_index, bi); } -static void -tcp_enqueue_to_output_now (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi, - u8 is_ip4) -{ - tcp_enqueue_to_output_i (wrk, b, bi, is_ip4, 1); -} #endif /* CLIB_MARCH_VARIANT */ static int @@ -1014,21 +982,6 @@ tcp_send_synack (tcp_connection_t * tc) TCP_EVT (TCP_EVT_SYNACK_SENT, tc); } -/** - * Flush tx frame populated by retransmits and timer pops - */ -void -tcp_flush_frame_to_output (tcp_worker_ctx_t * wrk, u8 is_ip4) -{ - if (wrk->tx_frames[!is_ip4]) - { - u32 next_index; - next_index = is_ip4 ? tcp4_output_node.index : tcp6_output_node.index; - vlib_put_frame_to_node (wrk->vm, next_index, wrk->tx_frames[!is_ip4]); - wrk->tx_frames[!is_ip4] = 0; - } -} - /** * Flush ip lookup tx frames populated by timer pops */ @@ -1051,8 +1004,6 @@ tcp_flush_frame_to_ip_lookup (tcp_worker_ctx_t * wrk, u8 is_ip4) void tcp_flush_frames_to_output (tcp_worker_ctx_t * wrk) { - tcp_flush_frame_to_output (wrk, 1); - tcp_flush_frame_to_output (wrk, 0); tcp_flush_frame_to_ip_lookup (wrk, 1); tcp_flush_frame_to_ip_lookup (wrk, 0); } @@ -1093,7 +1044,7 @@ tcp_send_fin (tcp_connection_t * tc) b = vlib_get_buffer (vm, bi); tcp_init_buffer (vm, b); tcp_make_fin (tc, b); - tcp_enqueue_to_output_now (wrk, b, bi, tc->c_is_ip4); + tcp_enqueue_to_output (wrk, b, bi, tc->c_is_ip4); TCP_EVT (TCP_EVT_FIN_SENT, tc); /* Account for the FIN */ tc->snd_nxt += 1; -- 2.16.6