github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/virtcontainers/network_test.go (about)

     1  // Copyright (c) 2016 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package virtcontainers
     7  
     8  import (
     9  	"fmt"
    10  	"net"
    11  	"os"
    12  	"reflect"
    13  	"testing"
    14  
    15  	ktu "github.com/kata-containers/runtime/pkg/katatestutils"
    16  	vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/vishvananda/netlink"
    19  )
    20  
    21  func TestCreateDeleteNetNS(t *testing.T) {
    22  	assert := assert.New(t)
    23  	if tc.NotValid(ktu.NeedRoot()) {
    24  		t.Skip(testDisabledAsNonRoot)
    25  	}
    26  
    27  	netNSPath, err := createNetNS()
    28  	assert.NoError(err)
    29  	assert.NotEmpty(netNSPath)
    30  
    31  	_, err = os.Stat(netNSPath)
    32  	assert.NoError(err)
    33  
    34  	err = deleteNetNS(netNSPath)
    35  	assert.NoError(err)
    36  }
    37  
    38  func TestGenerateInterfacesAndRoutes(t *testing.T) {
    39  	//
    40  	//Create a couple of addresses
    41  	//
    42  	address1 := &net.IPNet{IP: net.IPv4(172, 17, 0, 2), Mask: net.CIDRMask(16, 32)}
    43  	address2 := &net.IPNet{IP: net.IPv4(182, 17, 0, 2), Mask: net.CIDRMask(16, 32)}
    44  	address3 := &net.IPNet{IP: net.ParseIP("2001:db8:1::242:ac11:2"), Mask: net.CIDRMask(64, 128)}
    45  
    46  	addrs := []netlink.Addr{
    47  		{IPNet: address1, Label: "phyaddr1"},
    48  		{IPNet: address2, Label: "phyaddr2"},
    49  		{IPNet: address3, Label: "phyaddr3"},
    50  	}
    51  
    52  	// Create a couple of routes:
    53  	dst2 := &net.IPNet{IP: net.IPv4(172, 17, 0, 0), Mask: net.CIDRMask(16, 32)}
    54  	src2 := net.IPv4(172, 17, 0, 2)
    55  	gw2 := net.IPv4(172, 17, 0, 1)
    56  
    57  	dstV6 := &net.IPNet{IP: net.ParseIP("2001:db8:1::"), Mask: net.CIDRMask(64, 128)}
    58  	gatewayV6 := net.ParseIP("2001:db8:1::1")
    59  
    60  	routes := []netlink.Route{
    61  		{LinkIndex: 329, Dst: nil, Src: nil, Gw: net.IPv4(172, 17, 0, 1), Scope: netlink.Scope(254)},
    62  		{LinkIndex: 329, Dst: dst2, Src: src2, Gw: gw2},
    63  		{LinkIndex: 329, Dst: dstV6, Src: nil, Gw: nil},
    64  		{LinkIndex: 329, Dst: nil, Src: nil, Gw: gatewayV6},
    65  	}
    66  
    67  	arpMAC, _ := net.ParseMAC("6a:92:3a:59:70:aa")
    68  
    69  	neighs := []netlink.Neigh{
    70  		{LinkIndex: 329, IP: net.IPv4(192, 168, 0, 101), State: netlink.NUD_PERMANENT, HardwareAddr: arpMAC},
    71  	}
    72  
    73  	networkInfo := NetworkInfo{
    74  		Iface: NetlinkIface{
    75  			LinkAttrs: netlink.LinkAttrs{MTU: 1500},
    76  			Type:      "",
    77  		},
    78  		Addrs:     addrs,
    79  		Routes:    routes,
    80  		Neighbors: neighs,
    81  	}
    82  
    83  	ep0 := &PhysicalEndpoint{
    84  		IfaceName:          "eth0",
    85  		HardAddr:           net.HardwareAddr{0x02, 0x00, 0xca, 0xfe, 0x00, 0x04}.String(),
    86  		EndpointProperties: networkInfo,
    87  	}
    88  
    89  	endpoints := []Endpoint{ep0}
    90  
    91  	nns := NetworkNamespace{NetNsPath: "foobar", NetNsCreated: true, Endpoints: endpoints}
    92  
    93  	resInterfaces, resRoutes, resNeighs, err := generateVCNetworkStructures(nns)
    94  
    95  	//
    96  	// Build expected results:
    97  	//
    98  	expectedAddresses := []*vcTypes.IPAddress{
    99  		{Family: netlink.FAMILY_V4, Address: "172.17.0.2", Mask: "16"},
   100  		{Family: netlink.FAMILY_V4, Address: "182.17.0.2", Mask: "16"},
   101  		{Family: netlink.FAMILY_V6, Address: "2001:db8:1::242:ac11:2", Mask: "64"},
   102  	}
   103  
   104  	expectedInterfaces := []*vcTypes.Interface{
   105  		{Device: "eth0", Name: "eth0", IPAddresses: expectedAddresses, Mtu: 1500, HwAddr: "02:00:ca:fe:00:04"},
   106  	}
   107  
   108  	expectedRoutes := []*vcTypes.Route{
   109  		{Dest: "", Gateway: "172.17.0.1", Device: "eth0", Source: "", Scope: uint32(254)},
   110  		{Dest: "172.17.0.0/16", Gateway: "172.17.0.1", Device: "eth0", Source: "172.17.0.2"},
   111  		{Dest: "2001:db8:1::/64", Gateway: "", Device: "eth0", Source: ""},
   112  		{Dest: "", Gateway: "2001:db8:1::1", Device: "eth0", Source: ""},
   113  	}
   114  
   115  	expectedNeighs := []*vcTypes.ARPNeighbor{
   116  		{
   117  			Device:      "eth0",
   118  			State:       netlink.NUD_PERMANENT,
   119  			LLAddr:      "6a:92:3a:59:70:aa",
   120  			ToIPAddress: &vcTypes.IPAddress{Address: "192.168.0.101", Family: netlink.FAMILY_V4},
   121  		},
   122  	}
   123  
   124  	for _, r := range resRoutes {
   125  		fmt.Printf("resRoute: %+v\n", r)
   126  	}
   127  
   128  	assert.Nil(t, err, "unexpected failure when calling generateKataInterfacesAndRoutes")
   129  	assert.True(t, reflect.DeepEqual(resInterfaces, expectedInterfaces),
   130  		"Interfaces returned didn't match: got %+v, expecting %+v", resInterfaces, expectedInterfaces)
   131  	assert.True(t, reflect.DeepEqual(resRoutes, expectedRoutes),
   132  		"Routes returned didn't match: got %+v, expecting %+v", resRoutes, expectedRoutes)
   133  	assert.True(t, reflect.DeepEqual(resNeighs, expectedNeighs),
   134  		"ARP Neighbors returned didn't match: got %+v, expecting %+v", resNeighs, expectedNeighs)
   135  }
   136  
   137  func TestNetInterworkingModelIsValid(t *testing.T) {
   138  	tests := []struct {
   139  		name string
   140  		n    NetInterworkingModel
   141  		want bool
   142  	}{
   143  		{"Invalid Model", NetXConnectInvalidModel, false},
   144  		{"Default Model", NetXConnectDefaultModel, true},
   145  		{"TC Filter Model", NetXConnectTCFilterModel, true},
   146  		{"Macvtap Model", NetXConnectMacVtapModel, true},
   147  	}
   148  	for _, tt := range tests {
   149  		t.Run(tt.name, func(t *testing.T) {
   150  			if got := tt.n.IsValid(); got != tt.want {
   151  				t.Errorf("NetInterworkingModel.IsValid() = %v, want %v", got, tt.want)
   152  			}
   153  		})
   154  	}
   155  }
   156  
   157  func TestNetInterworkingModelSetModel(t *testing.T) {
   158  	var n NetInterworkingModel
   159  	tests := []struct {
   160  		name      string
   161  		modelName string
   162  		wantErr   bool
   163  	}{
   164  		{"Invalid Model", "Invalid", true},
   165  		{"default Model", defaultNetModelStr, false},
   166  		{"macvtap Model", macvtapNetModelStr, false},
   167  		{"tcfilter Model", tcFilterNetModelStr, false},
   168  		{"none Model", noneNetModelStr, false},
   169  	}
   170  
   171  	for _, tt := range tests {
   172  		t.Run(tt.name, func(t *testing.T) {
   173  			if err := n.SetModel(tt.modelName); (err != nil) != tt.wantErr {
   174  				t.Errorf("NetInterworkingModel.SetModel() error = %v, wantErr %v", err, tt.wantErr)
   175  			}
   176  		})
   177  	}
   178  }
   179  
   180  func TestGenerateRandomPrivateMacAdd(t *testing.T) {
   181  	assert := assert.New(t)
   182  
   183  	addr1, err := generateRandomPrivateMacAddr()
   184  	assert.NoError(err)
   185  
   186  	_, err = net.ParseMAC(addr1)
   187  	assert.NoError(err)
   188  
   189  	addr2, err := generateRandomPrivateMacAddr()
   190  	assert.NoError(err)
   191  
   192  	_, err = net.ParseMAC(addr2)
   193  	assert.NoError(err)
   194  
   195  	assert.NotEqual(addr1, addr2)
   196  }
   197  
   198  func TestCreateGetTunTapLink(t *testing.T) {
   199  	if tc.NotValid(ktu.NeedRoot()) {
   200  		t.Skip(testDisabledAsNonRoot)
   201  	}
   202  
   203  	assert := assert.New(t)
   204  
   205  	netHandle, err := netlink.NewHandle()
   206  	defer netHandle.Delete()
   207  
   208  	assert.NoError(err)
   209  
   210  	tapName := "testtap0"
   211  	tapLink, fds, err := createLink(netHandle, tapName, &netlink.Tuntap{}, 1)
   212  	assert.NoError(err)
   213  	assert.NotNil(tapLink)
   214  	assert.NotZero(len(fds))
   215  
   216  	tapLink, err = getLinkByName(netHandle, tapName, &netlink.Tuntap{})
   217  	assert.NoError(err)
   218  
   219  	err = netHandle.LinkDel(tapLink)
   220  	assert.NoError(err)
   221  }
   222  
   223  func TestCreateMacVtap(t *testing.T) {
   224  	if tc.NotValid(ktu.NeedRoot()) {
   225  		t.Skip(testDisabledAsNonRoot)
   226  	}
   227  
   228  	assert := assert.New(t)
   229  
   230  	netHandle, err := netlink.NewHandle()
   231  	defer netHandle.Delete()
   232  
   233  	assert.NoError(err)
   234  
   235  	tapName := "testtap0"
   236  	tapLink, _, err := createLink(netHandle, tapName, &netlink.Tuntap{}, 1)
   237  	assert.NoError(err)
   238  
   239  	attrs := tapLink.Attrs()
   240  
   241  	mcLink := &netlink.Macvtap{
   242  		Macvlan: netlink.Macvlan{
   243  			LinkAttrs: netlink.LinkAttrs{
   244  				TxQLen:      attrs.TxQLen,
   245  				ParentIndex: attrs.Index,
   246  			},
   247  		},
   248  	}
   249  
   250  	macvtapName := "testmc0"
   251  	_, err = createMacVtap(netHandle, macvtapName, mcLink, 1)
   252  	assert.NoError(err)
   253  
   254  	macvtapLink, err := getLinkByName(netHandle, macvtapName, &netlink.Macvtap{})
   255  	assert.NoError(err)
   256  
   257  	err = netHandle.LinkDel(macvtapLink)
   258  	assert.NoError(err)
   259  
   260  	tapLink, err = getLinkByName(netHandle, tapName, &netlink.Tuntap{})
   261  	assert.NoError(err)
   262  
   263  	err = netHandle.LinkDel(tapLink)
   264  	assert.NoError(err)
   265  }
   266  
   267  func TestTcRedirectNetwork(t *testing.T) {
   268  	if tc.NotValid(ktu.NeedRoot()) {
   269  		t.Skip(testDisabledAsNonRoot)
   270  	}
   271  
   272  	assert := assert.New(t)
   273  
   274  	netHandle, err := netlink.NewHandle()
   275  	assert.NoError(err)
   276  	defer netHandle.Delete()
   277  
   278  	// Create a test veth interface.
   279  	vethName := "foo"
   280  	veth := &netlink.Veth{LinkAttrs: netlink.LinkAttrs{Name: vethName, TxQLen: 200, MTU: 1400}, PeerName: "bar"}
   281  
   282  	err = netlink.LinkAdd(veth)
   283  	assert.NoError(err)
   284  
   285  	endpoint, err := createVethNetworkEndpoint(1, vethName, NetXConnectTCFilterModel)
   286  	assert.NoError(err)
   287  
   288  	link, err := netlink.LinkByName(vethName)
   289  	assert.NoError(err)
   290  
   291  	err = netHandle.LinkSetUp(link)
   292  	assert.NoError(err)
   293  
   294  	err = setupTCFiltering(endpoint, 1, true)
   295  	assert.NoError(err)
   296  
   297  	err = removeTCFiltering(endpoint)
   298  	assert.NoError(err)
   299  
   300  	// Remove the veth created for testing.
   301  	err = netHandle.LinkDel(link)
   302  	assert.NoError(err)
   303  }