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