summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorMathiasRaoul <mathias.raoul@gmail.com>2019-12-06 15:38:56 +0000
committerNathan Skrzypczak <nathan.skrzypczak@gmail.com>2019-12-11 10:58:52 +0100
commit1802fcc5f1c06b78b02d5c0f1a415e0976fa14c3 (patch)
tree1b6d474986bc8a56cff19cf6debc9069e0228786 /src/plugins
parent5de4fb7076a46ab75e2d3c30079dd6639af16a86 (diff)
quic: add more detailed statistics
Type: feature Change-Id: I3df7b054ec08c7b307413d24468fc3df6a5aacc3 Signed-off-by: MathiasRaoul <mathias.raoul@gmail.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/quic/quic.c61
-rw-r--r--src/plugins/quic/quic_error.def6
2 files changed, 67 insertions, 0 deletions
diff --git a/src/plugins/quic/quic.c b/src/plugins/quic/quic.c
index 54a2d9019ba..0a70dd2e02a 100644
--- a/src/plugins/quic/quic.c
+++ b/src/plugins/quic/quic.c
@@ -549,6 +549,7 @@ quic_on_stream_destroy (quicly_stream_t * stream, int err)
stream_session->session_state = SESSION_STATE_CLOSED;
session_transport_delete_notify (&sctx->connection);
+ quic_increment_counter (QUIC_ERROR_CLOSED_STREAM, 1);
quic_ctx_free (sctx);
clib_mem_free (stream->data);
}
@@ -1017,6 +1018,8 @@ quic_connect_stream (session_t * quic_session, u32 opaque)
QUIC_DBG (2, "Stream open failed with %d", rv);
return -1;
}
+ quic_increment_counter (QUIC_ERROR_OPENED_STREAM, 1);
+
sctx->stream = stream;
QUIC_DBG (2, "Opened stream %d, creating session", stream->stream_id);
@@ -1053,6 +1056,7 @@ quic_connect_stream (session_t * quic_session, u32 opaque)
if (app_worker_connect_notify (app_wrk, stream_session, opaque))
{
QUIC_ERR ("failed to notify app");
+ quic_increment_counter (QUIC_ERROR_CLOSED_STREAM, 1);
quicly_reset_stream (stream, QUIC_APP_CONNECT_NOTIFY_ERROR);
return -1;
}
@@ -1157,6 +1161,8 @@ quic_proto_on_close (u32 ctx_index, u32 thread_index)
quicly_conn_t *conn = ctx->conn;
/* Start connection closing. Keep sending packets until quicly_send
returns QUICLY_ERROR_FREE_CONNECTION */
+
+ quic_increment_counter (QUIC_ERROR_CLOSED_CONNECTION, 1);
quicly_close (conn, QUIC_APP_ERROR_CLOSE_NOTIFY, "Closed by peer");
/* This also causes all streams to be closed (and the cb called) */
quic_send_packets (ctx);
@@ -2319,12 +2325,67 @@ quic_format_ctx_stat (u8 * s, va_list * args)
return s;
}
+u64
+quic_get_counter_value (u32 event_code)
+{
+ vlib_node_t *n;
+ vlib_main_t *vm;
+ vlib_error_main_t *em;
+
+ u32 code, i;
+ u64 c, sum = 0;
+ int index = 0;
+
+ vm = vlib_get_main ();
+ em = &vm->error_main;
+ n = vlib_get_node (vm, quic_input_node.index);
+ code = event_code;
+ /* *INDENT-OFF* */
+ foreach_vlib_main(({
+ em = &this_vlib_main->error_main;
+ i = n->error_heap_index + code;
+ c = em->counters[i];
+
+ if (i < vec_len (em->counters_last_clear))
+ c -= em->counters_last_clear[i];
+ sum += c;
+ index++;
+ }));
+ /* *INDENT-ON* */
+ return sum;
+}
+
static clib_error_t *
quic_plugin_showstats_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
quic_main_t *qm = &quic_main;
+
+ vlib_cli_output (vm, "\n-------- Connections --------\n");
+ vlib_cli_output (vm, "%=20s%10Ld%=20s%10Ld", "Opened:",
+ quic_get_counter_value (QUIC_ERROR_OPENED_CONNECTION),
+ "Closed:",
+ quic_get_counter_value (QUIC_ERROR_CLOSED_CONNECTION));
+
+ vlib_cli_output (vm, "\n---------- Streams ----------\n");
+ vlib_cli_output (vm, "%=20s%10Ld%=20s%10Ld", "Opened:",
+ quic_get_counter_value (QUIC_ERROR_OPENED_STREAM),
+ "Closed:",
+ quic_get_counter_value (QUIC_ERROR_CLOSED_STREAM));
+
+ vlib_cli_output (vm, "\n--------- RX Packets ---------\n");
+ vlib_cli_output (vm, "%=20s%10Ld", "Total:",
+ quic_get_counter_value (QUIC_ERROR_RX_PACKETS));
+ vlib_cli_output (vm, "%=20s%10Ld", "0RTT :",
+ quic_get_counter_value (QUIC_ERROR_ZERO_RTT_RX_PACKETS));
+ vlib_cli_output (vm, "%=20s%10Ld", "1RTT :",
+ quic_get_counter_value (QUIC_ERROR_ONE_RTT_RX_PACKETS));
+
+ vlib_cli_output (vm, "\n-------- TX Packets --------\n");
+ vlib_cli_output (vm, "%=20s%10Ld", "Total:",
+ quic_get_counter_value (QUIC_ERROR_TX_PACKETS));
+
quic_ctx_t *ctx = NULL;
u32 num_workers = vlib_num_workers ();
diff --git a/src/plugins/quic/quic_error.def b/src/plugins/quic/quic_error.def
index ecfcd677b46..2d2a5d6c8b2 100644
--- a/src/plugins/quic/quic_error.def
+++ b/src/plugins/quic/quic_error.def
@@ -18,5 +18,11 @@
quic_error (NONE, "no error")
quic_error (TX_PACKETS, "quic TX packets")
quic_error (RX_PACKETS, "quic RX packets")
+quic_error (OPENED_STREAM, "quic opened streams number")
+quic_error (CLOSED_STREAM, "quic closed streams number")
+quic_error (OPENED_CONNECTION, "quic opened connections number")
+quic_error (CLOSED_CONNECTION, "quic closed connections number")
+quic_error (ZERO_RTT_RX_PACKETS, "0RTT RX packets number")
+quic_error (ONE_RTT_RX_PACKETS, "1RTT RX packets number")
quic_error (PACKET_DROP, "quic packet drops")
f='#n368'>368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
#!/usr/bin/env python3
""" Vpp QUIC tests """

import unittest
import os
import subprocess
import signal
from framework import VppTestCase, VppTestRunner, running_extended_tests, \
    Worker
from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath


class QUICAppWorker(Worker):
    """ QUIC Test Application Worker """
    process = None

    def __init__(self, build_dir, appname, executable_args, logger, role,
                 testcase, env=None, *args, **kwargs):
        if env is None:
            env = {}
        app = "%s/vpp/bin/%s" % (build_dir, appname)
        self.args = [app] + executable_args
        self.role = role
        self.wait_for_gdb = 'wait-for-gdb'
        self.testcase = testcase
        super(QUICAppWorker, self).__init__(self.args, logger, env,
                                            *args, **kwargs)

    def run(self):
        super(QUICAppWorker, self).run()

    def teardown(self, logger, timeout):
        if self.process is None:
            return False
        try:
            logger.debug("Killing worker process (pid %d)" % self.process.pid)
            os.killpg(os.getpgid(self.process.pid), signal.SIGKILL)
            self.join(timeout)
        except OSError as e:
            logger.debug("Couldn't kill worker process")
            return True
        return False


class QUICTestCase(VppTestCase):
    """ QUIC Test Case """

    timeout = 20
    pre_test_sleep = 0.3
    post_test_sleep = 0.3

    @classmethod
    def setUpClass(cls):
        cls.extra_vpp_plugin_config.append("plugin quic_plugin.so { enable }")
        super(QUICTestCase, cls).setUpClass()

    def setUp(self):
        super(QUICTestCase, self).setUp()
        var = "VPP_BUILD_DIR"
        self.build_dir = os.getenv(var, None)
        if self.build_dir is None:
            raise Exception("Environment variable `%s' not set" % var)
        self.vppDebug = 'vpp_debug' in self.build_dir

        self.create_loopback_interfaces(2)
        self.uri = "quic://%s/1234" % self.loop0.local_ip4
        table_id = 1
        for i in self.lo_interfaces:
            i.admin_up()

            if table_id != 0:
                tbl = VppIpTable(self, table_id)
                tbl.add_vpp_config()

            i.set_table_ip4(table_id)
            i.config_ip4()
            table_id += 1

        # Configure namespaces
        self.vapi.app_namespace_add_del(namespace_id="server",
                                        sw_if_index=self.loop0.sw_if_index)
        self.vapi.app_namespace_add_del(namespace_id="client",
                                        sw_if_index=self.loop1.sw_if_index)

        # Add inter-table routes
        self.ip_t01 = VppIpRoute(self, self.loop1.local_ip4, 32,
                                 [VppRoutePath("0.0.0.0",
                                               0xffffffff,
                                               nh_table_id=2)], table_id=1)
        self.ip_t10 = VppIpRoute(self, self.loop0.local_ip4, 32,
                                 [VppRoutePath("0.0.0.0",
                                               0xffffffff,
                                               nh_table_id=1)], table_id=2)
        self.ip_t01.add_vpp_config()
        self.ip_t10.add_vpp_config()
        self.logger.debug(self.vapi.cli("show ip fib"))

    def tearDown(self):
        # Delete inter-table routes
        self.ip_t01.remove_vpp_config()
        self.ip_t10.remove_vpp_config()

        for i in self.lo_interfaces:
            i.unconfig_ip4()
            i.set_table_ip4(0)
            i.admin_down()
        super(QUICTestCase, self).tearDown()


class QUICEchoIntTestCase(QUICTestCase):
    """QUIC Echo Internal Test Case"""
    test_bytes = ' test-bytes'
    extra_vpp_punt_config = ["session", "{", "enable", "poll-main", "}"]

    def setUp(self):
        super(QUICEchoIntTestCase, self).setUp()
        self.client_args = 'uri {uri} fifo-size 64{testbytes} appns client' \
            .format(uri=self.uri, testbytes=self.test_bytes)
        self.server_args = "uri %s fifo-size 64 appns server" % self.uri

    def tearDown(self):
        super(QUICEchoIntTestCase, self).tearDown()

    def server(self, *args):
        error = self.vapi.cli(
            "test echo server %s %s" %
            (self.server_args, ' '.join(args)))
        if error:
            self.logger.critical(error)
            self.assertNotIn("failed", error)

    def client(self, *args):
        error = self.vapi.cli(
            "test echo client %s %s" %
            (self.client_args, ' '.join(args)))
        if error:
            self.logger.critical(error)
            self.assertNotIn("failed", error)


class QUICEchoIntTransferTestCase(QUICEchoIntTestCase):
    """QUIC Echo Internal Transfer Test Case"""
    def test_quic_int_transfer(self):
        """QUIC internal transfer"""
        self.server()
        self.client("no-output", "mbytes", "2")


class QUICEchoIntSerialTestCase(QUICEchoIntTestCase):
    """QUIC Echo Internal Serial Transfer Test Case"""
    def test_quic_serial_int_transfer(self):
        """QUIC serial internal transfer"""
        self.server()
        self.client("no-output", "mbytes", "2")
        self.client("no-output", "mbytes", "2")
        self.client("no-output", "mbytes", "2")
        self.client("no-output", "mbytes", "2")
        self.client("no-output", "mbytes", "2")


class QUICEchoIntMStreamTestCase(QUICEchoIntTestCase):
    """QUIC Echo Internal MultiStream Test Case"""
    def test_quic_int_multistream_transfer(self):
        """QUIC internal multi-stream transfer"""
        self.server()
        self.client("nclients", "10", "mbytes", "1", "no-output")


class QUICEchoExtTestCase(QUICTestCase):
    quic_setup = "default"
    test_bytes = "test-bytes:assert"
    pre_test_sleep = 1
    post_test_sleep = 1
    app = "vpp_echo"
    evt_q_len = 16384
    worker_config = "workers 1"
    server_fifo_size = "1M"
    client_fifo_size = "4M"
    extra_vpp_punt_config = ["session", "{",
                             "enable", "poll-main", "evt_qs_memfd_seg",
                             "evt_qs_seg_size", "64M",
                             "event-queue-length", f"{evt_q_len}",
                             "preallocated-sessions", "1024",
                             "v4-session-table-buckets", "20000",
                             "v4-session-table-memory", "64M",
                             "v4-halfopen-table-buckets", "20000",
                             "v4-halfopen-table-memory", "64M",
                             "local-endpoints-table-buckets", "250000",
                             "local-endpoints-table-memory", "512M",
                             "}"]

    def setUp(self):
        super(QUICEchoExtTestCase, self).setUp()
        common_args = [
            "uri", self.uri,
            "json",
            self.test_bytes,
            "socket-name", self.api_sock,
            "quic-setup", self.quic_setup,
            "nthreads", "1",
            "mq-size", f"{self.evt_q_len}"
        ]
        self.server_echo_test_args = common_args + \
            ["server", "appns", "server", "fifo-size",
             f"{self.server_fifo_size}"]
        self.client_echo_test_args = common_args + \
            ["client", "appns", "client", "fifo-size",
             f"{self.client_fifo_size}"]
        error = self.vapi.cli("quic set fifo-size 2M")
        if error:
            self.logger.critical(error)
            self.assertNotIn("failed", error)

    def server(self, *args):
        _args = self.server_echo_test_args + list(args)
        self.worker_server = QUICAppWorker(
            self.build_dir,
            self.app,
            _args,
            self.logger,
            'server',
            self)
        self.worker_server.start()
        self.sleep(self.pre_test_sleep)

    def client(self, *args):
        _args = self.client_echo_test_args + list(args)
        self.worker_client = QUICAppWorker(
            self.build_dir,
            self.app,
            _args,
            self.logger,
            'client',
            self)
        self.worker_client.start()
        timeout = None if self.debug_all else self.timeout
        self.worker_client.join(timeout)
        if self.worker_client.is_alive():
            error = f"Client failed to complete in {timeout} seconds!"
            self.logger.critical(error)
            return
        self.worker_server.join(timeout)
        if self.worker_server.is_alive():
            error = f"Server failed to complete in {timeout} seconds!"
            self.logger.critical(error)
        self.sleep(self.post_test_sleep)

    def validate_ext_test_results(self):
        server_result = self.worker_server.result
        client_result = self.worker_client.result
        self.logger.info("Server worker result is `%s'" %
                         server_result)
        self.logger.info("Client worker result is `%s'" %
                         client_result)
        server_kill_error = False
        if self.worker_server.result is None:
            server_kill_error = self.worker_server.teardown(
                self.logger, self.timeout)
        if self.worker_client.result is None:
            self.worker_client.teardown(self.logger, self.timeout)
        err_msg = "Wrong server worker return code (%s)" % server_result
        self.assertEqual(server_result, 0, err_msg)
        self.assertIsNotNone(
            client_result,
            "Timeout! Client worker did not finish in %ss" %
            self.timeout)
        err_msg = "Wrong client worker return code (%s)" % client_result
        self.assertEqual(client_result, 0, err_msg)
        self.assertFalse(server_kill_error, "Server kill errored")


class QUICEchoExtTransferTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Test Case"""
    timeout = 60

    def test_quic_ext_transfer(self):
        """QUIC external transfer"""
        self.server()
        self.client()
        self.validate_ext_test_results()


class QUICEchoExtTransferBigTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Big Test Case"""
    server_fifo_size = '4M'
    client_fifo_size = '4M'
    test_bytes = ''
    timeout = 60

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    def test_quic_ext_transfer_big(self):
        """QUIC external transfer, big stream"""
        self.server("TX=0", "RX=2G")
        self.client("TX=2G", "RX=0")
        self.validate_ext_test_results()


class QUICEchoExtQcloseRxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Qclose Rx Test Case"""

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_qclose_rx(self):
        """QUIC external transfer, rx close"""
        self.server("TX=0", "RX=10M", "qclose=Y", "sclose=N")
        self.client("TX=10M", "RX=0", "qclose=W", "sclose=W")
        self.validate_ext_test_results()


class QUICEchoExtQcloseTxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Qclose Tx Test Case"""

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_qclose_tx(self):
        """QUIC external transfer, tx close"""
        self.server("TX=0", "RX=10M", "qclose=W", "sclose=W",
                    "rx-results-diff")
        self.client("TX=10M", "RX=0", "qclose=Y", "sclose=N")
        self.validate_ext_test_results()


class QUICEchoExtEarlyQcloseRxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Early Qclose Rx Test Case"""

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_early_qclose_rx(self):
        """QUIC external transfer, early rx close"""
        self.server("TX=0", "RX=10M", "qclose=Y", "sclose=N")
        self.client("TX=20M", "RX=0", "qclose=W", "sclose=W",
                    "tx-results-diff")
        self.validate_ext_test_results()


class QUICEchoExtEarlyQcloseTxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Early Qclose Tx Test Case"""

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_early_qclose_tx(self):
        """QUIC external transfer, early tx close"""
        self.server("TX=0", "RX=20M", "qclose=W", "sclose=W",
                    "rx-results-diff")
        self.client("TX=10M", "RX=0", "qclose=Y", "sclose=N")
        self.validate_ext_test_results()


class QUICEchoExtScloseRxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Sclose Rx Test Case"""

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_sclose_rx(self):
        """QUIC external transfer, rx stream close"""
        self.server("TX=0", "RX=10M", "qclose=N", "sclose=Y")
        self.client("TX=10M", "RX=0", "qclose=W", "sclose=W")
        self.validate_ext_test_results()


class QUICEchoExtScloseTxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Sclose Tx Test Case"""

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_sclose_tx(self):
        """QUIC external transfer, tx stream close"""
        self.server("TX=0", "RX=10M", "qclose=W", "sclose=W")
        self.client("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
        self.validate_ext_test_results()


class QUICEchoExtEarlyScloseRxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Early Sclose Rx Test Case"""

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_early_sclose_rx(self):
        """QUIC external transfer, early rx stream close"""
        self.server("TX=0", "RX=10M", "qclose=N", "sclose=Y")
        self.client("TX=20M", "RX=0", "qclose=W", "sclose=W",
                    "tx-results-diff")
        self.validate_ext_test_results()


class QUICEchoExtEarlyScloseTxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Early Sclose Tx Test Case"""

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_early_sclose_tx(self):
        """QUIC external transfer, early tx stream close"""
        self.server("TX=0", "RX=20M", "qclose=W", "sclose=W",
                    "rx-results-diff")
        self.client("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream Test Case"""
    quic_setup = "serverstream"
    timeout = 60

    def test_quic_ext_transfer_server_stream(self):
        """QUIC external server transfer"""
        self.server("TX=10M", "RX=0")
        self.client("TX=0", "RX=10M")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamBigTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream Big Test Case"""
    quic_setup = "serverstream"
    server_fifo_size = '4M'
    client_fifo_size = '4M'
    test_bytes = ''
    timeout = 60

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    def test_quic_ext_transfer_server_stream_big(self):
        """QUIC external server transfer, big stream"""
        self.server("TX=2G", "RX=0")
        self.client("TX=0", "RX=2G")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamQcloseRxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream Qclose Rx Test Case"""
    quic_setup = "serverstream"

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_server_stream_qclose_rx(self):
        """QUIC external server transfer, rx close"""
        self.server("TX=10M", "RX=0", "qclose=W", "sclose=W")
        self.client("TX=0", "RX=10M", "qclose=Y", "sclose=N")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamQcloseTxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream Qclose Tx Test Case"""
    quic_setup = "serverstream"

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_server_stream_qclose_tx(self):
        """QUIC external server transfer, tx close"""
        self.server("TX=10M", "RX=0", "qclose=Y", "sclose=N")
        self.client("TX=0", "RX=10M", "qclose=W", "sclose=W",
                    "rx-results-diff")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamEarlyQcloseRxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream Early Qclose Rx Test Case"""
    quic_setup = "serverstream"

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_server_stream_early_qclose_rx(self):
        """QUIC external server transfer, early rx close"""
        self.server("TX=20M", "RX=0", "qclose=W", "sclose=W",
                    "tx-results-diff")
        self.client("TX=0", "RX=10M", "qclose=Y", "sclose=N")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamEarlyQcloseTxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream Early Qclose Tx Test Case"""
    quic_setup = "serverstream"

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_server_stream_early_qclose_tx(self):
        """QUIC external server transfer, early tx close"""
        self.server("TX=10M", "RX=0", "qclose=Y", "sclose=N")
        self.client("TX=0", "RX=20M", "qclose=W", "sclose=W",
                    "rx-results-diff")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamScloseRxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream Sclose Rx Test Case"""
    quic_setup = "serverstream"

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_server_stream_sclose_rx(self):
        """QUIC external server transfer, rx stream close"""
        self.server("TX=10M", "RX=0", "qclose=W", "sclose=W")
        self.client("TX=0", "RX=10M", "qclose=N", "sclose=Y")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamScloseTxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream Sclose Tx Test Case"""
    quic_setup = "serverstream"

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_server_stream_sclose_tx(self):
        """QUIC external server transfer, tx stream close"""
        self.server("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
        self.client("TX=0", "RX=10M", "qclose=W", "sclose=W")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamEarlyScloseRxTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream Early Sclose Rx Test Case"""
    quic_setup = "serverstream"

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_server_stream_early_sclose_rx(self):
        """QUIC external server transfer, early rx stream close"""
        self.server("TX=20M", "RX=0", "qclose=W", "sclose=W",
                    "tx-results-diff")
        self.client("TX=0", "RX=10M", "qclose=N", "sclose=Y")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamEarlyScloseTxTestCase(QUICEchoExtTestCase):
    """QUIC Echo Ext Transfer Server Stream Early Sclose Tx Test Case"""
    quic_setup = "serverstream"

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_server_stream_early_sclose_tx(self):
        """QUIC external server transfer, early tx stream close"""
        self.server("TX=10M", "RX=0", "qclose=Y", "sclose=Y")
        self.client("TX=0", "RX=20M", "qclose=W", "sclose=W",
                    "rx-results-diff")
        self.validate_ext_test_results()


class QUICEchoExtServerStreamWorkersTestCase(QUICEchoExtTestCase):
    """QUIC Echo External Transfer Server Stream MultiWorker Test Case"""
    quic_setup = "serverstream"

    @unittest.skipUnless(running_extended_tests, "part of extended tests")
    @unittest.skip("testcase under development")
    def test_quic_ext_transfer_server_stream_multi_workers(self):
        """QUIC external server transfer, multi-worker"""
        self.server("nclients", "4", "quic-streams", "4", "TX=10M", "RX=0")
        self.client("nclients", "4", "quic-streams", "4", "TX=0", "RX=10M")
        self.validate_ext_test_results()


if __name__ == '__main__':
    unittest.main(testRunner=VppTestRunner)