High-level declarative macros for clj-ebpf.
This namespace provides macros that reduce boilerplate and make BPF programming more 'Clojure-like' for scripting and application development.
Main macros:
defprogram - Define a named BPF program with assembled bytecodedefmap-spec - Define a reusable map specificationwith-bpf-script - Lifecycle management for maps, programs, and attachmentsHigh-level declarative macros for clj-ebpf. This namespace provides macros that reduce boilerplate and make BPF programming more 'Clojure-like' for scripting and application development. Main macros: - `defprogram` - Define a named BPF program with assembled bytecode - `defmap-spec` - Define a reusable map specification - `with-bpf-script` - Lifecycle management for maps, programs, and attachments
(close-programs progs-map)Close all BPF programs.
Close all BPF programs.
(create-defmap map-spec)Create a map from a specification defined with defmap-spec.
This is a convenience function that creates a BPF map from a spec.
Parameters: map-spec - A map specification created with defmap-spec
Returns: A BpfMap record
Example: (defmap-spec my-map :type :hash :key-size 4 :value-size 4 :max-entries 100) (let [m (create-defmap my-map)] (try ;; use map (finally (bpf/close-map m))))
Create a map from a specification defined with defmap-spec.
This is a convenience function that creates a BPF map from a spec.
Parameters:
map-spec - A map specification created with defmap-spec
Returns:
A BpfMap record
Example:
(defmap-spec my-map :type :hash :key-size 4 :value-size 4 :max-entries 100)
(let [m (create-defmap my-map)]
(try
;; use map
(finally
(bpf/close-map m))))(create-maps-from-specs map-specs)Create BPF maps from specifications. Returns map of binding->BpfMap.
Create BPF maps from specifications. Returns map of binding->BpfMap.
(defmap-spec name & args)Define a reusable BPF map specification.
Creates a var containing a map specification that can be passed to
create-map or used with with-bpf-script.
Parameters: name - The var name for this map specification docstring - Optional documentation string
Options (keyword args): :type - Map type keyword (:hash, :array, :lru-hash, :percpu-hash, :percpu-array, :lru-percpu-hash, :stack, :queue, :ringbuf, :lpm-trie, :perf-event-array) :key-size - Size of key in bytes (required for most map types) :value-size - Size of value in bytes (required for most map types) :max-entries - Maximum number of entries (required) :flags - Optional map flags (default 0) :map-name - Optional name string for the map :key-serializer - Function to serialize keys to bytes (default: int->bytes) :key-deserializer - Function to deserialize bytes to keys (default: bytes->int) :value-serializer - Function to serialize values to bytes (default: int->bytes) :value-deserializer - Function to deserialize bytes to values (default: bytes->int)
Example: (defmap-spec my-hash-map :type :hash :key-size 4 :value-size 8 :max-entries 1024)
;; With docstring: (defmap-spec my-hash-map "A map for storing events" :type :hash :key-size 4 :value-size 8 :max-entries 1024)
;; Usage: (bpf/with-map [m (bpf/create-map my-hash-map)] (bpf/map-update m 1 100))
;; Or with with-bpf-script: (with-bpf-script {:maps [m my-hash-map]} (bpf/map-update m 1 100))
Define a reusable BPF map specification.
Creates a var containing a map specification that can be passed to
`create-map` or used with `with-bpf-script`.
Parameters:
name - The var name for this map specification
docstring - Optional documentation string
Options (keyword args):
:type - Map type keyword (:hash, :array, :lru-hash, :percpu-hash,
:percpu-array, :lru-percpu-hash, :stack, :queue, :ringbuf,
:lpm-trie, :perf-event-array)
:key-size - Size of key in bytes (required for most map types)
:value-size - Size of value in bytes (required for most map types)
:max-entries - Maximum number of entries (required)
:flags - Optional map flags (default 0)
:map-name - Optional name string for the map
:key-serializer - Function to serialize keys to bytes (default: int->bytes)
:key-deserializer - Function to deserialize bytes to keys (default: bytes->int)
:value-serializer - Function to serialize values to bytes (default: int->bytes)
:value-deserializer - Function to deserialize bytes to values (default: bytes->int)
Example:
(defmap-spec my-hash-map
:type :hash
:key-size 4
:value-size 8
:max-entries 1024)
;; With docstring:
(defmap-spec my-hash-map
"A map for storing events"
:type :hash
:key-size 4
:value-size 8
:max-entries 1024)
;; Usage:
(bpf/with-map [m (bpf/create-map my-hash-map)]
(bpf/map-update m 1 100))
;; Or with with-bpf-script:
(with-bpf-script {:maps [m my-hash-map]}
(bpf/map-update m 1 100))(defprogram name & args)Define a named BPF program with assembled bytecode and metadata.
Creates a var containing a map with the program specification that can
be passed to load-program or used with with-bpf-script.
Parameters: name - The var name for this program docstring - Optional documentation string
Options (keyword args): :type - Program type keyword (:kprobe, :kretprobe, :uprobe, :uretprobe, :tracepoint, :raw-tracepoint, :xdp, :tc, :cgroup-skb, :cgroup-sock, :lsm, :fentry, :fexit, :socket-filter, etc.) :license - License string (default "GPL") :body - Vector of DSL instructions (will be assembled into bytecode) :opts - Optional map of additional options: :log-level - Verifier log level (0=off, 1=basic, 2=verbose) :prog-name - Program name for debugging
The :body is assembled into bytecode using clj-ebpf.dsl/assemble.
Example: (defprogram my-xdp-filter :type :xdp :license "GPL" :body [(dsl/mov :r0 2) ; XDP_PASS (dsl/exit-insn)])
;; With docstring: (defprogram my-xdp-filter "An XDP program that passes all packets" :type :xdp :body [(dsl/mov :r0 2) (dsl/exit-insn)])
;; Usage: (bpf/with-program [prog (bpf/load-program my-xdp-filter)] (bpf/attach-xdp prog "lo"))
;; Or with with-bpf-script: (with-bpf-script {:progs [p my-xdp-filter] :attach [{:prog p :type :xdp :target "lo"}]} (Thread/sleep 5000))
Define a named BPF program with assembled bytecode and metadata.
Creates a var containing a map with the program specification that can
be passed to `load-program` or used with `with-bpf-script`.
Parameters:
name - The var name for this program
docstring - Optional documentation string
Options (keyword args):
:type - Program type keyword (:kprobe, :kretprobe, :uprobe, :uretprobe,
:tracepoint, :raw-tracepoint, :xdp, :tc, :cgroup-skb,
:cgroup-sock, :lsm, :fentry, :fexit, :socket-filter, etc.)
:license - License string (default "GPL")
:body - Vector of DSL instructions (will be assembled into bytecode)
:opts - Optional map of additional options:
:log-level - Verifier log level (0=off, 1=basic, 2=verbose)
:prog-name - Program name for debugging
The :body is assembled into bytecode using `clj-ebpf.dsl/assemble`.
Example:
(defprogram my-xdp-filter
:type :xdp
:license "GPL"
:body [(dsl/mov :r0 2) ; XDP_PASS
(dsl/exit-insn)])
;; With docstring:
(defprogram my-xdp-filter
"An XDP program that passes all packets"
:type :xdp
:body [(dsl/mov :r0 2)
(dsl/exit-insn)])
;; Usage:
(bpf/with-program [prog (bpf/load-program my-xdp-filter)]
(bpf/attach-xdp prog "lo"))
;; Or with with-bpf-script:
(with-bpf-script {:progs [p my-xdp-filter]
:attach [{:prog p :type :xdp :target "lo"}]}
(Thread/sleep 5000))(detach-all attached-pairs)Detach all attached programs.
Detach all attached programs.
(load-defprogram prog-spec)Load a program defined with defprogram.
This is a convenience function that resolves the program spec and loads it.
Parameters: prog-spec - A program specification created with defprogram
Returns: A loaded BpfProgram record
Example: (defprogram my-prog :type :xdp :body [...]) (let [prog (load-defprogram my-prog)] (try ;; use prog (finally (bpf/close-program prog))))
Load a program defined with defprogram.
This is a convenience function that resolves the program spec and loads it.
Parameters:
prog-spec - A program specification created with defprogram
Returns:
A loaded BpfProgram record
Example:
(defprogram my-prog :type :xdp :body [...])
(let [prog (load-defprogram my-prog)]
(try
;; use prog
(finally
(bpf/close-program prog))))(load-programs-from-specs prog-specs maps-map)Load BPF programs from specifications. Returns map of binding->BpfProgram.
Load BPF programs from specifications. Returns map of binding->BpfProgram.
(perform-attachments attach-specs progs-map)Perform attachments based on attach specifications. Returns a vector of [prog-binding updated-prog] pairs.
Perform attachments based on attach specifications. Returns a vector of [prog-binding updated-prog] pairs.
(with-bpf-script {:keys [maps progs attach]} & body)Execute body with BPF maps, programs, and attachments, ensuring cleanup.
This is the 'god macro' for quick scripts, tutorials, and REPL experiments. It handles the entire lifecycle of BPF resources.
Parameters: config - Map with the following optional keys: :maps - Vector of [binding map-spec] pairs for maps to create :progs - Vector of [binding prog-spec] pairs for programs to load :attach - Vector of attachment specifications body - Forms to execute while resources are active
Attachment specification keys: :prog - Binding name of the program to attach :type - Attachment type (:xdp, :tc, :kprobe, :kretprobe, :tracepoint, :uprobe, :uretprobe, :cgroup-skb, :cgroup-sock, :lsm) :target - Target for attachment (interface, function name, cgroup path, etc.)
Type-specific options: :xdp - :flags, :mode (:skb, :native, :offload) :tc - :direction (:ingress, :egress), :priority :kprobe - :function, :retprobe? :tracepoint - :category, :event :uprobe - :binary, :offset, :symbol, :retprobe? :cgroup-skb - :cgroup-path, :direction (:ingress, :egress) :cgroup-sock - :cgroup-path :lsm - :hook
Example: (defmap-spec counter-map :type :array :key-size 4 :value-size 8 :max-entries 1)
(defprogram filter-prog :type :xdp :body [(dsl/mov :r0 2) ; XDP_PASS (dsl/exit-insn)])
(with-bpf-script {:maps [m counter-map] :progs [p filter-prog] :attach [{:prog p :type :xdp :target "lo"}]}
(println "BPF running on loopback")
(bpf/map-update m 0 42)
(println "Counter:" (bpf/map-lookup m 0))
(Thread/sleep 5000))
;; Automatically detaches, unloads programs, and closes maps
Execute body with BPF maps, programs, and attachments, ensuring cleanup.
This is the 'god macro' for quick scripts, tutorials, and REPL experiments.
It handles the entire lifecycle of BPF resources.
Parameters:
config - Map with the following optional keys:
:maps - Vector of [binding map-spec] pairs for maps to create
:progs - Vector of [binding prog-spec] pairs for programs to load
:attach - Vector of attachment specifications
body - Forms to execute while resources are active
Attachment specification keys:
:prog - Binding name of the program to attach
:type - Attachment type (:xdp, :tc, :kprobe, :kretprobe, :tracepoint,
:uprobe, :uretprobe, :cgroup-skb, :cgroup-sock, :lsm)
:target - Target for attachment (interface, function name, cgroup path, etc.)
Type-specific options:
:xdp - :flags, :mode (:skb, :native, :offload)
:tc - :direction (:ingress, :egress), :priority
:kprobe - :function, :retprobe?
:tracepoint - :category, :event
:uprobe - :binary, :offset, :symbol, :retprobe?
:cgroup-skb - :cgroup-path, :direction (:ingress, :egress)
:cgroup-sock - :cgroup-path
:lsm - :hook
Example:
(defmap-spec counter-map
:type :array
:key-size 4
:value-size 8
:max-entries 1)
(defprogram filter-prog
:type :xdp
:body [(dsl/mov :r0 2) ; XDP_PASS
(dsl/exit-insn)])
(with-bpf-script
{:maps [m counter-map]
:progs [p filter-prog]
:attach [{:prog p :type :xdp :target "lo"}]}
(println "BPF running on loopback")
(bpf/map-update m 0 42)
(println "Counter:" (bpf/map-lookup m 0))
(Thread/sleep 5000))
;; Automatically detaches, unloads programs, and closes mapscljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |