github.com/inspektor-gadget/inspektor-gadget@v0.28.1/docs/reference/gadget-helper-api.md (about)

     1  ---
     2  title: 'Gadget helper API'
     3  weight: 10
     4  description: 'Reference documentation for the gadget helper API'
     5  ---
     6  
     7  The gadget helper API is a set of features exposed by Inspektor Gadget that is accessible from eBPF code.
     8  
     9  ## Container enrichment
    10  
    11  To make use of container enrichment, gadgets must include
    12  [gadget/mntns.h](https://github.com/inspektor-gadget/inspektor-gadget/blob/main/include/gadget/mntns.h):
    13  
    14  ```C
    15  #include <gadget/mntns.h>
    16  ```
    17  
    18  Inspektor Gadget will automatically enrich events with container information
    19  when the events include the mount namespace in this way:
    20  
    21  ```C
    22  struct event {
    23          gadget_mntns_id mntns_id;
    24          /* other fields */
    25  }
    26  ```
    27  
    28  An eBPF program can look up the mount namespace with the following:
    29  
    30  ```C
    31  u64 mntns_id;
    32  mntns_id = gadget_get_mntns_id();
    33  ```
    34  
    35  eBPF programs of type socket filter cannot use `gadget_get_mntns_id()`, but instead
    36  use socket enrichment to find the mount namespace.
    37  
    38  ## Container filtering
    39  
    40  To make use of container filtering, gadgets must include
    41  [gadget/mntns_filter.h](https://github.com/inspektor-gadget/inspektor-gadget/blob/main/include/gadget/mntns_filter.h):
    42  
    43  ```C
    44  #include <gadget/mntns_filter.h>
    45  ```
    46  
    47  eBPF programs should stop processing an event when it does not originate from a
    48  container the user is interested in.
    49  
    50  ```
    51  if (gadget_should_discard_mntns_id(mntns_id))
    52          return 0;
    53  ```
    54  
    55  ## Socket enrichment
    56  
    57  To make use of socket enrichment, gadgets must include
    58  [gadget/sockets-map.h](https://github.com/inspektor-gadget/inspektor-gadget/blob/main/include/gadget/sockets-map.h).
    59  
    60  For eBPF programs of type socket filter:
    61  
    62  ```C
    63  #define GADGET_TYPE_NETWORKING
    64  #include <gadget/sockets-map.h>
    65  ```
    66  
    67  For eBPF programs of other kinds:
    68  
    69  ```C
    70  #define GADGET_TYPE_TRACING
    71  #include <gadget/sockets-map.h>
    72  ```
    73  
    74  This will define the following struct:
    75  
    76  ```C
    77  #define TASK_COMM_LEN 16
    78  struct sockets_value {
    79          __u64 mntns;
    80          __u64 pid_tgid;
    81          __u64 uid_gid;
    82          char task[TASK_COMM_LEN];
    83          /* other private fields */
    84  };
    85  ```
    86  
    87  Then, an eBPF can find additional details about a socket with
    88  `gadget_socket_lookup()`. There are two different definitions of this function
    89  depending on the eBPF program type. The developer must define either
    90  `GADGET_TYPE_NETWORKING` or `GADGET_TYPE_TRACING` to define the right one.
    91  It can return NULL if the socket is not found.
    92  
    93  For eBPF programs of type socket filter:
    94  
    95  ```C
    96  struct sockets_value *skb_val = gadget_socket_lookup(skb);
    97  if (skb_val != NULL) {
    98          /* Access skb_val->mntns and other fields */
    99  }
   100  ```
   101  
   102  For eBPF programs of other kinds:
   103  
   104  ```C
   105  struct sockets_value *skb_val = gadget_socket_lookup(sk, netns);
   106  if (skb_val != NULL) {
   107          /* Access skb_val->mntns and other fields */
   108  }
   109  ```
   110  
   111  ## Enriched types
   112  
   113  When a gadget emits an event with one of the following fields, it will be
   114  automatically enriched.
   115  
   116  ```C
   117  struct event {
   118          struct gadget_l3endpoint_t  field1;
   119          struct gadget_l4endpoint_t  field2;
   120          gadget_mntns_id             field3;
   121          gadget_timestamp            field4;
   122  }
   123  ```
   124  
   125  * `struct gadget_l3endpoint_t` and `struct gadget_l4endpoint_t`: enrich with the Kubernetes endpoint. TODO: add details.
   126  * `typedef __u64 gadget_mntns_id`: container enrichment (see #container-enrichment)
   127  * `typedef __u64 gadget_timestamp`: add human-readable timestamp from `bpf_ktime_get_boot_ns()`.
   128  
   129  ## Buffer API
   130  
   131  There are two kind of eBPF maps used to send events to userspace: (a) perf ring buffer or (b) eBPF
   132  ring buffer. The later is more efficient and flexible, however it's only available from kernel 5.8.
   133  Check https://nakryiko.com/posts/bpf-ringbuf/ to get more details about the differences.
   134  `<gadget/buffer.h>` provides an abstraction to automatically use the right buffer according to the
   135  kernel features.
   136  
   137  First, you need to declare the buffer with the following macro:
   138  
   139  ```C
   140  GADGET_TRACER_MAP(events, 1024 * 256);
   141  ```
   142  
   143  Then, you can interact with the buffer using these functions:
   144  
   145  1. `void *gadget_reserve_buf(void *map, __u64 size)`: Reserves memory in the corresponding buffer.
   146  1. `long gadget_submit_buf(void *ctx, void *map, void *buf, __u64 size)`: Writes the previously reserved memory in the corresponding buffer.
   147  1. `void gadget_discard_buf(void *buf)`: Discards the previously reserved buffer. This is needed to avoid wasting memory.
   148  1. `long gadget_output_buf(void *ctx, void *map, void *buf, __u64 size)`: Reserves and writes the buffer in the corresponding map. This is equivalent to calling `gadget_reserve_buf()` and `gadget_submit_buf()`.
   149  
   150  The following snippet demonstrates how to use the code available in `<gadget/buffer.h>`, it is taken from `trace_open`:
   151  
   152  ```C
   153  #include <gadget/buffer.h>
   154  
   155  /* ... */
   156  
   157  GADGET_TRACER_MAP(events, 1024 * 256);
   158  
   159  GADGET_TRACER(exit, events, event);
   160  
   161  /* ... */
   162  
   163  static __always_inline int trace_exit(struct syscall_trace_exit *ctx)
   164  {
   165  	struct event *event;
   166  
   167  	/* ... */
   168  
   169  	event = gadget_reserve_buf(&events, sizeof(*event));
   170  	if (!event)
   171  		goto cleanup;
   172  
   173  	/* fill the event here */
   174  
   175  	/* ... */
   176  	gadget_submit_buf(ctx, &events, event, sizeof(*event));
   177  
   178  	/* ... */
   179  }
   180  ```
   181  
   182  If you know you will not make use of `gadget_reserve_buf()/gadget_submit_buf()` and only rely on `gadget_output_buf()`, you can define the `GADGET_NO_BUF_RESERVE` macro before including `<gadget/buffer.h>`.
   183  This will not declare the map associated with `gadget_reserve_buf()` as well as the other functions.
   184  Here is an example, taken from `trace_exec`, of using `gadget_output_buf()`:
   185  
   186  ```C
   187  #define GADGET_NO_BUF_RESERVE
   188  #include <gadget/buffer.h>
   189  
   190  /* ... */
   191  
   192  GADGET_TRACER_MAP(events, 1024 * 256);
   193  
   194  GADGET_TRACER(exec, events, event);
   195  
   196  /* ... */
   197  
   198  SEC("tracepoint/syscalls/sys_exit_execve")
   199  int ig_execve_x(struct syscall_trace_exit *ctx)
   200  {
   201  	/* ... */
   202  	struct event *event;
   203  
   204  	/* ... */
   205  
   206  	event = bpf_map_lookup_elem(&execs, &pid);
   207  	if (!event)
   208  		return 0;
   209  
   210  	/* ... */
   211  
   212  	if (len <= sizeof(*event))
   213  		gadget_output_buf(ctx, &events, event, len);
   214  
   215  	/* ... */
   216  }
   217  ```