github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/cmd/examples/map_in_map/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/bpfsys" 13 "github.com/dylandreimerink/gobpfld/bpftypes" 14 "golang.org/x/sys/unix" 15 16 _ "embed" 17 ) 18 19 //go:embed bpf/map_in_map_counter 20 var f embed.FS 21 22 func main() { 23 elfFileBytes, err := f.ReadFile("bpf/map_in_map_counter") 24 if err != nil { 25 fmt.Fprintf(os.Stderr, "error opening ELF file: %s\n", err.Error()) 26 os.Exit(1) 27 } 28 29 elf, err := gobpfld.LoadProgramFromELF(bytes.NewReader(elfFileBytes), gobpfld.ELFParseSettings{}) 30 if err != nil { 31 fmt.Fprintf(os.Stderr, "error while reading ELF file: %s\n", err.Error()) 32 os.Exit(1) 33 } 34 35 program := elf.Programs["xdp_stats1_func"].(*gobpfld.ProgramXDP) 36 37 innerDef := gobpfld.BPFMapDef{ 38 Type: bpftypes.BPF_MAP_TYPE_ARRAY, 39 KeySize: 4, 40 ValueSize: 8, 41 MaxEntries: 5, 42 Flags: bpftypes.BPFMapFlagsInnerMap, 43 } 44 45 firstStatsMap := &gobpfld.ArrayMap{ 46 AbstractMap: gobpfld.AbstractMap{ 47 Name: gobpfld.MustNewObjName("even_proto"), 48 Definition: innerDef, 49 }, 50 } 51 52 secondStatsMap := &gobpfld.ArrayMap{ 53 AbstractMap: gobpfld.AbstractMap{ 54 Name: gobpfld.MustNewObjName("uneven_proto"), 55 Definition: innerDef, 56 }, 57 } 58 59 mapInMap := program.Maps["map_of_maps"].(*gobpfld.ArrayOfMapsMap) 60 61 // We need to set the inner map definition, All 62 mapInMap.InnerMapDef = innerDef 63 64 // Load the program, this will also load the maps 65 log, err := program.Load(gobpfld.ProgXDPLoadOpts{ 66 VerifierLogLevel: bpftypes.BPFLogLevelBasic, 67 }) 68 69 fmt.Printf("BPF Verifier log:\n%s\n", log) 70 71 if err != nil { 72 fmt.Fprintf(os.Stderr, "error while loading program: %s\n", err.Error()) 73 os.Exit(1) 74 } 75 76 err = firstStatsMap.Load() 77 if err != nil { 78 fmt.Fprintf(os.Stderr, "error while loading even stats map: %s\n", err.Error()) 79 os.Exit(1) 80 } 81 82 err = mapInMap.Set(0, firstStatsMap, bpfsys.BPFMapElemAny) 83 if err != nil { 84 fmt.Fprintf(os.Stderr, "error while setting value map in map: %s\n", err.Error()) 85 os.Exit(1) 86 } 87 88 err = secondStatsMap.Load() 89 if err != nil { 90 fmt.Fprintf(os.Stderr, "error while loading uneven stats map: %s\n", err.Error()) 91 os.Exit(1) 92 } 93 94 err = mapInMap.Set(1, secondStatsMap, bpfsys.BPFMapElemAny) 95 if err != nil { 96 fmt.Fprintf(os.Stderr, "error while setting value map in map: %s\n", err.Error()) 97 os.Exit(1) 98 } 99 100 sigChan := make(chan os.Signal, 1) 101 signal.Notify(sigChan, os.Interrupt, unix.SIGTERM, unix.SIGINT) 102 103 err = program.Attach(gobpfld.ProgXDPAttachOpts{ 104 InterfaceName: "lo", 105 Replace: true, 106 }) 107 108 if err != nil { 109 fmt.Fprintf(os.Stderr, "error while attaching program to loopback device: %s\n", err.Error()) 110 os.Exit(1) 111 } 112 113 detach := func() { 114 err = program.XDPLinkDetach(gobpfld.BPFProgramXDPLinkDetachSettings{ 115 All: true, 116 }) 117 if err != nil { 118 fmt.Fprintf(os.Stderr, "error while detaching program: %s\n", err.Error()) 119 os.Exit(1) 120 } 121 } 122 123 ticker := time.Tick(1 * time.Second) 124 for { 125 select { 126 case <-ticker: 127 // The key is 2 since the program puts stats in the XDP_PASS key which has value 2 128 // Tho this is specific to the XDP program we are using as an example. 129 var value int64 130 err = firstStatsMap.Get(2, &value) 131 if err != nil { 132 fmt.Fprintf(os.Stderr, "error while getting stats from first map: %s\n", err.Error()) 133 detach() 134 os.Exit(1) 135 } 136 137 fmt.Printf("first map has %d packets were processed\n", value) 138 139 err = secondStatsMap.Get(2, &value) 140 if err != nil { 141 fmt.Fprintf(os.Stderr, "error while getting stats from second map: %s\n", err.Error()) 142 detach() 143 os.Exit(1) 144 } 145 146 fmt.Printf("second map has %d packets were processed\n", value) 147 148 fmt.Println("Swapping maps") 149 150 zeroMap, err := mapInMap.Get(0) 151 if err != nil { 152 fmt.Fprintf(os.Stderr, "error while getting map at index 0: %s\n", err.Error()) 153 detach() 154 os.Exit(1) 155 } 156 157 fmt.Println("Index 0 fd: ", zeroMap.GetFD()) 158 159 oneMap, err := mapInMap.Get(1) 160 if err != nil { 161 fmt.Fprintf(os.Stderr, "error while getting map at index 1: %s\n", err.Error()) 162 detach() 163 os.Exit(1) 164 } 165 166 fmt.Println("Index 1 fd: ", oneMap.GetFD()) 167 168 err = mapInMap.Set(0, oneMap, bpfsys.BPFMapElemAny) 169 if err != nil { 170 fmt.Fprintf(os.Stderr, "error while setting map at index 0: %s\n", err.Error()) 171 detach() 172 os.Exit(1) 173 } 174 175 err = mapInMap.Set(1, zeroMap, bpfsys.BPFMapElemAny) 176 if err != nil { 177 fmt.Fprintf(os.Stderr, "error while setting map at index 1: %s\n", err.Error()) 178 detach() 179 os.Exit(1) 180 } 181 182 case <-sigChan: 183 fmt.Println("Detaching XPD program and stopping") 184 185 detach() 186 187 os.Exit(0) 188 } 189 } 190 }