vcl: add support to write segments 85/41485/3
authorAritra Basu <aritrbas@cisco.com>
Wed, 28 Aug 2024 01:05:17 +0000 (18:05 -0700)
committerAritra Basu <aritrbas@cisco.com>
Thu, 29 Aug 2024 20:51:05 +0000 (13:51 -0700)
Type: improvement

Change-Id: Icfdaed6b70b83668127656930afcb4ac3c63b234
Signed-off-by: Aritra Basu <aritrbas@cisco.com>
src/plugins/hs_apps/vcl/vcl_test.h
src/plugins/hs_apps/vcl/vcl_test_server.c
src/vcl/vppcom.c
src/vcl/vppcom.h

index 0ce27ef..2b45339 100644 (file)
@@ -420,6 +420,39 @@ vcl_test_write (vcl_test_session_t *ts, void *buf, uint32_t nbytes)
   return (tx_bytes);
 }
 
+static inline int
+vcl_test_write_ds (vcl_test_session_t *ts)
+{
+  vcl_test_stats_t *stats = &ts->stats;
+  int tx_bytes;
+
+  do
+    {
+      stats->tx_xacts++;
+      if (ts->ds[1].len)
+       tx_bytes = vppcom_session_write_segments (ts->fd, ts->ds, 2);
+      else
+       tx_bytes = vppcom_session_write_segments (ts->fd, ts->ds, 1);
+
+      if (tx_bytes < 0)
+       errno = -tx_bytes;
+      if ((tx_bytes == 0) ||
+         ((tx_bytes < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))))
+       stats->rx_eagain++;
+    }
+  while ((tx_bytes == 0) ||
+        ((tx_bytes < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))));
+
+  if (tx_bytes < 0)
+    {
+      vterr ("vppcom_session_write_segments()", -errno);
+    }
+  else
+    stats->tx_bytes += tx_bytes;
+
+  return (tx_bytes);
+}
+
 static inline void
 dump_help (void)
 {
index d17a208..5de5317 100644 (file)
@@ -282,11 +282,7 @@ vts_server_process_rx (vcl_test_session_t *conn, int rx_bytes)
   if (conn->cfg.test == HS_TEST_TYPE_BI)
     {
       if (vsm->use_ds)
-       {
-         (void) vcl_test_write (conn, conn->ds[0].data, conn->ds[0].len);
-         if (conn->ds[1].len)
-           (void) vcl_test_write (conn, conn->ds[1].data, conn->ds[1].len);
-       }
+       (void) vcl_test_write_ds (conn);
       else
        (void) vcl_test_write (conn, conn->rxbuf, rx_bytes);
     }
index 56f6504..5408fb7 100644 (file)
@@ -2344,6 +2344,75 @@ vppcom_session_write_inline (vcl_worker_t *wrk, vcl_session_t *s, void *buf,
   return n_write;
 }
 
+int
+vppcom_session_write_segments (uint32_t session_handle,
+                              vppcom_data_segment_t *ds, uint32_t n_segments)
+{
+  vcl_worker_t *wrk = vcl_worker_get_current ();
+  int n_write = 0, n_bytes = 0, is_nonblocking;
+  vcl_session_t *s = 0;
+  svm_fifo_t *tx_fifo;
+  svm_msg_q_t *mq;
+  u8 is_ct;
+  u32 i;
+
+  if (PREDICT_FALSE (!ds))
+    return VPPCOM_EFAULT;
+
+  /* Accept zero length writes but just return */
+  if (PREDICT_FALSE (ds[0].len == 0))
+    return VPPCOM_OK;
+
+  s = vcl_session_get_w_handle (wrk, session_handle);
+  if (PREDICT_FALSE (!s || (s->flags & VCL_SESSION_F_IS_VEP)))
+    return VPPCOM_EBADFD;
+
+  if (PREDICT_FALSE (!vcl_session_is_open (s)))
+    return vcl_session_closed_error (s);
+
+  if (PREDICT_FALSE (s->flags & VCL_SESSION_F_WR_SHUTDOWN))
+    return VPPCOM_EPIPE;
+
+  is_nonblocking = vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK);
+  is_ct = vcl_session_is_ct (s);
+  mq = wrk->app_event_queue;
+  tx_fifo = is_ct ? s->ct_tx_fifo : s->tx_fifo;
+
+  for (i = 0; i < n_segments; i++)
+    n_bytes += ds[i].len;
+
+  if (svm_fifo_max_enqueue_prod (tx_fifo) < n_bytes)
+    {
+      if (is_nonblocking)
+       {
+         return VPPCOM_EWOULDBLOCK;
+       }
+      while (svm_fifo_max_enqueue_prod (tx_fifo) < n_bytes)
+       {
+         svm_fifo_add_want_deq_ntf (tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
+         if (vcl_session_is_closing (s))
+           return vcl_session_closing_error (s);
+
+         svm_msg_q_wait (mq, SVM_MQ_WAIT_EMPTY);
+         vcl_worker_flush_mq_events (wrk);
+       }
+    }
+
+  n_write = svm_fifo_enqueue_segments (tx_fifo, (svm_fifo_seg_t *) ds,
+                                      n_segments, 0 /* allow_partial */);
+
+  /* The underlying fifo segment can run out of memory */
+  if (PREDICT_FALSE (n_write < 0))
+    return VPPCOM_EAGAIN;
+
+  if (svm_fifo_set_event (s->tx_fifo))
+    app_send_io_evt_to_vpp (s->vpp_evt_q,
+                           s->tx_fifo->shr->master_session_index,
+                           SESSION_IO_EVT_TX, SVM_Q_WAIT);
+
+  return n_write;
+}
+
 int
 vppcom_session_write (uint32_t session_handle, void *buf, size_t n)
 {
index 386d7d0..3de2934 100644 (file)
@@ -259,6 +259,9 @@ extern int vppcom_session_read_segments (uint32_t session_handle,
                                         vppcom_data_segment_t * ds,
                                         uint32_t n_segments,
                                         uint32_t max_bytes);
+extern int vppcom_session_write_segments (uint32_t session_handle,
+                                        vppcom_data_segment_t * ds,
+                                        uint32_t n_segments);
 extern void vppcom_session_free_segments (uint32_t session_handle,
                                          uint32_t n_bytes);
 extern int vppcom_add_cert_key_pair (vppcom_cert_key_pair_t *ckpair);