github.com/vishvananda/netlink@v1.3.0/handle_test.go (about) 1 // +build linux 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 // Create an handle on the current netns 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 // Create an handle on a custom netns 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 // Create an interface using the current handle 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 // Verify the new handle cannot find the interface 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 // Move the interface to the new netns 98 err = ch.LinkSetNsFd(l, int(newNs)) 99 if err != nil { 100 t.Fatal(err) 101 } 102 103 // Verify new netns handle can find the interface while current cannot 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 // Do few route and xfrm operation on the two handles in parallel 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 }