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