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