Gadget eBPF API
The gadget helper API is a set of features exposed by Inspektor Gadget that is accessible from eBPF code. These features simplify the creation of new gadgets by providing convenient functions for common operations, making the developer's life easier when implementing gadgets.
Gadgets define structures that contain the information provided to the users. The fields of those structures are exposed in different ways according to the format chosen by the user (json, columns, etc.). Inspektor Gadget provides some special types that can be used to provide enrichment and other features as described below.
Ignoring fields
Fields starting with __
are considered private and are ignored by Inspektor
Gadget.
Container enrichment
To make use of container enrichment, gadgets must include gadget/mntns.h:
#include <gadget/mntns.h>
Inspektor Gadget will automatically enrich events with container information when the events include the mount namespace inode ID (see https://man7.org/linux/man-pages/man7/mount_namespaces.7.html) in this way:
You can only have one field of this type in a struct
.
struct event {
gadget_mntns_id mntns_id;
/* other fields */
}
An eBPF program can look up the mount namespace inode ID with the following:
u64 mntns_id;
mntns_id = gadget_get_current_mntns_id();
eBPF programs of type socket filter cannot use gadget_get_current_mntns_id()
, but instead
use socket enrichment to find the mount namespace.
The following fields can be added from the mount or net namespace inode ID. The exact fields that are added depend on the environment (Kubernetes vs local host) and the container runtime (docker, cri-o, containerd, etc.).
Field | Description |
---|---|
k8s.node | Name of the k8s node |
k8s.namespace | Name of the k8s namespace |
k8s.podName | Name of the k8s pod |
k8s.containerName | Name of the k8s container name |
k8s.hostnetwork | true, if the container is using the host network |
runtime.containerName | Name of the container on the container runtime |
runtime.runtimeName | Name of the used container runtime |
runtime.containerId | ID of the container |
runtime.containerImageName | Name of the container image, e.g. nginx:latest |
runtime.containerImageDigest | Digest (hash value) of the container image |
Event filtering
One of the key functionalities of Inspektor Gadget is to efficiently filter events in the kernel. Inspektor Gadget provides a set of helpers that should be used by the Gadget authors. The following helpers (and in general any operation that discards an event) should be executed as early as possible in the eBPF program to minimize the performance overhead of processing events that will be discarded.
The following helpers are available on the
gadget/filter.h
file. Inspektor Gadget automatically exposes the pid
, tid
, comm
, uid
,
gid
and container related parameters to the user when this file is included in
a Gadget.
gadget_should_discard_data
bool gadget_should_discard_data(gadget_mntns_id mntns_id, gadget_pid pid, gadget_tid tid,
gadget_comm comm[TASK_COMM_LEN], gadget_uid uid, gadget_uid gid)
This function receives the common fields of an event and returns true
if it
should be discarded.
gadget_should_discard_data_current
bool gadget_should_discard_data_current()
This function returns true
if an event should be discarded based on the
current process.
Container filtering
To make use of container filtering, gadgets must include gadget/mntns_filter.h:
#include <gadget/mntns_filter.h>
eBPF programs should stop processing an event when it does not originate from a container the user is interested in.
if (gadget_should_discard_mntns_id(mntns_id))
return 0;
Socket enrichment
To make use of socket enrichment, gadgets must include gadget/sockets-map.h.
For eBPF programs of type socket filter:
#define GADGET_TYPE_NETWORKING
#include <gadget/sockets-map.h>
For eBPF programs of other kinds:
#define GADGET_TYPE_TRACING
#include <gadget/sockets-map.h>
This will define the following struct:
#define TASK_COMM_LEN 16
struct gadget_socket_value {
__u64 mntns;
__u64 pid_tgid;
__u64 uid_gid;
char task[TASK_COMM_LEN];
/* other private fields */
};
Then, an eBPF program can find additional details about a socket with
gadget_socket_lookup()
. There are two different definitions of this function
depending on the eBPF program type. The developer must define either
GADGET_TYPE_NETWORKING
or GADGET_TYPE_TRACING
to define the right one. It
can return NULL if the socket is not found.
For eBPF programs of type socket filter:
struct gadget_socket_value *skb_val = gadget_socket_lookup(skb);
if (skb_val != NULL) {
/* Access skb_val->mntns and other fields */
}
For eBPF programs of other kinds:
struct gadget_socket_value *skb_val = gadget_socket_lookup(sk, netns);
if (skb_val != NULL) {
/* Access skb_val->mntns and other fields */
}
Optional Fields
Some of the fields provided by the socket enricher are optional and their size
is configurable, it means, the administrator configuring IG can disable them or
change their max size to reduce the resource consumption. In order to use these
fields, Gadgets MUST use bpf_core_field_exists()
to check if a specific field
is enabled and bpf_core_field_size()
to get their size.
...
bool cwd_exists = bpf_core_field_exists(skb_val->cwd);
int cwd_len = bpf_core_field_size(skb_val->cwd);
if (cwd_exists) {
bpf_probe_read_kernel_str(&event->cwd, cwd_len, skb_val->cwd);
}
...
Enriched types
When a gadget emits an event with one of the following fields, it will be automatically enriched, i.e. new field(s) containing more information will be added to the event.
In some cases, these enrichments can be customized further by applying field annotations. For further information about field annotations, see the metadata documentation.
Some of the enriched fields (or their source fields) are hidden by default when
using the columns
output mode. You can still access them by using either the
json
output mode or the --fields
flag as described in the Selecting
specific fields documentation.