github.com/jayanthvn/pure-gobpf@v0.0.0-20230623131354-8d1d959d9e0b/README.md (about)

     1  # aws-ebpf-sdk-go
     2  
     3  This is a golang based SDK to load eBPF programs and maps. The SDK internally calls the bpf() system calls from unix package to load the programs and maps defined in the elf. The SDK supports attaching Kprobes, Tracepoint probes, traffic classifiers and XDP. Additionally supports perf event buffers for 5.4 kernels and ring buffer for 5.10 onwards kernel.
     4  
     5  Contributions welcome!
     6  
     7  # Getting started
     8  
     9  ## How to build elf file?
    10  
    11  ```
    12  clang -I../../.. -O2 -target bpf -c <C file> -o <ELF file>
    13  ```
    14  
    15  ## How to build SDK?
    16  
    17  Run `make buid-linux` - this will build the sdk binary.
    18  
    19  ## How to use the SDK?
    20  
    21  In your application, 
    22  
    23  1. Get the latest SDK -
    24  
    25  ```
    26  GOPROXY=direct go get github.com/aws/aws-ebpf-sdk-go
    27  ```
    28  
    29  2. Import the elfparser - 
    30  
    31  ```
    32  goebpfelfparser "github.com/aws/aws-ebpf-sdk-go/pkg/elfparser"
    33  ```
    34  
    35  3. Load the elf -
    36  
    37  ```
    38  goebpfelfparser.LoadBpfFile(<ELF file>)
    39  ```
    40  
    41  This return ELFContext which contains all programs under a section and all maps.
    42  
    43  ```
    44  type ELFContext struct {
    45  	// .elf will have multiple sections and maps
    46  	Section map[string]ELFSection // Indexed by section type
    47  	Maps    map[string]ELFMap     // Index by map name
    48  }
    49  
    50  type ELFSection struct {
    51  	// Each sections will have a program but a single section type can have multiple programs
    52  	// like tc_cls
    53  	Programs map[string]ELFProgram // Index by program name
    54  }
    55  
    56  type ELFProgram struct {
    57  	// return program name, prog FD and pinPath
    58  	ProgFD  int
    59  	PinPath string
    60  }
    61  
    62  type ELFMap struct {
    63  	// return map type, map FD and pinPath
    64  	MapType int
    65  	MapFD   int
    66  	PinPath string
    67  }
    68  ```
    69  
    70  ## How to attach XDP?
    71  
    72  1. Import the ebpf package - 
    73  
    74  ```
    75  goebpf "github.com/aws/aws-ebpf-sdk-go/pkg/ebpf"
    76  ```
    77  
    78  2. Attach XDP -
    79  
    80  Pass the interface name, program FD and program name.
    81  
    82  ```
    83  elfcontext, err := goebpfelfparser.LoadBpfFile(<ELF file>)
    84  
    85  Retrieve the progFD for the intended program from elfcontext -
    86  
    87  err = goebpf.XDPAttach(hostVethName, progFD)
    88  ```
    89  
    90  ## How to attach TC?
    91  
    92  1. Import the ebpf package - 
    93  
    94  ```
    95  goebpf "github.com/aws/aws-ebpf-sdk-go/pkg/ebpf"
    96  ```
    97  
    98  2. Attach TC - 
    99  
   100  ```
   101  elfcontext, err := goebpfelfparser.LoadBpfFile(<ELF file>)
   102  
   103  Retrieve the progFD for the intended program from elfcontext -
   104  
   105  err = goebpf.TCIngressAttach(hostVethName, progFD)
   106  ```
   107  
   108  ## Sample example
   109  
   110  ### Fetch program from ELFContext - 
   111  
   112  ```
   113  var elfContext *goebpfelfparser.ELFContext
   114  elfContext, err = goebpfelfparser.LoadBpfFile(<ELF file>)
   115  if err != nil {
   116     log.Errorf("LoadElf() failed: %v", err)
   117  }
   118  
   119  for pgmName, pgmData := range elfContext.Section["xdp"].Programs {
   120      log.Infof("xdp -> PgmName %s : ProgFD %d and PinPath %s", pgmName, pgmData.ProgFD, pgmData.PinPath)
   121  }
   122  
   123  for pgmName, pgmData := range elfContext.Section["tc_cls"].Programs {
   124      log.Infof("tc_cls -> PgmName %s : ProgFD %d and PinPath %s", pgmName, pgmData.ProgFD, pgmData.PinPath)
   125  }
   126  ```
   127  
   128  ### Map operations -
   129  
   130  ```
   131  var elfContext *goebpfelfparser.ELFContext
   132  elfContext, err = goebpfelfparser.LoadBpfFile(<ELF file>)
   133  if err != nil {
   134  	log.Errorf("LoadElf() failed: %v", err)
   135  }
   136  
   137  for pgmName, pgmData := range elfContext.Section["xdp"].Programs {
   138  	log.Infof("xdp -> PgmName %s : ProgFD %d and PinPath %s", pgmName, pgmData.ProgFD, pgmData.PinPath)
   139  }
   140  
   141  for pgmName, pgmData := range elfContext.Section["tc_cls"].Programs {
   142  	log.Infof("tc_cls -> PgmName %s : ProgFD %d and PinPath %s", pgmName, pgmData.ProgFD, pgmData.PinPath)
   143  }
   144  
   145  for k, v := range elfContext.Maps {
   146  	log.Infof("Found map %s with fd %d", k, v.MapFD)
   147  }
   148  
   149  //Insert into map
   150  type BPFInetTrieKey struct {
   151  	Prefixlen uint32
   152  	Addr [4]byte
   153  }
   154  dummykey := BPFInetTrieKey{
   155  	Prefixlen: 32,
   156  	Addr: [4]byte{192, 168, 0, 0},
   157  }
   158  dummyvalue := uint32(40)
   159  
   160  dummykey2 := BPFInetTrieKey{
   161  	Prefixlen: 32,
   162  	Addr: [4]byte{192, 168, 0, 1},
   163  }
   164  dummyvalue2 := uint32(30)
   165  
   166  if mapToUpdate, ok := elfContext.Maps["ingressmap"]; ok {
   167  	log.Infof("Found map to Create entry")
   168  	err = mapToUpdate.CreateMapEntry(uintptr(unsafe.Pointer((&dummykey))), uintptr(unsafe.Pointer((&dummyvalue))))
   169  	if err != nil {
   170  		log.Errorf("Unable to Insert into eBPF map: %v", err)
   171  	}
   172  	dummyvalue := uint32(20)
   173  
   174  	log.Infof("Found map to Update entry")
   175  	err = mapToUpdate.UpdateMapEntry(uintptr(unsafe.Pointer((&dummykey))), uintptr(unsafe.Pointer((&dummyvalue))))
   176  	if err != nil {
   177  		log.Errorf("Unable to Update into eBPF map: %v", err)
   178  	}
   179  
   180  	var mapVal uint32
   181  	log.Infof("Get map entry")
   182  	err := mapToUpdate.GetMapEntry(uintptr(unsafe.Pointer(&dummykey)), uintptr(unsafe.Pointer(&mapVal)))
   183  	if err != nil {
   184  		log.Errorf("Unable to get map entry: %v", err)
   185  	} else {
   186  		log.Infof("Found the map entry and value %d", mapVal)
   187  	}
   188  
   189  	log.Infof("Found map to Create dummy2 entry")
   190  	err = mapToUpdate.CreateMapEntry(uintptr(unsafe.Pointer((&dummykey2))), uintptr(unsafe.Pointer((&dummyvalue2))))
   191  	if err != nil {
   192  		log.Errorf("Unable to Insert into eBPF map: %v", err)
   193  	}
   194  
   195  	log.Infof("Try next key")
   196  	nextKey := BPFInetTrieKey{}
   197  	err = mapToUpdate.GetNextMapEntry(uintptr(unsafe.Pointer(&dummykey)), uintptr(unsafe.Pointer(&nextKey)))
   198  	if err != nil {
   199  		log.Errorf("Unable to get next key: %v", err)
   200  	} else {
   201  		log.Infof("Get map entry of next key")
   202  		var newMapVal uint32
   203  		err := mapToUpdate.GetMapEntry(uintptr(unsafe.Pointer(&nextKey)), uintptr(unsafe.Pointer(&newMapVal)))
   204  		if err != nil {
   205  			log.Errorf("Unable to get next map entry: %v", err)
   206  		} else {
   207  			log.Infof("Found the next map entry and value %d", newMapVal)
   208  		}
   209  	}
   210  
   211  	log.Infof("Found map to Delete entry")
   212  	err = mapToUpdate.DeleteMapEntry(uintptr(unsafe.Pointer((&dummykey))))
   213  	if err != nil {
   214  		log.Errorf("Unable to Delete in eBPF map: %v", err)
   215  	}
   216  }
   217  ```
   218  
   219  ### Map dump all -
   220  
   221  ```
   222  iterKey := BPFInetTrieKey{}
   223  iterNextKey := BPFInetTrieKey{}
   224  
   225  err = mapToUpdate.GetFirstMapEntry(uintptr(unsafe.Pointer(&iterKey)))
   226  if err != nil {
   227  	log.Errorf("Unable to get First key: %v", err)
   228  } else {
   229      for {
   230  		var newMapVal uint32
   231  		err = mapToUpdate.GetMapEntry(uintptr(unsafe.Pointer(&iterKey)), uintptr(unsafe.Pointer(&newMapVal)))
   232  		if err != nil {
   233  			log.Errorf("Unable to get map entry: %v", err)
   234  		} else {
   235  			log.Infof("Found the map entry and value %d", newMapVal)
   236  		}
   237  
   238  		err = mapToUpdate.GetNextMapEntry(uintptr(unsafe.Pointer(&iterKey)), uintptr(unsafe.Pointer(&iterNextKey)))
   239  		if err != nil {
   240  			log.Errorf("Done searching : %v", err)
   241  			break
   242  		}
   243  		iterKey = iterNextKey
   244  	}
   245  }
   246  ```