All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fabiano Rosas <farosas@suse.de>
To: Jason Wang <jasowang@redhat.com>,
	jasowang@redhat.com, zhangckid@gmail.com, lizhijian@fujitsu.com
Cc: qemu-devel@nongnu.org, lulu@redhat.com
Subject: Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change
Date: Fri, 26 Dec 2025 17:59:15 -0300	[thread overview]
Message-ID: <87tsxd7ye4.fsf@suse.de> (raw)
In-Reply-To: <20251225072442.36012-2-jasowang@redhat.com>

Jason Wang <jasowang@redhat.com> writes:

> Add test_change_interval_timer to verify that modifying the 'interval'
> property of filter-buffer at runtime takes effect immediately.
>
> The test uses socket backend and filter-redirector to verify timer behavior:
> - Creates filter-buffer with a very long interval (1000 seconds)
> - Sends a packet which gets buffered
> - Advances virtual clock by 1 second, verifies packet is still buffered
> - Changes interval to 1ms via qom-set (timer should be rescheduled)
> - Advances virtual clock by 2ms, verifies packet is now released
> - This proves the timer was rescheduled immediately when interval changed
>
> The test uses filter-redirector to observe when packets are released
> by filter-buffer, providing end-to-end verification of the timer
> rescheduling behavior.
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
>  tests/qtest/meson.build          |   1 +
>  tests/qtest/test-filter-buffer.c | 169 +++++++++++++++++++++++++++++++
>  tests/qtest/test-netfilter.c     |   3 +
>  3 files changed, 173 insertions(+)
>  create mode 100644 tests/qtest/test-filter-buffer.c
>
> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
> index 669d07c06b..ffa85ba984 100644
> --- a/tests/qtest/meson.build
> +++ b/tests/qtest/meson.build
> @@ -46,6 +46,7 @@ qtests_cxl = \
>  #        for the availability of the default NICs in the tests
>  qtests_filter = \
>    (get_option('default_devices') and slirp.found() ? ['test-netfilter'] : []) + \
> +  (get_option('default_devices') and host_os != 'windows' ? ['test-filter-buffer'] : []) + \
>    (get_option('default_devices') and host_os != 'windows' ? ['test-filter-mirror'] : []) + \
>    (get_option('default_devices') and host_os != 'windows' ? ['test-filter-redirector'] : [])
>  
> diff --git a/tests/qtest/test-filter-buffer.c b/tests/qtest/test-filter-buffer.c
> new file mode 100644
> index 0000000000..441cbb975c
> --- /dev/null
> +++ b/tests/qtest/test-filter-buffer.c
> @@ -0,0 +1,169 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QTest testcase for filter-buffer
> + *
> + * Copyright (c) 2025 Red Hat, Inc.
> + * Author: Jason Wang <jasowang@redhat.com>
> + */
> +
> +#include "qemu/osdep.h"
> +#include "libqtest.h"
> +#include "qobject/qdict.h"
> +#include "qemu/iov.h"
> +#include "qemu/sockets.h"
> +
> +/*
> + * Test that changing interval at runtime affects packet release timing.
> + *
> + * Traffic flow with filter-buffer and filter-redirector:
> + *
> + * test side                        | qemu side
> + *                                  |
> + * +--------+                       | +---------+
> + * |  send  +------------------------>| backend |
> + * | sock[0]|                       | +----+----+
> + * +--------+                       |      |
> + *                                  | +----v----+
> + *                                  | |  fbuf0  | filter-buffer (queue=tx)
> + *                                  | +----+----+
> + *                                  |      |
> + *                                  | +----v----+  +----------+
> + *                                  | |   rd0   +->| chardev0 |
> + *                                  | +---------+  +----+-----+
> + *                                  |                   |
> + * +--------+                       |                   |
> + * |  recv  |<--------------------------------------+
> + * |  sock  |                       |
> + * +--------+                       |
> + *
> + * The test verifies that when interval is changed via qom-set, the timer
> + * is rescheduled immediately, causing buffered packets to be released
> + * at the new interval rather than waiting for the old interval to elapse.
> + */
> +static void test_change_interval_timer(void)
> +{
> +    QTestState *qts;
> +    QDict *response;
> +    int backend_sock[2], recv_sock;
> +    int ret;
> +    char send_buf[] = "Hello filter-buffer!";
> +    char recv_buf[128];
> +    char sock_path[] = "filter-buffer-test.XXXXXX";
> +    uint32_t size = sizeof(send_buf);
> +    uint32_t len;
> +
> +    size = htonl(size);
> +
> +    ret = socketpair(PF_UNIX, SOCK_STREAM, 0, backend_sock);
> +    g_assert_cmpint(ret, !=, -1);
> +
> +    ret = mkstemp(sock_path);
> +    g_assert_cmpint(ret, !=, -1);
> +
> +    /*
> +     * Start QEMU with:
> +     * - socket backend connected to our socketpair
> +     * - filter-buffer with a very long interval (1000 seconds)
> +     * - filter-redirector to send released packets to a chardev socket
> +     *
> +     * queue=tx intercepts packets going from backend to the guest,
> +     * i.e., data we send from the test side.
> +     */
> +    qts = qtest_initf(
> +        "-nic socket,id=qtest-bn0,fd=%d "
> +        "-chardev socket,id=chardev0,path=%s,server=on,wait=off "
> +        "-object filter-buffer,id=fbuf0,netdev=qtest-bn0,"
> +        "queue=tx,interval=1000000000 "
> +        "-object filter-redirector,id=rd0,netdev=qtest-bn0,"
> +        "queue=tx,outdev=chardev0",
> +        backend_sock[1], sock_path);
> +
> +    /* Connect to the chardev socket to receive redirected packets */
> +    recv_sock = unix_connect(sock_path, NULL);
> +    g_assert_cmpint(recv_sock, !=, -1);
> +
> +    /* Send a QMP command to ensure chardev connection is established */
> +    qtest_qmp_assert_success(qts, "{ 'execute' : 'query-status'}");
> +
> +    /*
> +     * Send a packet from the test side.
> +     * It should be buffered by filter-buffer.
> +     */
> +    struct iovec iov[] = {
> +        {
> +            .iov_base = &size,
> +            .iov_len = sizeof(size),
> +        }, {
> +            .iov_base = send_buf,
> +            .iov_len = sizeof(send_buf),
> +        },
> +    };
> +
> +    ret = iov_send(backend_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_buf));
> +    g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
> +
> +    /*
> +     * Advance virtual clock by 1 second (1,000,000,000 ns).
> +     * This is much less than the 1000 second interval, so the packet
> +     * should still be buffered.
> +     */
> +    qtest_clock_step(qts, 1000000000LL);
> +
> +    /* Try to receive with non-blocking - should fail (packet still buffered) */
> +    ret = recv(recv_sock, recv_buf, sizeof(recv_buf), MSG_DONTWAIT);
> +    g_assert_cmpint(ret, ==, -1);
> +    g_assert(errno == EAGAIN || errno == EWOULDBLOCK);
> +
> +    /*
> +     * Now change the interval to 1000 us (1ms) via qom-set.
> +     * This should reschedule the timer to fire in 1ms from now.
> +     */
> +    response = qtest_qmp(qts,
> +                         "{'execute': 'qom-set',"
> +                         " 'arguments': {"
> +                         "   'path': 'fbuf0',"
> +                         "   'property': 'interval',"
> +                         "   'value': 1000"
> +                         "}}");
> +    g_assert(response);
> +    g_assert(!qdict_haskey(response, "error"));
> +    qobject_unref(response);
> +
> +    /*
> +     * Advance virtual clock by 2ms (2,000,000 ns).
> +     * This exceeds the new 1ms interval, so the timer should fire
> +     * and release the buffered packet.
> +     *
> +     * If the interval change didn't take effect immediately, we would
> +     * still be waiting for the original 1000 second interval to elapse,
> +     * and the packet would not be released.
> +     */
> +    qtest_clock_step(qts, 2000000LL);
> +
> +    /*
> +     * Now we should be able to receive the packet through the redirector.
> +     * The packet was released by filter-buffer and sent to filter-redirector,
> +     * which forwarded it to the chardev socket.
> +     */
> +    ret = recv(recv_sock, &len, sizeof(len), 0);
> +    g_assert_cmpint(ret, ==, sizeof(len));
> +    len = ntohl(len);
> +    g_assert_cmpint(len, ==, sizeof(send_buf));
> +
> +    ret = recv(recv_sock, recv_buf, len, 0);
> +    g_assert_cmpint(ret, ==, len);
> +    g_assert_cmpstr(recv_buf, ==, send_buf);
> +
> +    close(recv_sock);
> +    close(backend_sock[0]);
> +    unlink(sock_path);
> +    qtest_quit(qts);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    g_test_init(&argc, &argv, NULL);
> +    qtest_add_func("/netfilter/change_interval_timer",
> +                   test_change_interval_timer);
> +    return g_test_run();
> +}
> diff --git a/tests/qtest/test-netfilter.c b/tests/qtest/test-netfilter.c
> index 326d4bd85f..b7271055d6 100644
> --- a/tests/qtest/test-netfilter.c
> +++ b/tests/qtest/test-netfilter.c
> @@ -10,7 +10,10 @@
>  
>  #include "qemu/osdep.h"
>  #include "libqtest-single.h"
> +#include "libqtest.h"
>  #include "qobject/qdict.h"
> +#include "qemu/iov.h"
> +#include "qemu/sockets.h"
>  

Some extra changes here^

>  /* add a netfilter to a netdev and then remove it */
>  static void add_one_netfilter(void)


  parent reply	other threads:[~2025-12-26 21:00 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-25  7:24 [PATCH 1/2] net/filter-buffer: make interval change take effect immediately Jason Wang
2025-12-25  7:24 ` [PATCH 2/2] tests/qtest: add test for filter-buffer interval change Jason Wang
2025-12-25 10:26   ` Zhang Chen
2025-12-26  1:36     ` Jason Wang
2025-12-26  3:14       ` Zhang Chen
2025-12-26  6:26         ` Jason Wang
2025-12-26  6:29           ` Jason Wang
2025-12-26  7:18             ` Zhang Chen
2025-12-26  7:28               ` Jason Wang
2025-12-26  7:50                 ` Zhang Chen
2025-12-26 20:59   ` Fabiano Rosas [this message]
2025-12-29  3:00     ` Jason Wang
2025-12-25  9:56 ` [PATCH 1/2] net/filter-buffer: make interval change take effect immediately Zhang Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87tsxd7ye4.fsf@suse.de \
    --to=farosas@suse.de \
    --cc=jasowang@redhat.com \
    --cc=lizhijian@fujitsu.com \
    --cc=lulu@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=zhangckid@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.