Back to godoc.org
github.com/cilium/ebpf

Package ebpf

v0.0.0 (6445519)
Latest Go to latest
Published: today | License: MIT | Module: github.com/cilium/ebpf

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.

Example (CustomMarshaler)

ExampleMarshaler shows how to use custom encoding with map methods.

Code:

package ebpf

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 Example_customMarshaler() {
	hash := createHash()
	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)
	}

	
key: HELLO, value: 111
Example (ExtractDistance)

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

Code:

package ebpf_test

// 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 Example_extractDistance() {
	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).Sym("ipv6"),
		asm.LoadAbs(-0x100000+7, asm.Byte),

		// stash the load result into FP[-4]
		asm.StoreMem(asm.RFP, -4, asm.R0, asm.Word).Sym("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()).Sym("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).Sym("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()
}
Example (SocketELF)

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

Code:

// +build linux

package ebpf_test

import (
	"bytes"
	"flag"
	"fmt"
	"syscall"
	"time"

	"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 Example_socketELF() {
	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) {
	const ETH_P_ALL uint16 = 0x00<<8 | 0x03
	sock, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, int(ETH_P_ALL))
	if err != nil {
		return 0, err
	}
	sll := syscall.SockaddrLinklayer{}
	sll.Protocol = ETH_P_ALL
	sll.Ifindex = index
	if err := syscall.Bind(sock, &sll); err != nil {
		return 0, err
	}
	return sock, nil
}
Example (Tracepoint)

This demonstrates how to attach an eBPF program to a tracepoint. The program will be attached to the sys_enter_open syscall and print out the integer 123 everytime the sycall is used.

Code:

// +build linux

package ebpf_test

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
	"time"

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

	"golang.org/x/sys/unix"
)

// getTracepointID returns the system specific ID for the tracepoint sys_enter_open.
func getTracepointID() (uint64, error) {
	data, err := ioutil.ReadFile("/sys/kernel/debug/tracing/events/syscalls/sys_enter_open/id")
	if err != nil {
		return 0, fmt.Errorf("failed to read tracepoint ID for 'sys_enter_open': %v", err)
	}
	tid := strings.TrimSuffix(string(data), "\n")
	return strconv.ParseUint(tid, 10, 64)
}

// This demonstrates how to attach an eBPF program to a tracepoint.
// The program will be attached to the sys_enter_open syscall and print out the integer
// 123 everytime the sycall is used.
func Example_tracepoint() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	events, err := ebpf.NewMap(&ebpf.MapSpec{
		Type: ebpf.PerfEventArray,
		Name: "pureGo",
	})
	if err != nil {
		panic(fmt.Errorf("could not create event map: %v\n", err))
	}
	defer events.Close()

	rd, err := perf.NewReader(events, os.Getpagesize())
	if err != nil {
		panic(fmt.Errorf("could not create event reader: %v", err))
	}
	defer rd.Close()

	go func() {
		for {
			select {
			case <-ctx.Done():
				return
			default:
			}
			record, err := rd.Read()
			if err != nil {
				if perf.IsClosed(err) {
					return
				}
				panic(fmt.Errorf("could not read from reader: %v", err))
			}
			fmt.Println(record)
		}
	}()

	ins := asm.Instructions{
		// store the integer 123 at FP[-8]
		asm.Mov.Imm(asm.R2, 123),
		asm.StoreMem(asm.RFP, -8, asm.R2, asm.Word),

		// load registers with arguments for call of FnPerfEventOutput
		asm.LoadMapPtr(asm.R2, events.FD()),
		asm.LoadImm(asm.R3, 0xffffffff, asm.DWord),
		asm.Mov.Reg(asm.R4, asm.RFP),
		asm.Add.Imm(asm.R4, -8),
		asm.Mov.Imm(asm.R5, 4),

		// call FnPerfEventOutput
		asm.FnPerfEventOutput.Call(),

		// set exit code to 0
		asm.Mov.Imm(asm.R0, 0),
		asm.Return(),
	}

	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
		Name:         "sys_enter_open",
		Type:         ebpf.TracePoint,
		License:      "GPL",
		Instructions: ins,
	})
	if err != nil {
		panic(fmt.Errorf("could not create new ebpf program: %v", err))
	}
	defer prog.Close()

	tid, err := getTracepointID()
	if err != nil {
		panic(fmt.Errorf("could not get tracepoint id: %v", err))
	}

	attr := unix.PerfEventAttr{
		Type:        unix.PERF_TYPE_TRACEPOINT,
		Config:      tid,
		Sample_type: unix.PERF_SAMPLE_RAW,
		Sample:      1,
		Wakeup:      1,
	}
	pfd, err := unix.PerfEventOpen(&attr, -1, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
	if err != nil {
		panic(fmt.Errorf("unable to open perf events: %v", err))
	}
	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(pfd), unix.PERF_EVENT_IOC_ENABLE, 0); errno != 0 {
		panic(fmt.Errorf("unable to enable perf events: %v", err))
	}
	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(pfd), unix.PERF_EVENT_IOC_SET_BPF, uintptr(prog.FD())); errno != 0 {
		panic(fmt.Errorf("unable to attach bpf program to perf events: %v", err))
	}

	<-ctx.Done()

	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(pfd), unix.PERF_EVENT_IOC_DISABLE, 0); errno != 0 {
		panic(fmt.Errorf("unable to disable perf events: %v", err))
	}
}

Index

Examples

Package Files

Constants

const DefaultVerifierLogSize = 64 * 1024

DefaultVerifierLogSize is the default number of bytes allocated for the verifier log.

Variables

var (
	ErrKeyNotExist      = errors.New("key does not exist")
	ErrKeyExist         = errors.New("key already exists")
	ErrIterationAborted = errors.New("iteration aborted")
)

Errors returned by Map and MapIterator methods.

var (
	ErrNotExist = errors.New("requested object does not exist")
)

Generic errors returned by BPF syscalls.

var ErrNotSupported = internal.ErrNotSupported

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

func SanitizeName

func SanitizeName(name string, replacement rune) string

SanitizeName replaces all invalid characters in name.

Use this to automatically generate valid names for maps and programs at run time.

Passing a negative value for replacement will delete characters instead of replacing them.

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 (
	AttachCGroupInetIngress AttachType = iota
	AttachCGroupInetEgress
	AttachCGroupInetSockCreate
	AttachCGroupSockOps
	AttachSkSKBStreamParser
	AttachSkSKBStreamVerdict
	AttachCGroupDevice
	AttachSkMsgVerdict
	AttachCGroupInet4Bind
	AttachCGroupInet6Bind
	AttachCGroupInet4Connect
	AttachCGroupInet6Connect
	AttachCGroupInet4PostBind
	AttachCGroupInet6PostBind
	AttachCGroupUDP4Sendmsg
	AttachCGroupUDP6Sendmsg
	AttachLircMode2
	AttachFlowDissector
	AttachCGroupSysctl
	AttachCGroupUDP4Recvmsg
	AttachCGroupUDP6Recvmsg
	AttachCGroupGetsockopt
	AttachCGroupSetsockopt
	AttachTraceRawTp
	AttachTraceFEntry
	AttachTraceFExit
	AttachModifyReturn
	AttachLSMMac
	AttachTraceIter
	AttachCgroupInet4GetPeername
	AttachCgroupInet6GetPeername
	AttachCgroupInet4GetSockname
	AttachCgroupInet6GetSockname
	AttachXDPDevMap
	AttachCgroupInetSockRelease
	AttachXDPCPUMap
	AttachSkLookup
	AttachXDP
)
const AttachNone AttachType = 0

AttachNone is an alias for AttachCGroupInetIngress for readability reasons

func (AttachType) String

func (i AttachType) String() string

type Collection

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

Collection is a collection of Programs and Maps associated with their symbols

func LoadCollection

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

LoadCollection parses an object file and converts it to a collection.

func NewCollection

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

NewCollection creates a Collection from a specification.

Only maps referenced by at least one of the programs are initialized.

func NewCollectionWithOptions

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

NewCollectionWithOptions creates a Collection from a specification.

Only maps referenced by at least one of the programs are initialized.

func (*Collection) Assign

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

Assign the contents of a collection to a struct.

`to` must be a pointer to a struct like the following:

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

See CollectionSpec.Assign for the semantics of this function.

DetachMap and DetachProgram is invoked for all assigned elements if the function is successful.

Example

Code:

coll, err := NewCollection(&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",
		},
	},
})
if err != nil {
	panic(err)
}

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

if err := coll.Assign(&objs); err != nil {
	panic(err)
}

fmt.Println(objs.Program.ABI().Type)
fmt.Println(objs.Map.ABI().Type)
SocketFilter
Array

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 {
	Programs ProgramOptions
}

CollectionOptions control loading a collection into the kernel.

type CollectionSpec

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

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 collection spec to a struct.

This function is a short-cut to manually checking the presence of maps and programs in a collection spec.

The argument 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 *ProgramSpec or *MapSpec. The tag gives 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"`
    Ignored int
}

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

Example

Code:

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 specs struct {
	Program *ProgramSpec `ebpf:"prog1"`
	Map     *MapSpec     `ebpf:"map1"`
}

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

fmt.Println(specs.Program.Type)
fmt.Println(specs.Map.Type)
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 creates a collection from a spec, and assigns it to a struct.

See Collection.Assign for details.

Example

Code:

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)
}

fmt.Println(objs.Program.ABI().Type)
fmt.Println(objs.Map.ABI().Type)
SocketFilter
Array

func (*CollectionSpec) RewriteConstants

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:

static volatile const type foobar;
static 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 if a constant doesn't exist.

func (*CollectionSpec) RewriteMaps

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.

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.

Code:

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

first := []uint32{4, 5}
if err := arr.Put(uint32(0), first); err != nil {
	panic(err)
}

second := []uint32{2, 8}
if err := arr.Put(uint32(1), second); err != nil {
	panic(err)
}

var values []uint32
if err := arr.Lookup(uint32(0), &values); err != nil {
	panic(err)
}
fmt.Println("First two values:", values[:2])

var (
	key     uint32
	entries = arr.Iterate()
)

for entries.Next(&key, &values) {
	// NB: sum can overflow, real code should check for this
	var sum uint32
	for _, n := range values {
		sum += n
	}
	fmt.Printf("Sum of %d: %d\n", key, sum)
}

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

It is possible to use unsafe.Pointer to avoid marshalling and copy overhead. It is the resposibility 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.

Code:

hash := createHash()
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)
The value is: 23

func LoadPinnedMap

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

LoadPinnedMap load a Map from a BPF file.

The function is not compatible with nested maps. Use LoadPinnedMapExplicit in these situations.

func LoadPinnedMapExplicit

func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error)

LoadPinnedMapExplicit loads a map with explicit parameters.

func NewMap

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

NewMap 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 unix.Setrlimit with unix.RLIMIT_MEMLOCK prior to calling NewMap.

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 (*Map) ABI

func (m *Map) ABI() MapABI

ABI gets the ABI of the Map

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.

Cloning a nil Map returns nil.

func (*Map) Close

func (m *Map) Close() error

Close removes a Map

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) 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) ID

func (m *Map) ID() (MapID, error)

ID returns the systemwide unique ID of the map.

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.

Code:

hash := createHash()
defer hash.Close()

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

if err := hash.Put("world", uint32(42)); err != nil {
	panic(err)
}

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

for entries.Next(&key, &value) {

	fmt.Printf("key: %s, value: %d\n", key, value)
}

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

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

Code:

var arrayOfMaps *Map // Set this up somehow

var (
	key     uint32
	m       *Map
	entries = arrayOfMaps.Iterate()
)

defer m.Close()

for entries.Next(&key, &m) {

	fmt.Printf("key: %v, map: %v\n", key, m)
}

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

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 IsNotExist.

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) 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) MarshalBinary

func (m *Map) MarshalBinary() ([]byte, error)

MarshalBinary implements BinaryMarshaler.

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

Code:

hash := createHash()
defer hash.Close()

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

if err := hash.Put("world", uint32(42)); err != nil {
	panic(err)
}

var firstKey string
if err := hash.NextKey(nil, &firstKey); err != nil {
	panic(err)
}

var nextKey string
if err := hash.NextKey(firstKey, &nextKey); err != nil {
	panic(err)
}

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 past the lifetime of the process that created it.

This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional

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) Update

func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error

Update changes the value of a key.

type MapABI

type MapABI struct {
	Type       MapType
	KeySize    uint32
	ValueSize  uint32
	MaxEntries uint32
	Flags      uint32
}

MapABI are the attributes of a Map which are available across all supported kernels.

func (*MapABI) Equal

func (abi *MapABI) Equal(other *MapABI) bool

Equal returns true if two ABIs have the same values.

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 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 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      uint32

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

	// Whether to freeze a map after setting its initial contents.
	Freeze bool

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

	// The BTF associated with this map.
	BTF *btf.Map
}

MapSpec defines a Map.

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 thow 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
)

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
)

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 (UnmarshalFromMap)

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

Code:

progArray, err := LoadPinnedMap("/path/to/map")
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)
}

func LoadPinnedProgram

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

LoadPinnedProgram loads a Program from a BPF file.

Requires at least Linux 4.11.

func NewProgram

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

NewProgram creates a new Program.

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

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.11.

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.

Example

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.

Code:

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

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

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

func (*Program) ABI

func (p *Program) ABI() ProgramABI

ABI gets the ABI of the Program

func (*Program) Attach

func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error

Attach a Program.

Deprecated: use link.RawAttachProgram instead.

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.

Note: profiling a call to this function will skew it's results, see https://github.com/cilium/ebpf/issues/24

This function requires at least Linux 4.12.

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 unloads the program from the kernel.

func (*Program) Detach

func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error

Detach a Program.

Deprecated: use link.RawDetachProgram instead.

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) ID

func (p *Program) ID() (ProgramID, error)

ID returns the systemwide unique ID of the program.

func (*Program) MarshalBinary

func (p *Program) MarshalBinary() ([]byte, error)

MarshalBinary implements BinaryMarshaler.

func (*Program) Pin

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

Pin persists the Program past the lifetime of the process that created it

This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional

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. outLen may be zero.

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.

type ProgramABI

type ProgramABI struct {
	Type ProgramType
}

ProgramABI are the attributes of a Program which are available across all supported kernels.

func (*ProgramABI) Equal

func (abi *ProgramABI) Equal(other *ProgramABI) bool

Equal returns true if two ABIs have the same values.

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 ProgramOptions

type ProgramOptions struct {
	// Controls the detail emitted by the kernel verifier. Set to non-zero
	// to enable logging.
	LogLevel uint32
	// Controls the output buffer size for the verifier. Defaults to
	// DefaultVerifierLogSize.
	LogSize int
}

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 AttachType
	// Name of a kernel data structure to attach to. It's interpretation
	// depends on Type and AttachType.
	AttachTo     string
	Instructions asm.Instructions

	// 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 tracing programs.
	//
	// Deprecated: superseded by BTF.
	KernelVersion uint32

	// The BTF associated with this program. Changing Instructions
	// will most likely invalidate the contained data, and may
	// result in errors when attempting to load it into the kernel.
	BTF *btf.Program

	// 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.

type ProgramType

type ProgramType uint32

ProgramType of the eBPF program

const (
	UnspecifiedProgram ProgramType = iota
	SocketFilter
	Kprobe
	SchedCLS
	SchedACT
	TracePoint
	XDP
	PerfEvent
	CGroupSKB
	CGroupSock
	LWTIn
	LWTOut
	LWTXmit
	SockOps
	SkSKB
	CGroupDevice
	SkMsg
	RawTracepoint
	CGroupSockAddr
	LWTSeg6Local
	LircMode2
	SkReuseport
	FlowDissector
	CGroupSysctl
	RawTracepointWritable
	CGroupSockopt
	Tracing
	StructOps
	Extension
	LSM
	SkLookup
)

eBPF program types

func (ProgramType) String

func (i ProgramType) String() string
Documentation was rendered with GOOS=linux and GOARCH=amd64.

Jump to identifier

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to identifier