@@ -2,6 +2,7 @@ package main
2
2
3
3
import (
4
4
"encoding/binary"
5
+ "flag"
5
6
"github.com/cilium/ebpf"
6
7
"github.com/cilium/ebpf/btf"
7
8
"github.com/cilium/ebpf/link"
@@ -16,14 +17,47 @@ import (
16
17
17
18
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go bpf acl.c -- -I.
18
19
20
+ const (
21
+ INADDR_TEST = "127.0.0.1"
22
+ BindPort = 9090
23
+
24
+ DATA = "testing"
25
+ )
26
+
19
27
// go generate .
20
- // CGO_ENABLED=0 go run .
28
+ // CGO_ENABLED=0 go run . --action=1
29
+ // CGO_ENABLED=0 go run . --action=0
21
30
func main () {
22
31
logrus .SetReportCaller (true )
23
32
33
+ actionArg := flag .Int ("action" , 1 , "for xdp" )
34
+ iface := flag .String ("iface" , "lo" , "the interface to attach this program to" )
35
+ flag .Parse ()
36
+
24
37
stopCh := make (chan os.Signal , 1 )
25
38
signal .Notify (stopCh , os .Interrupt , syscall .SIGTERM )
26
39
40
+ serverFd := startServer ()
41
+ defer unix .Close (serverFd )
42
+ clientFd := connectToFd (serverFd )
43
+ defer unix .Close (clientFd )
44
+ // connect 已经建立 tcp connection,从全队列(accept)里取出一个 connection socket
45
+ clientServerFd , _ , err := unix .Accept (serverFd )
46
+ if err != nil {
47
+ logrus .Fatalf ("Accept err: %v" , err )
48
+ }
49
+ defer unix .Close (clientServerFd )
50
+ if _ , err = unix .Write (clientFd , []byte (DATA )); err != nil {
51
+ logrus .Fatalf ("unix.Write err: %v" , err )
52
+ }
53
+ cbuf := make ([]byte , 1024 )
54
+ n , _ , _ , _ , err := unix .Recvmsg (clientServerFd , cbuf , nil , 0 )
55
+ if err != nil {
56
+ logrus .Fatalf ("unix.Recvmsg err: %v" , err )
57
+ }
58
+ cbuf = cbuf [:n ]
59
+ logrus .Infof ("server recvmsg from client: %s" , string (cbuf ))
60
+
27
61
// Load pre-compiled programs and maps into the kernel.
28
62
btfSpec , err := btf .LoadKernelSpec ()
29
63
if err != nil {
@@ -58,12 +92,11 @@ func main() {
58
92
logrus .Error (err )
59
93
}
60
94
61
- ip1 := "172.16.10.3"
62
95
var addr uint32
63
96
if IsLittleEndian () {
64
- addr = binary .LittleEndian .Uint32 (net .ParseIP (ip1 ).To4 ()) // byte[]{a,b,c,d} -> dcba
97
+ addr = binary .LittleEndian .Uint32 (net .ParseIP (INADDR_TEST ).To4 ()) // byte[]{a,b,c,d} -> dcba
65
98
} else {
66
- addr = binary .BigEndian .Uint32 (net .ParseIP (ip1 ).To4 ()) // byte[]{a,b,c,d} -> abcd
99
+ addr = binary .BigEndian .Uint32 (net .ParseIP (INADDR_TEST ).To4 ()) // byte[]{a,b,c,d} -> abcd
67
100
}
68
101
// serverIPs := bpfServerIps{
69
102
// TargetIps: [4]uint32{
@@ -80,10 +113,10 @@ func main() {
80
113
81
114
endpoint := bpfEndpoint {
82
115
Protocol : unix .IPPROTO_TCP ,
83
- Dport : uint16 (9090 ),
116
+ Dport : uint16 (BindPort ),
84
117
}
85
118
action := bpfAction {
86
- Action : uint8 (0 ),
119
+ Action : uint8 (* actionArg ),
87
120
}
88
121
if err := objs .bpfMaps .Endpoints .Put (endpoint , action ); err != nil {
89
122
logrus .Error (err )
@@ -95,7 +128,7 @@ func main() {
95
128
}
96
129
logrus .Infof ("%+v" , action1 )
97
130
98
- ifaceObj , err := net .InterfaceByName ("eth0" )
131
+ ifaceObj , err := net .InterfaceByName (* iface )
99
132
if err != nil {
100
133
logrus .Fatalf ("loading objects: %v" , err )
101
134
}
@@ -109,12 +142,117 @@ func main() {
109
142
}
110
143
defer l .Close ()
111
144
145
+ if _ , err = unix .Write (clientFd , []byte (DATA )); err != nil {
146
+ logrus .Fatalf ("unix.Write err: %v" , err )
147
+ }
148
+ cbuf2 := make ([]byte , 1024 )
149
+ n2 , _ , _ , _ , err := unix .Recvmsg (clientServerFd , cbuf2 , nil , 0 )
150
+ if err != nil {
151
+ logrus .Fatalf ("unix.Recvmsg err: %v" , err )
152
+ }
153
+ cbuf2 = cbuf2 [:n2 ]
154
+ logrus .Infof ("server recvmsg from client: %s" , string (cbuf2 ))
155
+
112
156
// Wait
113
157
<- stopCh
114
158
}
115
159
160
+ func connectToFd (serverFd int ) int {
161
+ socketType , err := unix .GetsockoptInt (serverFd , unix .SOL_SOCKET , unix .SO_TYPE )
162
+ if err != nil {
163
+ logrus .Fatal (err )
164
+ }
165
+
166
+ //tcpSaveSyn, err := unix.GetsockoptInt(serverFd, unix.SOL_TCP, unix.TCP_SAVE_SYN)
167
+
168
+ serverSockAddr , err := unix .Getsockname (serverFd )
169
+ if err != nil {
170
+ logrus .Fatal (err )
171
+ }
172
+
173
+ clientFd , err := unix .Socket (unix .AF_INET , socketType , 0 )
174
+ if err != nil {
175
+ logrus .Fatal (err )
176
+ }
177
+ setSocketTimeout (clientFd , 5000 )
178
+
179
+ ip := net .ParseIP (INADDR_TEST )
180
+ sa := & unix.SockaddrInet4 {
181
+ Port : BindPort + 1 ,
182
+ Addr : [4 ]byte {},
183
+ }
184
+ copy (sa .Addr [:], ip )
185
+ err = unix .Bind (clientFd , sa )
186
+ if err != nil {
187
+ logrus .Fatal (err )
188
+ }
189
+
190
+ // 非阻塞的
191
+ err = unix .Connect (clientFd , serverSockAddr )
192
+ if err != nil {
193
+ logrus .Fatal (err )
194
+ }
195
+
196
+ return clientFd
197
+ }
198
+
199
+ func startServer () int {
200
+ serverFd , err := unix .Socket (unix .AF_INET , unix .SOCK_STREAM , 0 )
201
+ if err != nil {
202
+ logrus .Fatal (err )
203
+ }
204
+ setSocketTimeout (serverFd , 5000 )
205
+
206
+ err = unix .SetsockoptInt (serverFd , unix .SOL_SOCKET , unix .SO_REUSEADDR , 1 )
207
+ if err != nil {
208
+ logrus .Fatalf ("unix.SO_REUSEADDR error: %v" , err )
209
+ }
210
+
211
+ ip := net .ParseIP (INADDR_TEST )
212
+ sa := & unix.SockaddrInet4 {
213
+ Port : BindPort ,
214
+ Addr : [4 ]byte {},
215
+ }
216
+ copy (sa .Addr [:], ip )
217
+ err = unix .Bind (serverFd , sa )
218
+ if err != nil {
219
+ logrus .Fatal (err )
220
+ }
221
+
222
+ err = unix .Listen (serverFd , 1 )
223
+ if err != nil {
224
+ logrus .Fatal (err )
225
+ }
226
+
227
+ return serverFd
228
+ }
229
+
230
+ func setSocketTimeout (fd , timeoutMs int ) {
231
+ var timeVal * unix.Timeval
232
+ if timeoutMs > 0 {
233
+ timeVal = & unix.Timeval {
234
+ Sec : int64 (timeoutMs / 1000 ),
235
+ Usec : int64 (timeoutMs % 1000 * 1000 ),
236
+ }
237
+ } else {
238
+ timeVal = & unix.Timeval {
239
+ Sec : 3 ,
240
+ }
241
+ }
242
+
243
+ err := unix .SetsockoptTimeval (fd , unix .SOL_SOCKET , unix .SO_RCVTIMEO , timeVal )
244
+ if err != nil {
245
+ logrus .Fatal (err )
246
+ }
247
+
248
+ err = unix .SetsockoptTimeval (fd , unix .SOL_SOCKET , unix .SO_SNDTIMEO , timeVal )
249
+ if err != nil {
250
+ logrus .Fatal (err )
251
+ }
252
+ }
253
+
116
254
func IsLittleEndian () bool {
117
- var val int32 = 0x1
255
+ val := int32 ( 0x1 )
118
256
119
257
return * (* byte )(unsafe .Pointer (& val )) == 1
120
258
}
0 commit comments