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  }