diff --git a/README.md b/README.md index d7821f442..3989e6666 100644 --- a/README.md +++ b/README.md @@ -326,7 +326,7 @@ These selectors are applicable when "deviceType" is "accelerator". These selectors are applicable when "deviceType" is "netDevice" (note: this is default) -| Field | Required | Description | Type/Defaults | Example/Accepted values | +| Field | Required | Description | Type/Defaults | Example/Accepted values | |----------------|----------|--------------------------------------------------------------------------|-----------------------------------------------------|--------------------------------------------------------------------------------------------------| | "vendors" | N | Target device's vendor Hex code as string | `string` list Default: `null` | "vendors": ["8086", "15b3"] | | "devices" | N | Target Devices' device Hex code as string | `string` list Default: `null` | "devices": ["154c", "1889", "1018"] | @@ -337,6 +337,7 @@ These selectors are applicable when "deviceType" is "netDevice" (note: this is d | "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") | | "linkTypes" | N | The link type of the net device associated with the PCI device | `string` list Default: `null` | "linkTypes": ["ether"] | | "ddpProfiles" | N | A map of device selectors | `string` list Default: `null` | "ddpProfiles": ["GTPv1-C/U IPv4/IPv6 payload"] | +| "pKeys" | N | Infiniband Partition Keys. Will match only to the devices' default (index0) PKeys. Compatible only with linkTypes = infiniband | `string` list Default: `null` | "pKeys": ["0x1", "0xABCD", "0x50"] | | "isRdma" | N | Mount RDMA resources. Incompatible with vdpaType | `bool` values `true` or `false` Default: `false` | "isRdma": `true` | | "needVhostNet" | N | Share /dev/vhost-net and /dev/net/tun | `bool` values `true` or `false` Default: `false` | "needVhostNet": `true` | | "vdpaType" | N | The type of vDPA device (virtio, vhost). Incompatible with isRdma = true | `string` values `vhost` or `virtio` Default: `null` | "vdpaType": "vhost" | diff --git a/go.mod b/go.mod index 8faf1c04e..9e5aacd2e 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/jaypipes/pcidb v1.0.0 github.com/k8snetworkplumbingwg/govdpa v0.1.4 github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0 - github.com/k8snetworkplumbingwg/sriovnet v1.2.0 + github.com/k8snetworkplumbingwg/sriovnet v1.2.1-0.20240128120937-3ca5e43034e6 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.30.0 github.com/pkg/errors v0.9.1 @@ -50,7 +50,7 @@ require ( github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb // indirect github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/spf13/afero v1.9.4 // indirect + github.com/spf13/afero v1.9.5 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/vishvananda/netns v0.0.4 // indirect diff --git a/go.sum b/go.sum index 99d7cc4dc..5661a9cbc 100644 --- a/go.sum +++ b/go.sum @@ -203,8 +203,8 @@ github.com/k8snetworkplumbingwg/govdpa v0.1.4 h1:e6mM7JFZkLVJeMQw3px96EigHAhnb4V github.com/k8snetworkplumbingwg/govdpa v0.1.4/go.mod h1:UQR1xu7A+nnRK1dkLEi12OnNL0OiBPpIKOYDuaQQkck= github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0 h1:VzM3TYHDgqPkettiP6I6q2jOeQFL4nrJM+UcAc4f6Fs= github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0/go.mod h1:nqCI7aelBJU61wiBeeZWJ6oi4bJy5nrjkM6lWIMA4j0= -github.com/k8snetworkplumbingwg/sriovnet v1.2.0 h1:6ELfAxCB1dvosGUy3DVRmfH+HWTzmPD3W67HKQvMR1M= -github.com/k8snetworkplumbingwg/sriovnet v1.2.0/go.mod h1:jyWzGe6ZtYiPq6ih6aXCOy6mZ49Y9mNyBOLBBXnli+k= +github.com/k8snetworkplumbingwg/sriovnet v1.2.1-0.20240128120937-3ca5e43034e6 h1:Ho6fhRwqgow7ytMgQ1/55j1gG5AbkxIYRbAhJnXr/MM= +github.com/k8snetworkplumbingwg/sriovnet v1.2.1-0.20240128120937-3ca5e43034e6/go.mod h1:LuzcqxxXdSgopWe1yo2kQFSgFTz9Ec5qLu6bb0s5Ut4= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -269,8 +269,8 @@ github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/spf13/afero v1.9.4 h1:Sd43wM1IWz/s1aVXdOBkjJvuP8UdyqioeE4AmM0QsBs= -github.com/spf13/afero v1.9.4/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -322,7 +322,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -392,6 +392,7 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= @@ -462,6 +463,7 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -482,6 +484,7 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= diff --git a/pkg/factory/factory.go b/pkg/factory/factory.go index 5738d2302..15a287658 100644 --- a/pkg/factory/factory.go +++ b/pkg/factory/factory.go @@ -99,6 +99,8 @@ func (rf *resourceFactory) GetSelector(attr string, values []string) (types.Devi return resources.NewDdpSelector(values), nil case "auxTypes": return resources.NewAuxTypeSelector(values), nil + case "pKeys": + return resources.NewPKeySelector(values), nil default: return nil, fmt.Errorf("GetSelector(): invalid attribute %s", attr) } diff --git a/pkg/factory/factory_test.go b/pkg/factory/factory_test.go index 9afba6bbb..8d5251627 100644 --- a/pkg/factory/factory_test.go +++ b/pkg/factory/factory_test.go @@ -97,6 +97,7 @@ var _ = Describe("Factory", func() { Entry("rootDevices", "rootDevices", true, reflect.TypeOf(resources.NewRootDeviceSelector([]string{}))), Entry("linkTypes", "linkTypes", true, reflect.TypeOf(resources.NewLinkTypeSelector([]string{}))), Entry("ddpProfiles", "ddpProfiles", true, reflect.TypeOf(resources.NewDdpSelector([]string{}))), + Entry("pKeys", "pKeys", true, reflect.TypeOf(resources.NewPKeySelector([]string{}))), Entry("invalid", "fakeAndInvalid", false, reflect.TypeOf(nil)), ) Describe("getting resource pool for netdevice", func() { @@ -119,6 +120,7 @@ var _ = Describe("Factory", func() { rootDevices := []string{"0000:86:00.0", "0000:86:00.1", "0000:86:00.2", "0000:86:00.3"} linkTypes := []string{"ether", "infiniband", "other", "other2"} ddpProfiles := []string{"GTP", "PPPoE", "GTP", "PPPoE"} + pKeys := []string{"0x1", "0x2", "0xABCD", "0x50"} for i := range devs { d := &mocks.PciNetDevice{} d.On("GetVendor").Return(vendors[i]). @@ -130,7 +132,8 @@ var _ = Describe("Factory", func() { On("GetPfPciAddr").Return(rootDevices[i]). On("GetAPIDevice").Return(&pluginapi.Device{}). On("GetLinkType").Return(linkTypes[i]). - On("GetDDPProfiles").Return(ddpProfiles[i]) + On("GetDDPProfiles").Return(ddpProfiles[i]). + On("GetPKey").Return(pKeys[i]) devs[i] = d } @@ -145,7 +148,8 @@ var _ = Describe("Factory", func() { "pfNames": ["enp2s0f2"], "rootDevices": ["0000:86:00.0"], "linkTypes": ["ether"], - "ddpProfiles": ["GTP"] + "ddpProfiles": ["GTP"], + "pKeys": ["0x1"] } ]`), ) @@ -197,6 +201,7 @@ var _ = Describe("Factory", func() { rootDevices := []string{"0000:86:00.0", "0000:86:00.1", "0000:86:00.2", "0000:86:00.3"} linkTypes := []string{"ether", "infiniband", "other", "other2"} ddpProfiles := []string{"GTP", "PPPoE", "GTP", "PPPoE"} + pKeys := []string{"0x1", "0x2", "0xABCD", "0x50"} for i := range devs { d := &mocks.PciNetDevice{} d.On("GetVendor").Return(vendors[i]). @@ -209,7 +214,8 @@ var _ = Describe("Factory", func() { On("GetAPIDevice").Return(&pluginapi.Device{}). On("GetLinkType").Return(linkTypes[i]). On("GetDDPProfiles").Return(ddpProfiles[i]). - On("GetFuncID").Return(-1) + On("GetFuncID").Return(-1). + On("GetPKey").Return(pKeys[i]) devs[i] = d } @@ -254,7 +260,8 @@ var _ = Describe("Factory", func() { "pfNames": ["enp2s0f2"], "rootDevices": ["0000:86:00.0"], "linkTypes": ["ether"], - "ddpProfiles": ["GTP"] + "ddpProfiles": ["GTP"], + "pKeys": ["0x1"] }`), []string{"0000:03:02.0"}), Entry("with a slice of one selector object it should match devices", []byte(` [{ @@ -265,7 +272,8 @@ var _ = Describe("Factory", func() { "pfNames": ["enp2s0f2"], "rootDevices": ["0000:86:00.0"], "linkTypes": ["ether"], - "ddpProfiles": ["GTP"] + "ddpProfiles": ["GTP"], + "pKeys": ["0x1"] }]`), []string{"0000:03:02.0"}), Entry("with more than one selector object, it should match devices from all selector objects", []byte(` [{ @@ -276,7 +284,8 @@ var _ = Describe("Factory", func() { "pfNames": ["enp2s0f2"], "rootDevices": ["0000:86:00.0"], "linkTypes": ["ether"], - "ddpProfiles": ["GTP"] + "ddpProfiles": ["GTP"], + "pKeys": ["0x1"] }, { "vendors": ["8086"], "devices": ["1111"], @@ -285,7 +294,8 @@ var _ = Describe("Factory", func() { "pfNames": ["net2"], "rootDevices": ["0000:86:00.3"], "linkTypes": ["other2"], - "ddpProfiles": ["PPPoE"] + "ddpProfiles": ["PPPoE"], + "pKeys": ["0x50"] }]`), []string{"0000:03:02.0", "0000:03:02.3"}), ) Describe("getting exclusive resource pool for netdevice", func() { @@ -308,6 +318,7 @@ var _ = Describe("Factory", func() { rootDevices := []string{"0000:86:00.0", "0000:86:00.1", "0000:86:00.2", "0000:86:00.3"} linkTypes := []string{"ether", "infiniband", "other", "other2"} ddpProfiles := []string{"GTP", "PPPoE", "GTP", "PPPoE"} + pKeys := []string{"0x1", "0x2", "0xABCD", "0x50"} for i := range devs { d := &mocks.PciNetDevice{} d.On("GetVendor").Return(vendors[i]). @@ -320,7 +331,8 @@ var _ = Describe("Factory", func() { On("GetAPIDevice").Return(&pluginapi.Device{}). On("GetLinkType").Return(linkTypes[i]). On("GetDDPProfiles").Return(ddpProfiles[i]). - On("GetFuncID").Return(-1) + On("GetFuncID").Return(-1). + On("GetPKey").Return(pKeys[i]) devs[i] = d } @@ -334,7 +346,8 @@ var _ = Describe("Factory", func() { "pfNames": ["enp2s0f2"], "rootDevices": ["0000:86:00.0"], "linkTypes": ["ether"], - "ddpProfiles": ["GTP"] + "ddpProfiles": ["GTP"], + "pKeys": ["0x1"] } `), ) @@ -350,7 +363,8 @@ var _ = Describe("Factory", func() { "pfNames": ["enp2s0f2"], "rootDevices": ["0000:86:00.0"], "linkTypes": ["ether"], - "ddpProfiles": ["GTP"] + "ddpProfiles": ["GTP"], + "pKeys": ["0x1"] }] `), ) diff --git a/pkg/netdevice/netDeviceProvider.go b/pkg/netdevice/netDeviceProvider.go index 11ec41319..4d3d15b8d 100644 --- a/pkg/netdevice/netDeviceProvider.go +++ b/pkg/netdevice/netDeviceProvider.go @@ -125,6 +125,9 @@ func (np *netDeviceProvider) GetFilteredDevices(devices []types.HostDevice, // filter by DDP Profiles list filteredDevice = rf.FilterBySelector("ddpProfiles", nf.DDPProfiles, filteredDevice) + // filter by PKeys list + filteredDevice = rf.FilterBySelector("pKeys", nf.PKeys, filteredDevice) + // filter for rdma devices if nf.IsRdma { rdmaDevices := make([]types.HostDevice, 0) diff --git a/pkg/netdevice/pciNetDevice.go b/pkg/netdevice/pciNetDevice.go index b200ed8e3..26821ffe3 100644 --- a/pkg/netdevice/pciNetDevice.go +++ b/pkg/netdevice/pciNetDevice.go @@ -30,9 +30,12 @@ type pciNetDevice struct { devices.GenPciDevice devices.GenNetDevice vdpaDev types.VdpaDevice + pKey string } // NewPciNetDevice returns an instance of PciNetDevice interface +// +//nolint:gocyclo func NewPciNetDevice(dev *ghw.PCIDevice, rFactory types.ResourceFactory, rc *types.ResourceConfig, selectorIndex int) (types.PciNetDevice, error) { var vdpaDev types.VdpaDevice @@ -95,11 +98,21 @@ func NewPciNetDevice(dev *ghw.PCIDevice, return nil, err } + pKey := "" + if netDev.GetLinkType() == "infiniband" { + pciAddr := pciDev.GetPciAddr() + pKey, err = utils.GetPKey(pciAddr) + if err != nil { + glog.Infof("getPKey(): unable to get PKey for device %s : %q", pciAddr, err) + } + } + return &pciNetDevice{ HostDevice: hostDev, GenPciDevice: *pciDev, GenNetDevice: *netDev, vdpaDev: vdpaDev, + pKey: pKey, }, nil } @@ -116,3 +129,7 @@ func (nd *pciNetDevice) GetDDPProfiles() string { func (nd *pciNetDevice) GetVdpaDevice() types.VdpaDevice { return nd.vdpaDev } + +func (nd *pciNetDevice) GetPKey() string { + return nd.pKey +} diff --git a/pkg/resources/pKeySelector.go b/pkg/resources/pKeySelector.go new file mode 100644 index 000000000..7b06824ce --- /dev/null +++ b/pkg/resources/pKeySelector.go @@ -0,0 +1,27 @@ +package resources + +import ( + "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types" +) + +type pKeySelector struct { + pKeys []string +} + +// NewPKeySelector returns a DeviceSelector interface to filter devices based on available PKeys +func NewPKeySelector(pKeys []string) types.DeviceSelector { + return &pKeySelector{pKeys: pKeys} +} + +func (ds *pKeySelector) Filter(inDevices []types.HostDevice) []types.HostDevice { + filteredList := make([]types.HostDevice, 0) + + for _, dev := range inDevices { + pKey := dev.(types.PciNetDevice).GetPKey() + if pKey != "" && contains(ds.pKeys, pKey) { + filteredList = append(filteredList, dev) + } + } + + return filteredList +} diff --git a/pkg/resources/pKeySelector_test.go b/pkg/resources/pKeySelector_test.go new file mode 100644 index 000000000..288744a95 --- /dev/null +++ b/pkg/resources/pKeySelector_test.go @@ -0,0 +1,37 @@ +package resources_test + +import ( + "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/resources" + "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types" + "github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types/mocks" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("PKeySelector", func() { + Describe("PKey selector", func() { + Context("filtering", func() { + It("should return devices matching given PKeys", func() { + pKeys := []string{"0x1", "0x2"} + sel := resources.NewPKeySelector(pKeys) + + dev0 := mocks.PciNetDevice{} + dev0.On("GetPKey").Return("0x1") + + dev1 := mocks.PciNetDevice{} + dev1.On("GetPKey").Return("0x2") + + dev2 := mocks.PciNetDevice{} + dev2.On("GetPKey").Return("0x3") + + in := []types.HostDevice{&dev0, &dev1, &dev2} + filtered := sel.Filter(in) + + Expect(filtered).To(ContainElement(&dev0)) + Expect(filtered).To(ContainElement(&dev1)) + Expect(filtered).NotTo(ContainElement(&dev2)) + }) + }) + }) +}) diff --git a/pkg/types/mocks/PciNetDevice.go b/pkg/types/mocks/PciNetDevice.go index e17fe7267..4188c6815 100644 --- a/pkg/types/mocks/PciNetDevice.go +++ b/pkg/types/mocks/PciNetDevice.go @@ -290,6 +290,20 @@ func (_m *PciNetDevice) IsRdma() bool { return r0 } +// GetPKey provides a mock function with given fields: +func (_m *PciNetDevice) GetPKey() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + // NewPciNetDevice creates a new instance of PciNetDevice. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewPciNetDevice(t interface { diff --git a/pkg/types/types.go b/pkg/types/types.go index 757368f8e..3b7066087 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -136,6 +136,7 @@ type NetDeviceSelectors struct { DDPProfiles []string `json:"ddpProfiles,omitempty"` NeedVhostNet bool // share vhost-net along the selected resource VdpaType VdpaType `json:"vdpaType,omitempty"` + PKeys []string `json:"pKeys,omitempty"` } // AccelDeviceSelectors contains accelerator(FPGA etc.) related selectors fields @@ -281,6 +282,8 @@ type PciNetDevice interface { GetDDPProfiles() string // GetVdpaDevice returns VDPA device GetVdpaDevice() VdpaDevice + // GetPKey return IB Partition key + GetPKey() string } // AccelDevice extends PciDevice interface diff --git a/pkg/utils/mocks/SriovnetProvider.go b/pkg/utils/mocks/SriovnetProvider.go index 04b7cbccb..a0e76ed7f 100644 --- a/pkg/utils/mocks/SriovnetProvider.go +++ b/pkg/utils/mocks/SriovnetProvider.go @@ -157,6 +157,30 @@ func (_m *SriovnetProvider) GetUplinkRepresentorFromAux(auxDev string) (string, return r0, r1 } +// GetDefaultPKeyFromPci provides a mock function with given fields: pciAddr +func (_m *SriovnetProvider) GetDefaultPKeyFromPci(pciAddr string) (string, error) { + ret := _m.Called(pciAddr) + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(string) (string, error)); ok { + return rf(pciAddr) + } + if rf, ok := ret.Get(0).(func(string) string); ok { + r0 = rf(pciAddr) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(pciAddr) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // NewSriovnetProvider creates a new instance of SriovnetProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewSriovnetProvider(t interface { diff --git a/pkg/utils/sriovnet_provider.go b/pkg/utils/sriovnet_provider.go index 4f10255fd..05ef96ccc 100644 --- a/pkg/utils/sriovnet_provider.go +++ b/pkg/utils/sriovnet_provider.go @@ -12,6 +12,7 @@ type SriovnetProvider interface { GetSfIndexByAuxDev(auxDev string) (int, error) GetNetDevicesFromAux(auxDev string) ([]string, error) GetAuxNetDevicesFromPci(pciAddr string) ([]string, error) + GetDefaultPKeyFromPci(pciAddr string) (string, error) } type defaultSriovnetProvider struct { @@ -52,3 +53,7 @@ func (defaultSriovnetProvider) GetNetDevicesFromAux(auxDev string) ([]string, er func (defaultSriovnetProvider) GetAuxNetDevicesFromPci(pciAddr string) ([]string, error) { return sriovnet.GetAuxNetDevicesFromPci(pciAddr) } + +func (defaultSriovnetProvider) GetDefaultPKeyFromPci(pciAddr string) (string, error) { + return sriovnet.GetDefaultPKeyFromPci(pciAddr) +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 1377a5e73..262525035 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -537,3 +537,27 @@ func ParseAuxDeviceType(deviceID string) string { // not an auxiliary device return "" } + +// isInfinibandDevice checks if a pci device has infiniband config folder +func isInfinibandDevice(pciAddr string) bool { + totalVfFilePath := filepath.Join(sysBusPci, pciAddr, "infiniband") + if _, err := os.Stat(totalVfFilePath); err != nil { + return false + } + return true +} + +// GetPKey returns IB Partition Key for the given IB device +// If device is not IB device or has no PKey then it will return empty string +func GetPKey(pciAddr string) (string, error) { + if !isInfinibandDevice(pciAddr) { + return "", nil + } + + pKey, err := GetSriovnetProvider().GetDefaultPKeyFromPci(pciAddr) + if err != nil { + return "", err + } + + return pKey, nil +} diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/.gitignore b/vendor/github.com/k8snetworkplumbingwg/sriovnet/.gitignore new file mode 100644 index 000000000..860dc4918 --- /dev/null +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/.gitignore @@ -0,0 +1,31 @@ + +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +*.cover +*.lcov + +# Kubernetes Generated files - skip generated files, except for vendored files + +!vendor/**/zz_generated.* + +# editor and IDE paraphernalia +.idea +.vscode +*.swp +*.swo +*~ + +# Folders +bin +testbin +build diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/.golangci.yml b/vendor/github.com/k8snetworkplumbingwg/sriovnet/.golangci.yml index 64dbb3614..108d8c67c 100644 --- a/vendor/github.com/k8snetworkplumbingwg/sriovnet/.golangci.yml +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/.golangci.yml @@ -76,7 +76,6 @@ linters: disable-all: true enable: - bodyclose - - depguard - dogsled - dupl - errcheck diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/Makefile b/vendor/github.com/k8snetworkplumbingwg/sriovnet/Makefile index 180a8a809..0b3364f8d 100644 --- a/vendor/github.com/k8snetworkplumbingwg/sriovnet/Makefile +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/Makefile @@ -11,7 +11,7 @@ GCOV2LCOV := $(BIN_DIR)/gcov2lcov # golangci-lint version should be updated periodically # we keep it fixed to avoid it from unexpectedly failing on the project # in case of a version bump -GOLANGCI_LINT_VER := v1.49.0 +GOLANGCI_LINT_VER := v1.53.3 Q = $(if $(filter 1,$V),,@) @@ -32,7 +32,7 @@ lint: | $(GOLANGCI_LINT) ; $(info running golangci-lint...) @ ## Run lint tests .PHONY: test tests test: ; $(info running unit tests...) ## Run unit tests - $Q go test ./... + $Q go test -race ./... tests: test lint ; ## Run all tests @@ -41,7 +41,7 @@ COVERAGE_MODE = count test-coverage-tools: $(GCOV2LCOV) test-coverage: | test-coverage-tools; $(info running coverage tests...) @ ## Run coverage tests $Q go test -covermode=$(COVERAGE_MODE) -coverprofile=sriovnet.cover ./... - $Q $(GCOV2LCOV) -infile sriovnet.cover -outfile sriovnet.info + $Q $(GCOV2LCOV) -infile sriovnet.cover -outfile sriovnet.lcov # Tools $(GOLANGCI_LINT): | $(BIN_DIR) ; $(info building golangci-lint...) @@ -55,7 +55,7 @@ $(GCOV2LCOV): | $(BIN_DIR) ; $(info building gocov2lcov...) clean: ; $(info Cleaning...) @ ## Cleanup everything @rm -rf $(BIN_DIR) @rm sriovnet.cover - @rm sriovnet.info + @rm sriovnet.lcov .PHONY: help help: ; @ ## Show this message diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/errors.go b/vendor/github.com/k8snetworkplumbingwg/sriovnet/errors.go new file mode 100644 index 000000000..aa6ff7ebd --- /dev/null +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/errors.go @@ -0,0 +1,25 @@ +/* +Copyright 2023 NVIDIA CORPORATION & AFFILIATES + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sriovnet + +import ( + "errors" +) + +var ( + ErrDeviceNotFound = errors.New("device not found") +) diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/file_access.go b/vendor/github.com/k8snetworkplumbingwg/sriovnet/file_access.go index b0fe653b3..1bc5211af 100644 --- a/vendor/github.com/k8snetworkplumbingwg/sriovnet/file_access.go +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/file_access.go @@ -1,3 +1,19 @@ +/* +Copyright 2023 NVIDIA CORPORATION & + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + //nolint:gomnd package sriovnet diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/mofed_ib_helper.go b/vendor/github.com/k8snetworkplumbingwg/sriovnet/mofed_ib_helper.go index 0e99e4191..6bf9aad8c 100644 --- a/vendor/github.com/k8snetworkplumbingwg/sriovnet/mofed_ib_helper.go +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/mofed_ib_helper.go @@ -1,3 +1,19 @@ +/* +Copyright 2023 NVIDIA CORPORATION & AFFILIATES + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package sriovnet import ( diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet.go b/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet.go index 09dfacfe0..2504a6c93 100644 --- a/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet.go +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet.go @@ -1,3 +1,19 @@ +/* +Copyright 2023 NVIDIA CORPORATION & AFFILIATES + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package sriovnet import ( @@ -387,7 +403,7 @@ func AllocateVfByMacAddress(handle *PfNetdevHandle, vfMacAddress string) (*VfObj handle.PfNetdevName, vfMacAddress) } -func FreeVf(handle *PfNetdevHandle, vf *VfObj) { +func FreeVf(_ *PfNetdevHandle, vf *VfObj) { vf.Allocated = false log.Printf("Free vf = %v\n", *vf) } @@ -433,6 +449,24 @@ func GetVfIndexByPciAddress(vfPciAddress string) (int, error) { return -1, fmt.Errorf("vf index for %s not found", vfPciAddress) } +// gets the PF index that's associated with a VF PCI address (e.g '0000:03:00.4') +func GetPfIndexByVfPciAddress(vfPciAddress string) (int, error) { + const pciParts = 4 + pfPciAddress, err := GetPfPciFromVfPci(vfPciAddress) + if err != nil { + return -1, err + } + var domain, bus, dev, fn int + parsed, err := fmt.Sscanf(pfPciAddress, "%04x:%02x:%02x.%d", &domain, &bus, &dev, &fn) + if err != nil { + return -1, fmt.Errorf("error trying to parse PF PCI address %s: %v", pfPciAddress, err) + } + if parsed != pciParts { + return -1, fmt.Errorf("failed to parse PF PCI address %s. Unexpected format", pfPciAddress) + } + return fn, err +} + // GetPfPciFromVfPci retrieves the parent PF PCI address of the provided VF PCI address in D:B:D.f format func GetPfPciFromVfPci(vfPciAddress string) (string, error) { pfPath := filepath.Join(PciSysDir, vfPciAddress, "physfn") @@ -486,3 +520,28 @@ func GetPciFromNetDevice(name string) (string, error) { } return base, nil } + +// GetPKeyByIndexFromPci returns the PKey stored under given index for the IB PCI device +func GetPKeyByIndexFromPci(pciAddress string, index int) (string, error) { + pciDir := filepath.Join(PciSysDir, pciAddress, "infiniband") + dirEntries, err := utilfs.Fs.ReadDir(pciDir) + if err != nil { + return "", fmt.Errorf("failed to read infiniband directory: %v", err) + } + if len(dirEntries) == 0 { + return "", fmt.Errorf("infiniband directory is empty for device: %s", pciAddress) + } + + indexFilePath := filepath.Join(pciDir, dirEntries[0].Name(), "ports", "1", "pkeys", strconv.Itoa(index)) + pKeyBytes, err := utilfs.Fs.ReadFile(indexFilePath) + if err != nil { + return "", fmt.Errorf("failed to read PKey file: %v", err) + } + + return strings.TrimSpace(string(pKeyBytes)), nil +} + +// GetDefaultPKeyFromPci returns the index0 PKey for the IB PCI device +func GetDefaultPKeyFromPci(pciAddress string) (string, error) { + return GetPKeyByIndexFromPci(pciAddress, 0) +} diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_aux.go b/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_aux.go index a60061b3e..4614e1254 100644 --- a/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_aux.go +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_aux.go @@ -1,21 +1,18 @@ -/*---------------------------------------------------- - * - * 2022 NVIDIA CORPORATION & AFFILIATES - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - *---------------------------------------------------- - */ +/* +Copyright 2023 NVIDIA CORPORATION & AFFILIATES + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ package sriovnet @@ -28,6 +25,10 @@ import ( utilfs "github.com/k8snetworkplumbingwg/sriovnet/pkg/utils/filesystem" ) +const ( + u32Mask = 0xffffffff +) + // GetNetDeviceFromAux gets auxiliary device name (e.g 'mlx5_core.sf.2') and // returns the correlate netdevice func GetNetDevicesFromAux(auxDev string) ([]string, error) { @@ -103,9 +104,39 @@ func GetAuxNetDevicesFromPci(pciAddr string) ([]string, error) { auxDevs := make([]string, 0) for _, file := range files { + if !file.IsDir() { + // auxiliary devices appear as directory here. + continue + } if auxiliaryDeviceRe.MatchString(file.Name()) { auxDevs = append(auxDevs, file.Name()) } } return auxDevs, nil } + +// GetAuxSFDevByPciAndSFIndex returns auxiliary SF device name which is associated with the given parent PCI address +// and SF index. returns error if an error occurred. returns ErrDeviceNotFound error if device is not found. +func GetAuxSFDevByPciAndSFIndex(pciAddress string, sfIndex uint32) (string, error) { + devs, err := GetAuxNetDevicesFromPci(pciAddress) + if err != nil { + return "", err + } + + for _, dev := range devs { + // skip non sf devices + if !strings.Contains(dev, ".sf.") { + continue + } + + idx, err := GetSfIndexByAuxDev(dev) + if err != nil || idx < 0 { + continue + } + + if uint32(idx&u32Mask) == sfIndex { + return dev, nil + } + } + return "", ErrDeviceNotFound +} diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_helper.go b/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_helper.go index 46ab4fb7e..bb96487ed 100644 --- a/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_helper.go +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_helper.go @@ -1,3 +1,19 @@ +/* +Copyright 2023 NVIDIA CORPORATION & AFFILIATES + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package sriovnet import ( diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_switchdev.go b/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_switchdev.go index 5ccf3fadc..24ee2b749 100644 --- a/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_switchdev.go +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/sriovnet_switchdev.go @@ -1,3 +1,19 @@ +/* +Copyright 2023 NVIDIA CORPORATION & AFFILIATES + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package sriovnet import ( diff --git a/vendor/github.com/k8snetworkplumbingwg/sriovnet/utils.go b/vendor/github.com/k8snetworkplumbingwg/sriovnet/utils.go index 84772da95..dd9ec282e 100644 --- a/vendor/github.com/k8snetworkplumbingwg/sriovnet/utils.go +++ b/vendor/github.com/k8snetworkplumbingwg/sriovnet/utils.go @@ -1,21 +1,18 @@ -/*---------------------------------------------------- - * - * 2022 NVIDIA CORPORATION & AFFILIATES - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - *---------------------------------------------------- - */ +/* +Copyright 2023 NVIDIA CORPORATION & AFFILIATES + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ package sriovnet diff --git a/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/spf13/afero/memmap.go index 3f4ef42de..e6b7d70b9 100644 --- a/vendor/github.com/spf13/afero/memmap.go +++ b/vendor/github.com/spf13/afero/memmap.go @@ -15,6 +15,7 @@ package afero import ( "fmt" + "io" "log" "os" "path/filepath" @@ -237,7 +238,7 @@ func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, erro file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data()) } if flag&os.O_APPEND > 0 { - _, err = file.Seek(0, os.SEEK_END) + _, err = file.Seek(0, io.SeekEnd) if err != nil { file.Close() return nil, err diff --git a/vendor/github.com/spf13/afero/unionFile.go b/vendor/github.com/spf13/afero/unionFile.go index f02e75532..62dd6c93c 100644 --- a/vendor/github.com/spf13/afero/unionFile.go +++ b/vendor/github.com/spf13/afero/unionFile.go @@ -47,7 +47,7 @@ func (f *UnionFile) Read(s []byte) (int, error) { if (err == nil || err == io.EOF) && f.Base != nil { // advance the file position also in the base file, the next // call may be a write at this position (or a seek with SEEK_CUR) - if _, seekErr := f.Base.Seek(int64(n), os.SEEK_CUR); seekErr != nil { + if _, seekErr := f.Base.Seek(int64(n), io.SeekCurrent); seekErr != nil { // only overwrite err in case the seek fails: we need to // report an eventual io.EOF to the caller err = seekErr diff --git a/vendor/modules.txt b/vendor/modules.txt index ae630677a..75659629e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -132,8 +132,8 @@ github.com/k8snetworkplumbingwg/govdpa/pkg/kvdpa github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1 github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/utils -# github.com/k8snetworkplumbingwg/sriovnet v1.2.0 -## explicit; go 1.18 +# github.com/k8snetworkplumbingwg/sriovnet v1.2.1-0.20240128120937-3ca5e43034e6 +## explicit; go 1.20 github.com/k8snetworkplumbingwg/sriovnet github.com/k8snetworkplumbingwg/sriovnet/pkg/utils/filesystem github.com/k8snetworkplumbingwg/sriovnet/pkg/utils/netlinkops @@ -213,7 +213,7 @@ github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/spf13/afero v1.9.4 +# github.com/spf13/afero v1.9.5 ## explicit; go 1.16 github.com/spf13/afero github.com/spf13/afero/internal/common