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  }