netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Feedback on variable sized set elements
@ 2025-07-11  3:30 Shaun Brady
  2025-07-11 10:27 ` Florian Westphal
  0 siblings, 1 reply; 3+ messages in thread
From: Shaun Brady @ 2025-07-11  3:30 UTC (permalink / raw)
  To: netfilter-devel

Hello,

This email is mostly for education purposes.

I'm sure I bit off more than I could chew, but I attempted to write a proof of
concept patch to add a new set type, inet_addr, which would allow elements of
both ipv4_addr and ipv6_addr types.

Something to the tune of:

nft add set inet filter set_inet {type inet_addr\;}
nft add element inet filter set_inet { 10.0.1.195, 10.0.1.200, 10.0.1.201, 2001:db8::8a2e:370:7334 }

Figuring most of this would be implemented in the nft userland, I started
there, and was able to successfully get a new set type that allowed v4
addresses OR v6 addresses, depending on how I defined the datasize of
inet_addr (4 bytes or 16 bytes).

When leaving inet_addr size at the required (for both v4 and v6) 16 bytes
netlink would return EINVAL when adding v4 addresses to the set. We found in
nft_value_init:

                if (len != desc->len)
                        return -EINVAL;

with len being the nlattr (the v4 address) and desc being the nft_set_desc. 4 != 16.


My questions:

1) Is this feature interesting enough to pursue (given what would have to be
done to make it work (see next question))?  The set type only makes sense in
inet tables (I think...) and even then, would roughly be syntactic sugar for
what could be done (more efficiently) with two sets of the base protocols. But
hey, nice things make nice tools?


2) (assuming #1) I believe we would have to put a condition to check the set
type versus the nlattr type, and allow a size difference on
set(inet_addr)/set_elem(ipv4_addr) (I don't know if that has any
ramifications).

I found set.ktype, but that is indicated to be unused in the kernel, and
comes from userland any way, so I don't believe it can be reliably used
to map to a set type.

Another possible approach would be to create an API to transmit valid size
types for a set type from userland. We would still need to ID the set type,
and that has the above problems of set.ktype.

Do either of these approaches make sense and secondly do either seem tenable?
Are there other obvious paths forward to deal with variable set element sizes?


Thanks!


SB

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Feedback on variable sized set elements
  2025-07-11  3:30 Feedback on variable sized set elements Shaun Brady
@ 2025-07-11 10:27 ` Florian Westphal
  2025-07-12  2:43   ` Shaun Brady
  0 siblings, 1 reply; 3+ messages in thread
From: Florian Westphal @ 2025-07-11 10:27 UTC (permalink / raw)
  To: Shaun Brady; +Cc: netfilter-devel

Shaun Brady <brady.1345@gmail.com> wrote:
> I'm sure I bit off more than I could chew, but I attempted to write a proof of
> concept patch to add a new set type, inet_addr, which would allow elements of
> both ipv4_addr and ipv6_addr types.

Why?  This is hard, the kernel has no notion of data types.

> Something to the tune of:
> 
> nft add set inet filter set_inet {type inet_addr\;}
> nft add element inet filter set_inet { 10.0.1.195, 10.0.1.200, 10.0.1.201, 2001:db8::8a2e:370:7334 }

How would this work with ranges or concatenations?

> Figuring most of this would be implemented in the nft userland, I started
> there, and was able to successfully get a new set type that allowed v4
> addresses OR v6 addresses, depending on how I defined the datasize of
> inet_addr (4 bytes or 16 bytes).
> 
> When leaving inet_addr size at the required (for both v4 and v6) 16 bytes
> netlink would return EINVAL when adding v4 addresses to the set. We found in
> nft_value_init:
> 
>                 if (len != desc->len)
>                         return -EINVAL;
> 
> with len being the nlattr (the v4 address) and desc being the nft_set_desc. 4 != 16.
> My questions:
> 
> 1) Is this feature interesting enough to pursue (given what would have to be
> done to make it work (see next question))?  The set type only makes sense in
> inet tables (I think...) and even then, would roughly be syntactic sugar for
> what could be done (more efficiently) with two sets of the base protocols. But
> hey, nice things make nice tools?

I don't see how its doable.  The lookup key fed to the set lookup
function via nft_lookup.c has a fixed size.

From kernel point of view, its an array of u32 of a given size dictated
by the sets key length.

> 2) (assuming #1) I believe we would have to put a condition to check the set
> type versus the nlattr type, and allow a size difference on
> set(inet_addr)/set_elem(ipv4_addr) (I don't know if that has any
> ramifications).

The kernel doesn't know what an ipv4 or ipv6 address is.
It only knows the total key size.  In case of nft_set_pipapo.c its also
told the sizes of the individual subkeys. (e.g. ipv4_addr .
inet_service -> 4 . 4, ipv6_addr . ip_protocol -> 16 . 4).

Maybe it would be possble to xlate ipv4 addresses to ipv6 mapped
addresses, but that would still require expansion in userland, because

ip saddr @foo
ip6 saddr @foo

cannot work.  We'd need to rewrite it to something like
meta nfproto ipv4 {
	reg32_1 = 0xffffffff
	reg32_2 = 0xffffffff
	reg32_3 = 0xffffffff
	reg32_4 = ip saddr
	lookup @foo sreg32_1
}
meta nfproto ipv6 ip6 saddr @foo

I don't think its worth the pain.  Also because then ipv4 becomes
indistinguishable from on-wire mapped addresses.

> Another possible approach would be to create an API to transmit valid size
> types for a set type from userland. We would still need to ID the set type,
> and that has the above problems of set.ktype.

There are different sets, yes, but none of these sets support a
particular data type.  They don't know what that is, the datatype is a
userspace thing and its only stored in the kernel so that 'nft list
ruleset' and friends know how to pretty-print the octet soups stored in
the set.  Its not related to matching.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Feedback on variable sized set elements
  2025-07-11 10:27 ` Florian Westphal
@ 2025-07-12  2:43   ` Shaun Brady
  0 siblings, 0 replies; 3+ messages in thread
From: Shaun Brady @ 2025-07-12  2:43 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel

On Fri, Jul 11, 2025 at 12:27:45PM +0200, Florian Westphal wrote:
> 
> Why?  This is hard, the kernel has no notion of data types.
> 

I speculated I could contain things up in userland, but as you
stated, the kernel got involved (would need to be aware of the change).

If the ask is more philosophical, it would have been for educational
purposes.

> 
> The kernel doesn't know what an ipv4 or ipv6 address is.
> It only knows the total key size.

This became clear, and clear that I wasn't missing anything. Further,
it indicated my thinking was swimming upstream from a design goal of
netfilter, so to hear you conclude with ...
> 
> ...I don't think its worth the pain.  Also because then ipv4 becomes
> indistinguishable from on-wire mapped addresses.
> 

... is mostly what I needed.


Thank you for taking the time to answer my open ended inquiries,
especially when no real code was presented.

I'll find something new to chew on shortly!


Thanks!


SB

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-07-12  2:43 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-11  3:30 Feedback on variable sized set elements Shaun Brady
2025-07-11 10:27 ` Florian Westphal
2025-07-12  2:43   ` Shaun Brady

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).