diff options
author | Florin Coras <fcoras@cisco.com> | 2019-12-19 16:10:58 -0800 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2020-02-25 19:18:49 +0000 |
commit | f22f4e562e1b922cff036ef628b77fd2d479d015 (patch) | |
tree | 4cbc3091a5ce89a73c94685dcee198dd583ca375 /src/plugins/tlsopenssl | |
parent | b020806806c0e6c54886cdb4347a5fd1f19504b0 (diff) |
svm: refactor fifo
Type: refactor
Switch from a wrapped byte space to a "continuous" one wherein fifo
chunks are appended to the fifo as more data is enqueued and chunks are
removed as data is dequeued.
The fifo is still subject to a maximum size, i.e., maximum number of
bytes that can be enqueued, so the max number of chunks associated to
the fifo is also constrained.
When enqueueing data, which must fit within the available free space, if
not enough "supporting" chunk memory is available, the fifo asks the
fifo segment for enough chunk memory to ensure that the write can
succeed. To avoid allocating large amounts of small chunks due to small
writes, if possible, the size of the chunks requested is lower capped by
min_alloc.
When dequeuing data, all the chunks that have been completely drained,
i.e., head moved beyond the chunks’ end bytes, are unlinked from the
fifo and returned to the fifo segment. The one exception to this is the
last chunk which is never unlinked.
Change-Id: I98c1dbd9135fb79650365c7e40c29238b96cd4ee
Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/plugins/tlsopenssl')
-rw-r--r-- | src/plugins/tlsopenssl/tls_openssl.c | 276 |
1 files changed, 169 insertions, 107 deletions
diff --git a/src/plugins/tlsopenssl/tls_openssl.c b/src/plugins/tlsopenssl/tls_openssl.c index 288f0e1ae1e..078dd2f5b77 100644 --- a/src/plugins/tlsopenssl/tls_openssl.c +++ b/src/plugins/tlsopenssl/tls_openssl.c @@ -110,70 +110,183 @@ openssl_lctx_get (u32 lctx_index) } static int -openssl_try_handshake_read (openssl_ctx_t * oc, session_t * tls_session) +openssl_read_from_bio_into_fifo (svm_fifo_t * f, BIO * bio) { - u32 deq_max, deq_now; - svm_fifo_t *f; - int wrote, rv; + u32 enq_now, enq_max; + svm_fifo_chunk_t *c; + int read, rv; - f = tls_session->rx_fifo; - deq_max = svm_fifo_max_dequeue_cons (f); - if (!deq_max) + enq_max = svm_fifo_max_enqueue_prod (f); + if (!enq_max) return 0; - deq_now = clib_min (svm_fifo_max_read_chunk (f), deq_max); - wrote = BIO_write (oc->wbio, svm_fifo_head (f), deq_now); - if (wrote <= 0) + svm_fifo_fill_chunk_list (f); + + enq_now = clib_min (svm_fifo_max_write_chunk (f), enq_max); + if (!enq_now) return 0; - svm_fifo_dequeue_drop (f, wrote); - if (wrote < deq_max) + read = BIO_read (bio, svm_fifo_tail (f), enq_now); + if (read <= 0) + return 0; + + if (read == enq_now) { - deq_now = clib_min (svm_fifo_max_read_chunk (f), deq_max - wrote); - rv = BIO_write (oc->wbio, svm_fifo_head (f), deq_now); - if (rv > 0) + c = svm_fifo_tail_chunk (f); + while (read < enq_max) { - svm_fifo_dequeue_drop (f, rv); - wrote += rv; + c = c->next; + enq_now = clib_min (c->length, enq_max - read); + rv = BIO_read (bio, c->data, enq_now); + read += rv > 0 ? rv : 0; + + if (rv < enq_now) + break; } } - return wrote; + + svm_fifo_enqueue_nocopy (f, read); + + return read; } static int -openssl_try_handshake_write (openssl_ctx_t * oc, session_t * tls_session) +openssl_read_from_ssl_into_fifo (svm_fifo_t * f, SSL * ssl) { - u32 enq_max, deq_now; - svm_fifo_t *f; + u32 enq_now, enq_max; + svm_fifo_chunk_t *c; int read, rv; - if (BIO_ctrl_pending (oc->rbio) <= 0) - return 0; - - f = tls_session->tx_fifo; enq_max = svm_fifo_max_enqueue_prod (f); if (!enq_max) return 0; - deq_now = clib_min (svm_fifo_max_write_chunk (f), enq_max); - read = BIO_read (oc->rbio, svm_fifo_tail (f), deq_now); + 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); if (read <= 0) return 0; + if (read == enq_now) + { + c = svm_fifo_tail_chunk (f); + while (read < enq_max) + { + c = c->next; + if (!c) + break; + enq_now = clib_min (c->length, enq_max - read); + rv = SSL_read (ssl, c->data, enq_now); + read += rv > 0 ? rv : 0; + + if (rv < enq_now) + break; + } + } + svm_fifo_enqueue_nocopy (f, read); - tls_add_vpp_q_tx_evt (tls_session); - if (read < enq_max) + return read; +} + +static int +openssl_write_from_fifo_into_bio (svm_fifo_t * f, BIO * bio, u32 len) +{ + svm_fifo_chunk_t *c; + int wrote, rv; + u32 deq_now; + + svm_fifo_fill_chunk_list (f); + + deq_now = clib_min (svm_fifo_max_read_chunk (f), len); + wrote = BIO_write (bio, svm_fifo_head (f), deq_now); + if (wrote <= 0) + return 0; + + if (wrote == deq_now) { - deq_now = clib_min (svm_fifo_max_write_chunk (f), enq_max - read); - rv = BIO_read (oc->rbio, svm_fifo_tail (f), deq_now); - if (rv > 0) + c = svm_fifo_head_chunk (f); + while (wrote < len) { - svm_fifo_enqueue_nocopy (f, rv); - read += rv; + c = c->next; + deq_now = clib_min (c->length, len - wrote); + rv = BIO_write (bio, c->data, deq_now); + wrote += rv > 0 ? rv : 0; + + if (rv < deq_now) + break; } } + svm_fifo_dequeue_drop (f, wrote); + + return wrote; +} + +static int +openssl_write_from_fifo_into_ssl (svm_fifo_t * f, SSL * ssl, u32 len) +{ + svm_fifo_chunk_t *c; + int wrote = 0, rv; + u32 deq_now; + + svm_fifo_fill_chunk_list (f); + + deq_now = clib_min (svm_fifo_max_read_chunk (f), len); + wrote = SSL_write (ssl, svm_fifo_head (f), deq_now); + if (wrote <= 0) + return 0; + + if (wrote == deq_now) + { + c = svm_fifo_head_chunk (f); + while (wrote < len) + { + c = c->next; + 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) + break; + } + } + + svm_fifo_dequeue_drop (f, wrote); + + return wrote; +} + +static int +openssl_try_handshake_read (openssl_ctx_t * oc, session_t * tls_session) +{ + svm_fifo_t *f; + u32 deq_max; + + f = tls_session->rx_fifo; + deq_max = svm_fifo_max_dequeue_cons (f); + if (!deq_max) + return 0; + + return openssl_write_from_fifo_into_bio (f, oc->wbio, deq_max); +} + +static int +openssl_try_handshake_write (openssl_ctx_t * oc, session_t * tls_session) +{ + u32 read; + + if (BIO_ctrl_pending (oc->rbio) <= 0) + return 0; + + read = openssl_read_from_bio_into_fifo (tls_session->tx_fifo, oc->rbio); + if (read) + tls_add_vpp_q_tx_evt (tls_session); + return read; } @@ -325,42 +438,33 @@ static inline int openssl_ctx_write (tls_ctx_t * ctx, session_t * app_session) { openssl_ctx_t *oc = (openssl_ctx_t *) ctx; - int wrote = 0, rv, read, max_buf = 100 * TLS_CHUNK_SIZE, max_space; - u32 enq_max, deq_max, deq_now, to_write; + int wrote = 0, read, max_buf = 100 * TLS_CHUNK_SIZE, max_space; + u32 deq_max, to_write; session_t *tls_session; svm_fifo_t *f; f = app_session->tx_fifo; + deq_max = svm_fifo_max_dequeue_cons (f); if (!deq_max) goto check_tls_fifo; + /* Figure out how much data to write */ max_space = max_buf - BIO_ctrl_pending (oc->rbio); max_space = (max_space < 0) ? 0 : max_space; - deq_now = clib_min (deq_max, (u32) max_space); - to_write = clib_min (svm_fifo_max_read_chunk (f), deq_now); - wrote = SSL_write (oc->ssl, svm_fifo_head (f), to_write); - if (wrote <= 0) + to_write = clib_min (deq_max, (u32) max_space); + + wrote = openssl_write_from_fifo_into_ssl (f, oc->ssl, to_write); + if (!wrote) { tls_add_vpp_q_builtin_tx_evt (app_session); goto check_tls_fifo; } - svm_fifo_dequeue_drop (app_session->tx_fifo, wrote); - if (wrote < deq_now) - { - to_write = clib_min (svm_fifo_max_read_chunk (f), deq_now - wrote); - rv = SSL_write (oc->ssl, svm_fifo_head (f), to_write); - if (rv > 0) - { - svm_fifo_dequeue_drop (app_session->tx_fifo, rv); - wrote += rv; - } - } - if (svm_fifo_needs_deq_ntf (app_session->tx_fifo, wrote)) + if (svm_fifo_needs_deq_ntf (f, wrote)) session_dequeue_notify (app_session); - if (wrote < deq_max) + if (svm_fifo_max_dequeue_cons (f)) tls_add_vpp_q_builtin_tx_evt (app_session); check_tls_fifo: @@ -369,33 +473,16 @@ check_tls_fifo: return wrote; tls_session = session_get_from_handle (ctx->tls_session_handle); - f = tls_session->tx_fifo; - enq_max = svm_fifo_max_enqueue_prod (f); - if (!enq_max) - { - tls_add_vpp_q_builtin_tx_evt (app_session); - return wrote; - } - deq_now = clib_min (svm_fifo_max_write_chunk (f), enq_max); - read = BIO_read (oc->rbio, svm_fifo_tail (f), deq_now); - if (read <= 0) + read = openssl_read_from_bio_into_fifo (tls_session->tx_fifo, oc->rbio); + if (!read) { tls_add_vpp_q_builtin_tx_evt (app_session); return wrote; } - svm_fifo_enqueue_nocopy (f, read); tls_add_vpp_q_tx_evt (tls_session); - if (read < enq_max && BIO_ctrl_pending (oc->rbio) > 0) - { - deq_now = clib_min (svm_fifo_max_write_chunk (f), enq_max - read); - read = BIO_read (oc->rbio, svm_fifo_tail (f), deq_now); - if (read > 0) - svm_fifo_enqueue_nocopy (f, read); - } - if (BIO_ctrl_pending (oc->rbio) > 0) tls_add_vpp_q_builtin_tx_evt (app_session); else if (ctx->app_closed) @@ -407,9 +494,9 @@ check_tls_fifo: static inline int openssl_ctx_read (tls_ctx_t * ctx, session_t * tls_session) { - int read, wrote = 0, max_space, max_buf = 100 * TLS_CHUNK_SIZE, rv; + int read, wrote = 0, max_space, max_buf = 100 * TLS_CHUNK_SIZE; openssl_ctx_t *oc = (openssl_ctx_t *) ctx; - u32 deq_max, enq_max, deq_now, to_read; + u32 deq_max, to_write; session_t *app_session; svm_fifo_t *f; @@ -422,31 +509,21 @@ openssl_ctx_read (tls_ctx_t * ctx, session_t * tls_session) } f = tls_session->rx_fifo; + deq_max = svm_fifo_max_dequeue_cons (f); max_space = max_buf - BIO_ctrl_pending (oc->wbio); max_space = max_space < 0 ? 0 : max_space; - deq_now = clib_min (deq_max, max_space); - if (!deq_now) + to_write = clib_min (deq_max, max_space); + if (!to_write) goto check_app_fifo; - to_read = clib_min (svm_fifo_max_read_chunk (f), deq_now); - wrote = BIO_write (oc->wbio, svm_fifo_head (f), to_read); - if (wrote <= 0) + wrote = openssl_write_from_fifo_into_bio (f, oc->wbio, to_write); + if (!wrote) { tls_add_vpp_q_builtin_rx_evt (tls_session); goto check_app_fifo; } - svm_fifo_dequeue_drop (f, wrote); - if (wrote < deq_now) - { - to_read = clib_min (svm_fifo_max_read_chunk (f), deq_now - wrote); - rv = BIO_write (oc->wbio, svm_fifo_head (f), to_read); - if (rv > 0) - { - svm_fifo_dequeue_drop (f, rv); - wrote += rv; - } - } + if (svm_fifo_max_dequeue_cons (f)) tls_add_vpp_q_builtin_rx_evt (tls_session); @@ -457,28 +534,13 @@ check_app_fifo: app_session = session_get_from_handle (ctx->app_session_handle); f = app_session->rx_fifo; - enq_max = svm_fifo_max_enqueue_prod (f); - if (!enq_max) - { - tls_add_vpp_q_builtin_rx_evt (tls_session); - return wrote; - } - deq_now = clib_min (svm_fifo_max_write_chunk (f), enq_max); - read = SSL_read (oc->ssl, svm_fifo_tail (f), deq_now); - if (read <= 0) + read = openssl_read_from_ssl_into_fifo (f, oc->ssl); + if (!read) { tls_add_vpp_q_builtin_rx_evt (tls_session); return wrote; } - svm_fifo_enqueue_nocopy (f, read); - if (read < enq_max && SSL_pending (oc->ssl) > 0) - { - deq_now = clib_min (svm_fifo_max_write_chunk (f), enq_max - read); - read = SSL_read (oc->ssl, svm_fifo_tail (f), deq_now); - if (read > 0) - svm_fifo_enqueue_nocopy (f, read); - } /* If handshake just completed, session may still be in accepting state */ if (app_session->session_state >= SESSION_STATE_READY) |