From 7a3367891b7eddccf3fee8a38351de3aae3545fb Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Wed, 4 Mar 2026 16:06:24 -0800 Subject: [PATCH 1/2] daemon: cgen: emit missing skb load in _bf_nf_gen_inline_get_skb --- src/bpfilter/cgen/nf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bpfilter/cgen/nf.c b/src/bpfilter/cgen/nf.c index 8d2957b7d..4013bd64c 100644 --- a/src/bpfilter/cgen/nf.c +++ b/src/bpfilter/cgen/nf.c @@ -147,6 +147,7 @@ static int _bf_nf_gen_inline_get_skb(struct bf_program *program, int reg) EMIT(program, BPF_LDX_MEM(BPF_DW, reg, BPF_REG_10, BF_PROG_CTX_OFF(arg))); if ((offset = bf_btf_get_field_off("bpf_nf_ctx", "skb")) < 0) return offset; + EMIT(program, BPF_LDX_MEM(BPF_DW, reg, reg, offset)); return 0; } From 6af7c7f4f20089222408c7c890bad15625e0518a Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Wed, 4 Mar 2026 16:08:27 -0800 Subject: [PATCH 2/2] daemon: cgen: route matcher codegen through flavor-specific dispatch Replace gen_inline_get_mark and gen_inline_get_skb in bf_flavor_ops with a single gen_inline_matcher callback that gives each flavor full control over matcher codegen. Packet-based flavors intercept matcher types they handle specially (e.g., meta.mark on __sk_buff-based flavors) and delegate the rest to bf_matcher_generate_packet(). Extract bf_matcher_generate_packet() from program.c into cgen/ matcher/packet.{h,c} where it belongs alongside the matcher codegen it dispatches to. Export bf_matcher_generate_meta_mark() and bf_matcher_generate_meta_flow_hash() as comparison-only helpers. Callers load the value into BPF_REG_1 before calling. This is a prerequisite for CGROUP_SOCK_ADDR support, where the flavor needs to intercept matchers like ip4.daddr and generate bytecode that reads from bpf_sock_addr fields instead of packet headers. --- src/bpfilter/CMakeLists.txt | 1 + src/bpfilter/cgen/cgroup_skb.c | 39 +++++++----- src/bpfilter/cgen/matcher/meta.c | 39 ++++++------ src/bpfilter/cgen/matcher/meta.h | 26 ++++++++ src/bpfilter/cgen/matcher/packet.c | 75 ++++++++++++++++++++++ src/bpfilter/cgen/matcher/packet.h | 27 ++++++++ src/bpfilter/cgen/nf.c | 53 +++++++++------- src/bpfilter/cgen/program.c | 77 ++--------------------- src/bpfilter/cgen/tc.c | 35 +++++++---- src/bpfilter/cgen/xdp.c | 2 + src/libbpfilter/include/bpfilter/flavor.h | 13 +++- 11 files changed, 242 insertions(+), 145 deletions(-) create mode 100644 src/bpfilter/cgen/matcher/packet.c create mode 100644 src/bpfilter/cgen/matcher/packet.h diff --git a/src/bpfilter/CMakeLists.txt b/src/bpfilter/CMakeLists.txt index f951efc78..d630c1368 100644 --- a/src/bpfilter/CMakeLists.txt +++ b/src/bpfilter/CMakeLists.txt @@ -23,6 +23,7 @@ add_executable(bpfilter ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/tcp.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/tcp.c ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/udp.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/udp.c ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/meta.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/meta.c + ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/packet.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/packet.c ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/set.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/set.c ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/icmp.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/icmp.c ${CMAKE_CURRENT_SOURCE_DIR}/cgen/nf.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/nf.c diff --git a/src/bpfilter/cgen/cgroup_skb.c b/src/bpfilter/cgen/cgroup_skb.c index 00a276af6..7d3330ea2 100644 --- a/src/bpfilter/cgen/cgroup_skb.c +++ b/src/bpfilter/cgen/cgroup_skb.c @@ -15,9 +15,12 @@ #include #include #include +#include #include #include "cgen/cgen.h" +#include "cgen/matcher/meta.h" +#include "cgen/matcher/packet.h" #include "cgen/program.h" #include "cgen/stub.h" #include "cgen/swich.h" @@ -114,30 +117,35 @@ static int _bf_cgroup_skb_gen_inline_set_mark(struct bf_program *program, return 0; } -static int _bf_cgroup_skb_gen_inline_get_mark(struct bf_program *program, - int reg) +static int _bf_cgroup_skb_gen_inline_matcher(struct bf_program *program, + const struct bf_matcher *matcher) { - EMIT(program, - BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(arg))); - EMIT(program, - BPF_LDX_MEM(BPF_W, reg, BPF_REG_1, offsetof(struct __sk_buff, mark))); + assert(program); + assert(matcher); - return 0; -} + switch (bf_matcher_get_type(matcher)) { + case BF_MATCHER_META_MARK: + EMIT(program, + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(arg))); + EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, + offsetof(struct __sk_buff, mark))); -static int _bf_cgroup_skb_gen_inline_get_skb(struct bf_program *program, - int reg) -{ - EMIT(program, BPF_LDX_MEM(BPF_DW, reg, BPF_REG_10, BF_PROG_CTX_OFF(arg))); + return bf_matcher_generate_meta_mark_cmp(program, matcher); + case BF_MATCHER_META_FLOW_HASH: + EMIT(program, + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(arg))); - return 0; + return bf_matcher_generate_meta_flow_hash_cmp(program, matcher); + default: + return bf_matcher_generate_packet(program, matcher); + } } /** * Convert a standard verdict into a return value. * * @param verdict Verdict to convert. Must be valid. - * @return TC return code corresponding to the verdict, as an integer. + * @return Cgroup return code corresponding to the verdict, as an integer. */ static int _bf_cgroup_skb_get_verdict(enum bf_verdict verdict) { @@ -155,7 +163,6 @@ const struct bf_flavor_ops bf_flavor_ops_cgroup_skb = { .gen_inline_prologue = _bf_cgroup_skb_gen_inline_prologue, .gen_inline_epilogue = _bf_cgroup_skb_gen_inline_epilogue, .gen_inline_set_mark = _bf_cgroup_skb_gen_inline_set_mark, - .gen_inline_get_mark = _bf_cgroup_skb_gen_inline_get_mark, - .gen_inline_get_skb = _bf_cgroup_skb_gen_inline_get_skb, .get_verdict = _bf_cgroup_skb_get_verdict, + .gen_inline_matcher = _bf_cgroup_skb_gen_inline_matcher, }; diff --git a/src/bpfilter/cgen/matcher/meta.c b/src/bpfilter/cgen/matcher/meta.c index 02f123006..719e3fb52 100644 --- a/src/bpfilter/cgen/matcher/meta.c +++ b/src/bpfilter/cgen/matcher/meta.c @@ -141,15 +141,15 @@ static int _bf_matcher_generate_meta_port(struct bf_program *program, return 0; } -static int _bf_matcher_generate_meta_mark(struct bf_program *program, - const struct bf_matcher *matcher) +int bf_matcher_generate_meta_mark_cmp(struct bf_program *program, + const struct bf_matcher *matcher) { - uint32_t mark = *(uint32_t *)bf_matcher_payload(matcher); - int r; + uint32_t mark; - r = program->runtime.ops->gen_inline_get_mark(program, BPF_REG_1); - if (r) - return bf_err_r(r, "failed to get inline mark"); + assert(program); + assert(matcher); + + mark = *(uint32_t *)bf_matcher_payload(matcher); switch (bf_matcher_get_op(matcher)) { case BF_MATCHER_EQ: @@ -169,15 +169,15 @@ static int _bf_matcher_generate_meta_mark(struct bf_program *program, return 0; } -static int _bf_matcher_generate_meta_flow_hash(struct bf_program *program, - const struct bf_matcher *matcher) +int bf_matcher_generate_meta_flow_hash_cmp(struct bf_program *program, + const struct bf_matcher *matcher) { - uint32_t *hash = (uint32_t *)bf_matcher_payload(matcher); - int r; + uint32_t *hash; - r = program->runtime.ops->gen_inline_get_skb(program, BPF_REG_1); - if (r) - return bf_err_r(r, "failed to get inline skb"); + assert(program); + assert(matcher); + + hash = (uint32_t *)bf_matcher_payload(matcher); EMIT(program, BPF_EMIT_CALL(BPF_FUNC_get_hash_recalc)); @@ -276,15 +276,14 @@ int bf_matcher_generate_meta(struct bf_program *program, case BF_MATCHER_META_DPORT: r = _bf_matcher_generate_meta_port(program, matcher); break; - case BF_MATCHER_META_MARK: - r = _bf_matcher_generate_meta_mark(program, matcher); - break; - case BF_MATCHER_META_FLOW_HASH: - r = _bf_matcher_generate_meta_flow_hash(program, matcher); - break; case BF_MATCHER_META_FLOW_PROBABILITY: r = _bf_matcher_generate_meta_flow_probability(program, matcher); break; + case BF_MATCHER_META_MARK: + case BF_MATCHER_META_FLOW_HASH: + return bf_err_r(-ENOTSUP, + "matcher '%s' requires flavor-specific dispatch", + bf_matcher_type_to_str(bf_matcher_get_type(matcher))); default: return bf_err_r(-EINVAL, "unknown matcher type %d", bf_matcher_get_type(matcher)); diff --git a/src/bpfilter/cgen/matcher/meta.h b/src/bpfilter/cgen/matcher/meta.h index 14791c923..7594c92c3 100644 --- a/src/bpfilter/cgen/matcher/meta.h +++ b/src/bpfilter/cgen/matcher/meta.h @@ -10,3 +10,29 @@ struct bf_program; int bf_matcher_generate_meta(struct bf_program *program, const struct bf_matcher *matcher); + +/** + * @brief Generate bytecode to compare a packet mark. + * + * The mark value must already be loaded into `BPF_REG_1`. + * + * @param program Program being generated. Can't be NULL. + * @param matcher Matcher to generate comparison for. Can't be NULL. + * @return 0 on success, negative errno on error. + */ +int bf_matcher_generate_meta_mark_cmp(struct bf_program *program, + const struct bf_matcher *matcher); + +/** + * @brief Generate bytecode to compute and compare a flow hash. + * + * The skb pointer must already be loaded into `BPF_REG_1`. Calls + * `bpf_get_hash_recalc` on the skb, then compares the result against the + * matcher's payload. + * + * @param program Program being generated. Can't be NULL. + * @param matcher Matcher to generate comparison for. Can't be NULL. + * @return 0 on success, negative errno on error. + */ +int bf_matcher_generate_meta_flow_hash_cmp(struct bf_program *program, + const struct bf_matcher *matcher); diff --git a/src/bpfilter/cgen/matcher/packet.c b/src/bpfilter/cgen/matcher/packet.c new file mode 100644 index 000000000..ece0a0089 --- /dev/null +++ b/src/bpfilter/cgen/matcher/packet.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + */ + +#include "cgen/matcher/packet.h" + +#include + +#include +#include +#include + +#include "cgen/matcher/icmp.h" +#include "cgen/matcher/ip4.h" +#include "cgen/matcher/ip6.h" +#include "cgen/matcher/meta.h" +#include "cgen/matcher/set.h" +#include "cgen/matcher/tcp.h" +#include "cgen/matcher/udp.h" +#include "cgen/program.h" + +int bf_matcher_generate_packet(struct bf_program *program, + const struct bf_matcher *matcher) +{ + assert(program); + assert(matcher); + + switch (bf_matcher_get_type(matcher)) { + case BF_MATCHER_META_IFACE: + case BF_MATCHER_META_L3_PROTO: + case BF_MATCHER_META_L4_PROTO: + case BF_MATCHER_META_PROBABILITY: + case BF_MATCHER_META_SPORT: + case BF_MATCHER_META_DPORT: + case BF_MATCHER_META_FLOW_PROBABILITY: + return bf_matcher_generate_meta(program, matcher); + case BF_MATCHER_META_MARK: + case BF_MATCHER_META_FLOW_HASH: + return bf_err_r(-ENOTSUP, + "matcher '%s' is not supported by this flavor", + bf_matcher_type_to_str(bf_matcher_get_type(matcher))); + case BF_MATCHER_IP4_SADDR: + case BF_MATCHER_IP4_SNET: + case BF_MATCHER_IP4_DADDR: + case BF_MATCHER_IP4_DNET: + case BF_MATCHER_IP4_PROTO: + case BF_MATCHER_IP4_DSCP: + return bf_matcher_generate_ip4(program, matcher); + case BF_MATCHER_IP6_SADDR: + case BF_MATCHER_IP6_SNET: + case BF_MATCHER_IP6_DADDR: + case BF_MATCHER_IP6_DNET: + case BF_MATCHER_IP6_NEXTHDR: + case BF_MATCHER_IP6_DSCP: + return bf_matcher_generate_ip6(program, matcher); + case BF_MATCHER_TCP_SPORT: + case BF_MATCHER_TCP_DPORT: + case BF_MATCHER_TCP_FLAGS: + return bf_matcher_generate_tcp(program, matcher); + case BF_MATCHER_UDP_SPORT: + case BF_MATCHER_UDP_DPORT: + return bf_matcher_generate_udp(program, matcher); + case BF_MATCHER_ICMP_TYPE: + case BF_MATCHER_ICMP_CODE: + case BF_MATCHER_ICMPV6_TYPE: + case BF_MATCHER_ICMPV6_CODE: + return bf_matcher_generate_icmp(program, matcher); + case BF_MATCHER_SET: + return bf_matcher_generate_set(program, matcher); + default: + return bf_err_r(-EINVAL, "unknown matcher type %d", + bf_matcher_get_type(matcher)); + } +} diff --git a/src/bpfilter/cgen/matcher/packet.h b/src/bpfilter/cgen/matcher/packet.h new file mode 100644 index 000000000..54acd0a1a --- /dev/null +++ b/src/bpfilter/cgen/matcher/packet.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + */ + +#pragma once + +struct bf_matcher; +struct bf_program; + +/** + * @brief Generate bytecode for a packet-based matcher. + * + * Dispatches to the appropriate matcher codegen function based on the matcher + * type. Handles all matchers that operate on packet headers or metadata common + * to all packet-based flavors. + * + * `BF_MATCHER_META_MARK` and `BF_MATCHER_META_FLOW_HASH` are not supported + * by this function and return `-ENOTSUP`, as they require flavor-specific + * context access. + * + * @param program Program being generated. Can't be NULL. + * @param matcher Matcher to generate code for. Can't be NULL. + * @return 0 on success, negative errno on error. + */ +int bf_matcher_generate_packet(struct bf_program *program, + const struct bf_matcher *matcher); diff --git a/src/bpfilter/cgen/nf.c b/src/bpfilter/cgen/nf.c index 4013bd64c..9f3984d19 100644 --- a/src/bpfilter/cgen/nf.c +++ b/src/bpfilter/cgen/nf.c @@ -19,9 +19,12 @@ #include #include #include +#include #include #include "cgen/jmp.h" +#include "cgen/matcher/meta.h" +#include "cgen/matcher/packet.h" #include "cgen/program.h" #include "cgen/stub.h" #include "cgen/swich.h" @@ -124,39 +127,44 @@ static int _bf_nf_gen_inline_epilogue(struct bf_program *program) return 0; } -static int _bf_nf_gen_inline_get_mark(struct bf_program *program, int reg) +static int _bf_nf_gen_inline_matcher(struct bf_program *program, + const struct bf_matcher *matcher) { int offset; - EMIT(program, - BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(arg))); - if ((offset = bf_btf_get_field_off("bpf_nf_ctx", "skb")) < 0) - return offset; - EMIT(program, BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, offset)); - if ((offset = bf_btf_get_field_off("sk_buff", "mark")) < 0) - return offset; - EMIT(program, BPF_LDX_MEM(BPF_W, reg, BPF_REG_2, offset)); - - return 0; -} + assert(program); + assert(matcher); -static int _bf_nf_gen_inline_get_skb(struct bf_program *program, int reg) -{ - int offset; + switch (bf_matcher_get_type(matcher)) { + case BF_MATCHER_META_MARK: + EMIT(program, + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(arg))); + if ((offset = bf_btf_get_field_off("bpf_nf_ctx", "skb")) < 0) + return offset; + EMIT(program, BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, offset)); + if ((offset = bf_btf_get_field_off("sk_buff", "mark")) < 0) + return offset; + EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_2, offset)); - EMIT(program, BPF_LDX_MEM(BPF_DW, reg, BPF_REG_10, BF_PROG_CTX_OFF(arg))); - if ((offset = bf_btf_get_field_off("bpf_nf_ctx", "skb")) < 0) - return offset; - EMIT(program, BPF_LDX_MEM(BPF_DW, reg, reg, offset)); + return bf_matcher_generate_meta_mark_cmp(program, matcher); + case BF_MATCHER_META_FLOW_HASH: + EMIT(program, + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(arg))); + if ((offset = bf_btf_get_field_off("bpf_nf_ctx", "skb")) < 0) + return offset; + EMIT(program, BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offset)); - return 0; + return bf_matcher_generate_meta_flow_hash_cmp(program, matcher); + default: + return bf_matcher_generate_packet(program, matcher); + } } /** * Convert a standard verdict into a return value. * * @param verdict Verdict to convert. Must be valid. - * @return TC return code corresponding to the verdict, as an integer. + * @return Netfilter return code corresponding to the verdict, as an integer. */ static int _bf_nf_get_verdict(enum bf_verdict verdict) { @@ -173,7 +181,6 @@ static int _bf_nf_get_verdict(enum bf_verdict verdict) const struct bf_flavor_ops bf_flavor_ops_nf = { .gen_inline_prologue = _bf_nf_gen_inline_prologue, .gen_inline_epilogue = _bf_nf_gen_inline_epilogue, - .gen_inline_get_mark = _bf_nf_gen_inline_get_mark, - .gen_inline_get_skb = _bf_nf_gen_inline_get_skb, .get_verdict = _bf_nf_get_verdict, + .gen_inline_matcher = _bf_nf_gen_inline_matcher, }; diff --git a/src/bpfilter/cgen/program.c b/src/bpfilter/cgen/program.c index 33853f0c1..9f98f64e0 100644 --- a/src/bpfilter/cgen/program.c +++ b/src/bpfilter/cgen/program.c @@ -41,13 +41,7 @@ #include "cgen/fixup.h" #include "cgen/handle.h" #include "cgen/jmp.h" -#include "cgen/matcher/icmp.h" -#include "cgen/matcher/ip4.h" -#include "cgen/matcher/ip6.h" -#include "cgen/matcher/meta.h" -#include "cgen/matcher/set.h" -#include "cgen/matcher/tcp.h" -#include "cgen/matcher/udp.h" +#include "cgen/matcher/packet.h" #include "cgen/nf.h" #include "cgen/printer.h" #include "cgen/prog/link.h" @@ -299,73 +293,14 @@ static int _bf_program_generate_rule(struct bf_program *program, if (rule->disabled) return 0; + assert(program->runtime.ops->gen_inline_matcher); + bf_list_foreach (&rule->matchers, matcher_node) { struct bf_matcher *matcher = bf_list_node_get_data(matcher_node); - switch (bf_matcher_get_type(matcher)) { - case BF_MATCHER_META_IFACE: - case BF_MATCHER_META_L3_PROTO: - case BF_MATCHER_META_L4_PROTO: - case BF_MATCHER_META_PROBABILITY: - case BF_MATCHER_META_SPORT: - case BF_MATCHER_META_DPORT: - case BF_MATCHER_META_MARK: - case BF_MATCHER_META_FLOW_HASH: - case BF_MATCHER_META_FLOW_PROBABILITY: - r = bf_matcher_generate_meta(program, matcher); - if (r) - return r; - break; - case BF_MATCHER_IP4_SADDR: - case BF_MATCHER_IP4_SNET: - case BF_MATCHER_IP4_DADDR: - case BF_MATCHER_IP4_DNET: - case BF_MATCHER_IP4_PROTO: - case BF_MATCHER_IP4_DSCP: - r = bf_matcher_generate_ip4(program, matcher); - if (r) - return r; - break; - case BF_MATCHER_IP6_SADDR: - case BF_MATCHER_IP6_SNET: - case BF_MATCHER_IP6_DADDR: - case BF_MATCHER_IP6_DNET: - case BF_MATCHER_IP6_NEXTHDR: - case BF_MATCHER_IP6_DSCP: - r = bf_matcher_generate_ip6(program, matcher); - if (r) - return r; - break; - case BF_MATCHER_TCP_SPORT: - case BF_MATCHER_TCP_DPORT: - case BF_MATCHER_TCP_FLAGS: - r = bf_matcher_generate_tcp(program, matcher); - if (r) - return r; - break; - case BF_MATCHER_UDP_SPORT: - case BF_MATCHER_UDP_DPORT: - r = bf_matcher_generate_udp(program, matcher); - if (r) - return r; - break; - case BF_MATCHER_ICMP_TYPE: - case BF_MATCHER_ICMP_CODE: - case BF_MATCHER_ICMPV6_TYPE: - case BF_MATCHER_ICMPV6_CODE: - r = bf_matcher_generate_icmp(program, matcher); - if (r) - return r; - break; - case BF_MATCHER_SET: - r = bf_matcher_generate_set(program, matcher); - if (r) - return r; - break; - default: - return bf_err_r(-EINVAL, "unknown matcher type %d", - bf_matcher_get_type(matcher)); - }; + r = program->runtime.ops->gen_inline_matcher(program, matcher); + if (r) + return r; } if (bf_rule_mark_is_set(rule)) { diff --git a/src/bpfilter/cgen/tc.c b/src/bpfilter/cgen/tc.c index 3571bb2f3..077f8d01a 100644 --- a/src/bpfilter/cgen/tc.c +++ b/src/bpfilter/cgen/tc.c @@ -15,9 +15,12 @@ #include #include #include +#include #include #include "cgen/cgen.h" +#include "cgen/matcher/meta.h" +#include "cgen/matcher/packet.h" #include "cgen/program.h" #include "cgen/stub.h" #include "filter.h" @@ -85,21 +88,28 @@ static int _bf_tc_gen_inline_set_mark(struct bf_program *program, uint32_t mark) return 0; } -static int _bf_tc_gen_inline_get_mark(struct bf_program *program, int reg) +static int _bf_tc_gen_inline_matcher(struct bf_program *program, + const struct bf_matcher *matcher) { - EMIT(program, - BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(arg))); - EMIT(program, - BPF_LDX_MEM(BPF_W, reg, BPF_REG_1, offsetof(struct __sk_buff, mark))); + assert(program); + assert(matcher); - return 0; -} + switch (bf_matcher_get_type(matcher)) { + case BF_MATCHER_META_MARK: + EMIT(program, + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(arg))); + EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, + offsetof(struct __sk_buff, mark))); -static int _bf_tc_gen_inline_get_skb(struct bf_program *program, int reg) -{ - EMIT(program, BPF_LDX_MEM(BPF_DW, reg, BPF_REG_10, BF_PROG_CTX_OFF(arg))); + return bf_matcher_generate_meta_mark_cmp(program, matcher); + case BF_MATCHER_META_FLOW_HASH: + EMIT(program, + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(arg))); - return 0; + return bf_matcher_generate_meta_flow_hash_cmp(program, matcher); + default: + return bf_matcher_generate_packet(program, matcher); + } } /** @@ -154,8 +164,7 @@ const struct bf_flavor_ops bf_flavor_ops_tc = { .gen_inline_prologue = _bf_tc_gen_inline_prologue, .gen_inline_epilogue = _bf_tc_gen_inline_epilogue, .gen_inline_set_mark = _bf_tc_gen_inline_set_mark, - .gen_inline_get_mark = _bf_tc_gen_inline_get_mark, - .gen_inline_get_skb = _bf_tc_gen_inline_get_skb, .gen_inline_redirect = _bf_tc_gen_inline_redirect, .get_verdict = _bf_tc_get_verdict, + .gen_inline_matcher = _bf_tc_gen_inline_matcher, }; diff --git a/src/bpfilter/cgen/xdp.c b/src/bpfilter/cgen/xdp.c index 58376e4e4..a57ddeeca 100644 --- a/src/bpfilter/cgen/xdp.c +++ b/src/bpfilter/cgen/xdp.c @@ -14,6 +14,7 @@ #include #include +#include "cgen/matcher/packet.h" #include "cgen/program.h" #include "cgen/stub.h" #include "filter.h" @@ -123,4 +124,5 @@ const struct bf_flavor_ops bf_flavor_ops_xdp = { .gen_inline_epilogue = _bf_xdp_gen_inline_epilogue, .gen_inline_redirect = _bf_xdp_gen_inline_redirect, .get_verdict = _bf_xdp_get_verdict, + .gen_inline_matcher = bf_matcher_generate_packet, }; diff --git a/src/libbpfilter/include/bpfilter/flavor.h b/src/libbpfilter/include/bpfilter/flavor.h index 8464ce6d6..0605fac9b 100644 --- a/src/libbpfilter/include/bpfilter/flavor.h +++ b/src/libbpfilter/include/bpfilter/flavor.h @@ -9,6 +9,7 @@ #include +struct bf_matcher; struct bf_program; /** @@ -91,8 +92,6 @@ struct bf_flavor_ops int (*gen_inline_epilogue)(struct bf_program *program); int (*gen_inline_set_mark)(struct bf_program *program, uint32_t mark); - int (*gen_inline_get_mark)(struct bf_program *program, int reg); - int (*gen_inline_get_skb)(struct bf_program *program, int reg); /** * @brief Generate bytecode to redirect a packet to another interface. @@ -117,6 +116,16 @@ struct bf_flavor_ops * value on failure. */ int (*get_verdict)(enum bf_verdict verdict); + + /** + * @brief Generate bytecode for a matcher. Required for all flavors. + * + * @param program Program being generated. Can't be NULL. + * @param matcher Matcher to generate code for. Can't be NULL. + * @return 0 on success, negative errno on error. + */ + int (*gen_inline_matcher)(struct bf_program *program, + const struct bf_matcher *matcher); }; /**