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  }