github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/cmd/examples/xdp_stats/main.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "embed" 6 "fmt" 7 "os" 8 "os/signal" 9 "time" 10 11 "github.com/dylandreimerink/gobpfld" 12 "github.com/dylandreimerink/gobpfld/bpftypes" 13 "golang.org/x/sys/unix" 14 15 _ "embed" 16 ) 17 18 //go:embed bpf/basic03_map_counter 19 var f embed.FS 20 21 // This example command is a pure go replacement for the userpace program of the Basic03 program from 22 // xdp-tutorial. https://github.com/xdp-project/xdp-tutorial/tree/master/basic03-map-counter 23 // This example has no options but does demonstrate program loading from ELF, attaching to a interface, and interacting with a map 24 25 func main() { 26 elfFileBytes, err := f.ReadFile("bpf/basic03_map_counter") 27 if err != nil { 28 fmt.Fprintf(os.Stderr, "error opening ELF file: %s\n", err.Error()) 29 os.Exit(1) 30 } 31 32 elf, err := gobpfld.LoadProgramFromELF(bytes.NewReader(elfFileBytes), gobpfld.ELFParseSettings{}) 33 if err != nil { 34 fmt.Fprintf(os.Stderr, "error while reading ELF file: %s\n", err.Error()) 35 os.Exit(1) 36 } 37 38 program := elf.Programs["xdp_stats1_func"].(*gobpfld.ProgramXDP) 39 40 // All maps loaded from elf files are BPFGenericMaps 41 statsMap := program.Maps["xdp_stats_map"].(*gobpfld.ArrayMap) 42 43 log, err := program.Load(gobpfld.ProgXDPLoadOpts{ 44 VerifierLogLevel: bpftypes.BPFLogLevelBasic, 45 }) 46 47 fmt.Printf("BPF Verifier log:\n%s\n", log) 48 49 if err != nil { 50 fmt.Fprintf(os.Stderr, "error while loading program: %s\n", err.Error()) 51 os.Exit(1) 52 } 53 54 sigChan := make(chan os.Signal, 1) 55 signal.Notify(sigChan, os.Interrupt, unix.SIGTERM, unix.SIGINT) 56 57 err = program.Attach(gobpfld.ProgXDPAttachOpts{ 58 InterfaceName: "lo", 59 Replace: true, 60 }) 61 62 if err != nil { 63 fmt.Fprintf(os.Stderr, "error while attaching program to loopback device: %s\n", err.Error()) 64 os.Exit(1) 65 } 66 67 detach := func() { 68 err = program.XDPLinkDetach(gobpfld.BPFProgramXDPLinkDetachSettings{ 69 All: true, 70 }) 71 if err != nil { 72 fmt.Fprintf(os.Stderr, "error while detaching program: %s\n", err.Error()) 73 os.Exit(1) 74 } 75 } 76 77 ticker := time.Tick(1 * time.Second) 78 for { 79 select { 80 case <-ticker: 81 // The key is 2 since the program puts stats in the XDP_PASS key which has value 2 82 // Tho this is specific to the XDP program we are using as an example. 83 var value int64 84 err = statsMap.Get(2, &value) 85 if err != nil { 86 fmt.Fprintf(os.Stderr, "error while getting stats from map: %s\n", err.Error()) 87 detach() 88 os.Exit(1) 89 } 90 91 fmt.Printf("%d packets were processed\n", value) 92 93 case <-sigChan: 94 fmt.Println("Detaching XPD program and stopping") 95 96 detach() 97 98 os.Exit(0) 99 } 100 } 101 }