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