I even found this patch which does exactly that, puts it into netns:
commit fc49b804967e5b1cc1665efd4de112945e1ab4c6
Author: Florian Westphal <[email protected]>
Date: Mon Nov 4 15:25:24 2024 +0100
selftests: netfilter: run conntrack_dump_flush in netns
On 12/18/25 18:22, Pavel Tikhomirov wrote:
> The patch looks reasonable and all.
>
> BUT, the IPCTNL_MSG_CT_GET is network namespace based and if we just run this
> test in its own separate network namespace it should not mess with host
> conntracks. This way we will not need to patch the test, right?
>
> On 12/17/25 04:57, Aleksei Oladko wrote:
>> The conntrack_dump_flush zone selftest assumes that the default conntrack
>> zone
>> is empty except for test connections. This assumption is incorrect on hosts
>> with active traffic, such as ssh sessions, leading to spurious test
>> failures.
>>
>> Update the test to count only the connections created by the test itself,
>> making it robust against existing host traffic.
>>
>> https://virtuozzo.atlassian.net/browse/VSTOR-120993
>>
>> Signed-off-by: Aleksei Oladko <[email protected]>
>> ---
>> .../net/netfilter/conntrack_dump_flush.c | 276 ++++++++++++------
>> 1 file changed, 186 insertions(+), 90 deletions(-)
>>
>> diff --git a/tools/testing/selftests/net/netfilter/conntrack_dump_flush.c
>> b/tools/testing/selftests/net/netfilter/conntrack_dump_flush.c
>> index 5f827e10717d..93e11d7c8620 100644
>> --- a/tools/testing/selftests/net/netfilter/conntrack_dump_flush.c
>> +++ b/tools/testing/selftests/net/netfilter/conntrack_dump_flush.c
>> @@ -15,6 +15,99 @@
>> #define TEST_ZONE_ID 123
>> #define NF_CT_DEFAULT_ZONE_ID 0
>>
>> +struct test_suite {
>> + uint32_t src4;
>> + uint32_t dst4;
>> + struct in6_addr src6;
>> + struct in6_addr dst6;
>> + uint16_t zone;
>> +} suite[] = {
>> + [0] = {
>> + .src4 = 0xf0f0f0f0,
>> + .dst4 = 0xf1f1f1f1,
>> + .src6 = (struct in6_addr) {{
>> + .__u6_addr32 = {
>> + 0xb80d0120,
>> + 0x00000000,
>> + 0x00000000,
>> + 0x01000000
>> + }
>> + }},
>> + .dst6 = (struct in6_addr) {{
>> + .__u6_addr32 = {
>> + 0xb80d0120,
>> + 0x00000000,
>> + 0x00000000,
>> + 0x02000000
>> + }
>> + }},
>> + .zone = TEST_ZONE_ID,
>> + },
>> + [1] = {
>> + .src4 = 0xf2f2f2f2,
>> + .dst4 = 0xf3f3f3f3,
>> + .src6 = (struct in6_addr) {{
>> + .__u6_addr32 = {
>> + 0xb80d0120,
>> + 0x00000000,
>> + 0x00000000,
>> + 0x03000000
>> + }
>> + }},
>> + .dst6 = (struct in6_addr) {{
>> + .__u6_addr32 = {
>> + 0xb80d0120,
>> + 0x00000000,
>> + 0x00000000,
>> + 0x04000000
>> + }
>> + }},
>> + .zone = TEST_ZONE_ID + 1,
>> + },
>> + [2] = {
>> + .src4 = 0xf4f4f4f4,
>> + .dst4 = 0xf5f5f5f5,
>> + .src6 = (struct in6_addr) {{
>> + .__u6_addr32 = {
>> + 0xb80d0120,
>> + 0x00000000,
>> + 0x00000000,
>> + 0x05000000
>> + }
>> + }},
>> + .dst6 = (struct in6_addr) {{
>> + .__u6_addr32 = {
>> + 0xb80d0120,
>> + 0x00000000,
>> + 0x00000000,
>> + 0x06000000
>> + }
>> + }},
>> + .zone = TEST_ZONE_ID + 2,
>> + },
>> + [3] = {
>> + .src4 = 0xf6f6f6f6,
>> + .dst4 = 0xf7f7f7f7,
>> + .src6 = (struct in6_addr) {{
>> + .__u6_addr32 = {
>> + 0xb80d0120,
>> + 0x00000000,
>> + 0x00000000,
>> + 0x07000000
>> + }
>> + }},
>> + .dst6 = (struct in6_addr) {{
>> + .__u6_addr32 = {
>> + 0xb80d0120,
>> + 0x00000000,
>> + 0x00000000,
>> + 0x08000000
>> + }
>> + }},
>> + .zone = NF_CT_DEFAULT_ZONE_ID,
>> + },
>> +};
>> +
>> static int reply_counter;
>>
>> static int build_cta_tuple_v4(struct nlmsghdr *nlh, int type,
>> @@ -210,9 +303,90 @@ static int conntrack_data_generate_v6(struct mnl_socket
>> *sock,
>> return conntrack_data_insert(sock, nlh, zone);
>> }
>>
>> +static int parse_conntrack_cb(const struct nlattr *attr, void *data)
>> +{
>> + const struct nlattr **tb = data;
>> + int type = mnl_attr_get_type(attr);
>> +
>> + if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
>> + return MNL_CB_OK;
>> +
>> + tb[type] = (struct nlattr *)attr;
>> + return MNL_CB_OK;
>> +}
>> +
>> +static int parse_conntrack_ip_cb(const struct nlattr *attr, void *data)
>> +{
>> + const struct nlattr **tb = data;
>> + int type = mnl_attr_get_type(attr);
>> +
>> + if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0)
>> + return MNL_CB_OK;
>> +
>> + tb[type] = (struct nlattr *)attr;
>> + return MNL_CB_OK;
>> +}
>> +
>> static int count_entries(const struct nlmsghdr *nlh, void *data)
>> {
>> - reply_counter++;
>> + struct nfgenmsg *nfg;
>> + struct nlattr *tb[CTA_MAX +1] = {};
>> + struct nlattr *tb_tuple[CTA_MAX + 1] = {};
>> + struct nlattr *tb_ip[CTA_IP_MAX + 1] = {};
>> + struct nlattr *tuple, *ip;
>> + int family;
>> +
>> + nfg = mnl_nlmsg_get_payload(nlh);
>> + family = nfg->nfgen_family;
>> + mnl_attr_parse(nlh, sizeof(*nfg), parse_conntrack_cb, tb);
>> +
>> + tuple = tb[CTA_TUPLE_ORIG];
>> + if (!tuple)
>> + return MNL_CB_OK;
>> +
>> + mnl_attr_parse_nested(tuple, parse_conntrack_cb, tb_tuple);
>> +
>> + ip = tb_tuple[CTA_TUPLE_IP];
>> + if (!ip)
>> + return MNL_CB_OK;
>> +
>> + mnl_attr_parse_nested(ip, parse_conntrack_ip_cb, tb_ip);
>> +
>> + if (family == AF_INET) {
>> + uint32_t src, dst;
>> + int i;
>> +
>> + if (!tb_ip[CTA_IP_V4_SRC] || !tb_ip[CTA_IP_V4_DST])
>> + return MNL_CB_OK;
>> +
>> + src = mnl_attr_get_u32(tb_ip[CTA_IP_V4_SRC]);
>> + dst = mnl_attr_get_u32(tb_ip[CTA_IP_V4_DST]);
>> +
>> + for (i = 0; i < sizeof(suite) / sizeof(suite[0]); i++) {
>> + if (src == suite[i].src4 && dst == suite[i].dst4) {
>> + reply_counter++;
>> + return MNL_CB_OK;
>> + }
>> + }
>> + } else if (family == AF_INET6) {
>> + struct in6_addr src6, dst6;
>> + int i;
>> +
>> + if (!tb_ip[CTA_IP_V6_SRC] || !tb_ip[CTA_IP_V6_DST])
>> + return MNL_CB_OK;
>> +
>> + memcpy(&src6, mnl_attr_get_payload(tb_ip[CTA_IP_V6_SRC]),
>> sizeof(src6));
>> + memcpy(&dst6, mnl_attr_get_payload(tb_ip[CTA_IP_V6_DST]),
>> sizeof(dst6));
>> +
>> + for (i = 0; i < sizeof(suite) / sizeof(suite[0]); i++) {
>> + if (!memcmp(&src6, &suite[i].src6, sizeof(src6)) &&
>> + !memcmp(&dst6, &suite[i].dst6, sizeof(dst6))) {
>> + reply_counter++;
>> + return MNL_CB_OK;
>> + }
>> + }
>> + }
>> +
>> return MNL_CB_OK;
>> }
>>
>> @@ -316,6 +490,7 @@ FIXTURE_SETUP(conntrack_dump_flush)
>> {
>> struct in6_addr src, dst;
>> int ret;
>> + int i;
>>
>> self->sock = mnl_socket_open(NETLINK_NETFILTER);
>> if (!self->sock) {
>> @@ -332,96 +507,17 @@ FIXTURE_SETUP(conntrack_dump_flush)
>> else if (ret < 0 && errno == EOPNOTSUPP)
>> SKIP(return, "Kernel does not seem to support conntrack zones");
>>
>> - ret = conntrack_data_generate_v4(self->sock, 0xf0f0f0f0, 0xf1f1f1f1,
>> - TEST_ZONE_ID);
>> - EXPECT_EQ(ret, 0);
>> - ret = conntrack_data_generate_v4(self->sock, 0xf2f2f2f2, 0xf3f3f3f3,
>> - TEST_ZONE_ID + 1);
>> - EXPECT_EQ(ret, 0);
>> - ret = conntrack_data_generate_v4(self->sock, 0xf4f4f4f4, 0xf5f5f5f5,
>> - TEST_ZONE_ID + 2);
>> - EXPECT_EQ(ret, 0);
>> - ret = conntrack_data_generate_v4(self->sock, 0xf6f6f6f6, 0xf7f7f7f7,
>> - NF_CT_DEFAULT_ZONE_ID);
>> - EXPECT_EQ(ret, 0);
>> -
>> - src = (struct in6_addr) {{
>> - .__u6_addr32 = {
>> - 0xb80d0120,
>> - 0x00000000,
>> - 0x00000000,
>> - 0x01000000
>> - }
>> - }};
>> - dst = (struct in6_addr) {{
>> - .__u6_addr32 = {
>> - 0xb80d0120,
>> - 0x00000000,
>> - 0x00000000,
>> - 0x02000000
>> - }
>> - }};
>> - ret = conntrack_data_generate_v6(self->sock, src, dst,
>> - TEST_ZONE_ID);
>> - EXPECT_EQ(ret, 0);
>> - src = (struct in6_addr) {{
>> - .__u6_addr32 = {
>> - 0xb80d0120,
>> - 0x00000000,
>> - 0x00000000,
>> - 0x03000000
>> - }
>> - }};
>> - dst = (struct in6_addr) {{
>> - .__u6_addr32 = {
>> - 0xb80d0120,
>> - 0x00000000,
>> - 0x00000000,
>> - 0x04000000
>> - }
>> - }};
>> - ret = conntrack_data_generate_v6(self->sock, src, dst,
>> - TEST_ZONE_ID + 1);
>> - EXPECT_EQ(ret, 0);
>> - src = (struct in6_addr) {{
>> - .__u6_addr32 = {
>> - 0xb80d0120,
>> - 0x00000000,
>> - 0x00000000,
>> - 0x05000000
>> - }
>> - }};
>> - dst = (struct in6_addr) {{
>> - .__u6_addr32 = {
>> - 0xb80d0120,
>> - 0x00000000,
>> - 0x00000000,
>> - 0x06000000
>> - }
>> - }};
>> - ret = conntrack_data_generate_v6(self->sock, src, dst,
>> - TEST_ZONE_ID + 2);
>> - EXPECT_EQ(ret, 0);
>> + for (i = 0; i < sizeof(suite) / sizeof(suite[0]); i++) {
>> + ret = conntrack_data_generate_v4(self->sock, suite[i].src4,
>> + suite[i].dst4, suite[i].zone);
>> + EXPECT_EQ(ret, 0);
>> + }
>>
>> - src = (struct in6_addr) {{
>> - .__u6_addr32 = {
>> - 0xb80d0120,
>> - 0x00000000,
>> - 0x00000000,
>> - 0x07000000
>> - }
>> - }};
>> - dst = (struct in6_addr) {{
>> - .__u6_addr32 = {
>> - 0xb80d0120,
>> - 0x00000000,
>> - 0x00000000,
>> - 0x08000000
>> - }
>> - }};
>> - ret = conntrack_data_generate_v6(self->sock, src, dst,
>> - NF_CT_DEFAULT_ZONE_ID);
>> - EXPECT_EQ(ret, 0);
>> + for (i = 0; i < sizeof(suite) / sizeof(suite[0]); i++) {
>> + ret = conntrack_data_generate_v6(self->sock, suite[i].src6,
>> + suite[i].dst6, suite[i].zone);
>> + EXPECT_EQ(ret, 0);
>> + }
>>
>> ret = conntracK_count_zone(self->sock, TEST_ZONE_ID);
>> EXPECT_GE(ret, 2);
>
--
Best regards, Pavel Tikhomirov
Senior Software Developer, Virtuozzo.
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel