From b3c5e3ab8096cc6f9ded22d86d2b093c0baa6ad9 Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Tue, 15 Apr 2025 11:02:45 -0400 Subject: [PATCH] http: fix http session deschedule Type: fix Change-Id: Ieda622ff48422e8f4707c8b624f14d93324e615d Signed-off-by: Matus Fabian --- src/plugins/http/http1.c | 37 ++++++++++++++++++++++++++----------- src/plugins/http/http2/http2.c | 19 ++++++++++++------- src/plugins/http/http_private.h | 39 +++++++++++++++++++++++++-------------- 3 files changed, 63 insertions(+), 32 deletions(-) diff --git a/src/plugins/http/http1.c b/src/plugins/http/http1.c index d99e4bd86cb..fbd0d32784c 100644 --- a/src/plugins/http/http1.c +++ b/src/plugins/http/http1.c @@ -125,6 +125,19 @@ http1_conn_free_req (http_conn_t *hc) hc->flags &= ~HTTP_CONN_F_HAS_REQUEST; } +/* Deschedule http session and wait for deq notification if underlying ts tx + * fifo almost full */ +static_always_inline void +http1_check_and_deschedule (http_conn_t *hc, http_req_t *req, + transport_send_params_t *sp) +{ + if (http_io_ts_check_write_thresh (hc)) + { + http_req_deschedule (req, sp); + http_io_ts_add_want_deq_ntf (hc); + } +} + static void http1_send_error (http_conn_t *hc, http_status_code_t ec, transport_send_params_t *sp) @@ -139,7 +152,7 @@ http1_send_error (http_conn_t *hc, http_status_code_t ec, HTTP_DBG (3, "%v", data); http_io_ts_write (hc, data, vec_len (data), sp); vec_free (data); - http_io_ts_after_write (hc, sp, 0, 1); + http_io_ts_after_write (hc, 0); } static int @@ -1039,7 +1052,7 @@ http1_req_state_transport_io_more_data (http_conn_t *hc, http_req_t *req, if (max_enq == 0) { HTTP_DBG (1, "app's rx fifo full"); - http_io_as_want_deq_ntf (req); + http_io_as_add_want_deq_ntf (req); return HTTP_SM_STOP; } @@ -1095,7 +1108,7 @@ http1_req_state_tunnel_rx (http_conn_t *hc, http_req_t *req, if (max_enq == 0) { HTTP_DBG (1, "app's rx fifo full"); - http_io_as_want_deq_ntf (req); + http_io_as_add_want_deq_ntf (req); return HTTP_SM_STOP; } max_read = clib_min (max_enq, max_deq); @@ -1187,7 +1200,7 @@ http1_req_state_udp_tunnel_rx (http_conn_t *hc, http_req_t *req, if (http_io_as_max_write (req) < dgram_size) { HTTP_DBG (1, "app's rx fifo full"); - http_io_as_want_deq_ntf (req); + http_io_as_add_want_deq_ntf (req); goto done; } @@ -1328,7 +1341,7 @@ http1_req_state_wait_app_reply (http_conn_t *hc, http_req_t *req, http_req_state_change (req, next_state); - http_io_ts_after_write (hc, sp, 0, 1); + http_io_ts_after_write (hc, 0); return sm_result; error: @@ -1445,7 +1458,7 @@ http1_req_state_wait_app_method (http_conn_t *hc, http_req_t *req, http_req_state_change (req, next_state); - http_io_ts_after_write (hc, sp, 0, 1); + http_io_ts_after_write (hc, 0); goto done; error: @@ -1497,9 +1510,10 @@ http1_req_state_app_io_more_data (http_conn_t *hc, http_req_t *req, HTTP_REQ_STATE_WAIT_TRANSPORT_REPLY); http_buffer_free (hb); } + http_io_ts_after_write (hc, finished); check_fifo: - http_io_ts_after_write (hc, sp, finished, !!n_written); + http1_check_and_deschedule (hc, req, sp); return HTTP_SM_STOP; } @@ -1529,10 +1543,10 @@ http1_req_state_tunnel_tx (http_conn_t *hc, http_req_t *req, http_io_as_read_segs (req, segs, &n_segs, max_read); n_written = http_io_ts_write_segs (hc, segs, n_segs, sp); http_io_as_drain (req, n_written); + http_io_ts_after_write (hc, 0); check_fifo: - http_io_ts_after_write (hc, sp, 0, !!n_written); - + http1_check_and_deschedule (hc, req, sp); return HTTP_SM_STOP; } @@ -1580,8 +1594,9 @@ http1_req_state_udp_tunnel_tx (http_conn_t *hc, http_req_t *req, } done: - http_io_ts_after_write (hc, sp, 0, written); - + if (written) + http_io_ts_after_write (hc, 0); + http1_check_and_deschedule (hc, req, sp); return HTTP_SM_STOP; } diff --git a/src/plugins/http/http2/http2.c b/src/plugins/http/http2/http2.c index bbfa25a8a1f..a447dc40038 100644 --- a/src/plugins/http/http2/http2.c +++ b/src/plugins/http/http2/http2.c @@ -224,7 +224,7 @@ http2_connection_error (http_conn_t *hc, http2_error_t error, response = http_get_tx_buf (hc); http2_frame_write_goaway (error, h2c->last_processed_stream_id, &response); http_io_ts_write (hc, response, vec_len (response), sp); - http_io_ts_after_write (hc, sp, 1, 1); + http_io_ts_after_write (hc, 1); hash_foreach (stream_id, req_index, h2c->req_by_stream_id, ({ req = http2_req_get (req_index, hc->c_thread_index); @@ -243,7 +243,7 @@ http2_send_stream_error (http_conn_t *hc, u32 stream_id, http2_error_t error, response = http_get_tx_buf (hc); http2_frame_write_rst_stream (error, stream_id, &response); http_io_ts_write (hc, response, vec_len (response), sp); - http_io_ts_after_write (hc, sp, 1, 1); + http_io_ts_after_write (hc, 1); } /* send RST_STREAM frame and notify app */ @@ -301,7 +301,7 @@ http2_send_server_preface (http_conn_t *hc) response = http_get_tx_buf (hc); http2_frame_write_settings (settings_list, &response); http_io_ts_write (hc, response, vec_len (response), 0); - http_io_ts_after_write (hc, 0, 0, 1); + http_io_ts_after_write (hc, 0); } /*************************************/ @@ -523,7 +523,7 @@ http2_req_state_wait_app_reply (http_conn_t *hc, http2_req_t *req, { response, vec_len (response) } }; n_written = http_io_ts_write_segs (hc, segs, 2, sp); ASSERT (n_written == (HTTP2_FRAME_HEADER_SIZE + vec_len (response))); - http_io_ts_after_write (hc, sp, 0, 1); + http_io_ts_after_write (hc, 0); return sm_result; } @@ -577,9 +577,14 @@ http2_req_state_app_io_more_data (http_conn_t *hc, http2_req_t *req, else req->stream_state = HTTP2_STREAM_STATE_HALF_CLOSED; } + http_io_ts_after_write (hc, finished); check_fifo: - http_io_ts_after_write (hc, sp, finished, !!n_written); + if (http_io_ts_check_write_thresh (hc)) + { + http_io_ts_add_want_deq_ntf (hc); + http_req_deschedule (&req->base, sp); + } return HTTP_SM_STOP; } @@ -842,7 +847,7 @@ http2_handle_settings_frame (http_conn_t *hc, http2_frame_header_t *fh) http2_frame_write_settings_ack (&resp); http_io_ts_write (hc, resp, vec_len (resp), 0); vec_free (resp); - http_io_ts_after_write (hc, 0, 0, 1); + http_io_ts_after_write (hc, 0); } return HTTP2_ERROR_NO_ERROR; @@ -946,7 +951,7 @@ http2_handle_ping_frame (http_conn_t *hc, http2_frame_header_t *fh) http2_frame_write_ping (1, rx_buf, &resp); http_io_ts_write (hc, resp, vec_len (resp), 0); vec_free (resp); - http_io_ts_after_write (hc, 0, 1, 1); + http_io_ts_after_write (hc, 1); return HTTP2_ERROR_NO_ERROR; } diff --git a/src/plugins/http/http_private.h b/src/plugins/http/http_private.h index c20694c6d90..cee60a49481 100644 --- a/src/plugins/http/http_private.h +++ b/src/plugins/http/http_private.h @@ -540,10 +540,17 @@ http_parse_content_length (http_req_t *req, u8 *rx_buf) return 0; } +always_inline void +http_req_deschedule (http_req_t *req, transport_send_params_t *sp) +{ + transport_connection_deschedule (&req->connection); + sp->flags |= TRANSPORT_SND_F_DESCHED; +} + /* Abstraction of app session fifo operations */ always_inline void -http_io_as_want_deq_ntf (http_req_t *req) +http_io_as_add_want_deq_ntf (http_req_t *req) { session_t *as = session_get_from_handle (req->hr_pa_session_handle); svm_fifo_add_want_deq_ntf (as->rx_fifo, SVM_FIFO_WANT_DEQ_NOTIF); @@ -656,6 +663,20 @@ http_io_ts_max_write (http_conn_t *hc, transport_send_params_t *sp) sp->max_burst_size); } +always_inline int +http_io_ts_check_write_thresh (http_conn_t *hc) +{ + session_t *ts = session_get_from_handle (hc->hc_tc_session_handle); + return (svm_fifo_max_enqueue_prod (ts->tx_fifo) < HTTP_FIFO_THRESH); +} + +always_inline void +http_io_ts_add_want_deq_ntf (http_conn_t *hc) +{ + session_t *ts = session_get_from_handle (hc->hc_tc_session_handle); + svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF); +} + always_inline u32 http_io_ts_read (http_conn_t *hc, u8 *buf, u32 len, u8 peek) { @@ -745,28 +766,18 @@ http_io_ts_write_segs (http_conn_t *hc, const svm_fifo_seg_t segs[], } always_inline void -http_io_ts_after_write (http_conn_t *hc, transport_send_params_t *sp, u8 flush, - u8 written) +http_io_ts_after_write (http_conn_t *hc, u8 flush) { session_t *ts = session_get_from_handle (hc->hc_tc_session_handle); if (!flush) { - if (written && svm_fifo_set_event (ts->tx_fifo)) + if (svm_fifo_set_event (ts->tx_fifo)) session_program_tx_io_evt (ts->handle, SESSION_IO_EVT_TX); - - if (sp && (svm_fifo_max_enqueue (ts->tx_fifo) < HTTP_FIFO_THRESH)) - { - /* Deschedule http session and wait for deq notification if - * underlying ts tx fifo almost full */ - svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF); - transport_connection_deschedule (&hc->connection); - sp->flags |= TRANSPORT_SND_F_DESCHED; - } } else { - if (written && svm_fifo_set_event (ts->tx_fifo)) + if (svm_fifo_set_event (ts->tx_fifo)) session_program_tx_io_evt (ts->handle, SESSION_IO_EVT_TX_FLUSH); } } -- 2.16.6