Add support for ETHTOOL Ring option

ETHTOOL Ring option is not supported by NetworkManager until
NM 1.25.2. Currently, ETHTOOL Ring option is not suppored by
Network role, so enable the support for ETHTOOL Ring option.

Configure ethtool ring option via:

	```yaml
            network_connections:
              - name: testnic1
                type: ethernet
                state: up
                ip:
                  dhcp4: no
                  auto6: no
                ethtool:
                  ring:
                    rx: 128
                    rx_jumbo: 128
                    rx_mini: 128
                    tx: 128
	```

Signed-off-by: Wen Liang <liangwen12year@gmail.com>
This commit is contained in:
Wen Liang 2020-11-19 15:36:17 -05:00 committed by Till Maas
parent 13e7f8a333
commit ae2d60a0b2
10 changed files with 354 additions and 0 deletions

View file

@ -22,3 +22,4 @@ rules:
/tests/tests_wireless_plugin_installation_nm.yml
/tests/tests_team_plugin_installation_nm.yml
/tests/tests_ethtool_coalesce_initscripts.yml
/tests/tests_ethtool_ring_initscripts.yml

View file

@ -436,6 +436,17 @@ The ethtool settings allow to enable or disable various features. The names
correspond to the names used by the `ethtool` utility. Depending on the actual
kernel and device, changing some options might not be supported.
The ethtool configuration supports the following options:
- `ring`
Changes the `rx`/`tx` `ring` parameters of the specified network device. The list
of supported `ring` parameters is:
- `rx` - Changes the number of ring entries for the Rx ring.
- `rx-jumbo` - Changes the number of ring entries for the Rx Jumbo ring.
- `rx-mini` - Changes the number of ring entries for the Rx Mini ring.
- `tx` - Changes the number of ring entries for the Tx ring.
```yaml
ethtool:
features:
@ -514,6 +525,11 @@ kernel and device, changing some options might not be supported.
tx_usecs_high: 0 # optional mininum=0 maximum=0xffffffff
tx_usecs_irq: 0 # optional mininum=0 maximum=0xffffffff
tx_usecs_low: 0 # optional mininum=0 maximum=0xffffffff
ring:
rx: 0 # optional mininum=0 maximum=0xffffffff
rx_jumbo: 0 # optional mininum=0 maximum=0xffffffff
rx_mini: 0 # optional mininum=0 maximum=0xffffffff
tx: 0 # optional mininum=0 maximum=0xffffffff
```
### `ieee802_1x`

20
examples/ethtool_ring.yml Normal file
View file

@ -0,0 +1,20 @@
# SPDX-License-Identifier: BSD-3-Clause
---
- hosts: all
tasks:
- include_role:
name: linux-system-roles.network
vars:
network_connections:
- name: "{{ network_interface_name1 }}"
state: up
type: ethernet
ip:
dhcp4: no
auto6: no
ethtool:
ring:
rx: 128
rx_jumbo: 128
rx_mini: 128
tx: 128

View file

@ -428,6 +428,19 @@ class IfcfgUtil:
connection["interface_name"],
" ".join(configured_coalesce),
)
ethtool_ring = connection["ethtool"]["ring"]
configured_ring = []
for ring, setting in ethtool_ring.items():
if setting is not None:
configured_ring.append("%s %s" % (ring.replace("_", "-"), setting))
if configured_ring:
if ethtool_options:
ethtool_options += " ; "
ethtool_options += "-G %s %s" % (
connection["interface_name"],
" ".join(configured_ring),
)
if ethtool_options:
ifcfg["ETHTOOL_OPTS"] = ethtool_options
@ -948,6 +961,14 @@ class NMUtil:
s_ethtool.option_set(nm_coalesce, None)
else:
s_ethtool.option_set_uint32(nm_coalesce, int(setting))
for ring, setting in connection["ethtool"]["ring"].items():
nm_ring = nm_provider.get_nm_ethtool_ring(ring)
if nm_ring:
if setting is None:
s_ethtool.option_set(nm_ring, None)
else:
s_ethtool.option_set_uint32(nm_ring, setting)
if connection["mtu"]:
if connection["type"] == "infiniband":
@ -2005,6 +2026,7 @@ class Cmd_nm(Cmd):
ethtool_dict = {
"features": nm_provider.get_nm_ethtool_feature,
"coalesce": nm_provider.get_nm_ethtool_coalesce,
"ring": nm_provider.get_nm_ethtool_ring,
}
for ethtool_key, nm_get_name_fcnt in ethtool_dict.items():

View file

@ -711,6 +711,7 @@ class ArgValidator_DictEthtool(ArgValidatorDict):
nested=[
ArgValidator_DictEthtoolFeatures(),
ArgValidator_DictEthtoolCoalesce(),
ArgValidator_DictEthtoolRing(),
],
default_value=ArgValidator.MISSING,
)
@ -1008,6 +1009,31 @@ class ArgValidator_DictEthtoolCoalesce(ArgValidatorDict):
)
class ArgValidator_DictEthtoolRing(ArgValidatorDict):
def __init__(self):
ArgValidatorDict.__init__(
self,
name="ring",
nested=[
ArgValidatorNum(
"rx", val_min=0, val_max=UINT32_MAX, default_value=None
),
ArgValidatorNum(
"rx_jumbo", val_min=0, val_max=UINT32_MAX, default_value=None
),
ArgValidatorNum(
"rx_mini", val_min=0, val_max=UINT32_MAX, default_value=None
),
ArgValidatorNum(
"tx", val_min=0, val_max=UINT32_MAX, default_value=None
),
],
)
self.default_value = dict(
[(k, v.default_value) for k, v in self.nested.items()]
)
class ArgValidator_DictBond(ArgValidatorDict):
VALID_MODES = [

View file

@ -10,6 +10,7 @@ from ansible.module_utils.network_lsr.utils import Util # noqa:E501
ETHTOOL_FEATURE_PREFIX = "ETHTOOL_OPTNAME_FEATURE_"
ETHTOOL_COALESCE_PREFIX = "ETHTOOL_OPTNAME_COALESCE_"
ETHTOOL_RING_PREFIX = "ETHTOOL_OPTNAME_RING_"
def get_nm_ethtool_feature(name):
@ -42,3 +43,18 @@ def get_nm_ethtool_coalesce(name):
coalesce = getattr(Util.NM(), name, None)
return coalesce
def get_nm_ethtool_ring(name):
"""
Translate ethtool ring option into NetworkManager attribute name
:param name: Name of the ring
:type name: str
:returns: Name of the setting to be used by `NM.SettingEthtool.set_ring()`
:rtype: str
"""
name = ETHTOOL_RING_PREFIX + name.upper()
ring = getattr(Util.NM(), name, None)
return ring

View file

@ -0,0 +1,194 @@
# SPDX-License-Identifier: BSD-3-Clause
---
- hosts: all
vars:
interface: testnic1
type: veth
tasks:
- debug:
msg: "this is: playbooks/tests_ethtool_ring.yml"
tags:
- always
- name: "INIT: Ethtool ring tests"
debug:
msg: "##################################################"
- include_tasks: tasks/show_interfaces.yml
- include_tasks: tasks/manage_test_interface.yml
vars:
state: present
- include_tasks: tasks/assert_device_present.yml
- name: Install ethtool (test dependency)
package:
name: ethtool
state: present
- block:
- name: >-
TEST: I can create a profile without any ring option.
debug:
msg: "##################################################"
- import_role:
name: linux-system-roles.network
vars:
network_connections:
- name: "{{ interface }}"
type: ethernet
state: up
ip:
dhcp4: no
auto6: no
- name: Get profile's ring options
command: nmcli -g ethtool.ring-rx c show {{ interface }}
register: no_ring_nm
when:
- network_provider == "nm"
- name: "ASSERT: The profile does not contain ring options"
assert:
that: no_ring_nm.stdout | length == 0
when:
- network_provider == "nm"
- name: Get profile's ring options
command:
grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface }}
register: no_ring_initscripts
ignore_errors: true
when:
- network_provider == "initscripts"
- name: "ASSERT: The profile does not contain ring options"
assert:
that: no_ring_initscripts.stdout | length == 0
when:
- network_provider == "initscripts"
- name: >-
TEST: I can set rx.
debug:
msg: "##################################################"
- import_role:
name: linux-system-roles.network
vars:
network_connections:
- name: "{{ interface }}"
type: ethernet
state: up
ip:
dhcp4: no
auto6: no
ethtool:
ring:
rx: 128
rx_jumbo: 128
rx_mini: 128
tx: 128
- name: Get profile's ethtool.ring-rx options
command: nmcli -g ethtool.ring-rx c show {{ interface }}
register: with_ring_rx
when:
- network_provider == "nm"
- name: Assert ethtool.ring-rx option set in profile
assert:
that: with_ring_rx.stdout == '128'
when:
- network_provider == "nm"
- name: Get profile's ethtool.ring-rx-jumbo options
command: nmcli -g ethtool.ring-rx-jumbo c show {{ interface }}
register: with_ring_rx_jumbo
when:
- network_provider == "nm"
- name: Assert ethtool.ring-rx-jumbo option set in profile
assert:
that: with_ring_rx_jumbo.stdout == '128'
when:
- network_provider == "nm"
- name: Get profile's ethtool.ring-rx-mini options
command: nmcli -g ethtool.ring-rx-mini c show {{ interface }}
register: with_ring_rx_mini
when:
- network_provider == "nm"
- name: Assert ethtool.ring-rx-mini option set in profile
assert:
that: with_ring_rx_mini.stdout == '128'
when:
- network_provider == "nm"
- name: Get profile's ethtool.ring-tx options
command: nmcli -g ethtool.ring-tx c show {{ interface }}
register: with_ring_tx
when:
- network_provider == "nm"
- name: Assert ethtool.ring-tx option set in profile
assert:
that: with_ring_tx.stdout == '128'
when:
- network_provider == "nm"
- name: Get profile's ethtool.ring options
command:
grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface }}
register: with_ring
ignore_errors: true
when:
- network_provider == "initscripts"
- name: Assert ethtool.ring option set in profile
assert:
that:
- '"rx 128" in with_ring.stdout'
- '"rx-jumbo 128" in with_ring.stdout'
- '"rx-mini 128" in with_ring.stdout'
- '"tx 128" in with_ring.stdout'
when:
- network_provider == "initscripts"
- name: "TEST: I can clear ring options"
debug:
msg: "##################################################"
- import_role:
name: linux-system-roles.network
vars:
network_connections:
- name: "{{ interface }}"
type: ethernet
state: up
ip:
dhcp4: no
auto6: no
- name: Get profile's ring options
command: nmcli -g ethtool.ring-rx c show {{ interface }}
register: clear_ring_nm
when:
- network_provider == "nm"
- name: "ASSERT: The profile does reset ring options"
assert:
that: clear_ring_nm.stdout | length == 0
when:
- network_provider == "nm"
- name: Get profile's ring options
command:
grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface }}
register: clear_ring_initscripts
ignore_errors: true
when:
- network_provider == "initscripts"
- name: "ASSERT: The profile does reset ring options"
assert:
that: clear_ring_initscripts.stdout | length == 0
when:
- network_provider == "initscripts"
always:
- block:
- import_role:
name: linux-system-roles.network
vars:
network_connections:
- name: "{{ interface }}"
persistent_state: absent
ignore_errors: true
- include_tasks: tasks/manage_test_interface.yml
vars:
state: absent
tags:
- "tests::cleanup"

View file

@ -0,0 +1,13 @@
# SPDX-License-Identifier: BSD-3-Clause
# This file was generated by ensure_provider_tests.py
---
- hosts: all
name: Run playbook 'playbooks/tests_ethtool_ring.yml' with initscripts as provider
tasks:
- name: Set network provider to 'initscripts'
set_fact:
network_provider: initscripts
tags:
- always
- import_playbook: playbooks/tests_ethtool_ring.yml

View file

@ -0,0 +1,37 @@
# SPDX-License-Identifier: BSD-3-Clause
# This file was generated by ensure_provider_tests.py
---
# set network provider and gather facts
- hosts: all
name: Run playbook 'playbooks/tests_ethtool_ring.yml' with nm as provider
tasks:
- name: Set network provider to 'nm'
set_fact:
network_provider: nm
tags:
- always
- block:
- name: Install NetworkManager
package:
name: NetworkManager
state: present
- name: Get NetworkManager version
command: rpm -q --qf "%{version}" NetworkManager
args:
warn: false
register: NetworkManager_version
when: true
when:
- ansible_distribution_major_version != '6'
tags:
- always
# The test requires or should run with NetworkManager, therefore it cannot run
# on RHEL/CentOS 6
- import_playbook: playbooks/tests_ethtool_ring.yml
when:
- ansible_distribution_major_version != '6'
- NetworkManager_version.stdout is version('1.25.2', '>=')

View file

@ -140,9 +140,18 @@ ETHTOOL_COALESCE_DEFAULTS = {
"tx_usecs_low": None,
}
ETHTOOL_RING_DEFAULTS = {
"rx": None,
"rx_jumbo": None,
"rx_mini": None,
"tx": None,
}
ETHTOOL_DEFAULTS = {
"features": ETHTOOL_FEATURES_DEFAULTS,
"coalesce": ETHTOOL_COALESCE_DEFAULTS,
"ring": ETHTOOL_RING_DEFAULTS,
}
ETHERNET_DEFAULTS = {"autoneg": None, "duplex": None, "speed": 0}