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