Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API preferred allocation: GetPreferredAllocation #267

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The SR-IOV network device plugin is Kubernetes device plugin for discovering and
- Supports devices with both Kernel and userspace (UIO and VFIO) drivers
- Allows resource grouping using "Selector"
- User configurable resourceName
- User configurable policy for preferred device allocation
- Detects Kubelet restarts and auto-re-register
- Detects Link status (for Linux network devices) and updates associated VFs health accordingly
- Extensible to support new device types with minimal effort if not already supported
Expand Down Expand Up @@ -181,6 +182,7 @@ This plugin creates device plugin endpoints based on the configurations given in
{
"resourceName": "intel_sriov_dpdk",
"resourcePrefix": "intel.com",
"allocatePolicy": "packed",
"selectors": {
"vendors": ["8086"],
"devices": ["154c", "10ed"],
Expand All @@ -192,6 +194,7 @@ This plugin creates device plugin endpoints based on the configurations given in
{
"resourceName": "mlnx_sriov_rdma",
"resourcePrefix": "mellanox.com",
"allocatePolicy": "packed",
"selectors": {
"vendors": ["15b3"],
"devices": ["1018"],
Expand Down Expand Up @@ -228,6 +231,7 @@ This plugin creates device plugin endpoints based on the configurations given in
| "resourcePrefix" | N | Endpoint resource prefix name override. Should not contain special characters | string Default : "intel.com" | "yourcompany.com" |
| "deviceType" | N | Device Type for a resource pool. | string value of supported types. Default: "netDevice" | Currently supported values: "accelerator", "netDevice" |
| "selectors" | N | A map of device selectors. The "deviceType" value determines the "selectors" options. | json object as string Default: null | Example: "selectors": {"vendors": ["8086"],"devices": ["154c"]} |
| "allocatePolicy" | N | Preferred device allocation policy for a resource pool. The "allocatePolicy" value determines which device in a resource pool is allocated first | string value of supported allocate policy. Default: "" | Example: "allocatePolicy": "packed" |



Expand Down Expand Up @@ -270,7 +274,7 @@ This selector is applicable when "deviceType" is "accelerator". The "accelerator
This plugin accepts the following optional run-time command line arguments:

```bash
./sriovdp --help
./sriovdp -h

Usage of ./sriovdp:
-alsologtostderr
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
golang.org/x/net v0.0.0-20201021035429-f5854403a974
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect
google.golang.org/grpc v1.28.1
k8s.io/kubelet v0.18.1
k8s.io/kubelet v0.19.0
)

replace github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2
215 changes: 210 additions & 5 deletions go.sum

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion pkg/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,22 @@ func (rf *resourceFactory) GetResourceServer(rp types.ResourcePool) (types.Resou
if prefixOverride := rp.GetResourcePrefix(); prefixOverride != "" {
prefix = prefixOverride
}
return resources.NewResourceServer(prefix, rf.endPointSuffix, rf.pluginWatch, rp), nil
policy := rp.GetAllocatePolicy()
return resources.NewResourceServer(prefix, rf.endPointSuffix, rf.pluginWatch, rp, rf.GetAllocator(policy)), nil
}
return nil, fmt.Errorf("factory: unable to get resource pool object")
}

// GetAllocator returns an instance of Allocator using preferredAllocationPolicy
func (rf *resourceFactory) GetAllocator(policy string) types.Allocator {
switch policy {
case "packed":
return resources.NewPackedAllocator()
default:
return nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if there's a misconfig or unsupported policy. Can we raise an error here? I tested this and if we specify a policy that does not match any case, then it is silently ignored.

}
}

// GetDefaultInfoProvider returns an instance of DeviceInfoProvider using name as string
func (rf *resourceFactory) GetDefaultInfoProvider(pciAddr string, name string) types.DeviceInfoProvider {
switch name {
Expand Down
17 changes: 16 additions & 1 deletion pkg/factory/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ var _ = Describe("Factory", func() {
})
})
})
DescribeTable("getting allocator",
func(policy string, expected reflect.Type) {
f := factory.NewResourceFactory("fake", "fake", true)
a := f.GetAllocator(policy)
if expected != nil {
Expect(reflect.TypeOf(a)).To(Equal(expected))
} else {
Expect(a).To(BeNil())
}
},
Entry("packed", "packed", reflect.TypeOf(resources.NewPackedAllocator())),
Entry("empty", "", nil),
Entry("any other value", "random policy", nil),
)
DescribeTable("getting info provider",
func(name string, expected reflect.Type) {
f := factory.NewResourceFactory("fake", "fake", true)
Expand Down Expand Up @@ -284,7 +298,8 @@ var _ = Describe("Factory", func() {
f := factory.NewResourceFactory("fake", "fake", true)
rp := mocks.ResourcePool{}
rp.On("GetResourcePrefix").Return("overriden").
On("GetResourceName").Return("fake")
On("GetResourceName").Return("fake").
On("GetAllocatePolicy").Return("")
rs, e := f.GetResourceServer(&rp)
It("should not fail", func() {
Expect(e).NotTo(HaveOccurred())
Expand Down
3 changes: 3 additions & 0 deletions pkg/netdevice/netDeviceProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ func hasDefaultRoute(pciAddr string) (bool, error) {
}

routes, err := netlink.RouteList(link, netlink.FAMILY_V4) // IPv6 routes: all interface has at least one link local route entry
if err != nil {
glog.Infof("error getting route list for net device %s", ifName)
}
for _, r := range routes {
if r.Dst == nil {
glog.Infof("excluding interface %s: default route found: %+v", ifName, r)
Expand Down
108 changes: 108 additions & 0 deletions pkg/resources/allocator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright 2018 Intel Corp. All Rights Reserved.
//
// 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 resources

import (
"sort"

"github.com/k8snetworkplumbingwg/sriov-network-device-plugin/pkg/types"
pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
)

// DeviceSet is to hold and manipulate a set of PciDevice
type DeviceSet map[string]types.PciDevice

// PackedAllocator implements the Allocator interface
type PackedAllocator struct {
}

// Allocator implements the Allocator interface
type Allocator struct {
}

// NewPackedAllocator create instance of PackedAllocator
func NewPackedAllocator() types.Allocator {
return &PackedAllocator{}
}

// NewAllocator create instance of Allocator
func NewAllocator() types.Allocator {
return &Allocator{}
}

// NewDeviceSet is to create an empty DeviceSet
func NewDeviceSet() DeviceSet {
set := make(DeviceSet)
return set
}

// Insert is to add a PciDevice in DeviceSet
func (ds DeviceSet) Insert(pciAddr string, device types.PciDevice) {
ds[pciAddr] = device
}

// Delete is to delete a PciDevice in DeviceSet
func (ds DeviceSet) Delete(pciAddr string) {
delete(ds, pciAddr)
}

// Sort is to sort the DeviceSet and return the sorted keys
func (ds DeviceSet) Sort() []string {
keys := make([]string, 0, len(ds))
for k := range ds {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}

// Allocate return the preferred allocation
func (pa *PackedAllocator) Allocate(rqt *pluginapi.ContainerPreferredAllocationRequest, rp types.ResourcePool) []string {
size := rqt.AllocationSize
preferredDevices := make([]string, 0)
if size <= 0 || len(rqt.AvailableDeviceIDs) < int(size) || len(rqt.MustIncludeDeviceIDs) > int(size) {
return preferredDevices
}

availableSet := NewDeviceSet()
for _, available := range rqt.AvailableDeviceIDs {
dev, ok := rp.GetDevicePool()[available]
if ok {
availableSet.Insert(available, dev)
} else {
return preferredDevices
}
}
for _, required := range rqt.MustIncludeDeviceIDs {
_, ok := rp.GetDevicePool()[required]
if ok {
availableSet.Delete(required)
} else {
return preferredDevices
}
}
sortedAvailableSet := availableSet.Sort()

preferredDevices = append(preferredDevices, rqt.MustIncludeDeviceIDs...)
if len(preferredDevices) < int(size) {
preferredDevices = append(preferredDevices, sortedAvailableSet[:int(size)-len(preferredDevices)]...)
}
return preferredDevices
}

// Allocate return the preferred allocation
func (a *Allocator) Allocate(rqt *pluginapi.ContainerPreferredAllocationRequest, rp types.ResourcePool) []string {
return make([]string, 0)
}
Loading