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  }