From 5ee89f46096626ca8aac37da9237635e3d17766a Mon Sep 17 00:00:00 2001
From: Christian Breunig <christian@breunig.cc>
Date: Sun, 3 Mar 2024 20:24:46 +0100
Subject: vyos.ethtool: T6083: use JSON input data for ethernet interface
 flow-control settings

---
 python/vyos/ethtool.py                            | 21 +++++++-----------
 smoketest/scripts/cli/test_interfaces_ethernet.py | 27 +++++++++++++++++++++++
 2 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/python/vyos/ethtool.py b/python/vyos/ethtool.py
index ccbb97ad4..473c98d0c 100644
--- a/python/vyos/ethtool.py
+++ b/python/vyos/ethtool.py
@@ -62,8 +62,7 @@ class Ethtool:
     _driver_name = None
     _auto_negotiation = False
     _auto_negotiation_supported = None
-    _flow_control = False
-    _flow_control_enabled = None
+    _flow_control = None
     _eee = False
     _eee_enabled = None
 
@@ -115,12 +114,9 @@ class Ethtool:
 
         # Get current flow control settings, but this is not supported by
         # all NICs (e.g. vmxnet3 does not support is)
-        out, _ = popen(f'ethtool --show-pause {ifname}')
-        if len(out.splitlines()) > 1:
-            self._flow_control = True
-            # read current flow control setting, this returns:
-            # ['Autonegotiate:', 'on']
-            self._flow_control_enabled = out.splitlines()[1].split()[-1]
+        out, err = popen(f'ethtool --json --show-pause {ifname}')
+        if not bool(err):
+            self._flow_control = loads(out)
 
         # Get current Energy Efficient Ethernet (EEE) settings, but this is
         # not supported by all NICs (e.g. vmxnet3 does not support is)
@@ -207,15 +203,14 @@ class Ethtool:
 
     def check_flow_control(self):
         """ Check if the NIC supports flow-control """
-        if self.get_driver_name() in _drivers_without_speed_duplex_flow:
-            return False
-        return self._flow_control
+        return bool(self._flow_control)
 
     def get_flow_control(self):
-        if self._flow_control_enabled == None:
+        if self._flow_control == None:
             raise ValueError('Interface does not support changing '\
                              'flow-control settings!')
-        return self._flow_control_enabled
+
+        return 'on' if bool(self._flow_control[0]['autonegotiate']) else 'off'
 
     def check_eee(self):
         """ Check if the NIC supports eee """
diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py
index 9bf6a1a61..8f387b23d 100755
--- a/smoketest/scripts/cli/test_interfaces_ethernet.py
+++ b/smoketest/scripts/cli/test_interfaces_ethernet.py
@@ -31,6 +31,7 @@ from vyos.ifconfig import Section
 from vyos.pki import CERT_BEGIN
 from vyos.utils.process import cmd
 from vyos.utils.process import process_named_running
+from vyos.utils.process import popen
 from vyos.utils.file import read_file
 from vyos.utils.network import is_ipv6_link_local
 
@@ -304,6 +305,8 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase):
 
     def test_ethtool_ring_buffer(self):
         for interface in self._interfaces:
+            # We do not use vyos.ethtool here to not have any chance
+            # for invalid testcases. Re-gain data by hand
             tmp = cmd(f'sudo ethtool --json --show-ring {interface}')
             tmp = loads(tmp)
             max_rx = str(tmp[0]['rx-max'])
@@ -327,5 +330,29 @@ class EthernetInterfaceTest(BasicInterfaceTest.TestCase):
             self.assertEqual(max_rx, rx)
             self.assertEqual(max_tx, tx)
 
+    def test_ethtool_flow_control(self):
+        for interface in self._interfaces:
+            # Disable flow-control
+            self.cli_set(self._base_path + [interface, 'disable-flow-control'])
+            # Check current flow-control state on ethernet interface
+            out, err = popen(f'sudo ethtool --json --show-pause {interface}')
+            # Flow-control not supported - test if it bails out with a proper
+            # this is a dynamic path where err = 1 on VMware, but err = 0 on
+            # a physical box.
+            if bool(err):
+                with self.assertRaises(ConfigSessionError):
+                    self.cli_commit()
+            else:
+                out = loads(out)
+                # Flow control is on
+                self.assertTrue(out[0]['autonegotiate'])
+
+                # commit change on CLI to disable-flow-control and re-test
+                self.cli_commit()
+
+                out, err = popen(f'sudo ethtool --json --show-pause {interface}')
+                out = loads(out)
+                self.assertFalse(out[0]['autonegotiate'])
+
 if __name__ == '__main__':
     unittest.main(verbosity=2)
-- 
cgit v1.2.3