Message ID | 20210603101425.560384-8-me@ubique.spb.ru |
---|---|
State | New |
Headers | show |
Series | bpfilter | expand |
On 6/3/21 3:14 AM, Dmitrii Banshchikov wrote: > struct rule is an equivalent of struct ipt_entry. A rule consists of > zero or more matches and a target. A rule has a pointer to its ipt_entry > in entries blob. struct rule should simplify iteration over a blob and > avoid blob's guts in code generation. > > Signed-off-by: Dmitrii Banshchikov <me@ubique.spb.ru> > --- > net/bpfilter/Makefile | 2 +- > net/bpfilter/rule.c | 163 ++++++++++++++++++ > net/bpfilter/rule.h | 32 ++++ > .../testing/selftests/bpf/bpfilter/.gitignore | 1 + > tools/testing/selftests/bpf/bpfilter/Makefile | 5 +- > .../selftests/bpf/bpfilter/bpfilter_util.h | 8 + > .../selftests/bpf/bpfilter/test_rule.c | 55 ++++++ > 7 files changed, 264 insertions(+), 2 deletions(-) > create mode 100644 net/bpfilter/rule.c > create mode 100644 net/bpfilter/rule.h > create mode 100644 tools/testing/selftests/bpf/bpfilter/test_rule.c > [...] > + > +bool rule_has_standard_target(const struct rule *rule); > +bool is_rule_unconditional(const struct rule *rule); > +int init_rule(struct context *ctx, const struct bpfilter_ipt_entry *ipt_entry, struct rule *rule); > +void free_rule(struct rule *rule); > + > +#endif // NET_BPFILTER_RULE_H > diff --git a/tools/testing/selftests/bpf/bpfilter/.gitignore b/tools/testing/selftests/bpf/bpfilter/.gitignore > index 7e077f506af1..4d7c5083d980 100644 > --- a/tools/testing/selftests/bpf/bpfilter/.gitignore > +++ b/tools/testing/selftests/bpf/bpfilter/.gitignore > @@ -2,3 +2,4 @@ > test_map > test_match > test_target > +test_rule > diff --git a/tools/testing/selftests/bpf/bpfilter/Makefile b/tools/testing/selftests/bpf/bpfilter/Makefile > index a11775e8b5af..27a1ddcb6dc9 100644 > --- a/tools/testing/selftests/bpf/bpfilter/Makefile > +++ b/tools/testing/selftests/bpf/bpfilter/Makefile > @@ -11,6 +11,7 @@ CFLAGS += -Wall -g -pthread -I$(TOOLSINCDIR) -I$(APIDIR) -I$(BPFILTERSRCDIR) > TEST_GEN_PROGS += test_map > TEST_GEN_PROGS += test_match > TEST_GEN_PROGS += test_target > +TEST_GEN_PROGS += test_rule > > KSFT_KHDR_INSTALL := 1 > > @@ -19,9 +20,11 @@ include ../../lib.mk > BPFILTER_MATCH_SRCS := $(BPFILTERSRCDIR)/match.c $(BPFILTERSRCDIR)/xt_udp.c > BPFILTER_TARGET_SRCS := $(BPFILTERSRCDIR)/target.c > > -BPFILTER_COMMON_SRCS := $(BPFILTERSRCDIR)/map-common.c $(BPFILTERSRCDIR)/context.c > +BPFILTER_COMMON_SRCS := $(BPFILTERSRCDIR)/map-common.c $(BPFILTERSRCDIR)/context.c \ > + $(BPFILTERSRCDIR)/rule.c > BPFILTER_COMMON_SRCS += $(BPFILTER_MATCH_SRCS) $(BPFILTER_TARGET_SRCS) > > $(OUTPUT)/test_map: test_map.c $(BPFILTERSRCDIR)/map-common.c > $(OUTPUT)/test_match: test_match.c $(BPFILTER_COMMON_SRCS) > $(OUTPUT)/test_target: test_target.c $(BPFILTER_COMMON_SRCS) > +$(OUTPUT)/test_rule: test_rule.c $(BPFILTER_COMMON_SRCS) > diff --git a/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h b/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h > index d82ff86f280e..55fb0e959fca 100644 > --- a/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h > +++ b/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h > @@ -7,6 +7,7 @@ > #include <linux/netfilter/x_tables.h> > > #include <stdio.h> > +#include <string.h> > > static inline void init_standard_target(struct xt_standard_target *ipt_target, int revision, > int verdict) > @@ -28,4 +29,11 @@ static inline void init_error_target(struct xt_error_target *ipt_target, int rev > snprintf(ipt_target->errorname, sizeof(ipt_target->errorname), "%s", error_name); > } > > +static inline void init_standard_entry(struct ipt_entry *entry, __u16 matches_size) > +{ > + memset(entry, 0, sizeof(*entry)); > + entry->target_offset = sizeof(*entry) + matches_size; > + entry->next_offset = sizeof(*entry) + matches_size + sizeof(struct xt_standard_target); > +} > + > #endif // BPFILTER_UTIL_H > diff --git a/tools/testing/selftests/bpf/bpfilter/test_rule.c b/tools/testing/selftests/bpf/bpfilter/test_rule.c > new file mode 100644 > index 000000000000..fe12adf32fe5 > --- /dev/null > +++ b/tools/testing/selftests/bpf/bpfilter/test_rule.c > @@ -0,0 +1,55 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#define _GNU_SOURCE > + > +#include "rule.h" > + > +#include <linux/bpfilter.h> > +#include <linux/err.h> > + > +#include <linux/netfilter_ipv4/ip_tables.h> > + > +#include <stdio.h> > +#include <stdlib.h> > + > +#include "../../kselftest_harness.h" > + > +#include "context.h" > +#include "rule.h" > + > +#include "bpfilter_util.h" > + > +FIXTURE(test_standard_rule) > +{ > + struct context ctx; > + struct { > + struct ipt_entry entry; > + struct xt_standard_target target; > + } entry; > + struct rule rule; > +}; > + > +FIXTURE_SETUP(test_standard_rule) > +{ > + const int verdict = BPFILTER_NF_ACCEPT; > + > + ASSERT_EQ(create_context(&self->ctx), 0); > + self->ctx.log_file = stderr; > + > + init_standard_entry(&self->entry.entry, 0); > + init_standard_target(&self->entry.target, 0, -verdict - 1); > +} > + > +FIXTURE_TEARDOWN(test_standard_rule) > +{ > + free_rule(&self->rule); > + free_context(&self->ctx); > +} > + > +TEST_F(test_standard_rule, init) > +{ > + ASSERT_EQ(0, init_rule(&self->ctx, (const struct bpfilter_ipt_entry *)&self->entry.entry, > + &self->rule)); > +} > + > +TEST_HARNESS_MAIN When compiling selftests/bpf/bpfilter, I got the following compilation warning: gcc -Wall -g -pthread -I/home/yhs/work/bpf-next/tools/include -I/home/yhs/work/bpf-next/tools/include/uapi -I../../../../../net/bpfilter test_rule.c ../../../../../net/bpfilter/map-common.c ../../../../../net/bpfilter/context.c ../../../../../net/bpfilter/rule.c ../../../../../net/bpfilter/table.c ../../../../../net/bpfilter/match.c ../../../../../net/bpfilter/xt_udp.c ../../../../../net/bpfilter/target.c -o /home/yhs/work/bpf-next/tools/testing/selftests/bpf/bpfilter/test_rule In file included from test_rule.c:15: ../../kselftest_harness.h:674: warning: "ARRAY_SIZE" redefined #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) In file included from /usr/include/linux/netfilter/x_tables.h:4, from /usr/include/linux/netfilter_ipv4/ip_tables.h:24, from test_rule.c:10: /home/yhs/work/bpf-next/tools/include/linux/kernel.h:105: note: this is the location of the previous definition #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
On Wed, Jun 09, 2021 at 05:30:56PM -0700, Yonghong Song wrote: > > > On 6/3/21 3:14 AM, Dmitrii Banshchikov wrote: > > struct rule is an equivalent of struct ipt_entry. A rule consists of > > zero or more matches and a target. A rule has a pointer to its ipt_entry > > in entries blob. struct rule should simplify iteration over a blob and > > avoid blob's guts in code generation. > > > > Signed-off-by: Dmitrii Banshchikov <me@ubique.spb.ru> > > --- > > net/bpfilter/Makefile | 2 +- > > net/bpfilter/rule.c | 163 ++++++++++++++++++ > > net/bpfilter/rule.h | 32 ++++ > > .../testing/selftests/bpf/bpfilter/.gitignore | 1 + > > tools/testing/selftests/bpf/bpfilter/Makefile | 5 +- > > .../selftests/bpf/bpfilter/bpfilter_util.h | 8 + > > .../selftests/bpf/bpfilter/test_rule.c | 55 ++++++ > > 7 files changed, 264 insertions(+), 2 deletions(-) > > create mode 100644 net/bpfilter/rule.c > > create mode 100644 net/bpfilter/rule.h > > create mode 100644 tools/testing/selftests/bpf/bpfilter/test_rule.c > > > [...] > > + > > +bool rule_has_standard_target(const struct rule *rule); > > +bool is_rule_unconditional(const struct rule *rule); > > +int init_rule(struct context *ctx, const struct bpfilter_ipt_entry *ipt_entry, struct rule *rule); > > +void free_rule(struct rule *rule); > > + > > +#endif // NET_BPFILTER_RULE_H > > diff --git a/tools/testing/selftests/bpf/bpfilter/.gitignore b/tools/testing/selftests/bpf/bpfilter/.gitignore > > index 7e077f506af1..4d7c5083d980 100644 > > --- a/tools/testing/selftests/bpf/bpfilter/.gitignore > > +++ b/tools/testing/selftests/bpf/bpfilter/.gitignore > > @@ -2,3 +2,4 @@ > > test_map > > test_match > > test_target > > +test_rule > > diff --git a/tools/testing/selftests/bpf/bpfilter/Makefile b/tools/testing/selftests/bpf/bpfilter/Makefile > > index a11775e8b5af..27a1ddcb6dc9 100644 > > --- a/tools/testing/selftests/bpf/bpfilter/Makefile > > +++ b/tools/testing/selftests/bpf/bpfilter/Makefile > > @@ -11,6 +11,7 @@ CFLAGS += -Wall -g -pthread -I$(TOOLSINCDIR) -I$(APIDIR) -I$(BPFILTERSRCDIR) > > TEST_GEN_PROGS += test_map > > TEST_GEN_PROGS += test_match > > TEST_GEN_PROGS += test_target > > +TEST_GEN_PROGS += test_rule > > KSFT_KHDR_INSTALL := 1 > > @@ -19,9 +20,11 @@ include ../../lib.mk > > BPFILTER_MATCH_SRCS := $(BPFILTERSRCDIR)/match.c $(BPFILTERSRCDIR)/xt_udp.c > > BPFILTER_TARGET_SRCS := $(BPFILTERSRCDIR)/target.c > > -BPFILTER_COMMON_SRCS := $(BPFILTERSRCDIR)/map-common.c $(BPFILTERSRCDIR)/context.c > > +BPFILTER_COMMON_SRCS := $(BPFILTERSRCDIR)/map-common.c $(BPFILTERSRCDIR)/context.c \ > > + $(BPFILTERSRCDIR)/rule.c > > BPFILTER_COMMON_SRCS += $(BPFILTER_MATCH_SRCS) $(BPFILTER_TARGET_SRCS) > > $(OUTPUT)/test_map: test_map.c $(BPFILTERSRCDIR)/map-common.c > > $(OUTPUT)/test_match: test_match.c $(BPFILTER_COMMON_SRCS) > > $(OUTPUT)/test_target: test_target.c $(BPFILTER_COMMON_SRCS) > > +$(OUTPUT)/test_rule: test_rule.c $(BPFILTER_COMMON_SRCS) > > diff --git a/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h b/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h > > index d82ff86f280e..55fb0e959fca 100644 > > --- a/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h > > +++ b/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h > > @@ -7,6 +7,7 @@ > > #include <linux/netfilter/x_tables.h> > > #include <stdio.h> > > +#include <string.h> > > static inline void init_standard_target(struct xt_standard_target *ipt_target, int revision, > > int verdict) > > @@ -28,4 +29,11 @@ static inline void init_error_target(struct xt_error_target *ipt_target, int rev > > snprintf(ipt_target->errorname, sizeof(ipt_target->errorname), "%s", error_name); > > } > > +static inline void init_standard_entry(struct ipt_entry *entry, __u16 matches_size) > > +{ > > + memset(entry, 0, sizeof(*entry)); > > + entry->target_offset = sizeof(*entry) + matches_size; > > + entry->next_offset = sizeof(*entry) + matches_size + sizeof(struct xt_standard_target); > > +} > > + > > #endif // BPFILTER_UTIL_H > > diff --git a/tools/testing/selftests/bpf/bpfilter/test_rule.c b/tools/testing/selftests/bpf/bpfilter/test_rule.c > > new file mode 100644 > > index 000000000000..fe12adf32fe5 > > --- /dev/null > > +++ b/tools/testing/selftests/bpf/bpfilter/test_rule.c > > @@ -0,0 +1,55 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +#define _GNU_SOURCE > > + > > +#include "rule.h" > > + > > +#include <linux/bpfilter.h> > > +#include <linux/err.h> > > + > > +#include <linux/netfilter_ipv4/ip_tables.h> > > + > > +#include <stdio.h> > > +#include <stdlib.h> > > + > > +#include "../../kselftest_harness.h" > > + > > +#include "context.h" > > +#include "rule.h" > > + > > +#include "bpfilter_util.h" > > + > > +FIXTURE(test_standard_rule) > > +{ > > + struct context ctx; > > + struct { > > + struct ipt_entry entry; > > + struct xt_standard_target target; > > + } entry; > > + struct rule rule; > > +}; > > + > > +FIXTURE_SETUP(test_standard_rule) > > +{ > > + const int verdict = BPFILTER_NF_ACCEPT; > > + > > + ASSERT_EQ(create_context(&self->ctx), 0); > > + self->ctx.log_file = stderr; > > + > > + init_standard_entry(&self->entry.entry, 0); > > + init_standard_target(&self->entry.target, 0, -verdict - 1); > > +} > > + > > +FIXTURE_TEARDOWN(test_standard_rule) > > +{ > > + free_rule(&self->rule); > > + free_context(&self->ctx); > > +} > > + > > +TEST_F(test_standard_rule, init) > > +{ > > + ASSERT_EQ(0, init_rule(&self->ctx, (const struct bpfilter_ipt_entry *)&self->entry.entry, > > + &self->rule)); > > +} > > + > > +TEST_HARNESS_MAIN > > When compiling selftests/bpf/bpfilter, I got the following compilation > warning: > > gcc -Wall -g -pthread -I/home/yhs/work/bpf-next/tools/include > -I/home/yhs/work/bpf-next/tools/include/uapi -I../../../../../net/bpfilter > test_rule.c ../../../../../net/bpfilter/map-common.c > ../../../../../net/bpfilter/context.c ../../../../../net/bpfilter/rule.c > ../../../../../net/bpfilter/table.c ../../../../../net/bpfilter/match.c > ../../../../../net/bpfilter/xt_udp.c ../../../../../net/bpfilter/target.c > -o /home/yhs/work/bpf-next/tools/testing/selftests/bpf/bpfilter/test_rule > In file included from test_rule.c:15: > ../../kselftest_harness.h:674: warning: "ARRAY_SIZE" redefined > #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) > > In file included from /usr/include/linux/netfilter/x_tables.h:4, > from /usr/include/linux/netfilter_ipv4/ip_tables.h:24, > from test_rule.c:10: > /home/yhs/work/bpf-next/tools/include/linux/kernel.h:105: note: this is the > location of the previous definition > #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + > __must_be_array(arr)) > Hmm. I cannot reproduce it locally now though I saw this error and fixed it by removing some of the includes from header files. I will double check it. -- Dmitrii Banshchikov
diff --git a/net/bpfilter/Makefile b/net/bpfilter/Makefile index 031c9dd40d2d..7ce961162283 100644 --- a/net/bpfilter/Makefile +++ b/net/bpfilter/Makefile @@ -4,7 +4,7 @@ # userprogs := bpfilter_umh -bpfilter_umh-objs := main.o map-common.o context.o match.o target.o +bpfilter_umh-objs := main.o map-common.o context.o match.o target.o rule.o bpfilter_umh-objs += xt_udp.o userccflags += -I $(srctree)/tools/include/ -I $(srctree)/tools/include/uapi diff --git a/net/bpfilter/rule.c b/net/bpfilter/rule.c new file mode 100644 index 000000000000..6018b4b7c0cc --- /dev/null +++ b/net/bpfilter/rule.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 Telegram FZ-LLC + */ + +#define _GNU_SOURCE + +#include "rule.h" + +#include "../../include/uapi/linux/bpfilter.h" + +#include <linux/err.h> +#include <linux/netfilter/x_tables.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "context.h" +#include "match.h" + +static const struct bpfilter_ipt_target * +ipt_entry_target(const struct bpfilter_ipt_entry *ipt_entry) +{ + return (const void *)ipt_entry + ipt_entry->target_offset; +} + +static const struct bpfilter_ipt_match *ipt_entry_match(const struct bpfilter_ipt_entry *entry, + size_t offset) +{ + return (const void *)entry + offset; +} + +static int ipt_entry_num_matches(const struct bpfilter_ipt_entry *ipt_entry) +{ + const struct bpfilter_ipt_match *ipt_match; + uint32_t offset = sizeof(*ipt_entry); + int num_matches = 0; + + while (offset < ipt_entry->target_offset) { + ipt_match = ipt_entry_match(ipt_entry, offset); + + if ((uintptr_t)ipt_match % __alignof__(struct bpfilter_ipt_match)) + return -EINVAL; + + if (ipt_entry->target_offset < offset + sizeof(*ipt_match)) + return -EINVAL; + + if (ipt_match->u.match_size < sizeof(*ipt_match)) + return -EINVAL; + + if (ipt_entry->target_offset < offset + ipt_match->u.match_size) + return -EINVAL; + + ++num_matches; + offset += ipt_match->u.match_size; + } + + if (offset != ipt_entry->target_offset) + return -EINVAL; + + return num_matches; +} + +static int init_rule_matches(struct context *ctx, const struct bpfilter_ipt_entry *ipt_entry, + struct rule *rule) +{ + const struct bpfilter_ipt_match *ipt_match; + uint32_t offset = sizeof(*ipt_entry); + struct match *match; + int err; + + rule->matches = calloc(rule->num_matches, sizeof(rule->matches[0])); + if (!rule->matches) + return -ENOMEM; + + match = rule->matches; + while (offset < ipt_entry->target_offset) { + ipt_match = ipt_entry_match(ipt_entry, offset); + err = init_match(ctx, ipt_match, match); + if (err) { + free(rule->matches); + rule->matches = NULL; + return err; + } + + ++match; + offset += ipt_match->u.match_size; + } + + return 0; +} + +static int check_ipt_entry_ip(const struct bpfilter_ipt_ip *ip) +{ + if (ip->flags & ~BPFILTER_IPT_F_MASK) + return -EINVAL; + + if (ip->invflags & ~BPFILTER_IPT_INV_MASK) + return -EINVAL; + + return 0; +} + +bool rule_has_standard_target(const struct rule *rule) +{ + return rule->target.target_ops == &standard_target_ops; +} + +bool is_rule_unconditional(const struct rule *rule) +{ + static const struct bpfilter_ipt_ip unconditional; + + if (rule->num_matches) + return false; + + return !memcmp(&rule->ipt_entry->ip, &unconditional, sizeof(unconditional)); +} + +int init_rule(struct context *ctx, const struct bpfilter_ipt_entry *ipt_entry, struct rule *rule) +{ + const struct bpfilter_ipt_target *ipt_target; + int err; + + err = check_ipt_entry_ip(&ipt_entry->ip); + if (err) + return err; + + if (ipt_entry->target_offset < sizeof(*ipt_entry)) + return -EINVAL; + + if (ipt_entry->next_offset < ipt_entry->target_offset + sizeof(*ipt_target)) + return -EINVAL; + + ipt_target = ipt_entry_target(ipt_entry); + + if (ipt_target->u.target_size < sizeof(*ipt_target)) + return -EINVAL; + + if (ipt_entry->next_offset < ipt_entry->target_offset + ipt_target->u.target_size) + return -EINVAL; + + err = init_target(ctx, ipt_target, &rule->target); + if (err) + return err; + + if (rule_has_standard_target(rule)) { + if (XT_ALIGN(ipt_entry->target_offset + + sizeof(struct bpfilter_ipt_standard_target)) != ipt_entry->next_offset) + return -EINVAL; + } + + rule->num_matches = ipt_entry_num_matches(ipt_entry); + if (rule->num_matches < 0) + return rule->num_matches; + + return init_rule_matches(ctx, ipt_entry, rule); +} + +void free_rule(struct rule *rule) +{ + free(rule->matches); +} diff --git a/net/bpfilter/rule.h b/net/bpfilter/rule.h new file mode 100644 index 000000000000..cf879a19c670 --- /dev/null +++ b/net/bpfilter/rule.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 Telegram FZ-LLC + */ + +#ifndef NET_BPFILTER_RULE_H +#define NET_BPFILTER_RULE_H + +#include <stdint.h> +#include <stdbool.h> + +#include "target.h" + +struct bpfilter_ipt_entry; +struct context; +struct match; + +struct rule { + const struct bpfilter_ipt_entry *ipt_entry; + uint32_t came_from; + uint32_t hook_mask; + uint16_t num_matches; + struct match *matches; + struct target target; +}; + +bool rule_has_standard_target(const struct rule *rule); +bool is_rule_unconditional(const struct rule *rule); +int init_rule(struct context *ctx, const struct bpfilter_ipt_entry *ipt_entry, struct rule *rule); +void free_rule(struct rule *rule); + +#endif // NET_BPFILTER_RULE_H diff --git a/tools/testing/selftests/bpf/bpfilter/.gitignore b/tools/testing/selftests/bpf/bpfilter/.gitignore index 7e077f506af1..4d7c5083d980 100644 --- a/tools/testing/selftests/bpf/bpfilter/.gitignore +++ b/tools/testing/selftests/bpf/bpfilter/.gitignore @@ -2,3 +2,4 @@ test_map test_match test_target +test_rule diff --git a/tools/testing/selftests/bpf/bpfilter/Makefile b/tools/testing/selftests/bpf/bpfilter/Makefile index a11775e8b5af..27a1ddcb6dc9 100644 --- a/tools/testing/selftests/bpf/bpfilter/Makefile +++ b/tools/testing/selftests/bpf/bpfilter/Makefile @@ -11,6 +11,7 @@ CFLAGS += -Wall -g -pthread -I$(TOOLSINCDIR) -I$(APIDIR) -I$(BPFILTERSRCDIR) TEST_GEN_PROGS += test_map TEST_GEN_PROGS += test_match TEST_GEN_PROGS += test_target +TEST_GEN_PROGS += test_rule KSFT_KHDR_INSTALL := 1 @@ -19,9 +20,11 @@ include ../../lib.mk BPFILTER_MATCH_SRCS := $(BPFILTERSRCDIR)/match.c $(BPFILTERSRCDIR)/xt_udp.c BPFILTER_TARGET_SRCS := $(BPFILTERSRCDIR)/target.c -BPFILTER_COMMON_SRCS := $(BPFILTERSRCDIR)/map-common.c $(BPFILTERSRCDIR)/context.c +BPFILTER_COMMON_SRCS := $(BPFILTERSRCDIR)/map-common.c $(BPFILTERSRCDIR)/context.c \ + $(BPFILTERSRCDIR)/rule.c BPFILTER_COMMON_SRCS += $(BPFILTER_MATCH_SRCS) $(BPFILTER_TARGET_SRCS) $(OUTPUT)/test_map: test_map.c $(BPFILTERSRCDIR)/map-common.c $(OUTPUT)/test_match: test_match.c $(BPFILTER_COMMON_SRCS) $(OUTPUT)/test_target: test_target.c $(BPFILTER_COMMON_SRCS) +$(OUTPUT)/test_rule: test_rule.c $(BPFILTER_COMMON_SRCS) diff --git a/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h b/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h index d82ff86f280e..55fb0e959fca 100644 --- a/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h +++ b/tools/testing/selftests/bpf/bpfilter/bpfilter_util.h @@ -7,6 +7,7 @@ #include <linux/netfilter/x_tables.h> #include <stdio.h> +#include <string.h> static inline void init_standard_target(struct xt_standard_target *ipt_target, int revision, int verdict) @@ -28,4 +29,11 @@ static inline void init_error_target(struct xt_error_target *ipt_target, int rev snprintf(ipt_target->errorname, sizeof(ipt_target->errorname), "%s", error_name); } +static inline void init_standard_entry(struct ipt_entry *entry, __u16 matches_size) +{ + memset(entry, 0, sizeof(*entry)); + entry->target_offset = sizeof(*entry) + matches_size; + entry->next_offset = sizeof(*entry) + matches_size + sizeof(struct xt_standard_target); +} + #endif // BPFILTER_UTIL_H diff --git a/tools/testing/selftests/bpf/bpfilter/test_rule.c b/tools/testing/selftests/bpf/bpfilter/test_rule.c new file mode 100644 index 000000000000..fe12adf32fe5 --- /dev/null +++ b/tools/testing/selftests/bpf/bpfilter/test_rule.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE + +#include "rule.h" + +#include <linux/bpfilter.h> +#include <linux/err.h> + +#include <linux/netfilter_ipv4/ip_tables.h> + +#include <stdio.h> +#include <stdlib.h> + +#include "../../kselftest_harness.h" + +#include "context.h" +#include "rule.h" + +#include "bpfilter_util.h" + +FIXTURE(test_standard_rule) +{ + struct context ctx; + struct { + struct ipt_entry entry; + struct xt_standard_target target; + } entry; + struct rule rule; +}; + +FIXTURE_SETUP(test_standard_rule) +{ + const int verdict = BPFILTER_NF_ACCEPT; + + ASSERT_EQ(create_context(&self->ctx), 0); + self->ctx.log_file = stderr; + + init_standard_entry(&self->entry.entry, 0); + init_standard_target(&self->entry.target, 0, -verdict - 1); +} + +FIXTURE_TEARDOWN(test_standard_rule) +{ + free_rule(&self->rule); + free_context(&self->ctx); +} + +TEST_F(test_standard_rule, init) +{ + ASSERT_EQ(0, init_rule(&self->ctx, (const struct bpfilter_ipt_entry *)&self->entry.entry, + &self->rule)); +} + +TEST_HARNESS_MAIN
struct rule is an equivalent of struct ipt_entry. A rule consists of zero or more matches and a target. A rule has a pointer to its ipt_entry in entries blob. struct rule should simplify iteration over a blob and avoid blob's guts in code generation. Signed-off-by: Dmitrii Banshchikov <me@ubique.spb.ru> --- net/bpfilter/Makefile | 2 +- net/bpfilter/rule.c | 163 ++++++++++++++++++ net/bpfilter/rule.h | 32 ++++ .../testing/selftests/bpf/bpfilter/.gitignore | 1 + tools/testing/selftests/bpf/bpfilter/Makefile | 5 +- .../selftests/bpf/bpfilter/bpfilter_util.h | 8 + .../selftests/bpf/bpfilter/test_rule.c | 55 ++++++ 7 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 net/bpfilter/rule.c create mode 100644 net/bpfilter/rule.h create mode 100644 tools/testing/selftests/bpf/bpfilter/test_rule.c