Created
November 11, 2021 20:21
-
-
Save florianl/935cfcbeeee209537d8303165dab41e0 to your computer and use it in GitHub Desktop.
xdp ebpf example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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