test_spi.c revision fbc6cc04
17d09751dSDmitri Tikhonov/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ 250aadb33SDmitri Tikhonov#include <assert.h> 350aadb33SDmitri Tikhonov#include <errno.h> 450aadb33SDmitri Tikhonov#include <stdio.h> 550aadb33SDmitri Tikhonov#include <stdlib.h> 650aadb33SDmitri Tikhonov#include <string.h> 750aadb33SDmitri Tikhonov#include <sys/queue.h> 8461e84d8SAmol Deshpande#ifndef WIN32 950aadb33SDmitri Tikhonov#include <unistd.h> 10461e84d8SAmol Deshpande#endif 1150aadb33SDmitri Tikhonov 1250aadb33SDmitri Tikhonov#include "lsquic.h" 1350aadb33SDmitri Tikhonov 145392f7a3SLiteSpeed Tech#include "lsquic_int_types.h" 15bfc7bfd8SDmitri Tikhonov#include "lsquic_packet_common.h" 1650aadb33SDmitri Tikhonov#include "lsquic_packet_in.h" 1750aadb33SDmitri Tikhonov#include "lsquic_conn_flow.h" 1850aadb33SDmitri Tikhonov#include "lsquic_sfcw.h" 195392f7a3SLiteSpeed Tech#include "lsquic_varint.h" 205392f7a3SLiteSpeed Tech#include "lsquic_hq.h" 215392f7a3SLiteSpeed Tech#include "lsquic_hash.h" 225392f7a3SLiteSpeed Tech#include "lsquic_conn.h" 2350aadb33SDmitri Tikhonov#include "lsquic_stream.h" 2450aadb33SDmitri Tikhonov#include "lsquic_types.h" 25fbc6cc04SDmitri Tikhonov#include "lsquic_rtt.h" 26fbc6cc04SDmitri Tikhonov#include "lsquic_conn_public.h" 2750aadb33SDmitri Tikhonov#include "lsquic_spi.h" 2850aadb33SDmitri Tikhonov#include "lsquic_logger.h" 2950aadb33SDmitri Tikhonov 3050aadb33SDmitri Tikhonov 3150aadb33SDmitri Tikhonov/* Sharing the same SPI tests safety of reusing the same iterator object 3250aadb33SDmitri Tikhonov * (no need to deinitialize it). 3350aadb33SDmitri Tikhonov */ 3450aadb33SDmitri Tikhonovstatic struct stream_prio_iter spi; 3550aadb33SDmitri Tikhonov 365392f7a3SLiteSpeed Techstatic struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 0); 375392f7a3SLiteSpeed Tech 38fbc6cc04SDmitri Tikhonovstatic struct lsquic_conn_public conn_pub = { .lconn = &lconn, }; 39fbc6cc04SDmitri Tikhonov 4050aadb33SDmitri Tikhonov 4150aadb33SDmitri Tikhonovstatic lsquic_stream_t * 4250aadb33SDmitri Tikhonovnew_stream (unsigned priority) 4350aadb33SDmitri Tikhonov{ 4450aadb33SDmitri Tikhonov lsquic_stream_t *stream = calloc(1, sizeof(*stream)); 4550aadb33SDmitri Tikhonov stream->sm_priority = priority; 4650aadb33SDmitri Tikhonov return stream; 4750aadb33SDmitri Tikhonov} 4850aadb33SDmitri Tikhonov 4950aadb33SDmitri Tikhonov 5050aadb33SDmitri Tikhonovstatic void 5150aadb33SDmitri Tikhonovfree_streams (lsquic_stream_t **streams, size_t count) 5250aadb33SDmitri Tikhonov{ 5350aadb33SDmitri Tikhonov size_t n; 5450aadb33SDmitri Tikhonov for (n = 0; n < count; ++n) 5550aadb33SDmitri Tikhonov free(streams[n]); 5650aadb33SDmitri Tikhonov} 5750aadb33SDmitri Tikhonov 5850aadb33SDmitri Tikhonov 5950aadb33SDmitri Tikhonovstatic void 6050aadb33SDmitri Tikhonovtest_same_priority (unsigned priority) 6150aadb33SDmitri Tikhonov{ 6250aadb33SDmitri Tikhonov lsquic_stream_t *stream_arr[4] = { 6350aadb33SDmitri Tikhonov new_stream(priority), 6450aadb33SDmitri Tikhonov new_stream(priority), 6550aadb33SDmitri Tikhonov new_stream(priority), 6650aadb33SDmitri Tikhonov new_stream(priority), 6750aadb33SDmitri Tikhonov }; 6850aadb33SDmitri Tikhonov struct lsquic_streams_tailq streams; 6950aadb33SDmitri Tikhonov lsquic_stream_t *stream; 7050aadb33SDmitri Tikhonov 7150aadb33SDmitri Tikhonov TAILQ_INIT(&streams); 72c51ce338SDmitri Tikhonov TAILQ_INSERT_TAIL(&streams, stream_arr[0], next_write_stream); 73c51ce338SDmitri Tikhonov TAILQ_INSERT_TAIL(&streams, stream_arr[1], next_write_stream); 74c51ce338SDmitri Tikhonov TAILQ_INSERT_TAIL(&streams, stream_arr[2], next_write_stream); 75c51ce338SDmitri Tikhonov TAILQ_INSERT_TAIL(&streams, stream_arr[3], next_write_stream); 7650aadb33SDmitri Tikhonov 77c51ce338SDmitri Tikhonov lsquic_spi_init(&spi, TAILQ_FIRST(&streams), 7850aadb33SDmitri Tikhonov TAILQ_LAST(&streams, lsquic_streams_tailq), 79c51ce338SDmitri Tikhonov (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_write_stream), 80fbc6cc04SDmitri Tikhonov &conn_pub, __func__, NULL, NULL); 8150aadb33SDmitri Tikhonov 8250aadb33SDmitri Tikhonov stream = lsquic_spi_first(&spi); 8350aadb33SDmitri Tikhonov assert(stream == stream_arr[0]); 8450aadb33SDmitri Tikhonov stream = lsquic_spi_next(&spi); 8550aadb33SDmitri Tikhonov assert(stream == stream_arr[1]); 8650aadb33SDmitri Tikhonov stream = lsquic_spi_next(&spi); 8750aadb33SDmitri Tikhonov assert(stream == stream_arr[2]); 8850aadb33SDmitri Tikhonov stream = lsquic_spi_next(&spi); 8950aadb33SDmitri Tikhonov assert(stream == stream_arr[3]); 9050aadb33SDmitri Tikhonov stream = lsquic_spi_next(&spi); 9150aadb33SDmitri Tikhonov assert(stream == NULL); 9250aadb33SDmitri Tikhonov 9350aadb33SDmitri Tikhonov /* Test reinitialization: */ 94c51ce338SDmitri Tikhonov lsquic_spi_init(&spi, stream_arr[0], stream_arr[1], 95c51ce338SDmitri Tikhonov (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_write_stream), 96fbc6cc04SDmitri Tikhonov &conn_pub, __func__, NULL, NULL); 9750aadb33SDmitri Tikhonov stream = lsquic_spi_first(&spi); 9850aadb33SDmitri Tikhonov assert(stream == stream_arr[0]); 9950aadb33SDmitri Tikhonov stream = lsquic_spi_next(&spi); 10050aadb33SDmitri Tikhonov assert(stream == stream_arr[1]); 10150aadb33SDmitri Tikhonov stream = lsquic_spi_next(&spi); 10250aadb33SDmitri Tikhonov assert(stream == NULL); 10350aadb33SDmitri Tikhonov 10450aadb33SDmitri Tikhonov free_streams(stream_arr, sizeof(stream_arr) / sizeof(stream_arr[0])); 10550aadb33SDmitri Tikhonov} 10650aadb33SDmitri Tikhonov 10750aadb33SDmitri Tikhonov 10850aadb33SDmitri Tikhonovstatic void 10950aadb33SDmitri Tikhonovtest_different_priorities (int *priority) 11050aadb33SDmitri Tikhonov{ 11150aadb33SDmitri Tikhonov struct lsquic_streams_tailq streams; 11250aadb33SDmitri Tikhonov lsquic_stream_t *stream; 11350aadb33SDmitri Tikhonov int prio, prev_prio, count, n_streams = 0; 11450aadb33SDmitri Tikhonov 11550aadb33SDmitri Tikhonov TAILQ_INIT(&streams); 11650aadb33SDmitri Tikhonov 11750aadb33SDmitri Tikhonov for ( ; *priority >= 0; ++priority) 11850aadb33SDmitri Tikhonov { 11950aadb33SDmitri Tikhonov assert(*priority < 256); 12050aadb33SDmitri Tikhonov stream = new_stream(*priority); 12150aadb33SDmitri Tikhonov TAILQ_INSERT_TAIL(&streams, stream, next_send_stream); 12250aadb33SDmitri Tikhonov ++n_streams; 12350aadb33SDmitri Tikhonov } 12450aadb33SDmitri Tikhonov 125c51ce338SDmitri Tikhonov lsquic_spi_init(&spi, TAILQ_FIRST(&streams), 12650aadb33SDmitri Tikhonov TAILQ_LAST(&streams, lsquic_streams_tailq), 12750aadb33SDmitri Tikhonov (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_send_stream), 128fbc6cc04SDmitri Tikhonov &conn_pub, __func__, NULL, NULL); 12950aadb33SDmitri Tikhonov for (prev_prio = -1, count = 0, stream = lsquic_spi_first(&spi); stream; 13050aadb33SDmitri Tikhonov stream = lsquic_spi_next(&spi), ++count) 13150aadb33SDmitri Tikhonov { 13250aadb33SDmitri Tikhonov prio = stream->sm_priority; 13350aadb33SDmitri Tikhonov assert(prio >= prev_prio); 13450aadb33SDmitri Tikhonov if (prio > prev_prio) 13550aadb33SDmitri Tikhonov prev_prio = prio; 13650aadb33SDmitri Tikhonov } 13750aadb33SDmitri Tikhonov 13850aadb33SDmitri Tikhonov assert(count == n_streams); 13950aadb33SDmitri Tikhonov 14050aadb33SDmitri Tikhonov while ((stream = TAILQ_FIRST(&streams))) 14150aadb33SDmitri Tikhonov { 14250aadb33SDmitri Tikhonov TAILQ_REMOVE(&streams, stream, next_send_stream); 14350aadb33SDmitri Tikhonov free(stream); 14450aadb33SDmitri Tikhonov } 14550aadb33SDmitri Tikhonov} 14650aadb33SDmitri Tikhonov 14750aadb33SDmitri Tikhonov 148c51ce338SDmitri Tikhonovstruct stream_info 14950aadb33SDmitri Tikhonov{ 150c51ce338SDmitri Tikhonov uint32_t stream_id; 151a0e1aeeeSDmitri Tikhonov enum stream_b_flags bflags; 152c51ce338SDmitri Tikhonov unsigned char prio; 15350aadb33SDmitri Tikhonov}; 15450aadb33SDmitri Tikhonov 15550aadb33SDmitri Tikhonov 156c51ce338SDmitri Tikhonovconst struct stream_info infos1[] = { 1577a8b2eceSDmitri Tikhonov { 1, SMBF_CRITICAL, 0, }, 1587a8b2eceSDmitri Tikhonov { 3, SMBF_CRITICAL, 0, }, 159a0e1aeeeSDmitri Tikhonov { 5, 0, 0, }, 160a0e1aeeeSDmitri Tikhonov { 7, 0, 1, }, 161a0e1aeeeSDmitri Tikhonov { 127, 0, 200, }, 162c51ce338SDmitri Tikhonov}; 16350aadb33SDmitri Tikhonov 16450aadb33SDmitri Tikhonov 165c51ce338SDmitri Tikhonovconst struct stream_info infos2[] = { 1667a8b2eceSDmitri Tikhonov { 1, SMBF_CRITICAL, 0, }, 1677a8b2eceSDmitri Tikhonov { 3, SMBF_CRITICAL, 0, }, 168a0e1aeeeSDmitri Tikhonov { 5, 0, 4, }, 169a0e1aeeeSDmitri Tikhonov { 7, 0, 1, }, 170a0e1aeeeSDmitri Tikhonov { 127, 0, 200, }, 171a0e1aeeeSDmitri Tikhonov}; 172a0e1aeeeSDmitri Tikhonov 173a0e1aeeeSDmitri Tikhonov 174a0e1aeeeSDmitri Tikhonovconst struct stream_info infos3[] = { 175a0e1aeeeSDmitri Tikhonov { 0, 0, 0, }, 176c51ce338SDmitri Tikhonov}; 17750aadb33SDmitri Tikhonov 17850aadb33SDmitri Tikhonov 179c51ce338SDmitri Tikhonovstruct drop_test 180c51ce338SDmitri Tikhonov{ 181c51ce338SDmitri Tikhonov const struct stream_info *infos; 182c51ce338SDmitri Tikhonov unsigned n_infos; 183c51ce338SDmitri Tikhonov unsigned high_streams; 184c51ce338SDmitri Tikhonov}; 18550aadb33SDmitri Tikhonov 18650aadb33SDmitri Tikhonov 187c51ce338SDmitri Tikhonovstatic const struct drop_test drop_tests[] = { 188c51ce338SDmitri Tikhonov { infos1, 5, 0x7, }, 189c51ce338SDmitri Tikhonov { infos2, 5, 0x3, }, 190a0e1aeeeSDmitri Tikhonov { infos3, 1, 0x0, }, 191c51ce338SDmitri Tikhonov}; 19250aadb33SDmitri Tikhonov 19350aadb33SDmitri Tikhonov 19450aadb33SDmitri Tikhonovstatic void 195c51ce338SDmitri Tikhonovtest_drop (const struct drop_test *test) 19650aadb33SDmitri Tikhonov{ 197c51ce338SDmitri Tikhonov 198c51ce338SDmitri Tikhonov struct lsquic_stream stream_arr[20]; 199c51ce338SDmitri Tikhonov unsigned seen_mask, n; 20050aadb33SDmitri Tikhonov struct lsquic_streams_tailq streams; 201c51ce338SDmitri Tikhonov lsquic_stream_t *stream; 202c51ce338SDmitri Tikhonov int drop_high; 20350aadb33SDmitri Tikhonov 20450aadb33SDmitri Tikhonov TAILQ_INIT(&streams); 205c51ce338SDmitri Tikhonov for (n = 0; n < test->n_infos; ++n) 20650aadb33SDmitri Tikhonov { 207c51ce338SDmitri Tikhonov stream_arr[n].sm_priority = test->infos[n].prio; 208c51ce338SDmitri Tikhonov stream_arr[n].id = test->infos[n].stream_id; 209a0e1aeeeSDmitri Tikhonov stream_arr[n].sm_bflags = SMBF_USE_HEADERS | test->infos[n].bflags; 21050aadb33SDmitri Tikhonov } 21150aadb33SDmitri Tikhonov 212c51ce338SDmitri Tikhonov for (drop_high = 0; drop_high < 2; ++drop_high) 21350aadb33SDmitri Tikhonov { 214c51ce338SDmitri Tikhonov TAILQ_INIT(&streams); 215c51ce338SDmitri Tikhonov for (n = 0; n < test->n_infos; ++n) 216c51ce338SDmitri Tikhonov TAILQ_INSERT_TAIL(&streams, &stream_arr[n], next_write_stream); 217c51ce338SDmitri Tikhonov 218c51ce338SDmitri Tikhonov lsquic_spi_init(&spi, TAILQ_FIRST(&streams), 219c51ce338SDmitri Tikhonov TAILQ_LAST(&streams, lsquic_streams_tailq), 220c51ce338SDmitri Tikhonov (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_write_stream), 221fbc6cc04SDmitri Tikhonov &conn_pub, __func__, NULL, NULL); 222c51ce338SDmitri Tikhonov 223c51ce338SDmitri Tikhonov if (drop_high) 224c51ce338SDmitri Tikhonov lsquic_spi_drop_high(&spi); 225c51ce338SDmitri Tikhonov else 226c51ce338SDmitri Tikhonov lsquic_spi_drop_non_high(&spi); 227c51ce338SDmitri Tikhonov 228c51ce338SDmitri Tikhonov seen_mask = 0; 229c51ce338SDmitri Tikhonov for (stream = lsquic_spi_first(&spi); stream; 230c51ce338SDmitri Tikhonov stream = lsquic_spi_next(&spi)) 231c51ce338SDmitri Tikhonov seen_mask |= 1 << (stream - stream_arr); 232c51ce338SDmitri Tikhonov 233a0e1aeeeSDmitri Tikhonov if (test->n_infos == 1) 234a0e1aeeeSDmitri Tikhonov assert(seen_mask == (1u << test->infos[0].stream_id)); 235a0e1aeeeSDmitri Tikhonov else if (drop_high) 236c51ce338SDmitri Tikhonov assert((((1 << test->n_infos) - 1) & ~test->high_streams) == seen_mask); 237c51ce338SDmitri Tikhonov else 238c51ce338SDmitri Tikhonov assert(test->high_streams == seen_mask); 23950aadb33SDmitri Tikhonov } 24050aadb33SDmitri Tikhonov} 24150aadb33SDmitri Tikhonov 24250aadb33SDmitri Tikhonov 24319f667fbSDmitri Tikhonov#define MAGIC 0x12312312U 24419f667fbSDmitri Tikhonov 24519f667fbSDmitri Tikhonovstruct my_filter_ctx 24619f667fbSDmitri Tikhonov{ 24719f667fbSDmitri Tikhonov unsigned magic; 24819f667fbSDmitri Tikhonov}; 24919f667fbSDmitri Tikhonov 25019f667fbSDmitri Tikhonov 25119f667fbSDmitri Tikhonovstatic int 25219f667fbSDmitri Tikhonovfilter_out_odd_priorities (void *ctx, lsquic_stream_t *stream) 25319f667fbSDmitri Tikhonov{ 25419f667fbSDmitri Tikhonov struct my_filter_ctx *fctx = ctx; 25519f667fbSDmitri Tikhonov assert(fctx->magic == MAGIC); 25619f667fbSDmitri Tikhonov return 0 == (stream->sm_priority & 1); 25719f667fbSDmitri Tikhonov} 25819f667fbSDmitri Tikhonov 25919f667fbSDmitri Tikhonov 26019f667fbSDmitri Tikhonovstatic void 26119f667fbSDmitri Tikhonovtest_different_priorities_filter_odd (int *priority) 26219f667fbSDmitri Tikhonov{ 26319f667fbSDmitri Tikhonov struct lsquic_streams_tailq streams; 26419f667fbSDmitri Tikhonov lsquic_stream_t *stream; 26519f667fbSDmitri Tikhonov int prio, prev_prio, count, n_streams = 0; 26619f667fbSDmitri Tikhonov 26719f667fbSDmitri Tikhonov TAILQ_INIT(&streams); 26819f667fbSDmitri Tikhonov 26919f667fbSDmitri Tikhonov for ( ; *priority >= 0; ++priority) 27019f667fbSDmitri Tikhonov { 27119f667fbSDmitri Tikhonov assert(*priority < 256); 27219f667fbSDmitri Tikhonov stream = new_stream(*priority); 27319f667fbSDmitri Tikhonov TAILQ_INSERT_TAIL(&streams, stream, next_send_stream); 27419f667fbSDmitri Tikhonov ++n_streams; 27519f667fbSDmitri Tikhonov } 27619f667fbSDmitri Tikhonov 27719f667fbSDmitri Tikhonov struct my_filter_ctx my_filter_ctx = { MAGIC }; 27819f667fbSDmitri Tikhonov 27919f667fbSDmitri Tikhonov lsquic_spi_init(&spi, TAILQ_FIRST(&streams), 28019f667fbSDmitri Tikhonov TAILQ_LAST(&streams, lsquic_streams_tailq), 28119f667fbSDmitri Tikhonov (uintptr_t) &TAILQ_NEXT((lsquic_stream_t *) NULL, next_send_stream), 282fbc6cc04SDmitri Tikhonov &conn_pub, __func__, filter_out_odd_priorities, &my_filter_ctx); 28319f667fbSDmitri Tikhonov 28419f667fbSDmitri Tikhonov for (prev_prio = -1, count = 0, stream = lsquic_spi_first(&spi); stream; 28519f667fbSDmitri Tikhonov stream = lsquic_spi_next(&spi), ++count) 28619f667fbSDmitri Tikhonov { 28719f667fbSDmitri Tikhonov prio = stream->sm_priority; 28819f667fbSDmitri Tikhonov assert(0 == (prio & 1)); 28919f667fbSDmitri Tikhonov assert(prio >= prev_prio); 29019f667fbSDmitri Tikhonov if (prio > prev_prio) 29119f667fbSDmitri Tikhonov prev_prio = prio; 29219f667fbSDmitri Tikhonov } 29319f667fbSDmitri Tikhonov 29419f667fbSDmitri Tikhonov assert(count < n_streams); 29519f667fbSDmitri Tikhonov 29619f667fbSDmitri Tikhonov while ((stream = TAILQ_FIRST(&streams))) 29719f667fbSDmitri Tikhonov { 29819f667fbSDmitri Tikhonov TAILQ_REMOVE(&streams, stream, next_send_stream); 29919f667fbSDmitri Tikhonov free(stream); 30019f667fbSDmitri Tikhonov } 30119f667fbSDmitri Tikhonov} 30219f667fbSDmitri Tikhonov 30319f667fbSDmitri Tikhonov 30450aadb33SDmitri Tikhonovint 30550aadb33SDmitri Tikhonovmain (int argc, char **argv) 30650aadb33SDmitri Tikhonov{ 30750aadb33SDmitri Tikhonov lsquic_log_to_fstream(stderr, LLTS_NONE); 30850aadb33SDmitri Tikhonov lsq_log_levels[LSQLM_SPI] = LSQ_LOG_DEBUG; 30950aadb33SDmitri Tikhonov 31050aadb33SDmitri Tikhonov test_same_priority(0); 31150aadb33SDmitri Tikhonov test_same_priority(99); 31250aadb33SDmitri Tikhonov test_same_priority(255); 31350aadb33SDmitri Tikhonov 31450aadb33SDmitri Tikhonov { 31550aadb33SDmitri Tikhonov int prio[] = { 1, 2, 3, 4, 5, 6, 7, -1 }; 31650aadb33SDmitri Tikhonov test_different_priorities(prio); 31750aadb33SDmitri Tikhonov } 31850aadb33SDmitri Tikhonov 31950aadb33SDmitri Tikhonov { 32050aadb33SDmitri Tikhonov int prio[] = { 7, 6, 5, 4, 3, 2, 1, -1 }; 32150aadb33SDmitri Tikhonov test_different_priorities(prio); 32250aadb33SDmitri Tikhonov } 32350aadb33SDmitri Tikhonov 32450aadb33SDmitri Tikhonov { 32550aadb33SDmitri Tikhonov int prio[] = { 7, 100, 80, 1, 0, 0, 20, 23, 255, 30, 2, 101, -1 }; 32650aadb33SDmitri Tikhonov test_different_priorities(prio); 32750aadb33SDmitri Tikhonov } 32850aadb33SDmitri Tikhonov 32950aadb33SDmitri Tikhonov { 33050aadb33SDmitri Tikhonov int prio[] = { 200, 202, 240, 201, 200, 199, -1 }; 33150aadb33SDmitri Tikhonov test_different_priorities(prio); 33250aadb33SDmitri Tikhonov } 33350aadb33SDmitri Tikhonov 33419f667fbSDmitri Tikhonov { 33519f667fbSDmitri Tikhonov int prio[] = { 200, 202, 240, 201, 200, 199, -1 }; 33619f667fbSDmitri Tikhonov test_different_priorities_filter_odd(prio); 33719f667fbSDmitri Tikhonov } 33819f667fbSDmitri Tikhonov 339c51ce338SDmitri Tikhonov unsigned n; 340c51ce338SDmitri Tikhonov for (n = 0; n < sizeof(drop_tests) / sizeof(drop_tests[0]); ++n) 341c51ce338SDmitri Tikhonov test_drop(&drop_tests[n]); 34250aadb33SDmitri Tikhonov 34350aadb33SDmitri Tikhonov return 0; 34450aadb33SDmitri Tikhonov} 345