Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc/Doxyfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 17 additions & 14 deletions src/bfcli/print.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 : <unknown header>\n");
return;
}
Expand Down Expand Up @@ -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 : <unknown header>\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));
Expand All @@ -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));
Expand Down Expand Up @@ -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 : <unknown header>\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",
Expand All @@ -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),
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
}
2 changes: 1 addition & 1 deletion src/libbpfilter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ bf_target_add_elfstubs(libbpfilter
"parse_ipv6_eh"
"parse_ipv6_nh"
"update_counters"
"log"
"pkt_log"
"flow_hash"
)

Expand Down
Original file line number Diff line number Diff line change
@@ -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 <linux/bpf.h>
Expand All @@ -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);
Expand All @@ -28,28 +28,29 @@ __u8 bf_log(struct bf_runtime *ctx, __u32 rule_id, __u8 headers, __u32 verdict,
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);
Expand Down
2 changes: 1 addition & 1 deletion src/libbpfilter/cgen/program.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions src/libbpfilter/include/bpfilter/elfstub.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down
111 changes: 92 additions & 19 deletions src/libbpfilter/include/bpfilter/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <linux/in6.h>

#include <asm/types.h>

/**
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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;

Expand All @@ -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
Expand Down
Loading