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

Protocol Library

Whistler includes a compile-time protocol header library in protocols.lisp. All macros expand to (load TYPE ptr OFFSET) at compile time -- zero runtime cost.

defheader

Define custom protocol headers:

(defheader my-proto
  (field-a :offset 0 :type u32)
  (field-b :offset 4 :type u16 :net-order t))

Each field generates an accessor macro (my-proto-FIELD ptr). When :net-order t, the accessor wraps the load in ntohs / ntohl as appropriate for the field size.

Built-in headers

Ethernet (14 bytes)

AccessorOffsetTypeNet-order
eth-dst-mac-hi0u32no
eth-dst-mac-lo4u16no
eth-src-mac-hi6u32no
eth-src-mac-lo10u16no
eth-type12u16yes

IPv4 (20 bytes)

AccessorOffsetTypeNet-order
ipv4-ver-ihl0u8no
ipv4-tos1u8no
ipv4-total-len2u16yes
ipv4-ttl8u8no
ipv4-protocol9u8no
ipv4-src-addr12u32no
ipv4-dst-addr16u32no

IPv6 (40 bytes)

Accessors: ipv6-ver-tc-flow, ipv6-payload-len, ipv6-nexthdr, ipv6-hop-limit, ipv6-src-addr-hi/lo, ipv6-dst-addr-hi/lo.

TCP (20 bytes)

AccessorOffsetTypeNet-order
tcp-src-port0u16yes
tcp-dst-port2u16yes
tcp-seq4u32yes
tcp-ack-seq8u32yes
tcp-data-off12u8no
tcp-flags13u8no
tcp-window14u16yes

UDP (8 bytes)

Accessors: udp-src-port, udp-dst-port, udp-length, udp-checksum.

ICMP (8 bytes)

Accessors: icmp-type, icmp-code, icmp-checksum, icmp-rest.

XDP context access

CO-RE-aware context loads for XDP programs:

(xdp-data)      ;; -> (core-ctx-load u32 0 xdp-md data)
(xdp-data-end)  ;; -> (core-ctx-load u32 4 xdp-md data-end)

Statement-oriented parsing (with-*)

These macros bind packet pointers, perform bounds checks, and early-return XDP_PASS on failure. They use flat guard structure (no nesting of success paths), which is optimal for the BPF verifier.

(with-packet (data data-end :min-len 34) ...)
(with-eth (data data-end) ...)
(with-ipv4 (data data-end ip) ...)
(with-tcp (data data-end tcp) ...)
(with-udp (data data-end udp) ...)

Example:

(defprog my-xdp (:type :xdp :section "xdp" :license "GPL")
  (with-tcp (data data-end tcp)
    ;; tcp is bound to the TCP header pointer
    ;; data, data-end are bound from XDP context
    (when (= (tcp-dst-port tcp) 80)
      (return XDP_DROP)))
  XDP_PASS)

Expression-oriented parsing (parse-*)

Return a pointer on success or 0 on failure. Use with when-let for pipeline-style composition:

(parse-eth data data-end)   ;; returns data or 0
(parse-ipv4 data data-end)  ;; returns IP header ptr or 0
(parse-tcp data data-end)   ;; returns TCP header ptr or 0
(parse-udp data data-end)   ;; returns UDP header ptr or 0

Example:

(let ((data (xdp-data))
      (data-end (xdp-data-end)))
  (when-let ((tcp (parse-tcp data data-end)))
    (incf (getmap stats (tcp-dst-port tcp)))))

TC variants

Traffic Control programs use __sk_buff context (data at offset 76, data_end at offset 80) and return TC_ACT_OK on early exit:

(tc-data)       ;; -> (ctx-load u32 76)
(tc-data-end)   ;; -> (ctx-load u32 80)

(with-tc-packet (data data-end :min-len N) ...)
(with-tc-eth (data data-end) ...)
(with-tc-ipv4 (data data-end ip) ...)
(with-tc-tcp (data data-end tcp) ...)
(with-tc-udp (data data-end udp) ...)

Constants

ConstantValueCategory
+ethertype-ipv4+#x0800EtherType
+ethertype-ipv6+#x86ddEtherType
+ethertype-arp+#x0806EtherType
+ethertype-vlan+#x8100EtherType
+eth-hdr-len+14Header size
+ipv4-hdr-len+20Header size
+ipv6-hdr-len+40Header size
+tcp-hdr-len+20Header size
+udp-hdr-len+8Header size
+icmp-hdr-len+8Header size
+ip-proto-icmp+1IP protocol
+ip-proto-tcp+6IP protocol
+ip-proto-udp+17IP protocol
+tcp-fin+#x01TCP flag
+tcp-syn+#x02TCP flag
+tcp-rst+#x04TCP flag
+tcp-psh+#x08TCP flag
+tcp-ack+#x10TCP flag
+tcp-urg+#x20TCP flag