summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/tlsopenssl/tls_openssl.c59
-rw-r--r--src/svm/svm_fifo.c36
-rw-r--r--src/svm/svm_fifo.h15
3 files changed, 77 insertions, 33 deletions
diff --git a/src/plugins/tlsopenssl/tls_openssl.c b/src/plugins/tlsopenssl/tls_openssl.c
index 5e49dbfe6c9..789c64d88d3 100644
--- a/src/plugins/tlsopenssl/tls_openssl.c
+++ b/src/plugins/tlsopenssl/tls_openssl.c
@@ -113,32 +113,27 @@ openssl_lctx_get (u32 lctx_index)
static int
openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl)
{
- u32 enq_now, enq_max;
- svm_fifo_chunk_t *c;
- int read, rv;
-
- enq_max = svm_fifo_max_enqueue_prod (f);
- if (!enq_max)
+ int read, rv, n_fs, i;
+ const int n_segs = 2;
+ svm_fifo_seg_t fs[n_segs];
+ u32 max_enq;
+
+ max_enq = svm_fifo_max_enqueue_prod (f);
+ n_fs = svm_fifo_provision_chunks (f, fs, n_segs, max_enq);
+ if (n_fs < 0)
return 0;
- svm_fifo_fill_chunk_list (f);
-
- enq_now = clib_min (svm_fifo_max_write_chunk (f), enq_max);
- if (!enq_now)
- return 0;
-
- read = SSL_read (ssl, svm_fifo_tail (f), enq_now);
+ /* Return early if we can't read anything */
+ read = SSL_read (ssl, fs[0].data, fs[0].len);
if (read <= 0)
return 0;
- c = svm_fifo_tail_chunk (f);
- while ((c = c->next) && read < enq_max)
+ for (i = 1; i < n_fs; i++)
{
- enq_now = clib_min (c->length, enq_max - read);
- rv = SSL_read (ssl, c->data, enq_now);
+ rv = SSL_read (ssl, fs[i].data, fs[i].len);
read += rv > 0 ? rv : 0;
- if (rv < enq_now)
+ if (rv < fs[i].len)
break;
}
@@ -148,29 +143,27 @@ openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl)
}
static int
-openssl_write_from_fifo_into_ssl (svm_fifo_t * f, SSL * ssl, u32 len)
+openssl_write_from_fifo_into_ssl (svm_fifo_t *f, SSL *ssl, u32 max_len)
{
- svm_fifo_chunk_t *c;
- int wrote = 0, rv;
- u32 deq_now;
+ int wrote = 0, rv, i = 0, len;
+ const int n_segs = 2;
+ svm_fifo_seg_t fs[n_segs];
- deq_now = clib_min (svm_fifo_max_read_chunk (f), len);
- wrote = SSL_write (ssl, svm_fifo_head (f), deq_now);
- if (wrote <= 0)
+ len = svm_fifo_segments (f, 0, fs, n_segs, max_len);
+ if (len <= 0)
return 0;
- c = svm_fifo_head_chunk (f);
- while ((c = c->next) && wrote < len)
+ while (wrote < len && i < n_segs)
{
- deq_now = clib_min (c->length, len - wrote);
- rv = SSL_write (ssl, c->data, deq_now);
- wrote += rv > 0 ? rv : 0;
-
- if (rv < deq_now)
+ rv = SSL_write (ssl, fs[i].data, fs[i].len);
+ wrote += (rv > 0) ? rv : 0;
+ if (rv < fs[i].len)
break;
+ i++;
}
- svm_fifo_dequeue_drop (f, wrote);
+ if (wrote)
+ svm_fifo_dequeue_drop (f, wrote);
return wrote;
}
diff --git a/src/svm/svm_fifo.c b/src/svm/svm_fifo.c
index f1ac8d49b92..ff941a7a6dd 100644
--- a/src/svm/svm_fifo.c
+++ b/src/svm/svm_fifo.c
@@ -1222,6 +1222,42 @@ svm_fifo_fill_chunk_list (svm_fifo_t * f)
}
int
+svm_fifo_provision_chunks (svm_fifo_t *f, svm_fifo_seg_t *fs, u32 n_segs,
+ u32 len)
+{
+ u32 head, tail, n_avail, head_pos, n_bytes, fs_index = 1, clen;
+ svm_fifo_chunk_t *c;
+
+ f_load_head_tail_prod (f, &head, &tail);
+
+ if (f_free_count (f, head, tail) < len)
+ return SVM_FIFO_EFULL;
+
+ n_avail = f_chunk_end (f->end_chunk) - tail;
+
+ if (n_avail < len && f_try_chunk_alloc (f, head, tail, len))
+ return SVM_FIFO_EGROW;
+
+ c = f->tail_chunk;
+ head_pos = (tail - c->start_byte);
+ fs[0].data = c->data + head_pos;
+ fs[0].len = clib_min (c->length - head_pos, len);
+ n_bytes = fs[0].len;
+
+ while (n_bytes < len && fs_index < n_segs)
+ {
+ c = c->next;
+ clen = clib_min (c->length, len - n_bytes);
+ fs[fs_index].data = c->data;
+ fs[fs_index].len = clen;
+ n_bytes += clen;
+ fs_index += 1;
+ }
+
+ return fs_index;
+}
+
+int
svm_fifo_segments (svm_fifo_t * f, u32 offset, svm_fifo_seg_t * fs,
u32 n_segs, u32 max_bytes)
{
diff --git a/src/svm/svm_fifo.h b/src/svm/svm_fifo.h
index 4239e9d78ea..2a054526865 100644
--- a/src/svm/svm_fifo.h
+++ b/src/svm/svm_fifo.h
@@ -208,6 +208,21 @@ svm_fifo_chunk_t *svm_fifo_chunk_alloc (u32 size);
*/
int svm_fifo_fill_chunk_list (svm_fifo_t * f);
/**
+ * Provision and return chunks for number of bytes requested
+ *
+ * Allocates enough chunks to cover the bytes requested and returns them
+ * in the fifo segment array. The number of bytes provisioned may be less
+ * than requested if not enough segments were provided.
+ *
+ * @param f fifo
+ * @param fs array of fifo segments
+ * @param n_segs length of fifo segments array
+ * @param len number of bytes to preallocate
+ * @return number of fifo segments provisioned or error
+ */
+int svm_fifo_provision_chunks (svm_fifo_t *f, svm_fifo_seg_t *fs, u32 n_segs,
+ u32 len);
+/**
* Initialize rbtrees used for ooo lookups
*
* @param f fifo