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 ```