Skip to content

Commit caa886b

Browse files
committed
feat: add support for vhost-net for AuxNetDevice
add support for mounting /dev/vhost-net and /dev/net/tun for AuxNetDevice similarly to PciNetDevice. Signed-off-by: adrianc <[email protected]>
1 parent 8e991ee commit caa886b

File tree

5 files changed

+151
-11
lines changed

5 files changed

+151
-11
lines changed

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -348,14 +348,15 @@ These selectors are applicable when "deviceType" is "auxNetDevice".
348348

349349
| Field | Required | Description | Type/Defaults | Example/Accepted values |
350350
|---------------|----------|----------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|--------------------------------------------------------------------------------------------------|
351-
| "vendors" | N | Target device's vendor Hex code as string | `string` list Default: `null` | "vendors": ["8086", "15b3"] |
352-
| "devices" | N | Parent PCI device Hex code as string | `string` list Default: `null` | "devices": ["154c", "1889", "1018"] |
353-
| "drivers" | N | Target device driver names as string | `string` list Default: `null` | "drivers": ["vfio-pci"] |
354-
| "pfNames" | N | functions from PF matches list of PF names | `string` list Default: `null` | "pfNames": ["enp2s2f0"] (See follow-up sections for some advance usage of "pfNames") |
355-
| "rootDevices" | N | functions from PF matches list of PF PCI addresses | `string` list Default: `null` | "rootDevices": ["0000:86:00.0"] (See follow-up sections for some advance usage of "rootDevices") |
356-
| "linkTypes" | N | The link type of the net device associated with the PCI device | `string` list Default: `null` | "linkTypes": ["ether"] |
357-
| "isRdma" | N | Mount RDMA resources. Incompatible with vdpaType | `bool` values `true` or `false` Default: `false` | "isRdma": `true` |
358-
| "auxTypes" | N | List of vendor specific auxiliary network device types. Device type can be determined by its name: <driver_name>.<kind_of_a_type>.<id> | `string` list Default: `null` | "auxTypes": ["sf", "eth"] |
351+
| "vendors" | N | Target device's vendor Hex code as string | `string` list Default: `null` | "vendors": ["8086", "15b3"] |
352+
| "devices" | N | Parent PCI device Hex code as string | `string` list Default: `null` | "devices": ["154c", "1889", "1018"] |
353+
| "drivers" | N | Target device driver names as string | `string` list Default: `null` | "drivers": ["vfio-pci"] |
354+
| "pfNames" | N | functions from PF matches list of PF names | `string` list Default: `null` | "pfNames": ["enp2s2f0"] (See follow-up sections for some advance usage of "pfNames") |
355+
| "rootDevices" | N | functions from PF matches list of PF PCI addresses | `string` list Default: `null` | "rootDevices": ["0000:86:00.0"] (See follow-up sections for some advance usage of "rootDevices") |
356+
| "linkTypes" | N | The link type of the net device associated with the PCI device | `string` list Default: `null` | "linkTypes": ["ether"] |
357+
| "isRdma" | N | Mount RDMA resources. Incompatible with vdpaType | `bool` values `true` or `false` Default: `false` | "isRdma": `true` |
358+
| "needVhostNet" | N | Share /dev/vhost-net and /dev/net/tun | `bool` values `true` or `false` Default: `false` | "needVhostNet": `true` |
359+
| "auxTypes" | N | List of vendor specific auxiliary network device types. Device type can be determined by its name: <driver_name>.<kind_of_a_type>.<id> | `string` list Default: `null` | "auxTypes": ["sf", "eth"] |
359360

360361
[//]: # (The tables above generated using: https://ozh.github.io/ascii-tables/)
361362

pkg/auxnetdevice/auxNetDevice.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ func NewAuxNetDevice(dev *ghw.PCIDevice, deviceID string, rFactory types.Resourc
6565
glog.Warningf("RDMA resources for %s not found. Are RDMA modules loaded?", deviceID)
6666
}
6767
}
68+
69+
if nf.NeedVhostNet {
70+
if infoprovider.VhostNetDeviceExist() {
71+
infoProviders = append(infoProviders, infoprovider.NewVhostNetInfoProvider())
72+
} else {
73+
glog.Warningf("vhost-net is required in the configuration for %s but /dev/vhost-net doesn't exist", deviceID)
74+
}
75+
}
6876
}
6977

7078
hostDev, err := devices.NewHostDeviceImpl(dev, deviceID, rFactory, rc, infoProviders)

pkg/auxnetdevice/auxNetDevice_test.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package auxnetdevice_test
1919

2020
import (
21+
"path/filepath"
2122
"testing"
2223

2324
"github.com/jaypipes/ghw"
@@ -28,6 +29,7 @@ import (
2829

2930
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/auxnetdevice"
3031
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/factory"
32+
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/infoprovider"
3133
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types"
3234
tmocks "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types/mocks"
3335
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils"
@@ -299,5 +301,133 @@ var _ = Describe("AuxNetDevice", func() {
299301
fakeSriovnetProvider.AssertExpectations(t)
300302
})
301303
})
304+
305+
Context("with needVhostNet", func() {
306+
It("should provide expected environment variables and mounts", func() {
307+
fs := &utils.FakeFilesystem{
308+
Dirs: []string{
309+
"sys/bus/pci/devices/0000:00:00.1/net/net0",
310+
"sys/bus/pci/drivers/mlx5_core",
311+
"dev/net/tun",
312+
"dev/vhost-net",
313+
},
314+
Symlinks: map[string]string{
315+
"sys/bus/pci/devices/0000:00:00.1/driver": "../../../../bus/pci/drivers/mlx5_core",
316+
},
317+
Files: map[string][]byte{"sys/bus/pci/devices/0000:00:00.1/numa_node": []byte("0")},
318+
}
319+
defer fs.Use()()
320+
321+
infoprovider.HostNet = filepath.Join(fs.RootDir, "dev/vhost-net")
322+
infoprovider.HostTun = filepath.Join(fs.RootDir, "dev/net/tun")
323+
324+
utils.SetDefaultMockNetlinkProvider()
325+
auxDevID := "mlx5_core.sf.0"
326+
fakeSriovnetProvider := mocks.SriovnetProvider{}
327+
fakeSriovnetProvider.
328+
On("GetUplinkRepresentorFromAux", auxDevID).Return("net0", nil).
329+
On("GetPfPciFromAux", auxDevID).Return("0000:00:00.1", nil).
330+
On("GetSfIndexByAuxDev", auxDevID).Return(1, nil).
331+
On("GetNetDevicesFromAux", auxDevID).Return([]string{"eth0"}, nil)
332+
utils.SetSriovnetProviderInst(&fakeSriovnetProvider)
333+
334+
f := factory.NewResourceFactory("fake", "fake", true, false)
335+
in := newPciDevice("0000:00:00.1")
336+
rc := &types.ResourceConfig{
337+
ResourceName: "fake",
338+
ResourcePrefix: "fake",
339+
DeviceType: types.AuxNetDeviceType,
340+
SelectorObjs: []interface{}{&types.AuxNetDeviceSelectors{
341+
NeedVhostNet: true,
342+
}}}
343+
344+
dev, err := auxnetdevice.NewAuxNetDevice(in, auxDevID, f, rc, 0)
345+
Expect(err).NotTo(HaveOccurred())
346+
Expect(dev).NotTo(BeNil())
347+
Expect(dev.GetDriver()).To(Equal("mlx5_core"))
348+
Expect(dev.GetNetName()).To(Equal("eth0"))
349+
350+
envs := dev.GetEnvVal()
351+
Expect(envs).To(HaveLen(2))
352+
// validate device ID env var
353+
Expect(envs).To(HaveKey("generic"))
354+
Expect(envs["generic"]).To(HaveKeyWithValue("deviceID", "mlx5_core.sf.0"))
355+
// validate vhost env vars
356+
Expect(envs).To(HaveKey("vhost"))
357+
Expect(envs["vhost"]).To(HaveKeyWithValue("net-mount", "/dev/vhost-net"))
358+
Expect(envs["vhost"]).To(HaveKeyWithValue("tun-mount", "/dev/net/tun"))
359+
360+
// validate mounts
361+
devSpecs := dev.GetDeviceSpecs()
362+
Expect(devSpecs).To(HaveLen(2))
363+
Expect(devSpecs).To(ConsistOf(
364+
And(HaveField("HostPath", "/dev/vhost-net"), HaveField("ContainerPath", "/dev/vhost-net")),
365+
And(HaveField("HostPath", "/dev/net/tun"), HaveField("ContainerPath", "/dev/net/tun")),
366+
))
367+
368+
Expect(dev.GetLinkType()).To(Equal("fakeLinkType"))
369+
Expect(dev.GetFuncID()).To(Equal(1))
370+
Expect(dev.GetAPIDevice().Topology.Nodes[0].ID).To(Equal(int64(0)))
371+
Expect(dev.GetAuxType()).To(Equal("sf"))
372+
fakeSriovnetProvider.AssertExpectations(t)
373+
})
374+
375+
It("should not contain vhost related environment variables and mounts if vhost-net device does not exist", func() {
376+
fs := &utils.FakeFilesystem{
377+
Dirs: []string{
378+
"sys/bus/pci/devices/0000:00:00.1/net/net0",
379+
"sys/bus/pci/drivers/mlx5_core",
380+
},
381+
Symlinks: map[string]string{
382+
"sys/bus/pci/devices/0000:00:00.1/driver": "../../../../bus/pci/drivers/mlx5_core",
383+
},
384+
Files: map[string][]byte{"sys/bus/pci/devices/0000:00:00.1/numa_node": []byte("0")},
385+
}
386+
defer fs.Use()()
387+
388+
infoprovider.HostNet = filepath.Join(fs.RootDir, "dev/vhost-net")
389+
infoprovider.HostTun = filepath.Join(fs.RootDir, "dev/net/tun")
390+
391+
utils.SetDefaultMockNetlinkProvider()
392+
auxDevID := "mlx5_core.sf.0"
393+
fakeSriovnetProvider := mocks.SriovnetProvider{}
394+
fakeSriovnetProvider.
395+
On("GetUplinkRepresentorFromAux", auxDevID).Return("net0", nil).
396+
On("GetPfPciFromAux", auxDevID).Return("0000:00:00.1", nil).
397+
On("GetSfIndexByAuxDev", auxDevID).Return(1, nil).
398+
On("GetNetDevicesFromAux", auxDevID).Return([]string{"eth0"}, nil)
399+
utils.SetSriovnetProviderInst(&fakeSriovnetProvider)
400+
401+
f := factory.NewResourceFactory("fake", "fake", true, false)
402+
in := newPciDevice("0000:00:00.1")
403+
rc := &types.ResourceConfig{
404+
ResourceName: "fake",
405+
ResourcePrefix: "fake",
406+
DeviceType: types.AuxNetDeviceType,
407+
SelectorObjs: []interface{}{&types.AuxNetDeviceSelectors{
408+
NeedVhostNet: true,
409+
}}}
410+
411+
dev, err := auxnetdevice.NewAuxNetDevice(in, auxDevID, f, rc, 0)
412+
Expect(err).NotTo(HaveOccurred())
413+
Expect(dev).NotTo(BeNil())
414+
Expect(dev.GetDriver()).To(Equal("mlx5_core"))
415+
Expect(dev.GetNetName()).To(Equal("eth0"))
416+
417+
envs := dev.GetEnvVal()
418+
Expect(envs).To(HaveLen(1))
419+
// validate device ID env var
420+
Expect(envs).To(HaveKey("generic"))
421+
Expect(envs["generic"]).To(HaveKeyWithValue("deviceID", "mlx5_core.sf.0"))
422+
423+
// validate no mounts
424+
Expect(dev.GetDeviceSpecs()).To(BeEmpty())
425+
Expect(dev.GetLinkType()).To(Equal("fakeLinkType"))
426+
Expect(dev.GetFuncID()).To(Equal(1))
427+
Expect(dev.GetAPIDevice().Topology.Nodes[0].ID).To(Equal(int64(0)))
428+
Expect(dev.GetAuxType()).To(Equal("sf"))
429+
fakeSriovnetProvider.AssertExpectations(t)
430+
})
431+
})
302432
})
303433
})

pkg/netdevice/pciNetDevice.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func NewPciNetDevice(dev *ghw.PCIDevice,
7878
if infoprovider.VhostNetDeviceExist() {
7979
infoProviders = append(infoProviders, infoprovider.NewVhostNetInfoProvider())
8080
} else {
81-
glog.Errorf("GetDeviceSpecs(): vhost-net is required in the configuration but /dev/vhost-net doesn't exist")
81+
glog.Warningf("vhost-net is required in the configuration for %s but /dev/vhost-net doesn't exist", dev.Address)
8282
}
8383
}
8484
}

pkg/types/types.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ type NetDeviceSelectors struct {
135135
GenericPciDeviceSelectors
136136
GenericNetDeviceSelectors
137137
DDPProfiles []string `json:"ddpProfiles,omitempty"`
138-
NeedVhostNet bool // share vhost-net along the selected resource
138+
NeedVhostNet bool `json:"needVhostNet,omitempty"` // share vhost-net along the selected resource
139139
VdpaType VdpaType `json:"vdpaType,omitempty"`
140140
PKeys []string `json:"pKeys,omitempty"`
141141
}
@@ -150,7 +150,8 @@ type AccelDeviceSelectors struct {
150150
type AuxNetDeviceSelectors struct {
151151
DeviceSelectors
152152
GenericNetDeviceSelectors
153-
AuxTypes []string `json:"auxTypes,omitempty"`
153+
AuxTypes []string `json:"auxTypes,omitempty"`
154+
NeedVhostNet bool `json:"needVhostNet,omitempty"` // share vhost-net along the selected resource
154155
}
155156

156157
// ResourceConfList is list of ResourceConfig

0 commit comments

Comments
 (0)