diff options
author | Aritra Basu <aritrbas@cisco.com> | 2024-08-27 18:05:17 -0700 |
---|---|---|
committer | Aritra Basu <aritrbas@cisco.com> | 2024-08-29 13:51:05 -0700 |
commit | f0e81d247b7cd13b621262f29ed1ae6366b68b78 (patch) | |
tree | 2f5f7bc47c7bca3bea151f61e2d7bc819430400d | |
parent | e9bc3320192d72f817379aa4621c1dff15bdee29 (diff) |
vcl: add support to write segments
Type: improvement
Change-Id: Icfdaed6b70b83668127656930afcb4ac3c63b234
Signed-off-by: Aritra Basu <aritrbas@cisco.com>
-rw-r--r-- | src/plugins/hs_apps/vcl/vcl_test.h | 33 | ||||
-rw-r--r-- | src/plugins/hs_apps/vcl/vcl_test_server.c | 6 | ||||
-rw-r--r-- | src/vcl/vppcom.c | 69 | ||||
-rw-r--r-- | src/vcl/vppcom.h | 3 |
4 files changed, 106 insertions, 5 deletions
diff --git a/src/plugins/hs_apps/vcl/vcl_test.h b/src/plugins/hs_apps/vcl/vcl_test.h index 0ce27ef84e2..2b45339099e 100644 --- a/src/plugins/hs_apps/vcl/vcl_test.h +++ b/src/plugins/hs_apps/vcl/vcl_test.h @@ -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) { diff --git a/src/plugins/hs_apps/vcl/vcl_test_server.c b/src/plugins/hs_apps/vcl/vcl_test_server.c index d17a2089ba7..5de53173784 100644 --- a/src/plugins/hs_apps/vcl/vcl_test_server.c +++ b/src/plugins/hs_apps/vcl/vcl_test_server.c @@ -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); } diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index 56f650438a4..5408fb79186 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -2345,6 +2345,75 @@ vppcom_session_write_inline (vcl_worker_t *wrk, vcl_session_t *s, void *buf, } 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) { vcl_worker_t *wrk = vcl_worker_get_current (); diff --git a/src/vcl/vppcom.h b/src/vcl/vppcom.h index 386d7d0c3f7..3de2934adc1 100644 --- a/src/vcl/vppcom.h +++ b/src/vcl/vppcom.h @@ -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); |