Skip to content

Commit f63dde9

Browse files
driver/rawnetworkinterfacedriver: ethtool get/change settings
Add interface configuration (`ethtool --change`) support to the RawNetworkInterfaceDriver. This allows configuring the bound interface (speed, lanes, duplex, port, master-slave, mdix, autoneg, advertise, phyad, xcvr, wol, sopass, msglvl). Also add add a `get_settings()` method to query those settings. Note that ethtool gained the required --json support for the default sub command in v6.10. Signed-off-by: Bastian Krause <[email protected]>
1 parent 12179e7 commit f63dde9

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

helpers/labgrid-raw-interface

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import argparse
1111
import os
12+
import string
1213
import sys
1314

1415
import yaml
@@ -45,7 +46,7 @@ def main(program, options):
4546
if options.ifname in denylist:
4647
raise ValueError(f"Interface name '{options.ifname}' is denied in denylist.")
4748

48-
programs = ["tcpreplay", "tcpdump", "ip"]
49+
programs = ["tcpreplay", "tcpdump", "ip", "ethtool"]
4950
if program not in programs:
5051
raise ValueError(f"Invalid program {program} called with wrapper, valid programs are: {programs}")
5152

@@ -86,6 +87,18 @@ def main(program, options):
8687
args.append(options.ifname)
8788
args.append(options.action)
8889

90+
elif program == "ethtool":
91+
allowed_chars = set(string.ascii_letters + string.digits + "-/:")
92+
93+
if options.subcommand == "change":
94+
for arg in options.ethtool_change_args:
95+
if arg.startswith("-") or not allowed_chars.issuperset(arg):
96+
raise ValueError(f"ethtool --change arg '{arg}' contains invalid characters")
97+
98+
args.append("--change")
99+
args.append(options.ifname)
100+
args.extend(options.ethtool_change_args)
101+
89102
try:
90103
os.execvp(args[0], args)
91104
except FileNotFoundError as e:
@@ -114,6 +127,17 @@ if __name__ == "__main__":
114127
ip_parser.add_argument("ifname", type=str, help="interface name")
115128
ip_parser.add_argument("action", type=str, choices=["up", "down"], help="action, one of {%(choices)s}")
116129

130+
# ethtool
131+
ethtool_parser = subparsers.add_parser("ethtool")
132+
ethtool_subparsers = ethtool_parser.add_subparsers(dest="subcommand")
133+
134+
# ethtool: change
135+
ethtool_change_parser = ethtool_subparsers.add_parser("change")
136+
ethtool_change_parser.add_argument("ifname", type=str, help="interface name")
137+
ethtool_change_parser.add_argument(
138+
"ethtool_change_args", metavar="ARG", nargs=argparse.REMAINDER, help="ethtool --change args"
139+
)
140+
117141
args = parser.parse_args()
118142
try:
119143
main(args.program, args)

labgrid/driver/rawnetworkinterfacedriver.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,28 @@ def wait_state(self, expected_state, timeout=60):
9797
"""Wait until the expected state is reached or the timeout expires."""
9898
self._wait_state(expected_state, timeout=timeout)
9999

100+
@Driver.check_active
101+
def get_ethtool_settings(self):
102+
"""
103+
Returns settings via ethtool of the bound network interface resource.
104+
"""
105+
cmd = self.iface.command_prefix + ["ethtool", "--json", self.iface.ifname]
106+
output = subprocess.check_output(cmd, encoding="utf-8")
107+
return json.loads(output)[0]
108+
109+
@Driver.check_active
110+
@step(args=["settings"])
111+
def ethtool_configure(self, **settings):
112+
"""
113+
Change settings on interface.
114+
115+
Supported settings are described in ethtool(8) --change (use "_" instead of "-").
116+
"""
117+
cmd = ["ethtool", "change", self.iface.ifname]
118+
cmd += [item.replace("_", "-") for pair in settings.items() for item in pair]
119+
cmd = self._wrap_command(cmd)
120+
subprocess.check_call(cmd)
121+
100122
def _stop(self, proc, *, timeout=None):
101123
assert proc is not None
102124

0 commit comments

Comments
 (0)