github.com/rumpl/bof@v23.0.0-rc.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  	"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  
   325  	defer testutils.SetupTestOSContext(t)()
   326  
   327  	key, err := newKey(t)
   328  	if err != nil {
   329  		t.Fatalf("Failed to obtain a key: %v", err)
   330  	}
   331  
   332  	s, err := NewSandbox(key, true, false)
   333  	if err != nil {
   334  		t.Fatalf("Failed to create a new sandbox: %v", err)
   335  	}
   336  	runtime.LockOSThread()
   337  	defer destroyTest(t, s)
   338  
   339  	n, ok := s.(*networkNamespace)
   340  	if !ok {
   341  		t.Fatal(ok)
   342  	}
   343  	nlh := n.nlHandle
   344  
   345  	ipv4, _ := types.ParseCIDR("172.30.0.33/24")
   346  	ipv6, _ := types.ParseCIDR("2001:db8::44/64")
   347  	iface := &nwIface{address: ipv4, addressIPv6: ipv6, ns: n, dstName: "sideA"}
   348  
   349  	if err := nlh.LinkAdd(&netlink.Veth{
   350  		LinkAttrs: netlink.LinkAttrs{Name: "sideA"},
   351  		PeerName:  "sideB",
   352  	}); err != nil {
   353  		t.Fatal(err)
   354  	}
   355  
   356  	linkA, err := nlh.LinkByName("sideA")
   357  	if err != nil {
   358  		t.Fatal(err)
   359  	}
   360  
   361  	linkB, err := nlh.LinkByName("sideB")
   362  	if err != nil {
   363  		t.Fatal(err)
   364  	}
   365  
   366  	if err := nlh.LinkSetUp(linkA); err != nil {
   367  		t.Fatal(err)
   368  	}
   369  
   370  	if err := nlh.LinkSetUp(linkB); err != nil {
   371  		t.Fatal(err)
   372  	}
   373  
   374  	if err := setInterfaceIP(nlh, linkA, iface); err != nil {
   375  		t.Fatal(err)
   376  	}
   377  
   378  	if err := setInterfaceIPv6(nlh, linkA, iface); err != nil {
   379  		t.Fatal(err)
   380  	}
   381  
   382  	err = setInterfaceIP(nlh, linkB, iface)
   383  	if err == nil {
   384  		t.Fatalf("Expected route conflict error, but succeeded")
   385  	}
   386  	if !strings.Contains(err.Error(), "conflicts with existing route") {
   387  		t.Fatalf("Unexpected error: %v", err)
   388  	}
   389  
   390  	err = setInterfaceIPv6(nlh, linkB, iface)
   391  	if err == nil {
   392  		t.Fatalf("Expected route conflict error, but succeeded")
   393  	}
   394  	if !strings.Contains(err.Error(), "conflicts with existing route") {
   395  		t.Fatalf("Unexpected error: %v", err)
   396  	}
   397  
   398  	// Create newsandbox with Restore - TRUE
   399  	s, err = NewSandbox(key, true, true)
   400  	if err != nil {
   401  		t.Fatalf("Failed to create a new sandbox: %v", err)
   402  	}
   403  	defer destroyTest(t, s)
   404  
   405  	// Check if the IPV4 & IPV6 entry present
   406  	// If present , we should get error in below call
   407  	// It shows us , we don't delete any config in live-restore case
   408  	if err := setInterfaceIPv6(nlh, linkA, iface); err == nil {
   409  		t.Fatalf("Expected route conflict error, but succeeded for IPV6 ")
   410  	}
   411  	if err := setInterfaceIP(nlh, linkA, iface); err == nil {
   412  		t.Fatalf("Expected route conflict error, but succeeded for IPV4 ")
   413  	}
   414  }
   415  
   416  func TestMain(m *testing.M) {
   417  	if reexec.Init() {
   418  		return
   419  	}
   420  	os.Exit(m.Run())
   421  }
   422  
   423  func TestSandboxCreate(t *testing.T) {
   424  	defer testutils.SetupTestOSContext(t)()
   425  
   426  	key, err := newKey(t)
   427  	if err != nil {
   428  		t.Fatalf("Failed to obtain a key: %v", err)
   429  	}
   430  
   431  	s, err := NewSandbox(key, true, false)
   432  	if err != nil {
   433  		t.Fatalf("Failed to create a new sandbox: %v", err)
   434  	}
   435  
   436  	if s.Key() != key {
   437  		t.Fatalf("s.Key() returned %s. Expected %s", s.Key(), key)
   438  	}
   439  
   440  	tbox, err := newInfo(ns.NlHandle(), t)
   441  	if err != nil {
   442  		t.Fatalf("Failed to generate new sandbox info: %v", err)
   443  	}
   444  
   445  	for _, i := range tbox.Info().Interfaces() {
   446  		err = s.AddInterface(i.SrcName(), i.DstName(),
   447  			tbox.InterfaceOptions().Bridge(i.Bridge()),
   448  			tbox.InterfaceOptions().Address(i.Address()),
   449  			tbox.InterfaceOptions().AddressIPv6(i.AddressIPv6()))
   450  		if err != nil {
   451  			t.Fatalf("Failed to add interfaces to sandbox: %v", err)
   452  		}
   453  	}
   454  
   455  	err = s.SetGateway(tbox.Info().Gateway())
   456  	if err != nil {
   457  		t.Fatalf("Failed to set gateway to sandbox: %v", err)
   458  	}
   459  
   460  	err = s.SetGatewayIPv6(tbox.Info().GatewayIPv6())
   461  	if err != nil {
   462  		t.Fatalf("Failed to set ipv6 gateway to sandbox: %v", err)
   463  	}
   464  
   465  	verifySandbox(t, s, []string{"0", "1", "2"})
   466  
   467  	err = s.Destroy()
   468  	if err != nil {
   469  		t.Fatal(err)
   470  	}
   471  	verifyCleanup(t, s, true)
   472  }
   473  
   474  func TestSandboxCreateTwice(t *testing.T) {
   475  	defer testutils.SetupTestOSContext(t)()
   476  
   477  	key, err := newKey(t)
   478  	if err != nil {
   479  		t.Fatalf("Failed to obtain a key: %v", err)
   480  	}
   481  
   482  	_, err = NewSandbox(key, true, false)
   483  	if err != nil {
   484  		t.Fatalf("Failed to create a new sandbox: %v", err)
   485  	}
   486  	runtime.LockOSThread()
   487  
   488  	// Create another sandbox with the same key to see if we handle it
   489  	// gracefully.
   490  	s, err := NewSandbox(key, true, false)
   491  	if err != nil {
   492  		t.Fatalf("Failed to create a new sandbox: %v", err)
   493  	}
   494  	runtime.LockOSThread()
   495  
   496  	err = s.Destroy()
   497  	if err != nil {
   498  		t.Fatal(err)
   499  	}
   500  	GC()
   501  	verifyCleanup(t, s, false)
   502  }
   503  
   504  func TestSandboxGC(t *testing.T) {
   505  	key, err := newKey(t)
   506  	if err != nil {
   507  		t.Fatalf("Failed to obtain a key: %v", err)
   508  	}
   509  
   510  	s, err := NewSandbox(key, true, false)
   511  	if err != nil {
   512  		t.Fatalf("Failed to create a new sandbox: %v", err)
   513  	}
   514  
   515  	err = s.Destroy()
   516  	if err != nil {
   517  		t.Fatal(err)
   518  	}
   519  
   520  	GC()
   521  	verifyCleanup(t, s, false)
   522  }
   523  
   524  func TestAddRemoveInterface(t *testing.T) {
   525  	defer testutils.SetupTestOSContext(t)()
   526  
   527  	key, err := newKey(t)
   528  	if err != nil {
   529  		t.Fatalf("Failed to obtain a key: %v", err)
   530  	}
   531  
   532  	s, err := NewSandbox(key, true, false)
   533  	if err != nil {
   534  		t.Fatalf("Failed to create a new sandbox: %v", err)
   535  	}
   536  	runtime.LockOSThread()
   537  
   538  	if s.Key() != key {
   539  		t.Fatalf("s.Key() returned %s. Expected %s", s.Key(), key)
   540  	}
   541  
   542  	tbox, err := newInfo(ns.NlHandle(), t)
   543  	if err != nil {
   544  		t.Fatalf("Failed to generate new sandbox info: %v", err)
   545  	}
   546  
   547  	for _, i := range tbox.Info().Interfaces() {
   548  		err = s.AddInterface(i.SrcName(), i.DstName(),
   549  			tbox.InterfaceOptions().Bridge(i.Bridge()),
   550  			tbox.InterfaceOptions().Address(i.Address()),
   551  			tbox.InterfaceOptions().AddressIPv6(i.AddressIPv6()))
   552  		if err != nil {
   553  			t.Fatalf("Failed to add interfaces to sandbox: %v", err)
   554  		}
   555  	}
   556  
   557  	verifySandbox(t, s, []string{"0", "1", "2"})
   558  
   559  	interfaces := s.Info().Interfaces()
   560  	if err := interfaces[0].Remove(); err != nil {
   561  		t.Fatalf("Failed to remove interfaces from sandbox: %v", err)
   562  	}
   563  
   564  	verifySandbox(t, s, []string{"1", "2"})
   565  
   566  	i := tbox.Info().Interfaces()[0]
   567  	if err := s.AddInterface(i.SrcName(), i.DstName(),
   568  		tbox.InterfaceOptions().Bridge(i.Bridge()),
   569  		tbox.InterfaceOptions().Address(i.Address()),
   570  		tbox.InterfaceOptions().AddressIPv6(i.AddressIPv6())); err != nil {
   571  		t.Fatalf("Failed to add interfaces to sandbox: %v", err)
   572  	}
   573  
   574  	verifySandbox(t, s, []string{"1", "2", "3"})
   575  
   576  	err = s.Destroy()
   577  	if err != nil {
   578  		t.Fatal(err)
   579  	}
   580  
   581  	GC()
   582  	verifyCleanup(t, s, false)
   583  }