aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/hs_apps
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2024-09-04 18:04:54 +0200
committerFlorin Coras <florin.coras@gmail.com>2024-09-08 22:41:27 +0000
commit9bb0762357015ca49ab8376308eda021d35d6f25 (patch)
treeb7b7e3c0b4e53f6daf88e780f1e66bd16b1b0282 /src/plugins/hs_apps
parentc4b5d10115d4370488ac14eb0ba7295b049a0615 (diff)
http: large POST handling
Type: improvement Change-Id: I28b8e8ccbff6f97e669b0048011b187decbfc892 Signed-off-by: Matus Fabian <matfabia@cisco.com>
Diffstat (limited to 'src/plugins/hs_apps')
-rw-r--r--src/plugins/hs_apps/http_tps.c154
1 files changed, 115 insertions, 39 deletions
diff --git a/src/plugins/hs_apps/http_tps.c b/src/plugins/hs_apps/http_tps.c
index 35a5802f476..39046b38d43 100644
--- a/src/plugins/hs_apps/http_tps.c
+++ b/src/plugins/hs_apps/http_tps.c
@@ -20,6 +20,8 @@
#include <http/http_header_names.h>
#include <http/http_content_types.h>
+#define HTS_RX_BUF_SIZE (64 << 10)
+
typedef struct
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
@@ -28,6 +30,7 @@ typedef struct
u64 data_len;
u64 data_offset;
u32 vpp_session_index;
+ u32 to_recv;
union
{
/** threshold after which connection is closed */
@@ -36,6 +39,7 @@ typedef struct
u32 close_rate;
};
u8 *uri;
+ u8 *rx_buf;
http_header_t *resp_headers;
} hts_session_t;
@@ -105,6 +109,8 @@ hts_session_free (hts_session_t *hs)
if (htm->debug_level > 0)
clib_warning ("Freeing session %u", hs->session_index);
+ vec_free (hs->rx_buf);
+
if (CLIB_DEBUG)
clib_memset (hs, 0xfa, sizeof (*hs));
@@ -227,6 +233,8 @@ hts_start_send_data (hts_session_t *hs, http_status_code_t status)
http_msg_t msg;
session_t *ts;
u8 *headers_buf = 0;
+ u32 n_segs = 1;
+ svm_fifo_seg_t seg[2];
int rv;
if (vec_len (hs->resp_headers))
@@ -235,6 +243,9 @@ hts_start_send_data (hts_session_t *hs, http_status_code_t status)
vec_free (hs->resp_headers);
msg.data.headers_offset = 0;
msg.data.headers_len = vec_len (headers_buf);
+ seg[1].data = headers_buf;
+ seg[1].len = msg.data.headers_len;
+ n_segs = 2;
}
else
{
@@ -248,17 +259,14 @@ hts_start_send_data (hts_session_t *hs, http_status_code_t status)
msg.data.body_len = hs->data_len;
msg.data.body_offset = msg.data.headers_len;
msg.data.len = msg.data.body_len + msg.data.headers_len;
+ seg[0].data = (u8 *) &msg;
+ seg[0].len = sizeof (msg);
ts = session_get (hs->vpp_session_index, hs->thread_index);
- rv = svm_fifo_enqueue (ts->tx_fifo, sizeof (msg), (u8 *) &msg);
- ASSERT (rv == sizeof (msg));
-
- if (msg.data.headers_len)
- {
- rv = svm_fifo_enqueue (ts->tx_fifo, vec_len (headers_buf), headers_buf);
- ASSERT (rv == msg.data.headers_len);
- vec_free (headers_buf);
- }
+ rv = svm_fifo_enqueue_segments (ts->tx_fifo, seg, n_segs,
+ 0 /* allow partial */);
+ vec_free (headers_buf);
+ ASSERT (rv == (sizeof (msg) + msg.data.headers_len));
if (!msg.data.body_len)
{
@@ -323,6 +331,40 @@ done:
return rc;
}
+static inline void
+hts_session_rx_body (hts_session_t *hs, session_t *ts)
+{
+ hts_main_t *htm = &hts_main;
+ u32 n_deq;
+ int rv;
+
+ n_deq = svm_fifo_max_dequeue (ts->rx_fifo);
+ if (!htm->no_zc)
+ {
+ svm_fifo_dequeue_drop_all (ts->rx_fifo);
+ }
+ else
+ {
+ n_deq = clib_min (n_deq, HTS_RX_BUF_SIZE);
+ rv = svm_fifo_dequeue (ts->rx_fifo, n_deq, hs->rx_buf);
+ ASSERT (rv == n_deq);
+ }
+ hs->to_recv -= n_deq;
+
+ if (hs->close_threshold > 0)
+ {
+ if ((f64) (hs->data_len - hs->to_recv) / hs->data_len >
+ hs->close_threshold)
+ hts_disconnect_transport (hs);
+ }
+
+ if (hs->to_recv == 0)
+ {
+ hts_start_send_data (hs, HTTP_STATUS_OK);
+ vec_free (hs->rx_buf);
+ }
+}
+
static int
hts_ts_rx_callback (session_t *ts)
{
@@ -333,44 +375,77 @@ hts_ts_rx_callback (session_t *ts)
int rv;
hs = hts_session_get (ts->thread_index, ts->opaque);
- hs->data_len = 0;
- hs->resp_headers = 0;
- /* Read the http message header */
- rv = svm_fifo_dequeue (ts->rx_fifo, sizeof (msg), (u8 *) &msg);
- ASSERT (rv == sizeof (msg));
-
- if (msg.type != HTTP_MSG_REQUEST || msg.method_type != HTTP_REQ_GET)
+ if (hs->to_recv == 0)
{
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_ALLOW),
- http_token_lit ("GET"));
- hts_start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
- goto done;
- }
+ hs->data_len = 0;
+ hs->resp_headers = 0;
+ hs->rx_buf = 0;
- if (msg.data.target_path_len == 0 ||
- msg.data.target_form != HTTP_TARGET_ORIGIN_FORM)
- {
- hts_start_send_data (hs, HTTP_STATUS_BAD_REQUEST);
- goto done;
- }
+ /* Read the http message header */
+ rv = svm_fifo_dequeue (ts->rx_fifo, sizeof (msg), (u8 *) &msg);
+ ASSERT (rv == sizeof (msg));
- vec_validate (target, msg.data.target_path_len - 1);
- rv = svm_fifo_peek (ts->rx_fifo, msg.data.target_path_offset,
- msg.data.target_path_len, target);
- ASSERT (rv == msg.data.target_path_len);
+ if (msg.type != HTTP_MSG_REQUEST)
+ {
+ hts_start_send_data (hs, HTTP_STATUS_INTERNAL_ERROR);
+ goto done;
+ }
+ if (msg.method_type != HTTP_REQ_GET && msg.method_type != HTTP_REQ_POST)
+ {
+ http_add_header (&hs->resp_headers,
+ http_header_name_token (HTTP_HEADER_ALLOW),
+ http_token_lit ("GET, POST"));
+ hts_start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
+ goto done;
+ }
- if (htm->debug_level)
- clib_warning ("Request target: %v", target);
+ if (msg.data.target_path_len == 0 ||
+ msg.data.target_form != HTTP_TARGET_ORIGIN_FORM)
+ {
+ hts_start_send_data (hs, HTTP_STATUS_BAD_REQUEST);
+ goto done;
+ }
- if (try_test_file (hs, target))
- hts_start_send_data (hs, HTTP_STATUS_NOT_FOUND);
+ vec_validate (target, msg.data.target_path_len - 1);
+ rv = svm_fifo_peek (ts->rx_fifo, msg.data.target_path_offset,
+ msg.data.target_path_len, target);
+ ASSERT (rv == msg.data.target_path_len);
- vec_free (target);
+ if (htm->debug_level)
+ clib_warning ("%s request target: %v",
+ msg.method_type == HTTP_REQ_GET ? "GET" : "POST",
+ target);
+
+ if (msg.method_type == HTTP_REQ_GET)
+ {
+ if (try_test_file (hs, target))
+ hts_start_send_data (hs, HTTP_STATUS_NOT_FOUND);
+ vec_free (target);
+ }
+ else
+ {
+ vec_free (target);
+ if (!msg.data.body_len)
+ {
+ hts_start_send_data (hs, HTTP_STATUS_BAD_REQUEST);
+ goto done;
+ }
+ /* drop everything up to body */
+ svm_fifo_dequeue_drop (ts->rx_fifo, msg.data.body_offset);
+ hs->to_recv = msg.data.body_len;
+ if (htm->no_zc)
+ vec_validate (hs->rx_buf, HTS_RX_BUF_SIZE - 1);
+ hts_session_rx_body (hs, ts);
+ return 0;
+ }
+
+ done:
+ svm_fifo_dequeue_drop (ts->rx_fifo, msg.data.len);
+ }
+ else
+ hts_session_rx_body (hs, ts);
-done:
- svm_fifo_dequeue_drop (ts->rx_fifo, msg.data.len);
return 0;
}
@@ -397,6 +472,7 @@ hts_ts_accept_callback (session_t *ts)
hs = hts_session_alloc (ts->thread_index);
hs->vpp_session_index = ts->session_index;
+ hs->to_recv = 0;
ts->opaque = hs->session_index;
ts->session_state = SESSION_STATE_READY;