* [PATCH 1/2] net/filter-buffer: make interval change take effect immediately @ 2025-12-25 7:24 Jason Wang 2025-12-25 7:24 ` [PATCH 2/2] tests/qtest: add test for filter-buffer interval change Jason Wang 2025-12-25 9:56 ` [PATCH 1/2] net/filter-buffer: make interval change take effect immediately Zhang Chen 0 siblings, 2 replies; 13+ messages in thread From: Jason Wang @ 2025-12-25 7:24 UTC (permalink / raw) To: jasowang, zhangckid, lizhijian; +Cc: qemu-devel, lulu Previously, when the 'interval' property was modified at runtime via QMP, the new value would only take effect after the current timer period elapsed. This could lead to unexpected behavior when users expect immediate changes. Fix this by checking if the timer is already running when setting the interval property. If so, reschedule the timer with the new interval value immediately. Signed-off-by: Jason Wang <jasowang@redhat.com> --- net/filter-buffer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/filter-buffer.c b/net/filter-buffer.c index a36be31dc8..427da24097 100644 --- a/net/filter-buffer.c +++ b/net/filter-buffer.c @@ -159,6 +159,7 @@ static void filter_buffer_set_interval(Object *obj, Visitor *v, Error **errp) { FilterBufferState *s = FILTER_BUFFER(obj); + NetFilterState *nf = NETFILTER(obj); uint32_t value; if (!visit_type_uint32(v, name, &value, errp)) { @@ -170,6 +171,11 @@ static void filter_buffer_set_interval(Object *obj, Visitor *v, return; } s->interval = value; + + if (nf->netdev && nf->on) { + timer_mod(&s->release_timer, + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval); + } } static void filter_buffer_class_init(ObjectClass *oc, const void *data) -- 2.34.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 2025-12-25 7:24 [PATCH 1/2] net/filter-buffer: make interval change take effect immediately Jason Wang @ 2025-12-25 7:24 ` Jason Wang 2025-12-25 10:26 ` Zhang Chen 2025-12-26 20:59 ` Fabiano Rosas 2025-12-25 9:56 ` [PATCH 1/2] net/filter-buffer: make interval change take effect immediately Zhang Chen 1 sibling, 2 replies; 13+ messages in thread From: Jason Wang @ 2025-12-25 7:24 UTC (permalink / raw) To: jasowang, zhangckid, lizhijian; +Cc: qemu-devel, lulu 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" /* add a netfilter to a netdev and then remove it */ static void add_one_netfilter(void) -- 2.34.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 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 20:59 ` Fabiano Rosas 1 sibling, 1 reply; 13+ messages in thread From: Zhang Chen @ 2025-12-25 10:26 UTC (permalink / raw) To: Jason Wang; +Cc: lizhijian, qemu-devel, lulu On Thu, Dec 25, 2025 at 3:24 PM Jason Wang <jasowang@redhat.com> wrote: > > 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. If user try to simulate network latency by filter-buffer, the accuracy of time is important. Do we need add some note about the first buffered packet time not equel to dynamic changed time (default interval time - new qmp cmd effected time + changed time ?). Another issue is what level of stable accuracy the QEMU filter-buffer can be achieved in actual testing? Maybe need to tell user recommended test range? Thanks Chen > > 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" > > /* add a netfilter to a netdev and then remove it */ > static void add_one_netfilter(void) > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 2025-12-25 10:26 ` Zhang Chen @ 2025-12-26 1:36 ` Jason Wang 2025-12-26 3:14 ` Zhang Chen 0 siblings, 1 reply; 13+ messages in thread From: Jason Wang @ 2025-12-26 1:36 UTC (permalink / raw) To: Zhang Chen; +Cc: lizhijian, qemu-devel, lulu On Thu, Dec 25, 2025 at 6:27 PM Zhang Chen <zhangckid@gmail.com> wrote: > > On Thu, Dec 25, 2025 at 3:24 PM Jason Wang <jasowang@redhat.com> wrote: > > > > 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. > > If user try to simulate network latency by filter-buffer, the accuracy > of time is important. > Do we need add some note about the first buffered packet time not > equel to dynamic > changed time (default interval time - new qmp cmd effected time + > changed time ?). I'm not sure I will get here, we can't forcast when the first packet will come. So the behaviour is always that the filter-buffer will flush at a fixed interval. Or I may miss something here. > > Another issue is what level of stable accuracy the QEMU filter-buffer > can be achieved in actual testing? We use qemu_clock_get_us() so it's the us actually? > Maybe need to tell user recommended test range? Could you elaborate more on this? Thanks > > Thanks > Chen > > > > > 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" > > > > /* add a netfilter to a netdev and then remove it */ > > static void add_one_netfilter(void) > > -- > > 2.34.1 > > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 2025-12-26 1:36 ` Jason Wang @ 2025-12-26 3:14 ` Zhang Chen 2025-12-26 6:26 ` Jason Wang 0 siblings, 1 reply; 13+ messages in thread From: Zhang Chen @ 2025-12-26 3:14 UTC (permalink / raw) To: Jason Wang; +Cc: lizhijian, qemu-devel, lulu On Fri, Dec 26, 2025 at 9:37 AM Jason Wang <jasowang@redhat.com> wrote: > > On Thu, Dec 25, 2025 at 6:27 PM Zhang Chen <zhangckid@gmail.com> wrote: > > > > On Thu, Dec 25, 2025 at 3:24 PM Jason Wang <jasowang@redhat.com> wrote: > > > > > > 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. > > > > If user try to simulate network latency by filter-buffer, the accuracy > > of time is important. > > Do we need add some note about the first buffered packet time not > > equel to dynamic > > changed time (default interval time - new qmp cmd effected time + > > changed time ?). > > I'm not sure I will get here, we can't forcast when the first packet > will come. So the behaviour is always that the filter-buffer will > flush at a fixed interval. Or I may miss something here. This case same like this test, before change the user target interval time, filter-buffer maybe already buffered lots of packets, for this parts, the user external measured time did not meet the expected settings. > > > > > Another issue is what level of stable accuracy the QEMU filter-buffer > > can be achieved in actual testing? > > We use qemu_clock_get_us() so it's the us actually? Yes, this is our expectation, but in actual operation, there may be many interferences. For example user setup filter-buffer interval to 100us, even on the same physical machine host to guest, external client may get test result as 110us(like ping). > > > Maybe need to tell user recommended test range? > > Could you elaborate more on this? Based on the above statement, is it necessary to provide an empirical value for the time range, such as 10us(like 100us --> 110us)? Thanks Chen > > Thanks > > > > > Thanks > > Chen > > > > > > > > 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" > > > > > > /* add a netfilter to a netdev and then remove it */ > > > static void add_one_netfilter(void) > > > -- > > > 2.34.1 > > > > > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 2025-12-26 3:14 ` Zhang Chen @ 2025-12-26 6:26 ` Jason Wang 2025-12-26 6:29 ` Jason Wang 0 siblings, 1 reply; 13+ messages in thread From: Jason Wang @ 2025-12-26 6:26 UTC (permalink / raw) To: Zhang Chen; +Cc: lizhijian, qemu-devel, lulu On Fri, Dec 26, 2025 at 11:15 AM Zhang Chen <zhangckid@gmail.com> wrote: > > On Fri, Dec 26, 2025 at 9:37 AM Jason Wang <jasowang@redhat.com> wrote: > > > > On Thu, Dec 25, 2025 at 6:27 PM Zhang Chen <zhangckid@gmail.com> wrote: > > > > > > On Thu, Dec 25, 2025 at 3:24 PM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > 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. > > > > > > If user try to simulate network latency by filter-buffer, the accuracy > > > of time is important. > > > Do we need add some note about the first buffered packet time not > > > equel to dynamic > > > changed time (default interval time - new qmp cmd effected time + > > > changed time ?). > > > > I'm not sure I will get here, we can't forcast when the first packet > > will come. So the behaviour is always that the filter-buffer will > > flush at a fixed interval. Or I may miss something here. > > This case same like this test, before change the user target interval time, > filter-buffer maybe already buffered lots of packets, for this parts, the user > external measured time did not meet the expected settings. There's indeed a change of the behaviour, but I'm not sure if there's a user that depends on the previous behaviour. Or if we really care, we need a new attribute. > > > > > > > > > Another issue is what level of stable accuracy the QEMU filter-buffer > > > can be achieved in actual testing? > > > > We use qemu_clock_get_us() so it's the us actually? > > Yes, this is our expectation, but in actual operation, there may be > many interferences. > For example user setup filter-buffer interval to 100us, even on the > same physical machine > host to guest, external client may get test result as 110us(like ping). Yes, but this topic is somehow out of the scope of this patch. It require the support of the timer and probably some realtime support in the qemu timer. > > > > > > > Maybe need to tell user recommended test range? > > > > Could you elaborate more on this? > > Based on the above statement, is it necessary to provide an empirical value > for the time range, such as 10us(like 100us --> 110us)? It's better not since it could easily run out of sync with the behaviour of the code. Thanks > > Thanks > Chen > > > > > > Thanks > > > > > > > > Thanks > > > Chen > > > > > > > > > > > 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" > > > > > > > > /* add a netfilter to a netdev and then remove it */ > > > > static void add_one_netfilter(void) > > > > -- > > > > 2.34.1 > > > > > > > > > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 2025-12-26 6:26 ` Jason Wang @ 2025-12-26 6:29 ` Jason Wang 2025-12-26 7:18 ` Zhang Chen 0 siblings, 1 reply; 13+ messages in thread From: Jason Wang @ 2025-12-26 6:29 UTC (permalink / raw) To: Zhang Chen; +Cc: lizhijian, qemu-devel, lulu On Fri, Dec 26, 2025 at 2:26 PM Jason Wang <jasowang@redhat.com> wrote: > > On Fri, Dec 26, 2025 at 11:15 AM Zhang Chen <zhangckid@gmail.com> wrote: > > > > On Fri, Dec 26, 2025 at 9:37 AM Jason Wang <jasowang@redhat.com> wrote: > > > > > > On Thu, Dec 25, 2025 at 6:27 PM Zhang Chen <zhangckid@gmail.com> wrote: > > > > > > > > On Thu, Dec 25, 2025 at 3:24 PM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > > > 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. > > > > > > > > If user try to simulate network latency by filter-buffer, the accuracy > > > > of time is important. > > > > Do we need add some note about the first buffered packet time not > > > > equel to dynamic > > > > changed time (default interval time - new qmp cmd effected time + > > > > changed time ?). > > > > > > I'm not sure I will get here, we can't forcast when the first packet > > > will come. So the behaviour is always that the filter-buffer will > > > flush at a fixed interval. Or I may miss something here. > > > > This case same like this test, before change the user target interval time, > > filter-buffer maybe already buffered lots of packets, for this parts, the user > > external measured time did not meet the expected settings. > > There's indeed a change of the behaviour, but I'm not sure if there's > a user that depends on the previous behaviour. > > Or if we really care, we need a new attribute. Btw, the use case is something like these (out of the scope of COLO). Mgmt want to buffer the packets for a while and release the buffered packets immediately when something happens. Thanks ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 2025-12-26 6:29 ` Jason Wang @ 2025-12-26 7:18 ` Zhang Chen 2025-12-26 7:28 ` Jason Wang 0 siblings, 1 reply; 13+ messages in thread From: Zhang Chen @ 2025-12-26 7:18 UTC (permalink / raw) To: Jason Wang; +Cc: lizhijian, qemu-devel, lulu On Fri, Dec 26, 2025 at 2:30 PM Jason Wang <jasowang@redhat.com> wrote: > > On Fri, Dec 26, 2025 at 2:26 PM Jason Wang <jasowang@redhat.com> wrote: > > > > On Fri, Dec 26, 2025 at 11:15 AM Zhang Chen <zhangckid@gmail.com> wrote: > > > > > > On Fri, Dec 26, 2025 at 9:37 AM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > On Thu, Dec 25, 2025 at 6:27 PM Zhang Chen <zhangckid@gmail.com> wrote: > > > > > > > > > > On Thu, Dec 25, 2025 at 3:24 PM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > > > > > 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. > > > > > > > > > > If user try to simulate network latency by filter-buffer, the accuracy > > > > > of time is important. > > > > > Do we need add some note about the first buffered packet time not > > > > > equel to dynamic > > > > > changed time (default interval time - new qmp cmd effected time + > > > > > changed time ?). > > > > > > > > I'm not sure I will get here, we can't forcast when the first packet > > > > will come. So the behaviour is always that the filter-buffer will > > > > flush at a fixed interval. Or I may miss something here. > > > > > > This case same like this test, before change the user target interval time, > > > filter-buffer maybe already buffered lots of packets, for this parts, the user > > > external measured time did not meet the expected settings. > > > > There's indeed a change of the behaviour, but I'm not sure if there's > > a user that depends on the previous behaviour. > > > > Or if we really care, we need a new attribute. > > Btw, the use case is something like these (out of the scope of COLO). > > Mgmt want to buffer the packets for a while and release the buffered > packets immediately when something happens. Yes, I know that. And back to COLO, do you think we should change the colo-compare module to a general network comparision module? Any comments about it? Thanks Chen > > Thanks > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 2025-12-26 7:18 ` Zhang Chen @ 2025-12-26 7:28 ` Jason Wang 2025-12-26 7:50 ` Zhang Chen 0 siblings, 1 reply; 13+ messages in thread From: Jason Wang @ 2025-12-26 7:28 UTC (permalink / raw) To: Zhang Chen; +Cc: lizhijian, qemu-devel, lulu On Fri, Dec 26, 2025 at 3:19 PM Zhang Chen <zhangckid@gmail.com> wrote: > > On Fri, Dec 26, 2025 at 2:30 PM Jason Wang <jasowang@redhat.com> wrote: > > > > On Fri, Dec 26, 2025 at 2:26 PM Jason Wang <jasowang@redhat.com> wrote: > > > > > > On Fri, Dec 26, 2025 at 11:15 AM Zhang Chen <zhangckid@gmail.com> wrote: > > > > > > > > On Fri, Dec 26, 2025 at 9:37 AM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > > > On Thu, Dec 25, 2025 at 6:27 PM Zhang Chen <zhangckid@gmail.com> wrote: > > > > > > > > > > > > On Thu, Dec 25, 2025 at 3:24 PM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > > > > > > > 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. > > > > > > > > > > > > If user try to simulate network latency by filter-buffer, the accuracy > > > > > > of time is important. > > > > > > Do we need add some note about the first buffered packet time not > > > > > > equel to dynamic > > > > > > changed time (default interval time - new qmp cmd effected time + > > > > > > changed time ?). > > > > > > > > > > I'm not sure I will get here, we can't forcast when the first packet > > > > > will come. So the behaviour is always that the filter-buffer will > > > > > flush at a fixed interval. Or I may miss something here. > > > > > > > > This case same like this test, before change the user target interval time, > > > > filter-buffer maybe already buffered lots of packets, for this parts, the user > > > > external measured time did not meet the expected settings. > > > > > > There's indeed a change of the behaviour, but I'm not sure if there's > > > a user that depends on the previous behaviour. > > > > > > Or if we really care, we need a new attribute. > > > > Btw, the use case is something like these (out of the scope of COLO). > > > > Mgmt want to buffer the packets for a while and release the buffered > > packets immediately when something happens. > > Yes, I know that. And back to COLO, do you think we should change the > colo-compare module > to a general network comparision module? Any comments about it? I don't see how colo-compare could be used out of the scope of COLO, but I do see buffer, mirror and redirector can. Going back to this patch, are you ok with this or expect something else Thanks > > Thanks > Chen > > > > > Thanks > > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 2025-12-26 7:28 ` Jason Wang @ 2025-12-26 7:50 ` Zhang Chen 0 siblings, 0 replies; 13+ messages in thread From: Zhang Chen @ 2025-12-26 7:50 UTC (permalink / raw) To: Jason Wang; +Cc: lizhijian, qemu-devel, lulu On Fri, Dec 26, 2025 at 3:29 PM Jason Wang <jasowang@redhat.com> wrote: > > On Fri, Dec 26, 2025 at 3:19 PM Zhang Chen <zhangckid@gmail.com> wrote: > > > > On Fri, Dec 26, 2025 at 2:30 PM Jason Wang <jasowang@redhat.com> wrote: > > > > > > On Fri, Dec 26, 2025 at 2:26 PM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > On Fri, Dec 26, 2025 at 11:15 AM Zhang Chen <zhangckid@gmail.com> wrote: > > > > > > > > > > On Fri, Dec 26, 2025 at 9:37 AM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > > > > > On Thu, Dec 25, 2025 at 6:27 PM Zhang Chen <zhangckid@gmail.com> wrote: > > > > > > > > > > > > > > On Thu, Dec 25, 2025 at 3:24 PM Jason Wang <jasowang@redhat.com> wrote: > > > > > > > > > > > > > > > > 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. > > > > > > > > > > > > > > If user try to simulate network latency by filter-buffer, the accuracy > > > > > > > of time is important. > > > > > > > Do we need add some note about the first buffered packet time not > > > > > > > equel to dynamic > > > > > > > changed time (default interval time - new qmp cmd effected time + > > > > > > > changed time ?). > > > > > > > > > > > > I'm not sure I will get here, we can't forcast when the first packet > > > > > > will come. So the behaviour is always that the filter-buffer will > > > > > > flush at a fixed interval. Or I may miss something here. > > > > > > > > > > This case same like this test, before change the user target interval time, > > > > > filter-buffer maybe already buffered lots of packets, for this parts, the user > > > > > external measured time did not meet the expected settings. > > > > > > > > There's indeed a change of the behaviour, but I'm not sure if there's > > > > a user that depends on the previous behaviour. > > > > > > > > Or if we really care, we need a new attribute. > > > > > > Btw, the use case is something like these (out of the scope of COLO). > > > > > > Mgmt want to buffer the packets for a while and release the buffered > > > packets immediately when something happens. > > > > Yes, I know that. And back to COLO, do you think we should change the > > colo-compare module > > to a general network comparision module? Any comments about it? > > I don't see how colo-compare could be used out of the scope of COLO, > but I do see buffer, mirror and redirector can. > > Going back to this patch, are you ok with this or expect something else > Yes, it's OK for me. Thanks for add the new qtest. Reviewed-by: Zhang Chen <zhangckid@gmail.com> Thanks Chen > Thanks > > > > > Thanks > > Chen > > > > > > > > Thanks > > > > > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 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 20:59 ` Fabiano Rosas 2025-12-29 3:00 ` Jason Wang 1 sibling, 1 reply; 13+ messages in thread From: Fabiano Rosas @ 2025-12-26 20:59 UTC (permalink / raw) To: Jason Wang, jasowang, zhangckid, lizhijian; +Cc: qemu-devel, lulu 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) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] tests/qtest: add test for filter-buffer interval change 2025-12-26 20:59 ` Fabiano Rosas @ 2025-12-29 3:00 ` Jason Wang 0 siblings, 0 replies; 13+ messages in thread From: Jason Wang @ 2025-12-29 3:00 UTC (permalink / raw) To: Fabiano Rosas; +Cc: zhangckid, lizhijian, qemu-devel, lulu On Sat, Dec 27, 2025 at 4:59 AM Fabiano Rosas <farosas@suse.de> wrote: > > 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^ Indeed, let me fix that in v2. Thanks ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] net/filter-buffer: make interval change take effect immediately 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 9:56 ` Zhang Chen 1 sibling, 0 replies; 13+ messages in thread From: Zhang Chen @ 2025-12-25 9:56 UTC (permalink / raw) To: Jason Wang; +Cc: lizhijian, qemu-devel, lulu On Thu, Dec 25, 2025 at 3:24 PM Jason Wang <jasowang@redhat.com> wrote: > > Previously, when the 'interval' property was modified at runtime via > QMP, the new value would only take effect after the current timer > period elapsed. This could lead to unexpected behavior when users > expect immediate changes. > > Fix this by checking if the timer is already running when setting > the interval property. If so, reschedule the timer with the new > interval value immediately. > > Signed-off-by: Jason Wang <jasowang@redhat.com> LGTM. Reviewed-by: Zhang Chen <zhangckid@gmail.com> > --- > net/filter-buffer.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/net/filter-buffer.c b/net/filter-buffer.c > index a36be31dc8..427da24097 100644 > --- a/net/filter-buffer.c > +++ b/net/filter-buffer.c > @@ -159,6 +159,7 @@ static void filter_buffer_set_interval(Object *obj, Visitor *v, > Error **errp) > { > FilterBufferState *s = FILTER_BUFFER(obj); > + NetFilterState *nf = NETFILTER(obj); > uint32_t value; > > if (!visit_type_uint32(v, name, &value, errp)) { > @@ -170,6 +171,11 @@ static void filter_buffer_set_interval(Object *obj, Visitor *v, > return; > } > s->interval = value; > + > + if (nf->netdev && nf->on) { > + timer_mod(&s->release_timer, > + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval); > + } > } > > static void filter_buffer_class_init(ObjectClass *oc, const void *data) > -- > 2.34.1 > ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-12-29 3:01 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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 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
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.