Skip to content
This repository was archived by the owner on Mar 20, 2024. It is now read-only.

Commit 1d346de

Browse files
authored
FIX_Ethtool_filters (#63)
Ethtool feature moved to CNI where filters now assigned via the networkAttachmentDefinition. DeviceFile functions removed. -Ethtool unit tests removed from device plugin. -Corrected changes from previous commit -Amended readme section -example network-attachment-definition.yaml updated --------- Signed-off-by: Patrick O Grady <[email protected]>
1 parent 7a50f12 commit 1d346de

File tree

10 files changed

+98
-306
lines changed

10 files changed

+98
-306
lines changed

README.md

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,6 @@ Below are some additional optional configurations that can be applied to pools.
403403
UID is an integer configuration. It is useful in scenarios where the AF_XDP pod runs as a non-zero user. This configuration can be used to inform the device plugin about the user ID of the pod. This allows that non-zero user to use the UDS without issue. If unset, then only user 0 can use the UDS.
404404
Note: User 0 does not imply that the pod needs to be privileged.
405405

406-
#### EthtoolCmds
407-
408-
EthtoolCmds is an array of strings. This is a setting that can be applied to devices in a `primary` mode pool. Here the user can provide a list of Ethtool filters to apply to the devices as they are being allocated to a pod. These strings should be formatted exactly as if setting Ethtool filters manually from the command line. Some Ethtool filters require the netdev name or the IP address and in these instances, the user can substitute these with `-device-` and `-ip-` respectively. The plugins will apply the filters with the correct name and IP address when they become known during pod creation.
409-
410406
#### UdsServerDisable
411407

412408
UdsServerDisable is a Boolean configuration. If set to true, devices in this pool will not have the BPF app loaded onto the netdev. This means no UDS server is spun up when a device is allocated to a pod. By default, this is set to false.
@@ -425,13 +421,12 @@ The example below has two pools configured.
425421

426422
The first pool:
427423

428-
- Has the **name** `myPrimarypool`.
429-
- Is in `primary` **mode**, meaning no secondary devices will be created. Pods requesting `afxdp/myPrimarypool` will be allocated the full NIC port.
430-
- The **drivers** field for this pool has one driver, `i40e`, meaning this pool will be assigned i40e devices, where available.
431-
- The **uid** field for this pool is set to `1500` meaning the AF_XDP pod can run as user 1500 and use the UDS without issue.
432-
- The **udsTimeout** field for this pool is set to `300`, meaning the UDS server will only time out and terminate after 5 minutes of inactivity on the UDS.
433-
- The **RequiresUnprivilegedBpf** field is set to `true` meaning this pool will only be assigned devices from nodes where unprivileged eBPF is allowed.
434-
- Finally, the **ethtoolCmds** field has two filters configured. This means the filters `ethtool -X <device> equal 5 start 3` and `ethtool --config-ntuple -device- flow-type udp4 dst-ip <ip> action` will be configured on all devices as they are being attached to the AF_XDP pods. The plugins will substitute `<device>` and `<ip>` accordingly.
424+
- Has the **name** `myPrimarypool`.
425+
- Is in `primary` **mode**, meaning no secondary devices will be created. Pods requesting `afxdp/myPrimarypool` will be allocated the full NIC port.
426+
- The **drivers** field for this pool has one driver, `i40e`, meaning this pool will be assigned i40e devices, where available.
427+
- The **uid** field for this pool is set to `1500` meaning the AF_XDP pod can run as user 1500 and use the UDS without issue.
428+
- The **udsTimeout** field for this pool is set to `300`, meaning the UDS server will only time out and terminate after 5 minutes of inactivity on the UDS.
429+
- The **RequiresUnprivilegedBpf** field is set to `true` meaning this pool will only be assigned devices from nodes where unprivileged eBPF is allowed.
435430

436431
The second pool:
437432

@@ -444,15 +439,11 @@ The second pool:
444439
{
445440
"pools":[
446441
{
447-
"name": "myPrimarypool",
448-
"mode": "primary",
449-
"uid": 1500,
450-
"udsTimeout": 300,
451-
"RequiresUnprivilegedBpf": true,
452-
"ethtoolCmds":[
453-
"-X -device- equal 5 start 3",
454-
"--config-ntuple -device- flow-type udp4 dst-ip -ip- action"
455-
],
442+
"name":"myPrimarypool",
443+
"mode":"primary",
444+
"uid":1500,
445+
"udsTimeout":300,
446+
"RequiresUnprivilegedBpf":true,
456447
"drivers":[
457448
{
458449
"name": "i40e"
@@ -533,6 +524,14 @@ The kindCluster flag is used to indicate if this is a physical cluster or a Kind
533524
}
534525
```
535526

527+
### Ethtool Filters
528+
Ethtool filters can be applied to devices during CNI runtime. This setting can only be assigned to devices in a `primary` mode pool from the networkAttachmentDefinition file.
529+
The EthtoolCmds field is an array of strings. These strings should be formatted exactly as if setting Ethtool filters where manually from the command line. Some Ethtool filters require the device name or the IP address and in these instances, the user can substitute these with `-device-` and `-ip-` respectively. The plugins will apply the filters with the correct name and IP address when they become known during pod creation.
530+
531+
From the [examples/network-attachment-definition.yaml](./examples/network-attachment-definition.yaml) file: **ethtoolCmds** field has two filters configured. This means the filters `ethtool -X <device> equal 5 start 3` and `ethtool --config-ntuple -device- flow-type udp4 dst-ip <ip> action` will be configured on all devices as they are being attached to the AF_XDP pods. The plugins will substitute `<device>` and `<ip>` accordingly.
532+
533+
*Note: When setting ethtool commands in the **ethtoolCmds** field, the 'ethtool' prefix must be removed.
534+
536535
## CLOC
537536

538537
Output from CLOC (count lines of code) - github.com/AlDanial/cloc

constants/constants.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,6 @@ var (
101101
handshakeResponseBadRequest = "/nak" // general non-acknowledgement response, usually indicates a bad request
102102
handshakeResponseError = "/error" // general error occurred response, indicates an error occurred on the device plugin end
103103

104-
/*DeviceFile*/
105-
name = "device.json" // file which enables passing of device information from device plugin to CNI in the form of device map object.
106-
directory = "/tmp/afxdp_dp/" // host location where deviceFile file is placed.
107-
filePermissions = 0600 // permissions for device file.
108-
109104
/*EthtoolFilters*/
110105
ethtoolFilterRegex = `^[a-zA-Z0-9-:.-/\s/g]+$` // regex to validate ethtool filter commands.
111106
)
@@ -339,12 +334,6 @@ func init() {
339334
},
340335
}
341336

342-
DeviceFile = deviceFile{
343-
Name: name,
344-
FilePermissions: filePermissions,
345-
Directory: directory,
346-
}
347-
348337
EthtoolFilter = ethtoolFilter{
349338
EthtoolFilterRegex: ethtoolFilterRegex,
350339
}

examples/network-attachment-definition.yaml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
33
apiVersion: "k8s.cni.cncf.io/v1"
44
kind: NetworkAttachmentDefinition
55
metadata:
6-
name: afxdp-network # Name of this network, pods will request this network by name
6+
name: afxdp-network # Name of this network, pods will request this network by name
77
annotations:
8-
k8s.v1.cni.cncf.io/resourceName: afxdp/myPool # Needs to match the device plugin pool name / resource type
8+
k8s.v1.cni.cncf.io/resourceName: afxdp/myPool # Needs to match the device plugin pool name / resource type
99
spec:
1010
config: '{
1111
"cniVersion": "0.3.0",
12-
"type": "afxdp", # CNI binary, leave as afxdp
13-
"mode": "primary", # CNI mode setting (required)
14-
"logFile": "afxdp-cni.log", # CNI log file location (optional)
15-
"logLevel": "debug", # CNI logging level (optional)
16-
"ipam": { # CNI IPAM plugin and associated config (optional)
12+
"type": "afxdp", # CNI binary, leave as afxdp
13+
"mode": "primary", # CNI mode setting (required)
14+
"logFile": "afxdp-cni.log", # CNI log file location (optional)
15+
"logLevel": "debug", # CNI logging level (optional)
16+
"ethtoolCmds" : ["-X -device- equal 5 start 3", # CNI ethtool filters (optional)
17+
"--config-ntuple -device- flow-type udp4 dst-ip -ip- action"
18+
],
19+
20+
"ipam": { # CNI IPAM plugin and associated config (optional)
1721
"type": "host-local",
1822
"subnet": "192.168.1.0/24",
1923
"rangeStart": "192.168.1.200",

internal/cni/cni.go

Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"github.com/intel/afxdp-plugins-for-kubernetes/internal/host"
3030
"github.com/intel/afxdp-plugins-for-kubernetes/internal/logformats"
3131
"github.com/intel/afxdp-plugins-for-kubernetes/internal/networking"
32-
"github.com/intel/afxdp-plugins-for-kubernetes/internal/tools"
3332
logging "github.com/sirupsen/logrus"
3433
"github.com/vishvananda/netlink"
3534
"os"
@@ -45,12 +44,13 @@ NetConfig holds the config passed via stdin
4544
*/
4645
type NetConfig struct {
4746
types.NetConf
48-
Device string `json:"deviceID"`
49-
Mode string `json:"mode"`
50-
SkipUnloadBpf bool `json:"skipUnloadBpf,omitempty"`
51-
Queues string `json:"queues,omitempty"`
52-
LogFile string `json:"logFile,omitempty"`
53-
LogLevel string `json:"logLevel,omitempty"`
47+
Device string `json:"deviceID"`
48+
Mode string `json:"mode"`
49+
SkipUnloadBpf bool `json:"skipUnloadBpf,omitempty"`
50+
Queues string `json:"queues,omitempty"`
51+
LogFile string `json:"logFile,omitempty"`
52+
LogLevel string `json:"logLevel,omitempty"`
53+
EthtoolCmds []string `json:"ethtoolCmds,omitempty"`
5454
}
5555

5656
func init() {
@@ -64,6 +64,7 @@ func (n NetConfig) Validate() error {
6464
var (
6565
allowedLogLevels = constants.Logging.Levels
6666
allowedModes = constants.Plugins.Modes
67+
ethtoolRegex = constants.EthtoolFilter.EthtoolFilterRegex
6768
logLevels []interface{} = make([]interface{}, len(allowedLogLevels))
6869
modes []interface{} = make([]interface{}, len(allowedModes))
6970
)
@@ -93,6 +94,13 @@ func (n NetConfig) Validate() error {
9394
&n.Mode,
9495
validation.In(modes...).Error("validate(): must be "+fmt.Sprintf("%v", modes)),
9596
),
97+
validation.Field(
98+
&n.EthtoolCmds,
99+
validation.Each(
100+
validation.Required.When(len(n.EthtoolCmds) > 0).Error("Ethtool field must not be empty"),
101+
validation.Match(regexp.MustCompile(ethtoolRegex)).Error("Ethtool commands must be alphanumeric or approved characters"),
102+
),
103+
),
96104
)
97105
}
98106

@@ -142,7 +150,6 @@ CmdAdd is called by kubelet during pod create
142150
func CmdAdd(args *skel.CmdArgs) error {
143151
host := host.NewHandler()
144152
var result *current.Result
145-
var deviceDetails *networking.Device
146153
netHandler := networking.NewHandler()
147154

148155
cfg, err := loadConf(args.StdinData)
@@ -195,45 +202,28 @@ func CmdAdd(args *skel.CmdArgs) error {
195202
}
196203

197204
if cfg.Mode == "primary" {
198-
deviceFile, err := tools.FilePathExists(constants.DeviceFile.Directory + constants.DeviceFile.Name)
199-
if err != nil {
200-
logging.Errorf("cmdAdd(): Failed to locate deviceFile: %v", err)
201-
}
202-
203-
if deviceFile {
204-
deviceDetails, err = netHandler.GetDeviceFromFile(cfg.Device, constants.DeviceFile.Directory+constants.DeviceFile.Name)
205-
if err != nil {
206-
logging.Errorf("cmdAdd():- Failed to extract device map values: %v", err)
207-
return err
208-
}
209-
205+
if cfg.EthtoolCmds != nil {
210206
ethInstalled, version, err := host.HasEthtool()
211207
if err != nil {
212208
logging.Warningf("cmdAdd(): failed to discover ethtool on host: %v", err)
213209
}
214-
215210
if ethInstalled {
216211
logging.Debugf("cmdAdd(): ethtool found on host")
217212
logging.Debugf("\t" + version)
218-
if deviceDetails != nil {
219-
if deviceDetails.GetEthtoolFilters() != nil {
220-
logging.Infof("cmdAdd(): applying ethtool filters on device: %s", cfg.Device)
221-
ethtoolCommand := deviceDetails.GetEthtoolFilters()
222-
iPAddr, err := extractIP(result)
223-
if err != nil {
224-
logging.Errorf("cmdAdd(): Error extracting IP from result interface %v", err)
225-
return err
226-
}
227-
err = netHandler.SetEthtool(ethtoolCommand, cfg.Device, iPAddr)
228-
if err != nil {
229-
logging.Errorf("cmdAdd(): unable to executed ethtool filter: %v", err)
230-
return err
231-
}
232-
} else {
233-
logging.Debugf("cmdAdd(): ethtool filters have not been specified")
234-
}
213+
logging.Infof("cmdAdd(): applying ethtool filters on device: %s", cfg.Device)
214+
iPAddr, err := extractIP(result)
215+
if err != nil {
216+
logging.Errorf("cmdAdd(): Error extracting IP from result interface %v", err)
217+
return err
218+
}
219+
err = netHandler.SetEthtool(cfg.EthtoolCmds, cfg.Device, iPAddr)
220+
if err != nil {
221+
logging.Errorf("cmdAdd(): unable to executed ethtool filter: %v", err)
222+
return err
235223
}
236224
}
225+
} else {
226+
logging.Debugf("cmdAdd(): ethtool filters have not been specified")
237227
}
238228
}
239229

@@ -354,19 +344,20 @@ func CmdDel(args *skel.CmdArgs) error {
354344
return err
355345
}
356346
}
357-
358347
if cfg.Mode == "primary" {
359-
logging.Debugf("cmdDel: checking host for Ethtool")
360-
ethInstalled, _, err := host.HasEthtool()
361-
if err != nil {
362-
logging.Errorf("cmdDel(): error checking if Ethtool is present on host: %v", err)
363-
return err
364-
}
365-
if ethInstalled {
366-
logging.Infof("cmdDel(): Removing ethtool filters on device: %s", cfg.Device)
367-
err := netHandler.DeleteEthtool(cfg.Device)
348+
if cfg.EthtoolCmds != nil {
349+
logging.Debugf("cmdDel: checking host for Ethtool")
350+
ethInstalled, _, err := host.HasEthtool()
368351
if err != nil {
369-
logging.Warningf("cmdDel(): failed to remove ethtool filter: %v", err)
352+
logging.Errorf("cmdDel(): error checking if Ethtool is present on host: %v", err)
353+
return err
354+
}
355+
if ethInstalled {
356+
logging.Infof("cmdDel(): Removing ethtool filters on device: %s", cfg.Device)
357+
err := netHandler.DeleteEthtool(cfg.Device)
358+
if err != nil {
359+
logging.Warningf("cmdDel(): failed to remove ethtool filter: %v", err)
360+
}
370361
}
371362
}
372363
}

internal/deviceplugin/config.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,12 @@ type PoolConfig struct {
5555
Name string // the name of the pool, used for logging and advertising resource to K8s. Pods will request this resource
5656
Mode string // the mode that this pool operates in
5757
Devices map[string]*networking.Device // a map of devices that the pool will manage
58-
Filters []string // the ethtool/rss filters we apply to devices from this pool
5958
UdsServerDisable bool // a boolean to say if pods in this pool require BPF loading the UDS server
6059
UdsTimeout int // timeout value in seconds for the UDS sockets, user provided or defaults to value from constants package
6160
UdsFuzz bool // a boolean to turn on fuzz testing within the UDS server, has no use outside of development and testing
6261
RequiresUnprivilegedBpf bool // a boolean to say if this pool requires unprivileged BPF
6362
UID int // the id of the pod user, we give this user ACL access to the UDS socket
64-
EthtoolCmds []string // list of ethtool filters to apply to the netdev
63+
6564
}
6665

6766
/*
@@ -252,7 +251,6 @@ func GetPoolConfigs(configFile string, net networking.Handler, host host.Handler
252251
UdsFuzz: pool.UdsFuzz,
253252
RequiresUnprivilegedBpf: pool.RequiresUnprivilegedBpf,
254253
UID: pool.UID,
255-
EthtoolCmds: pool.EthtoolCmds,
256254
})
257255
}
258256

internal/deviceplugin/configFile.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ const (
5555
poolUdsTimeoutError = "UDS socket timeout must be -1, 0, or between 30 and 300 seconds"
5656
poolModeRequiredError = "Plugin must have a mode"
5757
poolModeMustBeError = "Plugin mode must be one of "
58-
poolEthtoolNotEmpty = "Ethtool commands cannot be empty"
59-
poolEthtoolCharacters = "Ethtool commands must be alphanumeric or contain only approved charaters"
6058

6159
// logging errors
6260
filenameValidError = "must be a valid .log or .txt filename"
@@ -94,7 +92,6 @@ type configFile_Pool struct {
9492
UdsFuzz bool `json:"UdsFuzz"`
9593
RequiresUnprivilegedBpf bool `json:"RequiresUnprivilegedBpf"`
9694
UID int `json:"uid"`
97-
EthtoolCmds []string `json:"ethtoolCmds"`
9895
}
9996

10097
type configFile struct {
@@ -229,13 +226,6 @@ func (c configFile_Pool) Validate() error {
229226
validation.When(!(c.UID == 0), validation.Max(constants.UID.Maximum)),
230227
validation.When(!(c.UID == 0), validation.Min(constants.UID.Minimum)),
231228
),
232-
validation.Field(
233-
&c.EthtoolCmds,
234-
validation.Each(
235-
validation.Required.When(len(c.EthtoolCmds) > 0).Error(poolEthtoolNotEmpty),
236-
validation.Match(regexp.MustCompile(constants.EthtoolFilter.EthtoolFilterRegex)).Error(poolEthtoolCharacters),
237-
),
238-
),
239229
)
240230
}
241231

0 commit comments

Comments
 (0)