From 9f86d225ab4f3dccbf61383a75d6af7d321a204e Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Mon, 23 Mar 2020 15:34:22 +0000 Subject: [PATCH] session tls: support tls descheduling Type: improvement Signed-off-by: Florin Coras Change-Id: Ieb8bb9c6deb92479fdd3e045778fe5ae4782d1ea --- src/plugins/quic/quic.c | 2 +- src/plugins/tlsmbedtls/tls_mbedtls.c | 5 ++-- src/plugins/tlsopenssl/tls_openssl.c | 58 ++++++++++++++++++++++-------------- src/plugins/tlspicotls/tls_picotls.c | 5 ++-- src/vnet/session/application_local.c | 2 +- src/vnet/session/session_node.c | 21 ++++++------- src/vnet/session/transport.h | 25 ++++++++++++---- src/vnet/tcp/tcp.h | 2 +- src/vnet/tcp/tcp_output.c | 11 ++++--- src/vnet/tls/tls.c | 27 ++++++++++++----- src/vnet/tls/tls.h | 3 +- 11 files changed, 101 insertions(+), 60 deletions(-) diff --git a/src/plugins/quic/quic.c b/src/plugins/quic/quic.c index 4d809446130..de0e4e46892 100644 --- a/src/plugins/quic/quic.c +++ b/src/plugins/quic/quic.c @@ -1928,7 +1928,7 @@ quic_custom_app_rx_callback (transport_connection_t * tc) } static int -quic_custom_tx_callback (void *s, u32 max_burst_size) +quic_custom_tx_callback (void *s, transport_send_params_t * sp) { session_t *stream_session = (session_t *) s; quic_stream_data_t *stream_data; diff --git a/src/plugins/tlsmbedtls/tls_mbedtls.c b/src/plugins/tlsmbedtls/tls_mbedtls.c index 8ac736ae6f3..3fccba2ec5a 100644 --- a/src/plugins/tlsmbedtls/tls_mbedtls.c +++ b/src/plugins/tlsmbedtls/tls_mbedtls.c @@ -431,7 +431,8 @@ mbedtls_ctx_handshake_rx (tls_ctx_t * ctx) } static int -mbedtls_ctx_write (tls_ctx_t * ctx, session_t * app_session, u32 max_write) +mbedtls_ctx_write (tls_ctx_t * ctx, session_t * app_session, + transport_send_params_t * sp) { mbedtls_ctx_t *mc = (mbedtls_ctx_t *) ctx; u8 thread_index = ctx->c_thread_index; @@ -446,7 +447,7 @@ mbedtls_ctx_write (tls_ctx_t * ctx, session_t * app_session, u32 max_write) if (!deq_max) return 0; - deq_max = clib_min (deq_max, max_write); + deq_max = clib_min (deq_max, sp->max_burst_size); tls_session = session_get_from_handle (ctx->tls_session_handle); enq_max = svm_fifo_max_enqueue_prod (tls_session->tx_fifo); deq_now = clib_min (deq_max, TLS_CHUNK_SIZE); diff --git a/src/plugins/tlsopenssl/tls_openssl.c b/src/plugins/tlsopenssl/tls_openssl.c index 935e0147e30..669a503487f 100644 --- a/src/plugins/tlsopenssl/tls_openssl.c +++ b/src/plugins/tlsopenssl/tls_openssl.c @@ -110,15 +110,11 @@ openssl_lctx_get (u32 lctx_index) } static int -openssl_read_from_bio_into_fifo (svm_fifo_t * f, BIO * bio) +openssl_read_from_bio_into_fifo (svm_fifo_t * f, BIO * bio, u32 enq_max) { - u32 enq_now, enq_max; svm_fifo_chunk_t *c; int read, rv; - - enq_max = svm_fifo_max_enqueue_prod (f); - if (!enq_max) - return 0; + u32 enq_now; svm_fifo_fill_chunk_list (f); @@ -256,12 +252,17 @@ openssl_try_handshake_read (openssl_ctx_t * oc, session_t * tls_session) static int openssl_try_handshake_write (openssl_ctx_t * oc, session_t * tls_session) { - u32 read; + u32 read, enq_max; if (BIO_ctrl_pending (oc->rbio) <= 0) return 0; - read = openssl_read_from_bio_into_fifo (tls_session->tx_fifo, oc->rbio); + enq_max = svm_fifo_max_enqueue_prod (tls_session->tx_fifo); + if (!enq_max) + return 0; + + read = openssl_read_from_bio_into_fifo (tls_session->tx_fifo, oc->rbio, + enq_max); if (read) tls_add_vpp_q_tx_evt (tls_session); @@ -413,11 +414,12 @@ openssl_confirm_app_close (tls_ctx_t * ctx) } static inline int -openssl_ctx_write (tls_ctx_t * ctx, session_t * app_session, u32 max_write) +openssl_ctx_write (tls_ctx_t * ctx, session_t * app_session, + transport_send_params_t * sp) { openssl_ctx_t *oc = (openssl_ctx_t *) ctx; - int wrote = 0, read, max_buf = 4 * TLS_CHUNK_SIZE, max_space; - u32 deq_max, to_write; + int wrote = 0, read, max_buf = 4 * TLS_CHUNK_SIZE, max_space, n_pending; + u32 deq_max, to_write, enq_max; session_t *tls_session; svm_fifo_t *f; @@ -427,7 +429,7 @@ openssl_ctx_write (tls_ctx_t * ctx, session_t * app_session, u32 max_write) if (!deq_max) goto check_tls_fifo; - deq_max = clib_min (deq_max, max_write); + deq_max = clib_min (deq_max, sp->max_burst_size); /* Figure out how much data to write */ max_space = max_buf - BIO_ctrl_pending (oc->rbio); @@ -443,26 +445,38 @@ openssl_ctx_write (tls_ctx_t * ctx, session_t * app_session, u32 max_write) check_tls_fifo: - if (BIO_ctrl_pending (oc->rbio) <= 0) + if ((n_pending = BIO_ctrl_pending (oc->rbio)) <= 0) return wrote; tls_session = session_get_from_handle (ctx->tls_session_handle); - read = openssl_read_from_bio_into_fifo (tls_session->tx_fifo, oc->rbio); + enq_max = svm_fifo_max_enqueue_prod (tls_session->tx_fifo); + if (!enq_max) + goto maybe_reschedule; + + read = openssl_read_from_bio_into_fifo (tls_session->tx_fifo, oc->rbio, + enq_max); if (!read) - { - /* Request tx reschedule of the app session */ - app_session->flags |= SESSION_F_CUSTOM_TX; - return wrote; - } + goto maybe_reschedule; tls_add_vpp_q_tx_evt (tls_session); - if (BIO_ctrl_pending (oc->rbio) > 0) - app_session->flags |= SESSION_F_CUSTOM_TX; - else if (ctx->app_closed) + if (PREDICT_FALSE (ctx->app_closed && !BIO_ctrl_pending (oc->rbio))) openssl_confirm_app_close (ctx); +maybe_reschedule: + + if (!svm_fifo_max_enqueue_prod (tls_session->tx_fifo)) + { + svm_fifo_add_want_deq_ntf (tls_session->tx_fifo, + SVM_FIFO_WANT_DEQ_NOTIF); + transport_connection_deschedule (&ctx->connection); + sp->flags |= TRANSPORT_SND_F_DESCHED; + } + else + /* Request tx reschedule of the app session */ + app_session->flags |= SESSION_F_CUSTOM_TX; + return wrote; } diff --git a/src/plugins/tlspicotls/tls_picotls.c b/src/plugins/tlspicotls/tls_picotls.c index a9eea333779..a8944bc299a 100644 --- a/src/plugins/tlspicotls/tls_picotls.c +++ b/src/plugins/tlspicotls/tls_picotls.c @@ -410,7 +410,8 @@ picotls_content_process (picotls_ctx_t * ptls_ctx, svm_fifo_t * src_fifo, } static inline int -picotls_ctx_write (tls_ctx_t * ctx, session_t * app_session, u32 max_write) +picotls_ctx_write (tls_ctx_t * ctx, session_t * app_session, + transport_send_params_t * sp) { picotls_ctx_t *ptls_ctx = (picotls_ctx_t *) ctx; u32 deq_max, deq_now; @@ -458,7 +459,7 @@ picotls_ctx_write (tls_ctx_t * ctx, session_t * app_session, u32 max_write) if (!deq_max) return deq_max; - deq_max = clib_min (deq_max, max_write); + deq_max = clib_min (deq_max, sp->max_burst_size); deq_now = clib_min (deq_max, svm_fifo_max_read_chunk (app_tx_fifo)); enq_max = svm_fifo_max_enqueue_prod (tls_tx_fifo); diff --git a/src/vnet/session/application_local.c b/src/vnet/session/application_local.c index d54d1119ce6..0e1f6db19fb 100644 --- a/src/vnet/session/application_local.c +++ b/src/vnet/session/application_local.c @@ -470,7 +470,7 @@ format_ct_connection_id (u8 * s, va_list * args) } static int -ct_custom_tx (void *session, u32 max_burst_size) +ct_custom_tx (void *session, transport_send_params_t * sp) { session_t *s = (session_t *) session; if (session_has_transport (s)) diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c index 30eca1e6577..f023a95c98c 100644 --- a/src/vnet/session/session_node.c +++ b/src/vnet/session/session_node.c @@ -872,7 +872,8 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk, { u32 n_custom_tx; ctx->s->flags &= ~SESSION_F_CUSTOM_TX; - n_custom_tx = ctx->transport_vft->custom_tx (ctx->tc, max_burst); + ctx->sp.max_burst_size = max_burst; + n_custom_tx = ctx->transport_vft->custom_tx (ctx->tc, &ctx->sp); *n_tx_packets += n_custom_tx; if (PREDICT_FALSE (ctx->s->session_state >= SESSION_STATE_TRANSPORT_CLOSED)) @@ -1068,8 +1069,9 @@ session_tx_fifo_dequeue_internal (session_worker_t * wrk, vlib_node_runtime_t * node, session_evt_elt_t * elt, int *n_tx_packets) { + transport_send_params_t *sp = &wrk->ctx.sp; session_t *s = wrk->ctx.s; - u32 n_packets, max_pkts; + u32 n_packets; if (PREDICT_FALSE (s->session_state >= SESSION_STATE_TRANSPORT_CLOSED)) return 0; @@ -1077,18 +1079,17 @@ session_tx_fifo_dequeue_internal (session_worker_t * wrk, /* Clear custom-tx flag used to request reschedule for tx */ s->flags &= ~SESSION_F_CUSTOM_TX; - max_pkts = clib_min (VLIB_FRAME_SIZE - *n_tx_packets, - TRANSPORT_PACER_MAX_BURST_PKTS); - n_packets = transport_custom_tx (session_get_transport_proto (s), s, - max_pkts); - *n_tx_packets -= n_packets; + sp->max_burst_size = clib_min (VLIB_FRAME_SIZE - *n_tx_packets, + TRANSPORT_PACER_MAX_BURST_PKTS); - if (svm_fifo_max_dequeue_cons (s->tx_fifo) - || (s->flags & SESSION_F_CUSTOM_TX)) + n_packets = transport_custom_tx (session_get_transport_proto (s), s, sp); + *n_tx_packets += n_packets; + + if (s->flags & SESSION_F_CUSTOM_TX) { session_evt_add_old (wrk, elt); } - else + else if (!(sp->flags & TRANSPORT_SND_F_DESCHED)) { svm_fifo_unset_event (s->tx_fifo); if (svm_fifo_max_dequeue_cons (s->tx_fifo)) diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h index 6dc6984cdf4..eb98032b1e4 100644 --- a/src/vnet/session/transport.h +++ b/src/vnet/session/transport.h @@ -44,9 +44,21 @@ typedef enum transport_snd_flags_ typedef struct transport_send_params_ { - u32 snd_space; - u32 tx_offset; - u16 snd_mss; + union + { + /* Used to retrieve snd params from transports */ + struct + { + u32 snd_space; + u32 tx_offset; + u16 snd_mss; + }; + /* Used by custom tx functions */ + struct + { + u32 max_burst_size; + }; + }; transport_snd_flags_t flags; } transport_send_params_t; @@ -76,7 +88,7 @@ typedef struct _transport_proto_vft transport_send_params_t *sp); void (*update_time) (f64 time_now, u8 thread_index); void (*flush_data) (transport_connection_t *tconn); - int (*custom_tx) (void *session, u32 max_burst_size); + int (*custom_tx) (void *session, transport_send_params_t *sp); int (*app_rx_evt) (transport_connection_t *tconn); /* @@ -152,9 +164,10 @@ transport_get_half_open (transport_proto_t tp, u32 conn_index) } static inline int -transport_custom_tx (transport_proto_t tp, void *s, u32 max_burst_size) +transport_custom_tx (transport_proto_t tp, void *s, + transport_send_params_t * sp) { - return tp_vfts[tp].custom_tx (s, max_burst_size); + return tp_vfts[tp].custom_tx (s, sp); } static inline int diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h index f8c8cb342fe..f4cc2c88e62 100644 --- a/src/vnet/tcp/tcp.h +++ b/src/vnet/tcp/tcp.h @@ -325,7 +325,7 @@ void tcp_reschedule (tcp_connection_t * tc); fib_node_index_t tcp_lookup_rmt_in_fib (tcp_connection_t * tc); u32 tcp_session_push_header (transport_connection_t * tconn, vlib_buffer_t * b); -int tcp_session_custom_tx (void *conn, u32 max_burst_size); +int tcp_session_custom_tx (void *conn, transport_send_params_t * sp); void tcp_connection_timers_init (tcp_connection_t * tc); void tcp_connection_timers_reset (tcp_connection_t * tc); diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index 095f3602557..b1af535eea7 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -2010,7 +2010,7 @@ tcp_do_retransmit (tcp_connection_t * tc, u32 max_burst_size) } int -tcp_session_custom_tx (void *conn, u32 max_burst_size) +tcp_session_custom_tx (void *conn, transport_send_params_t * sp) { tcp_connection_t *tc = (tcp_connection_t *) conn; u32 n_segs = 0; @@ -2018,8 +2018,7 @@ tcp_session_custom_tx (void *conn, u32 max_burst_size) if (tcp_in_cong_recovery (tc) && (tc->flags & TCP_CONN_RXT_PENDING)) { tc->flags &= ~TCP_CONN_RXT_PENDING; - n_segs = tcp_do_retransmit (tc, max_burst_size); - max_burst_size -= n_segs; + n_segs = tcp_do_retransmit (tc, sp->max_burst_size); } if (!(tc->flags & TCP_CONN_SNDACK)) @@ -2031,13 +2030,13 @@ tcp_session_custom_tx (void *conn, u32 max_burst_size) if (n_segs && !tc->pending_dupacks) return n_segs; - if (!max_burst_size) + if (sp->max_burst_size <= n_segs) { tcp_program_ack (tc); - return max_burst_size; + return n_segs; } - n_segs += tcp_send_acks (tc, max_burst_size); + n_segs += tcp_send_acks (tc, sp->max_burst_size - n_segs); return n_segs; } diff --git a/src/vnet/tls/tls.c b/src/vnet/tls/tls.c index d0552dc6f3b..89dbd36bc44 100644 --- a/src/vnet/tls/tls.c +++ b/src/vnet/tls/tls.c @@ -307,13 +307,13 @@ tls_ctx_init_client (tls_ctx_t * ctx) } static inline int -tls_ctx_write (tls_ctx_t * ctx, session_t * app_session, u32 max_burst_size) +tls_ctx_write (tls_ctx_t * ctx, session_t * app_session, + transport_send_params_t * sp) { - u32 max_write, n_wrote; + u32 n_wrote; - max_write = max_burst_size * TRANSPORT_PACER_MIN_MSS; - n_wrote = tls_vfts[ctx->tls_ctx_engine].ctx_write (ctx, app_session, - max_write); + sp->max_burst_size = sp->max_burst_size * TRANSPORT_PACER_MIN_MSS; + n_wrote = tls_vfts[ctx->tls_ctx_engine].ctx_write (ctx, app_session, sp); return n_wrote > 0 ? clib_max (n_wrote / TRANSPORT_PACER_MIN_MSS, 1) : 0; } @@ -447,6 +447,17 @@ tls_app_rx_callback (session_t * tls_session) return 0; } +int +tls_app_tx_callback (session_t * tls_session) +{ + tls_ctx_t *ctx; + + ctx = tls_ctx_get (tls_session->opaque); + transport_connection_reschedule (&ctx->connection); + + return 0; +} + int tls_session_connected_callback (u32 tls_app_index, u32 ho_ctx_index, session_t * tls_session, session_error_t err) @@ -524,6 +535,7 @@ static session_cb_vft_t tls_app_cb_vft = { .add_segment_callback = tls_add_segment_callback, .del_segment_callback = tls_del_segment_callback, .builtin_app_rx_callback = tls_app_rx_callback, + .builtin_app_tx_callback = tls_app_tx_callback, .session_cleanup_callback = tls_app_session_cleanup, }; /* *INDENT-ON* */ @@ -712,7 +724,7 @@ tls_listener_get (u32 listener_index) } int -tls_custom_tx_callback (void *session, u32 max_burst_size) +tls_custom_tx_callback (void *session, transport_send_params_t * sp) { session_t *app_session = (session_t *) session; tls_ctx_t *ctx; @@ -722,8 +734,7 @@ tls_custom_tx_callback (void *session, u32 max_burst_size) return 0; ctx = tls_ctx_get (app_session->connection_index); - tls_ctx_write (ctx, app_session, max_burst_size); - return 0; + return tls_ctx_write (ctx, app_session, sp); } u8 * diff --git a/src/vnet/tls/tls.h b/src/vnet/tls/tls.h index 2d09b291aa7..d950fe82629 100644 --- a/src/vnet/tls/tls.h +++ b/src/vnet/tls/tls.h @@ -110,7 +110,8 @@ typedef struct tls_engine_vft_ int (*ctx_init_client) (tls_ctx_t * ctx); int (*ctx_init_server) (tls_ctx_t * ctx); int (*ctx_read) (tls_ctx_t * ctx, session_t * tls_session); - int (*ctx_write) (tls_ctx_t * ctx, session_t * app_session, u32 max_write); + int (*ctx_write) (tls_ctx_t * ctx, session_t * app_session, + transport_send_params_t * sp); u8 (*ctx_handshake_is_over) (tls_ctx_t * ctx); int (*ctx_start_listen) (tls_ctx_t * ctx); int (*ctx_stop_listen) (tls_ctx_t * ctx); -- 2.16.6