diff options
author | Tomas Mraz <tomas@openssl.org> | 2024-02-14 12:45:15 +0100 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2024-03-15 10:19:19 +0100 |
commit | b7de38e84c13bbf56a9703fb600f925b86a9a28d (patch) | |
tree | a65c1789b9cc9a197fafe8e72505d36764a85dbe | |
parent | 37ffd4a1fa02b37919b5c7a8059ba57d3c49b1f0 (diff) |
Add a test using the bandwidth limit filter
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23588)
-rw-r--r-- | test/helpers/quictestlib.c | 46 | ||||
-rw-r--r-- | test/helpers/quictestlib.h | 14 | ||||
-rw-r--r-- | test/quicapitest.c | 93 |
3 files changed, 153 insertions, 0 deletions
diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index 403e1f4384..0454e332cf 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -80,6 +80,7 @@ static void qtest_reset_time(void); static int using_fake_time = 0; static OSSL_TIME fake_now; static CRYPTO_RWLOCK *fake_now_lock = NULL; +static OSSL_TIME start_time; static OSSL_TIME fake_now_cb(void *arg) { @@ -220,6 +221,7 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, if ((flags & QTEST_FLAG_NOISE) != 0) { BIO *noisebio; + struct bio_noise_now_cb_st now_cb = { fake_now_cb, NULL }; /* * It is an error to not have a QTEST_FAULT object when introducing noise @@ -232,12 +234,22 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, if (!TEST_ptr(noisebio)) goto err; cbio = BIO_push(noisebio, cbio); + if ((flags & QTEST_FLAG_FAKE_TIME) != 0) { + if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_SET_NOW_CB, + 0, &now_cb), 1)) + goto err; + } noisebio = BIO_new(bio_f_noisy_dgram_filter()); if (!TEST_ptr(noisebio)) goto err; sbio = BIO_push(noisebio, sbio); + if ((flags & QTEST_FLAG_FAKE_TIME) != 0) { + if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_SET_NOW_CB, + 0, &now_cb), 1)) + goto err; + } /* * TODO(QUIC SERVER): * Currently the simplistic handler of the quic tserver cannot cope @@ -364,6 +376,16 @@ static void qtest_reset_time(void) qtest_add_time(1); } +void qtest_start_stopwatch(void) +{ + start_time = qtest_get_time(); +} + +uint64_t qtest_get_stopwatch_time(void) +{ + return ossl_time2ms(ossl_time_subtract(qtest_get_time(), start_time)); +} + QTEST_FAULT *qtest_create_injector(QUIC_TSERVER *ts) { QTEST_FAULT *f; @@ -1207,6 +1229,30 @@ int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen) return 1; } +int qtest_fault_set_bw_limit(QTEST_FAULT *fault, + size_t ctos_bw, size_t stoc_bw, + int noise_rate) +{ + BIO *sbio = fault->noiseargs.sbio; + BIO *cbio = fault->noiseargs.cbio; + + if (!TEST_ptr(sbio) || !TEST_ptr(cbio)) + return 0; + if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_RATE, noise_rate, NULL), 1)) + return 0; + if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_RATE, noise_rate, NULL), 1)) + return 0; + /* We set the bandwidth limit on the sending side */ + if (!TEST_int_eq(BIO_ctrl(cbio, BIO_CTRL_NOISE_SEND_BANDWIDTH, + (long)ctos_bw, NULL), 1)) + return 0; + if (!TEST_int_eq(BIO_ctrl(sbio, BIO_CTRL_NOISE_SEND_BANDWIDTH, + (long)stoc_bw, NULL), 1)) + return 0; + return 1; +} + + int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src) { /* diff --git a/test/helpers/quictestlib.h b/test/helpers/quictestlib.h index 228d396f41..d9d01f7fc1 100644 --- a/test/helpers/quictestlib.h +++ b/test/helpers/quictestlib.h @@ -49,6 +49,11 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, /* Where QTEST_FLAG_FAKE_TIME is used, add millis to the current time */ void qtest_add_time(uint64_t millis); +/* Starts time measurement */ +void qtest_start_stopwatch(void); +/* Returns the duration from the start in millis */ +uint64_t qtest_get_stopwatch_time(void); + QTEST_FAULT *qtest_create_injector(QUIC_TSERVER *ts); BIO_METHOD *qtest_get_bio_method(void); @@ -244,6 +249,15 @@ int qtest_fault_set_datagram_listener(QTEST_FAULT *fault, */ int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen); +/* + * Set bandwidth and noise rate on noisy dgram filter. + * Arguments with values of 0 mean no limit/no noise. + */ + +int qtest_fault_set_bw_limit(QTEST_FAULT *fault, + size_t ctos_bw, size_t stoc_bw, + int noise_rate); + /* Copy a BIO_MSG */ int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src); diff --git a/test/quicapitest.c b/test/quicapitest.c index 098e1a9b39..2b6c2fc6e0 100644 --- a/test/quicapitest.c +++ b/test/quicapitest.c @@ -1566,6 +1566,98 @@ static int test_noisy_dgram(int idx) return testresult; } +/* + * Create a connection and send some big data using a transport with limited bandwidth. + */ + +#define TEST_TRANSFER_DATA_SIZE (2*1024*1024) /* 2 MBytes */ +#define TEST_SINGLE_WRITE_SIZE (16*1024) /* 16 kBytes */ +#define TEST_BW_LIMIT 1000 /* 1000 Bytes/ms */ +static int test_bw_limit(void) +{ + SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()); + SSL *clientquic = NULL; + QUIC_TSERVER *qtserv = NULL; + int testresult = 0; + unsigned char *msg = NULL, *recvbuf = NULL; + size_t sendlen = TEST_TRANSFER_DATA_SIZE; + size_t recvlen = TEST_TRANSFER_DATA_SIZE; + size_t written, readbytes; + int flags = QTEST_FLAG_NOISE | QTEST_FLAG_FAKE_TIME; + QTEST_FAULT *fault = NULL; + uint64_t real_bw; + + if (!TEST_ptr(cctx) + || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert, + privkey, flags, + &qtserv, + &clientquic, &fault, NULL))) + goto err; + + if (!TEST_ptr(msg = OPENSSL_zalloc(TEST_SINGLE_WRITE_SIZE)) + || !TEST_ptr(recvbuf = OPENSSL_zalloc(TEST_SINGLE_WRITE_SIZE))) + goto err; + + /* Set BW to 1000 Bytes/ms -> 1MByte/s both ways */ + if (!TEST_true(qtest_fault_set_bw_limit(fault, 1000, 1000, 0))) + goto err; + + if (!TEST_true(qtest_create_quic_connection(qtserv, clientquic))) + goto err; + + qtest_start_stopwatch(); + + while (recvlen > 0) { + qtest_add_time(1); + + if (sendlen > 0) { + if (!SSL_write_ex(clientquic, msg, + sendlen > TEST_SINGLE_WRITE_SIZE ? TEST_SINGLE_WRITE_SIZE + : sendlen, + &written)) { + TEST_info("Retrying to send: %llu", (unsigned long long) sendlen); + if (!TEST_int_eq(SSL_get_error(clientquic, 0), SSL_ERROR_WANT_WRITE)) + goto err; + } else { + sendlen -= written; + TEST_info("Remaining to send: %llu", (unsigned long long) sendlen); + } + } else { + SSL_handle_events(clientquic); + } + + if (ossl_quic_tserver_read(qtserv, 0, recvbuf, + recvlen > TEST_SINGLE_WRITE_SIZE ? TEST_SINGLE_WRITE_SIZE + : recvlen, + &readbytes) + && readbytes > 1) { + recvlen -= readbytes; + TEST_info("Remaining to recv: %llu", (unsigned long long) recvlen); + } else { + TEST_info("No progress on recv: %llu", (unsigned long long) recvlen); + } + ossl_quic_tserver_tick(qtserv); + } + real_bw = TEST_TRANSFER_DATA_SIZE / qtest_get_stopwatch_time(); + + TEST_info("BW limit: %d Bytes/ms Real bandwidth reached: %llu Bytes/ms", + TEST_BW_LIMIT, (unsigned long long)real_bw); + + if (!TEST_uint64_t_lt(real_bw, TEST_BW_LIMIT)) + goto err; + + testresult = 1; + err: + OPENSSL_free(msg); + OPENSSL_free(recvbuf); + ossl_quic_tserver_free(qtserv); + SSL_free(clientquic); + SSL_CTX_free(cctx); + qtest_fault_free(fault); + + return testresult; +} + enum { TPARAM_OP_DUP, TPARAM_OP_DROP, @@ -2165,6 +2257,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_client_auth, 3); ADD_ALL_TESTS(test_alpn, 2); ADD_ALL_TESTS(test_noisy_dgram, 2); + ADD_TEST(test_bw_limit); ADD_TEST(test_get_shutdown); ADD_ALL_TESTS(test_tparam, OSSL_NELEM(tparam_tests)); |