Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Control Flow

if

Two-way conditional. Returns the value of the taken branch.

(if (> data-end (+ data 34))
    (process-packet data)
    XDP_DROP)

When the test is a comparison form (=, >, <, etc.), the compiler emits a direct conditional jump instead of materializing a 0/1 value.

when, unless

One-armed conditionals with implicit progn body. Return 0 when the body is skipped.

(when (= proto +ip-proto-tcp+)
  (incf (getmap tcp-count 0))
  (process-tcp data))

(unless (> (+ data 34) data-end)
  (return XDP_PASS))

when-let

Bind variables and execute the body only if all bound values are non-zero. If any initializer evaluates to 0, the remaining bindings and the body are skipped. Returns 0 when skipped.

;; Null-check a map lookup and use the pointer
(when-let ((p (map-lookup my-map key)))
  (atomic-add p 0 1))

;; Typed binding
(when-let ((p u64 (map-lookup my-map key)))
  (load u32 p 0))

;; Multiple bindings -- all must be non-zero
(when-let ((a (map-lookup m1 k1))
           (b (map-lookup m2 k2)))
  (+ (load u64 a 0) (load u64 b 0)))

if-let

Bind a variable and branch on its value. If the initializer is non-zero, execute the then branch with the variable in scope. Otherwise execute the else branch.

(if-let (p (map-lookup my-map key))
  (load u64 p 0)   ; then: p is bound and non-zero
  0)                ; else: key not found

;; Typed binding
(if-let (p u64 (map-lookup my-map key))
  (load u32 p 0)
  0)

cond

Multi-way conditional. Clauses are tested in order; the body of the first matching clause executes. A final t clause is the default.

(cond
  ((= proto +ip-proto-tcp+)  (handle-tcp data))
  ((= proto +ip-proto-udp+)  (handle-udp data))
  (t                          XDP_PASS))

case

Multi-way dispatch on a value. Shadows CL's case. Each clause is (value body...) or ((v1 v2 ...) body...). The final clause may use t or otherwise as a catch-all. Compiles to a cond chain.

(case (ipv4-protocol ip)
  (+ip-proto-tcp+  (handle-tcp))
  (+ip-proto-udp+  (handle-udp))
  ((41 47)         (handle-tunnel))   ; match multiple values
  (t               XDP_PASS))

and, or

Short-circuit logical operators. and returns 0 as soon as any operand is zero; or returns the first non-zero operand. These are compiler primitives, not CL macros.

(when (and (= proto +ip-proto-tcp+)
           (logand flags +tcp-syn+)
           (not (logand flags +tcp-ack+)))
  (log-syn-packet data))

(let ((port (or (tcp-dst-port tcp) (tcp-src-port tcp))))
  ...)

progn

Evaluate forms in sequence, return the value of the last one.

(progn
  (incf (getmap pkt-count 0))
  XDP_PASS)

return

Exit the BPF program early with a return value. If no value is given, returns 0.

(when (> (+ data 34) data-end)
  (return XDP_PASS))