Skip to content

Commit

Permalink
Add support for ETHTOOL Ring option
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
liangwen12year committed May 10, 2021
1 parent 13e7f8a commit 6e36cc0
Show file tree
Hide file tree
Showing 10 changed files with 354 additions and 0 deletions.
1 change: 1 addition & 0 deletions .yamllint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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`
Expand Down
20 changes: 20 additions & 0 deletions examples/ethtool_ring.yml
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions library/network_connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,19 @@ def ifcfg_create(
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
Expand Down Expand Up @@ -948,6 +961,14 @@ def connection_create(self, connections, idx, connection_current=None):
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":
Expand Down Expand Up @@ -2005,6 +2026,7 @@ def _check_ethtool_setting_support(self, idx, connection):
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():
Expand Down
26 changes: 26 additions & 0 deletions module_utils/network_lsr/argument_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@ def __init__(self):
nested=[
ArgValidator_DictEthtoolFeatures(),
ArgValidator_DictEthtoolCoalesce(),
ArgValidator_DictEthtoolRing(),
],
default_value=ArgValidator.MISSING,
)
Expand Down Expand Up @@ -1008,6 +1009,31 @@ def __init__(self):
)


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 = [
Expand Down
16 changes: 16 additions & 0 deletions module_utils/network_lsr/nm_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

ETHTOOL_FEATURE_PREFIX = "ETHTOOL_OPTNAME_FEATURE_"
ETHTOOL_COALESCE_PREFIX = "ETHTOOL_OPTNAME_COALESCE_"
ETHTOOL_RING_PREFIX = "ETHTOOL_OPTNAME_RING_"


def get_nm_ethtool_feature(name):
Expand Down Expand Up @@ -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
194 changes: 194 additions & 0 deletions tests/playbooks/tests_ethtool_ring.yml
Original file line number Diff line number Diff line change
@@ -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"
13 changes: 13 additions & 0 deletions tests/tests_ethtool_ring_initscripts.yml
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 6e36cc0

Please sign in to comment.