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