From ea718ffdc4c2dfcde1d33ced907a98ad35a310cd Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Fri, 20 Mar 2026 09:58:57 -0700 Subject: [PATCH 1/4] 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 423462ee2..85bc67f59 100644 --- a/src/libbpfilter/cgen/program.c +++ b/src/libbpfilter/cgen/program.c @@ -363,7 +363,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 05a35023109eb586349a7997ddced0634ef87ff9 Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Fri, 20 Mar 2026 10:06:15 -0700 Subject: [PATCH 2/4] 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 | 111 +++++++++++++++++---- 4 files changed, 121 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..1d3de9b39 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 BF_ANONYMOUS_MEMBER(name) name +#else +#define BF_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,78 @@ 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; + + /** 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 +177,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; + } BF_ANONYMOUS_MEMBER(payload); }; struct bf_ip4_lpm_key From c03a0ebbd4a5d0c0d2f1235c8b38ebb72935e04e Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Fri, 20 Mar 2026 10:43:20 -0700 Subject: [PATCH 3/4] 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 5cc7d36e9132373360cd161a6fd08385bbda5f63 Mon Sep 17 00:00:00 2001 From: yaakov-stein Date: Fri, 20 Mar 2026 10:53:55 -0700 Subject: [PATCH 4/4] 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 85bc67f59..b1b6f82d9 100644 --- a/src/libbpfilter/cgen/program.c +++ b/src/libbpfilter/cgen/program.c @@ -298,6 +298,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; @@ -352,18 +353,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); }; /**