diff --git a/src/runtime/virtcontainers/clh.go b/src/runtime/virtcontainers/clh.go index df493f4b3d..23a16f46f1 100644 --- a/src/runtime/virtcontainers/clh.go +++ b/src/runtime/virtcontainers/clh.go @@ -1457,25 +1457,22 @@ func (clh *cloudHypervisor) addNet(e Endpoint) error { mac := e.HardwareAddr() netPair := e.NetworkPair() if netPair == nil { - return errors.New("net Pair to be added is nil, needed to get TAP path") + return errors.New("net Pair to be added is nil, needed to get TAP file descriptors") } - tapPath := netPair.TapInterface.TAPIface.Name - if tapPath == "" { - return errors.New("TAP path in network pair is empty") + if len(netPair.TapInterface.VMFds) == 0 { + return errors.New("The file descriptors for the network pair are not present") } clh.netDevicesFiles[mac] = netPair.TapInterface.VMFds clh.Logger().WithFields(log.Fields{ "mac": mac, - "tap": tapPath, }).Info("Adding Net") netRateLimiterConfig := clh.getNetRateLimiterConfig() net := chclient.NewNetConfig() net.Mac = &mac - net.Tap = &tapPath if netRateLimiterConfig != nil { net.SetRateLimiterConfig(*netRateLimiterConfig) } diff --git a/src/runtime/virtcontainers/clh_test.go b/src/runtime/virtcontainers/clh_test.go index 1343cfac78..302d945f00 100644 --- a/src/runtime/virtcontainers/clh_test.go +++ b/src/runtime/virtcontainers/clh_test.go @@ -10,6 +10,7 @@ package virtcontainers import ( "context" + "io/ioutil" "net/http" "os" "path/filepath" @@ -129,25 +130,30 @@ func TestCloudHypervisorAddVSock(t *testing.T) { // Check addNet appends to the network config list new configurations. // Check that the elements in the list has the correct values func TestCloudHypervisorAddNetCheckNetConfigListValues(t *testing.T) { - macTest := "00:00:00:00:00" - tapPath := "/path/to/tap" - assert := assert.New(t) + macTest := "00:00:00:00:00" + + file, err := ioutil.TempFile("", "netFd") + assert.Nil(err) + defer os.Remove(file.Name()) + + vmFds := make([]*os.File, 1) + vmFds = append(vmFds, file) + clh := cloudHypervisor{} clh.netDevicesFiles = make(map[string][]*os.File) e := &VethEndpoint{} e.NetPair.TAPIface.HardAddr = macTest - e.NetPair.TapInterface.TAPIface.Name = tapPath + e.NetPair.TapInterface.VMFds = vmFds - err := clh.addNet(e) + err = clh.addNet(e) assert.Nil(err) assert.Equal(len(*clh.netDevices), 1) if err == nil { assert.Equal(*(*clh.netDevices)[0].Mac, macTest) - assert.Equal(*(*clh.netDevices)[0].Tap, tapPath) } err = clh.addNet(e) @@ -156,7 +162,6 @@ func TestCloudHypervisorAddNetCheckNetConfigListValues(t *testing.T) { assert.Equal(len(*clh.netDevices), 2) if err == nil { assert.Equal(*(*clh.netDevices)[1].Mac, macTest) - assert.Equal(*(*clh.netDevices)[1].Tap, tapPath) } } @@ -165,10 +170,18 @@ func TestCloudHypervisorAddNetCheckNetConfigListValues(t *testing.T) { func TestCloudHypervisorAddNetCheckEnpointTypes(t *testing.T) { assert := assert.New(t) - tapPath := "/path/to/tap" + macTest := "00:00:00:00:00" + + file, err := ioutil.TempFile("", "netFd") + assert.Nil(err) + defer os.Remove(file.Name()) + + vmFds := make([]*os.File, 1) + vmFds = append(vmFds, file) validVeth := &VethEndpoint{} - validVeth.NetPair.TapInterface.TAPIface.Name = tapPath + validVeth.NetPair.TAPIface.HardAddr = macTest + validVeth.NetPair.TapInterface.VMFds = vmFds type args struct { e Endpoint @@ -189,9 +202,9 @@ func TestCloudHypervisorAddNetCheckEnpointTypes(t *testing.T) { clh.netDevicesFiles = make(map[string][]*os.File) if err := clh.addNet(tt.args.e); (err != nil) != tt.wantErr { t.Errorf("cloudHypervisor.addNet() error = %v, wantErr %v", err, tt.wantErr) - } else if err == nil { - assert.Equal(*(*clh.netDevices)[0].Tap, tapPath) + files := clh.netDevicesFiles[macTest] + assert.Equal(files, vmFds) } }) } @@ -201,10 +214,15 @@ func TestCloudHypervisorAddNetCheckEnpointTypes(t *testing.T) { func TestCloudHypervisorNetRateLimiter(t *testing.T) { assert := assert.New(t) - tapPath := "/path/to/tap" + file, err := ioutil.TempFile("", "netFd") + assert.Nil(err) + defer os.Remove(file.Name()) + + vmFds := make([]*os.File, 1) + vmFds = append(vmFds, file) validVeth := &VethEndpoint{} - validVeth.NetPair.TapInterface.TAPIface.Name = tapPath + validVeth.NetPair.TapInterface.VMFds = vmFds type args struct { bwMaxRate int64 diff --git a/src/runtime/virtcontainers/fc.go b/src/runtime/virtcontainers/fc.go index 3a89c7fa44..b792c90acb 100644 --- a/src/runtime/virtcontainers/fc.go +++ b/src/runtime/virtcontainers/fc.go @@ -927,6 +927,12 @@ func (fc *firecracker) fcAddNetDevice(ctx context.Context, endpoint Endpoint) { ifaceID := endpoint.Name() + // VMFds are not used by Firecracker, as it opens the tuntap + // device by its name. Let's just close those. + for _, f := range endpoint.NetworkPair().TapInterface.VMFds { + f.Close() + } + // The implementation of rate limiter is based on TBF. // Rate Limiter defines a token bucket with a maximum capacity (size) to store tokens, and an interval for refilling purposes (refill_time). // The refill-rate is derived from size and refill_time, and it is the constant rate at which the tokens replenish. diff --git a/src/runtime/virtcontainers/network_linux.go b/src/runtime/virtcontainers/network_linux.go index f8456a4976..f3356bb1cf 100644 --- a/src/runtime/virtcontainers/network_linux.go +++ b/src/runtime/virtcontainers/network_linux.go @@ -411,6 +411,16 @@ func createLink(netHandle *netlink.Handle, name string, expectedLink netlink.Lin flags := netlink.TUNTAP_VNET_HDR | netlink.TUNTAP_NO_PI if queues > 0 { flags |= netlink.TUNTAP_MULTI_QUEUE_DEFAULTS + } else { + // We need to enforce `queues = 1` here in case + // multi-queue is *not* supported, the reason being + // `linkModify()`, a method called by `LinkAdd()`, only + // returning the file descriptor of the opened tuntap + // device when the queues are set to *non zero*. + // + // Please, for more information, refer to: + // https://github.com/kata-containers/kata-containers/blob/e6e5d2593ac319329269d7b58c30f99ba7b2bf5a/src/runtime/vendor/github.com/vishvananda/netlink/link_linux.go#L1164-L1316 + queues = 1 } newLink = &netlink.Tuntap{ LinkAttrs: netlink.LinkAttrs{Name: name},