forked from cilium/ebpf
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add an example for attaching an eBPF program to a network interface with XDP. The example program parses the IPv4 source address from packets (if available) and records packet counts by IP address in an LRU hash map. Issue: cilium#645 Signed-off-by: Will Daly <[email protected]>
- Loading branch information
Showing
8 changed files
with
416 additions
and
0 deletions.
There are no files selected for viewing
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
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Binary file not shown.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Binary file not shown.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
//go:build linux | ||
// +build linux | ||
|
||
// This program demonstrates attaching an eBPF program to a network interface | ||
// with XDP (eXpress Data Path). The program parses the IPv4 source address | ||
// from packets and writes the packet count by IP to an LRU hash map. | ||
// The userspace program (Go code in this file) prints the contents | ||
// of the map to stdout every second. | ||
// It is possible to modify the XDP program to drop or redirect packets | ||
// as well -- give it a try! | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"net" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/cilium/ebpf" | ||
"github.com/cilium/ebpf/link" | ||
) | ||
|
||
// $BPF_CLANG and $BPF_CFLAGS are set by the Makefile. | ||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS bpf xdp.c -- -I../headers | ||
|
||
func main() { | ||
if len(os.Args) < 2 { | ||
log.Fatalf("Please specify a network interface") | ||
} | ||
|
||
// Look up the network interface by name. | ||
ifaceName := os.Args[1] | ||
iface, err := net.InterfaceByName(ifaceName) | ||
if err != nil { | ||
log.Fatalf("lookup network iface %q: %s", ifaceName, err) | ||
} | ||
|
||
// Load pre-compiled programs into the kernel. | ||
objs := bpfObjects{} | ||
if err := loadBpfObjects(&objs, nil); err != nil { | ||
log.Fatalf("loading objects: %s", err) | ||
} | ||
defer objs.Close() | ||
|
||
// Attach the program. | ||
l, err := link.AttachXDP(link.XDPOptions{ | ||
Program: objs.XdpProgFunc, | ||
Interface: iface.Index, | ||
}) | ||
if err != nil { | ||
log.Fatalf("could not attach XDP program: %s", err) | ||
} | ||
defer l.Close() | ||
|
||
log.Printf("Attached XDP program to iface %q (index %d)", iface.Name, iface.Index) | ||
log.Printf("Press Ctrl-C to exit and remove the program") | ||
|
||
// Print the contents of the BPF hash map (source IP address -> packet count). | ||
ticker := time.NewTicker(1 * time.Second) | ||
defer ticker.Stop() | ||
for range ticker.C { | ||
s, err := formatMapContents(objs.XdpStatsMap) | ||
if err != nil { | ||
log.Printf("Error reading map: %s", err) | ||
continue | ||
} | ||
log.Printf("Map contents:\n%s", s) | ||
} | ||
} | ||
|
||
func formatMapContents(m *ebpf.Map) (string, error) { | ||
var sb strings.Builder | ||
var key, val uint32 | ||
iter := m.Iterate() | ||
for iter.Next(&key, &val) { | ||
sourceIP := net.IPv4(byte(key>>24), byte(key>>16&0xFF), byte(key>>8)&0xFF, byte(key&0xFF)) | ||
packetCount := val | ||
sb.WriteString(fmt.Sprintf("\t%s => %d\n", sourceIP, packetCount)) | ||
} | ||
return sb.String(), iter.Err() | ||
} |
Oops, something went wrong.