summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/hs_apps/CMakeLists.txt15
-rw-r--r--src/plugins/hs_apps/vcl/vcl_test.h106
-rw-r--r--src/plugins/hs_apps/vcl/vcl_test_client.c228
-rw-r--r--src/plugins/hs_apps/vcl/vcl_test_protos.c674
-rw-r--r--src/plugins/hs_apps/vcl/vcl_test_server.c127
5 files changed, 836 insertions, 314 deletions
diff --git a/src/plugins/hs_apps/CMakeLists.txt b/src/plugins/hs_apps/CMakeLists.txt
index da86512f99f..1f474828b15 100644
--- a/src/plugins/hs_apps/CMakeLists.txt
+++ b/src/plugins/hs_apps/CMakeLists.txt
@@ -47,8 +47,6 @@ endif(VPP_BUILD_HS_SAPI_APPS)
option(VPP_BUILD_VCL_TESTS "Build vcl tests." ON)
if(VPP_BUILD_VCL_TESTS)
foreach(test
- vcl_test_server
- vcl_test_client
sock_test_server
sock_test_client
)
@@ -58,4 +56,17 @@ if(VPP_BUILD_VCL_TESTS)
NO_INSTALL
)
endforeach()
+
+ foreach(test
+ vcl_test_server
+ vcl_test_client
+ )
+ add_vpp_executable(${test}
+ SOURCES
+ "vcl/${test}.c"
+ vcl/vcl_test_protos.c
+ LINK_LIBRARIES vppcom pthread
+ NO_INSTALL
+ )
+ endforeach()
endif(VPP_BUILD_VCL_TESTS)
diff --git a/src/plugins/hs_apps/vcl/vcl_test.h b/src/plugins/hs_apps/vcl/vcl_test.h
index 386e9686ef2..18e3c00f487 100644
--- a/src/plugins/hs_apps/vcl/vcl_test.h
+++ b/src/plugins/hs_apps/vcl/vcl_test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -19,6 +19,7 @@
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <vcl/vppcom.h>
@@ -121,14 +122,16 @@ typedef struct
struct timespec stop;
} vcl_test_stats_t;
-typedef struct
+typedef struct vcl_test_session
{
uint8_t is_alloc;
uint8_t is_open;
int fd;
+ int (*read) (struct vcl_test_session *ts, void *buf, uint32_t buflen);
+ int (*write) (struct vcl_test_session *ts, void *buf, uint32_t buflen);
uint32_t txbuf_size;
- char *txbuf;
uint32_t rxbuf_size;
+ char *txbuf;
char *rxbuf;
vcl_test_cfg_t cfg;
vcl_test_stats_t stats;
@@ -138,64 +141,45 @@ typedef struct
vppcom_data_segment_t ds[2];
} vcl_test_session_t;
-/*
- * TLS server cert and keys to be used for testing only
- */
-char vcl_test_crt_rsa[] =
- "-----BEGIN CERTIFICATE-----\r\n"
- "MIID5zCCAs+gAwIBAgIJALeMYCEHrTtJMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD\r\n"
- "VQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQK\r\n"
- "DAVDaXNjbzEOMAwGA1UECwwFZmQuaW8xFjAUBgNVBAMMDXRlc3R0bHMuZmQuaW8x\r\n"
- "IjAgBgkqhkiG9w0BCQEWE3ZwcC1kZXZAbGlzdHMuZmQuaW8wHhcNMTgwMzA1MjEx\r\n"
- "NTEyWhcNMjgwMzAyMjExNTEyWjCBiTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNB\r\n"
- "MREwDwYDVQQHDAhTYW4gSm9zZTEOMAwGA1UECgwFQ2lzY28xDjAMBgNVBAsMBWZk\r\n"
- "LmlvMRYwFAYDVQQDDA10ZXN0dGxzLmZkLmlvMSIwIAYJKoZIhvcNAQkBFhN2cHAt\r\n"
- "ZGV2QGxpc3RzLmZkLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\r\n"
- "4C1k8a1DuStgggqT4o09fP9sJ2dC54bxhS/Xk2VEfaIZ222WSo4X/syRVfVy9Yah\r\n"
- "cpI1zJ/RDxaZSFhgA+nPZBrFMsrULkrdAOpOVj8eDEp9JuWdO2ODSoFnCvLxcYWB\r\n"
- "Yc5kHryJpEaGJl1sFQSesnzMFty/59ta0stk0Fp8r5NhIjWvSovGzPo6Bhz+VS2c\r\n"
- "ebIZh4x1t2hHaFcgm0qJoJ6DceReWCW8w+yOVovTolGGq+bpb2Hn7MnRSZ2K2NdL\r\n"
- "+aLXpkZbS/AODP1FF2vTO1mYL290LO7/51vJmPXNKSDYMy5EvILr5/VqtjsFCwRL\r\n"
- "Q4jcM/+GeHSAFWx4qIv0BwIDAQABo1AwTjAdBgNVHQ4EFgQUWa1SOB37xmT53tZQ\r\n"
- "aXuLLhRI7U8wHwYDVR0jBBgwFoAUWa1SOB37xmT53tZQaXuLLhRI7U8wDAYDVR0T\r\n"
- "BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoUht13W4ya27NVzQuCMvqPWL3VM4\r\n"
- "3xbPFk02FaGz/WupPu276zGlzJAZrbuDcQowwwU1Ni1Yygxl96s1c2M5rHDTrOKG\r\n"
- "rK0hbkSFBo+i6I8u4HiiQ4rYmG0Hv6+sXn3of0HsbtDPGgWZoipPWDljPYEURu3e\r\n"
- "3HRe/Dtsj9CakBoSDzs8ndWaBR+f4sM9Tk1cjD46Gq2T/qpSPXqKxEUXlzhdCAn4\r\n"
- "twub17Bq2kykHpppCwPg5M+v30tHG/R2Go15MeFWbEJthFk3TZMjKL7UFs7fH+x2\r\n"
- "wSonXb++jY+KmCb93C+soABBizE57g/KmiR2IxQ/LMjDik01RSUIaM0lLA==\r\n"
- "-----END CERTIFICATE-----\r\n";
-uint32_t vcl_test_crt_rsa_len = sizeof (vcl_test_crt_rsa);
-
-char vcl_test_key_rsa[] =
- "-----BEGIN PRIVATE KEY-----\r\n"
- "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgLWTxrUO5K2CC\r\n"
- "CpPijT18/2wnZ0LnhvGFL9eTZUR9ohnbbZZKjhf+zJFV9XL1hqFykjXMn9EPFplI\r\n"
- "WGAD6c9kGsUyytQuSt0A6k5WPx4MSn0m5Z07Y4NKgWcK8vFxhYFhzmQevImkRoYm\r\n"
- "XWwVBJ6yfMwW3L/n21rSy2TQWnyvk2EiNa9Ki8bM+joGHP5VLZx5shmHjHW3aEdo\r\n"
- "VyCbSomgnoNx5F5YJbzD7I5Wi9OiUYar5ulvYefsydFJnYrY10v5otemRltL8A4M\r\n"
- "/UUXa9M7WZgvb3Qs7v/nW8mY9c0pINgzLkS8guvn9Wq2OwULBEtDiNwz/4Z4dIAV\r\n"
- "bHioi/QHAgMBAAECggEBAMzGipP8+oT166U+NlJXRFifFVN1DvdhG9PWnOxGL+c3\r\n"
- "ILmBBC08WQzmHshPemBvR6DZkA1H23cV5JTiLWrFtC00CvhXsLRMrE5+uWotI6yE\r\n"
- "iofybMroHvD6/X5R510UX9hQ6MHu5ShLR5VZ9zXHz5MpTmB/60jG5dLx+jgcwBK8\r\n"
- "LuGv2YB/WCUwT9QJ3YU2eaingnXtz/MrFbkbltrqlnBdlD+kTtw6Yac9y1XuuQXc\r\n"
- "BPeulLNDuPolJVWbUvDBZrpt2dXTgz8ws1sv+wCNE0xwQJsqW4Nx3QkpibUL9RUr\r\n"
- "CVbKlNfa9lopT6nGKlgX69R/uH35yh9AOsfasro6w0ECgYEA82UJ8u/+ORah+0sF\r\n"
- "Q0FfW5MTdi7OAUHOz16pUsGlaEv0ERrjZxmAkHA/VRwpvDBpx4alCv0Hc39PFLIk\r\n"
- "nhSsM2BEuBkTAs6/GaoNAiBtQVE/hN7awNRWVmlieS0go3Y3dzaE9IUMyj8sPOFT\r\n"
- "5JdJ6BM69PHKCkY3dKdnnfpFEuECgYEA68mRpteunF1mdZgXs+WrN+uLlRrQR20F\r\n"
- "ZyMYiUCH2Dtn26EzA2moy7FipIIrQcX/j+KhYNGM3e7MU4LymIO29E18mn8JODnH\r\n"
- "sQOXzBTsf8A4yIVMkcuQD3bfb0JiUGYUPOidTp2N7IJA7+6Yc3vQOyb74lnKnJoO\r\n"
- "gougPT2wS+cCgYAn7muzb6xFsXDhyW0Tm6YJYBfRS9yAWEuVufINobeBZPSl2cN1\r\n"
- "Jrnw+HlrfTNbrJWuJmjtZJXUXQ6cVp2rUbjutNyRV4vG6iRwEXYQ40EJdkr1gZpi\r\n"
- "CHQhuShuuPih2MNAy7EEbM+sXrDjTBR3bFqzuHPzu7dp+BshCFX3lRfAAQKBgGQt\r\n"
- "K5i7IhCFDjb/+3IPLgOAK7mZvsvZ4eXD33TQ2eZgtut1PXtBtNl17/b85uv293Fm\r\n"
- "VDISVcsk3eLNS8zIiT6afUoWlxAwXEs0v5WRfjl4radkGvgGiJpJYvyeM67877RB\r\n"
- "EDSKc/X8ESLfOB44iGvZUEMG6zJFscx9DgN25iQZAoGAbyd+JEWwdVH9/K3IH1t2\r\n"
- "PBkZX17kNWv+iVM1WyFjbe++vfKZCrOJiyiqhDeEqgrP3AuNMlaaduC3VRC3G5oV\r\n"
- "Mj1tlhDWQ/qhvKdCKNdIVQYDE75nw+FRWV8yYkHAnXYW3tNoweDIwixE0hkPR1bc\r\n"
- "oEjPLVNtx8SOj/M4rhaPT3I=\r\n" "-----END PRIVATE KEY-----\r\n";
-uint32_t vcl_test_key_rsa_len = sizeof (vcl_test_key_rsa);
+static __thread int __wrk_index = 0;
+
+static inline int
+vcl_test_worker_index (void)
+{
+ return __wrk_index;
+}
+
+typedef struct
+{
+ int (*init) (vcl_test_cfg_t *cfg);
+ int (*open) (vcl_test_session_t *ts, vppcom_endpt_t *endpt);
+ int (*listen) (vcl_test_session_t *ts, vppcom_endpt_t *endpt);
+ int (*accept) (int listen_fd, vcl_test_session_t *ts);
+ int (*close) (vcl_test_session_t *ts);
+} vcl_test_proto_vft_t;
+
+typedef struct
+{
+ vcl_test_session_t *qsessions;
+ uint32_t n_qsessions;
+ uint32_t n_sessions;
+} vcl_test_wrk_t;
+
+typedef struct
+{
+ const vcl_test_proto_vft_t *protos[VPPCOM_PROTO_DTLS + 1];
+ uint32_t ckpair_index;
+ vcl_test_cfg_t cfg;
+ vcl_test_wrk_t *wrk;
+} vcl_test_main_t;
+
+extern vcl_test_main_t vcl_test_main;
+
+#define VCL_TEST_REGISTER_PROTO(proto, vft) \
+ static void __attribute__ ((constructor)) vcl_test_init_##proto (void) \
+ { \
+ vcl_test_main.protos[proto] = &vft; \
+ }
static inline void
vcl_test_stats_accumulate (vcl_test_stats_t * accum, vcl_test_stats_t * incr)
diff --git a/src/plugins/hs_apps/vcl/vcl_test_client.c b/src/plugins/hs_apps/vcl/vcl_test_client.c
index 0033ae6a30d..d87b4d3d3f6 100644
--- a/src/plugins/hs_apps/vcl/vcl_test_client.c
+++ b/src/plugins/hs_apps/vcl/vcl_test_client.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -44,25 +44,23 @@ typedef struct
vcl_test_client_worker_t *workers;
vppcom_endpt_t server_endpt;
uint32_t cfg_seq_num;
- vcl_test_session_t quic_session;
vcl_test_session_t ctrl_session;
vcl_test_session_t *sessions;
uint8_t dump_cfg;
vcl_test_t post_test;
uint8_t proto;
uint32_t n_workers;
- uint32_t ckpair_index;
volatile int active_workers;
struct sockaddr_storage server_addr;
} vcl_test_client_main_t;
-static __thread int __wrk_index = 0;
-
vcl_test_client_main_t vcl_client_main;
#define vtc_min(a, b) (a < b ? a : b)
#define vtc_max(a, b) (a > b ? a : b)
+vcl_test_main_t vcl_test_main;
+
static int
vtc_cfg_sync (vcl_test_session_t * ts)
{
@@ -75,15 +73,14 @@ vtc_cfg_sync (vcl_test_session_t * ts)
vtinf ("(fd %d): Sending config to server.", ts->fd);
vcl_test_cfg_dump (&ts->cfg, 1 /* is_client */ );
}
- tx_bytes = vcl_test_write (ts, (uint8_t *) &ts->cfg, sizeof (ts->cfg));
+ tx_bytes = ts->write (ts, &ts->cfg, sizeof (ts->cfg));
if (tx_bytes < 0)
{
vtwrn ("(fd %d): write test cfg failed (%d)!", ts->fd, tx_bytes);
return tx_bytes;
}
- rx_bytes =
- vcl_test_read (ts, (uint8_t *) ts->rxbuf, sizeof (vcl_test_cfg_t));
+ rx_bytes = ts->read (ts, ts->rxbuf, sizeof (vcl_test_cfg_t));
if (rx_bytes < 0)
return rx_bytes;
@@ -119,120 +116,15 @@ vtc_cfg_sync (vcl_test_session_t * ts)
}
static int
-vtc_quic_connect_test_sessions (vcl_test_client_worker_t * wrk)
-{
- vcl_test_client_main_t *vcm = &vcl_client_main;
- vcl_test_session_t *ts, *tq;
- uint32_t i, flags, flen;
- int rv;
-
- if (wrk->cfg.num_test_sessions < 1 || wrk->cfg.num_test_sessions_perq < 1)
- {
- errno = EINVAL;
- return -1;
- }
-
- if (wrk->n_sessions >= wrk->cfg.num_test_sessions)
- goto done;
-
- /* Connect Qsessions */
-
- if (wrk->n_qsessions)
- wrk->qsessions =
- realloc (wrk->qsessions,
- wrk->cfg.num_test_qsessions * sizeof (vcl_test_session_t));
- else
- wrk->qsessions =
- calloc (wrk->cfg.num_test_qsessions, sizeof (vcl_test_session_t));
-
- if (!wrk->qsessions)
- {
- vterr ("failed to alloc Qsessions", -errno);
- return errno;
- }
-
-
- for (i = 0; i < wrk->cfg.num_test_qsessions; i++)
- {
- tq = &wrk->qsessions[i];
- tq->fd = vppcom_session_create (vcm->proto, 0 /* is_nonblocking */ );
- tq->session_index = i;
- if (tq->fd < 0)
- {
- vterr ("vppcom_session_create()", tq->fd);
- return tq->fd;
- }
-
- /* Connect is blocking */
- rv = vppcom_session_connect (tq->fd, &vcm->server_endpt);
- if (rv < 0)
- {
- vterr ("vppcom_session_connect()", rv);
- return rv;
- }
- flags = O_NONBLOCK;
- flen = sizeof (flags);
- vppcom_session_attr (tq->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
- vtinf ("Test Qsession %d (fd %d) connected.", i, tq->fd);
- }
- wrk->n_qsessions = wrk->cfg.num_test_qsessions;
-
- /* Connect Stream sessions */
-
- if (wrk->n_sessions)
- wrk->sessions =
- realloc (wrk->sessions,
- wrk->cfg.num_test_sessions * sizeof (vcl_test_session_t));
- else
- wrk->sessions =
- calloc (wrk->cfg.num_test_sessions, sizeof (vcl_test_session_t));
-
- if (!wrk->sessions)
- {
- vterr ("failed to alloc sessions", -errno);
- return errno;
- }
-
- for (i = 0; i < wrk->cfg.num_test_sessions; i++)
- {
- tq = &wrk->qsessions[i / wrk->cfg.num_test_sessions_perq];
- ts = &wrk->sessions[i];
- ts->fd = vppcom_session_create (vcm->proto, 1 /* is_nonblocking */ );
- ts->session_index = i;
- if (ts->fd < 0)
- {
- vterr ("vppcom_session_create()", ts->fd);
- return ts->fd;
- }
-
- rv = vppcom_session_stream_connect (ts->fd, tq->fd);
- if (rv < 0)
- {
- vterr ("vppcom_session_stream_connect()", rv);
- return rv;
- }
-
- vtinf ("Test session %d (fd %d) connected.", i, ts->fd);
- }
- wrk->n_sessions = wrk->cfg.num_test_sessions;
-
-done:
- vtinf ("All test sessions (%d) connected!", wrk->cfg.num_test_sessions);
- return 0;
-}
-
-static int
vtc_connect_test_sessions (vcl_test_client_worker_t * wrk)
{
vcl_test_client_main_t *vcm = &vcl_client_main;
+ vcl_test_main_t *vt = &vcl_test_main;
+ const vcl_test_proto_vft_t *tp;
vcl_test_session_t *ts;
uint32_t n_test_sessions;
- uint32_t flags, flen;
int i, rv;
- if (vcm->proto == VPPCOM_PROTO_QUIC)
- return vtc_quic_connect_test_sessions (wrk);
-
n_test_sessions = wrk->cfg.num_test_sessions;
if (n_test_sessions < 1)
{
@@ -255,34 +147,15 @@ vtc_connect_test_sessions (vcl_test_client_worker_t * wrk)
return errno;
}
+ tp = vt->protos[vcm->proto];
+
for (i = 0; i < n_test_sessions; i++)
{
ts = &wrk->sessions[i];
- ts->fd = vppcom_session_create (vcm->proto, 0 /* is_nonblocking */ );
- if (ts->fd < 0)
- {
- vterr ("vppcom_session_create()", ts->fd);
- return ts->fd;
- }
-
- if (vcm->proto == VPPCOM_PROTO_TLS || vcm->proto == VPPCOM_PROTO_DTLS)
- {
- uint32_t ckp_len = sizeof (vcm->ckpair_index);
- vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR,
- &vcm->ckpair_index, &ckp_len);
- }
-
- /* Connect is blocking */
- rv = vppcom_session_connect (ts->fd, &vcm->server_endpt);
+ ts->session_index = i;
+ rv = tp->open (&wrk->sessions[i], &vcm->server_endpt);
if (rv < 0)
- {
- vterr ("vppcom_session_connect()", rv);
- return rv;
- }
- flags = O_NONBLOCK;
- flen = sizeof (flags);
- vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
- vtinf ("Test session %d (fd %d) connected.", i, ts->fd);
+ return rv;
}
wrk->n_sessions = n_test_sessions;
@@ -476,14 +349,13 @@ vtc_worker_loop (void *arg)
if (FD_ISSET (vppcom_session_index (ts->fd), rfdset)
&& ts->stats.rx_bytes < ts->cfg.total_bytes)
{
- (void) vcl_test_read (ts, (uint8_t *) ts->rxbuf, ts->rxbuf_size);
+ (void) ts->read (ts, ts->rxbuf, ts->rxbuf_size);
}
if (FD_ISSET (vppcom_session_index (ts->fd), wfdset)
&& ts->stats.tx_bytes < ts->cfg.total_bytes)
{
- rv =
- vcl_test_write (ts, (uint8_t *) ts->txbuf, ts->cfg.txbuf_size);
+ rv = ts->write (ts, ts->txbuf, ts->cfg.txbuf_size);
if (rv < 0)
{
vtwrn ("vppcom_test_write (%d) failed -- aborting test",
@@ -501,8 +373,7 @@ vtc_worker_loop (void *arg)
}
exit:
vtinf ("Worker %d done ...", wrk->wrk_index);
- if (wrk->cfg.test != VCL_TEST_TYPE_ECHO)
- vtc_accumulate_stats (wrk, ctrl);
+ vtc_accumulate_stats (wrk, ctrl);
sleep (VCL_TEST_DELAY_DISCONNECT);
vtc_worker_sessions_exit (wrk);
if (wrk->wrk_index)
@@ -558,14 +429,14 @@ vtc_echo_client (vcl_test_client_main_t * vcm)
cfg->total_bytes = strlen (ctrl->txbuf) + 1;
memset (&ctrl->stats, 0, sizeof (ctrl->stats));
- rv = vcl_test_write (ctrl, (uint8_t *) ctrl->txbuf, cfg->total_bytes);
+ rv = ctrl->write (ctrl, ctrl->txbuf, cfg->total_bytes);
if (rv < 0)
{
vtwrn ("vppcom_test_write (%d) failed ", ctrl->fd);
return;
}
- (void) vcl_test_read (ctrl, (uint8_t *) ctrl->rxbuf, ctrl->rxbuf_size);
+ (void) ctrl->read (ctrl, ctrl->rxbuf, ctrl->rxbuf_size);
}
static void
@@ -1059,12 +930,50 @@ vtc_ctrl_session_exit (void)
sleep (1);
}
+static int
+vtc_ctrl_session_init (vcl_test_client_main_t *vcm, vcl_test_session_t *ctrl)
+{
+ int rv;
+
+ ctrl->fd = vppcom_session_create (VPPCOM_PROTO_TCP, 0 /* is_nonblocking */);
+ if (ctrl->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ctrl->fd);
+ return ctrl->fd;
+ }
+
+ vtinf ("Connecting to server...");
+ rv = vppcom_session_connect (ctrl->fd, &vcm->server_endpt);
+ if (rv)
+ {
+ vterr ("vppcom_session_connect()", rv);
+ return rv;
+ }
+ vtinf ("Control session (fd %d) connected.", ctrl->fd);
+
+ ctrl->read = vcl_test_read;
+ ctrl->write = vcl_test_write;
+
+ ctrl->cfg.cmd = VCL_TEST_CMD_SYNC;
+ rv = vtc_cfg_sync (ctrl);
+ if (rv)
+ {
+ vterr ("vtc_cfg_sync()", rv);
+ return rv;
+ }
+
+ ctrl->cfg.ctrl_handle = ((vcl_test_cfg_t *) ctrl->rxbuf)->ctrl_handle;
+ memset (&ctrl->stats, 0, sizeof (ctrl->stats));
+
+ return 0;
+}
+
int
main (int argc, char **argv)
{
vcl_test_client_main_t *vcm = &vcl_client_main;
vcl_test_session_t *ctrl = &vcm->ctrl_session;
- vcl_test_session_t *quic_session = &vcm->quic_session;
+ vcl_test_main_t *vt = &vcl_test_main;
int rv;
vcm->n_workers = 1;
@@ -1073,27 +982,18 @@ main (int argc, char **argv)
vtc_process_opts (vcm, argc, argv);
vcm->workers = calloc (vcm->n_workers, sizeof (vcl_test_client_worker_t));
+ vt->wrk = calloc (vcm->n_workers, sizeof (vcl_test_wrk_t));
+
rv = vppcom_app_create ("vcl_test_client");
if (rv < 0)
vtfail ("vppcom_app_create()", rv);
- ctrl->fd = vppcom_session_create (VPPCOM_PROTO_TCP, 0 /* is_nonblocking */);
- if (ctrl->fd < 0)
- vtfail ("vppcom_session_create()", ctrl->fd);
-
- vtinf ("Connecting to server...");
- rv = vppcom_session_connect (ctrl->fd, &vcm->server_endpt);
- if (rv)
- vtfail ("vppcom_session_connect()", rv);
- vtinf ("Control session (fd %d) connected.", ctrl->fd);
-
- ctrl->cfg.cmd = VCL_TEST_CMD_SYNC;
- rv = vtc_cfg_sync (ctrl);
- if (rv)
- vtfail ("vtc_cfg_sync()", rv);
+ /* Protos like tls/dtls/quic need init */
+ if (vt->protos[vcm->proto]->init)
+ vt->protos[vcm->proto]->init (&ctrl->cfg);
- ctrl->cfg.ctrl_handle = ((vcl_test_cfg_t *) ctrl->rxbuf)->ctrl_handle;
- memset (&ctrl->stats, 0, sizeof (ctrl->stats));
+ if ((rv = vtc_ctrl_session_init (vcm, ctrl)))
+ vtfail ("vppcom_session_create() ctrl session", rv);
/* Update ctrl port to data port */
vcm->server_endpt.port += 1;
@@ -1157,8 +1057,6 @@ main (int argc, char **argv)
}
vtc_ctrl_session_exit ();
- if (quic_session)
- vppcom_session_close (quic_session->fd);
vppcom_app_destroy ();
free (vcm->workers);
return 0;
diff --git a/src/plugins/hs_apps/vcl/vcl_test_protos.c b/src/plugins/hs_apps/vcl/vcl_test_protos.c
new file mode 100644
index 00000000000..d2388224d12
--- /dev/null
+++ b/src/plugins/hs_apps/vcl/vcl_test_protos.c
@@ -0,0 +1,674 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hs_apps/vcl/vcl_test.h>
+
+static int
+vt_tcp_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ uint32_t flags, flen;
+ int rv;
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_TCP, 0 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ /* Connect is blocking */
+ rv = vppcom_session_connect (ts->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_connect()", rv);
+ return rv;
+ }
+
+ ts->read = vcl_test_read;
+ ts->write = vcl_test_write;
+ flags = O_NONBLOCK;
+ flen = sizeof (flags);
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
+ vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
+
+ return 0;
+}
+
+static int
+vt_tcp_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ int rv;
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_TCP, 0 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ rv = vppcom_session_bind (ts->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_bind()", rv);
+ return rv;
+ }
+
+ rv = vppcom_session_listen (ts->fd, 10);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_listen()", rv);
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+vt_tcp_accept (int listen_fd, vcl_test_session_t *ts)
+{
+ int client_fd;
+
+ client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
+ if (client_fd < 0)
+ {
+ vterr ("vppcom_session_accept()", client_fd);
+ return client_fd;
+ }
+ ts->fd = client_fd;
+ ts->is_open = 1;
+ ts->read = vcl_test_read;
+ ts->write = vcl_test_write;
+
+ return 0;
+}
+
+static const vcl_test_proto_vft_t vcl_test_tcp = {
+ .open = vt_tcp_connect,
+ .listen = vt_tcp_listen,
+ .accept = vt_tcp_accept,
+};
+
+VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_TCP, vcl_test_tcp);
+
+static int
+vt_udp_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ uint32_t flags, flen;
+ int rv;
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_UDP, 0 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ /* Connect is blocking */
+ rv = vppcom_session_connect (ts->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_connect()", rv);
+ return rv;
+ }
+
+ ts->read = vcl_test_read;
+ ts->write = vcl_test_write;
+ flags = O_NONBLOCK;
+ flen = sizeof (flags);
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
+ vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
+
+ return 0;
+}
+
+static int
+vt_udp_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ int rv;
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_UDP, 0 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CONNECTED, 0, 0);
+
+ /* Listen is implicit */
+ rv = vppcom_session_bind (ts->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_bind()", rv);
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+vt_udp_accept (int listen_fd, vcl_test_session_t *ts)
+{
+ int client_fd;
+
+ client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
+ if (client_fd < 0)
+ {
+ vterr ("vppcom_session_accept()", client_fd);
+ return client_fd;
+ }
+ ts->fd = client_fd;
+ ts->is_open = 1;
+ ts->read = vcl_test_read;
+ ts->write = vcl_test_write;
+
+ return 0;
+}
+
+static const vcl_test_proto_vft_t vcl_test_udp = {
+ .open = vt_udp_connect,
+ .listen = vt_udp_listen,
+ .accept = vt_udp_accept,
+};
+
+VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_UDP, vcl_test_udp);
+
+/*
+ * TLS server cert and keys to be used for testing only
+ */
+static char vcl_test_crt_rsa[] =
+ "-----BEGIN CERTIFICATE-----\r\n"
+ "MIID5zCCAs+gAwIBAgIJALeMYCEHrTtJMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD\r\n"
+ "VQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQK\r\n"
+ "DAVDaXNjbzEOMAwGA1UECwwFZmQuaW8xFjAUBgNVBAMMDXRlc3R0bHMuZmQuaW8x\r\n"
+ "IjAgBgkqhkiG9w0BCQEWE3ZwcC1kZXZAbGlzdHMuZmQuaW8wHhcNMTgwMzA1MjEx\r\n"
+ "NTEyWhcNMjgwMzAyMjExNTEyWjCBiTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNB\r\n"
+ "MREwDwYDVQQHDAhTYW4gSm9zZTEOMAwGA1UECgwFQ2lzY28xDjAMBgNVBAsMBWZk\r\n"
+ "LmlvMRYwFAYDVQQDDA10ZXN0dGxzLmZkLmlvMSIwIAYJKoZIhvcNAQkBFhN2cHAt\r\n"
+ "ZGV2QGxpc3RzLmZkLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\r\n"
+ "4C1k8a1DuStgggqT4o09fP9sJ2dC54bxhS/Xk2VEfaIZ222WSo4X/syRVfVy9Yah\r\n"
+ "cpI1zJ/RDxaZSFhgA+nPZBrFMsrULkrdAOpOVj8eDEp9JuWdO2ODSoFnCvLxcYWB\r\n"
+ "Yc5kHryJpEaGJl1sFQSesnzMFty/59ta0stk0Fp8r5NhIjWvSovGzPo6Bhz+VS2c\r\n"
+ "ebIZh4x1t2hHaFcgm0qJoJ6DceReWCW8w+yOVovTolGGq+bpb2Hn7MnRSZ2K2NdL\r\n"
+ "+aLXpkZbS/AODP1FF2vTO1mYL290LO7/51vJmPXNKSDYMy5EvILr5/VqtjsFCwRL\r\n"
+ "Q4jcM/+GeHSAFWx4qIv0BwIDAQABo1AwTjAdBgNVHQ4EFgQUWa1SOB37xmT53tZQ\r\n"
+ "aXuLLhRI7U8wHwYDVR0jBBgwFoAUWa1SOB37xmT53tZQaXuLLhRI7U8wDAYDVR0T\r\n"
+ "BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoUht13W4ya27NVzQuCMvqPWL3VM4\r\n"
+ "3xbPFk02FaGz/WupPu276zGlzJAZrbuDcQowwwU1Ni1Yygxl96s1c2M5rHDTrOKG\r\n"
+ "rK0hbkSFBo+i6I8u4HiiQ4rYmG0Hv6+sXn3of0HsbtDPGgWZoipPWDljPYEURu3e\r\n"
+ "3HRe/Dtsj9CakBoSDzs8ndWaBR+f4sM9Tk1cjD46Gq2T/qpSPXqKxEUXlzhdCAn4\r\n"
+ "twub17Bq2kykHpppCwPg5M+v30tHG/R2Go15MeFWbEJthFk3TZMjKL7UFs7fH+x2\r\n"
+ "wSonXb++jY+KmCb93C+soABBizE57g/KmiR2IxQ/LMjDik01RSUIaM0lLA==\r\n"
+ "-----END CERTIFICATE-----\r\n";
+static uint32_t vcl_test_crt_rsa_len = sizeof (vcl_test_crt_rsa);
+
+static char vcl_test_key_rsa[] =
+ "-----BEGIN PRIVATE KEY-----\r\n"
+ "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgLWTxrUO5K2CC\r\n"
+ "CpPijT18/2wnZ0LnhvGFL9eTZUR9ohnbbZZKjhf+zJFV9XL1hqFykjXMn9EPFplI\r\n"
+ "WGAD6c9kGsUyytQuSt0A6k5WPx4MSn0m5Z07Y4NKgWcK8vFxhYFhzmQevImkRoYm\r\n"
+ "XWwVBJ6yfMwW3L/n21rSy2TQWnyvk2EiNa9Ki8bM+joGHP5VLZx5shmHjHW3aEdo\r\n"
+ "VyCbSomgnoNx5F5YJbzD7I5Wi9OiUYar5ulvYefsydFJnYrY10v5otemRltL8A4M\r\n"
+ "/UUXa9M7WZgvb3Qs7v/nW8mY9c0pINgzLkS8guvn9Wq2OwULBEtDiNwz/4Z4dIAV\r\n"
+ "bHioi/QHAgMBAAECggEBAMzGipP8+oT166U+NlJXRFifFVN1DvdhG9PWnOxGL+c3\r\n"
+ "ILmBBC08WQzmHshPemBvR6DZkA1H23cV5JTiLWrFtC00CvhXsLRMrE5+uWotI6yE\r\n"
+ "iofybMroHvD6/X5R510UX9hQ6MHu5ShLR5VZ9zXHz5MpTmB/60jG5dLx+jgcwBK8\r\n"
+ "LuGv2YB/WCUwT9QJ3YU2eaingnXtz/MrFbkbltrqlnBdlD+kTtw6Yac9y1XuuQXc\r\n"
+ "BPeulLNDuPolJVWbUvDBZrpt2dXTgz8ws1sv+wCNE0xwQJsqW4Nx3QkpibUL9RUr\r\n"
+ "CVbKlNfa9lopT6nGKlgX69R/uH35yh9AOsfasro6w0ECgYEA82UJ8u/+ORah+0sF\r\n"
+ "Q0FfW5MTdi7OAUHOz16pUsGlaEv0ERrjZxmAkHA/VRwpvDBpx4alCv0Hc39PFLIk\r\n"
+ "nhSsM2BEuBkTAs6/GaoNAiBtQVE/hN7awNRWVmlieS0go3Y3dzaE9IUMyj8sPOFT\r\n"
+ "5JdJ6BM69PHKCkY3dKdnnfpFEuECgYEA68mRpteunF1mdZgXs+WrN+uLlRrQR20F\r\n"
+ "ZyMYiUCH2Dtn26EzA2moy7FipIIrQcX/j+KhYNGM3e7MU4LymIO29E18mn8JODnH\r\n"
+ "sQOXzBTsf8A4yIVMkcuQD3bfb0JiUGYUPOidTp2N7IJA7+6Yc3vQOyb74lnKnJoO\r\n"
+ "gougPT2wS+cCgYAn7muzb6xFsXDhyW0Tm6YJYBfRS9yAWEuVufINobeBZPSl2cN1\r\n"
+ "Jrnw+HlrfTNbrJWuJmjtZJXUXQ6cVp2rUbjutNyRV4vG6iRwEXYQ40EJdkr1gZpi\r\n"
+ "CHQhuShuuPih2MNAy7EEbM+sXrDjTBR3bFqzuHPzu7dp+BshCFX3lRfAAQKBgGQt\r\n"
+ "K5i7IhCFDjb/+3IPLgOAK7mZvsvZ4eXD33TQ2eZgtut1PXtBtNl17/b85uv293Fm\r\n"
+ "VDISVcsk3eLNS8zIiT6afUoWlxAwXEs0v5WRfjl4radkGvgGiJpJYvyeM67877RB\r\n"
+ "EDSKc/X8ESLfOB44iGvZUEMG6zJFscx9DgN25iQZAoGAbyd+JEWwdVH9/K3IH1t2\r\n"
+ "PBkZX17kNWv+iVM1WyFjbe++vfKZCrOJiyiqhDeEqgrP3AuNMlaaduC3VRC3G5oV\r\n"
+ "Mj1tlhDWQ/qhvKdCKNdIVQYDE75nw+FRWV8yYkHAnXYW3tNoweDIwixE0hkPR1bc\r\n"
+ "oEjPLVNtx8SOj/M4rhaPT3I=\r\n"
+ "-----END PRIVATE KEY-----\r\n";
+static uint32_t vcl_test_key_rsa_len = sizeof (vcl_test_key_rsa);
+
+static int
+vt_add_cert_key_pair ()
+{
+ vcl_test_main_t *vt = &vcl_test_main;
+ vppcom_cert_key_pair_t ckpair;
+ int ckp_index;
+
+ vtinf ("Adding tls certs ...");
+
+ ckpair.cert = vcl_test_crt_rsa;
+ ckpair.key = vcl_test_key_rsa;
+ ckpair.cert_len = vcl_test_crt_rsa_len;
+ ckpair.key_len = vcl_test_key_rsa_len;
+ ckp_index = vppcom_add_cert_key_pair (&ckpair);
+ if (ckp_index < 0)
+ {
+ vterr ("vppcom_add_cert_key_pair()", ckp_index);
+ return ckp_index;
+ }
+
+ vt->ckpair_index = ckp_index;
+ return 0;
+}
+
+static int
+vt_tls_init (vcl_test_cfg_t *cfg)
+{
+ return vt_add_cert_key_pair ();
+}
+
+static int
+vt_tls_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ vcl_test_main_t *vt = &vcl_test_main;
+ uint32_t flags, flen;
+ int rv;
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_TLS, 0 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ uint32_t ckp_len = sizeof (vt->ckpair_index);
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
+ &ckp_len);
+
+ /* Connect is blocking */
+ rv = vppcom_session_connect (ts->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_connect()", rv);
+ return rv;
+ }
+
+ ts->read = vcl_test_read;
+ ts->write = vcl_test_write;
+ flags = O_NONBLOCK;
+ flen = sizeof (flags);
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
+ vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
+
+ return 0;
+}
+
+static int
+vt_tls_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ vcl_test_main_t *vt = &vcl_test_main;
+ uint32_t ckp_len;
+ int rv;
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_TLS, 0 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ ckp_len = sizeof (vt->ckpair_index);
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
+ &ckp_len);
+
+ rv = vppcom_session_bind (ts->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_bind()", rv);
+ return rv;
+ }
+
+ rv = vppcom_session_listen (ts->fd, 10);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_listen()", rv);
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+vt_tls_accept (int listen_fd, vcl_test_session_t *ts)
+{
+ int client_fd;
+
+ client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
+ if (client_fd < 0)
+ {
+ vterr ("vppcom_session_accept()", client_fd);
+ return client_fd;
+ }
+ ts->fd = client_fd;
+ ts->is_open = 1;
+ ts->read = vcl_test_read;
+ ts->write = vcl_test_write;
+
+ return 0;
+}
+
+static const vcl_test_proto_vft_t vcl_test_tls = {
+ .init = vt_tls_init,
+ .open = vt_tls_connect,
+ .listen = vt_tls_listen,
+ .accept = vt_tls_accept,
+};
+
+VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_TLS, vcl_test_tls);
+
+static int
+vt_dtls_init (vcl_test_cfg_t *cfg)
+{
+ return vt_add_cert_key_pair ();
+}
+
+static int
+vt_dtls_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ vcl_test_main_t *vt = &vcl_test_main;
+ uint32_t flags, flen;
+ int rv;
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_DTLS, 0 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ uint32_t ckp_len = sizeof (vt->ckpair_index);
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
+ &ckp_len);
+
+ /* Connect is blocking */
+ rv = vppcom_session_connect (ts->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_connect()", rv);
+ return rv;
+ }
+
+ ts->read = vcl_test_read;
+ ts->write = vcl_test_write;
+ flags = O_NONBLOCK;
+ flen = sizeof (flags);
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
+ vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
+
+ return 0;
+}
+
+static int
+vt_dtls_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ vcl_test_main_t *vt = &vcl_test_main;
+ uint32_t ckp_len;
+ int rv;
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_DTLS, 0 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ ckp_len = sizeof (vt->ckpair_index);
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
+ &ckp_len);
+
+ rv = vppcom_session_bind (ts->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_bind()", rv);
+ return rv;
+ }
+
+ rv = vppcom_session_listen (ts->fd, 10);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_listen()", rv);
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+vt_dtls_accept (int listen_fd, vcl_test_session_t *ts)
+{
+ int client_fd;
+
+ client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
+ if (client_fd < 0)
+ {
+ vterr ("vppcom_session_accept()", client_fd);
+ return client_fd;
+ }
+ ts->fd = client_fd;
+ ts->is_open = 1;
+ ts->read = vcl_test_read;
+ ts->write = vcl_test_write;
+
+ return 0;
+}
+
+static const vcl_test_proto_vft_t vcl_test_dtls = {
+ .init = vt_dtls_init,
+ .open = vt_dtls_connect,
+ .listen = vt_dtls_listen,
+ .accept = vt_dtls_accept,
+};
+
+VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_DTLS, vcl_test_dtls);
+
+static int
+vt_quic_init (vcl_test_cfg_t *cfg)
+{
+ vcl_test_main_t *vt = &vcl_test_main;
+
+ if (cfg)
+ vt->cfg = *cfg;
+
+ return vt_add_cert_key_pair ();
+}
+
+static int
+vt_quic_maybe_init_wrk (vcl_test_main_t *vt, vcl_test_wrk_t *wrk,
+ vppcom_endpt_t *endpt)
+{
+ uint32_t size, i, flags, flen;
+ vcl_test_session_t *tq;
+ int rv;
+
+ /* Test already initialized */
+ if (wrk->n_qsessions == vt->cfg.num_test_qsessions)
+ return 0;
+
+ /* Make sure pool is large enough */
+ if (!wrk->qsessions)
+ {
+ wrk->qsessions =
+ calloc (vt->cfg.num_test_qsessions, sizeof (vcl_test_session_t));
+ }
+ else
+ {
+ size = vt->cfg.num_test_qsessions * sizeof (vcl_test_session_t);
+ wrk->qsessions = realloc (wrk->qsessions, size);
+ }
+
+ if (!wrk->qsessions)
+ {
+ vterr ("failed to alloc Qsessions", -errno);
+ return errno;
+ }
+
+ for (i = 0; i < vt->cfg.num_test_qsessions; i++)
+ {
+ tq = &wrk->qsessions[i];
+ tq->fd =
+ vppcom_session_create (VPPCOM_PROTO_QUIC, 0 /* is_nonblocking */);
+ tq->session_index = i;
+ if (tq->fd < 0)
+ {
+ vterr ("vppcom_session_create()", tq->fd);
+ return tq->fd;
+ }
+
+ /* Connect is blocking */
+ rv = vppcom_session_connect (tq->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_connect()", rv);
+ return rv;
+ }
+ flags = O_NONBLOCK;
+ flen = sizeof (flags);
+ vppcom_session_attr (tq->fd, VPPCOM_ATTR_SET_FLAGS, &flags, &flen);
+ vtinf ("Test Qsession %d (fd %d) connected.", i, tq->fd);
+ }
+ wrk->n_qsessions = vt->cfg.num_test_qsessions;
+
+ return 0;
+}
+
+static int
+vt_quic_connect (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ vcl_test_main_t *vt = &vcl_test_main;
+ vcl_test_session_t *tq;
+ vcl_test_wrk_t *wrk;
+ uint32_t wrk_index;
+ int rv;
+
+ wrk_index = vcl_test_worker_index ();
+ wrk = &vt->wrk[wrk_index];
+
+ /* Make sure qsessions are initialized */
+ vt_quic_maybe_init_wrk (vt, wrk, endpt);
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_QUIC, 1 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ /* Choose qession to use for stream */
+ tq = &wrk->qsessions[ts->session_index / vt->cfg.num_test_sessions_perq];
+
+ rv = vppcom_session_stream_connect (ts->fd, tq->fd);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_stream_connect()", rv);
+ return rv;
+ }
+
+ vtinf ("Test session %d (fd %d) connected.", ts->session_index, ts->fd);
+
+ return 0;
+}
+
+static int
+vt_quic_listen (vcl_test_session_t *ts, vppcom_endpt_t *endpt)
+{
+ vcl_test_main_t *vt = &vcl_test_main;
+ uint32_t ckp_len;
+ int rv;
+
+ ts->fd = vppcom_session_create (VPPCOM_PROTO_QUIC, 0 /* is_nonblocking */);
+ if (ts->fd < 0)
+ {
+ vterr ("vppcom_session_create()", ts->fd);
+ return ts->fd;
+ }
+
+ ckp_len = sizeof (vt->ckpair_index);
+ vppcom_session_attr (ts->fd, VPPCOM_ATTR_SET_CKPAIR, &vt->ckpair_index,
+ &ckp_len);
+
+ rv = vppcom_session_bind (ts->fd, endpt);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_bind()", rv);
+ return rv;
+ }
+
+ rv = vppcom_session_listen (ts->fd, 10);
+ if (rv < 0)
+ {
+ vterr ("vppcom_session_listen()", rv);
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+vt_quic_accept (int listen_fd, vcl_test_session_t *ts)
+{
+ int client_fd;
+
+ client_fd = vppcom_session_accept (listen_fd, &ts->endpt, 0);
+ if (client_fd < 0)
+ {
+ vterr ("vppcom_session_accept()", client_fd);
+ return client_fd;
+ }
+ ts->fd = client_fd;
+ ts->is_open = 1;
+ ts->read = vcl_test_read;
+ ts->write = vcl_test_write;
+
+ return 0;
+}
+
+static int
+vt_quic_close (vcl_test_session_t *ts)
+{
+ int listener_fd = vppcom_session_listener (ts->fd);
+
+ if ((vppcom_session_n_accepted (listener_fd) == 0) &
+ vppcom_session_is_connectable_listener (listener_fd))
+ {
+ vtinf ("Connected Listener fd %x has no more sessions", listener_fd);
+ vppcom_session_close (listener_fd);
+ }
+
+ return 0;
+}
+
+static const vcl_test_proto_vft_t vcl_test_quic = {
+ .init = vt_quic_init,
+ .open = vt_quic_connect,
+ .listen = vt_quic_listen,
+ .accept = vt_quic_accept,
+ .close = vt_quic_close,
+};
+
+VCL_TEST_REGISTER_PROTO (VPPCOM_PROTO_QUIC, vcl_test_quic);
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/plugins/hs_apps/vcl/vcl_test_server.c b/src/plugins/hs_apps/vcl/vcl_test_server.c
index b8fa1b7c600..ab0c6014620 100644
--- a/src/plugins/hs_apps/vcl/vcl_test_server.c
+++ b/src/plugins/hs_apps/vcl/vcl_test_server.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -40,7 +40,7 @@ typedef struct
typedef struct
{
uint32_t wrk_index;
- int listen_fd;
+ vcl_test_session_t listener;
int epfd;
struct epoll_event wait_events[VCL_TEST_CFG_MAX_EPOLL_EVENTS];
size_t conn_pool_size;
@@ -53,7 +53,6 @@ typedef struct
{
vcl_test_server_cfg_t cfg;
vcl_test_server_worker_t *workers;
-
vcl_test_session_t *ctrl;
int ctrl_listen_fd;
struct sockaddr_storage servaddr;
@@ -62,7 +61,7 @@ typedef struct
u8 use_ds;
} vcl_test_server_main_t;
-static __thread int __wrk_index = 0;
+vcl_test_main_t vcl_test_main;
static vcl_test_server_main_t vcl_server_main;
@@ -107,6 +106,7 @@ again:
{
wrk->conn_pool[i].endpt.ip = wrk->conn_pool[i].ip;
wrk->conn_pool[i].is_alloc = 1;
+ wrk->conn_pool[i].session_index = i;
return (&wrk->conn_pool[i]);
}
}
@@ -147,8 +147,15 @@ sync_config_and_reply (vcl_test_session_t *conn, vcl_test_cfg_t *rx_cfg)
static void
vts_session_close (vcl_test_session_t *conn)
{
+ vcl_test_server_main_t *vsm = &vcl_server_main;
+ vcl_test_main_t *vt = &vcl_test_main;
+
if (!conn->is_open)
return;
+
+ if (vt->protos[vsm->cfg.proto]->close)
+ vt->protos[vsm->cfg.proto]->close (conn);
+
vppcom_session_close (conn->fd);
conn->is_open = 0;
}
@@ -293,7 +300,7 @@ vts_server_echo (vcl_test_session_t *conn, int rx_bytes)
vtinf ("(fd %d): Echoing back", conn->fd);
nbytes = strlen ((const char *) conn->rxbuf) + 1;
- tx_bytes = vcl_test_write (conn, conn->rxbuf, nbytes);
+ tx_bytes = conn->write (conn, conn->rxbuf, nbytes);
if (tx_bytes >= 0)
vtinf ("(fd %d): TX (%d bytes) - '%s'", conn->fd, tx_bytes, conn->rxbuf);
}
@@ -301,9 +308,11 @@ vts_server_echo (vcl_test_session_t *conn, int rx_bytes)
static vcl_test_session_t *
vts_accept_client (vcl_test_server_worker_t *wrk, int listen_fd)
{
+ vcl_test_server_main_t *vsm = &vcl_server_main;
+ const vcl_test_proto_vft_t *tp;
vcl_test_session_t *conn;
struct epoll_event ev;
- int rv, client_fd;
+ int rv;
conn = conn_pool_alloc (wrk);
if (!conn)
@@ -312,21 +321,16 @@ vts_accept_client (vcl_test_server_worker_t *wrk, int listen_fd)
return 0;
}
- client_fd = vppcom_session_accept (listen_fd, &conn->endpt, 0);
- if (client_fd < 0)
- {
- vterr ("vppcom_session_accept()", client_fd);
- return 0;
- }
- conn->fd = client_fd;
- conn->is_open = 1;
+ tp = vcl_test_main.protos[vsm->cfg.proto];
+ if (tp->accept (listen_fd, conn))
+ return 0;
vtinf ("Got a connection -- fd = %d (0x%08x) on listener fd = %d (0x%08x)",
- client_fd, client_fd, listen_fd, listen_fd);
+ conn->fd, conn->fd, listen_fd, listen_fd);
ev.events = EPOLLIN;
ev.data.u64 = conn - wrk->conn_pool;
- rv = vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, client_fd, &ev);
+ rv = vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, conn->fd, &ev);
if (rv < 0)
{
vterr ("vppcom_epoll_ctl()", rv);
@@ -464,24 +468,10 @@ vcl_test_server_process_opts (vcl_test_server_main_t * vsm, int argc,
vcl_test_init_endpoint_addr (vsm);
}
-static void
-vts_clean_connected_listeners (vcl_test_server_worker_t * wrk,
- int listener_fd)
-{
- if ((vppcom_session_n_accepted (listener_fd) == 0) &
- vppcom_session_is_connectable_listener (listener_fd))
- {
- vtinf ("Connected Listener fd %x has no more sessions", listener_fd);
- vppcom_session_close (listener_fd);
- wrk->nfds--;
- }
-}
-
int
vts_handle_ctrl_cfg (vcl_test_server_worker_t *wrk, vcl_test_cfg_t *rx_cfg,
vcl_test_session_t *conn, int rx_bytes)
{
- int listener_fd;
if (rx_cfg->verbose)
{
vtinf ("(fd %d): Received a cfg msg!", conn->fd);
@@ -499,7 +489,7 @@ vts_handle_ctrl_cfg (vcl_test_server_worker_t *wrk, vcl_test_cfg_t *rx_cfg,
vtinf ("(fd %d): Replying to cfg msg", conn->fd);
vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ );
}
- vcl_test_write (conn, &conn->cfg, sizeof (conn->cfg));
+ conn->write (conn, &conn->cfg, sizeof (conn->cfg));
return -1;
}
@@ -517,8 +507,6 @@ vts_handle_ctrl_cfg (vcl_test_server_worker_t *wrk, vcl_test_cfg_t *rx_cfg,
case VCL_TEST_TYPE_EXIT:
vtinf ("Ctrl session fd %d closing!", conn->fd);
- listener_fd = vppcom_session_listener (conn->fd);
- vts_clean_connected_listeners (wrk, listener_fd);
vts_session_cleanup (conn);
wrk->nfds--;
if (wrk->nfds)
@@ -538,6 +526,8 @@ static void
vts_worker_init (vcl_test_server_worker_t * wrk)
{
vcl_test_server_main_t *vsm = &vcl_server_main;
+ vcl_test_main_t *vt = &vcl_test_main;
+ const vcl_test_proto_vft_t *tp;
struct epoll_event listen_ev;
int rv;
@@ -550,48 +540,9 @@ vts_worker_init (vcl_test_server_worker_t * wrk)
if (vppcom_worker_register ())
vtfail ("vppcom_worker_register()", 1);
- wrk->listen_fd = vppcom_session_create (vsm->cfg.proto,
- 0 /* is_nonblocking */ );
- if (wrk->listen_fd < 0)
- vtfail ("vppcom_session_create()", wrk->listen_fd);
-
- if (vsm->cfg.proto == VPPCOM_PROTO_UDP)
- {
- vppcom_session_attr (wrk->listen_fd, VPPCOM_ATTR_SET_CONNECTED, 0, 0);
- }
-
- if (vsm->cfg.proto == VPPCOM_PROTO_TLS ||
- vsm->cfg.proto == VPPCOM_PROTO_QUIC ||
- vsm->cfg.proto == VPPCOM_PROTO_DTLS)
- {
- vppcom_cert_key_pair_t ckpair;
- uint32_t ckp_len;
- int ckp_index;
-
- vtinf ("Adding tls certs ...");
- ckpair.cert = vcl_test_crt_rsa;
- ckpair.key = vcl_test_key_rsa;
- ckpair.cert_len = vcl_test_crt_rsa_len;
- ckpair.key_len = vcl_test_key_rsa_len;
- ckp_index = vppcom_add_cert_key_pair (&ckpair);
- if (ckp_index < 0)
- vtfail ("vppcom_add_cert_key_pair()", ckp_index);
-
- ckp_len = sizeof (ckp_index);
- vppcom_session_attr (wrk->listen_fd, VPPCOM_ATTR_SET_CKPAIR, &ckp_index,
- &ckp_len);
- }
-
- rv = vppcom_session_bind (wrk->listen_fd, &vsm->cfg.endpt);
- if (rv < 0)
- vtfail ("vppcom_session_bind()", rv);
-
- if (!(vsm->cfg.proto == VPPCOM_PROTO_UDP))
- {
- rv = vppcom_session_listen (wrk->listen_fd, 10);
- if (rv < 0)
- vtfail ("vppcom_session_listen()", rv);
- }
+ tp = vt->protos[vsm->cfg.proto];
+ if ((rv = tp->listen (&wrk->listener, &vsm->cfg.endpt)))
+ vtfail ("proto listen", rv);
/* First worker already has epoll fd */
if (wrk->wrk_index)
@@ -603,13 +554,14 @@ vts_worker_init (vcl_test_server_worker_t * wrk)
listen_ev.events = EPOLLIN;
listen_ev.data.u32 = VCL_TEST_DATA_LISTENER;
- rv = vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, wrk->listen_fd,
- &listen_ev);
+ rv =
+ vppcom_epoll_ctl (wrk->epfd, EPOLL_CTL_ADD, wrk->listener.fd, &listen_ev);
if (rv < 0)
vtfail ("vppcom_epoll_ctl", rv);
vsm->active_workers += 1;
- vtinf ("Waiting for a client to connect on port %d ...", vsm->cfg.port);
+ vtinf ("Waiting for client data connections on port %d ...",
+ ntohs (vsm->cfg.endpt.port));
}
static inline int
@@ -619,7 +571,7 @@ vts_conn_read (vcl_test_session_t *conn)
if (vsm->use_ds)
return vcl_test_read_ds (conn);
else
- return vcl_test_read (conn, conn->rxbuf, conn->rxbuf_size);
+ return conn->read (conn, conn->rxbuf, conn->rxbuf_size);
}
static void *
@@ -628,7 +580,7 @@ vts_worker_loop (void *arg)
vcl_test_server_main_t *vsm = &vcl_server_main;
vcl_test_server_worker_t *wrk = arg;
vcl_test_session_t *conn;
- int i, rx_bytes, num_ev, listener_fd;
+ int i, rx_bytes, num_ev;
vcl_test_cfg_t *rx_cfg;
if (wrk->wrk_index)
@@ -656,8 +608,6 @@ vts_worker_loop (void *arg)
*/
if (wrk->wait_events[i].events & (EPOLLHUP | EPOLLRDHUP))
{
- listener_fd = vppcom_session_listener (conn->fd);
- vts_clean_connected_listeners (wrk, listener_fd);
vts_session_close (conn);
wrk->nfds--;
if (!wrk->nfds)
@@ -684,7 +634,7 @@ vts_worker_loop (void *arg)
}
if (wrk->wait_events[i].data.u32 == VCL_TEST_DATA_LISTENER)
{
- conn = vts_accept_client (wrk, wrk->listen_fd);
+ conn = vts_accept_client (wrk, wrk->listener.fd);
conn->cfg = vsm->ctrl->cfg;
continue;
}
@@ -700,7 +650,7 @@ vts_worker_loop (void *arg)
if (!wrk->wrk_index && conn->fd == vsm->ctrl->fd)
{
- rx_bytes = vcl_test_read (conn, conn->rxbuf, conn->rxbuf_size);
+ rx_bytes = conn->read (conn, conn->rxbuf, conn->rxbuf_size);
rx_cfg = (vcl_test_cfg_t *) conn->rxbuf;
if (rx_cfg->magic == VCL_TEST_CFG_CTRL_MAGIC)
{
@@ -759,7 +709,7 @@ fail:
vsm->worker_fails -= 1;
done:
- vppcom_session_close (wrk->listen_fd);
+ vppcom_session_close (wrk->listener.fd);
if (wrk->conn_pool)
free (wrk->conn_pool);
vsm->active_workers -= 1;
@@ -799,13 +749,14 @@ vts_ctrl_session_init (vcl_test_server_worker_t *wrk)
if (rv < 0)
vtfail ("vppcom_epoll_ctl", rv);
- vtinf ("Waiting for a client to connect on port %d ...", vsm->cfg.port);
+ vtinf ("Waiting for client ctrl connection on port %d ...", vsm->cfg.port);
}
int
main (int argc, char **argv)
{
vcl_test_server_main_t *vsm = &vcl_server_main;
+ vcl_test_main_t *vt = &vcl_test_main;
int rv, i;
clib_mem_init_thread_safe (0, 64 << 20);
@@ -818,6 +769,10 @@ main (int argc, char **argv)
if (rv)
vtfail ("vppcom_app_create()", rv);
+ /* Protos like tls/dtls/quic need init */
+ if (vt->protos[vsm->cfg.proto]->init)
+ vt->protos[vsm->cfg.proto]->init (0);
+
vsm->workers = calloc (vsm->cfg.workers, sizeof (*vsm->workers));
vts_ctrl_session_init (&vsm->workers[0]);