From c58483ab8198ed1f0e539832480b66aea93863d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 Jan 2026 23:10:17 +0000 Subject: [PATCH] Fix documentation: correct comm() usage, XDP types, copyright year, and add uv support Co-authored-by: r41k0u <76248539+r41k0u@users.noreply.github.com> --- docs/README.md | 8 +++++++ docs/api/index.md | 5 +++-- docs/conf.py | 5 +---- docs/getting-started/installation.md | 33 +++++++++++++++++++++++++--- docs/getting-started/quickstart.md | 13 +++++------ docs/user-guide/decorators.md | 12 +++++----- docs/user-guide/helpers.md | 21 ++++++++++-------- docs/user-guide/maps.md | 3 ++- docs/user-guide/structs.md | 23 +++++++++++-------- 9 files changed, 82 insertions(+), 41 deletions(-) diff --git a/docs/README.md b/docs/README.md index dda335b..53c2ad8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,6 +8,14 @@ This directory contains the Sphinx documentation for PythonBPF. Install the documentation dependencies: +**Using uv (recommended):** +```bash +uv pip install -r requirements.txt +# Or install the optional docs dependencies +uv pip install pythonbpf[docs] +``` + +**Using pip:** ```bash pip install -r requirements.txt # Or install the optional docs dependencies diff --git a/docs/api/index.md b/docs/api/index.md index 5bf2313..9483e09 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -327,7 +327,7 @@ Ring buffer for efficient event delivery. ### Process Information * `pid()` - Get current process ID -* `comm()` - Get current process command name +* `comm(buf)` - Get current process command name (requires buffer parameter) * `uid()` - Get current user ID ### Time @@ -450,7 +450,8 @@ def track_exec(ctx: c_void_p) -> c_int64: event = Event() event.timestamp = ktime() event.pid = pid() - event.comm = comm() + # Note: comm() requires a buffer parameter + # comm(event.comm) # Fills event.comm with process name events.output(event) return c_int64(0) diff --git a/docs/conf.py b/docs/conf.py index 0a39eee..679d441 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,7 +13,7 @@ sys.path.insert(0, os.path.abspath('..')) # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = 'PythonBPF' -copyright = '2024, r41k0u, varun-r-mallya' +copyright = '2024-2026, r41k0u, varun-r-mallya' author = 'r41k0u, varun-r-mallya' release = '0.1.8' version = '0.1.8' @@ -90,9 +90,6 @@ html_theme_options = { 'titles_only': False } -# Add any paths that contain custom static files (such as style sheets) -html_static_path = ['_static'] - # -- Options for autodoc ----------------------------------------------------- autodoc_default_options = { diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index d2adc6a..5d8fdd2 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -43,8 +43,14 @@ The `llvm` package provides `llc`, the LLVM compiler that is used to compile LLV ### From PyPI (Recommended) -The easiest way to install PythonBPF is using pip: +The easiest way to install PythonBPF is using uv or pip: +**Using uv (recommended):** +```bash +uv pip install pythonbpf pylibbpf +``` + +**Using pip:** ```bash pip install pythonbpf pylibbpf ``` @@ -73,6 +79,13 @@ source .venv/bin/activate # On Windows: .venv\Scripts\activate 3. Install in development mode: +**Using uv (recommended):** +```bash +uv pip install -e . +uv pip install pylibbpf +``` + +**Using pip:** ```bash pip install -e . pip install pylibbpf @@ -88,6 +101,14 @@ make install If you want to build the documentation locally: +**Using uv (recommended):** +```bash +uv pip install pythonbpf[docs] +# Or from the repository root: +uv pip install -e .[docs] +``` + +**Using pip:** ```bash pip install pythonbpf[docs] # Or from the repository root: @@ -100,6 +121,12 @@ Some examples require access to kernel data structures. To use these features, y 1. Install additional dependencies: +**Using uv (recommended):** +```bash +uv pip install ctypeslib2 +``` + +**Using pip:** ```bash pip install ctypeslib2 ``` @@ -151,8 +178,8 @@ If you get errors about `llc` or `clang` not being found: If Python can't find the `pythonbpf` module: * Make sure you've activated your virtual environment -* Verify installation with `pip list | grep pythonbpf` -* Try reinstalling: `pip install --force-reinstall pythonbpf` +* Verify installation with `uv pip list | grep pythonbpf` or `pip list | grep pythonbpf` +* Try reinstalling: `uv pip install --force-reinstall pythonbpf` or `pip install --force-reinstall pythonbpf` ## Next Steps diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index e11b9c4..c431048 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -120,15 +120,14 @@ Let's make a more interesting program that tracks which processes are being crea ```python from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe -from pythonbpf.helper import pid, comm +from pythonbpf.helper import pid from ctypes import c_void_p, c_int64 @bpf @section("tracepoint/syscalls/sys_enter_execve") def track_exec(ctx: c_void_p) -> c_int64: process_id = pid() - process_name = comm() - print(f"Process {process_name} (PID: {process_id}) is starting") + print(f"Process with PID: {process_id} is starting") return c_int64(0) @bpf @@ -145,7 +144,6 @@ trace_pipe() This program uses BPF helper functions: * `pid()` - Gets the current process ID -* `comm()` - Gets the current process command name Run it with `sudo python3 track_exec.py` and watch processes being created! @@ -182,12 +180,11 @@ def trace_open(ctx: c_void_p) -> c_int64: For network packet processing: ```python -from ctypes import c_uint32 +from pythonbpf.helper import XDP_PASS @section("xdp") -def xdp_pass(ctx: c_void_p) -> c_uint32: - # XDP_PASS = 2 - return c_uint32(2) +def xdp_pass(ctx: c_void_p) -> c_int64: + return XDP_PASS ``` ## Best Practices diff --git a/docs/user-guide/decorators.md b/docs/user-guide/decorators.md index 5b9f9b6..5953b53 100644 --- a/docs/user-guide/decorators.md +++ b/docs/user-guide/decorators.md @@ -108,12 +108,13 @@ def trace_open_return(ctx): For network packet processing at the earliest point: ```python -from ctypes import c_uint32 +from pythonbpf.helper import XDP_PASS +from ctypes import c_void_p, c_int64 @section("xdp") -def xdp_prog(ctx: c_void_p) -> c_uint32: - # XDP_PASS = 2, XDP_DROP = 1, XDP_ABORTED = 0 - return c_uint32(2) +def xdp_prog(ctx: c_void_p) -> c_int64: + # XDP_PASS, XDP_DROP, XDP_ABORTED constants available from pythonbpf.helper + return XDP_PASS ``` #### TC (Traffic Control) @@ -257,7 +258,8 @@ def track_processes(ctx: c_void_p) -> c_int64: event = ProcessEvent() event.timestamp = ktime() event.pid = pid() - event.comm = comm() + # Note: comm() requires a buffer parameter + # comm(event.comm) # Fills event.comm with process name events.output(event) return c_int64(0) diff --git a/docs/user-guide/helpers.md b/docs/user-guide/helpers.md index c19beb9..c09465e 100644 --- a/docs/user-guide/helpers.md +++ b/docs/user-guide/helpers.md @@ -39,14 +39,19 @@ from pythonbpf.helper import comm @bpf @section("tracepoint/syscalls/sys_enter_execve") def trace_exec(ctx: c_void_p) -> c_int64: - process_name = comm() + # comm requires a buffer to fill + process_name = str(16) + comm(process_name) print(f"Executing: {process_name}") return c_int64(0) ``` -**Returns:** `str(16)` - The command name of the current task +**Parameters:** +* `buf` - Buffer to fill with the process command name -**Note:** The returned string is limited to 16 characters (TASK_COMM_LEN). +**Returns:** `c_int64` - 0 on success, negative on error + +**Note:** The buffer should be at least 16 bytes (TASK_COMM_LEN) to hold the full command name. #### uid() @@ -406,17 +411,16 @@ trace_pipe() ```python from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe -from pythonbpf.helper import pid, comm, uid +from pythonbpf.helper import pid, uid from ctypes import c_void_p, c_int64 @bpf @section("tracepoint/syscalls/sys_enter_execve") def track_exec(ctx: c_void_p) -> c_int64: process_id = pid() - process_name = comm() user_id = uid() - print(f"User {user_id} started {process_name} (PID: {process_id})") + print(f"User {user_id} started process (PID: {process_id})") return c_int64(0) @bpf @@ -477,7 +481,7 @@ for cpu, count in map_obj.items(): ```python from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe -from pythonbpf.helper import random, pid, comm +from pythonbpf.helper import random, pid from ctypes import c_void_p, c_int64 @bpf @@ -486,8 +490,7 @@ def sample_opens(ctx: c_void_p) -> c_int64: # Sample 5% of events if (random() % 100) < 5: process_id = pid() - process_name = comm() - print(f"Sampled: {process_name} ({process_id}) opening file") + print(f"Sampled: PID {process_id} opening file") return c_int64(0) diff --git a/docs/user-guide/maps.md b/docs/user-guide/maps.md index 3eacebd..35377fd 100644 --- a/docs/user-guide/maps.md +++ b/docs/user-guide/maps.md @@ -215,7 +215,8 @@ def log_exec(ctx: c_void_p) -> c_int64: event = ProcessEvent() event.timestamp = ktime() event.pid = pid() - event.comm = comm() + # Note: comm() requires a buffer parameter + # comm(event.comm) # Fills event.comm with process name events.output(event) return c_int64(0) diff --git a/docs/user-guide/structs.md b/docs/user-guide/structs.md index 2d27d74..9b0892a 100644 --- a/docs/user-guide/structs.md +++ b/docs/user-guide/structs.md @@ -119,10 +119,11 @@ def capture_event(ctx: c_void_p) -> c_int64: # Set fields event.timestamp = ktime() event.pid = pid() - event.comm = comm() + # Note: comm() requires a buffer parameter to fill + # comm(event.comm) # Fills event.comm with process name # Use the struct - print(f"Process {event.comm} with PID {event.pid}") + print(f"Process with PID {event.pid}") return c_int64(0) ``` @@ -204,7 +205,8 @@ def trace_fork(ctx: c_void_p) -> c_int64: event = ProcessEvent() event.timestamp = ktime() event.pid = pid() - event.comm = comm() + # Note: comm() requires a buffer parameter + # comm(event.comm) # Fills event.comm with process name # Send to userspace events.output(event) @@ -265,7 +267,8 @@ Assign values to fields: event = Event() event.timestamp = ktime() event.pid = pid() -event.comm = comm() +# Note: comm() requires a buffer parameter +# comm(event.comm) # Fills event.comm with process name ``` ### String Fields @@ -285,8 +288,8 @@ def example(ctx: c_void_p) -> c_int64: # Assign string value msg.text = "Hello from BPF" - # Use helper to get process name - msg.text = comm() + # Use helper to get process name (requires buffer) + # comm(msg.text) # Fills msg.text with process name return c_int64(0) ``` @@ -316,6 +319,7 @@ class MyStruct: ```python from pythonbpf import bpf, struct, map, section from pythonbpf.maps import RingBuffer +from pythonbpf.helper import ktime, XDP_PASS from ctypes import c_void_p, c_int64, c_uint8, c_uint16, c_uint32, c_uint64 @bpf @@ -336,7 +340,7 @@ def packets() -> RingBuffer: @bpf @section("xdp") -def capture_packets(ctx: c_void_p) -> c_uint32: +def capture_packets(ctx: c_void_p) -> c_int64: pkt = PacketEvent() pkt.timestamp = ktime() # Parse packet data from ctx... @@ -344,7 +348,7 @@ def capture_packets(ctx: c_void_p) -> c_uint32: packets.output(pkt) # XDP_PASS - return c_uint32(2) + return XDP_PASS ``` ### Process Lifecycle Tracking @@ -377,7 +381,8 @@ def track_fork(ctx: c_void_p) -> c_int64: info = ProcessLifecycle() info.pid = process_id info.start_time = ktime() - info.comm = comm() + # Note: comm() requires a buffer parameter + # comm(info.comm) # Fills info.comm with process name process_info.update(process_id, info)