Skip to content

Commit

Permalink
netfilter: ctnetlink: support filtering by zone
Browse files Browse the repository at this point in the history
conntrack zones are heavily used by tools like openvswitch to run
multiple virtual "routers" on a single machine. In this context each
conntrack zone matches to a single router, thereby preventing
overlapping IPs from becoming issues.
In these systems it is common to operate on all conntrack entries of a
given zone, e.g. to delete them when a router is deleted. Previously this
required these tools to dump the full conntrack table and filter out the
relevant entries in userspace potentially causing performance issues.

To do this we reuse the existing CTA_ZONE attribute. This was previous
parsed but not used during dump and flush requests. Now if CTA_ZONE is
set we filter these operations based on the provided zone.
However this means that users that previously passed CTA_ZONE will
experience a difference in functionality.

Alternatively CTA_FILTER could have been used for the same
functionality. However it is not yet supported during flush requests and
is only available when using AF_INET or AF_INET6.

Co-developed-by: Luca Czesla <luca.czesla@mail.schwarz>
Signed-off-by: Luca Czesla <luca.czesla@mail.schwarz>
Co-developed-by: Max Lamprecht <max.lamprecht@mail.schwarz>
Signed-off-by: Max Lamprecht <max.lamprecht@mail.schwarz>
Signed-off-by: Felix Huettner <felix.huettner@mail.schwarz>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
felixhuettner authored and ummakynes committed Dec 22, 2023
1 parent 08e4c8c commit eff3c55
Show file tree
Hide file tree
Showing 4 changed files with 442 additions and 5 deletions.
12 changes: 8 additions & 4 deletions net/netfilter/nf_conntrack_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -992,13 +992,13 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
if (err)
goto err_filter;

if (!cda[CTA_FILTER])
return filter;

err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone);
if (err < 0)
goto err_filter;

if (!cda[CTA_FILTER])
return filter;

err = ctnetlink_parse_filter(cda[CTA_FILTER], filter);
if (err < 0)
goto err_filter;
Expand Down Expand Up @@ -1043,7 +1043,7 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)

static bool ctnetlink_needs_filter(u8 family, const struct nlattr * const *cda)
{
return family || cda[CTA_MARK] || cda[CTA_FILTER] || cda[CTA_STATUS];
return family || cda[CTA_MARK] || cda[CTA_FILTER] || cda[CTA_STATUS] || cda[CTA_ZONE];
}

static int ctnetlink_start(struct netlink_callback *cb)
Expand Down Expand Up @@ -1148,6 +1148,10 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
if (filter->family && nf_ct_l3num(ct) != filter->family)
goto ignore_entry;

if (filter->zone.id != NF_CT_DEFAULT_ZONE_ID &&
!nf_ct_zone_equal_any(ct, &filter->zone))
goto ignore_entry;

if (filter->orig_flags) {
tuple = nf_ct_tuple(ct, IP_CT_DIR_ORIGINAL);
if (!ctnetlink_filter_match_tuple(&filter->orig, tuple,
Expand Down
2 changes: 2 additions & 0 deletions tools/testing/selftests/netfilter/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
nf-queue
connect_close
audit_logread
conntrack_dump_flush
sctp_collision
3 changes: 2 additions & 1 deletion tools/testing/selftests/netfilter/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ HOSTPKG_CONFIG := pkg-config
CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null)
LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl)

TEST_GEN_FILES = nf-queue connect_close audit_logread sctp_collision
TEST_GEN_FILES = nf-queue connect_close audit_logread sctp_collision \
conntrack_dump_flush

include ../lib.mk
Loading

0 comments on commit eff3c55

Please sign in to comment.