From 083aa279ff99f26ea109937d5d67fd311c60b4d0 Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Fri, 20 Mar 2026 09:58:57 -0700 Subject: [PATCH 1/5] lib: cgen: rename log elfstub to pkt_log Rename the packet logging ELF stub from `log` to `pkt_log` to establish naming symmetry with the upcoming `sock_log` stub for socket-based hooks. --- src/libbpfilter/CMakeLists.txt | 2 +- src/libbpfilter/bpf/{log.bpf.c => pkt_log.bpf.c} | 6 +++--- src/libbpfilter/cgen/program.c | 2 +- src/libbpfilter/include/bpfilter/elfstub.h | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) rename src/libbpfilter/bpf/{log.bpf.c => pkt_log.bpf.c} (89%) diff --git a/src/libbpfilter/CMakeLists.txt b/src/libbpfilter/CMakeLists.txt index 47d98e674..537d21691 100644 --- a/src/libbpfilter/CMakeLists.txt +++ b/src/libbpfilter/CMakeLists.txt @@ -109,7 +109,7 @@ bf_target_add_elfstubs(libbpfilter "parse_ipv6_eh" "parse_ipv6_nh" "update_counters" - "log" + "pkt_log" "flow_hash" ) diff --git a/src/libbpfilter/bpf/log.bpf.c b/src/libbpfilter/bpf/pkt_log.bpf.c similarity index 89% rename from src/libbpfilter/bpf/log.bpf.c rename to src/libbpfilter/bpf/pkt_log.bpf.c index bdd71516f..5ad9529c7 100644 --- a/src/libbpfilter/bpf/log.bpf.c +++ b/src/libbpfilter/bpf/pkt_log.bpf.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2023 Meta Platforms, Inc. and affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. */ #include @@ -11,8 +11,8 @@ #include "cgen/runtime.h" -__u8 bf_log(struct bf_runtime *ctx, __u32 rule_id, __u8 headers, __u32 verdict, - __u32 l3_l4_proto) +__u8 bf_pkt_log(struct bf_runtime *ctx, __u32 rule_id, __u8 headers, + __u32 verdict, __u32 l3_l4_proto) { struct bf_log *log; __u16 l3_proto = (__u16)(l3_l4_proto >> 16); diff --git a/src/libbpfilter/cgen/program.c b/src/libbpfilter/cgen/program.c index 84f8d7b5f..ca8524a20 100644 --- a/src/libbpfilter/cgen/program.c +++ b/src/libbpfilter/cgen/program.c @@ -357,7 +357,7 @@ static int _bf_program_generate_rule(struct bf_program *program, EMIT(program, BPF_ALU64_IMM(BPF_LSH, BPF_REG_5, 16)); EMIT(program, BPF_ALU64_REG(BPF_OR, BPF_REG_5, BPF_REG_8)); - EMIT_FIXUP_ELFSTUB(program, BF_ELFSTUB_LOG); + EMIT_FIXUP_ELFSTUB(program, BF_ELFSTUB_PKT_LOG); } if (rule->counters) { diff --git a/src/libbpfilter/include/bpfilter/elfstub.h b/src/libbpfilter/include/bpfilter/elfstub.h index 31a05ac80..1c54ee74e 100644 --- a/src/libbpfilter/include/bpfilter/elfstub.h +++ b/src/libbpfilter/include/bpfilter/elfstub.h @@ -122,7 +122,7 @@ enum bf_elfstub_id /** * Log user-requested packet headers to a ring buffer. * - * `__u8 bf_log(struct bf_runtime *ctx, __u32 rule_id, __u8 headers, __u32 verdict, __u32 l3_l4_proto)` + * `__u8 bf_pkt_log(struct bf_runtime *ctx, __u32 rule_id, __u8 headers, __u32 verdict, __u32 l3_l4_proto)` * * **Parameters** * - `ctx`: address of the `bf_runtime` context of the program. @@ -133,7 +133,7 @@ enum bf_elfstub_id * * **Return** 0 on success, or 1 on error. */ - BF_ELFSTUB_LOG, + BF_ELFSTUB_PKT_LOG, /** * Calculate flow hash from packet 5-tuple + IPv6 flow label. From c7e85d2b50249de2848fd57200f14a16a2418581 Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Fri, 20 Mar 2026 10:06:15 -0700 Subject: [PATCH 2/5] lib: runtime: restructure bf_log with tagged union Restructure bf_log as a tagged union with packet and socket address variants, discriminated by bf_log_type. --- doc/Doxyfile.in | 3 +- src/bfcli/print.c | 31 +++--- src/libbpfilter/bpf/pkt_log.bpf.c | 19 ++-- src/libbpfilter/include/bpfilter/runtime.h | 114 +++++++++++++++++---- 4 files changed, 124 insertions(+), 43 deletions(-) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 0e9dcc52d..44e5640c3 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -57,7 +57,8 @@ GENERATE_PERLMOD = NO #--------------------------------------------------------------------------- INCLUDE_PATH = "@CMAKE_SOURCE_DIR@/src" "@CMAKE_SOURCE_DIR@/tests" MACRO_EXPANSION = YES -PREDEFINED = bf_aligned(x)= +PREDEFINED = bf_aligned(x)= \ + DOXYGEN #--------------------------------------------------------------------------- # Configuration options related to diagram generator tools diff --git a/src/bfcli/print.c b/src/bfcli/print.c index b920dc21d..4a036f795 100644 --- a/src/bfcli/print.c +++ b/src/bfcli/print.c @@ -373,17 +373,17 @@ static void _bf_chain_log_header(const struct bf_log *log) bf_logger_get_color(BF_COLOR_LIGHT_CYAN, BF_STYLE_NORMAL), time_str, time.tv_nsec / BF_TIME_US, bf_logger_get_color(BF_COLOR_RESET, BF_STYLE_RESET), log->rule_id, - bf_logger_get_color(BF_COLOR_DEFAULT, BF_STYLE_BOLD), log->pkt_size, + bf_logger_get_color(BF_COLOR_DEFAULT, BF_STYLE_BOLD), log->pkt.pkt_size, bf_logger_get_color(BF_COLOR_RESET, BF_STYLE_RESET), bf_verdict_to_str((enum bf_verdict)log->verdict)); } static void _bf_chain_log_l2(const struct bf_log *log) { - struct ethhdr *ethhdr = (void *)log->l2hdr; + struct ethhdr *ethhdr = (void *)log->pkt.l2hdr; const char *ethertype; - if (!(log->headers & (1 << BF_PKTHDR_LINK))) { + if (!(log->pkt.headers & (1 << BF_PKTHDR_LINK))) { (void)fprintf(stdout, " Ethernet : \n"); return; } @@ -418,14 +418,14 @@ static void _bf_chain_log_l3(const struct bf_log *log) char dst_addr[INET6_ADDRSTRLEN]; const char *protocol; - if (!(log->headers & (1 << BF_PKTHDR_INTERNET))) { + if (!(log->pkt.headers & (1 << BF_PKTHDR_INTERNET))) { (void)fprintf(stdout, " Internet : \n"); return; } switch (log->l3_proto) { case ETH_P_IP: - iphdr = (struct iphdr *)&log->l3hdr[0]; + iphdr = (struct iphdr *)&log->pkt.l3hdr[0]; inet_ntop(AF_INET, &iphdr->saddr, src_addr, sizeof(src_addr)); inet_ntop(AF_INET, &iphdr->daddr, dst_addr, sizeof(dst_addr)); @@ -451,7 +451,7 @@ static void _bf_chain_log_l3(const struct bf_log *log) break; case ETH_P_IPV6: - ipv6hdr = (struct ipv6hdr *)log->l3hdr; + ipv6hdr = (struct ipv6hdr *)log->pkt.l3hdr; inet_ntop(AF_INET6, &ipv6hdr->saddr, src_addr, sizeof(src_addr)); inet_ntop(AF_INET6, &ipv6hdr->daddr, dst_addr, sizeof(dst_addr)); @@ -490,14 +490,14 @@ static void _bf_chain_log_l4(const struct bf_log *log) struct udphdr *udphdr; const char *tcp_flags_str; - if (!(log->headers & (1 << BF_PKTHDR_TRANSPORT))) { + if (!(log->pkt.headers & (1 << BF_PKTHDR_TRANSPORT))) { (void)fprintf(stdout, " Transport : \n"); return; } switch (log->l4_proto) { case IPPROTO_TCP: - tcphdr = (struct tcphdr *)log->l4hdr; + tcphdr = (struct tcphdr *)log->pkt.l4hdr; tcp_flags_str = _bf_tcp_flags_to_str(tcphdr); (void)fprintf(stdout, " TCP : %s%-5u%s → %s%-5u%s", @@ -522,7 +522,7 @@ static void _bf_chain_log_l4(const struct bf_log *log) break; case IPPROTO_UDP: - udphdr = (struct udphdr *)log->l4hdr; + udphdr = (struct udphdr *)log->pkt.l4hdr; (void)fprintf(stdout, " UDP : %s%-5u%s → %s%-5u%s [len=%u]\n", bf_logger_get_color(BF_COLOR_LIGHT_YELLOW, BF_STYLE_BOLD), @@ -535,7 +535,7 @@ static void _bf_chain_log_l4(const struct bf_log *log) break; case IPPROTO_ICMP: - icmphdr = (struct icmphdr *)log->l4hdr; + icmphdr = (struct icmphdr *)log->pkt.l4hdr; (void)fprintf(stdout, " ICMP : type=%-3u code=%-3u", icmphdr->type, icmphdr->code); @@ -550,7 +550,7 @@ static void _bf_chain_log_l4(const struct bf_log *log) break; case IPPROTO_ICMPV6: - icmp6hdr = (struct icmp6hdr *)log->l4hdr; + icmp6hdr = (struct icmp6hdr *)log->pkt.l4hdr; (void)fprintf(stdout, " ICMPv6 : type=%-3u code=%-3u", icmp6hdr->icmp6_type, icmp6hdr->icmp6_code); @@ -573,12 +573,15 @@ static void _bf_chain_log_l4(const struct bf_log *log) void bfc_print_log(const struct bf_log *log) { + if (log->log_type != BF_LOG_TYPE_PACKET) + return; + _bf_chain_log_header(log); - if (log->req_headers & (1 << BF_PKTHDR_LINK)) + if (log->pkt.req_headers & (1 << BF_PKTHDR_LINK)) _bf_chain_log_l2(log); - if (log->req_headers & (1 << BF_PKTHDR_INTERNET)) + if (log->pkt.req_headers & (1 << BF_PKTHDR_INTERNET)) _bf_chain_log_l3(log); - if (log->req_headers & (1 << BF_PKTHDR_TRANSPORT)) + if (log->pkt.req_headers & (1 << BF_PKTHDR_TRANSPORT)) _bf_chain_log_l4(log); } diff --git a/src/libbpfilter/bpf/pkt_log.bpf.c b/src/libbpfilter/bpf/pkt_log.bpf.c index 5ad9529c7..b2a426cbf 100644 --- a/src/libbpfilter/bpf/pkt_log.bpf.c +++ b/src/libbpfilter/bpf/pkt_log.bpf.c @@ -28,28 +28,29 @@ __u8 bf_pkt_log(struct bf_runtime *ctx, __u32 rule_id, __u8 headers, log->ts = bpf_ktime_get_ns(); log->rule_id = rule_id; log->verdict = verdict; - log->pkt_size = ctx->pkt_size; - log->req_headers = headers; - log->headers = 0; log->l3_proto = bpf_ntohs(l3_proto); log->l4_proto = l4_proto; + log->log_type = BF_LOG_TYPE_PACKET; + log->pkt.pkt_size = ctx->pkt_size; + log->pkt.req_headers = headers; + log->pkt.headers = 0; if (headers & (1 << BF_PKTHDR_LINK) && ctx->l2_hdr && ctx->l2_size <= BF_L2_SLICE_LEN) { - bpf_probe_read_kernel(log->l2hdr, ctx->l2_size, ctx->l2_hdr); - log->headers |= (1 << BF_PKTHDR_LINK); + bpf_probe_read_kernel(log->pkt.l2hdr, ctx->l2_size, ctx->l2_hdr); + log->pkt.headers |= (1 << BF_PKTHDR_LINK); } if (headers & (1 << BF_PKTHDR_INTERNET) && ctx->l3_hdr && ctx->l3_size <= BF_L3_SLICE_LEN) { - bpf_probe_read_kernel(log->l3hdr, ctx->l3_size, ctx->l3_hdr); - log->headers |= (1 << BF_PKTHDR_INTERNET); + bpf_probe_read_kernel(log->pkt.l3hdr, ctx->l3_size, ctx->l3_hdr); + log->pkt.headers |= (1 << BF_PKTHDR_INTERNET); } if (headers & (1 << BF_PKTHDR_TRANSPORT) && ctx->l4_hdr && ctx->l4_size <= BF_L4_SLICE_LEN) { - bpf_probe_read_kernel(log->l4hdr, ctx->l4_size, ctx->l4_hdr); - log->headers |= (1 << BF_PKTHDR_TRANSPORT); + bpf_probe_read_kernel(log->pkt.l4hdr, ctx->l4_size, ctx->l4_hdr); + log->pkt.headers |= (1 << BF_PKTHDR_TRANSPORT); } bpf_ringbuf_submit(log, 0); diff --git a/src/libbpfilter/include/bpfilter/runtime.h b/src/libbpfilter/include/bpfilter/runtime.h index f245bb62b..7ab54354c 100644 --- a/src/libbpfilter/include/bpfilter/runtime.h +++ b/src/libbpfilter/include/bpfilter/runtime.h @@ -7,11 +7,24 @@ #define bf_aligned(x) __attribute__((aligned(x))) +/** + * @brief Give an anonymous union or struct a name only for Doxygen. + * + * Allows anonymous unions/structs in code while keeping Doxygen's parser happy. + */ +#ifdef DOXYGEN +#define ANONYMOUS_MEMBER(name) name +#else +#define ANONYMOUS_MEMBER(name) +#endif + // _Static_assert doesn't exist in C++ #ifndef __cplusplus #define static_assert _Static_assert #endif +#include + #include /** @@ -50,6 +63,9 @@ static_assert(BF_L3_SLICE_LEN % 8 == 0, static_assert(BF_L4_SLICE_LEN % 8 == 0, "BF_L4_SLICE_LEN should be aligned to 8 bytes"); +/** Size of the process name buffer, matches TASK_COMM_LEN. */ +#define BF_COMM_LEN 16 + /** * @brief Types of network packet headers. */ @@ -77,23 +93,81 @@ enum bf_pkthdr _BF_PKTHDR_MAX, }; +/** + * @brief Log entry type discriminator. + */ +enum bf_log_type +{ + /** Packet-based log entry (XDP, TC, NF, cgroup_skb). */ + BF_LOG_TYPE_PACKET, + + /** Socket address log entry (cgroup_sock_addr). */ + BF_LOG_TYPE_SOCK_ADDR, + + _BF_LOG_TYPE_MAX, +}; + +/** + * @brief Packet log payload fields (XDP, TC, NF, cgroup_skb). + */ +struct bf_log_pkt +{ + /** Total size of the packet, including the payload. */ + __u64 pkt_size; + + /** User-requested headers, as defined in the rule. */ + __u8 req_headers:4; + + /** Logged headers, as not all hooks can access all headers. */ + __u8 headers:4; + + /** Layer 2 header. */ + bf_aligned(8) __u8 l2hdr[BF_L2_SLICE_LEN]; + + /** Layer 3 header. */ + bf_aligned(8) __u8 l3hdr[BF_L3_SLICE_LEN]; + + /** Layer 4 header. */ + bf_aligned(8) __u8 l4hdr[BF_L4_SLICE_LEN]; +}; + +/** + * @brief Socket address log payload fields (cgroup_sock_addr). + */ +struct bf_log_sock_addr +{ + /** Root namespace PID (tgid) of the process. */ + __u32 pid; + + /** Destination port in host byteorder. */ + __u16 dport; + + /** User-requested log options bitmask. */ + __u8 req_log_opts; + + /** Process name. */ + bf_aligned(8) __u8 comm[BF_COMM_LEN]; + + /** Source address (4 bytes for IPv4, 16 for IPv6). */ + bf_aligned(8) __u8 saddr[sizeof(struct in6_addr)]; + + /** Destination address (4 bytes for IPv4, 16 for IPv6). */ + bf_aligned(8) __u8 daddr[sizeof(struct in6_addr)]; +}; + /** * @brief Log structure published by a chain when the `log` action is hit. * * The structure is published into a log buffer by the chain, when a hit rule * has a `log` action defined. * - * Except for the raw packet headers (`l2hdr`, `l3hdr`, and `l4hdr`), all the - * values are stored in host byteorder. + * All fields are stored in host byteorder unless noted otherwise. */ struct bf_log { - /** Timestamp of the packet processing. */ + /** Timestamp of the event. */ __u64 ts; - /** Total size of the packet, including the payload. */ - __u64 pkt_size; - /** ID of the rule triggering the log. */ __u32 rule_id; @@ -106,20 +180,22 @@ struct bf_log /** Layer 4 (transport) protocol identifier. */ __u8 l4_proto; - /** User-request headers, as defined in the rule. */ - __u8 req_headers:4; - - /** Logged headers, as not all hooks can access all headers. */ - __u8 headers:4; + /** Log entry type. */ + __u8 log_type; - /** Layer 2 header. */ - bf_aligned(8) __u8 l2hdr[BF_L2_SLICE_LEN]; - - /** Layer 3 header. */ - bf_aligned(8) __u8 l3hdr[BF_L3_SLICE_LEN]; - - /** Layer 4 header. */ - bf_aligned(8) __u8 l4hdr[BF_L4_SLICE_LEN]; + /** + * Flavor-specific payload, discriminated by `log_type`. + * + * - `BF_LOG_TYPE_PACKET`: use `pkt` — raw packet headers in network + * byteorder. + * - `BF_LOG_TYPE_SOCK_ADDR`: use `sock_addr` — socket address, port, + * and process metadata. + */ + union + { + struct bf_log_pkt pkt; + struct bf_log_sock_addr sock_addr; + } ANONYMOUS_MEMBER(payload); }; struct bf_ip4_lpm_key From a7bc7c573a62fd5369ca670801d8ec2f99becb10 Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Fri, 20 Mar 2026 12:57:28 -0700 Subject: [PATCH 3/5] lib: rename bf_pkthdr to bf_log_opt --- src/bfcli/lexer.l | 2 +- src/bfcli/parser.y | 12 ++++----- src/bfcli/print.c | 20 +++++++-------- src/libbpfilter/bpf/pkt_log.bpf.c | 12 ++++----- src/libbpfilter/include/bpfilter/rule.h | 29 +++++++++------------- src/libbpfilter/include/bpfilter/runtime.h | 25 ++++++++----------- src/libbpfilter/rule.c | 28 ++++++++++----------- tests/fuzz/keywords.dict | 2 +- tests/harness/Rule.hpp | 2 +- tests/harness/fake.c | 2 +- tests/unit/libbpfilter/rule.c | 5 ++-- 11 files changed, 65 insertions(+), 74 deletions(-) diff --git a/src/bfcli/lexer.l b/src/bfcli/lexer.l index 8a04987a7..16476d854 100644 --- a/src/bfcli/lexer.l +++ b/src/bfcli/lexer.l @@ -101,7 +101,7 @@ log { BEGIN(STATE_LOG_OPTS); return LOG; } [0-9a-zA-Z]+(,[0-9a-zA-Z]+)* { BEGIN(INITIAL); yylval.sval = strdup(yytext); - return LOG_HEADERS; + return LOG_OPTS; } } diff --git a/src/bfcli/parser.y b/src/bfcli/parser.y index 98a4cd238..9655c0c79 100644 --- a/src/bfcli/parser.y +++ b/src/bfcli/parser.y @@ -103,7 +103,7 @@ %token SET %token LOG COUNTER MARK %token REDIRECT_TOKEN -%token LOG_HEADERS +%token LOG_OPTS %token SET_TYPE %token SET_RAW_PAYLOAD %token STRING @@ -320,7 +320,7 @@ rule : RULE matchers rule_options rule_verdict } ; -rule_option : LOG LOG_HEADERS +rule_option : LOG LOG_OPTS { _cleanup_free_ char *in = $2; char *tmp = in; @@ -329,12 +329,12 @@ rule_option : LOG LOG_HEADERS uint8_t log = 0; while ((token = strtok_r(tmp, ",", &saveptr))) { - enum bf_pkthdr header; + enum bf_log_opt opt; - if (bf_pkthdr_from_str(token, &header) < 0) - bf_parse_err("unknown packet header '%s'", token); + if (bf_log_opt_from_str(token, &opt) < 0) + bf_parse_err("unknown log option '%s'", token); - log |= BF_FLAG(header); + log |= BF_FLAG(opt); tmp = NULL; } diff --git a/src/bfcli/print.c b/src/bfcli/print.c index 4a036f795..73292ee62 100644 --- a/src/bfcli/print.c +++ b/src/bfcli/print.c @@ -265,12 +265,12 @@ void bfc_chain_dump(struct bf_chain *chain, struct bf_hookopts *hookopts, (void)fprintf(stdout, " log "); - for (enum bf_pkthdr hdr = 0; hdr < _BF_PKTHDR_MAX; ++hdr) { - if (!(log & BF_FLAG(hdr))) + for (enum bf_log_opt opt = 0; opt < _BF_LOG_OPT_MAX; ++opt) { + if (!(log & BF_FLAG(opt))) continue; - log &= ~BF_FLAG(hdr); - (void)fprintf(stdout, "%s%s", bf_pkthdr_to_str(hdr), + log &= ~BF_FLAG(opt); + (void)fprintf(stdout, "%s%s", bf_log_opt_to_str(opt), log ? "," : "\n"); } } @@ -383,7 +383,7 @@ static void _bf_chain_log_l2(const struct bf_log *log) struct ethhdr *ethhdr = (void *)log->pkt.l2hdr; const char *ethertype; - if (!(log->pkt.headers & (1 << BF_PKTHDR_LINK))) { + if (!(log->pkt.headers & (1 << BF_LOG_OPT_LINK))) { (void)fprintf(stdout, " Ethernet : \n"); return; } @@ -418,7 +418,7 @@ static void _bf_chain_log_l3(const struct bf_log *log) char dst_addr[INET6_ADDRSTRLEN]; const char *protocol; - if (!(log->pkt.headers & (1 << BF_PKTHDR_INTERNET))) { + if (!(log->pkt.headers & (1 << BF_LOG_OPT_INTERNET))) { (void)fprintf(stdout, " Internet : \n"); return; } @@ -490,7 +490,7 @@ static void _bf_chain_log_l4(const struct bf_log *log) struct udphdr *udphdr; const char *tcp_flags_str; - if (!(log->pkt.headers & (1 << BF_PKTHDR_TRANSPORT))) { + if (!(log->pkt.headers & (1 << BF_LOG_OPT_TRANSPORT))) { (void)fprintf(stdout, " Transport : \n"); return; } @@ -578,10 +578,10 @@ void bfc_print_log(const struct bf_log *log) _bf_chain_log_header(log); - if (log->pkt.req_headers & (1 << BF_PKTHDR_LINK)) + if (log->pkt.req_headers & (1 << BF_LOG_OPT_LINK)) _bf_chain_log_l2(log); - if (log->pkt.req_headers & (1 << BF_PKTHDR_INTERNET)) + if (log->pkt.req_headers & (1 << BF_LOG_OPT_INTERNET)) _bf_chain_log_l3(log); - if (log->pkt.req_headers & (1 << BF_PKTHDR_TRANSPORT)) + if (log->pkt.req_headers & (1 << BF_LOG_OPT_TRANSPORT)) _bf_chain_log_l4(log); } diff --git a/src/libbpfilter/bpf/pkt_log.bpf.c b/src/libbpfilter/bpf/pkt_log.bpf.c index b2a426cbf..c2ba7af92 100644 --- a/src/libbpfilter/bpf/pkt_log.bpf.c +++ b/src/libbpfilter/bpf/pkt_log.bpf.c @@ -35,22 +35,22 @@ __u8 bf_pkt_log(struct bf_runtime *ctx, __u32 rule_id, __u8 headers, log->pkt.req_headers = headers; log->pkt.headers = 0; - if (headers & (1 << BF_PKTHDR_LINK) && ctx->l2_hdr && + if (headers & (1 << BF_LOG_OPT_LINK) && ctx->l2_hdr && ctx->l2_size <= BF_L2_SLICE_LEN) { bpf_probe_read_kernel(log->pkt.l2hdr, ctx->l2_size, ctx->l2_hdr); - log->pkt.headers |= (1 << BF_PKTHDR_LINK); + log->pkt.headers |= (1 << BF_LOG_OPT_LINK); } - if (headers & (1 << BF_PKTHDR_INTERNET) && ctx->l3_hdr && + if (headers & (1 << BF_LOG_OPT_INTERNET) && ctx->l3_hdr && ctx->l3_size <= BF_L3_SLICE_LEN) { bpf_probe_read_kernel(log->pkt.l3hdr, ctx->l3_size, ctx->l3_hdr); - log->pkt.headers |= (1 << BF_PKTHDR_INTERNET); + log->pkt.headers |= (1 << BF_LOG_OPT_INTERNET); } - if (headers & (1 << BF_PKTHDR_TRANSPORT) && ctx->l4_hdr && + if (headers & (1 << BF_LOG_OPT_TRANSPORT) && ctx->l4_hdr && ctx->l4_size <= BF_L4_SLICE_LEN) { bpf_probe_read_kernel(log->pkt.l4hdr, ctx->l4_size, ctx->l4_hdr); - log->pkt.headers |= (1 << BF_PKTHDR_TRANSPORT); + log->pkt.headers |= (1 << BF_LOG_OPT_TRANSPORT); } bpf_ringbuf_submit(log, 0); diff --git a/src/libbpfilter/include/bpfilter/rule.h b/src/libbpfilter/include/bpfilter/rule.h index c1d6bcc72..91cd6d5ba 100644 --- a/src/libbpfilter/include/bpfilter/rule.h +++ b/src/libbpfilter/include/bpfilter/rule.h @@ -19,28 +19,23 @@ #define BF_RULE_MARK_MASK (0x00000000ffffffffULL) /** - * @brief Return the string representation of a `bf_pkthdr` enumeration value. + * @brief Return the string representation of a `bf_log_opt` enumeration value. * - * @param hdr `bf_pkthdr` enumeration value. - * @return A pointer to the C-string representation of `hdr`. + * @param opt `bf_log_opt` enumeration value. + * @return A pointer to the C-string representation of `opt`. */ -const char *bf_pkthdr_to_str(enum bf_pkthdr hdr); +const char *bf_log_opt_to_str(enum bf_log_opt opt); /** - * @brief Return the `bf_pkthdr` enumeration value corresponding to a string. + * @brief Return the `bf_log_opt` enumeration value corresponding to a string. * - * @pre - * - `str` is a non-NULL pointer to a C-string. - * - `hdr != NULL` - * @post - * - On failure, `hdr` is unchanged. - * - * @param str String to get the corresponding `bf_pkthdr` enumeration value for. - * @param hdr On success, contains the `bf_pkthdr` enumeration value - * corresponding to `str`. + * @param str String to get the corresponding `bf_log_opt` enumeration value + * for. + * @param opt On success, contains the `bf_log_opt` enumeration value + * corresponding to `str`. Can't be NULL. * @return 0 on success, or a negative error value on failure. */ -int bf_pkthdr_from_str(const char *str, enum bf_pkthdr *hdr); +int bf_log_opt_from_str(const char *str, enum bf_log_opt *opt); #define _free_bf_rule_ __attribute__((__cleanup__(bf_rule_free))) @@ -77,8 +72,8 @@ struct bf_rule }; static_assert( - _BF_PKTHDR_MAX < 8, - "bf_pkthdr has more than 8 values, it won't fit in bf_rule.log's 8 bits"); + _BF_LOG_OPT_MAX <= 8, + "bf_log_opt has more than 8 values, it won't fit in bf_rule.log's 8 bits"); /** * Allocated and initialise a new rule. diff --git a/src/libbpfilter/include/bpfilter/runtime.h b/src/libbpfilter/include/bpfilter/runtime.h index 7ab54354c..b4d7dfa0b 100644 --- a/src/libbpfilter/include/bpfilter/runtime.h +++ b/src/libbpfilter/include/bpfilter/runtime.h @@ -67,30 +67,25 @@ static_assert(BF_L4_SLICE_LEN % 8 == 0, #define BF_COMM_LEN 16 /** - * @brief Types of network packet headers. + * @brief Log options controlling which headers are captured in a log entry. */ -enum bf_pkthdr +enum bf_log_opt { - /** - * Link layer header: Ethernet, ... - */ - BF_PKTHDR_LINK, + /** Link layer data: Ethernet header. */ + BF_LOG_OPT_LINK, - /** - * Internet header: IPv4, IPv6, ... - */ - BF_PKTHDR_INTERNET, + /** Internet layer data: IPv4/IPv6 header. */ + BF_LOG_OPT_INTERNET, /** - * Transport header: TCP, UDP, ... + * Transport layer data: TCP/UDP header. * * ICMPv6 is an internet layer (L3) header, but it's encapsulated inside an - * IPv6 packet, so it's considered a transport layer (L4) header in - * bpfilter. + * IPv6 packet, so it's considered layer 4 in bpfilter. */ - BF_PKTHDR_TRANSPORT, + BF_LOG_OPT_TRANSPORT, - _BF_PKTHDR_MAX, + _BF_LOG_OPT_MAX, }; /** diff --git a/src/libbpfilter/rule.c b/src/libbpfilter/rule.c index 22b86ab27..3abb04e98 100644 --- a/src/libbpfilter/rule.c +++ b/src/libbpfilter/rule.c @@ -19,28 +19,28 @@ #include "bpfilter/runtime.h" #include "bpfilter/verdict.h" -static const char *_bf_pkthdr_strs[] = { - [BF_PKTHDR_LINK] = "link", - [BF_PKTHDR_INTERNET] = "internet", - [BF_PKTHDR_TRANSPORT] = "transport", +static const char *_bf_log_opt_strs[] = { + [BF_LOG_OPT_LINK] = "link", + [BF_LOG_OPT_INTERNET] = "internet", + [BF_LOG_OPT_TRANSPORT] = "transport", }; -static_assert_enum_mapping(_bf_pkthdr_strs, _BF_PKTHDR_MAX); +static_assert_enum_mapping(_bf_log_opt_strs, _BF_LOG_OPT_MAX); -const char *bf_pkthdr_to_str(enum bf_pkthdr hdr) +const char *bf_log_opt_to_str(enum bf_log_opt opt) { - if (hdr < 0 || hdr >= _BF_PKTHDR_MAX) - return ""; + if (opt < 0 || opt >= _BF_LOG_OPT_MAX) + return ""; - return _bf_pkthdr_strs[hdr]; + return _bf_log_opt_strs[opt]; } -int bf_pkthdr_from_str(const char *str, enum bf_pkthdr *hdr) +int bf_log_opt_from_str(const char *str, enum bf_log_opt *opt) { - assert(hdr); + assert(opt); - for (int i = 0; i < _BF_PKTHDR_MAX; ++i) { - if (bf_streq_i(str, _bf_pkthdr_strs[i])) { - *hdr = (enum bf_pkthdr)i; + for (int i = 0; i < _BF_LOG_OPT_MAX; ++i) { + if (bf_streq_i(str, _bf_log_opt_strs[i])) { + *opt = (enum bf_log_opt)i; return 0; } } diff --git a/tests/fuzz/keywords.dict b/tests/fuzz/keywords.dict index 2377d20e1..2a7b0901e 100644 --- a/tests/fuzz/keywords.dict +++ b/tests/fuzz/keywords.dict @@ -132,7 +132,7 @@ "ipv4" "ipv6" -# Log headers (bf_pkthdr) +# Log options (bf_log_opt) "link" "internet" "transport" diff --git a/tests/harness/Rule.hpp b/tests/harness/Rule.hpp index 7a4a99068..45da2a1ed 100644 --- a/tests/harness/Rule.hpp +++ b/tests/harness/Rule.hpp @@ -21,7 +21,7 @@ extern "C" { namespace bf { -using RuleLogBitset = std::bitset<_BF_PKTHDR_MAX>; +using RuleLogBitset = std::bitset<_BF_LOG_OPT_MAX>; class Rule { diff --git a/tests/harness/fake.c b/tests/harness/fake.c index 8792305d7..f29538b67 100644 --- a/tests/harness/fake.c +++ b/tests/harness/fake.c @@ -189,7 +189,7 @@ struct bf_rule *bft_rule_dummy(size_t n_matchers) return NULL; rule->index = 0; - rule->log = BF_FLAGS(BF_PKTHDR_INTERNET, BF_PKTHDR_TRANSPORT); + rule->log = BF_FLAGS(BF_LOG_OPT_INTERNET, BF_LOG_OPT_TRANSPORT); rule->mark = 0x17; rule->counters = true; rule->verdict = BF_VERDICT_ACCEPT; diff --git a/tests/unit/libbpfilter/rule.c b/tests/unit/libbpfilter/rule.c index b70f99653..3b7c431f2 100644 --- a/tests/unit/libbpfilter/rule.c +++ b/tests/unit/libbpfilter/rule.c @@ -15,8 +15,9 @@ static void to_from_str(void **state) { (void)state; - assert_enum_to_from_str(enum bf_pkthdr, bf_pkthdr_to_str, - bf_pkthdr_from_str, BF_PKTHDR_LINK, _BF_PKTHDR_MAX); + assert_enum_to_from_str(enum bf_log_opt, bf_log_opt_to_str, + bf_log_opt_from_str, BF_LOG_OPT_LINK, + _BF_LOG_OPT_MAX); } static void new_and_free(void **state) From 3f33c9f718a3a59f88e3860336f4bfa542f95966 Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Fri, 20 Mar 2026 10:43:20 -0700 Subject: [PATCH 4/5] lib: cgen: move packet codegen out of matcher directory Move packet.c/h from cgen/matcher/ to cgen/ and rename bf_matcher_generate_packet() to bf_packet_gen_inline_matcher(). This file provides shared codegen utilities for all packet-based flavors, not a matcher implementation, and will host additional shared packet codegen like bf_packet_gen_inline_log() in subsequent commits. --- src/libbpfilter/CMakeLists.txt | 2 +- src/libbpfilter/cgen/cgroup_skb.c | 4 ++-- src/libbpfilter/cgen/nf.c | 4 ++-- src/libbpfilter/cgen/{matcher => }/packet.c | 6 +++--- src/libbpfilter/cgen/{matcher => }/packet.h | 4 ++-- src/libbpfilter/cgen/tc.c | 4 ++-- src/libbpfilter/cgen/xdp.c | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) rename src/libbpfilter/cgen/{matcher => }/packet.c (98%) rename src/libbpfilter/cgen/{matcher => }/packet.h (85%) diff --git a/src/libbpfilter/CMakeLists.txt b/src/libbpfilter/CMakeLists.txt index 537d21691..f3a0bee78 100644 --- a/src/libbpfilter/CMakeLists.txt +++ b/src/libbpfilter/CMakeLists.txt @@ -64,9 +64,9 @@ set(libbpfilter_srcs ${CMAKE_CURRENT_SOURCE_DIR}/cgen/jmp.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/jmp.c ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/cmp.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/matcher/cmp.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/nf.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/nf.c + ${CMAKE_CURRENT_SOURCE_DIR}/cgen/packet.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/packet.c ${CMAKE_CURRENT_SOURCE_DIR}/cgen/printer.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/printer.c ${CMAKE_CURRENT_SOURCE_DIR}/cgen/program.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/program.c ${CMAKE_CURRENT_SOURCE_DIR}/cgen/prog/link.h ${CMAKE_CURRENT_SOURCE_DIR}/cgen/prog/link.c diff --git a/src/libbpfilter/cgen/cgroup_skb.c b/src/libbpfilter/cgen/cgroup_skb.c index 459238e0e..2ffcef0a1 100644 --- a/src/libbpfilter/cgen/cgroup_skb.c +++ b/src/libbpfilter/cgen/cgroup_skb.c @@ -20,7 +20,7 @@ #include "cgen/cgen.h" #include "cgen/matcher/cmp.h" -#include "cgen/matcher/packet.h" +#include "cgen/packet.h" #include "cgen/program.h" #include "cgen/stub.h" #include "cgen/swich.h" @@ -133,7 +133,7 @@ static int _bf_cgroup_skb_gen_inline_matcher(struct bf_program *program, return bf_cmp_value(program, bf_matcher_get_op(matcher), bf_matcher_payload(matcher), 4, BPF_REG_1); default: - return bf_matcher_generate_packet(program, matcher); + return bf_packet_gen_inline_matcher(program, matcher); } } diff --git a/src/libbpfilter/cgen/nf.c b/src/libbpfilter/cgen/nf.c index 08c596e81..f0728f986 100644 --- a/src/libbpfilter/cgen/nf.c +++ b/src/libbpfilter/cgen/nf.c @@ -24,7 +24,7 @@ #include "cgen/jmp.h" #include "cgen/matcher/cmp.h" -#include "cgen/matcher/packet.h" +#include "cgen/packet.h" #include "cgen/program.h" #include "cgen/stub.h" #include "cgen/swich.h" @@ -149,7 +149,7 @@ static int _bf_nf_gen_inline_matcher(struct bf_program *program, return bf_cmp_value(program, bf_matcher_get_op(matcher), bf_matcher_payload(matcher), 4, BPF_REG_1); default: - return bf_matcher_generate_packet(program, matcher); + return bf_packet_gen_inline_matcher(program, matcher); } } diff --git a/src/libbpfilter/cgen/matcher/packet.c b/src/libbpfilter/cgen/packet.c similarity index 98% rename from src/libbpfilter/cgen/matcher/packet.c rename to src/libbpfilter/cgen/packet.c index 3974edba9..41f7b0b7b 100644 --- a/src/libbpfilter/cgen/matcher/packet.c +++ b/src/libbpfilter/cgen/packet.c @@ -3,7 +3,7 @@ * Copyright (c) Meta Platforms, Inc. and affiliates. */ -#include "cgen/matcher/packet.h" +#include "cgen/packet.h" #include #include @@ -296,8 +296,8 @@ static int _bf_matcher_pkt_generate_ip6_dscp(struct bf_program *program, return 0; } -int bf_matcher_generate_packet(struct bf_program *program, - const struct bf_matcher *matcher) +int bf_packet_gen_inline_matcher(struct bf_program *program, + const struct bf_matcher *matcher) { const struct bf_matcher_meta *meta; diff --git a/src/libbpfilter/cgen/matcher/packet.h b/src/libbpfilter/cgen/packet.h similarity index 85% rename from src/libbpfilter/cgen/matcher/packet.h rename to src/libbpfilter/cgen/packet.h index 54acd0a1a..f459a363a 100644 --- a/src/libbpfilter/cgen/matcher/packet.h +++ b/src/libbpfilter/cgen/packet.h @@ -23,5 +23,5 @@ struct bf_program; * @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); +int bf_packet_gen_inline_matcher(struct bf_program *program, + const struct bf_matcher *matcher); diff --git a/src/libbpfilter/cgen/tc.c b/src/libbpfilter/cgen/tc.c index d83fcd411..eb624c4a8 100644 --- a/src/libbpfilter/cgen/tc.c +++ b/src/libbpfilter/cgen/tc.c @@ -20,7 +20,7 @@ #include "cgen/cgen.h" #include "cgen/matcher/cmp.h" -#include "cgen/matcher/packet.h" +#include "cgen/packet.h" #include "cgen/program.h" #include "cgen/stub.h" #include "filter.h" @@ -116,7 +116,7 @@ static int _bf_tc_gen_inline_matcher(struct bf_program *program, return bf_cmp_value(program, bf_matcher_get_op(matcher), bf_matcher_payload(matcher), 4, BPF_REG_0); default: - return bf_matcher_generate_packet(program, matcher); + return bf_packet_gen_inline_matcher(program, matcher); } } diff --git a/src/libbpfilter/cgen/xdp.c b/src/libbpfilter/cgen/xdp.c index a57ddeeca..c4e724e77 100644 --- a/src/libbpfilter/cgen/xdp.c +++ b/src/libbpfilter/cgen/xdp.c @@ -14,7 +14,7 @@ #include #include -#include "cgen/matcher/packet.h" +#include "cgen/packet.h" #include "cgen/program.h" #include "cgen/stub.h" #include "filter.h" @@ -124,5 +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, + .gen_inline_matcher = bf_packet_gen_inline_matcher, }; From 91afd7462e7ea05dc66c88f334ad6202c2c70eed Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Fri, 20 Mar 2026 10:53:55 -0700 Subject: [PATCH 5/5] lib: cgen: add gen_inline_log flavor callback --- src/libbpfilter/cgen/cgroup_skb.c | 1 + src/libbpfilter/cgen/cgroup_sock_addr.c | 11 ++++++++++ src/libbpfilter/cgen/nf.c | 1 + src/libbpfilter/cgen/packet.c | 25 +++++++++++++++++++++++ src/libbpfilter/cgen/packet.h | 14 +++++++++++++ src/libbpfilter/cgen/program.c | 16 ++++----------- src/libbpfilter/cgen/tc.c | 1 + src/libbpfilter/cgen/xdp.c | 1 + src/libbpfilter/include/bpfilter/flavor.h | 14 +++++++++++++ 9 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/libbpfilter/cgen/cgroup_skb.c b/src/libbpfilter/cgen/cgroup_skb.c index 2ffcef0a1..46eea5319 100644 --- a/src/libbpfilter/cgen/cgroup_skb.c +++ b/src/libbpfilter/cgen/cgroup_skb.c @@ -161,4 +161,5 @@ const struct bf_flavor_ops bf_flavor_ops_cgroup_skb = { .gen_inline_set_mark = _bf_cgroup_skb_gen_inline_set_mark, .get_verdict = _bf_cgroup_skb_get_verdict, .gen_inline_matcher = _bf_cgroup_skb_gen_inline_matcher, + .gen_inline_log = bf_packet_gen_inline_log, }; diff --git a/src/libbpfilter/cgen/cgroup_sock_addr.c b/src/libbpfilter/cgen/cgroup_sock_addr.c index 7d4c4d841..86273d5ac 100644 --- a/src/libbpfilter/cgen/cgroup_sock_addr.c +++ b/src/libbpfilter/cgen/cgroup_sock_addr.c @@ -273,9 +273,20 @@ static int _bf_cgroup_sock_addr_get_verdict(enum bf_verdict verdict) } } +static int _bf_cgroup_sock_addr_gen_inline_log(struct bf_program *program, + const struct bf_rule *rule) +{ + (void)program; + (void)rule; + + return bf_err_r(-ENOTSUP, + "logging is not yet supported for cgroup_sock_addr"); +} + const struct bf_flavor_ops bf_flavor_ops_cgroup_sock_addr = { .gen_inline_prologue = _bf_cgroup_sock_addr_gen_inline_prologue, .gen_inline_epilogue = _bf_cgroup_sock_addr_gen_inline_epilogue, .get_verdict = _bf_cgroup_sock_addr_get_verdict, .gen_inline_matcher = _bf_cgroup_sock_addr_gen_inline_matcher, + .gen_inline_log = _bf_cgroup_sock_addr_gen_inline_log, }; diff --git a/src/libbpfilter/cgen/nf.c b/src/libbpfilter/cgen/nf.c index f0728f986..2fdba83c3 100644 --- a/src/libbpfilter/cgen/nf.c +++ b/src/libbpfilter/cgen/nf.c @@ -176,4 +176,5 @@ const struct bf_flavor_ops bf_flavor_ops_nf = { .gen_inline_epilogue = _bf_nf_gen_inline_epilogue, .get_verdict = _bf_nf_get_verdict, .gen_inline_matcher = _bf_nf_gen_inline_matcher, + .gen_inline_log = bf_packet_gen_inline_log, }; diff --git a/src/libbpfilter/cgen/packet.c b/src/libbpfilter/cgen/packet.c index 41f7b0b7b..115874149 100644 --- a/src/libbpfilter/cgen/packet.c +++ b/src/libbpfilter/cgen/packet.c @@ -14,14 +14,17 @@ #include #include +#include #include #include #include +#include #include "cgen/matcher/cmp.h" #include "cgen/matcher/meta.h" #include "cgen/matcher/set.h" #include "cgen/program.h" +#include "cgen/runtime.h" #include "cgen/stub.h" #include "filter.h" @@ -355,3 +358,25 @@ int bf_packet_gen_inline_matcher(struct bf_program *program, bf_matcher_get_type(matcher)); } } + +int bf_packet_gen_inline_log(struct bf_program *program, + const struct bf_rule *rule) +{ + assert(program); + assert(rule); + + EMIT(program, BPF_MOV64_REG(BPF_REG_1, BPF_REG_10)); + EMIT(program, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, BF_PROG_CTX_OFF(arg))); + EMIT(program, BPF_MOV64_IMM(BPF_REG_2, rule->index)); + EMIT(program, BPF_MOV64_IMM(BPF_REG_3, rule->log)); + EMIT(program, BPF_MOV64_IMM(BPF_REG_4, rule->verdict)); + + // Pack l3_proto and l4_proto + EMIT(program, BPF_MOV64_REG(BPF_REG_5, BPF_REG_7)); + EMIT(program, BPF_ALU64_IMM(BPF_LSH, BPF_REG_5, 16)); + EMIT(program, BPF_ALU64_REG(BPF_OR, BPF_REG_5, BPF_REG_8)); + + EMIT_FIXUP_ELFSTUB(program, BF_ELFSTUB_PKT_LOG); + + return 0; +} diff --git a/src/libbpfilter/cgen/packet.h b/src/libbpfilter/cgen/packet.h index f459a363a..06303eb7c 100644 --- a/src/libbpfilter/cgen/packet.h +++ b/src/libbpfilter/cgen/packet.h @@ -7,6 +7,7 @@ struct bf_matcher; struct bf_program; +struct bf_rule; /** * @brief Generate bytecode for a packet-based matcher. @@ -25,3 +26,16 @@ struct bf_program; */ int bf_packet_gen_inline_matcher(struct bf_program *program, const struct bf_matcher *matcher); + +/** + * @brief Generate bytecode for packet-based rule logging. + * + * Sets up registers and calls the packet log ELF stub. Shared by all + * packet-based flavors (TC, NF, XDP, cgroup_skb). + * + * @param program Program being generated. Can't be NULL. + * @param rule Rule whose log action to generate. Can't be NULL. + * @return 0 on success, negative errno on error. + */ +int bf_packet_gen_inline_log(struct bf_program *program, + const struct bf_rule *rule); diff --git a/src/libbpfilter/cgen/program.c b/src/libbpfilter/cgen/program.c index ca8524a20..5195d024d 100644 --- a/src/libbpfilter/cgen/program.c +++ b/src/libbpfilter/cgen/program.c @@ -292,6 +292,7 @@ static int _bf_program_generate_rule(struct bf_program *program, assert(program); assert(rule); assert(program->runtime.ops->gen_inline_matcher); + assert(program->runtime.ops->gen_inline_log); if (rule->disabled) return 0; @@ -346,18 +347,9 @@ static int _bf_program_generate_rule(struct bf_program *program, } if (rule->log) { - EMIT(program, BPF_MOV64_REG(BPF_REG_1, BPF_REG_10)); - EMIT(program, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, BF_PROG_CTX_OFF(arg))); - EMIT(program, BPF_MOV64_IMM(BPF_REG_2, rule->index)); - EMIT(program, BPF_MOV64_IMM(BPF_REG_3, rule->log)); - EMIT(program, BPF_MOV64_IMM(BPF_REG_4, rule->verdict)); - - // Pack l3_proto and l4_proto - EMIT(program, BPF_MOV64_REG(BPF_REG_5, BPF_REG_7)); - EMIT(program, BPF_ALU64_IMM(BPF_LSH, BPF_REG_5, 16)); - EMIT(program, BPF_ALU64_REG(BPF_OR, BPF_REG_5, BPF_REG_8)); - - EMIT_FIXUP_ELFSTUB(program, BF_ELFSTUB_PKT_LOG); + r = program->runtime.ops->gen_inline_log(program, rule); + if (r) + return r; } if (rule->counters) { diff --git a/src/libbpfilter/cgen/tc.c b/src/libbpfilter/cgen/tc.c index eb624c4a8..dd4d64aa0 100644 --- a/src/libbpfilter/cgen/tc.c +++ b/src/libbpfilter/cgen/tc.c @@ -175,4 +175,5 @@ const struct bf_flavor_ops bf_flavor_ops_tc = { .gen_inline_redirect = _bf_tc_gen_inline_redirect, .get_verdict = _bf_tc_get_verdict, .gen_inline_matcher = _bf_tc_gen_inline_matcher, + .gen_inline_log = bf_packet_gen_inline_log, }; diff --git a/src/libbpfilter/cgen/xdp.c b/src/libbpfilter/cgen/xdp.c index c4e724e77..7c2030e45 100644 --- a/src/libbpfilter/cgen/xdp.c +++ b/src/libbpfilter/cgen/xdp.c @@ -125,4 +125,5 @@ const struct bf_flavor_ops bf_flavor_ops_xdp = { .gen_inline_redirect = _bf_xdp_gen_inline_redirect, .get_verdict = _bf_xdp_get_verdict, .gen_inline_matcher = bf_packet_gen_inline_matcher, + .gen_inline_log = bf_packet_gen_inline_log, }; diff --git a/src/libbpfilter/include/bpfilter/flavor.h b/src/libbpfilter/include/bpfilter/flavor.h index 51c7440dd..82ccc4505 100644 --- a/src/libbpfilter/include/bpfilter/flavor.h +++ b/src/libbpfilter/include/bpfilter/flavor.h @@ -11,6 +11,7 @@ struct bf_matcher; struct bf_program; +struct bf_rule; /** * @file flavor.h @@ -135,6 +136,19 @@ struct bf_flavor_ops */ int (*gen_inline_matcher)(struct bf_program *program, const struct bf_matcher *matcher); + + /** + * @brief Generate bytecode for rule logging. + * + * Each flavor controls its own register setup and ELF stub selection. + * Required for all flavors. + * + * @param program Program being generated. Can't be NULL. + * @param rule Rule whose log action to generate. Can't be NULL. + * @return 0 on success, or negative errno on error. + */ + int (*gen_inline_log)(struct bf_program *program, + const struct bf_rule *rule); }; /**