diff options
31 files changed, 279 insertions, 101 deletions
@@ -106,6 +106,7 @@ DEB_DEPENDS += iperf ethtool # for 'make test TEST=vm_vpp_interfaces' DEB_DEPENDS += libpcap-dev DEB_DEPENDS += tshark DEB_DEPENDS += jq # for extracting test summary from .json report (hs-test) +DEB_DEPENDS += nasm libnuma-dev # for make-ext-deps LIBFFI=libffi6 # works on all but 20.04 and debian-testing ifeq ($(OS_VERSION_ID),24.04) diff --git a/build/external/deb/debian/control b/build/external/deb/debian/control index a4e59f4c577..701d7bf0961 100644 --- a/build/external/deb/debian/control +++ b/build/external/deb/debian/control @@ -2,7 +2,7 @@ Source: vpp-ext-deps Section: net Priority: extra Maintainer: vpp-dev@lists.fd.io -Build-Depends: debhelper (>= 9), dkms +Build-Depends: debhelper (>= 9) Standards-Version: 3.9.4 Package: vpp-ext-deps diff --git a/build/optional/deb/debian/control b/build/optional/deb/debian/control index d892395ddab..c18809f7f5e 100644 --- a/build/optional/deb/debian/control +++ b/build/optional/deb/debian/control @@ -2,7 +2,7 @@ Source: vpp-opt-deps Section: net Priority: extra Maintainer: vpp-dev@lists.fd.io -Build-Depends: debhelper (>= 9), dkms +Build-Depends: debhelper (>= 9) Standards-Version: 3.9.4 Package: vpp-opt-deps diff --git a/extras/hs-test/echo_test.go b/extras/hs-test/echo_test.go index b21c69a1e99..8d69c007113 100644 --- a/extras/hs-test/echo_test.go +++ b/extras/hs-test/echo_test.go @@ -39,7 +39,7 @@ func TcpWithLossTest(s *VethsSuite) { clientVpp.Vppctl("nsim output-feature enable-disable host-" + s.Interfaces.Server.Name()) // Do echo test from client-vpp container - output := clientVpp.Vppctl("test echo client uri tcp://%s/20022 verbose echo-bytes mbytes 50", + output := clientVpp.Vppctl("test echo client uri tcp://%s/20022 verbose echo-bytes bytes 50m", s.Interfaces.Server.Ip4AddressString()) s.Log(output) s.AssertNotEqual(len(output), 0) diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go index 760ca3ca936..93317bbf8d8 100644 --- a/extras/hs-test/http_test.go +++ b/extras/hs-test/http_test.go @@ -412,7 +412,8 @@ func httpClientGet(s *NoTopoSuite, response string, size int) { s.AssertContains(o, response) s.AssertContains(o, "Content-Length: "+strconv.Itoa(size)) - file_contents := vpp.Container.Exec(false, "cat /tmp/response.txt") + file_contents, err := vpp.Container.Exec(false, "cat /tmp/response.txt") + s.AssertNil(err) s.AssertContains(file_contents, response) } @@ -463,7 +464,8 @@ func httpClientRepeat(s *NoTopoSuite, requestMethod string, clientArgs string) { o := vpp.Vppctl(cmd) s.Log(o) - replyCount := s.Containers.NginxServer.Exec(false, "awk 'END { print NR }' "+logPath) + replyCount, err := s.Containers.NginxServer.Exec(false, "awk 'END { print NR }' "+logPath) + s.AssertNil(err) if replyCount != "" { replyCountInt, err = strconv.Atoi(replyCount[:len(replyCount)-1]) s.AssertNil(err) @@ -485,7 +487,8 @@ func httpClientRepeat(s *NoTopoSuite, requestMethod string, clientArgs string) { o = vpp.Vppctl(cmd) s.Log(o) - replyCount = s.Containers.NginxServer.Exec(false, "awk 'END { print NR }' "+logPath) + replyCount, err = s.Containers.NginxServer.Exec(false, "awk 'END { print NR }' "+logPath) + s.AssertNil(err) if replyCount != "" { replyCountInt, err = strconv.Atoi(replyCount[:len(replyCount)-1]) s.AssertNil(err) diff --git a/extras/hs-test/infra/container.go b/extras/hs-test/infra/container.go index 918c19e669e..efc317fa96d 100644 --- a/extras/hs-test/infra/container.go +++ b/extras/hs-test/infra/container.go @@ -460,7 +460,7 @@ func (c *Container) ExecServer(useEnvVars bool, command string, arguments ...any c.Suite.AssertNil(exechelper.Run(containerExecCommand)) } -func (c *Container) Exec(useEnvVars bool, command string, arguments ...any) string { +func (c *Container) Exec(useEnvVars bool, command string, arguments ...any) (string, error) { var envVars string serverCommand := fmt.Sprintf(command, arguments...) if useEnvVars { @@ -472,8 +472,7 @@ func (c *Container) Exec(useEnvVars bool, command string, arguments ...any) stri GinkgoHelper() c.Suite.Log(containerExecCommand) byteOutput, err := exechelper.CombinedOutput(containerExecCommand) - c.Suite.AssertNil(err, fmt.Sprint(err)) - return string(byteOutput) + return string(byteOutput), err } func (c *Container) saveLogs() { diff --git a/extras/hs-test/infra/vppinstance.go b/extras/hs-test/infra/vppinstance.go index 370d2be38d1..59d17de4d20 100644 --- a/extras/hs-test/infra/vppinstance.go +++ b/extras/hs-test/infra/vppinstance.go @@ -243,9 +243,11 @@ func (vpp *VppInstance) Start() error { } func (vpp *VppInstance) Stop() { - pid := strings.TrimSpace(vpp.Container.Exec(false, "pidof vpp")) + pid, err := vpp.Container.Exec(false, "pidof vpp") + pid = strings.TrimSpace(pid) // Stop VPP only if it's still running - if len(pid) > 0 { + if err == nil { + vpp.getSuite().Log("Stopping VPP") vpp.Container.Exec(false, "bash -c \"kill -15 "+pid+"\"") } } diff --git a/extras/hs-test/raw_session_test.go b/extras/hs-test/raw_session_test.go index c104031f78f..b93b27ab56b 100644 --- a/extras/hs-test/raw_session_test.go +++ b/extras/hs-test/raw_session_test.go @@ -35,6 +35,7 @@ func testVppEcho(s *VethsSuite, proto string) { " socket-name " + s.Containers.ClientApp.GetContainerWorkDir() + "/var/run/app_ns_sockets/default" + " use-app-socket-api uri " + uri s.Log(clientCommand) - o := s.Containers.ClientApp.Exec(true, clientCommand) + o, err := s.Containers.ClientApp.Exec(true, clientCommand) + s.AssertNil(err) s.Log(o) } diff --git a/extras/hs-test/vcl_test.go b/extras/hs-test/vcl_test.go index 11e2be1258e..bc557a90508 100644 --- a/extras/hs-test/vcl_test.go +++ b/extras/hs-test/vcl_test.go @@ -50,7 +50,8 @@ func testXEchoVclClient(s *VethsSuite, proto string) { testClientCommand := "vcl_test_client -N 100 -p " + proto + " " + s.Interfaces.Server.Ip4AddressString() + " " + port s.Log(testClientCommand) echoClnContainer.AddEnvVar("VCL_CONFIG", "/vcl.conf") - o := echoClnContainer.Exec(true, testClientCommand) + o, err := echoClnContainer.Exec(true, testClientCommand) + s.AssertNil(err) s.Log(o) s.AssertContains(o, "CLIENT RESULTS") } @@ -76,7 +77,7 @@ func testXEchoVclServer(s *VethsSuite, proto string) { serverVethAddress := s.Interfaces.Server.Ip4AddressString() clientVpp := s.Containers.ClientVpp.VppInstance - o := clientVpp.Vppctl("test echo client uri %s://%s/%s fifo-size 64k verbose mbytes 2", proto, serverVethAddress, port) + o := clientVpp.Vppctl("test echo client uri %s://%s/%s fifo-size 64k verbose bytes 2m", proto, serverVethAddress, port) s.Log(o) s.AssertContains(o, "Test finished at") } @@ -97,7 +98,8 @@ func testVclEcho(s *VethsSuite, proto string) { testClientCommand := "vcl_test_client -p " + proto + " " + serverVethAddress + " " + port echoClnContainer.AddEnvVar("VCL_CONFIG", "/vcl.conf") - o := echoClnContainer.Exec(true, testClientCommand) + o, err := echoClnContainer.Exec(true, testClientCommand) + s.AssertNil(err) s.Log(o) } @@ -137,7 +139,8 @@ func testRetryAttach(s *VethsSuite, proto string) { testClientCommand := "vcl_test_client -U -p " + proto + " " + serverVethAddress + " 12346" echoClnContainer.AddEnvVar("VCL_CONFIG", "/vcl.conf") - o := echoClnContainer.Exec(true, testClientCommand) + o, err := echoClnContainer.Exec(true, testClientCommand) + s.AssertNil(err) s.Log(o) s.Log("... First test ended. Stopping VPP server now.") @@ -152,7 +155,8 @@ func testRetryAttach(s *VethsSuite, proto string) { time.Sleep(30 * time.Second) // Wait a moment for the re-attachment to happen s.Log("... Running second echo client test, after disconnect and re-attachment.") - o = echoClnContainer.Exec(true, testClientCommand) + o, err = echoClnContainer.Exec(true, testClientCommand) + s.AssertNil(err) s.Log(o) s.Log("Done.") } diff --git a/extras/scripts/host-stack/http-speed-test/speed_test_startup_conf b/extras/scripts/host-stack/http-speed-test/speed_test_startup_conf new file mode 100644 index 00000000000..ec9230148e5 --- /dev/null +++ b/extras/scripts/host-stack/http-speed-test/speed_test_startup_conf @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2025 Cisco Systems, Inc. +unix { + interactive log /tmp/vpp.log + full-coredump + exec /scratch/matfabia/vpp/extras/scripts/host-stack/http-speed-test/speedtest.cli + cli-listen /run/vpp/cli.sock + poll-sleep-usec 0 +} +heapsize 4g +api-trace { on } +api-segment { global-size 2000M api-size 1G gid vpp } +dpdk { + dev 0000:17:00.0 { + num-tx-desc 256 + num-rx-desc 512 + num-rx-queues 1 + tso on + } + enable-tcp-udp-checksum +} +cpu { + skip-cores 0 + main-core 1 + corelist-workers 2-10 +} +buffers { buffers-per-numa 16536 } +session { event-queue-length 100000 use-app-socket-api } +tcp { max-rx-fifo 128m tso } +socksvr { socket-name /run/vpp-api.sock } + diff --git a/extras/scripts/host-stack/http-speed-test/speedtest.cli b/extras/scripts/host-stack/http-speed-test/speedtest.cli new file mode 100644 index 00000000000..555aa173d6b --- /dev/null +++ b/extras/scripts/host-stack/http-speed-test/speedtest.cli @@ -0,0 +1,5 @@ +comment {SPDX-License-Identifier: Apache-2.0} +comment {Copyright (c) 2025 Cisco Systems, Inc.} +set int ip address HundredGigabitEthernet17/0/0 6.0.1.1/24 +set int state HundredGigabitEthernet17/0/0 up +http static server www-root /scratch/matfabia/Speed-Test max-body-size 40m max-age 0 keepalive-timeout 120 cache-size 100m fifo-size 512k diff --git a/src/plugins/dev_octeon/crypto.c b/src/plugins/dev_octeon/crypto.c index 800f24a008a..52c796089d5 100644 --- a/src/plugins/dev_octeon/crypto.c +++ b/src/plugins/dev_octeon/crypto.c @@ -1354,7 +1354,7 @@ oct_crypto_aead_session_update (vlib_main_t *vm, oct_crypto_sess_t *sess, vnet_crypto_key_t *key = vnet_crypto_get_key (key_index); roc_se_cipher_type enc_type = 0; roc_se_auth_type auth_type = 0; - u32 digest_len = ~0; + u32 digest_len = 16; i32 rv = 0; switch (key->alg) @@ -1366,9 +1366,6 @@ oct_crypto_aead_session_update (vlib_main_t *vm, oct_crypto_sess_t *sess, sess->aes_gcm = 1; sess->iv_offset = 0; sess->iv_length = 16; - sess->cpt_ctx.mac_len = 16; - sess->cpt_op = type; - digest_len = 16; break; case VNET_CRYPTO_ALG_CHACHA20_POLY1305: enc_type = ROC_SE_CHACHA20; @@ -1381,6 +1378,9 @@ oct_crypto_aead_session_update (vlib_main_t *vm, oct_crypto_sess_t *sess, return -1; } + sess->cpt_ctx.mac_len = digest_len; + sess->cpt_op = type; + rv = roc_se_ciph_key_set (&sess->cpt_ctx, enc_type, key->data, key->length); if (rv) { @@ -1940,7 +1940,7 @@ oct_init_crypto_engine_handlers (vlib_main_t *vm, vnet_dev_t *dev) } int -oct_conf_sw_queue (vlib_main_t *vm, vnet_dev_t *dev) +oct_conf_sw_queue (vlib_main_t *vm, vnet_dev_t *dev, oct_crypto_dev_t *ocd) { oct_crypto_main_t *ocm = &oct_crypto_main; vlib_thread_main_t *tm = vlib_get_thread_main (); @@ -1961,7 +1961,7 @@ oct_conf_sw_queue (vlib_main_t *vm, vnet_dev_t *dev) * Each pending queue will get number of cpt desc / number of cores. * And that desc count is shared across inflight entries. */ - n_inflight_req = (OCT_CPT_LF_MAX_NB_DESC / tm->n_vlib_mains); + n_inflight_req = (ocd->n_desc / tm->n_vlib_mains); for (i = 0; i < tm->n_vlib_mains; ++i) { diff --git a/src/plugins/dev_octeon/crypto.h b/src/plugins/dev_octeon/crypto.h index 5bd26f6b9be..4d8c56a314c 100644 --- a/src/plugins/dev_octeon/crypto.h +++ b/src/plugins/dev_octeon/crypto.h @@ -11,6 +11,9 @@ #define OCT_MAX_N_CPT_DEV 2 +#define OCT_CPT_LF_DEF_NB_DESC 16384 + +#define OCT_CPT_LF_MIN_NB_DESC 1024 #define OCT_CPT_LF_MAX_NB_DESC 128000 /* CRYPTO_ID, KEY_LENGTH_IN_BYTES, TAG_LEN, AAD_LEN */ @@ -81,6 +84,7 @@ typedef struct struct roc_cpt_lmtline lmtline; struct roc_cpt_lf lf; vnet_dev_t *dev; + u32 n_desc; } oct_crypto_dev_t; typedef struct @@ -211,5 +215,6 @@ vnet_crypto_async_frame_t *oct_crypto_frame_dequeue (vlib_main_t *vm, u32 *nb_elts_processed, u32 *enqueue_thread_idx); int oct_init_crypto_engine_handlers (vlib_main_t *vm, vnet_dev_t *dev); -int oct_conf_sw_queue (vlib_main_t *vm, vnet_dev_t *dev); +int oct_conf_sw_queue (vlib_main_t *vm, vnet_dev_t *dev, + oct_crypto_dev_t *ocd); #endif /* _CRYPTO_H_ */ diff --git a/src/plugins/dev_octeon/init.c b/src/plugins/dev_octeon/init.c index 561cbe94fed..69fb097e91f 100644 --- a/src/plugins/dev_octeon/init.c +++ b/src/plugins/dev_octeon/init.c @@ -61,6 +61,22 @@ static struct #undef _ }; +static vnet_dev_arg_t oct_dev_args[] = { + { + .id = OCT_DEV_ARG_CRYPTO_N_DESC, + .name = "n_desc", + .desc = "number of cpt descriptors, applicable to cpt devices only", + .type = VNET_DEV_ARG_TYPE_UINT32, + .default_val.uint32 = OCT_CPT_LF_DEF_NB_DESC, + }, + { + .id = OCT_DEV_ARG_END, + .name = "end", + .desc = "Argument end", + .type = VNET_DEV_ARG_END, + }, +}; + static u8 * oct_probe (vlib_main_t *vm, vnet_dev_bus_index_t bus_index, void *dev_info) { @@ -241,7 +257,7 @@ oct_conf_cpt_queue (vlib_main_t *vm, vnet_dev_t *dev, oct_crypto_dev_t *ocd) cpt_lf = &ocd->lf; cpt_lmtline = &ocd->lmtline; - cpt_lf->nb_desc = OCT_CPT_LF_MAX_NB_DESC; + cpt_lf->nb_desc = ocd->n_desc; cpt_lf->lf_id = 0; if ((rrv = roc_cpt_lf_init (roc_cpt, cpt_lf)) < 0) return cnx_return_roc_err (dev, rrv, "roc_cpt_lf_init"); @@ -261,6 +277,7 @@ oct_init_cpt (vlib_main_t *vm, vnet_dev_t *dev) extern oct_plt_init_param_t oct_plt_init_param; oct_device_t *cd = vnet_dev_get_data (dev); oct_crypto_dev_t *ocd = NULL; + u32 n_desc; int rrv; if (ocm->n_cpt == OCT_MAX_N_CPT_DEV || ocm->started) @@ -274,6 +291,27 @@ oct_init_cpt (vlib_main_t *vm, vnet_dev_t *dev) ocd->roc_cpt->pci_dev = &cd->plt_pci_dev; ocd->dev = dev; + ocd->n_desc = OCT_CPT_LF_DEF_NB_DESC; + + foreach_vnet_dev_args (arg, dev) + { + if (arg->id == OCT_DEV_ARG_CRYPTO_N_DESC && + vnet_dev_arg_get_uint32 (arg)) + { + n_desc = vnet_dev_arg_get_uint32 (arg); + if (n_desc < OCT_CPT_LF_MIN_NB_DESC || + n_desc > OCT_CPT_LF_MAX_NB_DESC) + { + log_err (dev, + "number of cpt descriptors should be within range " + "of %u and %u", + OCT_CPT_LF_MIN_NB_DESC, OCT_CPT_LF_MAX_NB_DESC); + return VNET_DEV_ERR_NOT_SUPPORTED; + } + + ocd->n_desc = vnet_dev_arg_get_uint32 (arg); + } + } if ((rrv = roc_cpt_dev_init (ocd->roc_cpt))) return cnx_return_roc_err (dev, rrv, "roc_cpt_dev_init"); @@ -290,7 +328,7 @@ oct_init_cpt (vlib_main_t *vm, vnet_dev_t *dev) * Initialize s/w queues, which are common across multiple * crypto devices */ - oct_conf_sw_queue (vm, dev); + oct_conf_sw_queue (vm, dev, ocd); ocm->crypto_dev[0] = ocd; } @@ -396,6 +434,7 @@ VNET_DEV_REGISTER_DRIVER (octeon) = { .free = oct_free, .probe = oct_probe, }, + .args = oct_dev_args, }; static clib_error_t * diff --git a/src/plugins/dev_octeon/octeon.h b/src/plugins/dev_octeon/octeon.h index ccf8f62880d..0cf937528f0 100644 --- a/src/plugins/dev_octeon/octeon.h +++ b/src/plugins/dev_octeon/octeon.h @@ -25,6 +25,12 @@ typedef enum { + OCT_DEV_ARG_CRYPTO_N_DESC = 1, + OCT_DEV_ARG_END, +} oct_dev_args_t; + +typedef enum +{ OCT_DEVICE_TYPE_UNKNOWN = 0, OCT_DEVICE_TYPE_RVU_PF, OCT_DEVICE_TYPE_RVU_VF, diff --git a/src/plugins/dma_intel/dsa.c b/src/plugins/dma_intel/dsa.c index 473f2efa93e..20a90e34b0e 100644 --- a/src/plugins/dma_intel/dsa.c +++ b/src/plugins/dma_intel/dsa.c @@ -103,7 +103,6 @@ intel_dsa_batch_fallback (vlib_main_t *vm, intel_dsa_batch_t *b, clib_memcpy_fast (desc->dst, desc->src, desc->size); } b->status = INTEL_DSA_STATUS_CPU_SUCCESS; - ch->submitted++; return; } @@ -407,6 +406,7 @@ intel_dsa_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, /* fallback to software if exception happened */ intel_dsa_batch_fallback (vm, b, ch); glitch = 1 & b->barrier_before_last; + t->pending_batches[n++] = b; } else { diff --git a/src/plugins/hs_apps/echo_client.c b/src/plugins/hs_apps/echo_client.c index ff5a3bd6b3c..b08edaaa5f5 100644 --- a/src/plugins/hs_apps/echo_client.c +++ b/src/plugins/hs_apps/echo_client.c @@ -1073,7 +1073,7 @@ ec_command_fn (vlib_main_t *vm, unformat_input_t *input, uword *event_data = 0, event_type; clib_error_t *error = 0; int rv, had_config = 1; - u64 tmp, total_bytes; + u64 total_bytes; f64 delta; if (ecm->test_client_attached) @@ -1099,10 +1099,6 @@ ec_command_fn (vlib_main_t *vm, unformat_input_t *input, ; else if (unformat (line_input, "quic-streams %d", &ecm->quic_streams)) ; - else if (unformat (line_input, "mbytes %lld", &tmp)) - ecm->bytes_to_send = tmp << 20; - else if (unformat (line_input, "gbytes %lld", &tmp)) - ecm->bytes_to_send = tmp << 30; else if (unformat (line_input, "bytes %U", unformat_memory_size, &ecm->bytes_to_send)) ; @@ -1336,7 +1332,7 @@ cleanup: VLIB_CLI_COMMAND (ec_command, static) = { .path = "test echo clients", .short_help = - "test echo clients [nclients %d][[m|g]bytes <bytes>]" + "test echo clients [nclients %d][bytes <bytes>[m|g]]" "[test-timeout <time>][syn-timeout <time>][echo-bytes][fifo-size <size>]" "[private-segment-count <count>][private-segment-size <bytes>[m|g]]" "[preallocate-fifos][preallocate-sessions][client-batch <batch-size>]" diff --git a/src/plugins/http/http.c b/src/plugins/http/http.c index 5998a9ebd18..43b0993e462 100644 --- a/src/plugins/http/http.c +++ b/src/plugins/http/http.c @@ -525,7 +525,7 @@ http_ts_disconnect_callback (session_t *ts) hc_handle.as_u32 = ts->opaque; - HTTP_DBG (1, "hc [%u]%x", ts->thread_index, hc_index); + HTTP_DBG (1, "hc [%u]%x", ts->thread_index, hc_handle.conn_index); hc = http_conn_get_w_thread (hc_handle.conn_index, ts->thread_index); @@ -543,7 +543,7 @@ http_ts_reset_callback (session_t *ts) hc_handle.as_u32 = ts->opaque; - HTTP_DBG (1, "hc [%u]%x", ts->thread_index, hc_index); + HTTP_DBG (1, "hc [%u]%x", ts->thread_index, hc_handle.conn_index); hc = http_conn_get_w_thread (hc_handle.conn_index, ts->thread_index); @@ -607,7 +607,8 @@ http_ts_cleanup_callback (session_t *ts, session_cleanup_ntf_t ntf) hc_handle.as_u32 = ts->opaque; hc = http_conn_get_w_thread (hc_handle.conn_index, ts->thread_index); - HTTP_DBG (1, "going to free hc [%u]%x", ts->thread_index, hc_index); + HTTP_DBG (1, "going to free hc [%u]%x", ts->thread_index, + hc_handle.conn_index); if (!(hc->flags & HTTP_CONN_F_PENDING_TIMER)) http_conn_timer_stop (hc); diff --git a/src/plugins/http/http1.c b/src/plugins/http/http1.c index ec118aa4e52..265f6e7b24f 100644 --- a/src/plugins/http/http1.c +++ b/src/plugins/http/http1.c @@ -998,6 +998,7 @@ http1_req_state_wait_transport_method (http_conn_t *hc, http_req_t *req, /* send at least "control data" which is necessary minimum, * if there is some space send also portion of body */ max_enq = http_io_as_max_write (req); + max_enq -= sizeof (msg); if (max_enq < req->control_data_len) { clib_warning ("not enough room for control data in app's rx fifo"); @@ -1859,10 +1860,12 @@ http1_transport_rx_callback (http_conn_t *hc) if (!http1_req_state_is_rx_valid (req)) { - clib_warning ("hc [%u]%x invalid rx state: http req state " - "'%U', session state '%U'", - hc->c_thread_index, hc->hc_hc_index, format_http_req_state, - req->state, format_http_conn_state, hc); + if (http_io_ts_max_read (hc)) + clib_warning ("hc [%u]%x invalid rx state: http req state " + "'%U', session state '%U'", + hc->c_thread_index, hc->hc_hc_index, + format_http_req_state, req->state, + format_http_conn_state, hc); http_io_ts_drain_all (hc); return; } diff --git a/src/plugins/http/http_private.h b/src/plugins/http/http_private.h index ebec59aeaee..8354bf29289 100644 --- a/src/plugins/http/http_private.h +++ b/src/plugins/http/http_private.h @@ -691,7 +691,7 @@ http_conn_accept_request (http_conn_t *hc, http_req_t *req) int rv; HTTP_DBG (1, "hc [%u]%x req %x", hc->hc_hc_index, hc->c_thread_index, - req->hr_req_index); + req->hr_req_handle); /* allocate app session and initialize */ as = session_alloc (hc->c_thread_index); diff --git a/src/plugins/http_static/http_static.h b/src/plugins/http_static/http_static.h index e158a32dbc9..2b6de03c71a 100644 --- a/src/plugins/http_static/http_static.h +++ b/src/plugins/http_static/http_static.h @@ -33,7 +33,7 @@ /** \brief Application session */ -typedef struct +typedef struct hss_session_ { CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); u32 session_index; @@ -42,6 +42,9 @@ typedef struct /** vpp session index, handle */ u32 vpp_session_index; session_handle_t vpp_session_handle; + u8 *target_path; + u8 *target_query; + http_req_method_t rt; /** Fully-resolved file path */ u8 *path; /** Data to send */ @@ -58,6 +61,9 @@ typedef struct http_headers_ctx_t resp_headers; /** Response header buffer */ u8 *headers_buf; + /** POST body left to receive */ + u64 left_recv; + int (*read_body_handler) (struct hss_session_ *hs, session_t *ts); } hss_session_t; typedef struct hss_session_handle_ diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c index d7958fd3f1f..75481f840b2 100644 --- a/src/plugins/http_static/static_server.c +++ b/src/plugins/http_static/static_server.c @@ -30,6 +30,8 @@ #define HSS_HEADER_BUF_MAX_SIZE 16192 hss_main_t hss_main; +static int file_handler_discard_body (hss_session_t *hs, session_t *ts); + static int hss_add_header (hss_session_t *hs, http_header_name_t name, const char *value, uword value_len) @@ -280,14 +282,18 @@ content_type_from_request (u8 *request) } static int -try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, - u8 *target_path, u8 *target_query, u8 *data) +try_url_handler (hss_session_t *hs) { + hss_main_t *hsm = &hss_main; http_status_code_t sc = HTTP_STATUS_OK; hss_url_handler_args_t args = {}; uword *p, *url_table; + session_t *ts; + u8 *data = 0, *target_path; int rv; + target_path = hs->target_path; + if (!hsm->enable_url_handlers || !target_path) return -1; @@ -299,28 +305,48 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, /* Look for built-in GET / POST handlers */ url_table = - (rt == HTTP_REQ_GET) ? hsm->get_url_handlers : hsm->post_url_handlers; + (hs->rt == HTTP_REQ_GET) ? hsm->get_url_handlers : hsm->post_url_handlers; p = hash_get_mem (url_table, target_path); if (!p) return -1; + /* Read request body */ + if (hs->left_recv) + { + ts = session_get (hs->vpp_session_index, hs->thread_index); + /* TODO: add support for large content (use hs->read_body_handler) */ + if (svm_fifo_max_dequeue (ts->rx_fifo) < hs->left_recv) + { + hs->left_recv = 0; + start_send_data (hs, HTTP_STATUS_INTERNAL_ERROR); + hss_session_disconnect_transport (hs); + return 0; + } + vec_validate (data, hs->left_recv - 1); + rv = svm_fifo_dequeue (ts->rx_fifo, hs->left_recv, data); + ASSERT (rv == hs->left_recv); + hs->left_recv = 0; + } + hs->path = 0; hs->data_offset = 0; hs->cache_pool_index = ~0; if (hsm->debug_level > 0) - clib_warning ("%s '%s'", (rt == HTTP_REQ_GET) ? "GET" : "POST", + clib_warning ("%s '%s'", (hs->rt == HTTP_REQ_GET) ? "GET" : "POST", target_path); - args.req_type = rt; - args.query = target_query; + args.req_type = hs->rt; + args.query = hs->target_query; args.req_data = data; args.sh.thread_index = hs->thread_index; args.sh.session_index = hs->session_index; rv = ((hss_url_handler_fn) p[0]) (&args); + vec_free (data); + /* Wait for data from handler */ if (rv == HSS_URL_HANDLER_ASYNC) return 0; @@ -328,7 +354,7 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, if (rv == HSS_URL_HANDLER_ERROR) { clib_warning ("builtin handler %llx hit on %s '%s' but failed!", p[0], - (rt == HTTP_REQ_GET) ? "GET" : "POST", target_path); + (hs->rt == HTTP_REQ_GET) ? "GET" : "POST", target_path); sc = HTTP_STATUS_BAD_GATEWAY; } @@ -429,32 +455,49 @@ try_index_file (hss_main_t *hsm, hss_session_t *hs, u8 *path) } static int -try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, - u8 *target) +try_file_handler (hss_session_t *hs) { + hss_main_t *hsm = &hss_main; http_status_code_t sc = HTTP_STATUS_OK; u8 *path, *sanitized_path; - u32 ce_index; + u32 ce_index, max_dequeue; http_content_type_t type; u8 *last_modified; + session_t *ts; /* Feature not enabled */ if (!hsm->www_root) return -1; + /* Discard request body */ + if (hs->left_recv) + { + ts = session_get (hs->vpp_session_index, hs->thread_index); + max_dequeue = svm_fifo_max_dequeue (ts->rx_fifo); + if (max_dequeue < hs->left_recv) + { + svm_fifo_dequeue_drop (ts->rx_fifo, max_dequeue); + hs->left_recv -= max_dequeue; + hs->read_body_handler = file_handler_discard_body; + return 0; + } + svm_fifo_dequeue_drop (ts->rx_fifo, hs->left_recv); + hs->left_recv = 0; + } + /* Sanitize received path */ - sanitized_path = http_path_sanitize (target); + sanitized_path = http_path_sanitize (hs->target_path); /* * Construct the file to open */ - if (!target) + if (!sanitized_path) path = format (0, "%s%c", hsm->www_root, 0); else path = format (0, "%s/%s%c", hsm->www_root, sanitized_path, 0); if (hsm->debug_level > 0) - clib_warning ("%s '%s'", (rt == HTTP_REQ_GET) ? "GET" : "POST", path); + clib_warning ("%s '%s'", (hs->rt == HTTP_REQ_GET) ? "GET" : "POST", path); if (hs->data && hs->free_data) vec_free (hs->data); @@ -498,7 +541,7 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, * Cache-Control max-age * Last-Modified */ - type = content_type_from_request (target); + type = content_type_from_request (sanitized_path); if (hss_add_header (hs, HTTP_HEADER_CONTENT_TYPE, http_content_type_token (type)) || hss_add_header (hs, HTTP_HEADER_CACHE_CONTROL, @@ -520,15 +563,12 @@ done: } static void -handle_request (hss_session_t *hs, http_req_method_t rt, u8 *target_path, - u8 *target_query, u8 *data) +handle_request (hss_session_t *hs) { - hss_main_t *hsm = &hss_main; - - if (!try_url_handler (hsm, hs, rt, target_path, target_query, data)) + if (!try_url_handler (hs)) return; - if (!try_file_handler (hsm, hs, rt, target_path)) + if (!try_file_handler (hs)) return; /* Handler did not find anything return 404 */ @@ -537,19 +577,41 @@ handle_request (hss_session_t *hs, http_req_method_t rt, u8 *target_path, } static int +file_handler_discard_body (hss_session_t *hs, session_t *ts) +{ + u32 max_dequeue, to_discard; + + max_dequeue = svm_fifo_max_dequeue (ts->rx_fifo); + to_discard = clib_min (max_dequeue, hs->left_recv); + svm_fifo_dequeue_drop (ts->rx_fifo, to_discard); + hs->left_recv -= to_discard; + if (hs->left_recv == 0) + return try_file_handler (hs); + return 0; +} + +static int hss_ts_rx_callback (session_t *ts) { hss_main_t *hsm = &hss_main; hss_session_t *hs; - u8 *target_path = 0, *target_query = 0, *data = 0; http_msg_t msg; int rv; hs = hss_session_get (ts->thread_index, ts->opaque); + if (hs->left_recv != 0) + { + ASSERT (hs->read_body_handler); + return hs->read_body_handler (hs, ts); + } + if (hs->free_data) vec_free (hs->data); + hs->data = 0; hs->data_len = 0; + vec_free (hs->target_path); + vec_free (hs->target_query); http_init_headers_ctx (&hs->resp_headers, hs->headers_buf, vec_len (hs->headers_buf)); @@ -567,37 +629,38 @@ hss_ts_rx_callback (session_t *ts) goto err_done; } + hs->rt = msg.method_type; + /* Read target path */ if (msg.data.target_path_len) { - vec_validate (target_path, msg.data.target_path_len - 1); + vec_validate (hs->target_path, msg.data.target_path_len - 1); rv = svm_fifo_peek (ts->rx_fifo, msg.data.target_path_offset, - msg.data.target_path_len, target_path); + msg.data.target_path_len, hs->target_path); ASSERT (rv == msg.data.target_path_len); - if (http_validate_abs_path_syntax (target_path, 0)) + if (http_validate_abs_path_syntax (hs->target_path, 0)) { start_send_data (hs, HTTP_STATUS_BAD_REQUEST); goto err_done; } /* Target path must be a proper C-string in addition to a vector */ - vec_add1 (target_path, 0); + vec_add1 (hs->target_path, 0); } /* Read target query */ if (msg.data.target_query_len) { - vec_validate (target_query, msg.data.target_query_len - 1); + vec_validate (hs->target_query, msg.data.target_query_len - 1); rv = svm_fifo_peek (ts->rx_fifo, msg.data.target_query_offset, - msg.data.target_query_len, target_query); + msg.data.target_query_len, hs->target_query); ASSERT (rv == msg.data.target_query_len); - if (http_validate_query_syntax (target_query, 0)) + if (http_validate_query_syntax (hs->target_query, 0)) { start_send_data (hs, HTTP_STATUS_BAD_REQUEST); goto err_done; } } - /* Read request body for POST requests */ if (msg.data.body_len && msg.method_type == HTTP_REQ_POST) { if (msg.data.body_len > hsm->max_body_size) @@ -605,28 +668,19 @@ hss_ts_rx_callback (session_t *ts) start_send_data (hs, HTTP_STATUS_CONTENT_TOO_LARGE); goto err_done; } - if (svm_fifo_max_dequeue (ts->rx_fifo) - msg.data.body_offset < - msg.data.body_len) - { - start_send_data (hs, HTTP_STATUS_INTERNAL_ERROR); - goto err_done; - } - vec_validate (data, msg.data.body_len - 1); - rv = svm_fifo_peek (ts->rx_fifo, msg.data.body_offset, msg.data.body_len, - data); - ASSERT (rv == msg.data.body_len); + + hs->left_recv = msg.data.body_len; + /* drop everything up to body */ + svm_fifo_dequeue_drop (ts->rx_fifo, msg.data.body_offset); } /* Find and send data */ - handle_request (hs, msg.method_type, target_path, target_query, data); + handle_request (hs); goto done; err_done: hss_session_disconnect_transport (hs); done: - vec_free (target_path); - vec_free (target_query); - vec_free (data); svm_fifo_dequeue_drop (ts->rx_fifo, msg.data.len); return 0; } @@ -757,6 +811,8 @@ hss_ts_cleanup (session_t *s, session_cleanup_ntf_t ntf) hs->free_data = 0; vec_free (hs->headers_buf); vec_free (hs->path); + vec_free (hs->target_path); + vec_free (hs->target_query); hss_session_free (hs); } @@ -952,8 +1008,9 @@ hss_create_command_fn (vlib_main_t *vm, unformat_input_t *input, else if (unformat (line_input, "private-segment-size %U", unformat_memory_size, &seg_size)) hsm->private_segment_size = seg_size; - else if (unformat (line_input, "fifo-size %d", &hsm->fifo_size)) - hsm->fifo_size <<= 10; + else if (unformat (line_input, "fifo-size %U", unformat_memory_size, + &hsm->fifo_size)) + ; else if (unformat (line_input, "cache-size %U", unformat_memory_size, &hsm->cache_size)) ; diff --git a/src/vcl/vcl_private.c b/src/vcl/vcl_private.c index 1adc8cb6666..7a9b60a1959 100644 --- a/src/vcl/vcl_private.c +++ b/src/vcl/vcl_private.c @@ -212,14 +212,16 @@ vcl_worker_detached_start_signal_mq (vcl_worker_t *wrk) exit (1); } - int sig = 1, __clib_unused rv; + int __clib_unused rv; + u8 sig = 1; rv = write (wrk->detached_pipefds[1], &sig, 1); } void vcl_worker_detached_signal_mq (vcl_worker_t *wrk) { - int buf, __clib_unused rv; + int __clib_unused rv; + u8 buf; rv = read (wrk->detached_pipefds[0], &buf, 1); rv = write (wrk->detached_pipefds[1], &buf, 1); } diff --git a/test/Makefile b/test/Makefile index de3a3ca2a52..37f8e2db18b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -423,6 +423,7 @@ cov-post: wipe-cov $(BUILD_COV_DIR) -o $(BUILD_COV_DIR)/coverage-filtered$(HS_TEST).info @genhtml $(BUILD_COV_DIR)/coverage-filtered$(HS_TEST).info \ --output-directory $(BUILD_COV_DIR)/html + @rm -f $(BUILD_COV_DIR)/html/cmd_line @test -z "$(EXTERN_COV_DIR)" || \ genhtml $(BUILD_COV_DIR)/extern-coverage$(HS_TEST).info \ --output-directory $(BUILD_COV_DIR)/extern-html diff --git a/test/asf/asfframework.py b/test/asf/asfframework.py index 8e565d26a52..7670a0753d1 100644 --- a/test/asf/asfframework.py +++ b/test/asf/asfframework.py @@ -652,8 +652,6 @@ class VppAsfTestCase(CPUInterface, unittest.TestCase): cls.pump_thread.start() if cls.debug_gdb or cls.debug_gdbserver or cls.debug_attach: cls.vapi_response_timeout = 0 - elif config.gcov: - cls.vapi_response_timeout = 20 cls.vapi = VppPapiProvider(cls.__name__, cls, cls.vapi_response_timeout) if cls.step: hook = hookmodule.StepHook(cls) diff --git a/test/asf/test_quic.py b/test/asf/test_quic.py index c4fa6912114..78ebe0f40a7 100644 --- a/test/asf/test_quic.py +++ b/test/asf/test_quic.py @@ -178,7 +178,7 @@ class QUICEchoIntTransferTestCase(QUICEchoIntTestCase): def test_quic_int_transfer(self): """QUIC internal transfer""" self.server() - self.client("mbytes", "2") + self.client("bytes", "2m") @tag_fixme_vpp_workers @@ -188,11 +188,11 @@ class QUICEchoIntSerialTestCase(QUICEchoIntTestCase): def test_quic_serial_int_transfer(self): """QUIC serial internal transfer""" self.server() - self.client("mbytes", "2") - self.client("mbytes", "2") - self.client("mbytes", "2") - self.client("mbytes", "2") - self.client("mbytes", "2") + self.client("bytes", "2m") + self.client("bytes", "2m") + self.client("bytes", "2m") + self.client("bytes", "2m") + self.client("bytes", "2m") @tag_fixme_vpp_workers @@ -202,7 +202,7 @@ class QUICEchoIntMStreamTestCase(QUICEchoIntTestCase): def test_quic_int_multistream_transfer(self): """QUIC internal multi-stream transfer""" self.server() - self.client("nclients", "10", "mbytes", "1") + self.client("nclients", "10", "bytes", "1m") class QUICEchoExtTestCase(QUICTestCase): diff --git a/test/asf/test_session_sdl.py b/test/asf/test_session_sdl.py index 53301f7bd6c..d2e30daa9f2 100644 --- a/test/asf/test_session_sdl.py +++ b/test/asf/test_session_sdl.py @@ -5,6 +5,7 @@ import unittest from framework import VppTestCase from asfframework import VppTestRunner, tag_fixme_vpp_workers from ipaddress import IPv4Network, IPv6Network +from config import config from vpp_ip_route import ( VppIpRoute, @@ -25,6 +26,10 @@ class TestSessionSDL(VppTestCase): @classmethod def setUpClass(cls): + # increase vapi timeout, to avoid + # failures reported on test-cov + if config.gcov: + cls.vapi_response_timeout = 20 super(TestSessionSDL, cls).setUpClass() @classmethod diff --git a/test/asf/test_tcp.py b/test/asf/test_tcp.py index 23772d34c76..e9c9e1efb68 100644 --- a/test/asf/test_tcp.py +++ b/test/asf/test_tcp.py @@ -89,7 +89,7 @@ class TestTCP(VppAsfTestCase): self.assertNotIn("failed", error) error = self.vapi.cli( - "test echo client mbytes 10 appns 1 " + "test echo client bytes 10m appns 1 " + "fifo-size 4k test-bytes " + "syn-timeout 2 uri " + uri diff --git a/test/asf/test_tls.py b/test/asf/test_tls.py index 2ce87143339..6676132417c 100644 --- a/test/asf/test_tls.py +++ b/test/asf/test_tls.py @@ -142,7 +142,7 @@ class TestTLS(VppAsfTestCase): self.assertNotIn("failed", error) error = self.vapi.cli( - "test echo client mbytes 10 appns 1 " + "test echo client bytes 10m appns 1 " "fifo-size 4k test-bytes " "tls-engine 1 " "syn-timeout 2 uri " + uri diff --git a/test/test_pg_stream.py b/test/test_pg_stream.py index 471c85c43f0..915a5aa73d9 100644 --- a/test/test_pg_stream.py +++ b/test/test_pg_stream.py @@ -11,6 +11,7 @@ from scapy.layers.inet6 import IPv6 from framework import VppTestCase from asfframework import VppTestRunner +from config import config class TestPgStream(VppTestCase): @@ -19,6 +20,18 @@ class TestPgStream(VppTestCase): def __init__(self, *args): VppTestCase.__init__(self, *args) + @classmethod + def setUpClass(cls): + # increase vapi timeout, to avoid + # failures reported on test-cov + if config.gcov: + cls.vapi_response_timeout = 20 + super(TestPgStream, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TestPgStream, cls).tearDownClass() + def setUp(self): super(TestPgStream, self).setUp() diff --git a/test/test_udp.py b/test/test_udp.py index 6315f0efd5e..c7620fb7e9d 100644 --- a/test/test_udp.py +++ b/test/test_udp.py @@ -764,7 +764,7 @@ class TestUDP(VppTestCase): self.assertNotIn("failed", error) error = self.vapi.cli( - "test echo client mbytes 10 appns 1 " + "test echo client bytes 10m appns 1 " + "fifo-size 4k " + "syn-timeout 2 uri " + uri |