Project: Inspektor Gadget (Observability and Analysis / Observability)
File: gadget-helper-api.md

title: 'Gadget helper API' weight: 10 description: 'Reference documentation for the gadget helper API' The gadget helper API is a set of features exposed by Inspektor Gadget that is accessible from eBPF code. To make use of container enrichment, gadgets must include : ```C ``` Inspektor Gadget will automatically enrich events with container information when the events include the mount namespace in this way: ```C struct event { gadgetmntnsid mntns_id; / other fields / } ``` An eBPF program can look up the mount namespace with the following: ```C u64 mntns_id; mntnsid = gadgetgetmntnsid(); ``` eBPF programs of type socket filter cannot use `gadgetgetmntns_id()`, but instead use socket enrichment to find the mount namespace. To make use of container filtering, gadgets must include : ```C ``` eBPF programs should stop processing an event when it does not originate from a container the user is interested in. ``` if (gadgetshoulddiscardmntnsid(mntns_id)) return 0; ``` To make use of socket enrichment, gadgets must include . For eBPF programs of type socket filter: ```C ``` For eBPF programs of other kinds: ```C ``` This will define the following struct: ```C struct sockets_value { u64 mntns; u64 pid_tgid; u64 uid_gid; char task[TASKCOMMLEN]; / other private fields / }; ``` Then, an eBPF can find additional details about a socket with `gadgetsocketlookup()`. There are two different definitions of this function depending on the eBPF program type. The developer must define either `GADGETTYPENETWORKING` or `GADGETTYPETRACING` to define the right one. It can return NULL if the socket is not found. For eBPF programs of type socket filter: ```C struct socketsvalue *skbval = gadgetsocketlookup(skb); if (skb_val != NULL) { / Access skb_val->mntns and other fields / } ``` For eBPF programs of other kinds: ```C struct socketsvalue *skbval = gadgetsocketlookup(sk, netns); if (skb_val != NULL) { / Access skb_val->mntns and other fields / } ``` When a gadget emits an event with one of the following fields, it will be automatically

```C struct event { struct gadgetl3endpointt field1; struct gadgetl4endpointt field2; gadgetmntnsid field3; gadget_timestamp field4; } ``` `struct gadgetl3endpointt` and `struct gadgetl4endpointt`: enrich with the Kubernetes endpoint. TODO: add details. `typedef u64 gadgetmntnsid`: container enrichment (see #container-enrichment) `typedef u64 gadgettimestamp`: add human-readable timestamp from `bpfktimegetboot_ns()`. There are two kind of eBPF maps used to send events to userspace: (a) perf ring buffer or (b) eBPF ring buffer. The later is more efficient and flexible, however it's only available from kernel 5.8. Check https://nakryiko.com/posts/bpf-ringbuf/ to get more details about the differences. `<gadget/buffer.h>` provides an abstraction to automatically use the right buffer according to the kernel features. First, you need to declare the buffer with the following macro: ```C GADGETTRACERMAP(events, 1024 * 256); ``` Then, you can interact with the buffer using these functions: `void gadget_reserve_buf(void map, u64 size)`: Reserves memory in the corresponding buffer. `long gadgetsubmitbuf(void ctx, void map, void *buf, u64 size)`: Writes the previously reserved memory in the corresponding buffer. `void gadgetdiscardbuf(void *buf)`: Discards the previously reserved buffer. This is needed to avoid wasting memory. `long gadgetoutputbuf(void ctx, void map, void *buf, u64 size)`: Reserves and writes the buffer in the corresponding map. This is equivalent to calling `gadgetreservebuf()` and `gadgetsubmitbuf()`. The following snippet demonstrates how to use the code available in `<gadget/buffer.h>`, it is taken from `trace_open`: ```C / ... / GADGETTRACERMAP(events, 1024 * 256); GADGET_TRACER(exit, events, event); / ... / static alwaysinline int traceexit(struct syscalltraceexit *ctx) { struct event *event; / ... / event = gadgetreservebuf(&events, sizeof(*event)); if (!event) goto cleanup; / fill the event here / / ... / gadgetsubmitbuf(ctx, &events, event, sizeof(*event)); / ... / } ``` If you know you will not make use of `gadgetreservebuf()/gadgetsubmitbuf()` and only rely on `gadgetoutputbuf()`, you can define the `GADGETNOBUF_RESERVE` macro before including `<gadget/buffer.h>`. This will not declare the map associated with `gadgetreservebuf()` as well as the other functions. Here is an example, taken from `traceexec`, of using `gadgetoutput_buf()`: ```C / ... / GADGETTRACERMAP(events, 1024 * 256); GADGET_TRACER(exec, events, event); / ... / SEC("tracepoint/syscalls/sysexitexecve") int igexecvex(struct syscalltraceexit *ctx) { / ... / struct event *event; / ... / event = bpfmaplookup_elem(&execs, &pid); if (!event) return 0; / ... / if (len <= sizeof(*event)) gadgetoutputbuf(ctx, &events, event, len); / ... / } ```