ebpf

package module
v0.17.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 18, 2024 License: MIT Imports: 33 Imported by: 856

README

eBPF

PkgGoDev

HoneyGopher

ebpf-go is a pure Go library that provides utilities for loading, compiling, and debugging eBPF programs. It has minimal external dependencies and is intended to be used in long running processes.

See ebpf.io for complementary projects from the wider eBPF ecosystem.

Getting Started

Please take a look at our Getting Started guide.

Contributions are highly encouraged, as they highlight certain use cases of eBPF and the library, and help shape the future of the project.

Getting Help

The community actively monitors our GitHub Discussions page. Please search for existing threads before starting a new one. Refrain from opening issues on the bug tracker if you're just starting out or if you're not sure if something is a bug in the library code.

Alternatively, join the #ebpf-go channel on Slack if you have other questions regarding the project. Note that this channel is ephemeral and has its history erased past a certain point, which is less helpful for others running into the same problem later.

Packages

This library includes the following packages:

  • asm contains a basic assembler, allowing you to write eBPF assembly instructions directly within your Go code. (You don't need to use this if you prefer to write your eBPF program in C.)
  • cmd/bpf2go allows compiling and embedding eBPF programs written in C within Go code. As well as compiling the C code, it auto-generates Go code for loading and manipulating the eBPF program and map objects.
  • link allows attaching eBPF to various hooks
  • perf allows reading from a PERF_EVENT_ARRAY
  • ringbuf allows reading from a BPF_MAP_TYPE_RINGBUF map
  • features implements the equivalent of bpftool feature probe for discovering BPF-related kernel features using native Go.
  • rlimit provides a convenient API to lift the RLIMIT_MEMLOCK constraint on kernels before 5.11.
  • btf allows reading the BPF Type Format.
  • pin provides APIs for working with pinned objects on bpffs.

Requirements

  • A version of Go that is supported by upstream
  • CI is run against kernel.org LTS releases. >= 4.4 should work but EOL'ed versions are not supported.

License

MIT

eBPF Gopher

The eBPF honeygopher is based on the Go gopher designed by Renee French.

Documentation

Overview

Package ebpf is a toolkit for working with eBPF programs.

eBPF programs are small snippets of code which are executed directly in a VM in the Linux kernel, which makes them very fast and flexible. Many Linux subsystems now accept eBPF programs. This makes it possible to implement highly application specific logic inside the kernel, without having to modify the actual kernel itself.

This package is designed for long-running processes which want to use eBPF to implement part of their application logic. It has no run-time dependencies outside of the library and the Linux kernel itself. eBPF code should be compiled ahead of time using clang, and shipped with your application as any other resource.

Use the link subpackage to attach a loaded program to a hook in the kernel.

Note that losing all references to Map and Program resources will cause their underlying file descriptors to be closed, potentially removing those objects from the kernel. Always retain a reference by e.g. deferring a Close() of a Collection or LoadAndAssign object until application exit.

Special care needs to be taken when handling maps of type ProgramArray, as the kernel erases its contents when the last userspace or bpffs reference disappears, regardless of the map being in active use.

Example (CustomMarshaler)

ExampleMarshaler shows how to use custom encoding with map methods.

package main

import (
	"encoding"
	"fmt"
	"strings"
)

// Assert that customEncoding implements the correct interfaces.
var (
	_ encoding.BinaryMarshaler   = (*customEncoding)(nil)
	_ encoding.BinaryUnmarshaler = (*customEncoding)(nil)
)

type customEncoding struct {
	data string
}

func (ce *customEncoding) MarshalBinary() ([]byte, error) {
	return []byte(strings.ToUpper(ce.data)), nil
}

func (ce *customEncoding) UnmarshalBinary(buf []byte) error {
	ce.data = string(buf)
	return nil
}

// ExampleMarshaler shows how to use custom encoding with map methods.
func main() {
	hash, err := NewMap(&MapSpec{
		Type:       Hash,
		KeySize:    5,
		ValueSize:  4,
		MaxEntries: 10,
	})
	if err != nil {
		panic(err)
	}
	defer hash.Close()

	if err := hash.Put(&customEncoding{"hello"}, uint32(111)); err != nil {
		panic(err)
	}

	var (
		key     customEncoding
		value   uint32
		entries = hash.Iterate()
	)

	for entries.Next(&key, &value) {
		fmt.Printf("key: %s, value: %d\n", key.data, value)
	}

	if err := entries.Err(); err != nil {
		panic(err)
	}

}
Output:

key: HELLO, value: 111
Example (ExtractDistance)

ExampleExtractDistance shows how to attach an eBPF socket filter to extract the network distance of an IP host.

//go:build linux

package main

// This code is derived from https://github.com/cloudflare/cloudflare-blog/tree/master/2018-03-ebpf
//
// Copyright (c) 2015-2017 Cloudflare, Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of the Cloudflare, Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import (
	"fmt"
	"net"
	"syscall"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/asm"
)

// ExampleExtractDistance shows how to attach an eBPF socket filter to
// extract the network distance of an IP host.
func main() {
	filter, TTLs, err := newDistanceFilter()
	if err != nil {
		panic(err)
	}
	defer filter.Close()
	defer TTLs.Close()

	// Attach filter before the call to connect()
	dialer := net.Dialer{
		Control: func(network, address string, c syscall.RawConn) (err error) {
			const SO_ATTACH_BPF = 50

			err = c.Control(func(fd uintptr) {
				err = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, SO_ATTACH_BPF, filter.FD())
			})
			return err
		},
	}

	conn, err := dialer.Dial("tcp", "1.1.1.1:53")
	if err != nil {
		panic(err)
	}
	conn.Close()

	minDist, err := minDistance(TTLs)
	if err != nil {
		panic(err)
	}

	fmt.Println("1.1.1.1:53 is", minDist, "hops away")
}

func newDistanceFilter() (*ebpf.Program, *ebpf.Map, error) {
	const ETH_P_IPV6 uint16 = 0x86DD

	ttls, err := ebpf.NewMap(&ebpf.MapSpec{
		Type:       ebpf.Hash,
		KeySize:    4,
		ValueSize:  8,
		MaxEntries: 4,
	})
	if err != nil {
		return nil, nil, err
	}

	insns := asm.Instructions{
		// r1 has ctx
		// r0 = ctx[16] (aka protocol)
		asm.LoadMem(asm.R0, asm.R1, 16, asm.Word),

		// Perhaps ipv6
		asm.LoadImm(asm.R2, int64(ETH_P_IPV6), asm.DWord),
		asm.HostTo(asm.BE, asm.R2, asm.Half),
		asm.JEq.Reg(asm.R0, asm.R2, "ipv6"),

		// otherwise assume ipv4
		// 8th byte in IPv4 is TTL
		// LDABS requires ctx in R6
		asm.Mov.Reg(asm.R6, asm.R1),
		asm.LoadAbs(-0x100000+8, asm.Byte),
		asm.Ja.Label("store-ttl"),

		// 7th byte in IPv6 is Hop count
		// LDABS requires ctx in R6
		asm.Mov.Reg(asm.R6, asm.R1).WithSymbol("ipv6"),
		asm.LoadAbs(-0x100000+7, asm.Byte),

		// stash the load result into FP[-4]
		asm.StoreMem(asm.RFP, -4, asm.R0, asm.Word).WithSymbol("store-ttl"),
		// stash the &FP[-4] into r2
		asm.Mov.Reg(asm.R2, asm.RFP),
		asm.Add.Imm(asm.R2, -4),

		// r1 must point to map
		asm.LoadMapPtr(asm.R1, ttls.FD()),
		asm.FnMapLookupElem.Call(),

		// load ok? inc. Otherwise? jmp to mapupdate
		asm.JEq.Imm(asm.R0, 0, "update-map"),
		asm.Mov.Imm(asm.R1, 1),
		asm.StoreXAdd(asm.R0, asm.R1, asm.DWord),
		asm.Ja.Label("exit"),

		// MapUpdate
		// r1 has map ptr
		asm.LoadMapPtr(asm.R1, ttls.FD()).WithSymbol("update-map"),
		// r2 has key -> &FP[-4]
		asm.Mov.Reg(asm.R2, asm.RFP),
		asm.Add.Imm(asm.R2, -4),
		// r3 has value -> &FP[-16] , aka 1
		asm.StoreImm(asm.RFP, -16, 1, asm.DWord),
		asm.Mov.Reg(asm.R3, asm.RFP),
		asm.Add.Imm(asm.R3, -16),
		// r4 has flags, 0
		asm.Mov.Imm(asm.R4, 0),
		asm.FnMapUpdateElem.Call(),

		// set exit code to -1, don't trunc packet
		asm.Mov.Imm(asm.R0, -1).WithSymbol("exit"),
		asm.Return(),
	}

	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
		Name:         "distance_filter",
		Type:         ebpf.SocketFilter,
		License:      "GPL",
		Instructions: insns,
	})
	if err != nil {
		ttls.Close()
		return nil, nil, err
	}

	return prog, ttls, nil
}

func minDistance(TTLs *ebpf.Map) (int, error) {
	var (
		entries = TTLs.Iterate()
		ttl     uint32
		minDist uint32 = 255
		count   uint64
	)
	for entries.Next(&ttl, &count) {
		var dist uint32
		switch {
		case ttl > 128:
			dist = 255 - ttl
		case ttl > 64:
			dist = 128 - ttl
		case ttl > 32:
			dist = 64 - ttl
		default:
			dist = 32 - ttl
		}
		if minDist > dist {
			minDist = dist
		}
	}
	return int(minDist), entries.Err()
}
Output:

Example (SocketELF)

ExampleSocketELF demonstrates how to load an eBPF program from an ELF, and attach it to a raw socket.

//go:build linux

package main

import (
	"bytes"
	"encoding/binary"
	"flag"
	"fmt"
	"syscall"
	"time"
	"unsafe"

	"github.com/cilium/ebpf"
)

var program = [...]byte{
	0177, 0105, 0114, 0106, 0002, 0001, 0001, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0001, 0000, 0367, 0000, 0001, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0340, 0001, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0100, 0000, 0000, 0000, 0000, 0000, 0100, 0000, 0010, 0000, 0001, 0000,
	0277, 0026, 0000, 0000, 0000, 0000, 0000, 0000, 0060, 0000, 0000, 0000, 0027, 0000, 0000, 0000,
	0143, 0012, 0374, 0377, 0000, 0000, 0000, 0000, 0141, 0141, 0004, 0000, 0000, 0000, 0000, 0000,
	0125, 0001, 0010, 0000, 0004, 0000, 0000, 0000, 0277, 0242, 0000, 0000, 0000, 0000, 0000, 0000,
	0007, 0002, 0000, 0000, 0374, 0377, 0377, 0377, 0030, 0001, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0205, 0000, 0000, 0000, 0001, 0000, 0000, 0000,
	0025, 0000, 0002, 0000, 0000, 0000, 0000, 0000, 0141, 0141, 0000, 0000, 0000, 0000, 0000, 0000,
	0333, 0020, 0000, 0000, 0000, 0000, 0000, 0000, 0267, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0225, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0002, 0000, 0000, 0000, 0004, 0000, 0000, 0000,
	0010, 0000, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0000, 0000, 0000, 0002, 0000, 0000, 0000,
	0004, 0000, 0000, 0000, 0010, 0000, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0000, 0000, 0000,
	0107, 0120, 0114, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0065, 0000, 0000, 0000, 0000, 0000, 0003, 0000, 0150, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0034, 0000, 0000, 0000, 0020, 0000, 0006, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0110, 0000, 0000, 0000, 0020, 0000, 0003, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0014, 0000, 0000, 0000, 0020, 0000, 0005, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0023, 0000, 0000, 0000, 0020, 0000, 0005, 0000, 0024, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0070, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0001, 0000, 0000, 0000, 0004, 0000, 0000, 0000, 0000, 0056, 0164, 0145, 0170, 0164, 0000, 0155,
	0141, 0160, 0163, 0000, 0155, 0171, 0137, 0155, 0141, 0160, 0000, 0164, 0145, 0163, 0164, 0137,
	0155, 0141, 0160, 0000, 0137, 0154, 0151, 0143, 0145, 0156, 0163, 0145, 0000, 0056, 0163, 0164,
	0162, 0164, 0141, 0142, 0000, 0056, 0163, 0171, 0155, 0164, 0141, 0142, 0000, 0114, 0102, 0102,
	0060, 0137, 0063, 0000, 0056, 0162, 0145, 0154, 0163, 0157, 0143, 0153, 0145, 0164, 0061, 0000,
	0142, 0160, 0146, 0137, 0160, 0162, 0157, 0147, 0061, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0045, 0000, 0000, 0000, 0003, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0210, 0001, 0000, 0000, 0000, 0000, 0000, 0000,
	0122, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0001, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0001, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0006, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0100, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0004, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0100, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0006, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0100, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0170, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0010, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0074, 0000, 0000, 0000, 0011, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0170, 0001, 0000, 0000, 0000, 0000, 0000, 0000,
	0020, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0007, 0000, 0000, 0000, 0003, 0000, 0000, 0000,
	0010, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0020, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0007, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0003, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0270, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0050, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0004, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0035, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0003, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0340, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0004, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0001, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0055, 0000, 0000, 0000, 0002, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0350, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
	0220, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0001, 0000, 0000, 0000, 0002, 0000, 0000, 0000,
	0010, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0030, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
}

// ExampleSocketELF demonstrates how to load an eBPF program from an ELF,
// and attach it to a raw socket.
func main() {
	const SO_ATTACH_BPF = 50

	index := flag.Int("index", 0, "specify ethernet index")
	flag.Parse()

	spec, err := ebpf.LoadCollectionSpecFromReader(bytes.NewReader(program[:]))
	if err != nil {
		panic(err)
	}

	var objs struct {
		Prog  *ebpf.Program `ebpf:"bpf_prog1"`
		Stats *ebpf.Map     `ebpf:"my_map"`
	}

	if err := spec.LoadAndAssign(&objs, nil); err != nil {
		panic(err)
	}
	defer objs.Prog.Close()
	defer objs.Stats.Close()

	sock, err := openRawSock(*index)
	if err != nil {
		panic(err)
	}
	defer syscall.Close(sock)

	if err := syscall.SetsockoptInt(sock, syscall.SOL_SOCKET, SO_ATTACH_BPF, objs.Prog.FD()); err != nil {
		panic(err)
	}

	fmt.Printf("Filtering on eth index: %d\n", *index)
	fmt.Println("Packet stats:")

	for {
		const (
			ICMP = 0x01
			TCP  = 0x06
			UDP  = 0x11
		)

		time.Sleep(time.Second)
		var icmp uint64
		var tcp uint64
		var udp uint64
		err := objs.Stats.Lookup(uint32(ICMP), &icmp)
		if err != nil {
			panic(err)
		}
		err = objs.Stats.Lookup(uint32(TCP), &tcp)
		if err != nil {
			panic(err)
		}
		err = objs.Stats.Lookup(uint32(UDP), &udp)
		if err != nil {
			panic(err)
		}
		fmt.Printf("\r\033[m\tICMP: %d TCP: %d UDP: %d", icmp, tcp, udp)
	}
}

func openRawSock(index int) (int, error) {
	sock, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, int(htons(syscall.ETH_P_ALL)))
	if err != nil {
		return 0, err
	}
	sll := syscall.SockaddrLinklayer{
		Ifindex:  index,
		Protocol: htons(syscall.ETH_P_ALL),
	}
	if err := syscall.Bind(sock, &sll); err != nil {
		return 0, err
	}
	return sock, nil
}

// htons converts the unsigned short integer hostshort from host byte order to network byte order.
func htons(i uint16) uint16 {
	b := make([]byte, 2)
	binary.BigEndian.PutUint16(b, i)
	return *(*uint16)(unsafe.Pointer(&b[0]))
}
Output:

Index

Examples

Constants

View Source
const (
	UnspecifiedProgram    = ProgramType(sys.BPF_PROG_TYPE_UNSPEC)
	SocketFilter          = ProgramType(sys.BPF_PROG_TYPE_SOCKET_FILTER)
	Kprobe                = ProgramType(sys.BPF_PROG_TYPE_KPROBE)
	SchedCLS              = ProgramType(sys.BPF_PROG_TYPE_SCHED_CLS)
	SchedACT              = ProgramType(sys.BPF_PROG_TYPE_SCHED_ACT)
	TracePoint            = ProgramType(sys.BPF_PROG_TYPE_TRACEPOINT)
	XDP                   = ProgramType(sys.BPF_PROG_TYPE_XDP)
	PerfEvent             = ProgramType(sys.BPF_PROG_TYPE_PERF_EVENT)
	CGroupSKB             = ProgramType(sys.BPF_PROG_TYPE_CGROUP_SKB)
	CGroupSock            = ProgramType(sys.BPF_PROG_TYPE_CGROUP_SOCK)
	LWTIn                 = ProgramType(sys.BPF_PROG_TYPE_LWT_IN)
	LWTOut                = ProgramType(sys.BPF_PROG_TYPE_LWT_OUT)
	LWTXmit               = ProgramType(sys.BPF_PROG_TYPE_LWT_XMIT)
	SockOps               = ProgramType(sys.BPF_PROG_TYPE_SOCK_OPS)
	SkSKB                 = ProgramType(sys.BPF_PROG_TYPE_SK_SKB)
	CGroupDevice          = ProgramType(sys.BPF_PROG_TYPE_CGROUP_DEVICE)
	SkMsg                 = ProgramType(sys.BPF_PROG_TYPE_SK_MSG)
	RawTracepoint         = ProgramType(sys.BPF_PROG_TYPE_RAW_TRACEPOINT)
	CGroupSockAddr        = ProgramType(sys.BPF_PROG_TYPE_CGROUP_SOCK_ADDR)
	LWTSeg6Local          = ProgramType(sys.BPF_PROG_TYPE_LWT_SEG6LOCAL)
	LircMode2             = ProgramType(sys.BPF_PROG_TYPE_LIRC_MODE2)
	SkReuseport           = ProgramType(sys.BPF_PROG_TYPE_SK_REUSEPORT)
	FlowDissector         = ProgramType(sys.BPF_PROG_TYPE_FLOW_DISSECTOR)
	CGroupSysctl          = ProgramType(sys.BPF_PROG_TYPE_CGROUP_SYSCTL)
	RawTracepointWritable = ProgramType(sys.BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE)
	CGroupSockopt         = ProgramType(sys.BPF_PROG_TYPE_CGROUP_SOCKOPT)
	Tracing               = ProgramType(sys.BPF_PROG_TYPE_TRACING)
	StructOps             = ProgramType(sys.BPF_PROG_TYPE_STRUCT_OPS)
	Extension             = ProgramType(sys.BPF_PROG_TYPE_EXT)
	LSM                   = ProgramType(sys.BPF_PROG_TYPE_LSM)
	SkLookup              = ProgramType(sys.BPF_PROG_TYPE_SK_LOOKUP)
	Syscall               = ProgramType(sys.BPF_PROG_TYPE_SYSCALL)
	Netfilter             = ProgramType(sys.BPF_PROG_TYPE_NETFILTER)
)

eBPF program types

View Source
const (
	AttachCGroupInetIngress          = AttachType(sys.BPF_CGROUP_INET_INGRESS)
	AttachCGroupInetEgress           = AttachType(sys.BPF_CGROUP_INET_EGRESS)
	AttachCGroupInetSockCreate       = AttachType(sys.BPF_CGROUP_INET_SOCK_CREATE)
	AttachCGroupSockOps              = AttachType(sys.BPF_CGROUP_SOCK_OPS)
	AttachSkSKBStreamParser          = AttachType(sys.BPF_SK_SKB_STREAM_PARSER)
	AttachSkSKBStreamVerdict         = AttachType(sys.BPF_SK_SKB_STREAM_VERDICT)
	AttachCGroupDevice               = AttachType(sys.BPF_CGROUP_DEVICE)
	AttachSkMsgVerdict               = AttachType(sys.BPF_SK_MSG_VERDICT)
	AttachCGroupInet4Bind            = AttachType(sys.BPF_CGROUP_INET4_BIND)
	AttachCGroupInet6Bind            = AttachType(sys.BPF_CGROUP_INET6_BIND)
	AttachCGroupInet4Connect         = AttachType(sys.BPF_CGROUP_INET4_CONNECT)
	AttachCGroupInet6Connect         = AttachType(sys.BPF_CGROUP_INET6_CONNECT)
	AttachCGroupInet4PostBind        = AttachType(sys.BPF_CGROUP_INET4_POST_BIND)
	AttachCGroupInet6PostBind        = AttachType(sys.BPF_CGROUP_INET6_POST_BIND)
	AttachCGroupUDP4Sendmsg          = AttachType(sys.BPF_CGROUP_UDP4_SENDMSG)
	AttachCGroupUDP6Sendmsg          = AttachType(sys.BPF_CGROUP_UDP6_SENDMSG)
	AttachLircMode2                  = AttachType(sys.BPF_LIRC_MODE2)
	AttachFlowDissector              = AttachType(sys.BPF_FLOW_DISSECTOR)
	AttachCGroupSysctl               = AttachType(sys.BPF_CGROUP_SYSCTL)
	AttachCGroupUDP4Recvmsg          = AttachType(sys.BPF_CGROUP_UDP4_RECVMSG)
	AttachCGroupUDP6Recvmsg          = AttachType(sys.BPF_CGROUP_UDP6_RECVMSG)
	AttachCGroupGetsockopt           = AttachType(sys.BPF_CGROUP_GETSOCKOPT)
	AttachCGroupSetsockopt           = AttachType(sys.BPF_CGROUP_SETSOCKOPT)
	AttachTraceRawTp                 = AttachType(sys.BPF_TRACE_RAW_TP)
	AttachTraceFEntry                = AttachType(sys.BPF_TRACE_FENTRY)
	AttachTraceFExit                 = AttachType(sys.BPF_TRACE_FEXIT)
	AttachModifyReturn               = AttachType(sys.BPF_MODIFY_RETURN)
	AttachLSMMac                     = AttachType(sys.BPF_LSM_MAC)
	AttachTraceIter                  = AttachType(sys.BPF_TRACE_ITER)
	AttachCgroupInet4GetPeername     = AttachType(sys.BPF_CGROUP_INET4_GETPEERNAME)
	AttachCgroupInet6GetPeername     = AttachType(sys.BPF_CGROUP_INET6_GETPEERNAME)
	AttachCgroupInet4GetSockname     = AttachType(sys.BPF_CGROUP_INET4_GETSOCKNAME)
	AttachCgroupInet6GetSockname     = AttachType(sys.BPF_CGROUP_INET6_GETSOCKNAME)
	AttachXDPDevMap                  = AttachType(sys.BPF_XDP_DEVMAP)
	AttachCgroupInetSockRelease      = AttachType(sys.BPF_CGROUP_INET_SOCK_RELEASE)
	AttachXDPCPUMap                  = AttachType(sys.BPF_XDP_CPUMAP)
	AttachSkLookup                   = AttachType(sys.BPF_SK_LOOKUP)
	AttachXDP                        = AttachType(sys.BPF_XDP)
	AttachSkSKBVerdict               = AttachType(sys.BPF_SK_SKB_VERDICT)
	AttachSkReuseportSelect          = AttachType(sys.BPF_SK_REUSEPORT_SELECT)
	AttachSkReuseportSelectOrMigrate = AttachType(sys.BPF_SK_REUSEPORT_SELECT_OR_MIGRATE)
	AttachPerfEvent                  = AttachType(sys.BPF_PERF_EVENT)
	AttachTraceKprobeMulti           = AttachType(sys.BPF_TRACE_KPROBE_MULTI)
	AttachLSMCgroup                  = AttachType(sys.BPF_LSM_CGROUP)
	AttachStructOps                  = AttachType(sys.BPF_STRUCT_OPS)
	AttachNetfilter                  = AttachType(sys.BPF_NETFILTER)
	AttachTCXIngress                 = AttachType(sys.BPF_TCX_INGRESS)
	AttachTCXEgress                  = AttachType(sys.BPF_TCX_EGRESS)
	AttachTraceUprobeMulti           = AttachType(sys.BPF_TRACE_UPROBE_MULTI)
	AttachCgroupUnixConnect          = AttachType(sys.BPF_CGROUP_UNIX_CONNECT)
	AttachCgroupUnixSendmsg          = AttachType(sys.BPF_CGROUP_UNIX_SENDMSG)
	AttachCgroupUnixRecvmsg          = AttachType(sys.BPF_CGROUP_UNIX_RECVMSG)
	AttachCgroupUnixGetpeername      = AttachType(sys.BPF_CGROUP_UNIX_GETPEERNAME)
	AttachCgroupUnixGetsockname      = AttachType(sys.BPF_CGROUP_UNIX_GETSOCKNAME)
	AttachNetkitPrimary              = AttachType(sys.BPF_NETKIT_PRIMARY)
	AttachNetkitPeer                 = AttachType(sys.BPF_NETKIT_PEER)
)
View Source
const (
	// Print verifier state at branch points.
	LogLevelBranch = sys.BPF_LOG_LEVEL1

	// Print verifier state for every instruction.
	// Available since Linux v5.2.
	LogLevelInstruction = sys.BPF_LOG_LEVEL2

	// Print verifier errors and stats at the end of the verification process.
	// Available since Linux v5.2.
	LogLevelStats = sys.BPF_LOG_STATS
)

Variables

View Source
var (
	ErrKeyNotExist      = errors.New("key does not exist")
	ErrKeyExist         = errors.New("key already exists")
	ErrIterationAborted = errors.New("iteration aborted")
	ErrMapIncompatible  = errors.New("map spec is incompatible with existing map")
)

Errors returned by Map and MapIterator methods.

View Source
var ErrNotSupported = internal.ErrNotSupported

ErrNotSupported is returned whenever the kernel doesn't support a feature.

View Source
var ErrReadOnly = errors.New("resource is read-only")

Functions

func EnableStats added in v0.4.0

func EnableStats(which uint32) (io.Closer, error)

EnableStats starts the measuring of the runtime and run counts of eBPF programs.

Collecting statistics can have an impact on the performance.

Requires at least 5.8.

func MustPossibleCPU added in v0.13.0

func MustPossibleCPU() int

MustPossibleCPU is a helper that wraps a call to PossibleCPU and panics if the error is non-nil.

func PossibleCPU added in v0.13.0

func PossibleCPU() (int, error)

PossibleCPU returns the max number of CPUs a system may possibly have Logical CPU numbers must be of the form 0-n

func SanitizeName

func SanitizeName(name string, replacement rune) string

SanitizeName replaces all invalid characters in name with replacement. Passing a negative value for replacement will delete characters instead of replacing them. Use this to automatically generate valid names for maps and programs at runtime.

The set of allowed characters depends on the running kernel version. Dots are only allowed as of kernel 5.2.

Types

type AttachFlags

type AttachFlags uint32

AttachFlags of the eBPF program used in BPF_PROG_ATTACH command

type AttachType

type AttachType uint32

AttachType of the eBPF program, needed to differentiate allowed context accesses in some newer program types like CGroupSockAddr. Should be set to AttachNone if not required. Will cause invalid argument (EINVAL) at program load time if set incorrectly.

const AttachNone AttachType = 0

AttachNone is an alias for AttachCGroupInetIngress for readability reasons.

func (AttachType) String

func (i AttachType) String() string

type BatchOptions added in v0.4.0

type BatchOptions struct {
	ElemFlags uint64
	Flags     uint64
}

BatchOptions batch map operations options

Mirrors libbpf struct bpf_map_batch_opts Currently BPF_F_FLAG is the only supported flag (for ElemFlags).

type Collection

type Collection struct {
	Programs map[string]*Program
	Maps     map[string]*Map

	// Variables contains global variables used by the Collection's program(s). On
	// kernels older than 5.5, most interactions with Variables return
	// [ErrNotSupported].
	Variables map[string]*Variable
}

Collection is a collection of live BPF resources present in the kernel.

func LoadCollection

func LoadCollection(file string) (*Collection, error)

LoadCollection reads an object file and creates and loads its declared resources into the kernel.

Omitting Collection.Close() during application shutdown is an error. See the package documentation for details around Map and Program lifecycle.

func NewCollection

func NewCollection(spec *CollectionSpec) (*Collection, error)

NewCollection creates a Collection from the given spec, creating and loading its declared resources into the kernel.

Omitting Collection.Close() during application shutdown is an error. See the package documentation for details around Map and Program lifecycle.

func NewCollectionWithOptions

func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error)

NewCollectionWithOptions creates a Collection from the given spec using options, creating and loading its declared resources into the kernel.

Omitting Collection.Close() during application shutdown is an error. See the package documentation for details around Map and Program lifecycle.

func (*Collection) Assign

func (coll *Collection) Assign(to interface{}) error

Assign the contents of a Collection to a struct.

This function bridges functionality between bpf2go generated code and any functionality better implemented in Collection.

'to' must be a pointer to a struct. A field of the struct is updated with values from Programs or Maps if it has an `ebpf` tag and its type is *Program or *Map. The tag's value specifies the name of the program or map as found in the CollectionSpec.

struct {
    Foo     *ebpf.Program `ebpf:"xdp_foo"`
    Bar     *ebpf.Map     `ebpf:"bar_map"`
    Ignored int
}

Returns an error if any of the eBPF objects can't be found, or if the same Map or Program is assigned multiple times.

Ownership and Close()ing responsibility is transferred to `to` for any successful assigns. On error `to` is left in an undefined state.

func (*Collection) Close

func (coll *Collection) Close()

Close frees all maps and programs associated with the collection.

The collection mustn't be used afterwards.

func (*Collection) DetachMap

func (coll *Collection) DetachMap(name string) *Map

DetachMap removes the named map from the Collection.

This means that a later call to Close() will not affect this map.

Returns nil if no map of that name exists.

func (*Collection) DetachProgram

func (coll *Collection) DetachProgram(name string) *Program

DetachProgram removes the named program from the Collection.

This means that a later call to Close() will not affect this program.

Returns nil if no program of that name exists.

type CollectionOptions

type CollectionOptions struct {
	Maps     MapOptions
	Programs ProgramOptions

	// MapReplacements takes a set of Maps that will be used instead of
	// creating new ones when loading the CollectionSpec.
	//
	// For each given Map, there must be a corresponding MapSpec in
	// CollectionSpec.Maps, and its type, key/value size, max entries and flags
	// must match the values of the MapSpec.
	//
	// The given Maps are Clone()d before being used in the Collection, so the
	// caller can Close() them freely when they are no longer needed.
	MapReplacements map[string]*Map
}

CollectionOptions control loading a collection into the kernel.

Maps and Programs are passed to NewMapWithOptions and NewProgramsWithOptions.

type CollectionSpec

type CollectionSpec struct {
	Maps     map[string]*MapSpec
	Programs map[string]*ProgramSpec

	// Variables refer to global variables declared in the ELF. They can be read
	// and modified freely before loading the Collection. Modifying them after
	// loading has no effect on a running eBPF program.
	Variables map[string]*VariableSpec

	// Types holds type information about Maps and Programs.
	// Modifications to Types are currently undefined behaviour.
	Types *btf.Spec

	// ByteOrder specifies whether the ELF was compiled for
	// big-endian or little-endian architectures.
	ByteOrder binary.ByteOrder
}

CollectionSpec describes a collection.

func LoadCollectionSpec

func LoadCollectionSpec(file string) (*CollectionSpec, error)

LoadCollectionSpec parses an ELF file into a CollectionSpec.

func LoadCollectionSpecFromReader

func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error)

LoadCollectionSpecFromReader parses an ELF file into a CollectionSpec.

func (*CollectionSpec) Assign

func (cs *CollectionSpec) Assign(to interface{}) error

Assign the contents of a CollectionSpec to a struct.

This function is a shortcut to manually checking the presence of maps and programs in a CollectionSpec. Consider using bpf2go if this sounds useful.

'to' must be a pointer to a struct. A field of the struct is updated with values from Programs, Maps or Variables if it has an `ebpf` tag and its type is *ProgramSpec, *MapSpec or *VariableSpec. The tag's value specifies the name of the program or map as found in the CollectionSpec.

struct {
    Foo     *ebpf.ProgramSpec  `ebpf:"xdp_foo"`
    Bar     *ebpf.MapSpec      `ebpf:"bar_map"`
    Var     *ebpf.VariableSpec `ebpf:"some_var"`
    Ignored int
}

Returns an error if any of the eBPF objects can't be found, or if the same Spec is assigned multiple times.

Example
spec := &CollectionSpec{
	Maps: map[string]*MapSpec{
		"map1": {
			Type:       Array,
			KeySize:    4,
			ValueSize:  4,
			MaxEntries: 1,
		},
	},
	Programs: map[string]*ProgramSpec{
		"prog1": {
			Type: SocketFilter,
			Instructions: asm.Instructions{
				asm.LoadImm(asm.R0, 0, asm.DWord),
				asm.Return(),
			},
			License: "MIT",
		},
	},
}

type maps struct {
	Map *MapSpec `ebpf:"map1"`
}

var specs struct {
	maps
	Program *ProgramSpec `ebpf:"prog1"`
}

if err := spec.Assign(&specs); err != nil {
	panic(err)
}

fmt.Println(specs.Program.Type)
fmt.Println(specs.Map.Type)
Output:

SocketFilter
Array

func (*CollectionSpec) Copy

func (cs *CollectionSpec) Copy() *CollectionSpec

Copy returns a recursive copy of the spec.

func (*CollectionSpec) LoadAndAssign

func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) error

LoadAndAssign loads Maps and Programs into the kernel and assigns them to a struct.

Omitting Map/Program.Close() during application shutdown is an error. See the package documentation for details around Map and Program lifecycle.

This function is a shortcut to manually checking the presence of maps and programs in a CollectionSpec. Consider using bpf2go if this sounds useful.

'to' must be a pointer to a struct. A field of the struct is updated with a Program or Map if it has an `ebpf` tag and its type is *Program or *Map. The tag's value specifies the name of the program or map as found in the CollectionSpec. Before updating the struct, the requested objects and their dependent resources are loaded into the kernel and populated with values if specified.

struct {
    Foo     *ebpf.Program `ebpf:"xdp_foo"`
    Bar     *ebpf.Map     `ebpf:"bar_map"`
    Ignored int
}

opts may be nil.

Returns an error if any of the fields can't be found, or if the same Map or Program is assigned multiple times.

Example
spec := &CollectionSpec{
	Maps: map[string]*MapSpec{
		"map1": {
			Type:       Array,
			KeySize:    4,
			ValueSize:  4,
			MaxEntries: 1,
		},
	},
	Programs: map[string]*ProgramSpec{
		"prog1": {
			Type: SocketFilter,
			Instructions: asm.Instructions{
				asm.LoadImm(asm.R0, 0, asm.DWord),
				asm.Return(),
			},
			License: "MIT",
		},
	},
}

var objs struct {
	Program *Program `ebpf:"prog1"`
	Map     *Map     `ebpf:"map1"`
}

if err := spec.LoadAndAssign(&objs, nil); err != nil {
	panic(err)
}
defer objs.Program.Close()
defer objs.Map.Close()

fmt.Println(objs.Program.Type())
fmt.Println(objs.Map.Type())
Output:

SocketFilter
Array

func (*CollectionSpec) RewriteConstants deprecated

func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error

RewriteConstants replaces the value of multiple constants.

The constant must be defined like so in the C program:

volatile const type foobar;
volatile const type foobar = default;

Replacement values must be of the same length as the C sizeof(type). If necessary, they are marshalled according to the same rules as map values.

From Linux 5.5 the verifier will use constants to eliminate dead code.

Returns an error wrapping MissingConstantsError if a constant doesn't exist.

Deprecated: Use [CollectionSpec.Variables] to interact with constants instead. RewriteConstants is now a wrapper around the VariableSpec API.

func (*CollectionSpec) RewriteMaps deprecated

func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error

RewriteMaps replaces all references to specific maps.

Use this function to use pre-existing maps instead of creating new ones when calling NewCollection. Any named maps are removed from CollectionSpec.Maps.

Returns an error if a named map isn't used in at least one program.

Deprecated: Pass CollectionOptions.MapReplacements when loading the Collection instead.

type LoadPinOptions added in v0.5.0

type LoadPinOptions struct {
	// Request a read-only or write-only object. The default is a read-write
	// object. Only one of the flags may be set.
	ReadOnly  bool
	WriteOnly bool

	// Raw flags for the syscall. Other fields of this struct take precedence.
	Flags uint32
}

LoadPinOptions control how a pinned object is loaded.

func (*LoadPinOptions) Marshal added in v0.5.0

func (lpo *LoadPinOptions) Marshal() uint32

Marshal returns a value suitable for BPF_OBJ_GET syscall file_flags parameter.

type LogLevel added in v0.9.2

type LogLevel = sys.LogLevel

LogLevel controls the verbosity of the kernel's eBPF program verifier. These constants can be used for the ProgramOptions.LogLevel field.

type Map

type Map struct {
	// contains filtered or unexported fields
}

Map represents a Map file descriptor.

It is not safe to close a map which is used by other goroutines.

Methods which take interface{} arguments by default encode them using binary.Read/Write in the machine's native endianness.

Implement encoding.BinaryMarshaler or encoding.BinaryUnmarshaler if you require custom encoding.

Example (PerCPU)

Per CPU maps store a distinct value for each CPU. They are useful to collect metrics.

arr, err := NewMap(&MapSpec{
	Type:       PerCPUArray,
	KeySize:    4,
	ValueSize:  4,
	MaxEntries: 2,
})
if err != nil {
	panic(err)
}
defer arr.Close()

possibleCPUs := MustPossibleCPU()
perCPUValues := map[uint32]uint32{
	0: 4,
	1: 5,
}

for k, v := range perCPUValues {
	// We set each perCPU slots to the same value.
	values := make([]uint32, possibleCPUs)
	for i := range values {
		values[i] = v
	}
	if err := arr.Put(k, values); err != nil {
		panic(err)
	}
}

for k := 0; k < 2; k++ {
	var values []uint32
	if err := arr.Lookup(uint32(k), &values); err != nil {
		panic(err)
	}
	// Note we will print an unexpected message if this is not true.
	fmt.Printf("Value of key %v on all CPUs: %v\n", k, values[0])
}
var (
	key     uint32
	entries = arr.Iterate()
)

var values []uint32
for entries.Next(&key, &values) {
	expected, ok := perCPUValues[key]
	if !ok {
		fmt.Printf("Unexpected key %v\n", key)
		continue
	}

	for i, n := range values {
		if n != expected {
			fmt.Printf("Key %v, Value for cpu %v is %v not %v\n",
				key, i, n, expected)
		}
	}
}

if err := entries.Err(); err != nil {
	panic(err)
}
Output:

Value of key 0 on all CPUs: 4
Value of key 1 on all CPUs: 5
Example (ZeroCopy)

It is possible to use unsafe.Pointer to avoid marshalling and copy overhead. It is the responsibility of the caller to ensure the correct size of unsafe.Pointers.

Note that using unsafe.Pointer is only marginally faster than implementing Marshaler on the type.

hash, err := NewMap(&MapSpec{
	Type:       Hash,
	KeySize:    5,
	ValueSize:  4,
	MaxEntries: 10,
})
if err != nil {
	panic(err)
}
defer hash.Close()

key := [5]byte{'h', 'e', 'l', 'l', 'o'}
value := uint32(23)

if err := hash.Put(unsafe.Pointer(&key), unsafe.Pointer(&value)); err != nil {
	panic(err)
}

value = 0
if err := hash.Lookup(unsafe.Pointer(&key), unsafe.Pointer(&value)); err != nil {
	panic("can't get value:" + err.Error())
}

fmt.Printf("The value is: %d\n", value)
Output:

The value is: 23

func LoadPinnedMap

func LoadPinnedMap(fileName string, opts *LoadPinOptions) (*Map, error)

LoadPinnedMap opens a Map from a pin (file) on the BPF virtual filesystem.

Requires at least Linux 4.5.

func NewMap

func NewMap(spec *MapSpec) (*Map, error)

NewMap creates a new Map.

It's equivalent to calling NewMapWithOptions with default options.

func NewMapFromFD

func NewMapFromFD(fd int) (*Map, error)

NewMapFromFD creates a map from a raw fd.

You should not use fd after calling this function.

func NewMapFromID

func NewMapFromID(id MapID) (*Map, error)

NewMapFromID returns the map for a given id.

Returns ErrNotExist, if there is no eBPF map with the given id.

func NewMapWithOptions

func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error)

NewMapWithOptions creates a new Map.

Creating a map for the first time will perform feature detection by creating small, temporary maps.

The caller is responsible for ensuring the process' rlimit is set sufficiently high for locking memory during map creation. This can be done by calling rlimit.RemoveMemlock() prior to calling NewMapWithOptions.

May return an error wrapping ErrMapIncompatible.

func (*Map) BatchDelete added in v0.4.0

func (m *Map) BatchDelete(keys interface{}, opts *BatchOptions) (int, error)

BatchDelete batch deletes entries in the map by keys. "keys" must be of type slice, a pointer to a slice or buffer will not work.

func (*Map) BatchLookup added in v0.4.0

func (m *Map) BatchLookup(cursor *MapBatchCursor, keysOut, valuesOut interface{}, opts *BatchOptions) (int, error)

BatchLookup looks up many elements in a map at once.

"keysOut" and "valuesOut" must be of type slice, a pointer to a slice or buffer will not work. "cursor" is an pointer to an opaque handle. It must be non-nil. Pass "cursor" to subsequent calls of this function to continue the batching operation in the case of chunking.

Warning: This API is not very safe to use as the kernel implementation for batching relies on the user to be aware of subtle details with regarding to different map type implementations.

ErrKeyNotExist is returned when the batch lookup has reached the end of all possible results, even when partial results are returned. It should be used to evaluate when lookup is "done".

func (*Map) BatchLookupAndDelete added in v0.4.0

func (m *Map) BatchLookupAndDelete(cursor *MapBatchCursor, keysOut, valuesOut interface{}, opts *BatchOptions) (int, error)

BatchLookupAndDelete looks up many elements in a map at once,

It then deletes all those elements. "keysOut" and "valuesOut" must be of type slice, a pointer to a slice or buffer will not work. "cursor" is an pointer to an opaque handle. It must be non-nil. Pass "cursor" to subsequent calls of this function to continue the batching operation in the case of chunking.

Warning: This API is not very safe to use as the kernel implementation for batching relies on the user to be aware of subtle details with regarding to different map type implementations.

ErrKeyNotExist is returned when the batch lookup has reached the end of all possible results, even when partial results are returned. It should be used to evaluate when lookup is "done".

func (*Map) BatchUpdate added in v0.4.0

func (m *Map) BatchUpdate(keys, values interface{}, opts *BatchOptions) (int, error)

BatchUpdate updates the map with multiple keys and values simultaneously. "keys" and "values" must be of type slice, a pointer to a slice or buffer will not work.

func (*Map) Clone

func (m *Map) Clone() (*Map, error)

Clone creates a duplicate of the Map.

Closing the duplicate does not affect the original, and vice versa. Changes made to the map are reflected by both instances however. If the original map was pinned, the cloned map will not be pinned by default.

Cloning a nil Map returns nil.

func (*Map) Close

func (m *Map) Close() error

Close the Map's underlying file descriptor, which could unload the Map from the kernel if it is not pinned or in use by a loaded Program.

func (*Map) Delete

func (m *Map) Delete(key interface{}) error

Delete removes a value.

Returns ErrKeyNotExist if the key does not exist.

func (*Map) FD

func (m *Map) FD() int

FD gets the file descriptor of the Map.

Calling this function is invalid after Close has been called.

func (*Map) Flags

func (m *Map) Flags() uint32

Flags returns the flags of the map.

func (*Map) Freeze

func (m *Map) Freeze() error

Freeze prevents a map to be modified from user space.

It makes no changes to kernel-side restrictions.

func (*Map) Handle added in v0.16.0

func (m *Map) Handle() (*btf.Handle, error)

Handle returns a reference to the Map's type information in the kernel.

Returns ErrNotSupported if the kernel has no BTF support, or if there is no BTF associated with the Map.

func (*Map) Info added in v0.3.0

func (m *Map) Info() (*MapInfo, error)

Info returns metadata about the map. This was first introduced in Linux 4.5, but newer kernels support more MapInfo fields with the introduction of more features. See MapInfo and its methods for more details.

Returns an error wrapping ErrNotSupported if the kernel supports neither BPF_OBJ_GET_INFO_BY_FD nor reading map information from /proc/self/fdinfo.

func (*Map) IsPinned added in v0.4.0

func (m *Map) IsPinned() bool

IsPinned returns true if the map has a non-empty pinned path.

func (*Map) Iterate

func (m *Map) Iterate() *MapIterator

Iterate traverses a map.

It's safe to create multiple iterators at the same time.

It's not possible to guarantee that all keys in a map will be returned if there are concurrent modifications to the map.

Example

ExampleMap_Iterate demonstrates how to iterate over all entries in a map.

hash, err := NewMap(&MapSpec{
	Type:       Hash,
	KeySize:    5,
	ValueSize:  4,
	MaxEntries: 10,
	Contents: []MapKV{
		{"hello", uint32(21)},
		{"world", uint32(42)},
	},
})
if err != nil {
	panic(err)
}
defer hash.Close()

var (
	key     string
	value   uint32
	entries = hash.Iterate()
)

values := make(map[string]uint32)
for entries.Next(&key, &value) {
	// Order of keys is non-deterministic due to randomized map seed
	values[key] = value
}

if err := entries.Err(); err != nil {
	panic(fmt.Sprint("Iterator encountered an error:", err))
}

for k, v := range values {
	fmt.Printf("key: %s, value: %d\n", k, v)
}
Output:

key: hello, value: 21
key: world, value: 42
Example (NestedMapsAndProgramArrays)

It is possible to iterate nested maps and program arrays by unmarshaling into a *Map or *Program.

inner := &MapSpec{
	Type:       Array,
	KeySize:    4,
	ValueSize:  4,
	MaxEntries: 2,
	Contents: []MapKV{
		{uint32(0), uint32(1)},
		{uint32(1), uint32(2)},
	},
}
im, err := NewMap(inner)
if err != nil {
	panic(err)
}
defer im.Close()

outer := &MapSpec{
	Type:       ArrayOfMaps,
	InnerMap:   inner,
	KeySize:    4,
	ValueSize:  4,
	MaxEntries: 10,
	Contents: []MapKV{
		{uint32(0), im},
	},
}
arrayOfMaps, err := NewMap(outer)
if errors.Is(err, internal.ErrNotSupported) {
	// Fake the output if on very old kernel.
	fmt.Println("outerKey: 0")
	fmt.Println("\tinnerKey 0 innerValue 1")
	fmt.Println("\tinnerKey 1 innerValue 2")
	return
}
if err != nil {
	panic(err)
}
defer arrayOfMaps.Close()

var (
	key     uint32
	m       *Map
	entries = arrayOfMaps.Iterate()
)
for entries.Next(&key, &m) {
	// Make sure that the iterated map is closed after
	// we are done.
	defer m.Close()

	// Order of keys is non-deterministic due to randomized map seed
	fmt.Printf("outerKey: %v\n", key)

	var innerKey, innerValue uint32
	items := m.Iterate()
	for items.Next(&innerKey, &innerValue) {
		fmt.Printf("\tinnerKey %v innerValue %v\n", innerKey, innerValue)
	}
	if err := items.Err(); err != nil {
		panic(fmt.Sprint("Inner Iterator encountered an error:", err))
	}
}

if err := entries.Err(); err != nil {
	panic(fmt.Sprint("Iterator encountered an error:", err))
}
Output:

outerKey: 0
	innerKey 0 innerValue 1
	innerKey 1 innerValue 2

func (*Map) KeySize

func (m *Map) KeySize() uint32

KeySize returns the size of the map key in bytes.

func (*Map) Lookup

func (m *Map) Lookup(key, valueOut interface{}) error

Lookup retrieves a value from a Map.

Calls Close() on valueOut if it is of type **Map or **Program, and *valueOut is not nil.

Returns an error if the key doesn't exist, see ErrKeyNotExist.

func (*Map) LookupAndDelete

func (m *Map) LookupAndDelete(key, valueOut interface{}) error

LookupAndDelete retrieves and deletes a value from a Map.

Returns ErrKeyNotExist if the key doesn't exist.

func (*Map) LookupAndDeleteWithFlags added in v0.8.0

func (m *Map) LookupAndDeleteWithFlags(key, valueOut interface{}, flags MapLookupFlags) error

LookupAndDeleteWithFlags retrieves and deletes a value from a Map.

Passing LookupLock flag will look up and delete the value of a spin-locked map without returning the lock. This must be specified if the elements contain a spinlock.

Returns ErrKeyNotExist if the key doesn't exist.

func (*Map) LookupBytes

func (m *Map) LookupBytes(key interface{}) ([]byte, error)

LookupBytes gets a value from Map.

Returns a nil value if a key doesn't exist.

func (*Map) LookupWithFlags added in v0.8.0

func (m *Map) LookupWithFlags(key, valueOut interface{}, flags MapLookupFlags) error

LookupWithFlags retrieves a value from a Map with flags.

Passing LookupLock flag will look up the value of a spin-locked map without returning the lock. This must be specified if the elements contain a spinlock.

Calls Close() on valueOut if it is of type **Map or **Program, and *valueOut is not nil.

Returns an error if the key doesn't exist, see ErrKeyNotExist.

func (*Map) MaxEntries

func (m *Map) MaxEntries() uint32

MaxEntries returns the maximum number of elements the map can hold.

func (*Map) Memory added in v0.17.0

func (m *Map) Memory() (*Memory, error)

Memory returns a memory-mapped region for the Map. The Map must have been created with the BPF_F_MMAPABLE flag. Repeated calls to Memory return the same mapping. Callers are responsible for coordinating access to Memory.

func (*Map) NextKey

func (m *Map) NextKey(key, nextKeyOut interface{}) error

NextKey finds the key following an initial key.

See NextKeyBytes for details.

Returns ErrKeyNotExist if there is no next key.

Example
hash, err := NewMap(&MapSpec{
	Type:       Hash,
	KeySize:    5,
	ValueSize:  4,
	MaxEntries: 10,
	Contents: []MapKV{
		{"hello", uint32(21)},
		{"world", uint32(42)},
	},
})
if err != nil {
	panic(err)
}
defer hash.Close()

var cur, next string
var keys []string

for err = hash.NextKey(nil, &next); ; err = hash.NextKey(cur, &next) {
	if errors.Is(err, ErrKeyNotExist) {
		break
	}
	if err != nil {
		panic(err)
	}
	keys = append(keys, next)
	cur = next
}

// Order of keys is non-deterministic due to randomized map seed
sort.Strings(keys)
fmt.Printf("Keys are %v\n", keys)
Output:

Keys are [hello world]

func (*Map) NextKeyBytes

func (m *Map) NextKeyBytes(key interface{}) ([]byte, error)

NextKeyBytes returns the key following an initial key as a byte slice.

Passing nil will return the first key.

Use Iterate if you want to traverse all entries in the map.

Returns nil if there are no more keys.

func (*Map) Pin

func (m *Map) Pin(fileName string) error

Pin persists the map on the BPF virtual file system past the lifetime of the process that created it .

Calling Pin on a previously pinned map will overwrite the path, except when the new path already exists. Re-pinning across filesystems is not supported. You can Clone a map to pin it to a different path.

This requires bpffs to be mounted above fileName. See https://docs.cilium.io/en/stable/network/kubernetes/configuration/#mounting-bpffs-with-systemd

func (*Map) Put

func (m *Map) Put(key, value interface{}) error

Put replaces or creates a value in map.

It is equivalent to calling Update with UpdateAny.

func (*Map) String

func (m *Map) String() string

func (*Map) Type

func (m *Map) Type() MapType

Type returns the underlying type of the map.

func (*Map) Unpin added in v0.4.0

func (m *Map) Unpin() error

Unpin removes the persisted state for the map from the BPF virtual filesystem.

Failed calls to Unpin will not alter the state returned by IsPinned.

Unpinning an unpinned Map returns nil.

func (*Map) Update

func (m *Map) Update(key, value any, flags MapUpdateFlags) error

Update changes the value of a key.

func (*Map) ValueSize

func (m *Map) ValueSize() uint32

ValueSize returns the size of the map value in bytes.

type MapBatchCursor added in v0.13.0

type MapBatchCursor struct {
	// contains filtered or unexported fields
}

MapBatchCursor represents a starting point for a batch operation.

type MapID

type MapID uint32

MapID represents the unique ID of an eBPF map

func MapGetNextID

func MapGetNextID(startID MapID) (MapID, error)

MapGetNextID returns the ID of the next eBPF map.

Returns ErrNotExist, if there is no next eBPF map.

type MapInfo added in v0.3.0

type MapInfo struct {
	// Type of the map.
	Type MapType
	// KeySize is the size of the map key in bytes.
	KeySize uint32
	// ValueSize is the size of the map value in bytes.
	ValueSize uint32
	// MaxEntries is the maximum number of entries the map can hold. Its meaning
	// is map-specific.
	MaxEntries uint32
	// Flags used during map creation.
	Flags uint32
	// Name as supplied by user space at load time. Available from 4.15.
	Name string
	// contains filtered or unexported fields
}

MapInfo describes a map.

func (*MapInfo) BTFID added in v0.16.0

func (mi *MapInfo) BTFID() (btf.ID, bool)

BTFID returns the BTF ID associated with the Map.

The ID is only valid as long as the associated Map is kept alive. Available from 4.18.

The bool return value indicates whether this optional field is available and populated. (The field may be available but not populated if the kernel supports the field but the Map was loaded without BTF information.)

func (*MapInfo) Frozen added in v0.17.0

func (mi *MapInfo) Frozen() bool

Frozen indicates whether Map.Freeze was called on this map. If true, modifications from user space are not allowed.

Available from 5.2. Requires access to procfs.

If the kernel doesn't support map freezing, this field will always be false.

func (*MapInfo) ID added in v0.4.0

func (mi *MapInfo) ID() (MapID, bool)

ID returns the map ID.

Available from 4.13.

The bool return value indicates whether this optional field is available.

func (*MapInfo) MapExtra added in v0.17.0

func (mi *MapInfo) MapExtra() (uint64, bool)

MapExtra returns an opaque field whose meaning is map-specific.

Available from 5.16.

The bool return value indicates whether this optional field is available and populated, if it was specified during Map creation.

func (*MapInfo) Memlock added in v0.17.0

func (mi *MapInfo) Memlock() (uint64, bool)

Memlock returns an approximate number of bytes allocated to this map.

Available from 4.10.

The bool return value indicates whether this optional field is available.

type MapIterator

type MapIterator struct {
	// contains filtered or unexported fields
}

MapIterator iterates a Map.

See Map.Iterate.

func (*MapIterator) Err

func (mi *MapIterator) Err() error

Err returns any encountered error.

The method must be called after Next returns nil.

Returns ErrIterationAborted if it wasn't possible to do a full iteration.

func (*MapIterator) Next

func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool

Next decodes the next key and value.

Iterating a hash map from which keys are being deleted is not safe. You may see the same key multiple times. Iteration may also abort with an error, see IsIterationAborted.

Returns false if there are no more entries. You must check the result of Err afterwards.

See Map.Get for further caveats around valueOut.

type MapKV

type MapKV struct {
	Key   interface{}
	Value interface{}
}

MapKV is used to initialize the contents of a Map.

type MapLookupFlags added in v0.8.0

type MapLookupFlags uint64

MapLookupFlags controls the behaviour of the map lookup calls.

const LookupLock MapLookupFlags = sys.BPF_F_LOCK

LookupLock look up the value of a spin-locked map.

type MapOptions

type MapOptions struct {
	// The base path to pin maps in if requested via PinByName.
	// Existing maps will be re-used if they are compatible, otherwise an
	// error is returned.
	PinPath        string
	LoadPinOptions LoadPinOptions
}

MapOptions control loading a map into the kernel.

type MapSpec

type MapSpec struct {
	// Name is passed to the kernel as a debug aid. Must only contain
	// alpha numeric and '_' characters.
	Name       string
	Type       MapType
	KeySize    uint32
	ValueSize  uint32
	MaxEntries uint32

	// Flags is passed to the kernel and specifies additional map
	// creation attributes.
	Flags uint32

	// Automatically pin and load a map from MapOptions.PinPath.
	// Generates an error if an existing pinned map is incompatible with the MapSpec.
	Pinning PinType

	// Specify numa node during map creation
	// (effective only if sys.BPF_F_NUMA_NODE flag is set,
	// which can be imported from golang.org/x/sys/unix)
	NumaNode uint32

	// The initial contents of the map. May be nil.
	Contents []MapKV

	// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
	InnerMap *MapSpec

	// Extra trailing bytes found in the ELF map definition when using structs
	// larger than libbpf's bpf_map_def. nil if no trailing bytes were present.
	// Must be nil or empty before instantiating the MapSpec into a Map.
	Extra *bytes.Reader

	// The key and value type of this map. May be nil.
	Key, Value btf.Type
}

MapSpec defines a Map.

func (*MapSpec) Compatible added in v0.10.0

func (ms *MapSpec) Compatible(m *Map) error

Compatible returns nil if an existing map may be used instead of creating one from the spec.

Returns an error wrapping ErrMapIncompatible otherwise.

func (*MapSpec) Copy

func (ms *MapSpec) Copy() *MapSpec

Copy returns a copy of the spec.

MapSpec.Contents is a shallow copy.

func (*MapSpec) String

func (ms *MapSpec) String() string

type MapType

type MapType uint32

MapType indicates the type map structure that will be initialized in the kernel.

const (
	UnspecifiedMap MapType = iota
	// Hash is a hash map
	Hash
	// Array is an array map
	Array
	// ProgramArray - A program array map is a special kind of array map whose map
	// values contain only file descriptors referring to other eBPF
	// programs.  Thus, both the key_size and value_size must be
	// exactly four bytes.  This map is used in conjunction with the
	// TailCall helper.
	ProgramArray
	// PerfEventArray - A perf event array is used in conjunction with PerfEventRead
	// and PerfEventOutput calls, to read the raw bpf_perf_data from the registers.
	PerfEventArray
	// PerCPUHash - This data structure is useful for people who have high performance
	// network needs and can reconcile adds at the end of some cycle, so that
	// hashes can be lock free without the use of XAdd, which can be costly.
	PerCPUHash
	// PerCPUArray - This data structure is useful for people who have high performance
	// network needs and can reconcile adds at the end of some cycle, so that
	// hashes can be lock free without the use of XAdd, which can be costly.
	// Each CPU gets a copy of this hash, the contents of all of which can be reconciled
	// later.
	PerCPUArray
	// StackTrace - This holds whole user and kernel stack traces, it can be retrieved with
	// GetStackID
	StackTrace
	// CGroupArray - This is a very niche structure used to help SKBInCGroup determine
	// if an skb is from a socket belonging to a specific cgroup
	CGroupArray
	// LRUHash - This allows you to create a small hash structure that will purge the
	// least recently used items rather than throw an error when you run out of memory
	LRUHash
	// LRUCPUHash - This is NOT like PerCPUHash, this structure is shared among the CPUs,
	// it has more to do with including the CPU id with the LRU calculation so that if a
	// particular CPU is using a value over-and-over again, then it will be saved, but if
	// a value is being retrieved a lot but sparsely across CPUs it is not as important, basically
	// giving weight to CPU locality over overall usage.
	LRUCPUHash
	// LPMTrie - This is an implementation of Longest-Prefix-Match Trie structure. It is useful,
	// for storing things like IP addresses which can be bit masked allowing for keys of differing
	// values to refer to the same reference based on their masks. See wikipedia for more details.
	LPMTrie
	// ArrayOfMaps - Each item in the array is another map. The inner map mustn't be a map of maps
	// itself.
	ArrayOfMaps
	// HashOfMaps - Each item in the hash map is another map. The inner map mustn't be a map of maps
	// itself.
	HashOfMaps
	// DevMap - Specialized map to store references to network devices.
	DevMap
	// SockMap - Specialized map to store references to sockets.
	SockMap
	// CPUMap - Specialized map to store references to CPUs.
	CPUMap
	// XSKMap - Specialized map for XDP programs to store references to open sockets.
	XSKMap
	// SockHash - Specialized hash to store references to sockets.
	SockHash
	// CGroupStorage - Special map for CGroups.
	CGroupStorage
	// ReusePortSockArray - Specialized map to store references to sockets that can be reused.
	ReusePortSockArray
	// PerCPUCGroupStorage - Special per CPU map for CGroups.
	PerCPUCGroupStorage
	// Queue - FIFO storage for BPF programs.
	Queue
	// Stack - LIFO storage for BPF programs.
	Stack
	// SkStorage - Specialized map for local storage at SK for BPF programs.
	SkStorage
	// DevMapHash - Hash-based indexing scheme for references to network devices.
	DevMapHash
	// StructOpsMap - This map holds a kernel struct with its function pointer implemented in a BPF
	// program.
	StructOpsMap
	// RingBuf - Similar to PerfEventArray, but shared across all CPUs.
	RingBuf
	// InodeStorage - Specialized local storage map for inodes.
	InodeStorage
	// TaskStorage - Specialized local storage map for task_struct.
	TaskStorage
	// BloomFilter - Space-efficient data structure to quickly test whether an element exists in a set.
	BloomFilter
	// UserRingbuf - The reverse of RingBuf, used to send messages from user space to BPF programs.
	UserRingbuf
	// CgroupStorage - Store data keyed on a cgroup. If the cgroup disappears, the key is automatically removed.
	CgroupStorage
	// Arena - Sparse shared memory region between a BPF program and user space.
	Arena
)

All the various map types that can be created

func (MapType) String

func (i MapType) String() string

type MapUpdateFlags

type MapUpdateFlags uint64

MapUpdateFlags controls the behaviour of the Map.Update call.

The exact semantics depend on the specific MapType.

const (
	// UpdateAny creates a new element or update an existing one.
	UpdateAny MapUpdateFlags = iota
	// UpdateNoExist creates a new element.
	UpdateNoExist MapUpdateFlags = 1 << (iota - 1)
	// UpdateExist updates an existing element.
	UpdateExist
	// UpdateLock updates elements under bpf_spin_lock.
	UpdateLock
)

type Memory added in v0.17.0

type Memory struct {
	// contains filtered or unexported fields
}

Memory implements accessing a Map's memory without making any syscalls. Pay attention to the difference between Go and C struct alignment rules. Use structs.HostLayout on supported Go versions to help with alignment.

Note on memory coherence: avoid using packed structs in memory shared between user space and eBPF C programs. This drops a struct's memory alignment to 1, forcing the compiler to use single-byte loads and stores for field accesses. This may lead to partially-written data to be observed from user space.

On most architectures, the memmove implementation used by Go's copy() will access data in word-sized chunks. If paired with a matching access pattern on the eBPF C side (and if using default memory alignment), accessing shared memory without atomics or other synchronization primitives should be sound for individual values. For accesses beyond a single value, the usual concurrent programming rules apply.

func (*Memory) ReadAt added in v0.17.0

func (mm *Memory) ReadAt(p []byte, off int64) (int, error)

ReadAt implements io.ReaderAt. Useful for creating a new io.OffsetWriter.

See Memory for details around memory coherence.

func (*Memory) ReadOnly added in v0.17.0

func (mm *Memory) ReadOnly() bool

ReadOnly returns true if the memory-mapped region is read-only.

func (*Memory) Size added in v0.17.0

func (mm *Memory) Size() int

Size returns the size of the memory-mapped region in bytes.

func (*Memory) WriteAt added in v0.17.0

func (mm *Memory) WriteAt(p []byte, off int64) (int, error)

WriteAt implements io.WriterAt. Useful for creating a new io.SectionReader.

See Memory for details around memory coherence.

type MissingConstantsError added in v0.11.0

type MissingConstantsError struct {
	// The constants missing from .rodata.
	Constants []string
}

MissingConstantsError is returned by CollectionSpec.RewriteConstants.

func (*MissingConstantsError) Error added in v0.11.0

func (m *MissingConstantsError) Error() string

type PinType

type PinType uint32

PinType determines whether a map is pinned into a BPFFS.

const (
	PinNone PinType = iota
	// Pin an object by using its name as the filename.
	PinByName
)

Valid pin types.

Mirrors enum libbpf_pin_type.

func (PinType) String

func (i PinType) String() string

type Program

type Program struct {
	// Contains the output of the kernel verifier if enabled,
	// otherwise it is empty.
	VerifierLog string
	// contains filtered or unexported fields
}

Program represents BPF program loaded into the kernel.

It is not safe to close a Program which is used by other goroutines.

Example (RetrieveVerifierLog)

Use NewProgramWithOptions if you'd like to get the verifier output for a program, or if you want to change the buffer size used when generating error messages.

spec := &ProgramSpec{
	Type: SocketFilter,
	Instructions: asm.Instructions{
		asm.LoadImm(asm.R0, 0, asm.DWord),
		asm.Return(),
	},
	License: "MIT",
}

prog, err := NewProgramWithOptions(spec, ProgramOptions{
	LogLevel: LogLevelInstruction,
})
if err != nil {
	panic(err)
}
defer prog.Close()

fmt.Println("The verifier output is:")
fmt.Println(prog.VerifierLog)
Output:

Example (UnmarshalFromMap)

It's possible to read a program directly from a ProgramArray.

progArray, err := LoadPinnedMap("/path/to/map", nil)
if err != nil {
	panic(err)
}
defer progArray.Close()

// Load a single program
var prog *Program
if err := progArray.Lookup(uint32(0), &prog); err != nil {
	panic(err)
}
defer prog.Close()

fmt.Println("first prog:", prog)

// Iterate all programs
var (
	key     uint32
	entries = progArray.Iterate()
)

for entries.Next(&key, &prog) {
	fmt.Println(key, "is", prog)
}

if err := entries.Err(); err != nil {
	panic(err)
}
Output:

func LoadPinnedProgram

func LoadPinnedProgram(fileName string, opts *LoadPinOptions) (*Program, error)

LoadPinnedProgram loads a Program from a pin (file) on the BPF virtual filesystem.

Requires at least Linux 4.11.

func NewProgram

func NewProgram(spec *ProgramSpec) (*Program, error)

NewProgram creates a new Program.

See NewProgramWithOptions for details.

Returns a VerifierError containing the full verifier log if the program is rejected by the kernel.

func NewProgramFromFD

func NewProgramFromFD(fd int) (*Program, error)

NewProgramFromFD creates a program from a raw fd.

You should not use fd after calling this function.

Requires at least Linux 4.10.

func NewProgramFromID

func NewProgramFromID(id ProgramID) (*Program, error)

NewProgramFromID returns the program for a given id.

Returns ErrNotExist, if there is no eBPF program with the given id.

func NewProgramWithOptions

func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, error)

NewProgramWithOptions creates a new Program.

Loading a program for the first time will perform feature detection by loading small, temporary programs.

Returns a VerifierError containing the full verifier log if the program is rejected by the kernel.

func (*Program) Benchmark

func (p *Program) Benchmark(in []byte, repeat int, reset func()) (uint32, time.Duration, error)

Benchmark runs the Program with the given input for a number of times and returns the time taken per iteration.

Returns the result of the last execution of the program and the time per run or an error. reset is called whenever the benchmark syscall is interrupted, and should be set to testing.B.ResetTimer or similar.

This function requires at least Linux 4.12.

func (*Program) BindMap added in v0.8.0

func (p *Program) BindMap(m *Map) error

BindMap binds map to the program and is only released once program is released.

This may be used in cases where metadata should be associated with the program which otherwise does not contain any references to the map.

func (*Program) Clone

func (p *Program) Clone() (*Program, error)

Clone creates a duplicate of the Program.

Closing the duplicate does not affect the original, and vice versa.

Cloning a nil Program returns nil.

func (*Program) Close

func (p *Program) Close() error

Close the Program's underlying file descriptor, which could unload the program from the kernel if it is not pinned or attached to a kernel hook.

func (*Program) FD

func (p *Program) FD() int

FD gets the file descriptor of the Program.

It is invalid to call this function after Close has been called.

func (*Program) Handle added in v0.9.1

func (p *Program) Handle() (*btf.Handle, error)

Handle returns a reference to the program's type information in the kernel.

Returns ErrNotSupported if the kernel has no BTF support, or if there is no BTF associated with the program.

func (*Program) Info added in v0.3.0

func (p *Program) Info() (*ProgramInfo, error)

Info returns metadata about the program.

Requires at least 4.10.

func (*Program) IsPinned added in v0.4.0

func (p *Program) IsPinned() bool

IsPinned returns true if the Program has a non-empty pinned path.

func (*Program) Pin

func (p *Program) Pin(fileName string) error

Pin persists the Program on the BPF virtual file system past the lifetime of the process that created it

Calling Pin on a previously pinned program will overwrite the path, except when the new path already exists. Re-pinning across filesystems is not supported.

This requires bpffs to be mounted above fileName. See https://docs.cilium.io/en/stable/network/kubernetes/configuration/#mounting-bpffs-with-systemd

func (*Program) Run added in v0.9.1

func (p *Program) Run(opts *RunOptions) (uint32, error)

Run runs the Program in kernel with given RunOptions.

Note: the same restrictions from Test apply.

func (*Program) String

func (p *Program) String() string

func (*Program) Test

func (p *Program) Test(in []byte) (uint32, []byte, error)

Test runs the Program in the kernel with the given input and returns the value returned by the eBPF program.

Note: the kernel expects at least 14 bytes input for an ethernet header for XDP and SKB programs.

This function requires at least Linux 4.12.

func (*Program) Type

func (p *Program) Type() ProgramType

Type returns the underlying type of the program.

func (*Program) Unpin added in v0.4.0

func (p *Program) Unpin() error

Unpin removes the persisted state for the Program from the BPF virtual filesystem.

Failed calls to Unpin will not alter the state returned by IsPinned.

Unpinning an unpinned Program returns nil.

type ProgramID

type ProgramID uint32

ProgramID represents the unique ID of an eBPF program.

func ProgramGetNextID

func ProgramGetNextID(startID ProgramID) (ProgramID, error)

ProgramGetNextID returns the ID of the next eBPF program.

Returns ErrNotExist, if there is no next eBPF program.

type ProgramInfo added in v0.3.0

type ProgramInfo struct {
	Type ProgramType

	// Truncated hash of the BPF bytecode. Available from 4.13.
	Tag string
	// Name as supplied by user space at load time. Available from 4.15.
	Name string
	// contains filtered or unexported fields
}

ProgramInfo describes a program.

func (*ProgramInfo) BTFID added in v0.7.0

func (pi *ProgramInfo) BTFID() (btf.ID, bool)

BTFID returns the BTF ID associated with the program.

The ID is only valid as long as the associated program is kept alive. Available from 5.0.

The bool return value indicates whether this optional field is available and populated. (The field may be available but not populated if the kernel supports the field but the program was loaded without BTF information.)

func (*ProgramInfo) CreatedByUID added in v0.11.0

func (pi *ProgramInfo) CreatedByUID() (uint32, bool)

CreatedByUID returns the Uid that created the program.

Available from 4.15.

The bool return value indicates whether this optional field is available.

func (*ProgramInfo) FuncInfos added in v0.17.0

func (pi *ProgramInfo) FuncInfos() (btf.FuncOffsets, error)

FuncInfos returns the offset and function information of all (sub)programs in a BPF program.

Available from 5.0.

Requires CAP_SYS_ADMIN or equivalent for reading BTF information. Returns ErrNotSupported if the program was created without BTF or if the kernel doesn't support the field.

func (*ProgramInfo) ID added in v0.4.0

func (pi *ProgramInfo) ID() (ProgramID, bool)

ID returns the program ID.

Available from 4.13.

The bool return value indicates whether this optional field is available.

func (*ProgramInfo) Instructions added in v0.8.0

func (pi *ProgramInfo) Instructions() (asm.Instructions, error)

Instructions returns the 'xlated' instruction stream of the program after it has been verified and rewritten by the kernel. These instructions cannot be loaded back into the kernel as-is, this is mainly used for inspecting loaded programs for troubleshooting, dumping, etc.

For example, map accesses are made to reference their kernel map IDs, not the FDs they had when the program was inserted. Note that before the introduction of bpf_insn_prepare_dump in kernel 4.16, xlated instructions were not sanitized, making the output even less reusable and less likely to round-trip or evaluate to the same program Tag.

The first instruction is marked as a symbol using the Program's name.

If available, the instructions will be annotated with metadata from the BTF. This includes line information and function information. Reading this metadata requires CAP_SYS_ADMIN or equivalent. If capability is unavailable, the instructions will be returned without metadata.

Available from 4.13. Requires CAP_BPF or equivalent for plain instructions. Requires CAP_SYS_ADMIN for instructions with metadata.

func (*ProgramInfo) JitedFuncLens added in v0.17.0

func (pi *ProgramInfo) JitedFuncLens() ([]uint32, bool)

JitedFuncLens returns the insns length of each function in the JITed program.

Available from 4.18.

The bool return value indicates whether this optional field is available.

func (*ProgramInfo) JitedInsns added in v0.17.0

func (pi *ProgramInfo) JitedInsns() ([]byte, bool)

JitedInsns returns the JITed machine native instructions of the program.

Available from 4.13.

The bool return value indicates whether this optional field is available.

func (*ProgramInfo) JitedKsymAddrs added in v0.17.0

func (pi *ProgramInfo) JitedKsymAddrs() ([]uintptr, bool)

JitedKsymAddrs returns the ksym addresses of the BPF program, including its subprograms. The addresses correspond to their symbols in /proc/kallsyms.

Available from 4.18. Note that before 5.x, this field can be empty for programs without subprograms (bpf2bpf calls).

The bool return value indicates whether this optional field is available.

func (*ProgramInfo) JitedLineInfos added in v0.17.0

func (pi *ProgramInfo) JitedLineInfos() ([]uint64, bool)

JitedLineInfos returns the JITed line infos of the program.

Available from 5.0.

The bool return value indicates whether this optional field is available.

func (*ProgramInfo) JitedSize added in v0.17.0

func (pi *ProgramInfo) JitedSize() (uint32, error)

JitedSize returns the size of the program's JIT-compiled machine code in bytes, which is the actual code executed on the host's CPU. This field requires the BPF JIT compiler to be enabled.

Available from 4.13. Reading this metadata requires CAP_BPF or equivalent.

func (*ProgramInfo) LineInfos added in v0.17.0

func (pi *ProgramInfo) LineInfos() (btf.LineOffsets, error)

LineInfos returns the BTF line information of the program.

Available from 5.0.

Requires CAP_SYS_ADMIN or equivalent for reading BTF information. Returns ErrNotSupported if the program was created without BTF or if the kernel doesn't support the field.

func (*ProgramInfo) LoadTime added in v0.17.0

func (pi *ProgramInfo) LoadTime() (time.Duration, bool)

LoadTime returns when the program was loaded since boot time.

Available from 4.15.

The bool return value indicates whether this optional field is available.

func (*ProgramInfo) MapIDs added in v0.7.0

func (pi *ProgramInfo) MapIDs() ([]MapID, bool)

MapIDs returns the maps related to the program.

Available from 4.15.

The bool return value indicates whether this optional field is available.

func (*ProgramInfo) RecursionMisses added in v0.16.0

func (pi *ProgramInfo) RecursionMisses() (uint64, bool)

RecursionMisses returns the total number of times the program was NOT called. This can happen when another bpf program is already running on the cpu, which is likely to happen for example when you interrupt bpf program execution.

func (*ProgramInfo) RunCount added in v0.4.0

func (pi *ProgramInfo) RunCount() (uint64, bool)

RunCount returns the total number of times the program was called.

Can return 0 if the collection of statistics is not enabled. See EnableStats(). The bool return value indicates whether this optional field is available.

func (*ProgramInfo) Runtime added in v0.4.0

func (pi *ProgramInfo) Runtime() (time.Duration, bool)

Runtime returns the total accumulated runtime of the program.

Can return 0 if the collection of statistics is not enabled. See EnableStats(). The bool return value indicates whether this optional field is available.

func (*ProgramInfo) TranslatedSize added in v0.17.0

func (pi *ProgramInfo) TranslatedSize() (int, error)

TranslatedSize returns the size of the program's translated instructions in bytes, after it has been verified and rewritten by the kernel.

Available from 4.13. Reading this metadata requires CAP_BPF or equivalent.

func (*ProgramInfo) VerifiedInstructions added in v0.17.0

func (pi *ProgramInfo) VerifiedInstructions() (uint32, bool)

VerifiedInstructions returns the number verified instructions in the program.

Available from 5.16.

The bool return value indicates whether this optional field is available.

type ProgramOptions

type ProgramOptions struct {
	// Bitmap controlling the detail emitted by the kernel's eBPF verifier log.
	// LogLevel-type values can be ORed together to request specific kinds of
	// verifier output. See the documentation on [ebpf.LogLevel] for details.
	//
	//  opts.LogLevel = (ebpf.LogLevelBranch | ebpf.LogLevelStats)
	//
	// If left to its default value, the program will first be loaded without
	// verifier output enabled. Upon error, the program load will be repeated
	// with LogLevelBranch and the given (or default) LogSize value.
	//
	// Unless LogDisabled is set, setting this to a non-zero value will enable the verifier
	// log, populating the [ebpf.Program.VerifierLog] field on successful loads
	// and including detailed verifier errors if the program is rejected. This
	// will always allocate an output buffer, but will result in only a single
	// attempt at loading the program.
	LogLevel LogLevel

	// Starting size of the verifier log buffer. If the verifier log is larger
	// than this size, the buffer will be grown to fit the entire log. Leave at
	// its default value unless troubleshooting.
	LogSizeStart uint32

	// Disables the verifier log completely, regardless of other options.
	LogDisabled bool

	// Type information used for CO-RE relocations.
	//
	// This is useful in environments where the kernel BTF is not available
	// (containers) or where it is in a non-standard location. Defaults to
	// use the kernel BTF from a well-known location if nil.
	KernelTypes *btf.Spec

	// Type information used for CO-RE relocations of kernel modules,
	// indexed by module name.
	//
	// This is useful in environments where the kernel BTF is not available
	// (containers) or where it is in a non-standard location. Defaults to
	// use the kernel module BTF from a well-known location if nil.
	KernelModuleTypes map[string]*btf.Spec
}

ProgramOptions control loading a program into the kernel.

type ProgramSpec

type ProgramSpec struct {
	// Name is passed to the kernel as a debug aid. Must only contain
	// alpha numeric and '_' characters.
	Name string

	// Type determines at which hook in the kernel a program will run.
	Type ProgramType

	// AttachType of the program, needed to differentiate allowed context
	// accesses in some newer program types like CGroupSockAddr.
	//
	// Available on kernels 4.17 and later.
	AttachType AttachType

	// Name of a kernel data structure or function to attach to. Its
	// interpretation depends on Type and AttachType.
	AttachTo string

	// The program to attach to. Must be provided manually.
	AttachTarget *Program

	// The name of the ELF section this program originated from.
	SectionName string

	Instructions asm.Instructions

	// Flags is passed to the kernel and specifies additional program
	// load attributes.
	Flags uint32

	// License of the program. Some helpers are only available if
	// the license is deemed compatible with the GPL.
	//
	// See https://www.kernel.org/doc/html/latest/process/license-rules.html#id1
	License string

	// Version used by Kprobe programs.
	//
	// Deprecated on kernels 5.0 and later. Leave empty to let the library
	// detect this value automatically.
	KernelVersion uint32

	// The byte order this program was compiled for, may be nil.
	ByteOrder binary.ByteOrder
}

ProgramSpec defines a Program.

func (*ProgramSpec) Copy

func (ps *ProgramSpec) Copy() *ProgramSpec

Copy returns a copy of the spec.

func (*ProgramSpec) Tag added in v0.4.0

func (ps *ProgramSpec) Tag() (string, error)

Tag calculates the kernel tag for a series of instructions.

Use asm.Instructions.Tag if you need to calculate for non-native endianness.

Example
spec := &ProgramSpec{
	Type: SocketFilter,
	Instructions: asm.Instructions{
		asm.LoadImm(asm.R0, 0, asm.DWord),
		asm.Return(),
	},
	License: "MIT",
}

prog, _ := NewProgram(spec)
info, _ := prog.Info()
tag, _ := spec.Tag()

if info.Tag != tag {
	fmt.Printf("The tags don't match: %s != %s\n", info.Tag, tag)
} else {
	fmt.Println("The programs are identical, tag is", tag)
}
Output:

type ProgramType

type ProgramType uint32

ProgramType of the eBPF program

func (ProgramType) String

func (i ProgramType) String() string

type RunOptions added in v0.9.1

type RunOptions struct {
	// Program's data input. Required field.
	//
	// The kernel expects at least 14 bytes input for an ethernet header for
	// XDP and SKB programs.
	Data []byte
	// Program's data after Program has run. Caller must allocate. Optional field.
	DataOut []byte
	// Program's context input. Optional field.
	Context interface{}
	// Program's context after Program has run. Must be a pointer or slice. Optional field.
	ContextOut interface{}
	// Minimum number of times to run Program. Optional field. Defaults to 1.
	//
	// The program may be executed more often than this due to interruptions, e.g.
	// when runtime.AllThreadsSyscall is invoked.
	Repeat uint32
	// Optional flags.
	Flags uint32
	// CPU to run Program on. Optional field.
	// Note not all program types support this field.
	CPU uint32
	// Called whenever the syscall is interrupted, and should be set to testing.B.ResetTimer
	// or similar. Typically used during benchmarking. Optional field.
	//
	// Deprecated: use [testing.B.ReportMetric] with unit "ns/op" instead.
	Reset func()
}

Various options for Run'ing a Program

type Variable added in v0.17.0

type Variable struct {
	// contains filtered or unexported fields
}

Variable is a convenience wrapper for modifying global variables of a Collection after loading it into the kernel. Operations on a Variable are performed using direct memory access, bypassing the BPF map syscall API.

On kernels older than 5.5, most interactions with Variable return ErrNotSupported.

func (*Variable) Get added in v0.17.0

func (v *Variable) Get(out any) error

Get writes the value of the Variable to the provided output. The output must be a pointer to a value whose size matches the Variable.

func (*Variable) ReadOnly added in v0.17.0

func (v *Variable) ReadOnly() bool

ReadOnly returns true if the Variable represents a variable that is read-only after loading the Collection into the kernel.

On systems without BPF_F_MMAPABLE support, ReadOnly always returns true.

func (*Variable) Set added in v0.17.0

func (v *Variable) Set(in any) error

Set the value of the Variable to the provided input. The input must marshal to the same length as the size of the Variable.

func (*Variable) Size added in v0.17.0

func (v *Variable) Size() uint64

Size returns the size of the variable.

func (*Variable) String added in v0.17.0

func (v *Variable) String() string

func (*Variable) Type added in v0.17.0

func (v *Variable) Type() *btf.Var

Type returns the btf.Var representing the variable in its data section. This is useful for inspecting the variable's decl tags and the type information of the inner type.

Returns nil if the original ELF object did not contain BTF information.

type VariableSpec added in v0.17.0

type VariableSpec struct {
	// contains filtered or unexported fields
}

VariableSpec is a convenience wrapper for modifying global variables of a CollectionSpec before loading it into the kernel.

All operations on a VariableSpec's underlying MapSpec are performed in the host's native endianness.

func (*VariableSpec) Constant added in v0.17.0

func (s *VariableSpec) Constant() bool

Constant returns true if the VariableSpec represents a variable that is read-only from the perspective of the BPF program.

func (*VariableSpec) Get added in v0.17.0

func (s *VariableSpec) Get(out any) error

Get writes the value of the VariableSpec to the provided output using the host's native endianness.

func (*VariableSpec) MapName added in v0.17.0

func (s *VariableSpec) MapName() string

MapName returns the name of the underlying MapSpec.

func (*VariableSpec) Offset added in v0.17.0

func (s *VariableSpec) Offset() uint64

Offset returns the offset of the variable in the underlying MapSpec.

func (*VariableSpec) Set added in v0.17.0

func (s *VariableSpec) Set(in any) error

Set sets the value of the VariableSpec to the provided input using the host's native endianness.

func (*VariableSpec) Size added in v0.17.0

func (s *VariableSpec) Size() uint64

Size returns the size of the variable in bytes.

func (*VariableSpec) String added in v0.17.0

func (s *VariableSpec) String() string

func (*VariableSpec) Type added in v0.17.0

func (s *VariableSpec) Type() *btf.Var

Type returns the btf.Var representing the variable in its data section. This is useful for inspecting the variable's decl tags and the type information of the inner type.

Returns nil if the original ELF object did not contain BTF information.

type VerifierError added in v0.9.1

type VerifierError = internal.VerifierError

VerifierError is returned by NewProgram and NewProgramWithOptions if a program is rejected by the verifier.

Use errors.As to access the error.

Example

VerifierLog understands a variety of formatting flags.

err := internal.ErrorWithLog(
	"catastrophe",
	syscall.ENOSPC,
	[]byte("first\nsecond\nthird"),
)

fmt.Printf("With %%s: %s\n", err)
fmt.Printf("All log lines: %+v\n", err)
fmt.Printf("First line: %+1v\n", err)
fmt.Printf("Last two lines: %-2v\n", err)
Output:

With %s: catastrophe: no space left on device: third (2 line(s) omitted)
All log lines: catastrophe: no space left on device:
	first
	second
	third
First line: catastrophe: no space left on device:
	first
	(2 line(s) omitted)
Last two lines: catastrophe: no space left on device:
	(1 line(s) omitted)
	second
	third
Example (RetrieveFullLog)

Print the full verifier log when loading a program fails.

_, err := NewProgram(&ProgramSpec{
	Type: SocketFilter,
	Instructions: asm.Instructions{
		asm.LoadImm(asm.R0, 0, asm.DWord),
		// Missing Return
	},
	License: "MIT",
})

var ve *VerifierError
if errors.As(err, &ve) {
	// Using %+v will print the whole verifier error, not just the last
	// few lines.
	fmt.Printf("Verifier error: %+v\n", ve)
}
Output:

Directories

Path Synopsis
Package asm is an assembler for eBPF bytecode.
Package asm is an assembler for eBPF bytecode.
Package btf handles data encoded according to the BPF Type Format.
Package btf handles data encoded according to the BPF Type Format.
cmd
bpf2go
Program bpf2go embeds eBPF in Go.
Program bpf2go embeds eBPF in Go.
bpf2go/gen
Package gen contains utilities to generate Go bindings for eBPF ELF files.
Package gen contains utilities to generate Go bindings for eBPF ELF files.
bpf2go/test
Package test checks that the code generated by bpf2go conforms to a specific API.
Package test checks that the code generated by bpf2go conforms to a specific API.
docs
examples/getting_started
getting_started_gen {
getting_started_gen {
examples module
cgroup_skb
This program demonstrates attaching an eBPF program to a control group.
This program demonstrates attaching an eBPF program to a control group.
kprobe
This program demonstrates attaching an eBPF program to a kernel symbol.
This program demonstrates attaching an eBPF program to a kernel symbol.
kprobe_percpu
This program demonstrates attaching an eBPF program to a kernel symbol and using percpu map to collect data.
This program demonstrates attaching an eBPF program to a kernel symbol and using percpu map to collect data.
kprobepin
This program demonstrates attaching an eBPF program to a kernel symbol.
This program demonstrates attaching an eBPF program to a kernel symbol.
map_in_map
An example of using maps within maps.
An example of using maps within maps.
tcx
This program demonstrates attaching an eBPF program to a network interface with Linux TCX (Traffic Control with eBPF).
This program demonstrates attaching an eBPF program to a network interface with Linux TCX (Traffic Control with eBPF).
tracepoint_in_c
This program demonstrates attaching an eBPF program to a kernel tracepoint.
This program demonstrates attaching an eBPF program to a kernel tracepoint.
tracepoint_in_go
This program demonstrates how to attach an eBPF program to a tracepoint.
This program demonstrates how to attach an eBPF program to a tracepoint.
xdp
This program demonstrates attaching an eBPF program to a network interface with XDP (eXpress Data Path).
This program demonstrates attaching an eBPF program to a network interface with XDP (eXpress Data Path).
Package features allows probing for BPF features available to the calling process.
Package features allows probing for BPF features available to the calling process.
cmd/gentypes
Program gentypes reads a compressed vmlinux .BTF section and generates syscall bindings from it.
Program gentypes reads a compressed vmlinux .BTF section and generates syscall bindings from it.
kconfig
Package kconfig implements a parser for the format of Linux's .config file.
Package kconfig implements a parser for the format of Linux's .config file.
linux
Package linux contains OS specific wrappers around package unix.
Package linux contains OS specific wrappers around package unix.
sys
Package sys contains bindings for the BPF syscall.
Package sys contains bindings for the BPF syscall.
sysenc
Package sysenc provides efficient conversion of Go values to system call interfaces.
Package sysenc provides efficient conversion of Go values to system call interfaces.
unix
Package unix re-exports Linux specific parts of golang.org/x/sys/unix.
Package unix re-exports Linux specific parts of golang.org/x/sys/unix.
Package link allows attaching eBPF programs to various kernel hooks.
Package link allows attaching eBPF programs to various kernel hooks.
Package perf allows reading from BPF perf event arrays.
Package perf allows reading from BPF perf event arrays.
Package ringbuf allows interacting with Linux BPF ring buffer.
Package ringbuf allows interacting with Linux BPF ring buffer.
Package rlimit allows raising RLIMIT_MEMLOCK if necessary for the use of BPF.
Package rlimit allows raising RLIMIT_MEMLOCK if necessary for the use of BPF.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL