github.com/rumpl/bof@v23.0.0-rc.2+incompatible/libnetwork/osl/sandbox_linux_test.go (about) 1 package osl 2 3 import ( 4 "crypto/rand" 5 "encoding/hex" 6 "io" 7 "net" 8 "os" 9 "path/filepath" 10 "runtime" 11 "strings" 12 "syscall" 13 "testing" 14 "time" 15 16 "github.com/docker/docker/libnetwork/ns" 17 "github.com/docker/docker/libnetwork/testutils" 18 "github.com/docker/docker/libnetwork/types" 19 "github.com/docker/docker/pkg/reexec" 20 "github.com/vishvananda/netlink" 21 "github.com/vishvananda/netlink/nl" 22 "github.com/vishvananda/netns" 23 ) 24 25 const ( 26 vethName1 = "wierdlongname1" 27 vethName2 = "wierdlongname2" 28 vethName3 = "wierdlongname3" 29 vethName4 = "wierdlongname4" 30 sboxIfaceName = "containername" 31 ) 32 33 func generateRandomName(prefix string, size int) (string, error) { 34 id := make([]byte, 32) 35 if _, err := io.ReadFull(rand.Reader, id); err != nil { 36 return "", err 37 } 38 return prefix + hex.EncodeToString(id)[:size], nil 39 } 40 41 func newKey(t *testing.T) (string, error) { 42 name, err := generateRandomName("netns", 12) 43 if err != nil { 44 return "", err 45 } 46 47 name = filepath.Join("/tmp", name) 48 if _, err := os.Create(name); err != nil { 49 return "", err 50 } 51 52 // Set the rpmCleanupPeriod to be low to make the test run quicker 53 gpmLock.Lock() 54 gpmCleanupPeriod = 2 * time.Second 55 gpmLock.Unlock() 56 57 return name, nil 58 } 59 60 func newInfo(hnd *netlink.Handle, t *testing.T) (Sandbox, error) { 61 veth := &netlink.Veth{ 62 LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0}, 63 PeerName: vethName2} 64 if err := hnd.LinkAdd(veth); err != nil { 65 return nil, err 66 } 67 68 // Store the sandbox side pipe interface 69 // This is needed for cleanup on DeleteEndpoint() 70 intf1 := &nwIface{} 71 intf1.srcName = vethName2 72 intf1.dstName = sboxIfaceName 73 74 ip4, addr, err := net.ParseCIDR("192.168.1.100/24") 75 if err != nil { 76 return nil, err 77 } 78 intf1.address = addr 79 intf1.address.IP = ip4 80 81 ip6, addrv6, err := net.ParseCIDR("fe80::2/64") 82 if err != nil { 83 return nil, err 84 } 85 intf1.addressIPv6 = addrv6 86 intf1.addressIPv6.IP = ip6 87 88 _, route, err := net.ParseCIDR("192.168.2.1/32") 89 if err != nil { 90 return nil, err 91 } 92 93 intf1.routes = []*net.IPNet{route} 94 95 intf2 := &nwIface{} 96 intf2.srcName = "testbridge" 97 intf2.dstName = sboxIfaceName 98 intf2.bridge = true 99 100 veth = &netlink.Veth{ 101 LinkAttrs: netlink.LinkAttrs{Name: vethName3, TxQLen: 0}, 102 PeerName: vethName4} 103 104 if err := hnd.LinkAdd(veth); err != nil { 105 return nil, err 106 } 107 108 intf3 := &nwIface{} 109 intf3.srcName = vethName4 110 intf3.dstName = sboxIfaceName 111 intf3.master = "testbridge" 112 113 info := &networkNamespace{iFaces: []*nwIface{intf1, intf2, intf3}} 114 115 info.gw = net.ParseIP("192.168.1.1") 116 info.gwv6 = net.ParseIP("fe80::1") 117 118 return info, nil 119 } 120 121 func verifySandbox(t *testing.T, s Sandbox, ifaceSuffixes []string) { 122 _, ok := s.(*networkNamespace) 123 if !ok { 124 t.Fatalf("The sandbox interface returned is not of type networkNamespace") 125 } 126 127 sbNs, err := netns.GetFromPath(s.Key()) 128 if err != nil { 129 t.Fatalf("Failed top open network namespace path %q: %v", s.Key(), err) 130 } 131 defer sbNs.Close() 132 133 nh, err := netlink.NewHandleAt(sbNs) 134 if err != nil { 135 t.Fatal(err) 136 } 137 defer nh.Close() 138 139 for _, suffix := range ifaceSuffixes { 140 _, err = nh.LinkByName(sboxIfaceName + suffix) 141 if err != nil { 142 t.Fatalf("Could not find the interface %s inside the sandbox: %v", 143 sboxIfaceName+suffix, err) 144 } 145 } 146 } 147 148 func verifyCleanup(t *testing.T, s Sandbox, wait bool) { 149 if wait { 150 time.Sleep(gpmCleanupPeriod * 2) 151 } 152 153 if _, err := os.Stat(s.Key()); err == nil { 154 if wait { 155 t.Fatalf("The sandbox path %s is not getting cleaned up even after twice the cleanup period", s.Key()) 156 } else { 157 t.Fatalf("The sandbox path %s is not cleaned up after running gc", s.Key()) 158 } 159 } 160 } 161 162 func TestScanStatistics(t *testing.T) { 163 data := 164 "Inter-| Receive | Transmit\n" + 165 " face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n" + 166 " eth0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" + 167 " wlan0: 7787685 11141 0 0 0 0 0 0 1681390 7220 0 0 0 0 0 0\n" + 168 " lo: 783782 1853 0 0 0 0 0 0 783782 1853 0 0 0 0 0 0\n" + 169 "lxcbr0: 0 0 0 0 0 0 0 0 9006 61 0 0 0 0 0 0\n" 170 171 i := &types.InterfaceStatistics{} 172 173 if err := scanInterfaceStats(data, "wlan0", i); err != nil { 174 t.Fatal(err) 175 } 176 if i.TxBytes != 1681390 || i.TxPackets != 7220 || i.RxBytes != 7787685 || i.RxPackets != 11141 { 177 t.Fatalf("Error scanning the statistics") 178 } 179 180 if err := scanInterfaceStats(data, "lxcbr0", i); err != nil { 181 t.Fatal(err) 182 } 183 if i.TxBytes != 9006 || i.TxPackets != 61 || i.RxBytes != 0 || i.RxPackets != 0 { 184 t.Fatalf("Error scanning the statistics") 185 } 186 } 187 188 func TestDisableIPv6DAD(t *testing.T) { 189 defer testutils.SetupTestOSContext(t)() 190 191 key, err := newKey(t) 192 if err != nil { 193 t.Fatalf("Failed to obtain a key: %v", err) 194 } 195 196 s, err := NewSandbox(key, true, false) 197 if err != nil { 198 t.Fatalf("Failed to create a new sandbox: %v", err) 199 } 200 runtime.LockOSThread() 201 defer destroyTest(t, s) 202 203 n, ok := s.(*networkNamespace) 204 if !ok { 205 t.Fatal(ok) 206 } 207 nlh := n.nlHandle 208 209 ipv6, _ := types.ParseCIDR("2001:db8::44/64") 210 iface := &nwIface{addressIPv6: ipv6, ns: n, dstName: "sideA"} 211 212 veth := &netlink.Veth{ 213 LinkAttrs: netlink.LinkAttrs{Name: "sideA"}, 214 PeerName: "sideB", 215 } 216 217 err = nlh.LinkAdd(veth) 218 if err != nil { 219 t.Fatal(err) 220 } 221 222 link, err := nlh.LinkByName("sideA") 223 if err != nil { 224 t.Fatal(err) 225 } 226 227 err = setInterfaceIPv6(nlh, link, iface) 228 if err != nil { 229 t.Fatal(err) 230 } 231 232 addrList, err := nlh.AddrList(link, nl.FAMILY_V6) 233 if err != nil { 234 t.Fatal(err) 235 } 236 237 if addrList[0].Flags&syscall.IFA_F_NODAD == 0 { 238 t.Fatalf("Unexpected interface flags: 0x%x. Expected to contain 0x%x", addrList[0].Flags, syscall.IFA_F_NODAD) 239 } 240 } 241 242 func destroyTest(t *testing.T, s Sandbox) { 243 if err := s.Destroy(); err != nil { 244 t.Log(err) 245 } 246 } 247 248 func TestSetInterfaceIP(t *testing.T) { 249 defer testutils.SetupTestOSContext(t)() 250 251 key, err := newKey(t) 252 if err != nil { 253 t.Fatalf("Failed to obtain a key: %v", err) 254 } 255 256 s, err := NewSandbox(key, true, false) 257 if err != nil { 258 t.Fatalf("Failed to create a new sandbox: %v", err) 259 } 260 runtime.LockOSThread() 261 defer destroyTest(t, s) 262 263 n, ok := s.(*networkNamespace) 264 if !ok { 265 t.Fatal(ok) 266 } 267 nlh := n.nlHandle 268 269 ipv4, _ := types.ParseCIDR("172.30.0.33/24") 270 ipv6, _ := types.ParseCIDR("2001:db8::44/64") 271 iface := &nwIface{address: ipv4, addressIPv6: ipv6, ns: n, dstName: "sideA"} 272 273 if err := nlh.LinkAdd(&netlink.Veth{ 274 LinkAttrs: netlink.LinkAttrs{Name: "sideA"}, 275 PeerName: "sideB", 276 }); err != nil { 277 t.Fatal(err) 278 } 279 280 linkA, err := nlh.LinkByName("sideA") 281 if err != nil { 282 t.Fatal(err) 283 } 284 285 linkB, err := nlh.LinkByName("sideB") 286 if err != nil { 287 t.Fatal(err) 288 } 289 290 if err := nlh.LinkSetUp(linkA); err != nil { 291 t.Fatal(err) 292 } 293 294 if err := nlh.LinkSetUp(linkB); err != nil { 295 t.Fatal(err) 296 } 297 298 if err := setInterfaceIP(nlh, linkA, iface); err != nil { 299 t.Fatal(err) 300 } 301 302 if err := setInterfaceIPv6(nlh, linkA, iface); err != nil { 303 t.Fatal(err) 304 } 305 306 err = setInterfaceIP(nlh, linkB, iface) 307 if err == nil { 308 t.Fatalf("Expected route conflict error, but succeeded") 309 } 310 if !strings.Contains(err.Error(), "conflicts with existing route") { 311 t.Fatalf("Unexpected error: %v", err) 312 } 313 314 err = setInterfaceIPv6(nlh, linkB, iface) 315 if err == nil { 316 t.Fatalf("Expected route conflict error, but succeeded") 317 } 318 if !strings.Contains(err.Error(), "conflicts with existing route") { 319 t.Fatalf("Unexpected error: %v", err) 320 } 321 } 322 323 func TestLiveRestore(t *testing.T) { 324 325 defer testutils.SetupTestOSContext(t)() 326 327 key, err := newKey(t) 328 if err != nil { 329 t.Fatalf("Failed to obtain a key: %v", err) 330 } 331 332 s, err := NewSandbox(key, true, false) 333 if err != nil { 334 t.Fatalf("Failed to create a new sandbox: %v", err) 335 } 336 runtime.LockOSThread() 337 defer destroyTest(t, s) 338 339 n, ok := s.(*networkNamespace) 340 if !ok { 341 t.Fatal(ok) 342 } 343 nlh := n.nlHandle 344 345 ipv4, _ := types.ParseCIDR("172.30.0.33/24") 346 ipv6, _ := types.ParseCIDR("2001:db8::44/64") 347 iface := &nwIface{address: ipv4, addressIPv6: ipv6, ns: n, dstName: "sideA"} 348 349 if err := nlh.LinkAdd(&netlink.Veth{ 350 LinkAttrs: netlink.LinkAttrs{Name: "sideA"}, 351 PeerName: "sideB", 352 }); err != nil { 353 t.Fatal(err) 354 } 355 356 linkA, err := nlh.LinkByName("sideA") 357 if err != nil { 358 t.Fatal(err) 359 } 360 361 linkB, err := nlh.LinkByName("sideB") 362 if err != nil { 363 t.Fatal(err) 364 } 365 366 if err := nlh.LinkSetUp(linkA); err != nil { 367 t.Fatal(err) 368 } 369 370 if err := nlh.LinkSetUp(linkB); err != nil { 371 t.Fatal(err) 372 } 373 374 if err := setInterfaceIP(nlh, linkA, iface); err != nil { 375 t.Fatal(err) 376 } 377 378 if err := setInterfaceIPv6(nlh, linkA, iface); err != nil { 379 t.Fatal(err) 380 } 381 382 err = setInterfaceIP(nlh, linkB, iface) 383 if err == nil { 384 t.Fatalf("Expected route conflict error, but succeeded") 385 } 386 if !strings.Contains(err.Error(), "conflicts with existing route") { 387 t.Fatalf("Unexpected error: %v", err) 388 } 389 390 err = setInterfaceIPv6(nlh, linkB, iface) 391 if err == nil { 392 t.Fatalf("Expected route conflict error, but succeeded") 393 } 394 if !strings.Contains(err.Error(), "conflicts with existing route") { 395 t.Fatalf("Unexpected error: %v", err) 396 } 397 398 // Create newsandbox with Restore - TRUE 399 s, err = NewSandbox(key, true, true) 400 if err != nil { 401 t.Fatalf("Failed to create a new sandbox: %v", err) 402 } 403 defer destroyTest(t, s) 404 405 // Check if the IPV4 & IPV6 entry present 406 // If present , we should get error in below call 407 // It shows us , we don't delete any config in live-restore case 408 if err := setInterfaceIPv6(nlh, linkA, iface); err == nil { 409 t.Fatalf("Expected route conflict error, but succeeded for IPV6 ") 410 } 411 if err := setInterfaceIP(nlh, linkA, iface); err == nil { 412 t.Fatalf("Expected route conflict error, but succeeded for IPV4 ") 413 } 414 } 415 416 func TestMain(m *testing.M) { 417 if reexec.Init() { 418 return 419 } 420 os.Exit(m.Run()) 421 } 422 423 func TestSandboxCreate(t *testing.T) { 424 defer testutils.SetupTestOSContext(t)() 425 426 key, err := newKey(t) 427 if err != nil { 428 t.Fatalf("Failed to obtain a key: %v", err) 429 } 430 431 s, err := NewSandbox(key, true, false) 432 if err != nil { 433 t.Fatalf("Failed to create a new sandbox: %v", err) 434 } 435 436 if s.Key() != key { 437 t.Fatalf("s.Key() returned %s. Expected %s", s.Key(), key) 438 } 439 440 tbox, err := newInfo(ns.NlHandle(), t) 441 if err != nil { 442 t.Fatalf("Failed to generate new sandbox info: %v", err) 443 } 444 445 for _, i := range tbox.Info().Interfaces() { 446 err = s.AddInterface(i.SrcName(), i.DstName(), 447 tbox.InterfaceOptions().Bridge(i.Bridge()), 448 tbox.InterfaceOptions().Address(i.Address()), 449 tbox.InterfaceOptions().AddressIPv6(i.AddressIPv6())) 450 if err != nil { 451 t.Fatalf("Failed to add interfaces to sandbox: %v", err) 452 } 453 } 454 455 err = s.SetGateway(tbox.Info().Gateway()) 456 if err != nil { 457 t.Fatalf("Failed to set gateway to sandbox: %v", err) 458 } 459 460 err = s.SetGatewayIPv6(tbox.Info().GatewayIPv6()) 461 if err != nil { 462 t.Fatalf("Failed to set ipv6 gateway to sandbox: %v", err) 463 } 464 465 verifySandbox(t, s, []string{"0", "1", "2"}) 466 467 err = s.Destroy() 468 if err != nil { 469 t.Fatal(err) 470 } 471 verifyCleanup(t, s, true) 472 } 473 474 func TestSandboxCreateTwice(t *testing.T) { 475 defer testutils.SetupTestOSContext(t)() 476 477 key, err := newKey(t) 478 if err != nil { 479 t.Fatalf("Failed to obtain a key: %v", err) 480 } 481 482 _, err = NewSandbox(key, true, false) 483 if err != nil { 484 t.Fatalf("Failed to create a new sandbox: %v", err) 485 } 486 runtime.LockOSThread() 487 488 // Create another sandbox with the same key to see if we handle it 489 // gracefully. 490 s, err := NewSandbox(key, true, false) 491 if err != nil { 492 t.Fatalf("Failed to create a new sandbox: %v", err) 493 } 494 runtime.LockOSThread() 495 496 err = s.Destroy() 497 if err != nil { 498 t.Fatal(err) 499 } 500 GC() 501 verifyCleanup(t, s, false) 502 } 503 504 func TestSandboxGC(t *testing.T) { 505 key, err := newKey(t) 506 if err != nil { 507 t.Fatalf("Failed to obtain a key: %v", err) 508 } 509 510 s, err := NewSandbox(key, true, false) 511 if err != nil { 512 t.Fatalf("Failed to create a new sandbox: %v", err) 513 } 514 515 err = s.Destroy() 516 if err != nil { 517 t.Fatal(err) 518 } 519 520 GC() 521 verifyCleanup(t, s, false) 522 } 523 524 func TestAddRemoveInterface(t *testing.T) { 525 defer testutils.SetupTestOSContext(t)() 526 527 key, err := newKey(t) 528 if err != nil { 529 t.Fatalf("Failed to obtain a key: %v", err) 530 } 531 532 s, err := NewSandbox(key, true, false) 533 if err != nil { 534 t.Fatalf("Failed to create a new sandbox: %v", err) 535 } 536 runtime.LockOSThread() 537 538 if s.Key() != key { 539 t.Fatalf("s.Key() returned %s. Expected %s", s.Key(), key) 540 } 541 542 tbox, err := newInfo(ns.NlHandle(), t) 543 if err != nil { 544 t.Fatalf("Failed to generate new sandbox info: %v", err) 545 } 546 547 for _, i := range tbox.Info().Interfaces() { 548 err = s.AddInterface(i.SrcName(), i.DstName(), 549 tbox.InterfaceOptions().Bridge(i.Bridge()), 550 tbox.InterfaceOptions().Address(i.Address()), 551 tbox.InterfaceOptions().AddressIPv6(i.AddressIPv6())) 552 if err != nil { 553 t.Fatalf("Failed to add interfaces to sandbox: %v", err) 554 } 555 } 556 557 verifySandbox(t, s, []string{"0", "1", "2"}) 558 559 interfaces := s.Info().Interfaces() 560 if err := interfaces[0].Remove(); err != nil { 561 t.Fatalf("Failed to remove interfaces from sandbox: %v", err) 562 } 563 564 verifySandbox(t, s, []string{"1", "2"}) 565 566 i := tbox.Info().Interfaces()[0] 567 if err := s.AddInterface(i.SrcName(), i.DstName(), 568 tbox.InterfaceOptions().Bridge(i.Bridge()), 569 tbox.InterfaceOptions().Address(i.Address()), 570 tbox.InterfaceOptions().AddressIPv6(i.AddressIPv6())); err != nil { 571 t.Fatalf("Failed to add interfaces to sandbox: %v", err) 572 } 573 574 verifySandbox(t, s, []string{"1", "2", "3"}) 575 576 err = s.Destroy() 577 if err != nil { 578 t.Fatal(err) 579 } 580 581 GC() 582 verifyCleanup(t, s, false) 583 }