1
2
3 package netlink
4
5 import (
6 "crypto/rand"
7 "encoding/hex"
8 "fmt"
9 "io"
10 "net"
11 "sync"
12 "sync/atomic"
13 "testing"
14 "time"
15 "unsafe"
16
17 "github.com/vishvananda/netlink/nl"
18 "github.com/vishvananda/netns"
19 "golang.org/x/sys/unix"
20 )
21
22 func TestHandleCreateClose(t *testing.T) {
23 h, err := NewHandle()
24 if err != nil {
25 t.Fatal(err)
26 }
27 for _, f := range nl.SupportedNlFamilies {
28 sh, ok := h.sockets[f]
29 if !ok {
30 t.Fatalf("Handle socket(s) for family %d was not created", f)
31 }
32 if sh.Socket == nil {
33 t.Fatalf("Socket for family %d was not created", f)
34 }
35 }
36
37 h.Close()
38 if h.sockets != nil {
39 t.Fatalf("Handle socket(s) were not closed")
40 }
41 }
42
43 func TestHandleCreateNetns(t *testing.T) {
44 skipUnlessRoot(t)
45
46 id := make([]byte, 4)
47 if _, err := io.ReadFull(rand.Reader, id); err != nil {
48 t.Fatal(err)
49 }
50 ifName := "dummy-" + hex.EncodeToString(id)
51
52
53 curNs, err := netns.Get()
54 if err != nil {
55 t.Fatal(err)
56 }
57 defer curNs.Close()
58
59 ch, err := NewHandleAt(curNs)
60 if err != nil {
61 t.Fatal(err)
62 }
63 defer ch.Close()
64
65
66 newNs, err := netns.New()
67 if err != nil {
68 t.Fatal(err)
69 }
70 defer newNs.Close()
71
72 nh, err := NewHandleAt(newNs)
73 if err != nil {
74 t.Fatal(err)
75 }
76 defer nh.Close()
77
78
79 err = ch.LinkAdd(&Dummy{LinkAttrs{Name: ifName}})
80 if err != nil {
81 t.Fatal(err)
82 }
83 l, err := ch.LinkByName(ifName)
84 if err != nil {
85 t.Fatal(err)
86 }
87 if l.Type() != "dummy" {
88 t.Fatalf("Unexpected link type: %s", l.Type())
89 }
90
91
92 ll, err := nh.LinkByName(ifName)
93 if err == nil {
94 t.Fatalf("Unexpected link found on netns %s: %v", newNs, ll)
95 }
96
97
98 err = ch.LinkSetNsFd(l, int(newNs))
99 if err != nil {
100 t.Fatal(err)
101 }
102
103
104 ll, err = nh.LinkByName(ifName)
105 if err != nil {
106 t.Fatal(err)
107 }
108 if ll.Type() != "dummy" {
109 t.Fatalf("Unexpected link type: %s", ll.Type())
110 }
111 ll, err = ch.LinkByName(ifName)
112 if err == nil {
113 t.Fatalf("Unexpected link found on netns %s: %v", curNs, ll)
114 }
115 }
116
117 func TestHandleTimeout(t *testing.T) {
118 h, err := NewHandle()
119 if err != nil {
120 t.Fatal(err)
121 }
122 defer h.Close()
123
124 for _, sh := range h.sockets {
125 verifySockTimeVal(t, sh.Socket.GetFd(), unix.Timeval{Sec: 0, Usec: 0})
126 }
127
128 h.SetSocketTimeout(2*time.Second + 8*time.Millisecond)
129
130 for _, sh := range h.sockets {
131 verifySockTimeVal(t, sh.Socket.GetFd(), unix.Timeval{Sec: 2, Usec: 8000})
132 }
133 }
134
135 func TestHandleReceiveBuffer(t *testing.T) {
136 h, err := NewHandle()
137 if err != nil {
138 t.Fatal(err)
139 }
140 defer h.Close()
141 if err := h.SetSocketReceiveBufferSize(65536, false); err != nil {
142 t.Fatal(err)
143 }
144 sizes, err := h.GetSocketReceiveBufferSize()
145 if err != nil {
146 t.Fatal(err)
147 }
148 if len(sizes) != len(h.sockets) {
149 t.Fatalf("Unexpected number of socket buffer sizes: %d (expected %d)",
150 len(sizes), len(h.sockets))
151 }
152 for _, s := range sizes {
153 if s < 65536 || s > 2*65536 {
154 t.Fatalf("Unexpected socket receive buffer size: %d (expected around %d)",
155 s, 65536)
156 }
157 }
158 }
159
160 func verifySockTimeVal(t *testing.T, fd int, tv unix.Timeval) {
161 var (
162 tr unix.Timeval
163 v = uint32(0x10)
164 )
165 _, _, errno := unix.Syscall6(unix.SYS_GETSOCKOPT, uintptr(fd), unix.SOL_SOCKET, unix.SO_SNDTIMEO, uintptr(unsafe.Pointer(&tr)), uintptr(unsafe.Pointer(&v)), 0)
166 if errno != 0 {
167 t.Fatal(errno)
168 }
169
170 if tr.Sec != tv.Sec || tr.Usec != tv.Usec {
171 t.Fatalf("Unexpected timeout value read: %v. Expected: %v", tr, tv)
172 }
173
174 _, _, errno = unix.Syscall6(unix.SYS_GETSOCKOPT, uintptr(fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, uintptr(unsafe.Pointer(&tr)), uintptr(unsafe.Pointer(&v)), 0)
175 if errno != 0 {
176 t.Fatal(errno)
177 }
178
179 if tr.Sec != tv.Sec || tr.Usec != tv.Usec {
180 t.Fatalf("Unexpected timeout value read: %v. Expected: %v", tr, tv)
181 }
182 }
183
184 var (
185 iter = 10
186 numThread = uint32(4)
187 prefix = "iface"
188 handle1 *Handle
189 handle2 *Handle
190 ns1 netns.NsHandle
191 ns2 netns.NsHandle
192 done uint32
193 initError error
194 once sync.Once
195 )
196
197 func getXfrmState(thread int) *XfrmState {
198 return &XfrmState{
199 Src: net.IPv4(byte(192), byte(168), 1, byte(1+thread)),
200 Dst: net.IPv4(byte(192), byte(168), 2, byte(1+thread)),
201 Proto: XFRM_PROTO_AH,
202 Mode: XFRM_MODE_TUNNEL,
203 Spi: thread,
204 Auth: &XfrmStateAlgo{
205 Name: "hmac(sha256)",
206 Key: []byte("abcdefghijklmnopqrstuvwzyzABCDEF"),
207 },
208 }
209 }
210
211 func getXfrmPolicy(thread int) *XfrmPolicy {
212 return &XfrmPolicy{
213 Src: &net.IPNet{IP: net.IPv4(byte(10), byte(10), byte(thread), 0), Mask: []byte{255, 255, 255, 0}},
214 Dst: &net.IPNet{IP: net.IPv4(byte(10), byte(10), byte(thread), 0), Mask: []byte{255, 255, 255, 0}},
215 Proto: 17,
216 DstPort: 1234,
217 SrcPort: 5678,
218 Dir: XFRM_DIR_OUT,
219 Tmpls: []XfrmPolicyTmpl{
220 {
221 Src: net.IPv4(byte(192), byte(168), 1, byte(thread)),
222 Dst: net.IPv4(byte(192), byte(168), 2, byte(thread)),
223 Proto: XFRM_PROTO_ESP,
224 Mode: XFRM_MODE_TUNNEL,
225 },
226 },
227 }
228 }
229 func initParallel() {
230 ns1, initError = netns.New()
231 if initError != nil {
232 return
233 }
234 handle1, initError = NewHandleAt(ns1)
235 if initError != nil {
236 return
237 }
238 ns2, initError = netns.New()
239 if initError != nil {
240 return
241 }
242 handle2, initError = NewHandleAt(ns2)
243 if initError != nil {
244 return
245 }
246 }
247
248 func parallelDone() {
249 atomic.AddUint32(&done, 1)
250 if done == numThread {
251 if ns1.IsOpen() {
252 ns1.Close()
253 }
254 if ns2.IsOpen() {
255 ns2.Close()
256 }
257 if handle1 != nil {
258 handle1.Close()
259 }
260 if handle2 != nil {
261 handle2.Close()
262 }
263 }
264 }
265
266
267 func runParallelTests(t *testing.T, thread int) {
268 skipUnlessRoot(t)
269 defer parallelDone()
270
271 t.Parallel()
272
273 once.Do(initParallel)
274 if initError != nil {
275 t.Fatal(initError)
276 }
277
278 state := getXfrmState(thread)
279 policy := getXfrmPolicy(thread)
280 for i := 0; i < iter; i++ {
281 ifName := fmt.Sprintf("%s_%d_%d", prefix, thread, i)
282 link := &Dummy{LinkAttrs{Name: ifName}}
283 err := handle1.LinkAdd(link)
284 if err != nil {
285 t.Fatal(err)
286 }
287 l, err := handle1.LinkByName(ifName)
288 if err != nil {
289 t.Fatal(err)
290 }
291 err = handle1.LinkSetUp(l)
292 if err != nil {
293 t.Fatal(err)
294 }
295 handle1.LinkSetNsFd(l, int(ns2))
296 if err != nil {
297 t.Fatal(err)
298 }
299 err = handle1.XfrmStateAdd(state)
300 if err != nil {
301 t.Fatal(err)
302 }
303 err = handle1.XfrmPolicyAdd(policy)
304 if err != nil {
305 t.Fatal(err)
306 }
307 err = handle2.LinkSetDown(l)
308 if err != nil {
309 t.Fatal(err)
310 }
311 err = handle2.XfrmStateAdd(state)
312 if err != nil {
313 t.Fatal(err)
314 }
315 err = handle2.XfrmPolicyAdd(policy)
316 if err != nil {
317 t.Fatal(err)
318 }
319 _, err = handle2.LinkByName(ifName)
320 if err != nil {
321 t.Fatal(err)
322 }
323 handle2.LinkSetNsFd(l, int(ns1))
324 if err != nil {
325 t.Fatal(err)
326 }
327 err = handle1.LinkSetUp(l)
328 if err != nil {
329 t.Fatal(err)
330 }
331 _, err = handle1.LinkByName(ifName)
332 if err != nil {
333 t.Fatal(err)
334 }
335 err = handle1.XfrmPolicyDel(policy)
336 if err != nil {
337 t.Fatal(err)
338 }
339 err = handle2.XfrmPolicyDel(policy)
340 if err != nil {
341 t.Fatal(err)
342 }
343 err = handle1.XfrmStateDel(state)
344 if err != nil {
345 t.Fatal(err)
346 }
347 err = handle2.XfrmStateDel(state)
348 if err != nil {
349 t.Fatal(err)
350 }
351 }
352 }
353
354 func TestHandleParallel1(t *testing.T) {
355 runParallelTests(t, 1)
356 }
357
358 func TestHandleParallel2(t *testing.T) {
359 runParallelTests(t, 2)
360 }
361
362 func TestHandleParallel3(t *testing.T) {
363 runParallelTests(t, 3)
364 }
365
366 func TestHandleParallel4(t *testing.T) {
367 runParallelTests(t, 4)
368 }
369
View as plain text