session tcp: infra for transports to send buffers 03/22803/6
authorFlorin Coras <fcoras@cisco.com>
Thu, 17 Oct 2019 05:06:08 +0000 (22:06 -0700)
committerDave Barach <openvpp@barachs.net>
Thu, 17 Oct 2019 19:39:07 +0000 (19:39 +0000)
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 <fcoras@cisco.com>
src/vnet/session/session.h
src/vnet/session/session_node.c
src/vnet/tcp/tcp.h
src/vnet/tcp/tcp_output.c

index 1d3ae0c..f738f39 100644 (file)
@@ -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);
index f51b892..a32abb0 100644 (file)
@@ -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);
 
index 825099a..75046ae 100644 (file)
@@ -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);
 
index 6ba0ee2..e3228c0 100644 (file)
@@ -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;