Skip to content

Instantly share code, notes, and snippets.

@florianl
Created November 11, 2021 20:21
Show Gist options
  • Save florianl/935cfcbeeee209537d8303165dab41e0 to your computer and use it in GitHub Desktop.
Save florianl/935cfcbeeee209537d8303165dab41e0 to your computer and use it in GitHub Desktop.
xdp ebpf example
package main
import (
"fmt"
"log"
"net"
"github.com/cilium/ebpf"
"github.com/cilium/ebpf/asm"
"github.com/cilium/ebpf/rlimit"
"github.com/jsimonetti/rtnetlink"
"golang.org/x/sys/unix"
)
// setupDummyInterface installs a temporary dummy interface
func setupDummyInterface(iface string) (uint32, error) {
con, err := rtnetlink.Dial(nil)
if err != nil {
return 0, err
}
if err := con.Link.New(&rtnetlink.LinkMessage{
Family: unix.AF_UNSPEC,
Type: unix.ARPHRD_NETROM,
Index: 0,
Flags: unix.IFF_UP,
Change: unix.IFF_UP,
Attributes: &rtnetlink.LinkAttributes{
Name: iface,
Info: &rtnetlink.LinkInfo{Kind: "dummy"},
},
}); err != nil {
return 0, err
}
devID, err := net.InterfaceByName(iface)
if err != nil {
return 0, fmt.Errorf("could not get iface index of %s: %v", iface, err)
}
return uint32(devID.Index), err
}
// deleteDummyInterface removes a temporary dummy interface
func deleteDummyInterface(ifaceID uint32) error {
con, err := rtnetlink.Dial(nil)
if err != nil {
return err
}
if err := con.Link.Delete(ifaceID); err != nil {
return fmt.Errorf("could not delete iface (%d): %v", ifaceID, err)
}
return nil
}
func main() {
// Setup a dummy interface to attach the XDP eBPF program.
xdpIface, err := setupDummyInterface("xdpIface")
if err != nil {
log.Fatalf("could not get interface ID: %v\n", err)
}
defer deleteDummyInterface(xdpIface)
// Allow the current process to lock memory for eBPF resources.
if err := rlimit.RemoveMemlock(); err != nil {
log.Fatal(err)
}
// Metadata for the eBPF program used in this example.
progSpec := &ebpf.ProgramSpec{
Name: "my_xdp_prog",
Type: ebpf.XDP,
License: "GPL",
}
// Minimal program that drops all traffic.
progSpec.Instructions = asm.Instructions{
// set exit code to 1 which is XDP_DROP
asm.Mov.Imm(asm.R0, 1),
asm.Return(),
}
// Instantiate and insert the program into the kernel.
prog, err := ebpf.NewProgram(progSpec)
if err != nil {
log.Fatalf("creating ebpf program: %s", err)
}
defer prog.Close()
message := rtnetlink.LinkMessage{
Family: unix.AF_UNSPEC,
Index: xdpIface,
Attributes: &rtnetlink.LinkAttributes{
XDP: &rtnetlink.LinkXDP{
FD: int32(prog.FD()),
Flags: unix.XDP_FLAGS_HW_MODE,
},
},
}
// Establish a netlink connection.
conn, err := rtnetlink.Dial(nil)
if err != nil {
log.Fatalf("failed to establish netlink socket: %v", err)
}
defer conn.Close()
// Attach XDP eBPF program to interface.
if err := conn.Link.Set(&message); err != nil {
log.Fatalf("failed to attach XDP program to interface: %v", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment