-
Notifications
You must be signed in to change notification settings - Fork 180
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add auxiliary network devices support
Auxiliary devices pool is created when auxNetDevice type is specified in plugin config file. Auxiliary devices discovered for each discovered network PCI device, meaning only auxiliary network devices with parent PCI device are supported. New AuxTypes selector allows to filter auxiliary device by the type. For ex., given following auxiliary devices list.. driver1.sf.0 driver2.sf.0 driver2.sf.1 driver3.eth.0 .. and selector value ["sf"], first three devices will be added to the pool. Auxiliary network devices accept selectors: vendors, devices, drivers, pfNames, rootDevices, linkTypes, isRdma. Initially only "sf" auxiliary devices are supported. Signed-off-by: Dmytro Linkin <[email protected]>
- Loading branch information
1 parent
40812c2
commit 7e7aad9
Showing
22 changed files
with
1,515 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* 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 auxnetdevice | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/golang/glog" | ||
"github.com/jaypipes/ghw" | ||
|
||
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/devices" | ||
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/infoprovider" | ||
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types" | ||
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" | ||
) | ||
|
||
// auxNetDevice extends HostDevice and embedds GenNetDevice | ||
type auxNetDevice struct { | ||
types.HostDevice | ||
devices.GenNetDevice | ||
auxType string | ||
} | ||
|
||
// NewAuxNetDevice returns an instance of AciNetDevice interface | ||
func NewAuxNetDevice(dev *ghw.PCIDevice, deviceID string, rFactory types.ResourceFactory, | ||
rc *types.ResourceConfig) (types.AuxNetDevice, error) { | ||
driverName, err := utils.GetDriverName(dev.Address) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
infoProviders := make([]types.DeviceInfoProvider, 0) | ||
infoProviders = append(infoProviders, rFactory.GetDefaultInfoProvider(deviceID, driverName)) | ||
isRdma := false | ||
nf, ok := rc.SelectorObj.(*types.AuxNetDeviceSelectors) | ||
if ok { | ||
if nf.IsRdma { | ||
rdmaSpec := rFactory.GetRdmaSpec(types.AuxNetDeviceType, deviceID) | ||
if rdmaSpec.IsRdma() { | ||
isRdma = true | ||
infoProviders = append(infoProviders, infoprovider.NewRdmaInfoProvider(rdmaSpec)) | ||
} else { | ||
glog.Warningf("RDMA resources for %s not found. Are RDMA modules loaded?", deviceID) | ||
} | ||
} | ||
} | ||
|
||
hostDev, err := devices.NewHostDeviceImpl(dev, deviceID, rFactory, rc, infoProviders) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
netDev, err := devices.NewGenNetDevice(deviceID, types.AuxNetDeviceType, isRdma) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
auxType := utils.ParseAuxDeviceType(deviceID) | ||
if auxType == "" { | ||
return nil, fmt.Errorf("device ID %s doesn't represent auxuliary device", deviceID) | ||
} | ||
|
||
return &auxNetDevice{ | ||
HostDevice: hostDev, | ||
GenNetDevice: *netDev, | ||
auxType: auxType, | ||
}, nil | ||
} | ||
|
||
func (ad *auxNetDevice) GetAuxType() string { | ||
return ad.auxType | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
/* | ||
* SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* 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 auxnetdevice | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/golang/glog" | ||
"github.com/jaypipes/ghw" | ||
|
||
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types" | ||
"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/utils" | ||
) | ||
|
||
type auxNetDeviceProvider struct { | ||
deviceList []*ghw.PCIDevice | ||
rFactory types.ResourceFactory | ||
} | ||
|
||
// NewAuxNetDeviceProvider DeviceProvider implementation from auxNetDeviceProvider instance | ||
func NewAuxNetDeviceProvider(rf types.ResourceFactory) types.DeviceProvider { | ||
return &auxNetDeviceProvider{ | ||
rFactory: rf, | ||
deviceList: make([]*ghw.PCIDevice, 0), | ||
} | ||
} | ||
|
||
func (ap *auxNetDeviceProvider) GetDiscoveredDevices() []*ghw.PCIDevice { | ||
return ap.deviceList | ||
} | ||
|
||
func (ap *auxNetDeviceProvider) GetDevices(rc *types.ResourceConfig) []types.HostDevice { | ||
newAuxDevices := make([]types.HostDevice, 0) | ||
for _, device := range ap.deviceList { | ||
// discover auxiliary device names | ||
auxDevs, err := utils.GetSriovnetProvider().GetAuxNetDevicesFromPci(device.Address) | ||
if err == nil { | ||
if len(auxDevs) == 0 { | ||
glog.Warningf("auxnetdevice GetDevices(): no auxiliary devices for PCI %s", device.Address) | ||
continue | ||
} | ||
for _, auxDev := range auxDevs { | ||
if newDevice, err := NewAuxNetDevice(device, auxDev, ap.rFactory, rc); err == nil { | ||
newAuxDevices = append(newAuxDevices, newDevice) | ||
} else { | ||
glog.Warningf("auxnetdevice GetDevices(): error creating new device %s PCI %s: %q", | ||
auxDev, device.Address, err) | ||
} | ||
} | ||
} else { | ||
glog.Warningf("auxNetDevice GetDevices(): error getting auxnetdevices from device %s: %q", | ||
device.Address, err) | ||
} | ||
} | ||
return newAuxDevices | ||
} | ||
|
||
func (ap *auxNetDeviceProvider) AddTargetDevices(devices []*ghw.PCIDevice, deviceCode int) error { | ||
for _, device := range devices { | ||
devClass, err := utils.ParseDeviceID(device.Class.ID) | ||
if err != nil { | ||
glog.Warningf("auxNetDevice AddTargetDevices(): unable to parse device class for device %+v %q", device, err) | ||
continue | ||
} | ||
|
||
if devClass == int64(deviceCode) { | ||
vendorName := utils.NormalizeVendorName(device.Vendor.Name) | ||
productName := utils.NormalizeProductName(device.Product.Name) | ||
glog.Infof("auxnetdevice AddTargetDevices(): device found: %-12s\t%-12s\t%-20s\t%-40s", device.Address, | ||
device.Class.ID, vendorName, productName) | ||
if isDefaultRoute, _ := utils.HasDefaultRoute(device.Address); !isDefaultRoute { | ||
ap.deviceList = append(ap.deviceList, device) | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
//nolint:gocyclo | ||
func (ap *auxNetDeviceProvider) GetFilteredDevices(devices []types.HostDevice, rc *types.ResourceConfig) ([]types.HostDevice, error) { | ||
filteredDevice := devices | ||
nf, ok := rc.SelectorObj.(*types.AuxNetDeviceSelectors) | ||
if !ok { | ||
return filteredDevice, fmt.Errorf("unable to convert SelectorObj to AuxNetDeviceSelectors") | ||
} | ||
|
||
rf := ap.rFactory | ||
// filter by vendor list | ||
if nf.Vendors != nil && len(nf.Vendors) > 0 { | ||
if selector, err := rf.GetSelector("vendors", nf.Vendors); err == nil { | ||
filteredDevice = selector.Filter(filteredDevice) | ||
} | ||
} | ||
|
||
// filter by device list | ||
if nf.Devices != nil && len(nf.Devices) > 0 { | ||
if selector, err := rf.GetSelector("devices", nf.Devices); err == nil { | ||
filteredDevice = selector.Filter(filteredDevice) | ||
} | ||
} | ||
|
||
// filter by driver list | ||
if nf.Drivers != nil && len(nf.Drivers) > 0 { | ||
if selector, err := rf.GetSelector("drivers", nf.Drivers); err == nil { | ||
filteredDevice = selector.Filter(filteredDevice) | ||
} | ||
} | ||
|
||
// filter by auxiliary device type list | ||
if nf.AuxTypes != nil && len(nf.AuxTypes) > 0 { | ||
if selector, err := rf.GetSelector("auxTypes", nf.AuxTypes); err == nil { | ||
filteredDevice = selector.Filter(filteredDevice) | ||
} | ||
} | ||
|
||
// filter by PfNames list | ||
if nf.PfNames != nil && len(nf.PfNames) > 0 { | ||
if selector, err := rf.GetSelector("pfNames", nf.PfNames); err == nil { | ||
filteredDevice = selector.Filter(filteredDevice) | ||
} | ||
} | ||
|
||
// filter by RootDevices list | ||
if nf.RootDevices != nil && len(nf.RootDevices) > 0 { | ||
if selector, err := rf.GetSelector("rootDevices", nf.RootDevices); err == nil { | ||
filteredDevice = selector.Filter(filteredDevice) | ||
} | ||
} | ||
|
||
// filter by linkTypes list | ||
if nf.LinkTypes != nil && len(nf.LinkTypes) > 0 { | ||
if len(nf.LinkTypes) > 1 { | ||
glog.Warningf("Link type selector should have a single value.") | ||
} | ||
if selector, err := rf.GetSelector("linkTypes", nf.LinkTypes); err == nil { | ||
filteredDevice = selector.Filter(filteredDevice) | ||
} | ||
} | ||
|
||
// filter for rdma devices | ||
if nf.IsRdma { | ||
rdmaDevices := make([]types.HostDevice, 0) | ||
for _, dev := range filteredDevice { | ||
if dev.(types.NetDevice).IsRdma() { | ||
rdmaDevices = append(rdmaDevices, dev) | ||
} | ||
} | ||
filteredDevice = rdmaDevices | ||
} | ||
|
||
return filteredDevice, nil | ||
} | ||
|
||
// ValidConfig performs validation of AuxNetDeviceSelectors | ||
func (ap *auxNetDeviceProvider) ValidConfig(rc *types.ResourceConfig) bool { | ||
nf, ok := rc.SelectorObj.(*types.AuxNetDeviceSelectors) | ||
if !ok { | ||
glog.Errorf("unable to convert SelectorObj to AuxNetDeviceSelectors") | ||
return false | ||
} | ||
if len(nf.AuxTypes) == 0 { | ||
glog.Errorf("AuxTypes are not specified") | ||
return false | ||
} | ||
// Check that only supported auxiliary device types are specified | ||
// TODO ATM only SFs are supported; review this in the future if new types are added | ||
for _, auxType := range nf.AuxTypes { | ||
if auxType != "sf" { | ||
glog.Errorf("Only \"sf\" auxiliary device type currently supported") | ||
return false | ||
} | ||
} | ||
return true | ||
} |
Oops, something went wrong.