session: unify buffer tx dispatching
[vpp.git] / src / vnet / session / session_node.c
index fde1931..c15d2be 100644 (file)
@@ -816,8 +816,7 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
                                session_evt_elt_t * elt,
                                int *n_tx_packets, u8 peek_data)
 {
-  u32 next_index, next0, next1, *to_next, n_left_to_next, max_burst;
-  u32 n_trace, n_bufs_needed = 0, n_left, pbi;
+  u32 n_trace, n_bufs_needed = 0, n_left, pbi, next_index, max_burst;
   session_tx_context_t *ctx = &wrk->ctx;
   session_main_t *smm = &session_main;
   session_event_t *e = &elt->evt;
@@ -834,7 +833,6 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
     }
 
   next_index = smm->session_type_to_next[ctx->s->session_type];
-  next0 = next1 = next_index;
   max_burst = VLIB_FRAME_SIZE - *n_tx_packets;
 
   tp = session_get_transport_proto (ctx->s);
@@ -845,6 +843,7 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
     {
       if (ctx->transport_vft->flush_data)
        ctx->transport_vft->flush_data (ctx->tc);
+      e->event_type = SESSION_IO_EVT_TX;
     }
 
   if (ctx->s->flags & SESSION_F_CUSTOM_TX)
@@ -883,7 +882,12 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
   session_tx_set_dequeue_params (vm, ctx, max_burst, peek_data);
 
   if (PREDICT_FALSE (!ctx->max_len_to_snd))
-    return SESSION_TX_NO_DATA;
+    {
+      transport_connection_tx_pacer_reset_bucket (ctx->tc,
+                                                 vm->clib_time.
+                                                 last_cpu_time);
+      return SESSION_TX_NO_DATA;
+    }
 
   n_bufs_needed = ctx->n_segs_per_evt * ctx->n_bufs_per_seg;
   vec_validate_aligned (wrk->tx_buffers, n_bufs_needed - 1,
@@ -899,15 +903,6 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
       return SESSION_TX_NO_BUFFERS;
     }
 
-  /*
-   * Write until we fill up a frame
-   */
-  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-  if (PREDICT_FALSE (ctx->n_segs_per_evt > n_left_to_next))
-    {
-      ctx->n_segs_per_evt = n_left_to_next;
-      ctx->max_len_to_snd = ctx->snd_mss * n_left_to_next;
-    }
   ctx->left_to_snd = ctx->max_len_to_snd;
   n_left = ctx->n_segs_per_evt;
 
@@ -923,8 +918,8 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
       pb = vlib_get_buffer (vm, pbi);
       vlib_prefetch_buffer_header (pb, STORE);
 
-      to_next[0] = bi0 = wrk->tx_buffers[--n_bufs];
-      to_next[1] = bi1 = wrk->tx_buffers[--n_bufs];
+      bi0 = wrk->tx_buffers[--n_bufs];
+      bi1 = wrk->tx_buffers[--n_bufs];
 
       b0 = vlib_get_buffer (vm, bi0);
       b1 = vlib_get_buffer (vm, bi1);
@@ -935,16 +930,15 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
       ctx->transport_vft->push_header (ctx->tc, b0);
       ctx->transport_vft->push_header (ctx->tc, b1);
 
-      to_next += 2;
-      n_left_to_next -= 2;
       n_left -= 2;
 
       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b1);
 
-      vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
-                                      n_left_to_next, bi0, bi1, next0,
-                                      next1);
+      vec_add1 (wrk->pending_tx_buffers, bi0);
+      vec_add1 (wrk->pending_tx_buffers, bi1);
+      vec_add1 (wrk->pending_tx_nexts, next_index);
+      vec_add1 (wrk->pending_tx_nexts, next_index);
     }
   while (n_left)
     {
@@ -958,7 +952,7 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
          vlib_prefetch_buffer_header (pb, STORE);
        }
 
-      to_next[0] = bi0 = wrk->tx_buffers[--n_bufs];
+      bi0 = wrk->tx_buffers[--n_bufs];
       b0 = vlib_get_buffer (vm, bi0);
       session_tx_fill_buffer (vm, ctx, b0, &n_bufs, peek_data);
 
@@ -966,18 +960,16 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
        * total_length_not_including_first_buffer are updated */
       ctx->transport_vft->push_header (ctx->tc, b0);
 
-      to_next += 1;
-      n_left_to_next -= 1;
       n_left -= 1;
 
       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
 
-      vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
-                                      n_left_to_next, bi0, next0);
+      vec_add1 (wrk->pending_tx_buffers, bi0);
+      vec_add1 (wrk->pending_tx_nexts, next_index);
     }
 
   if (PREDICT_FALSE ((n_trace = vlib_get_trace_count (vm, node)) > 0))
-    session_tx_trace_frame (vm, node, next_index, to_next,
+    session_tx_trace_frame (vm, node, next_index, wrk->pending_tx_buffers,
                            ctx->n_segs_per_evt, ctx->s, n_trace);
 
   if (PREDICT_FALSE (n_bufs))
@@ -985,7 +977,6 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
 
   *n_tx_packets += ctx->n_segs_per_evt;
   transport_connection_update_tx_bytes (ctx->tc, ctx->max_len_to_snd);
-  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
 
   SESSION_EVT (SESSION_EVT_DEQ, ctx->s, ctx->max_len_to_snd, ctx->max_dequeue,
               ctx->s->tx_fifo->has_event, wrk->last_vlib_time);
@@ -1229,6 +1220,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)
@@ -1317,7 +1319,8 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
   old_he = pool_elt_at_index (wrk->event_elts, wrk->old_head);
   old_ti = clib_llist_prev_index (old_he, evt_list);
 
-  while (!clib_llist_is_empty (wrk->event_elts, evt_list, old_he))
+  while (n_tx_packets < VLIB_FRAME_SIZE
+        && !clib_llist_is_empty (wrk->event_elts, evt_list, old_he))
     {
       clib_llist_index_t ei;
 
@@ -1326,10 +1329,13 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
       session_event_dispatch_io (wrk, node, elt, thread_index, &n_tx_packets);
 
       old_he = pool_elt_at_index (wrk->event_elts, wrk->old_head);
-      if (n_tx_packets >= VLIB_FRAME_SIZE || ei == old_ti)
+      if (ei == old_ti)
        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);
 
@@ -1420,6 +1426,8 @@ session_node_cmp_event (session_event_t * e, svm_fifo_t * f)
     case SESSION_IO_EVT_RX:
     case SESSION_IO_EVT_TX:
     case SESSION_IO_EVT_BUILTIN_RX:
+    case SESSION_IO_EVT_BUILTIN_TX:
+    case SESSION_IO_EVT_TX_FLUSH:
       if (e->session_index == f->master_session_index)
        return 1;
       break;
@@ -1469,8 +1477,7 @@ session_node_lookup_fifo_event (svm_fifo_t * f, session_event_t * e)
       found = session_node_cmp_event (e, f);
       if (found)
        return 1;
-      if (++index == mq->q->maxsize)
-       index = 0;
+      index = (index + 1) % mq->q->maxsize;
     }
   /*
    * Search pending events vector
@@ -1478,18 +1485,31 @@ session_node_lookup_fifo_event (svm_fifo_t * f, session_event_t * e)
 
   /* *INDENT-OFF* */
   clib_llist_foreach (wrk->event_elts, evt_list,
-                      pool_elt_at_index (wrk->event_elts, wrk->old_head),
+                      pool_elt_at_index (wrk->event_elts, wrk->new_head),
                       elt, ({
     found = session_node_cmp_event (&elt->evt, f);
     if (found)
       {
        clib_memcpy_fast (e, &elt->evt, sizeof (*e));
-       break;
+       goto done;
       }
+  }));
+  /* *INDENT-ON* */
 
+  /* *INDENT-OFF* */
+  clib_llist_foreach (wrk->event_elts, evt_list,
+                      pool_elt_at_index (wrk->event_elts, wrk->old_head),
+                      elt, ({
+    found = session_node_cmp_event (&elt->evt, f);
+    if (found)
+      {
+       clib_memcpy_fast (e, &elt->evt, sizeof (*e));
+       goto done;
+      }
   }));
   /* *INDENT-ON* */
 
+done:
   return found;
 }