diff options
-rw-r--r-- | src/plugins/tlsopenssl/tls_openssl.c | 59 | ||||
-rw-r--r-- | src/svm/svm_fifo.c | 36 | ||||
-rw-r--r-- | src/svm/svm_fifo.h | 15 |
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 |