LCOV - code coverage report
Current view: top level - waltz/ebpf - fd_ebpf.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 3 40 7.5 %
Date: 2024-11-13 11:58:15 Functions: 1 30 3.3 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_ballet_ebpf_fd_ebpf_h
       2             : #define HEADER_fd_src_ballet_ebpf_fd_ebpf_h
       3             : 
       4             : /* fd_ebpf.h provides APIs for loading Linux eBPF programs.  Currently,
       5             :    only XDP programs are supported.
       6             : 
       7             :    The scope of this API is *trusted*:  It is assumed that only hardcoded
       8             :    eBPF programs and symbols are provided.
       9             : 
      10             :    ### What are eBPF programs?
      11             : 
      12             :    Linux eBPF programs are pieces of bytecode that userland programs can
      13             :    deploy into the kernel virtual machine.  The kernel can interact with
      14             :    these programs with very low overhead, which makes them particularly
      15             :    useful for fast packet filtering.
      16             : 
      17             :    Userland applications can deploy and interact with eBPF programs via
      18             :    the bpf(2) syscall.  When deploying, the user provides a bytecode blob
      19             :    (see fd_ebpf_base.h) which is produced by the userland on the fly.
      20             :    Typically, userland also shares file descriptors while deploying the
      21             :    program.
      22             : 
      23             :    To avoid hardcoding file descriptor numbers into the eBPF programs, eBPF
      24             :    programs are typically stored as ELF static objects.  These are
      25             :    "relocated" just-in-time to actual bytecode.  (The term relocation in
      26             :    this context has not much to do with offsets.  It refers to filling in
      27             :    symbolic names (such as "xsk_fileno") with an actual value (like 3)).
      28             : 
      29             :    This relocation step is provided by fd_ebpf_static_link.  Various
      30             :    wrappers for bpf(2) operations are also provided. */
      31             : 
      32             : #include "../../util/fd_util_base.h"
      33             : 
      34             : /* fd_ebpf_sym_t a key-value pair.  name matches the name of an imported
      35             :    symbol in the ELF object.  value is the 'absolute address' to fill in.
      36             :    (The 'absolute address' is abused as a generic 64-bit value and can
      37             :    also refer to file descriptors, config parameters, etc.) */
      38             : 
      39             : struct fd_ebpf_sym {
      40             :   char const * name;   /* null-terminated cstr */
      41             :   ulong        value;  /* arbitrary 64-bit value */
      42             : };
      43             : typedef struct fd_ebpf_sym fd_ebpf_sym_t;
      44             : 
      45             : /* fd_ebpf_link_opts_t describe parameters to load an eBPF ELF object into
      46             :    a bytecode blob that can be loaded into a kernel.  section is the name
      47             :    of the ELF section carrying the bytecode (not necessarily ".text"),
      48             :    and sym is an array of sym_cnt symbols containing values to fill in.
      49             :    fd_ebpf_static_link will look for a relocation table for this section,
      50             :    which identifies where and how to fill in symbol values in the given
      51             :    section. */
      52             : 
      53             : struct fd_ebpf_link_opts {
      54             :   /* In params */
      55             : 
      56             :   char const *          section;
      57             :   fd_ebpf_sym_t const * sym;
      58             :   ulong                 sym_cnt;
      59             : 
      60             :   /* Out params */
      61             : 
      62             :   ulong * bpf;
      63             :   ulong   bpf_sz;
      64             : };
      65             : typedef struct fd_ebpf_link_opts fd_ebpf_link_opts_t;
      66             : 
      67             : /* fd_ebpf_static_link relocates an eBPF ELF object as mentioned above.
      68             :    elf points to a memory region of elf_sz bytes containing the ELF static
      69             :    object.  This memory region will be clobbered during the relocation
      70             :    process.  Returns opts on success, with bpf pointing to the first eBPF
      71             :    instruction (a subrange of the memory region at elf).  bpf_sz is the
      72             :    size of the eBPF bytecode blob (multiple of 8).  On failure, returns
      73             :    NULL.
      74             : 
      75             :    ### Caveats
      76             : 
      77             :    The static linking process is fairly slow and quite complex.  This
      78             :    function only implements a small subset of the linking logic needed to
      79             :    load simple programs.  Users of this function should expect bugs and
      80             :    therefore independently test whether their programs load.  See
      81             :    test_xdp_ebpf on how to do unit testing of the relocated program with
      82             :    the bpf(2) syscall. */
      83             : 
      84             : fd_ebpf_link_opts_t *
      85             : fd_ebpf_static_link( fd_ebpf_link_opts_t * opts,
      86             :                      void *                elf,
      87             :                      ulong                 elf_sz );
      88             : 
      89             : /* bpf syscall wrappers **************************************************/
      90             : 
      91             : #if defined(__linux__) && defined(_DEFAULT_SOURCE) || defined(_BSD_SOURCE)
      92             : 
      93             : #include <sys/syscall.h>
      94             : #include <unistd.h>
      95             : #include <linux/bpf.h>
      96             : 
      97             : /* bpf Linux syscall */
      98             : 
      99             : static inline long
     100             : bpf( int              cmd,
     101             :      union bpf_attr * attr,
     102           3 :      ulong            attr_sz ) {
     103           3 :   return syscall( SYS_bpf, cmd, attr, attr_sz );
     104           3 : }
     105             : 
     106             : /* fd_bpf_map_get_next_key wraps bpf(2) op BPF_MAP_GET_NEXT_KEY.
     107             : 
     108             :    Given a BPF map file descriptor and a const ptr to the current key,
     109             :    finds and stores the next key into `next_key`.  key and next_key must
     110             :    match the key size of the map object.  If key does not exist, yields
     111             :    the first key of the map.  When mutating a map while iterating, get
     112             :    the next key before deleting the current key to avoid iterator from
     113             :    restarting.  Returns 0 on success and -1 on failure (sets errno).
     114             :    Sets errno to ENOENT if given key is last in map. */
     115             : 
     116             : static inline int
     117             : fd_bpf_map_get_next_key( int          map_fd,
     118             :                          void const * key,
     119           0 :                          void       * next_key ) {
     120           0 :   union bpf_attr attr = {
     121           0 :     .map_fd   = (uint)map_fd,
     122           0 :     .key      = (ulong)key,
     123           0 :     .next_key = (ulong)next_key
     124           0 :   };
     125           0 :   return (int)bpf( BPF_MAP_GET_NEXT_KEY, &attr, sizeof(union bpf_attr) );
     126           0 : }
     127             : 
     128             : /* fd_bpf_map_update_elem wraps bpf(2) op BPF_MAP_UPDATE_ELEM.
     129             : 
     130             :    Creates or updates an entry in a BPF map.  key and value point to
     131             :    the tuple to be inserted and must match the key/value size of the map
     132             :    object.  flags is one of BPF_ANY (create or update), BPF_NOEXIST
     133             :    (create only), BPF_EXIST (update only).  Returns 0 on success and -1
     134             :    on failure (sets errno).  Reasons for failure include: E2BIG (max
     135             :    entry limit reached), EEXIST (BPF_NOEXIST requested but key exists),
     136             :    ENOENT (BPF_EXIST requested but key not found). */
     137             : 
     138             : static inline int
     139             : fd_bpf_map_update_elem( int          map_fd,
     140             :                         void const * key,
     141             :                         void const * value,
     142           0 :                         ulong        flags ) {
     143           0 :   union bpf_attr attr = {
     144           0 :     .map_fd   = (uint)map_fd,
     145           0 :     .key      = (ulong)key,
     146           0 :     .value    = (ulong)value,
     147           0 :     .flags    = flags
     148           0 :   };
     149           0 :   return (int)bpf( BPF_MAP_UPDATE_ELEM, &attr, sizeof(union bpf_attr) );
     150           0 : }
     151             : 
     152             : /* fd_bpf_map_delete_elem wraps bpf(2) op BPF_MAP_DELETE_ELEM.
     153             : 
     154             :    Deletes an entry in a BPF map.  key points to the key to be deleted
     155             :    and must match the key size of the map object.  Returns 0 on success
     156             :    and -1 on failure (sets errno).  Reasons for failure include: ENOENT
     157             :    (no such key). */
     158             : 
     159             : static inline int
     160             : fd_bpf_map_delete_elem( int          map_fd,
     161           0 :                         void const * key ) {
     162           0 :   union bpf_attr attr = {
     163           0 :     .map_fd   = (uint)map_fd,
     164           0 :     .key      = (ulong)key
     165           0 :   };
     166           0 :   return (int)bpf( BPF_MAP_DELETE_ELEM, &attr, sizeof(union bpf_attr) );
     167           0 : }
     168             : 
     169             : /* fd_bpf_obj_get wraps bpf(2) op BPF_OBJ_GET.
     170             : 
     171             :    Opens a BPF map at given filesystem path.  Path must be within a
     172             :    valid bpffs mount and point to a BPF map pinned via BPF_OBJ_PIN.
     173             :    Returns fd number on success and negative integer on failure. */
     174             : 
     175             : static inline int
     176           0 : fd_bpf_obj_get( char const * pathname ) {
     177           0 :   union bpf_attr attr = {
     178           0 :     .pathname = (ulong)pathname
     179           0 :   };
     180           0 :   return (int)bpf( BPF_OBJ_GET, &attr, sizeof(union bpf_attr) );
     181           0 : }
     182             : 
     183             : /* fd_bpf_obj_pin wraps bpf(2) op BPF_OBJ_PIN.
     184             : 
     185             :    Pins a bpf syscall API object at given filesystem path.  Types of
     186             :    objects include: BPF map (BPF_MAP_CREATE), links (BPF_LINK_CREATE),
     187             :    programs (BPF_PROG_LOAD).  Returns 0 on success and -1 on failure. */
     188             : 
     189             : static inline int
     190             : fd_bpf_obj_pin( int          bpf_fd,
     191           0 :                 char const * pathname ) {
     192           0 :   union bpf_attr attr = {
     193           0 :     .bpf_fd   = (uint)bpf_fd,
     194           0 :     .pathname = (ulong)pathname
     195           0 :   };
     196           0 :   return (int)bpf( BPF_OBJ_PIN, &attr, sizeof(union bpf_attr) );
     197           0 : }
     198             : 
     199             : #endif /* defined (__linux__) */
     200             : 
     201             : #endif /* HEADER_fd_src_ballet_ebpf_fd_ebpf_h */

Generated by: LCOV version 1.14