Skip to content

dropbox/goebpf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

76 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go eBPF

Build Status Go Report Card Documentation

A nice and convenient way to work with eBPF programs / perf events from Go.

Requirements

  • Go 1.11+
  • Linux Kernel 4.15+

Supported eBPF features

  • eBPF programs
    • SocketFilter
    • XDP
    • Kprobe / Kretprobe
    • tc-cls (tc-act is partially implemented, currently)
  • Perf Events

Support for other program types / features can be added in future. Meanwhile your contributions are warmly welcomed.. :)

Installation

# Main library
go get github.com/dropbox/goebpf

# Mock version (if needed)
go get github.com/dropbox/goebpf/goebpf_mock

Quick start

Consider very simple example of Read / Load / Attach

    // In order to be simple this examples does not handle errors
    bpf := goebpf.NewDefaultEbpfSystem()
    // Read clang compiled binary
    bpf.LoadElf("test.elf")
    // Load XDP program into kernel (name matches function name in C)
    xdp := bpf.GetProgramByName("xdp_test")
    xdp.Load()
    // Attach to interface
    xdp.Attach("eth0")
    defer xdp.Detach()
    // Work with maps
    test := bpf.GetMapByName("test")
    value, _ := test.LookupInt(0)
    fmt.Printf("Value at index 0 of map 'test': %d\n", value)

Like it? Check our examples

Perf Events

Currently library has support for one, most popular use case of perf_events: where eBPF map key maps to cpu_id. So eBPF and go parts actually bind cpu_id to map index. It maybe as simple as:

    // Define special, perf_events map where key maps to CPU_ID
    BPF_MAP_DEF(perfmap) = {
        .map_type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
        .max_entries = 128,     // Max supported CPUs
    };
    BPF_MAP_ADD(perfmap);

    // ...

    // Emit perf event with "data" to map "perfmap" where index is current CPU_ID
    bpf_perf_event_output(ctx, &perfmap, BPF_F_CURRENT_CPU, &data, sizeof(data));

And the go part:

    perf, err := goebpf.NewPerfEvents("perfmap")
    // 4096 is ring buffer size
    perfEvents, err := perf.StartForAllProcessesAndCPUs(4096)
    defer perf.Stop()

    for {
        select {
            case data := <-perfEvents:
                fmt.Println(data)
        }
    }

Looks simple? Check our full XDP dump example

Kprobes

Library currently has support for kprobes and kretprobes. It can be as simple as:

    // kprobe handler function
    SEC("kprobe/guess_execve")
    int execve_entry(struct pt_regs *ctx) {
      // ...
      buf_perf_output(ctx);
      return 0;
    }

And the go part:

	// Cleanup old probes
	err := goebpf.CleanupProbes()

	// Attach all probe programs
	for _, prog := range bpf.GetPrograms() {
		err := prog.Attach(nil)
	}

	// Create perf events
	eventsMap := p.bpf.GetMapByName("events")
	p.pe, err = goebpf.NewPerfEvents(eventsMap)
	events, err := p.pe.StartForAllProcessesAndCPUs(4096)
	defer events.Stop()

	for {
		select {
		case data := <-events:
			fmt.Println(data) // kProbe event
		}
	}

Simple? Check exec dump example

Good readings

About

Library to work with eBPF programs from Go

Topics

Resources

License

Stars

1.2k stars

Watchers

32 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors