tcModule
Linux Traffic Control (TC) integration.
This library allows Lua scripts to interact with the kernel’s TC subsystem. It enables TC/eBPF programs to call Lua functions for packet processing, traffic shaping, filtering, and policy enforcement, providing a flexible way to implement custom networking logic in Lua at the ingress and egress layers of network stack. The primary mechanism involves a TC program calling the bpf_luatc_run
kfunc, which in turn invokes a Lua callback function previously registered
using tc.attach().
The module registers its kfunc through BTF: it needs a kernel built with CONFIG_DEBUG_INFO_BTF
and a build made after make btf_install. Without the module BTF it loads with its kfunc
unregistered, logging missing module BTF, and an eBPF program that calls the kfunc fails to
load. The eBPF program is loaded apart, with bpftool, as a SCHED_CLS (classifier) program
that declares bpf_luatc_run as a __ksym, as
examples/sniclassify does.
Class tc_ctx
| tc_ctx:argument () | Returns the argument data buffer passed from eBPF. |
| tc_ctx:skb () | Returns the packet object for the current TC context. |
tc
| attach (callback) | Registers a Lua callback function to be invoked by a TC/eBPF program. |
| detach () | Unregisters the Lua callback function associated with the current Lunatik runtime. |
Class tc_ctx in detail
- tc_ctx:argument ()
-
Returns the argument data buffer passed from eBPF.
Returns
-
data
argument buffer
- tc_ctx:skb ()
-
Returns the packet object for the current TC context.
Returns
tc in detail
- attach (callback)
-
Registers a Lua callback function to be invoked by a TC/eBPF program.
When a TC program calls the
bpf_luatc_runkfunc, Lunatik will execute the registered Luacallbackassociated with the current Lunatik runtime. The runtime must be softirq,lunatik run -c softirq <script>.The
bpf_luatc_runkfunc is called from an eBPF program with the following signature:int bpf_luatc_run(char key, size_t key__sz, struct __sk_buff sk_buff, void *arg, size_t arg__sz)key: A string identifying the Lunatik runtime: the script path under/lib/modules/luawithout its.luaextension, as given tolunatik run(e.g. “examples/sniclassify/sni”). This key is used to look up the runtime in Lunatik’s internal table of active runtimes.key_sz: Length of the key string (including the null terminator).sk_buff: The TC metadata context (struct __sk_buff *).arg: A pointer to arbitrary data passed from eBPF to Lua.arg_sz: The size of theargdata.
In the callback, the skb methods that would linearize a packet raise on a non-linear one instead, such as a locally sent TCP segment or a GRO-merged one: the verifier keeps the program’s packet pointers across a kfunc, and linearizing can move the packet out from under them. A program whose callback reads the whole packet calls
bpf_skb_pull_data(skb, skb->len)beforebpf_luatc_run, after which the verifier has it reload its packet pointers.Parameters
- callback
function
Lua function to call. It receives one argument:
ctx: A tc_ctx context object used to inspect the packet.It returns the verdict, a value of linux.tc.action, which
bpf_luatc_runreturns to the eBPF program. When it returns nothing or nil, or raises,bpf_luatc_runreturns-1and the verdict is left to the eBPF program; a value that is not a TC action is logged asinvalid actionand answered the same way.
Returns
-
nil
Raises
runtime context mismatchoutside a softirq runtime;not allowed while the runtime closesfrom a finalizer that runs at its close; or if internal setup fails.See also
Usage
-- Lua script my_tc_handler.lua, run with
lunatik run -c softirq my_tc_handlerlocal tc = require("tc") local action = require("linux.tc").action local function my_traffic_shaper(ctx) local skb = ctx:skb() print("Packet received, size:", #skb) return action.OK end tc.attach(my_traffic_shaper) -- In eBPF C code, to call the above Lua function: -- char rt_key[] = "my_tc_handler"; // the script name without .lua -- int verdict = bpf_luatc_run(rt_key, sizeof(rt_key), skb, NULL, 0); - detach ()
-
Unregisters the Lua callback function associated with the current Lunatik runtime.
After calling this,
bpf_luatc_runcalls targeting this runtime invoke no Lua function: they logno callback attached, return-1and leave the verdict to the eBPF program.Returns
-
nil
Usage
tc.detach()