From f0fbec71dd6e25c06c3d48a1b83fd23f3ed25a1c Mon Sep 17 00:00:00 2001 From: Nicolas Vollmar Date: Thu, 12 Dec 2024 19:34:20 +0100 Subject: [PATCH] T6944: adds option to enable switchdev mode on ethernet interface --- .../interfaces_ethernet.xml.in | 6 +++++ python/vyos/ifconfig/ethernet.py | 27 +++++++++++++++++++ .../scripts/cli/test_interfaces_ethernet.py | 10 +++++++ 3 files changed, 43 insertions(+) diff --git a/interface-definitions/interfaces_ethernet.xml.in b/interface-definitions/interfaces_ethernet.xml.in index 89f990d411d..b3559a6261c 100644 --- a/interface-definitions/interfaces_ethernet.xml.in +++ b/interface-definitions/interfaces_ethernet.xml.in @@ -56,6 +56,12 @@ auto + + + Enables switchdev mode on interface + + + #include diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 50dd0f39614..62a8590b9e8 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -14,6 +14,7 @@ # License along with this library. If not, see . import os +import re from glob import glob @@ -417,12 +418,38 @@ def set_ring_buffer(self, rx_tx, size): print(f'could not set "{rx_tx}" ring-buffer for {ifname}') return output + def set_switchdev(self, enable): + ifname = self.config['ifname'] + if not bool(re.match(r"^eth[0-9]+$", ifname)): + print(f'switchdev mode is only possible on physical interfaces!') + return + + addr, code = self._popen(f'ethtool -i {ifname} | grep bus-info | awk \'{{print $2}}\'') + if code != 0: + print(f'could not resolve PCIe address of {ifname}') + return + + enabled = False + state, code = self._popen(f'devlink dev eswitch show pci/0000:01:00.1 | awk \'{{print $3}}\'') + if code == 0 and state == 'switchdev': + enabled = True + + if enable and not enabled: + output, code = self._popen(f'/sbin/devlink dev eswitch set pci/{addr} mode switchdev') + if code != 0: + raise ConfigError(f'{ifname} does not support switchdev mode') + elif not enable and enabled: + self._cmd(f'/sbin/devlink dev eswitch set pci/{addr} mode legacy') + def update(self, config): """ General helper function which works on a dictionary retrived by get_config_dict(). It's main intention is to consolidate the scattered interface setup code and provide a single point of entry when workin on any interface. """ + # enable switchdev mode for additional offload options + self.set_switchdev('switchdev' in config) + # disable ethernet flow control (pause frames) value = 'off' if 'disable_flow_control' in config else 'on' self.set_flow_control(value) diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py index 3d12364f70e..6d7da77366c 100755 --- a/smoketest/scripts/cli/test_interfaces_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_ethernet.py @@ -222,5 +222,15 @@ def test_ethtool_evpn_uplink_tarcking(self): frrconfig = self.getFRRconfig(f'interface {interface}', daemon='zebra') self.assertIn(f' evpn mh uplink', frrconfig) + def test_switchdev(self): + interface = self._interfaces[0] + self.cli_set(self._base_path + [interface, 'switchdev']) + + # check validate() - virtual interfaces do not support switchdev + with self.assertRaises(ConfigSessionError): + self.cli_commit() + + self.cli_delete(self._base_path + [interface, 'switchdev']) + if __name__ == '__main__': unittest.main(verbosity=2)