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