This patchset adds some basic test for L2 MC behaviours. The first three patches add a MC related commands to LNST. The 4th patch adds the ability to count CPU traffic, so it will be possible to check if the traffic were really offloaded and hadn't gone via slowpath. Patches 5 & 6 update the current MDB test to be more generic and to check that the traffic is offloaded. Patch 7 adds a test to check that the MDB is ignored when MC is disabled. Patches 8-10 add tests for mrouter bridge config option (as in IGMP configuration, not to be confused with any L3 property). Patch 11 adds a test for unregistered MC packets.
This patchset does not address: * LAG in MC. * static MDB,
Nogah Frankel (11): common: add a consts file for mrouter port related consts Interface: add mcast flood and mrouter set functions Bridge: add set mcast bridge functions Interface: Add cpu ifstat function recipes: switchdev: TestLib: Change iperf_mc to be more generic recipes: switchdev: TestLib: Check whether packets goes in slowpath recipes: switchdev: Add the mdb mcast disabled test recipes: switchdev: Add basic mrouter test recipes: switchdev: Add mrouter learning test recipes: switchdev: Add a test for many floods with mrouters recipes: switchdev: Add a test for unregistered MC traffic
lnst/Common/Consts.py | 16 +++ lnst/Controller/Machine.py | 20 +++ lnst/Controller/Task.py | 15 +++ lnst/Slave/BridgeTool.py | 10 ++ lnst/Slave/InterfaceManager.py | 42 ++++++ lnst/Slave/NetTestSlave.py | 43 +++++++ recipes/switchdev/TestLib.py | 94 +++++++------- recipes/switchdev/l2-020-bridge_mdb.py | 38 ++++-- .../switchdev/l2-022-bridge_mdb_mcast_disabled.py | 85 ++++++++++++ .../switchdev/l2-022-bridge_mdb_mcast_disabled.xml | 70 ++++++++++ .../l2-023-bridge_mdb_mc_router_port_basic.py | 108 ++++++++++++++++ .../l2-023-bridge_mdb_mc_router_port_basic.xml | 70 ++++++++++ .../l2-024-bridge_mdb_mc_router_port_learning.py | 91 +++++++++++++ .../l2-024-bridge_mdb_mc_router_port_learning.xml | 70 ++++++++++ .../l2-025-bridge_mdb_flood_with_mc_router.py | 142 +++++++++++++++++++++ .../l2-025-bridge_mdb_flood_with_mc_router.xml | 70 ++++++++++ recipes/switchdev/l2-026-bridge_mdb_unreg_flood.py | 92 +++++++++++++ .../switchdev/l2-026-bridge_mdb_unreg_flood.xml | 70 ++++++++++ 18 files changed, 1093 insertions(+), 53 deletions(-) create mode 100644 lnst/Common/Consts.py create mode 100644 recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.py create mode 100644 recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.xml create mode 100644 recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.py create mode 100644 recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.xml create mode 100644 recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.py create mode 100644 recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.xml create mode 100644 recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.py create mode 100644 recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.xml create mode 100644 recipes/switchdev/l2-026-bridge_mdb_unreg_flood.py create mode 100644 recipes/switchdev/l2-026-bridge_mdb_unreg_flood.xml
Add a Consts file to Common that holds classes that have only constants values and no methods. Add there a class for L2 multicast-router port related consts.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com --- lnst/Common/Consts.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 lnst/Common/Consts.py
diff --git a/lnst/Common/Consts.py b/lnst/Common/Consts.py new file mode 100644 index 0000000..bdcff0b --- /dev/null +++ b/lnst/Common/Consts.py @@ -0,0 +1,16 @@ +""" +General perpuses constants file + +Copyright 2016-2017 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. +""" + +__autor__ = """ +nogahf@mellanox.com (Nogah Frankel) +""" + +class MCAST_ROUTER_PORT: + FIXED_OFF = 0 + LEARNING = 1 + FIXED_ON = 2
Mon, Sep 25, 2017 at 03:40:23PM CEST, nogahf@mellanox.com wrote:
Add a Consts file to Common that holds classes that have only constants values and no methods. Add there a class for L2 multicast-router port related consts.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com
lnst/Common/Consts.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 lnst/Common/Consts.py
diff --git a/lnst/Common/Consts.py b/lnst/Common/Consts.py new file mode 100644 index 0000000..bdcff0b --- /dev/null +++ b/lnst/Common/Consts.py @@ -0,0 +1,16 @@ +""" +General perpuses constants file
+Copyright 2016-2017 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. +"""
+__autor__ = """ +nogahf@mellanox.com (Nogah Frankel) +"""
+class MCAST_ROUTER_PORT:
- FIXED_OFF = 0
- LEARNING = 1
- FIXED_ON = 2
Hi Nogah,
I see that you're about to use this in a recipe. If so I think it should be placed under lnst/RecipeCommon/ directory rather than lnst/Common.
Additionally the Consts.py sounds too general to me. Is this file intended also for other stuff than switchdev testing?
Regards, Jan
-----Original Message----- From: Jan Tluka [mailto:jtluka@redhat.com] Sent: Monday, September 25, 2017 5:26 PM To: Nogah Frankel nogahf@mellanox.com Cc: lnst-developers@lists.fedorahosted.org; mlxsw mlxsw@mellanox.com; Yotam Gigi yotamg@mellanox.com Subject: Re: [PATCH LNST 01/11] common: add a consts file for mrouter port related consts
Mon, Sep 25, 2017 at 03:40:23PM CEST, nogahf@mellanox.com wrote:
Add a Consts file to Common that holds classes that have only constants values and no methods. Add there a class for L2 multicast-router port related consts.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com
lnst/Common/Consts.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 lnst/Common/Consts.py
diff --git a/lnst/Common/Consts.py b/lnst/Common/Consts.py new file mode 100644 index 0000000..bdcff0b --- /dev/null +++ b/lnst/Common/Consts.py @@ -0,0 +1,16 @@ +""" +General perpuses constants file
+Copyright 2016-2017 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. +"""
+__autor__ = """ +nogahf@mellanox.com (Nogah Frankel) +"""
+class MCAST_ROUTER_PORT:
- FIXED_OFF = 0
- LEARNING = 1
- FIXED_ON = 2
Hi Nogah,
I see that you're about to use this in a recipe. If so I think it should be placed under lnst/RecipeCommon/ directory rather than lnst/Common.
Additionally the Consts.py sounds too general to me. Is this file intended also for other stuff than switchdev testing?
Regards, Jan
Hi Jan
This file should contain a lot of consts classes, for multiple purposes. This first class is recipe only, but other classes might not be. (Actually, we have a code in writing right now that have a consts class that is in use in some BridgeTool function).
I agree that this file is quite general, and in the future it should probably become a package with several files under it , but I think that we should wait until we have some more classes in there before deciding how to break it apart.
Thanks
Nogah
Mon, Sep 25, 2017 at 04:46:44PM CEST, nogahf@mellanox.com wrote:
-----Original Message----- From: Jan Tluka [mailto:jtluka@redhat.com] Sent: Monday, September 25, 2017 5:26 PM To: Nogah Frankel nogahf@mellanox.com Cc: lnst-developers@lists.fedorahosted.org; mlxsw mlxsw@mellanox.com; Yotam Gigi yotamg@mellanox.com Subject: Re: [PATCH LNST 01/11] common: add a consts file for mrouter port related consts
Mon, Sep 25, 2017 at 03:40:23PM CEST, nogahf@mellanox.com wrote:
Add a Consts file to Common that holds classes that have only constants values and no methods. Add there a class for L2 multicast-router port related consts.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com
lnst/Common/Consts.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 lnst/Common/Consts.py
diff --git a/lnst/Common/Consts.py b/lnst/Common/Consts.py new file mode 100644 index 0000000..bdcff0b --- /dev/null +++ b/lnst/Common/Consts.py @@ -0,0 +1,16 @@ +""" +General perpuses constants file
+Copyright 2016-2017 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. +"""
+__autor__ = """ +nogahf@mellanox.com (Nogah Frankel) +"""
+class MCAST_ROUTER_PORT:
- FIXED_OFF = 0
- LEARNING = 1
- FIXED_ON = 2
Hi Nogah,
I see that you're about to use this in a recipe. If so I think it should be placed under lnst/RecipeCommon/ directory rather than lnst/Common.
Additionally the Consts.py sounds too general to me. Is this file intended also for other stuff than switchdev testing?
Regards, Jan
Hi Jan
This file should contain a lot of consts classes, for multiple purposes. This first class is recipe only, but other classes might not be. (Actually, we have a code in writing right now that have a consts class that is in use in some BridgeTool function).
I agree that this file is quite general, and in the future it should probably become a package with several files under it , but I think that we should wait until we have some more classes in there before deciding how to break it apart.
Thanks
Nogah
Ok, if you're going to use it also in other code than recipe, I'm ok with this.
-Jan
Add functions to set mcast flood on\off on an interface that is a bridge slave. Add a similar support to set mrouter port state. Mcast flood flag decides whether multicast packets should be flooded to a port when multicast snooping is disabled. Default is on. Mrouter port state can be fixed on, fixed off or learning, where the later indicates that the mrouter state should be learned according to IGMP queries. If a port is set to be mrouter port, all multicast packets will be flooded to it, when multicast snooping is enabled.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com --- lnst/Controller/Machine.py | 7 +++++++ lnst/Controller/Task.py | 6 ++++++ lnst/Slave/InterfaceManager.py | 13 +++++++++++++ lnst/Slave/NetTestSlave.py | 18 ++++++++++++++++++ 4 files changed, 44 insertions(+)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py index fe196ad..7077018 100644 --- a/lnst/Controller/Machine.py +++ b/lnst/Controller/Machine.py @@ -966,6 +966,13 @@ class Interface(object): self._machine._rpc_call_x(self._netns, "set_br_state", self._id, br_state_info)
+ def set_mcast_flood(self, on): + self._machine._rpc_call_x(self._netns, "set_mcast_flood", self._id, on) + + def set_mcast_router(self, state): + self._machine._rpc_call_x(self._netns, "set_mcast_router", self._id, + state) + def set_speed(self, speed): self._machine._rpc_call_x(self._netns, "set_speed", self._id, speed)
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py index b5080d2..daf52ab 100644 --- a/lnst/Controller/Task.py +++ b/lnst/Controller/Task.py @@ -700,6 +700,12 @@ class InterfaceAPI(object): def set_br_state(_self, state, self=False, master=False): _self._if.set_br_state({"state": state, "self": self, "master": master})
+ def set_mcast_flood(self, on): + return self._if.set_mcast_flood(on) + + def set_mcast_router(self, state): + return self._if.set_mcast_router(state) + def set_speed(self, speed): return self._if.set_speed(speed)
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py index b21c962..e6399b3 100644 --- a/lnst/Slave/InterfaceManager.py +++ b/lnst/Slave/InterfaceManager.py @@ -797,3 +797,16 @@ class Device(object): def set_pause_off(self): exec_cmd("ethtool -A %s rx off tx off autoneg off" % self._name, die_on_err=False) + + def set_mcast_flood(self, on = True): + cmd = "ip link set dev %s type bridge_slave mcast_flood " % self._name + if on: + cmd += "on" + else: + cmd += "off" + exec_cmd(cmd) + + def set_mcast_router(self, state): + cmd = "ip link set dev %s type bridge_slave mcast_router %d" % \ + (self._name, state) + exec_cmd(cmd) diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py index ddbfe72..8a39f90 100644 --- a/lnst/Slave/NetTestSlave.py +++ b/lnst/Slave/NetTestSlave.py @@ -1031,6 +1031,24 @@ class SlaveMethods: return False return True
+ def set_mcast_flood(self, if_id, on): + dev = self._if_manager.get_mapped_device(if_id) + if dev is not None: + dev.set_mcast_flood(on) + else: + logging.error("Device with id '%s' not found." % if_id) + return False + return True + + def set_mcast_router(self, if_id, state): + dev = self._if_manager.get_mapped_device(if_id) + if dev is not None: + dev.set_mcast_router(state) + else: + logging.error("Device with id '%s' not found." % if_id) + return False + return True + class ServerHandler(ConnectionHandler): def __init__(self, addr): super(ServerHandler, self).__init__()
Add an ability to set the mcast snooping option and mcast querier option on a bridge.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com --- lnst/Controller/Machine.py | 8 ++++++++ lnst/Controller/Task.py | 6 ++++++ lnst/Slave/BridgeTool.py | 10 ++++++++++ lnst/Slave/NetTestSlave.py | 18 ++++++++++++++++++ 4 files changed, 42 insertions(+)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py index 7077018..a6a3165 100644 --- a/lnst/Controller/Machine.py +++ b/lnst/Controller/Machine.py @@ -966,6 +966,14 @@ class Interface(object): self._machine._rpc_call_x(self._netns, "set_br_state", self._id, br_state_info)
+ def set_br_mcast_snooping(self, set_on): + self._machine._rpc_call_x(self._netns, "set_br_mcast_snooping", + self._id, set_on) + + def set_br_mcast_querier(self, set_on): + self._machine._rpc_call_x(self._netns, "set_br_mcast_querier", self._id, + set_on) + def set_mcast_flood(self, on): self._machine._rpc_call_x(self._netns, "set_mcast_flood", self._id, on)
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py index daf52ab..10b937d 100644 --- a/lnst/Controller/Task.py +++ b/lnst/Controller/Task.py @@ -700,6 +700,12 @@ class InterfaceAPI(object): def set_br_state(_self, state, self=False, master=False): _self._if.set_br_state({"state": state, "self": self, "master": master})
+ def set_br_mcast_snooping(_self, set_on = True): + _self._if.set_br_mcast_snooping(set_on) + + def set_br_mcast_querier(_self, set_on = True): + _self._if.set_br_mcast_querier(set_on) + def set_mcast_flood(self, on): return self._if.set_mcast_flood(on)
diff --git a/lnst/Slave/BridgeTool.py b/lnst/Slave/BridgeTool.py index 5e8f497..d93b1b9 100644 --- a/lnst/Slave/BridgeTool.py +++ b/lnst/Slave/BridgeTool.py @@ -117,3 +117,13 @@ class BridgeTool: if br_state_info["master"]: cmd += " master" exec_cmd(cmd) + + def set_mcast_snooping(self, set_on = True): + cmd = "ip link set %s type bridge mcast_snooping %d" % (self._dev_name, + set_on) + exec_cmd(cmd) + + def set_mcast_querier(self, set_on = True): + cmd = "ip link set %s type bridge mcast_querier %d" % (self._dev_name, + set_on) + exec_cmd(cmd) diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py index 8a39f90..af80f55 100644 --- a/lnst/Slave/NetTestSlave.py +++ b/lnst/Slave/NetTestSlave.py @@ -937,6 +937,24 @@ class SlaveMethods: brt.set_state(br_state_info) return True
+ def set_br_mcast_snooping(self, if_id, set_on = True): + dev = self._if_manager.get_mapped_device(if_id) + if not dev: + logging.error("Device with id '%s' not found." % if_id) + return False + brt = BridgeTool(dev.get_name()) + brt.set_mcast_snooping(set_on) + return True + + def set_br_mcast_querier(self, if_id, set_on = True): + dev = self._if_manager.get_mapped_device(if_id) + if not dev: + logging.error("Device with id '%s' not found." % if_id) + return False + brt = BridgeTool(dev.get_name()) + brt.set_mcast_querier(set_on) + return True + def set_speed(self, if_id, speed): dev = self._if_manager.get_mapped_device(if_id) if dev is not None:
Add a function that returns the ifstat (relative statistic, being set to 0 on every read) for cpu hits (packets that went on slow path). Can be used only on devices that support this ifstat extension.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com --- lnst/Controller/Machine.py | 5 +++++ lnst/Controller/Task.py | 3 +++ lnst/Slave/InterfaceManager.py | 29 +++++++++++++++++++++++++++++ lnst/Slave/NetTestSlave.py | 7 +++++++ 4 files changed, 44 insertions(+)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py index a6a3165..1836f71 100644 --- a/lnst/Controller/Machine.py +++ b/lnst/Controller/Machine.py @@ -783,6 +783,11 @@ class Interface(object): self._id) return stats
+ def link_cpu_ifstat(self): + stats = self._machine._rpc_call_x(self._netns, "link_cpu_ifstat", + self._id) + return stats + def set_addresses(self, ips): self._addresses = ips self._machine._rpc_call_x(self._netns, "set_addresses", diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py index 10b937d..70293a5 100644 --- a/lnst/Controller/Task.py +++ b/lnst/Controller/Task.py @@ -610,6 +610,9 @@ class InterfaceAPI(object): def link_stats(self): return self._if.link_stats()
+ def link_cpu_ifstat(self): + return self._if.link_cpu_ifstat() + def set_link_up(self): return self._if.set_link_up()
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py index e6399b3..e28682f 100644 --- a/lnst/Slave/InterfaceManager.py +++ b/lnst/Slave/InterfaceManager.py @@ -705,6 +705,35 @@ class Device(object): "tx_collsns": tx_stats[5]}) return stats
+ def link_cpu_ifstat(self): + stats = {"devname": self._name, + "hwaddr": self._hwaddr} + try: + out, _ = exec_cmd("ifstat -x c %s" % self._name) + except: + return {} + lines = iter(out.split("\n")) + line_first = "" + line_decond = "" + for line in lines: + if (len(line.split()) == 0): + continue + if (line.split()[0] == self._name): + break + else: + return {} + stats_data = line.split()[1:] + for i in range(len(stats_data)): + stats_data[i] = stats_data[i].replace("K", "000") + stats_data[i] = stats_data[i].replace("M", "000000") + + stats_data = map(int, stats_data) + stats["rx_packets"] = stats_data[0] + stats["tx_packets"] = stats_data[2] + stats["rx_bytes"] = stats_data[4] + stats["tx_bytes"] = stats_data[6] + return stats + def set_addresses(self, ips): self._conf.set_addresses(ips) exec_cmd("ip addr flush %s" % self._name) diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py index af80f55..cdcf951 100644 --- a/lnst/Slave/NetTestSlave.py +++ b/lnst/Slave/NetTestSlave.py @@ -194,6 +194,13 @@ class SlaveMethods: return {} return dev.get_if_data()
+ def link_cpu_ifstat(self, if_id): + dev = self._if_manager.get_mapped_device(if_id) + if dev is None: + logging.error("Device with id '%s' not found." % if_id) + return {} + return dev.link_cpu_ifstat() + def link_stats(self, if_id): dev = self._if_manager.get_mapped_device(if_id) if dev is None:
Currently the function iperf_mc have 3 tasks: * set up the environment for mc (setting mc enable, sending join requests, etc.). * send mc traffic and check who got it. * compare the results to the expected ones.
Following patches will introduce tests for more complicated scenarios. So this patch breaks the 3 tasks apart. The first one will be done in each test. The second remains in iperf_mc and the third will be done in a new function in Testlib called mc_ipref_compare_result. This patch also updates test 20 to keep up with these changes.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com --- recipes/switchdev/TestLib.py | 79 +++++++++++++++------------------- recipes/switchdev/l2-020-bridge_mdb.py | 31 ++++++++++--- 2 files changed, 58 insertions(+), 52 deletions(-)
diff --git a/recipes/switchdev/TestLib.py b/recipes/switchdev/TestLib.py index e34161c..62db24e 100644 --- a/recipes/switchdev/TestLib.py +++ b/recipes/switchdev/TestLib.py @@ -201,75 +201,64 @@ class TestLib: } return self._ctl.get_module("Iperf", options = modules_options)
- def iperf_mc(self, sender, listeners, bridged, mc_group, desc=None): + def iperf_mc_listen(self, listener, mc_group): + host = listener.get_host() + srv_m = self._get_iperf_srv_mod(mc_group) + proc = host.run(srv_m, bg=True, netns=listener.get_netns()) + return proc + + def iperf_mc(self, sender, recivers, mc_group, desc=None): if not desc: - desc = self._generate_default_desc(sender, listeners) + desc = self._generate_default_desc(sender, recivers)
sender.set_mtu(self._mtu) - sender.enable_multicast() - map(lambda i:i.enable_multicast(), listeners + bridged) - map(lambda i:i.set_mtu(self._mtu), listeners + bridged) + map(lambda i:i.set_mtu(self._mtu), recivers)
sender_host = sender.get_host() - listeners_host = map(lambda i:i.get_host(), listeners) - bridged_host = map(lambda i:i.get_host(), bridged) + recivers_host = map(lambda i:i.get_host(), recivers)
map(lambda i:i.sync_resources(modules=["Iperf"]), - listeners_host + bridged_host) + recivers_host)
duration = self._netperf_duration speed = self._mc_speed
# read link-stats - sender_stats = sender.link_stats() - listeners_stats = map(lambda i:i.link_stats(), listeners) - bridged_stats = map(lambda i:i.link_stats(), bridged) - - # Run iperf server for all listeners - srv_m = self._get_iperf_srv_mod(mc_group) - s_procs = map(lambda i:i[0].run(srv_m, bg=True, netns=i[1].get_netns()), - zip(listeners_host, listeners)) - self._ctl.wait(2) + sender_stats_before = sender.link_stats() + recivers_stats_before = map(lambda i:i.link_stats(), recivers)
# An send traffic to all listeners but bridged cli_m = self._get_iperf_cli_mod(mc_group, duration, speed) sender_host.run(cli_m, timeout=duration + 10, desc=desc, netns=sender.get_netns()) - map(lambda i:i.intr(), s_procs) - map(lambda i:i.disable_multicast(), listeners + bridged) - sender.disable_multicast()
# re-read link-stats - sender_stats1 = sender.link_stats() - listeners_stats1 = map(lambda i:i.link_stats(), listeners) - bridged_stats1 = map(lambda i:i.link_stats(), bridged) - - # Check that listeners got multi cast traffic - tx = sender_stats1["tx_bytes"] - sender_stats["tx_bytes"] - rx = map(lambda i:i[1]["rx_bytes"] - i[0]["rx_bytes"], - zip(listeners_stats, listeners_stats1)) - err = filter(lambda i:i[0] < self._mc_high_thershold, zip(rx, listeners)) - err_str = map(lambda i:("Traffic isn't received for %s:%s count %d" % - (i[1].get_host().get_id(), i[1].get_id(), i[0]), - i[1]), err) - for i in err_str: - self.custom(i[1].get_host(), "iperf_mc", i[0]) - for i in zip(rx, listeners): + sender_stats_after = sender.link_stats() + recivers_stats_after = map(lambda i:i.link_stats(), recivers) + + # Check that who got multi cast traffic + tx = sender_stats_after["tx_bytes"] - sender_stats_before["tx_bytes"] + rx = map(lambda i,l:i["rx_bytes"] - l["rx_bytes"], + recivers_stats_after, recivers_stats_before) + recivers_result = [rate > self._mc_high_thershold for rate in rx] + for i in zip(rx, recivers): logging.info("Measured traffic on %s:%s is %dMb, bytes lost %d (%d%%)" % (i[1].get_host().get_id(), i[1].get_id(), i[0] / 1000000, max(tx - i[0], 0), (max(tx - i[0], 0) * 100) / tx)) - - # Check that only listeners got traffic - rx = map(lambda i:i[1]["rx_bytes"] - i[0]["rx_bytes"], - zip(bridged_stats, bridged_stats1)) - err = filter(lambda i:i[0] > self._mc_low_thershold, zip(rx, bridged)) - err_str = map(lambda i:("Received unwanted traffic for %s:%s count %d" % - (i[1].get_host().get_id(), i[1].get_id(), i[0]), - i[1]), err) - for i in err_str: - self.custom(i[1].get_host(), "iperf_mc", i[0]) + return recivers_result + + def mc_ipref_compare_result(self, ifaces, results, expected): + err_indices = [i for i in range(len(results)) + if results[i] != expected[i]] + for i in err_indices: + iface, result, expect = ifaces[i], results[i], expected[i] + err_str = "interface %s in %s %s traffic, when it %s get" % \ + (iface.get_id(), iface.get_host().get_id(), \ + ["didn't get", "got"][result], \ + ["shouldn't", "should"][expect]) + self.custom(iface.get_host(), "iperf_mc", err_str)
def pktgen(self, if1, if2, pkt_size, desc=None, thread_option=[], **kwargs): if1.set_mtu(self._mtu) diff --git a/recipes/switchdev/l2-020-bridge_mdb.py b/recipes/switchdev/l2-020-bridge_mdb.py index 04bcae9..f48d11e 100644 --- a/recipes/switchdev/l2-020-bridge_mdb.py +++ b/recipes/switchdev/l2-020-bridge_mdb.py @@ -7,6 +7,7 @@ published by the Free Software Foundation; see COPYING for details. __author__ = """ eladr@mellanox.com (Elad Raz) jiri@mellanox.com (Jiri Pirko) +nogahf@mellanox.com (Nogah Frankel) """
from lnst.Controller.Task import ctl @@ -17,6 +18,16 @@ def test_ip(major, minor): return ["192.168.10%d.%d/24" % (major, minor), "2002:%d::%d/64" % (major, minor)]
+def mcgrp(i): + return "239.255.1.%d" % i + +def test_standard_mutlicast(tl, sender, listeners, bridged, group): + s_procs = [tl.iperf_mc_listen(listener, group) for listener in listeners] + res = tl.iperf_mc(sender, listeners+ bridged, group) + expected = [True for l in listeners] + [False for l in bridged] + tl.mc_ipref_compare_result(listeners + bridged, res, expected) + map(lambda i:i.intr(), s_procs) + def do_task(ctl, hosts, ifaces, aliases): m1, m2, sw = hosts m1_if, m2_if, m3_if, m4_if, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces @@ -25,16 +36,22 @@ def do_task(ctl, hosts, ifaces, aliases): sw_br = sw.create_bridge(slaves=[sw_if1, sw_if2, sw_if3, sw_if4], options={"vlan_filtering": 1})
- m1_if.set_addresses(["192.168.101.10/24", "2002::1/64"]) - m2_if.set_addresses(["192.168.101.11/24", "2002::2/64"]) - m3_if.set_addresses(["192.168.101.13/24", "2002::3/64"]) - m4_if.set_addresses(["192.168.101.14/24", "2002::4/64"]) + m1_if.set_addresses(test_ip(1,1)) + m2_if.set_addresses(test_ip(1, 2)) + m3_if.set_addresses(test_ip(1, 3)) + m4_if.set_addresses(test_ip(1, 4)) sleep(30)
tl = TestLib(ctl, aliases) - tl.iperf_mc(m1_if, [m2_if, m4_if], [m3_if], "239.255.1.3") - tl.iperf_mc(m1_if, [m4_if], [], "239.255.1.4") - tl.iperf_mc(m2_if, [m3_if, m4_if, m1_if] , [], "239.255.1.5") + + for iface in [m1_if, m2_if, m3_if, m4_if]: + iface.enable_multicast() + + test_standard_mutlicast(tl, m1_if, [m2_if, m4_if], [m3_if], mcgrp(3)) + test_standard_mutlicast(tl, m1_if, [m4_if], [m2_if, m3_if], mcgrp(4)) + test_standard_mutlicast(tl, m2_if, [m3_if, m4_if, m1_if], [], mcgrp(5)) + for iface in [m1_if, m2_if, m3_if, m4_if]: + iface.disable_multicast()
do_task(ctl, [ctl.get_host("machine1"), ctl.get_host("machine2"),
Add a function that validates that the amount of packets went via slowpath is below a threshold. It counts the traffic with ifstat, meaning that it returns the traffic count since the last call to it. So one should call it and ignore the results before starting the traffic. Add this check to test 20 to check that data is not going via slowpath.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com --- recipes/switchdev/TestLib.py | 17 +++++++++++++++++ recipes/switchdev/l2-020-bridge_mdb.py | 7 +++++-- 2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/recipes/switchdev/TestLib.py b/recipes/switchdev/TestLib.py index 62db24e..e6ba505 100644 --- a/recipes/switchdev/TestLib.py +++ b/recipes/switchdev/TestLib.py @@ -260,6 +260,23 @@ class TestLib: ["shouldn't", "should"][expect]) self.custom(iface.get_host(), "iperf_mc", err_str)
+ def check_cpu_traffic(self, ifaces, thershold = 100, test = True): + err = False + for iface in ifaces: + stats = iface.link_cpu_ifstat() + if not test: + continue + + # Check tx only, since in rx case it is hard to distinguish between + # offloading error and "legal" cpu traps. + if stats["tx_packets"] > thershold: + err = True + self.custom(iface.get_host(), "cpu traffic", + "%s sent too much data (%d packets)" % \ + (stats["devname"], stats["tx_packets"])) + if not err: + self.custom(iface.get_host(), "cpu traffic", "") + def pktgen(self, if1, if2, pkt_size, desc=None, thread_option=[], **kwargs): if1.set_mtu(self._mtu) m1 = if1.get_host() diff --git a/recipes/switchdev/l2-020-bridge_mdb.py b/recipes/switchdev/l2-020-bridge_mdb.py index f48d11e..7f89104 100644 --- a/recipes/switchdev/l2-020-bridge_mdb.py +++ b/recipes/switchdev/l2-020-bridge_mdb.py @@ -33,8 +33,9 @@ def do_task(ctl, hosts, ifaces, aliases): m1_if, m2_if, m3_if, m4_if, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces
# Create a bridge - sw_br = sw.create_bridge(slaves=[sw_if1, sw_if2, sw_if3, sw_if4], - options={"vlan_filtering": 1}) + sw_ports = [sw_if1, sw_if2, sw_if3, sw_if4] + sw_br = sw.create_bridge(slaves=sw_ports, options={"vlan_filtering": 1, + "multicast_querier": 1})
m1_if.set_addresses(test_ip(1,1)) m2_if.set_addresses(test_ip(1, 2)) @@ -44,6 +45,7 @@ def do_task(ctl, hosts, ifaces, aliases):
tl = TestLib(ctl, aliases)
+ tl.check_cpu_traffic(sw_ports, test=False) for iface in [m1_if, m2_if, m3_if, m4_if]: iface.enable_multicast()
@@ -52,6 +54,7 @@ def do_task(ctl, hosts, ifaces, aliases): test_standard_mutlicast(tl, m2_if, [m3_if, m4_if, m1_if], [], mcgrp(5)) for iface in [m1_if, m2_if, m3_if, m4_if]: iface.disable_multicast() + tl.check_cpu_traffic(sw_ports)
do_task(ctl, [ctl.get_host("machine1"), ctl.get_host("machine2"),
The mdb mcast disabled test case tests that the bridge mcast_disabled flag gets offloaded right
The test's algorithm is as follows: - Add ports to mcast group - Send traffic to that group - Validate that traffic received only by joined ports - Turn mcast_disabled flag on - Send traffic to that same group - Validate that traffic received by all ports - Check that all the traffic hadn't gone via slowpath
Signed-off-by: Yotam Gigi yotamg@mellanox.com Signed-off-by: Nogah Frankel nogahf@mellanox.com --- .../switchdev/l2-022-bridge_mdb_mcast_disabled.py | 85 ++++++++++++++++++++++ .../switchdev/l2-022-bridge_mdb_mcast_disabled.xml | 70 ++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.py create mode 100644 recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.xml
diff --git a/recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.py b/recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.py new file mode 100644 index 0000000..0351582 --- /dev/null +++ b/recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.py @@ -0,0 +1,85 @@ +""" +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__ = """ +yotamg@mellanox.com (Yotam Gigi) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def test_ip(major, minor): + return ["192.168.10%d.%d/24" % (major, minor), + "2002:%d::%d/64" % (major, minor)] + +def mcgrp(i): + return "239.255.1.%d" % i + +def test_mcast_onoff(tl, sw_br, sender, listeners, bridged, group): + mcast_ifaces = listeners + bridged + sw = sw_br.get_host() + + expected_mcast_on = [True for l in listeners] + [False for l in bridged] + expected_mcast_off = [True for l in listeners] + [True for l in bridged] + + s_procs = [tl.iperf_mc_listen(listener, group) for listener in listeners] + tl._ctl.wait(2) + + result = tl.iperf_mc(sender, mcast_ifaces, group) + tl.mc_ipref_compare_result(mcast_ifaces, result, expected_mcast_on) + + sw_br.set_br_mcast_snooping(False) + result = tl.iperf_mc(sender, mcast_ifaces, group) + tl.mc_ipref_compare_result(mcast_ifaces, result, expected_mcast_off) + + sw_br.set_br_mcast_snooping(True) + result = tl.iperf_mc(sender, mcast_ifaces, group) + tl.mc_ipref_compare_result(mcast_ifaces, result, expected_mcast_on) + + for proc in s_procs: + proc.intr() + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if, m2_if, m3_if, m4_if, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + # Create a bridge + sw_ifaces = [sw_if1, sw_if2, sw_if3, sw_if4] + sw_br = sw.create_bridge(slaves=sw_ifaces, options={"vlan_filtering": 1}) + + m1_if.set_addresses(test_ip(1, 1)) + m2_if.set_addresses(test_ip(1, 2)) + m3_if.set_addresses(test_ip(1, 3)) + m4_if.set_addresses(test_ip(1, 4)) + sleep(15) + + tl = TestLib(ctl, aliases) + for iface in [m1_if, m2_if, m3_if, m4_if]: + iface.enable_multicast() + tl.check_cpu_traffic(sw_ifaces, test=False) + + test_mcast_onoff(tl, sw_br, m1_if, [], [m3_if, m2_if, m4_if], mcgrp(1)) + test_mcast_onoff(tl, sw_br, m1_if, [m2_if], [m3_if, m4_if], mcgrp(2)) + test_mcast_onoff(tl, sw_br, m1_if, [m2_if, m4_if], [m3_if], mcgrp(3)) + test_mcast_onoff(tl, sw_br, m3_if, [m1_if, m4_if], [m2_if], mcgrp(4)) + + for iface in [m1_if, m2_if, m3_if, m4_if]: + iface.disable_multicast() + tl.check_cpu_traffic(sw_ifaces) + +do_task(ctl, [ctl.get_host("machine1"), + ctl.get_host("machine2"), + ctl.get_host("switch")], + [ctl.get_host("machine1").get_interface("veth1"), + ctl.get_host("machine1").get_interface("veth3"), + ctl.get_host("machine2").get_interface("veth1"), + ctl.get_host("machine2").get_interface("veth3"), + ctl.get_host("switch").get_interface("if1"), + ctl.get_host("switch").get_interface("if2"), + ctl.get_host("switch").get_interface("if3"), + ctl.get_host("switch").get_interface("if4")], + ctl.get_aliases()) diff --git a/recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.xml b/recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.xml new file mode 100644 index 0000000..8e17b59 --- /dev/null +++ b/recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.xml @@ -0,0 +1,70 @@ +<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" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="B" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="D" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="switch"> + <interfaces> + <eth id="if1" label="A" /> + <eth id="if2" label="B" /> + <eth id="if3" label="C" /> + <eth id="if4" label="D" /> + </interfaces> + </host> + </network> + <task python="l2-022-bridge_mdb_mcast_disabled.py" /> +</lnstrecipe>
This test tests MC flood to ports that is configured statically to be mrouter, meaning that it should get all the MC traffic, regardless of join requests.
The test uses 4 ports: one that sends the data, one that send no join request and shouldn't get any traffic, one that sends some join requests and should get some of the traffic and a PUT (port under tests).
The test use 3 MC groups: - Unregistered one (no port sent join request to it). - A MC group that was registered to only by a port that is not the PUT. - A MC group that is registered to by the previous port and the PUT.
The test's algorithm is as follows: - Send the needed join requests. - Set the PUT to be mrouter (statically on) - send traffic from all of the MC groups. - Check that all of them were sent to the PUT. - Check that the other ports got the traffic according to the join requests - Set the PUT to not be mrouter (statically off) - Send traffic from all of the MC groups. - Check that all the ports (including the PUT) got the traffic according to the join requests - Check that all the traffic hadn't gone via slowpath
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com --- .../l2-023-bridge_mdb_mc_router_port_basic.py | 108 +++++++++++++++++++++ .../l2-023-bridge_mdb_mc_router_port_basic.xml | 70 +++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.py create mode 100644 recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.xml
diff --git a/recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.py b/recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.py new file mode 100644 index 0000000..562454e --- /dev/null +++ b/recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.py @@ -0,0 +1,108 @@ +""" +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__ = """ +nogahf@mellanox.com (Nogah Frankel) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep +import logging +from lnst.Common.Consts import MCAST_ROUTER_PORT + +def test_ip(major, minor): + return ["192.168.10%d.%d/24" % (major, minor), + "2002:%d::%d/64" % (major, minor)] + +def mcgrp(i): + return "239.255.1.%d" % i + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if, m2_if, m3_if, m4_if, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + # Create a bridge + sw_ports = [sw_if1, sw_if2, sw_if3, sw_if4] + sw_br = sw.create_bridge(slaves=sw_ports, options={"vlan_filtering": 1}) + + m1_if.set_addresses(test_ip(1, 1)) + m2_if.set_addresses(test_ip(1, 2)) + m3_if.set_addresses(test_ip(1, 3)) + m4_if.set_addresses(test_ip(1, 4)) + sleep(15) + + tl = TestLib(ctl, aliases) + for iface in [m1_if, m2_if, m3_if, m4_if]: + iface.enable_multicast() + + logging.info("%s join %s" % (m3_if.get_devname(), mcgrp(1))) + s_procs_1 = [tl.iperf_mc_listen(m3_if, mcgrp(1))] + logging.info("%s and %s join %s" % (m2_if.get_devname(), + m3_if.get_devname(), mcgrp(2))) + s_procs_2 = [tl.iperf_mc_listen(listener, mcgrp(2)) + for listener in [m2_if, m3_if]] + tl._ctl.wait(2) + + logging.info("set mrouter on") + mcast_iface = [m2_if, m3_if, m4_if] + sw_if2.set_mcast_router(MCAST_ROUTER_PORT.FIXED_ON) + + logging.info("check registered mid flood") + tl.check_cpu_traffic(sw_ports, test=False) + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(1)) + tl.mc_ipref_compare_result(mcast_iface, result, [True, True, False]) + tl.check_cpu_traffic(sw_ports) + + logging.info("check registered mid with mrouter flood") + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(2)) + tl.mc_ipref_compare_result(mcast_iface, result, [True, True, False]) + tl.check_cpu_traffic(sw_ports) + + logging.info("check unregistered mc flood") + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(3)) + tl.mc_ipref_compare_result(mcast_iface, result, [True, False, False]) + tl.check_cpu_traffic(sw_ports) + + logging.info("set mrouter off") + sw_if2.set_mcast_router(MCAST_ROUTER_PORT.FIXED_OFF) + tl._ctl.wait(2) + + logging.info("check registered mid flood") + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(1)) + tl.mc_ipref_compare_result(mcast_iface, result, [False, True, False]) + tl.check_cpu_traffic(sw_ports) + + logging.info("check registered mid with mrouter flood") + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(2)) + tl.mc_ipref_compare_result(mcast_iface, result, [True, True, False]) + tl.check_cpu_traffic(sw_ports) + + logging.info("check unregistered mc flood") + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(3)) + tl.mc_ipref_compare_result(mcast_iface, result, [False, False, False]) + tl.check_cpu_traffic(sw_ports) + + sw_if2.set_mcast_router(MCAST_ROUTER_PORT.LEARNING) + + for proc in s_procs_1 + s_procs_2: + proc.intr() + + for iface in mcast_iface: + iface.disable_multicast() + +do_task(ctl, [ctl.get_host("machine1"), + ctl.get_host("machine2"), + ctl.get_host("switch")], + [ctl.get_host("machine1").get_interface("veth1"), + ctl.get_host("machine1").get_interface("veth3"), + ctl.get_host("machine2").get_interface("veth1"), + ctl.get_host("machine2").get_interface("veth3"), + ctl.get_host("switch").get_interface("if1"), + ctl.get_host("switch").get_interface("if2"), + ctl.get_host("switch").get_interface("if3"), + ctl.get_host("switch").get_interface("if4")], + ctl.get_aliases()) diff --git a/recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.xml b/recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.xml new file mode 100644 index 0000000..f672eb7 --- /dev/null +++ b/recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.xml @@ -0,0 +1,70 @@ +<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" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="B" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="D" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="switch"> + <interfaces> + <eth id="if1" label="A" /> + <eth id="if2" label="B" /> + <eth id="if3" label="C" /> + <eth id="if4" label="D" /> + </interfaces> + </host> + </network> + <task python="l2-023-bridge_mdb_mc_router_port_basic.py" /> +</lnstrecipe>
Add a test that check that mrouter state id offloaded correctly for a port in mrouter learning state (and not just statically set by user). The test check 2 MC groups, one unregistered and one registered but not by the PUT (port under test).
The test's algorithm is as follows: - Send the needed join request. - Set all ports but the PUT to mrouter fixed off. Set the PUT to learning mrouter state. - Send MC traffic of both groups. - Check that it was received according to the join request. - Set the PUT's peer to be a MC querier. (This should make the bridge to learn that the PUT is mrouter.) - Send MC traffic of both groups. - check that PUT receives both of them - Check that it was received by the other ports according to the join request. - Check that all the traffic hadn't gone via slowpath
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com --- .../l2-024-bridge_mdb_mc_router_port_learning.py | 91 ++++++++++++++++++++++ .../l2-024-bridge_mdb_mc_router_port_learning.xml | 70 +++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.py create mode 100644 recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.xml
diff --git a/recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.py b/recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.py new file mode 100644 index 0000000..576528d --- /dev/null +++ b/recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.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__ = """ +nogahf@mellanox.com (Nogah Frankel) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep +import logging +from lnst.Common.Consts import MCAST_ROUTER_PORT + +def test_ip(major, minor): + return ["192.168.10%d.%d/24" % (major, minor), + "2002:%d::%d/64" % (major, minor)] + +def mcgrp(i): + return "239.255.1.%d" % i + +def do_task(ctl, hosts, ifaces, host_br, aliases): + m1, m2, sw = hosts + m1_if, m2_if, m3_if, m4_if, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + sw_ports = [sw_if1, sw_if2, sw_if3, sw_if4] + sw_br = sw.create_bridge(slaves=sw_ports, options={"vlan_filtering": 1}) + + m1_if.set_addresses(test_ip(1, 1)) + m2_if.set_addresses(test_ip(1, 2)) + m3_if.set_addresses(test_ip(1, 3)) + m4_if.set_addresses(test_ip(1, 4)) + + tl = TestLib(ctl, aliases) + mcast_iface = [m1_if, m3_if, m4_if] + m2_if.enable_multicast() + for iface in mcast_iface: + iface.enable_multicast() + for iface in sw_ports: + iface.set_mcast_router(MCAST_ROUTER_PORT.FIXED_OFF) + + sw_if1.set_mcast_router(MCAST_ROUTER_PORT.LEARNING) + sleep(15) + + s_procs = tl.iperf_mc_listen(m3_if, mcgrp(1)) + tl._ctl.wait(2) + + tl.check_cpu_traffic(sw_ports, test=False) + result = tl.iperf_mc(m2_if, mcast_iface, mcgrp(1)) + tl.mc_ipref_compare_result(mcast_iface, result, [False, True, False]) + tl.check_cpu_traffic(sw_ports) + + result = tl.iperf_mc(m2_if, mcast_iface, mcgrp(2)) + tl.mc_ipref_compare_result(mcast_iface, result, [False, False, False]) + tl.check_cpu_traffic(sw_ports) + + host_br.set_br_mcast_snooping() + host_br.set_br_mcast_querier(True) + tl._ctl.wait(30) + + result = tl.iperf_mc(m2_if, mcast_iface, mcgrp(1)) + tl.mc_ipref_compare_result(mcast_iface, result, [True, True, False]) + tl.check_cpu_traffic(sw_ports) + + result = tl.iperf_mc(m2_if, mcast_iface, mcgrp(2)) + tl.mc_ipref_compare_result(mcast_iface, result, [True, False, False]) + tl.check_cpu_traffic(sw_ports) + + for iface in sw_ports: + iface.set_mcast_router(MCAST_ROUTER_PORT.LEARNING) + s_procs.intr() + + for iface in mcast_iface: + iface.disable_multicast() + m2_if.disable_multicast() + +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("machine1").get_interface("veth3"), + ctl.get_host("machine2").get_interface("veth1"), + ctl.get_host("machine2").get_interface("veth3"), + ctl.get_host("switch").get_interface("if1"), + ctl.get_host("switch").get_interface("if2"), + ctl.get_host("switch").get_interface("if3"), + ctl.get_host("switch").get_interface("if4")], + ctl.get_host("machine1").get_interface("brif1"), + ctl.get_aliases()) diff --git a/recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.xml b/recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.xml new file mode 100644 index 0000000..f49c977 --- /dev/null +++ b/recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.xml @@ -0,0 +1,70 @@ +<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" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="B" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="D" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="switch"> + <interfaces> + <eth id="if1" label="A" /> + <eth id="if2" label="B" /> + <eth id="if3" label="C" /> + <eth id="if4" label="D" /> + </interfaces> + </host> + </network> + <task python="l2-024-bridge_mdb_mc_router_port_learning.py" /> +</lnstrecipe>
This recipe tests mrouter with many flood configurations. Its algorithm is as follows: - Configure a bridge multicast setup - Configure some mc_router ports - Make several ports join a mc group and send traffic to it - Validate that traffic is received by both joined ports and mc_router ports - Remove the mc_router_ports and send traffic to that group - Validate that traffic is received by only by the joined ports - Add some mc_router ports again and send traffic to the group - Validate that traffic is received by both joined ports and mc_router ports - Check that all the traffic hadn't gone via slowpath
Signed-off-by: Yotam Gigi yotamg@mellanox.com Signed-off-by: Nogah Frankel nogahf@mellanox.com --- .../l2-025-bridge_mdb_flood_with_mc_router.py | 142 +++++++++++++++++++++ .../l2-025-bridge_mdb_flood_with_mc_router.xml | 70 ++++++++++ 2 files changed, 212 insertions(+) create mode 100644 recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.py create mode 100644 recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.xml
diff --git a/recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.py b/recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.py new file mode 100644 index 0000000..698705d --- /dev/null +++ b/recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.py @@ -0,0 +1,142 @@ +""" +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__ = """ +yotamg@mellanox.com (Yotam Gigi) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep +from lnst.Common.Consts import MCAST_ROUTER_PORT + +def test_ip(major, minor): + return ["192.168.10%d.%d/24" % (major, minor), + "2002:%d::%d/64" % (major, minor)] + +def mcgrp(i): + return "239.255.1.%d" % i + +def set_peer_mc_router(dev_map, dev, value): + sw_dev = dev_map[dev] + sw_dev.set_mcast_router(value) + sw = sw_dev.get_host() + +def test_mrouter(tl, dev_map, sender, listeners, bridged, mc_routers, group): + mcast_ifaces = listeners + bridged + + expected_no_mcr = [True for l in listeners] + [False for l in bridged] + expected = [True for l in listeners] + [l in mc_routers for l in bridged] + + s_procs = [tl.iperf_mc_listen(listener, group) for listener in listeners] + tl._ctl.wait(2) + + result = tl.iperf_mc(sender, mcast_ifaces, group) + tl.mc_ipref_compare_result(mcast_ifaces, result, expected_no_mcr) + + for mcr in mc_routers: + set_peer_mc_router(dev_map, mcr, MCAST_ROUTER_PORT.FIXED_ON) + + result = tl.iperf_mc(sender, mcast_ifaces, group) + tl.mc_ipref_compare_result(mcast_ifaces, result, expected) + + for mcr in mc_routers: + set_peer_mc_router(dev_map, mcr, MCAST_ROUTER_PORT.LEARNING) + + result = tl.iperf_mc(sender, mcast_ifaces, group) + tl.mc_ipref_compare_result(mcast_ifaces, result, expected_no_mcr) + + for mcr in mc_routers: + set_peer_mc_router(dev_map, mcr, MCAST_ROUTER_PORT.FIXED_ON) + + result = tl.iperf_mc(sender, mcast_ifaces, group) + tl.mc_ipref_compare_result(mcast_ifaces, result, expected) + + for proc in s_procs: + proc.intr() + + for mcr in mc_routers: + set_peer_mc_router(dev_map, mcr, MCAST_ROUTER_PORT.LEARNING) + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if, m2_if, m3_if, m4_if, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + dev_map = { m1_if : sw_if1, m2_if : sw_if2, m3_if : sw_if3, m4_if : sw_if4 } + + # Create a bridge + sw_ifaces = [sw_if1, sw_if2, sw_if3, sw_if4] + sw_br = sw.create_bridge(slaves=sw_ifaces, options={"vlan_filtering": 1}) + + m1_if.set_addresses(test_ip(1, 1)) + m2_if.set_addresses(test_ip(1, 2)) + m3_if.set_addresses(test_ip(1, 3)) + m4_if.set_addresses(test_ip(1, 4)) + sleep(15) + + tl = TestLib(ctl, aliases) + + for iface in [m1_if, m2_if, m3_if, m4_if]: + iface.enable_multicast() + + tl.check_cpu_traffic(sw_ifaces, test=False) + test_mrouter(tl, dev_map, \ + sender = m1_if, \ + listeners = [], \ + bridged = [m3_if, m2_if, m4_if], \ + mc_routers = [m4_if], \ + group = mcgrp(1)) + + test_mrouter(tl, dev_map, \ + sender = m1_if, \ + listeners = [m2_if], \ + bridged = [m4_if, m3_if], \ + mc_routers = [m3_if], \ + group = mcgrp(2)) + + test_mrouter(tl, dev_map, \ + sender = m1_if, \ + listeners = [m2_if, m4_if], \ + bridged = [m3_if], \ + mc_routers = [m3_if], \ + group = mcgrp(3)) + + test_mrouter(tl, dev_map, \ + sender = m1_if, \ + listeners = [m2_if], \ + bridged = [m3_if, m4_if], \ + mc_routers = [m3_if, m4_if], \ + group = mcgrp(4)) + + test_mrouter(tl, dev_map, \ + sender = m1_if, \ + listeners = [m2_if, m4_if], \ + bridged = [m3_if], \ + mc_routers = [m2_if], \ + group = mcgrp(5)) + + test_mrouter(tl, dev_map, \ + sender = m1_if, \ + listeners = [m2_if, m4_if], \ + bridged = [m3_if], \ + mc_routers = [m2_if, m3_if], \ + group = mcgrp(6)) + + tl.check_cpu_traffic(sw_ifaces) + for iface in [m1_if, m2_if, m3_if, m4_if]: + iface.disable_multicast() + +do_task(ctl, [ctl.get_host("machine1"), + ctl.get_host("machine2"), + ctl.get_host("switch")], + [ctl.get_host("machine1").get_interface("veth1"), + ctl.get_host("machine1").get_interface("veth3"), + ctl.get_host("machine2").get_interface("veth1"), + ctl.get_host("machine2").get_interface("veth3"), + ctl.get_host("switch").get_interface("if1"), + ctl.get_host("switch").get_interface("if2"), + ctl.get_host("switch").get_interface("if3"), + ctl.get_host("switch").get_interface("if4")], + ctl.get_aliases()) diff --git a/recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.xml b/recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.xml new file mode 100644 index 0000000..22aa966 --- /dev/null +++ b/recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.xml @@ -0,0 +1,70 @@ +<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" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="B" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="D" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="switch"> + <interfaces> + <eth id="if1" label="A" /> + <eth id="if2" label="B" /> + <eth id="if3" label="C" /> + <eth id="if4" label="D" /> + </interfaces> + </host> + </network> + <task python="l2-025-bridge_mdb_flood_with_mc_router.py" /> +</lnstrecipe>
This recipe tests unregistered MC traffic that should be flooded in the following way: * When MC is enabled it should be sent to all the mrouter ports * When MC is disabled it should be sent to all the ports that marked with MC flood flag (default on)
The test's algorithm is as follows: - Set MC on - Set one port as mrouter (statically on) and as MC flood off. - Check that unregistered MC traffic is received by this port and no other port. - Set MC off - Check that unregistered MC traffic if not received by this port but is received by the other ports. - Change this port to not be mrouter (statically off) and to flood MC packets. Change another port to be MC flood off and mrouter on. - Check unregistered MC traffic is not received by the new port but is received by the other ports. - Set MC on - Check that unregistered MC traffic is received only by the new port.
Signed-off-by: Nogah Frankel nogahf@mellanox.com Reviewed-by: Yotam Gigi yotamg@mellanox.com --- recipes/switchdev/l2-026-bridge_mdb_unreg_flood.py | 92 ++++++++++++++++++++++ .../switchdev/l2-026-bridge_mdb_unreg_flood.xml | 70 ++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 recipes/switchdev/l2-026-bridge_mdb_unreg_flood.py create mode 100644 recipes/switchdev/l2-026-bridge_mdb_unreg_flood.xml
diff --git a/recipes/switchdev/l2-026-bridge_mdb_unreg_flood.py b/recipes/switchdev/l2-026-bridge_mdb_unreg_flood.py new file mode 100644 index 0000000..bdb8b1c --- /dev/null +++ b/recipes/switchdev/l2-026-bridge_mdb_unreg_flood.py @@ -0,0 +1,92 @@ +""" +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__ = """ +nogahf@mellanox.com (Nogah Frankel) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep +import logging +from lnst.Common.Consts import MCAST_ROUTER_PORT + +def test_ip(major, minor): + return ["192.168.10%d.%d/24" % (major, minor), + "2002:%d::%d/64" % (major, minor)] + +def mcgrp(i): + return "239.255.1.%d" % i + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if, m2_if, m3_if, m4_if, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + # Create a bridge + sw_ports = [sw_if1, sw_if2, sw_if3, sw_if4] + sw_br = sw.create_bridge(slaves = sw_ports, options={"vlan_filtering": 1}) + + m1_if.set_addresses(test_ip(1, 1)) + m2_if.set_addresses(test_ip(1, 2)) + m3_if.set_addresses(test_ip(1, 3)) + m4_if.set_addresses(test_ip(1, 4)) + sleep(15) + + tl = TestLib(ctl, aliases) + for iface in [m1_if, m2_if, m3_if, m4_if]: + iface.enable_multicast() + + tl._ctl.wait(2) + tl.check_cpu_traffic(sw_ports, test=False) + + mcast_iface = [m2_if, m3_if, m4_if] + sw_if2.set_mcast_router(MCAST_ROUTER_PORT.FIXED_ON) + sw_if2.set_mcast_flood(False) + + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(1)) + tl.mc_ipref_compare_result(mcast_iface, result, [True, False, False]) + tl.check_cpu_traffic(sw_ports) + + sw_br.set_br_mcast_snooping(False) + tl._ctl.wait(2) + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(1)) + tl.mc_ipref_compare_result(mcast_iface, result, [False, True, True]) + tl.check_cpu_traffic(sw_ports) + + sw_if2.set_mcast_flood(True) + sw_if2.set_mcast_router(MCAST_ROUTER_PORT.FIXED_OFF) + sw_if3.set_mcast_router(MCAST_ROUTER_PORT.FIXED_ON) + sw_if3.set_mcast_flood(False) + + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(1)) + tl.mc_ipref_compare_result(mcast_iface, result, [True, False, True]) + tl.check_cpu_traffic(sw_ports) + + sw_br.set_br_mcast_snooping() + tl._ctl.wait(2) + + result = tl.iperf_mc(m1_if, mcast_iface, mcgrp(1)) + tl.mc_ipref_compare_result(mcast_iface, result, [False, True, False]) + tl.check_cpu_traffic(sw_ports) + + sw_if2.set_mcast_router(MCAST_ROUTER_PORT.LEARNING) + sw_if2.set_mcast_router(MCAST_ROUTER_PORT.LEARNING) + sw_if3.set_mcast_flood(True) + for iface in [m1_if, m2_if, m3_if, m4_if]: + iface.disable_multicast() + +do_task(ctl, [ctl.get_host("machine1"), + ctl.get_host("machine2"), + ctl.get_host("switch")], + [ctl.get_host("machine1").get_interface("veth1"), + ctl.get_host("machine1").get_interface("veth3"), + ctl.get_host("machine2").get_interface("veth1"), + ctl.get_host("machine2").get_interface("veth3"), + ctl.get_host("switch").get_interface("if1"), + ctl.get_host("switch").get_interface("if2"), + ctl.get_host("switch").get_interface("if3"), + ctl.get_host("switch").get_interface("if4")], + ctl.get_aliases()) diff --git a/recipes/switchdev/l2-026-bridge_mdb_unreg_flood.xml b/recipes/switchdev/l2-026-bridge_mdb_unreg_flood.xml new file mode 100644 index 0000000..3a29330 --- /dev/null +++ b/recipes/switchdev/l2-026-bridge_mdb_unreg_flood.xml @@ -0,0 +1,70 @@ +<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" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="B" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <veth_pair> + <veth id="veth0"/> + <veth id="veth1" netns="nsif1"> + </veth> + </veth_pair> + <bridge id="brif1"> + <slaves> + <slave id="if1"/> + <slave id="veth0"/> + </slaves> + </bridge> + <eth id="if2" label="D" /> + <veth_pair> + <veth id="veth2"/> + <veth id="veth3" netns="nsif2"> + </veth> + </veth_pair> + <bridge id="brif2"> + <slaves> + <slave id="if2"/> + <slave id="veth2"/> + </slaves> + </bridge> + </interfaces> + </host> + <host id="switch"> + <interfaces> + <eth id="if1" label="A" /> + <eth id="if2" label="B" /> + <eth id="if3" label="C" /> + <eth id="if4" label="D" /> + </interfaces> + </host> + </network> + <task python="l2-026-bridge_mdb_unreg_flood.py" /> +</lnstrecipe>
On Mon, Sep 25, 2017 at 04:40:22PM +0300, Nogah Frankel wrote:
This patchset adds some basic test for L2 MC behaviours. The first three patches add a MC related commands to LNST. The 4th patch adds the ability to count CPU traffic, so it will be possible to check if the traffic were really offloaded and hadn't gone via slowpath. Patches 5 & 6 update the current MDB test to be more generic and to check that the traffic is offloaded. Patch 7 adds a test to check that the MDB is ignored when MC is disabled. Patches 8-10 add tests for mrouter bridge config option (as in IGMP configuration, not to be confused with any L3 property). Patch 11 adds a test for unregistered MC packets.
This patchset does not address:
- LAG in MC.
- static MDB,
Nogah Frankel (11): common: add a consts file for mrouter port related consts Interface: add mcast flood and mrouter set functions Bridge: add set mcast bridge functions Interface: Add cpu ifstat function recipes: switchdev: TestLib: Change iperf_mc to be more generic recipes: switchdev: TestLib: Check whether packets goes in slowpath recipes: switchdev: Add the mdb mcast disabled test recipes: switchdev: Add basic mrouter test recipes: switchdev: Add mrouter learning test recipes: switchdev: Add a test for many floods with mrouters recipes: switchdev: Add a test for unregistered MC traffic
lnst/Common/Consts.py | 16 +++ lnst/Controller/Machine.py | 20 +++ lnst/Controller/Task.py | 15 +++ lnst/Slave/BridgeTool.py | 10 ++ lnst/Slave/InterfaceManager.py | 42 ++++++ lnst/Slave/NetTestSlave.py | 43 +++++++ recipes/switchdev/TestLib.py | 94 +++++++------- recipes/switchdev/l2-020-bridge_mdb.py | 38 ++++-- .../switchdev/l2-022-bridge_mdb_mcast_disabled.py | 85 ++++++++++++ .../switchdev/l2-022-bridge_mdb_mcast_disabled.xml | 70 ++++++++++ .../l2-023-bridge_mdb_mc_router_port_basic.py | 108 ++++++++++++++++ .../l2-023-bridge_mdb_mc_router_port_basic.xml | 70 ++++++++++ .../l2-024-bridge_mdb_mc_router_port_learning.py | 91 +++++++++++++ .../l2-024-bridge_mdb_mc_router_port_learning.xml | 70 ++++++++++ .../l2-025-bridge_mdb_flood_with_mc_router.py | 142 +++++++++++++++++++++ .../l2-025-bridge_mdb_flood_with_mc_router.xml | 70 ++++++++++ recipes/switchdev/l2-026-bridge_mdb_unreg_flood.py | 92 +++++++++++++ .../switchdev/l2-026-bridge_mdb_unreg_flood.xml | 70 ++++++++++ 18 files changed, 1093 insertions(+), 53 deletions(-) create mode 100644 lnst/Common/Consts.py create mode 100644 recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.py create mode 100644 recipes/switchdev/l2-022-bridge_mdb_mcast_disabled.xml create mode 100644 recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.py create mode 100644 recipes/switchdev/l2-023-bridge_mdb_mc_router_port_basic.xml create mode 100644 recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.py create mode 100644 recipes/switchdev/l2-024-bridge_mdb_mc_router_port_learning.xml create mode 100644 recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.py create mode 100644 recipes/switchdev/l2-025-bridge_mdb_flood_with_mc_router.xml create mode 100644 recipes/switchdev/l2-026-bridge_mdb_unreg_flood.py create mode 100644 recipes/switchdev/l2-026-bridge_mdb_unreg_flood.xml
-- 2.4.3 _______________________________________________ LNST-developers mailing list -- lnst-developers@lists.fedorahosted.org To unsubscribe send an email to lnst-developers-leave@lists.fedorahosted.org
patchset pushed, thanks -Ondrej
lnst-developers@lists.fedorahosted.org