1"use strict";(self.webpackChunkig_website=self.webpackChunkig_website||[]).push([[8691],{31316:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>d});const r=JSON.parse('{"id":"gadget-devel/program-types","title":"eBPF Program Types","description":"Different eBPF programs supported by Inspektor Gadget","source":"@site/versioned_docs/version-v0.56.0/gadget-devel/program-types.md","sourceDirName":"gadget-devel","slug":"/gadget-devel/program-types","permalink":"/docs/v0.56.0/gadget-devel/program-types","draft":false,"unlisted":false,"editUrl":"https://github.com/inspektor-gadget/inspektor-gadget/edit/main/versioned_docs/version-v0.56.0/gadget-devel/program-types.md","tags":[],"version":"v0.56.0","sidebarPosition":310,"frontMatter":{"title":"eBPF Program Types","sidebar_position":310,"description":"Different eBPF programs supported by Inspektor Gadget"},"sidebar":"mainSidebar","previous":{"title":"Gadget eBPF API","permalink":"/docs/v0.56.0/gadget-devel/gadget-ebpf-api"},"next":{"title":"Wasm Golang API","permalink":"/docs/v0.56.0/gadget-devel/gadget-wasm-api-go"}}');var s=n(74848),i=n(28453);const a={title:"eBPF Program Types",sidebar_position:310,description:"Different eBPF programs supported by Inspektor Gadget"},o=void 0,c={},d=[{value:"Program Types",id:"program-types",level:2},{value:"Kprobes / Kretprobes",id:"kprobes--kretprobes",level:3},{value:"Tracepoints",id:"tracepoints",level:3},{value:"Socket Filter",id:"socket-filter",level:3},{value:"SockOps",id:"sockops",level:3},{value:"SkSKB / SkMsg",id:"skskb--skmsg",level:3},{value:"Tracing",id:"tracing",level:3},{value:"Iterators",id:"iterators",level:4},{value:"Fentry / Fexit",id:"fentry--fexit",level:4},{value:"PerfEvents",id:"perfevents",level:3},{value:"Raw Tracepoints",id:"raw-tracepoints",level:3},{value:"SchedCLS",id:"schedcls",level:3},{value:"Uprobes / Uretprobes",id:"uprobes--uretprobes",level:3},{value:"User-Level Statically Defined Tracing (USDT)",id:"user-level-statically-defined-tracing-usdt",level:3},{value:"Tracing with Linux Security Modules (LSM)",id:"tracing-with-linux-security-modules-lsm",level:3},{value:"Disabling Programs",id:"disabling-programs",level:2}];function l(e){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:"Inspektor Gadget automatically loads and attaches the eBPF programs contained in a gadget. This\ndocument describes the different types that are supported and specific details about them.\nThe section name specifies the type of the program and the target they should be attached to."}),"\n",(0,s.jsx)(t.h2,{id:"program-types",children:"Program Types"}),"\n",(0,s.jsx)(t.h3,{id:"kprobes--kretprobes",children:"Kprobes / Kretprobes"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must use the ",(0,s.jsx)(t.code,{children:"kprobe/<function_name>"})," or ",(0,s.jsx)(t.code,{children:"kretprobe/<function_name>"})," formats.\n",(0,s.jsx)(t.code,{children:"<function_name>"})," is the kernel function that the kprobe will be attached to."]}),"\n",(0,s.jsx)(t.h3,{id:"tracepoints",children:"Tracepoints"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must use the ",(0,s.jsx)(t.code,{children:"tracepoint/<tracepoint_name>"}),". ",(0,s.jsx)(t.code,{children:"<tracepoint_name>"})," is one of the\navailable tracepoints on ",(0,s.jsx)(t.code,{children:"/sys/kernel/debug/tracing/events"}),"."]}),"\n",(0,s.jsx)(t.h3,{id:"socket-filter",children:"Socket Filter"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must start with ",(0,s.jsx)(t.code,{children:"socket"}),". Socket programs are attached to all network namespaces\nmatching the filter configuration when running the gadget."]}),"\n",(0,s.jsx)(t.h3,{id:"sockops",children:"SockOps"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must be ",(0,s.jsx)(t.code,{children:"sockops"}),". Socket operation programs are attached once\nto the host's cgroup-v2 root and therefore apply to all sockets on the host."]}),"\n",(0,s.jsx)(t.h3,{id:"skskb--skmsg",children:"SkSKB / SkMsg"}),"\n",(0,s.jsxs)(t.p,{children:["Socket map programs use ",(0,s.jsx)(t.code,{children:"sk_skb/stream_parser"}),", ",(0,s.jsx)(t.code,{children:"sk_skb/stream_verdict"}),", or\n",(0,s.jsx)(t.code,{children:"sk_msg"})," section names. Each program must name the ",(0,s.jsx)(t.code,{children:"BPF_MAP_TYPE_SOCKMAP"})," or\n",(0,s.jsx)(t.code,{children:"BPF_MAP_TYPE_SOCKHASH"})," where it will be attached:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-c",children:'GADGET_SK_TARGET_MAP(parse, sockets);\nGADGET_SK_TARGET_MAP(verdict, sockets);\n\nSEC("sk_skb/stream_parser")\nint parse(struct __sk_buff *skb) { /* ... */ }\n\nSEC("sk_skb/stream_verdict")\nint verdict(struct __sk_buff *skb) { /* ... */ }\n'})}),"\n",(0,s.jsxs)(t.p,{children:["See ",(0,s.jsx)(t.a,{href:"/docs/v0.56.0/gadget-devel/gadget-ebpf-api#socket-map-programs",children:"Socket map programs"})," for the full\nmap declaration and attachment details."]}),"\n",(0,s.jsx)(t.h3,{id:"tracing",children:"Tracing"}),"\n",(0,s.jsx)(t.p,{children:"Currently we support some iterators and fentry/fexit programs."}),"\n",(0,s.jsx)(t.h4,{id:"iterators",children:"Iterators"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must use ",(0,s.jsx)(t.code,{children:"iter/<iter_type>"}),". ig supports the following ",(0,s.jsx)(t.code,{children:"<iter_type>"}),":"]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.code,{children:"ksym"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.code,{children:"task"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.code,{children:"task_file"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.code,{children:"tcp"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.code,{children:"udp"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.code,{children:"bpf_map_elem"})}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"tcp"})," and ",(0,s.jsx)(t.code,{children:"udp"})," iterators are invoked in different network namespaces matching\nthe filter configuration when running the gadget."]}
1),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"bpf_map_elem"})," iterators run over the entries of a BPF map (any map type) and\nare non-destructive \u2014 entries remain in the map after iteration. Because the\nkernel requires the target map's file descriptor at attach time, the iter\nprogram must be associated with its map via the ",(0,s.jsx)(t.code,{children:"GADGET_ITER_TARGET_MAP"}),"\nmacro. This is particularly useful when consuming maps pinned by an external\nproducer (e.g. a userspace daemon writing to a ",(0,s.jsx)(t.code,{children:"LIBBPF_PIN_BY_NAME"})," map):"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-c",children:'struct {\n\t__uint(type, BPF_MAP_TYPE_LRU_HASH);\n\t__uint(max_entries, 4096);\n\t__type(key, struct mykey);\n\t__type(value, struct myval);\n\t__uint(pinning, LIBBPF_PIN_BY_NAME);\n} my_map SEC(".maps");\n\nstruct my_event { /* ... */ };\n\nGADGET_ITER(my_iter, my_event, dump_my_map);\nGADGET_ITER_TARGET_MAP(dump_my_map, my_map);\n\nSEC("iter/bpf_map_elem")\nint dump_my_map(struct bpf_iter__bpf_map_elem *ctx)\n{\n\tstruct mykey *key = ctx->key;\n\tstruct myval *val = ctx->value;\n\tif (!key || !val)\n\t\treturn 0;\n\t/* ... build event ... */\n\tbpf_seq_write(ctx->meta->seq, &ev, sizeof(ev));\n\treturn 0;\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["This is the right primitive for any iter-style topper or snapshot gadget that\nneeds to read map contents without modifying them. For periodic\n",(0,s.jsx)(t.em,{children:"destructive"})," draining of a ",(0,s.jsx)(t.code,{children:"BPF_MAP_TYPE_HASH"})," (e.g. counters that should\nbe reset on every fetch), use ",(0,s.jsx)(t.code,{children:"GADGET_MAPITER"})," instead."]}),"\n",(0,s.jsx)(t.p,{children:"You can find the list of iterator types supported by Linux with:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"git grep -w ^DEFINE_BPF_ITER_FUNC"})," in the Linux sources (16 types as of Linux 6.9)"]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"sudo bpftool btf dump id 1 format c |grep 'struct bpf_iter__'"})," in the current kernel"]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"fentry--fexit",children:"Fentry / Fexit"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must use the ",(0,s.jsx)(t.code,{children:"fentry/<function_name>"})," or ",(0,s.jsx)(t.code,{children:"fexit/<function_name>"}),". As in kprobes,\n",(0,s.jsx)(t.code,{children:"<function_name>"})," is the kernel function that the program will be attached to."]}),"\n",(0,s.jsx)(t.h3,{id:"perfevents",children:"PerfEvents"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must be ",(0,s.jsx)(t.code,{children:"perf_event/<name>"}),", where ",(0,s.jsx)(t.code,{children:"<name>"})," is used to apply parameters to the\nprogram using the ",(0,s.jsx)(t.code,{children:"gadget.yaml"})," file."]}),"\n",(0,s.jsxs)(t.p,{children:["Currently, we only support the following settings (",(0,s.jsx)(t.code,{children:"<name>"})," is ",(0,s.jsx)(t.code,{children:"myPerfEvent"})," in this case):"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-yaml",children:"programs:\n myPerfEvent:\n perf:\n type: software\n config: count_sw_cpu_clock\n sampleType: s
1ample_raw\n sampler:\n frequency: 49\n"})}),"\n",(0,s.jsx)(t.p,{children:"All parameters are mandatory for now."}),"\n",(0,s.jsx)(t.h3,{id:"raw-tracepoints",children:"Raw Tracepoints"}),"\n",(0,s.jsx)(t.p,{children:"TODO!"}),"\n",(0,s.jsx)(t.h3,{id:"schedcls",children:"SchedCLS"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must use the ",(0,s.jsx)(t.code,{children:"classifier/<ingress|egress>/<program_name>"})," format. SchedCLS programs\nare attached to the peer of the networking interface of the containers on the host according to the\nfiltering configuration."]}),"\n",(0,s.jsxs)(t.p,{children:["Inspektor Gadget supports running multiple gadgets that use SchedCLS programs at the same time.\nPrograms must return ",(0,s.jsx)(t.code,{children:"TC_ACT_UNSPEC"})," in order to allow the packet to be processed by other gadgets.\nThe order of execution of the programs is not deterministic, this is something we could visit later\non."]}),"\n",(0,s.jsx)(t.h3,{id:"uprobes--uretprobes",children:"Uprobes / Uretprobes"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must use the ",(0,s.jsx)(t.code,{children:"<prog_type>/<file_path>:<symbol>"})," format.\n",(0,s.jsx)(t.code,{children:"<prog_type>"})," must be either ",(0,s.jsx)(t.code,{children:"uprobe"})," or ",(0,s.jsx)(t.code,{children:"uretprobe"}),".\n",(0,s.jsx)(t.code,{children:"<file_path>"})," is the absolute path of an executable or a library, that the uprobe will be attached to.\nFor common libraries, ",(0,s.jsx)(t.code,{children:"<file_path>"})," can also be the library's name, such as ",(0,s.jsx)(t.code,{children:"libc"}),".\n",(0,s.jsx)(t.code,{children:"<symbol>"})," is a debugging symbol that can be found in the file mentioned above."]}),"\n",(0,s.jsx)(t.h3,{id:"user-level-statically-defined-tracing-usdt",children:"User-Level Statically Defined Tracing (USDT)"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must use the ",(0,s.jsx)(t.code,{children:"usdt/<file_path>:<providerName>:<probeName>"})," format.\n",(0,s.jsx)(t.code,{children:"<file_path>"})," can be either an absolute path or a library name, same as the field in Uprobe.\n",(0,s.jsx)(t.code,{children:"<providerName>"})," and ",(0,s.jsx)(t.code,{children:"<probeName>"})," are two fields that can jointly identify a USDT trace point."]}),"\n",(0,s.jsx)(t.h3,{id:"tracing-with-linux-security-modules-lsm",children:"Tracing with Linux Security Modules (LSM)"}),"\n",(0,s.jsxs)(t.p,{children:["The section name must use the ",(0,s.jsx)(t.code,{children:"lsm/<hook>"})," format.\nThe hook points could be found in ",(0,s.jsx)(t.a,{href:"https://github.com/torvalds/linux/blob/master/include/linux/lsm_hook_defs.h",children:(0,s.jsx)(t.code,{children:"<include/linux/lsm_hook_defs.h>"})}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"disabling-programs",children:"Disabling Programs"}),"\n",(0,s.jsxs)(t.p,{children:["You can disable a program by using ",(0,s.jsx)(t.code,{children:"gadget_program_disabled"})," as the program\ntarget. For example:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-c",children:'SEC("kprobe/gadget_program_disabled")\nint BPF_KPROBE(foo, args...)\n{\n\treturn 0;\n}\n'})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},28453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>o});var r=n(96540);const s={},i=r.createContext(s);function a(e){const t=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(i.Provider,{value:t},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.