From: Ido Schimmel <idosch(a)mellanox.com>
When PAUSE frames are enabled on a port it should send PAUSE frames
whenever its ingress buffers go above the Xoff threshold.
Make sure PAUSE frames are working properly by bridging two ports with
two different configured speeds. Send 40M UDP packets using pktgen
through the fast port and make sure no packets were lost by reading the
ethtool counters.
Perform a sanity check before enabling PAUSE frames and check that
packets are indeed dropped without it.
Signed-off-by: Ido Schimmel <idosch(a)mellanox.com>
---
recipes/switchdev/TestLib.py | 23 +++++++++
recipes/switchdev/default_aliases.xml | 4 ++
recipes/switchdev/qos-003-pause.py | 91 +++++++++++++++++++++++++++++++++++
recipes/switchdev/qos-003-pause.xml | 22 +++++++++
4 files changed, 140 insertions(+)
create mode 100644 recipes/switchdev/qos-003-pause.py
create mode 100644 recipes/switchdev/qos-003-pause.xml
diff --git a/recipes/switchdev/TestLib.py b/recipes/switchdev/TestLib.py
index 41ade9d..d6b8fa7 100644
--- a/recipes/switchdev/TestLib.py
+++ b/recipes/switchdev/TestLib.py
@@ -37,6 +37,10 @@ class TestLib:
self._mc_speed = int(aliases["mc_speed"])
else:
self._mc_speed = 1000
+ if "rx_prio_stats" in aliases:
+ self._rx_prio_stats = aliases["rx_prio_stats"]
+ if "tx_prio_stats" in aliases:
+ self._tx_prio_stats = aliases["tx_prio_stats"]
def _generate_default_desc(self, if1, ifs):
ret = "from %s->%s to " % (if1.get_host().get_id(), if1.get_id())
@@ -443,3 +447,22 @@ class TestLib:
self.devlink_pool_thtype_set(m, devlink_dev, pool, True)
self.devlink_port_quota_set(iface, pool, pool_size)
self.devlink_port_tc_quota_set(iface, tc, False, pool, pool_size)
+
+ def get_rx_prio_stats(self, iface, prio):
+ stat = "{}{}".format(self._rx_prio_stats, prio)
+ return iface.get_ethtool_stats()[stat]
+
+ def get_tx_prio_stats(self, iface, prio):
+ stat = "{}{}".format(self._tx_prio_stats, prio)
+ return iface.get_ethtool_stats()[stat]
+
+ def check_stats(self, iface, count, expected, desc, fail=False):
+ match = count == expected
+ err_msg = ""
+
+ if match and fail:
+ err_msg = "number of packets matched when shouldn't"
+ elif not match and not fail:
+ err_msg = "got {} packets, expected {}".format(count, expected)
+
+ return self.custom(iface.get_host(), desc, err_msg)
diff --git a/recipes/switchdev/default_aliases.xml
b/recipes/switchdev/default_aliases.xml
index 783fb5e..392506a 100644
--- a/recipes/switchdev/default_aliases.xml
+++ b/recipes/switchdev/default_aliases.xml
@@ -3,4 +3,8 @@
<alias name="mtu" value="1500" />
<alias name="netperf_duration" value="60" />
<alias name="netperf_num_parallel" value="30" />
+ <alias name="rx_prio_stats" value="rx_frames_prio_" />
+ <alias name="tx_prio_stats" value="tx_frames_prio_" />
+ <alias name="speed_hi" value="40000" />
+ <alias name="speed_lo" value="10000" />
</define>
diff --git a/recipes/switchdev/qos-003-pause.py b/recipes/switchdev/qos-003-pause.py
new file mode 100644
index 0000000..92a796f
--- /dev/null
+++ b/recipes/switchdev/qos-003-pause.py
@@ -0,0 +1,91 @@
+"""
+Copyright 2016 Mellanox Technologies. All rights reserved.
+Licensed under the GNU General Public License, version 2 as
+published by the Free Software Foundation; see COPYING for details.
+"""
+
+__author__ = """
+idosch(a)mellanox.com (Ido Schimmel)
+"""
+
+from lnst.Controller.Task import ctl
+from TestLib import TestLib
+from random import randint
+from time import sleep
+
+def get_stats(tl, rx_if, tx_if, prio):
+ return tl.get_rx_prio_stats(rx_if, prio), tl.get_tx_prio_stats(tx_if, prio)
+
+def do_task(ctl, hosts, ifaces, aliases):
+ m1, m2, sw = hosts
+ m1_if1, m2_if1, sw_if1, sw_if2 = ifaces
+
+ m1_if1.reset(ip=["192.168.101.10/24", "2002::1/64"])
+ m2_if1.reset(ip=["192.168.101.11/24", "2002::2/64"])
+
+ # Make sure we'll get the buffers congested.
+ sw_if1.set_speed(int(aliases["speed_hi"]))
+ sw_if2.set_speed(int(aliases["speed_lo"]))
+
+ sleep(30)
+
+ sw.create_bridge(slaves=[sw_if1, sw_if2], options={"vlan_filtering": 1})
+ sw_if1.add_br_vlan(10)
+ sw_if2.add_br_vlan(10)
+
+ # Packets can only stay in the headroom if the egress quotas
+ # of the egress port are set to the maximum.
+ tl = TestLib(ctl, aliases)
+ tl.devlink_port_etc_quota_max_set(sw_if2, 0)
+
+ # PAUSE frames and PFC can't be enabled simultaneously.
+ sw.enable_service("lldpad")
+ sw_if1.enable_lldp()
+ tl.lldp_pfc_set(sw_if1, [], willing=False)
+
+ m1.enable_service("lldpad")
+ m1_if1.enable_lldp()
+ tl.lldp_pfc_set(m1_if1, [])
+
+ # All the traffic should be directed to the same TC at egress.
+ sw_if2.enable_lldp()
+ tl.lldp_ets_default_set(sw_if2, willing=False)
+
+ m2.enable_service("lldpad")
+ m2_if1.enable_lldp()
+ tl.lldp_ets_default_set(m2_if1)
+
+ tl.ping_simple(m1_if1, m2_if1)
+
+ packet_count = 40 * 10 ** 6
+ prio = randint(1, 7)
+ # Make sure we get packet loss without PAUSE frames.
+ _, tx_stats_t0 = get_stats(tl, sw_if1, sw_if2, prio)
+ tl.pktgen(m1_if1, m2_if1, m1_if1.get_mtu(), vlan_id=10, vlan_p=prio,
+ count=packet_count)
+ _, tx_stats_t1 = get_stats(tl, sw_if1, sw_if2, prio)
+ tl.check_stats(sw_if1, tx_stats_t1 - tx_stats_t0, packet_count,
+ "tx prio {}".format(prio), fail=True)
+
+ sw_if1.set_pause_on()
+ m1_if1.set_pause_on()
+
+ for prio in range(1, 8):
+ rx_stats_t0, tx_stats_t0 = get_stats(tl, sw_if1, sw_if2, prio)
+ tl.pktgen(m1_if1, m2_if1, m1_if1.get_mtu(), vlan_id=10, vlan_p=prio,
+ count=packet_count)
+ rx_stats_t1, tx_stats_t1 = get_stats(tl, sw_if1, sw_if2, prio)
+
+ tl.check_stats(sw_if1, rx_stats_t1 - rx_stats_t0, packet_count,
+ "rx prio {}".format(prio))
+ tl.check_stats(sw_if2, tx_stats_t1 - tx_stats_t0, packet_count,
+ "tx prio {}".format(prio))
+
+do_task(ctl, [ctl.get_host("machine1"),
+ ctl.get_host("machine2"),
+ ctl.get_host("switch")],
+ [ctl.get_host("machine1").get_interface("if1"),
+ ctl.get_host("machine2").get_interface("if1"),
+ ctl.get_host("switch").get_interface("if1"),
+ ctl.get_host("switch").get_interface("if2")],
+ ctl.get_aliases())
diff --git a/recipes/switchdev/qos-003-pause.xml b/recipes/switchdev/qos-003-pause.xml
new file mode 100644
index 0000000..e60f508
--- /dev/null
+++ b/recipes/switchdev/qos-003-pause.xml
@@ -0,0 +1,22 @@
+<lnstrecipe
xmlns:xi="http://www.w3.org/2003/XInclude">
+ <xi:include href="default_aliases.xml" />
+ <network>
+ <host id="machine1">
+ <interfaces>
+ <eth id="if1" label="A" />
+ </interfaces>
+ </host>
+ <host id="machine2">
+ <interfaces>
+ <eth id="if1" label="B" />
+ </interfaces>
+ </host>
+ <host id="switch">
+ <interfaces>
+ <eth id="if1" label="A" />
+ <eth id="if2" label="B" />
+ </interfaces>
+ </host>
+ </network>
+ <task python="qos-003-pause.py" />
+</lnstrecipe>
--
2.7.4