aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/svm/svm_fifo.c27
-rw-r--r--src/svm/svm_fifo.h5
-rw-r--r--src/vcl/vcl_private.h2
-rw-r--r--src/vcl/vppcom.c38
4 files changed, 47 insertions, 25 deletions
diff --git a/src/svm/svm_fifo.c b/src/svm/svm_fifo.c
index 2cce2bf50b3..22cb64eb475 100644
--- a/src/svm/svm_fifo.c
+++ b/src/svm/svm_fifo.c
@@ -1136,10 +1136,11 @@ svm_fifo_fill_chunk_list (svm_fifo_t * f)
}
int
-svm_fifo_segments (svm_fifo_t * f, svm_fifo_seg_t * fs, u32 n_segs,
- u32 max_bytes)
+svm_fifo_segments (svm_fifo_t * f, u32 offset, svm_fifo_seg_t * fs,
+ u32 n_segs, u32 max_bytes)
{
- u32 cursize, to_read, head, tail, fs_index = 1, n_bytes, head_pos, len;
+ u32 cursize, to_read, head, tail, fs_index = 1;
+ u32 n_bytes, head_pos, len, start;
svm_fifo_chunk_t *c;
f_load_head_tail_cons (f, &head, &tail);
@@ -1150,22 +1151,32 @@ svm_fifo_segments (svm_fifo_t * f, svm_fifo_seg_t * fs, u32 n_segs,
if (PREDICT_FALSE (cursize == 0))
return SVM_FIFO_EEMPTY;
- to_read = clib_min (cursize, max_bytes);
+ if (offset >= cursize)
+ return SVM_FIFO_EEMPTY;
+
+ to_read = clib_min (cursize - offset, max_bytes);
+ start = head + offset;
+
+ if (!f->head_chunk)
+ f->head_chunk = svm_fifo_find_chunk (f, head);
c = f->head_chunk;
- head_pos = head - c->start_byte;
+
+ while (!f_chunk_includes_pos (c, start))
+ c = c->next;
+
+ head_pos = start - c->start_byte;
fs[0].data = c->data + head_pos;
- fs[0].len = c->length - head_pos;
+ fs[0].len = clib_min (c->length - head_pos, cursize - offset);
n_bytes = fs[0].len;
- c = c->next;
while (n_bytes < to_read && fs_index < n_segs)
{
+ c = c->next;
len = clib_min (c->length, to_read - n_bytes);
fs[fs_index].data = c->data;
fs[fs_index].len = len;
n_bytes += len;
- c = c->next;
fs_index += 1;
}
diff --git a/src/svm/svm_fifo.h b/src/svm/svm_fifo.h
index 93ef006fd48..408d99a3188 100644
--- a/src/svm/svm_fifo.h
+++ b/src/svm/svm_fifo.h
@@ -357,13 +357,14 @@ void svm_fifo_dequeue_drop_all (svm_fifo_t * f);
* data is consumed.
*
* @param f fifo
+ * @param offset offset from where to retrieve segments
* @param fs array of fifo segments allocated by caller
* @param n_segs number of fifo segments in array
* @param max_bytes max bytes to be mapped to fifo segments
* @return number of bytes in fifo segments or SVM_FIFO_EEMPTY
*/
-int svm_fifo_segments (svm_fifo_t * f, svm_fifo_seg_t * fs, u32 n_segs,
- u32 max_bytes);
+int svm_fifo_segments (svm_fifo_t * f, u32 offset, svm_fifo_seg_t * fs,
+ u32 n_segs, u32 max_bytes);
/**
* Add io events subscriber to list
*
diff --git a/src/vcl/vcl_private.h b/src/vcl/vcl_private.h
index 51bdd65a102..89151faa316 100644
--- a/src/vcl/vcl_private.h
+++ b/src/vcl/vcl_private.h
@@ -184,6 +184,8 @@ typedef struct
int libc_epfd;
svm_msg_q_t *our_evt_q;
vcl_session_msg_t *accept_evts_fifo;
+ /** bytes delivered as segment but not yet freed */
+ u32 rx_bytes_pending;
#if VCL_ELOG
elog_track_t elog_track;
#endif
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index 56f50ad5cba..f1bb2b0def5 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -1983,8 +1983,26 @@ vppcom_session_read_segments (uint32_t session_handle,
}
}
- n_read = svm_fifo_segments (rx_fifo, (svm_fifo_seg_t *) ds, n_segments,
- max_bytes);
+ n_read = svm_fifo_segments (rx_fifo, s->rx_bytes_pending,
+ (svm_fifo_seg_t *) ds, n_segments, max_bytes);
+ if (n_read < 0)
+ return VPPCOM_EAGAIN;
+
+ if (svm_fifo_max_dequeue_cons (rx_fifo) == n_read)
+ {
+ svm_fifo_unset_event (s->rx_fifo);
+ if (svm_fifo_max_dequeue_cons (rx_fifo) != n_read
+ && svm_fifo_set_event (s->rx_fifo)
+ && VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK))
+ {
+ session_event_t *e;
+ vec_add2 (wrk->unhandled_evts_vector, e, 1);
+ e->event_type = SESSION_IO_EVT_RX;
+ e->session_index = s->session_index;
+ }
+ }
+
+ s->rx_bytes_pending += n_read;
return n_read;
}
@@ -1999,19 +2017,9 @@ vppcom_session_free_segments (uint32_t session_handle, uint32_t n_bytes)
return;
svm_fifo_dequeue_drop (s->rx_fifo, n_bytes);
- if (svm_fifo_is_empty_cons (s->rx_fifo))
- {
- svm_fifo_unset_event (s->rx_fifo);
- if (!svm_fifo_is_empty_cons (s->rx_fifo)
- && svm_fifo_set_event (s->rx_fifo)
- && VCL_SESS_ATTR_TEST (s->attr, VCL_SESS_ATTR_NONBLOCK))
- {
- session_event_t *e;
- vec_add2 (wrk->unhandled_evts_vector, e, 1);
- e->event_type = SESSION_IO_EVT_RX;
- e->session_index = s->session_index;
- }
- }
+
+ ASSERT (s->rx_bytes_pending < n_bytes);
+ s->rx_bytes_pending -= n_bytes;
}
static u8