1
+ //go:build linux
2
+ // +build linux
3
+
4
+ package main
5
+
6
+ import (
7
+ "bytes"
8
+ "encoding/binary"
9
+ "errors"
10
+ "log"
11
+ "net"
12
+ "os"
13
+ "os/signal"
14
+ "syscall"
15
+
16
+ "golang.org/x/sys/unix"
17
+
18
+ "github.com/cilium/ebpf"
19
+ "github.com/cilium/ebpf/link"
20
+ "github.com/cilium/ebpf/ringbuf"
21
+ "github.com/cilium/ebpf/rlimit"
22
+ )
23
+
24
+ // $BPF_CLANG and $BPF_CFLAGS are set by the Makefile.
25
+ //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS -type event bpf fentry.c -- -I../headers
26
+
27
+ func main () {
28
+ if len (os .Args ) < 2 {
29
+ log .Fatalf ("Please specify a network interface" )
30
+ }
31
+
32
+ ifaceName := os .Args [1 ]
33
+ iface , err := net .InterfaceByName (ifaceName )
34
+ if err != nil {
35
+ log .Fatalf ("lookup network iface %q: %s" , ifaceName , err )
36
+ }
37
+
38
+ objs := bpfObjects {}
39
+ if err := loadBpfObjects (& objs , nil ); err != nil {
40
+ log .Fatalf ("loading objects: %s" , err )
41
+ }
42
+ defer objs .Close ()
43
+
44
+ l , err := link .AttachXDP (link.XDPOptions {
45
+ Program : objs .XdpProgFunc ,
46
+ Interface : iface .Index ,
47
+ })
48
+ if err != nil {
49
+ log .Fatalf ("could not attach XDP program: %s" , err )
50
+ }
51
+ defer l .Close ()
52
+
53
+ log .Printf ("Attached XDP program to iface %q (index %d)" , iface .Name , iface .Index )
54
+
55
+ ticker := time .NewTicker (1 * time .Second )
56
+ defer ticker .Stop ()
57
+ for range ticker .C {
58
+ s , err := formatMapContents (objs .XdpStatsMap )
59
+ if err != nil {
60
+ log .Printf ("Error reading map: %s" , err )
61
+ continue
62
+ }
63
+ log .Printf ("Map contents:\n %s" , s )
64
+ }
65
+ }
66
+
67
+ func intToIP (ipNum uint32 ) net.IP {
68
+ ip := make (net.IP , 4 )
69
+ binary .BigEndian .PutUint32 (ip , ipNum )
70
+ return ip
71
+ }
72
+
73
+ func saveDataToMap (desPort , srcAddr , port string ) {
74
+ // Allow the current process to lock memory for eBPF resources.
75
+ if err := rlimit .RemoveMemlock (); err != nil {
76
+ log .Fatal (err )
77
+ }
78
+
79
+ outerMapSpec := ebpf.MapSpec {
80
+ Name : "outer_map" ,
81
+ Type : ebpf .ArrayOfMaps ,
82
+ KeySize : 10000 ,
83
+ ValueSize : 10000 ,
84
+ MaxEntries : 10000 ,
85
+ Contents : make ([]ebpf.MapKV , 5 ),
86
+ InnerMap : & ebpf.MapSpec {
87
+ Name : "inner_map" ,
88
+ Type : ebpf .Array ,
89
+ KeySize : 100 ,
90
+ ValueSize : 100 ,
91
+ Flags : unix .BPF_F_INNER_MAP ,
92
+ MaxEntries : 1 ,
93
+ },
94
+ }
95
+
96
+ innerMapSpec := outerMapSpec .InnerMap .Copy ()
97
+ innerMapSpec .MaxEntries = 1000
98
+ innerMapSpec .Contents = make ([]ebpf.MapKV , innerMapSpec .MaxEntries )
99
+ innerMapSpec = append (innerMapSpec , ebpf.MapKV {Key : desPort , Value : srcAddr + port })
100
+ innerMap , err := ebpf .NewMap (innerMapSpec )
101
+ if err != nil {
102
+ log .Fatalf ("inner_map: %v" , err )
103
+ }
104
+ defer innerMap .Close ()
105
+ outerMapSpec .Contents = append (outerMapSpec .Contents , ebpf.MapKV {Key : i , Value : innerMap })
106
+ }
107
+
108
+ func readMap (outerMapSpec ebpf.MapSpec ) {
109
+ outerMap , err := ebpf .NewMap (& outerMapSpec )
110
+ if err != nil {
111
+ log .Fatalf ("outer_map: %v" , err )
112
+ }
113
+ defer outerMap .Close ()
114
+
115
+ mapIter := outerMap .Iterate ()
116
+ var outerMapKey uint32
117
+ var innerMapID ebpf.MapID
118
+ for mapIter .Next (& outerMapKey , & innerMapID ) {
119
+ innerMap , err := ebpf .NewMapFromID (innerMapID )
120
+ if err != nil {
121
+ log .Fatal (err )
122
+ }
123
+ innerMapInfo , err := innerMap .Info ()
124
+ if err != nil {
125
+ log .Fatal (err )
126
+ }
127
+ log .Printf ("outerMapKey %d, innerMap.Info: %+v" , outerMapKey , innerMapInfo .)
128
+ }
129
+ }
130
+
131
+ func formatMapContents (m * ebpf.Map ) (string , error ) {
132
+ var (
133
+ sb strings.Builder
134
+ key []byte
135
+ val uint32
136
+ )
137
+ iter := m .Iterate ()
138
+ for iter .Next (& key , & val ) {
139
+ sourceIP := net .IP (key ) // IPv4 source address in network byte order.
140
+ packetCount := val
141
+ sb .WriteString (fmt .Sprintf ("\t %s => %d\n " , sourceIP , packetCount ))
142
+ }
143
+ return sb .String (), iter .Err ()
144
+ }
0 commit comments