From: Jiri Pirko jiri@mellanox.com
This patch introduces initial recipe set for testing basic and l2 functionality of switchdev offloaded switches.
Signed-off-by: Ido Schimmel idosch@mellanox.com Signed-off-by: Jiri Pirko jiri@mellanox.com --- recipes/switchdev/TestLib.py | 202 +++++++++++++++++++++ recipes/switchdev/basic-001-links.py | 65 +++++++ recipes/switchdev/basic-001-links.xml | 23 +++ recipes/switchdev/basic-004-slowpath.py | 33 ++++ recipes/switchdev/basic-004-slowpath.xml | 17 ++ recipes/switchdev/basic-005-slowpath-exhaustive.py | 36 ++++ .../switchdev/basic-005-slowpath-exhaustive.xml | 17 ++ recipes/switchdev/basic-006-slowpath-vlan.py | 35 ++++ recipes/switchdev/basic-006-slowpath-vlan.xml | 17 ++ .../basic-007-slowpath-vlan-exhaustive.py | 40 ++++ .../basic-007-slowpath-vlan-exhaustive.xml | 17 ++ recipes/switchdev/default_aliases.xml | 6 + recipes/switchdev/l2-000-minimal.py | 36 ++++ recipes/switchdev/l2-000-minimal.xml | 24 +++ recipes/switchdev/l2-001-bridge.py | 38 ++++ recipes/switchdev/l2-001-bridge.xml | 22 +++ recipes/switchdev/l2-002-bridge_fdb.py | 142 +++++++++++++++ recipes/switchdev/l2-002-bridge_fdb.xml | 22 +++ recipes/switchdev/l2-003-bridge_stp.py | 93 ++++++++++ recipes/switchdev/l2-003-bridge_stp.xml | 24 +++ recipes/switchdev/l2-004-bridge_bond.py | 48 +++++ recipes/switchdev/l2-004-bridge_bond.xml | 26 +++ recipes/switchdev/l2-005-bridge_bond_failover.py | 64 +++++++ recipes/switchdev/l2-005-bridge_bond_failover.xml | 26 +++ recipes/switchdev/l2-006-bridge_team.py | 54 ++++++ recipes/switchdev/l2-006-bridge_team.xml | 26 +++ recipes/switchdev/l2-007-bridge_team_failover.py | 70 +++++++ recipes/switchdev/l2-007-bridge_team_failover.xml | 26 +++ recipes/switchdev/l2-008-bridge_vlan1q_sanity.py | 86 +++++++++ recipes/switchdev/l2-008-bridge_vlan1q_sanity.xml | 22 +++ recipes/switchdev/l2-009-bridge_vlan1q.py | 70 +++++++ recipes/switchdev/l2-009-bridge_vlan1q.xml | 22 +++ recipes/switchdev/l2-010-bridge_vlan1d_sanity.py | 60 ++++++ recipes/switchdev/l2-010-bridge_vlan1d_sanity.xml | 22 +++ recipes/switchdev/l2-011-bridge_vlan1d.py | 66 +++++++ recipes/switchdev/l2-011-bridge_vlan1d.xml | 22 +++ .../switchdev/l2-012-bridge_bond_vlan1d_sanity.py | 68 +++++++ .../switchdev/l2-012-bridge_bond_vlan1d_sanity.xml | 26 +++ recipes/switchdev/l2-013-bridge_bond_vlan1d.py | 74 ++++++++ recipes/switchdev/l2-013-bridge_bond_vlan1d.xml | 26 +++ .../switchdev/l2-014-bridge_team_vlan1d_sanity.py | 68 +++++++ .../switchdev/l2-014-bridge_team_vlan1d_sanity.xml | 26 +++ recipes/switchdev/l2-015-bridge_team_vlan1d.py | 74 ++++++++ recipes/switchdev/l2-015-bridge_team_vlan1d.xml | 27 +++ recipes/switchdev/l2-017-bridge_fdb_vlan1d.py | 144 +++++++++++++++ recipes/switchdev/l2-017-bridge_fdb_vlan1d.xml | 22 +++ recipes/switchdev/l2-018-bridge_fdb_team.py | 150 +++++++++++++++ recipes/switchdev/l2-018-bridge_fdb_team.xml | 26 +++ recipes/switchdev/l2-019-bridge_fdb_team_vlan1d.py | 157 ++++++++++++++++ .../switchdev/l2-019-bridge_fdb_team_vlan1d.xml | 26 +++ 50 files changed, 2533 insertions(+) create mode 100644 recipes/switchdev/TestLib.py create mode 100644 recipes/switchdev/basic-001-links.py create mode 100644 recipes/switchdev/basic-001-links.xml create mode 100644 recipes/switchdev/basic-004-slowpath.py create mode 100644 recipes/switchdev/basic-004-slowpath.xml create mode 100644 recipes/switchdev/basic-005-slowpath-exhaustive.py create mode 100644 recipes/switchdev/basic-005-slowpath-exhaustive.xml create mode 100644 recipes/switchdev/basic-006-slowpath-vlan.py create mode 100644 recipes/switchdev/basic-006-slowpath-vlan.xml create mode 100644 recipes/switchdev/basic-007-slowpath-vlan-exhaustive.py create mode 100644 recipes/switchdev/basic-007-slowpath-vlan-exhaustive.xml create mode 100644 recipes/switchdev/default_aliases.xml create mode 100644 recipes/switchdev/l2-000-minimal.py create mode 100644 recipes/switchdev/l2-000-minimal.xml create mode 100644 recipes/switchdev/l2-001-bridge.py create mode 100644 recipes/switchdev/l2-001-bridge.xml create mode 100644 recipes/switchdev/l2-002-bridge_fdb.py create mode 100644 recipes/switchdev/l2-002-bridge_fdb.xml create mode 100644 recipes/switchdev/l2-003-bridge_stp.py create mode 100644 recipes/switchdev/l2-003-bridge_stp.xml create mode 100644 recipes/switchdev/l2-004-bridge_bond.py create mode 100644 recipes/switchdev/l2-004-bridge_bond.xml create mode 100644 recipes/switchdev/l2-005-bridge_bond_failover.py create mode 100644 recipes/switchdev/l2-005-bridge_bond_failover.xml create mode 100644 recipes/switchdev/l2-006-bridge_team.py create mode 100644 recipes/switchdev/l2-006-bridge_team.xml create mode 100644 recipes/switchdev/l2-007-bridge_team_failover.py create mode 100644 recipes/switchdev/l2-007-bridge_team_failover.xml create mode 100644 recipes/switchdev/l2-008-bridge_vlan1q_sanity.py create mode 100644 recipes/switchdev/l2-008-bridge_vlan1q_sanity.xml create mode 100644 recipes/switchdev/l2-009-bridge_vlan1q.py create mode 100644 recipes/switchdev/l2-009-bridge_vlan1q.xml create mode 100644 recipes/switchdev/l2-010-bridge_vlan1d_sanity.py create mode 100644 recipes/switchdev/l2-010-bridge_vlan1d_sanity.xml create mode 100644 recipes/switchdev/l2-011-bridge_vlan1d.py create mode 100644 recipes/switchdev/l2-011-bridge_vlan1d.xml create mode 100644 recipes/switchdev/l2-012-bridge_bond_vlan1d_sanity.py create mode 100644 recipes/switchdev/l2-012-bridge_bond_vlan1d_sanity.xml create mode 100644 recipes/switchdev/l2-013-bridge_bond_vlan1d.py create mode 100644 recipes/switchdev/l2-013-bridge_bond_vlan1d.xml create mode 100644 recipes/switchdev/l2-014-bridge_team_vlan1d_sanity.py create mode 100644 recipes/switchdev/l2-014-bridge_team_vlan1d_sanity.xml create mode 100644 recipes/switchdev/l2-015-bridge_team_vlan1d.py create mode 100644 recipes/switchdev/l2-015-bridge_team_vlan1d.xml create mode 100644 recipes/switchdev/l2-017-bridge_fdb_vlan1d.py create mode 100644 recipes/switchdev/l2-017-bridge_fdb_vlan1d.xml create mode 100644 recipes/switchdev/l2-018-bridge_fdb_team.py create mode 100644 recipes/switchdev/l2-018-bridge_fdb_team.xml create mode 100644 recipes/switchdev/l2-019-bridge_fdb_team_vlan1d.py create mode 100644 recipes/switchdev/l2-019-bridge_fdb_team_vlan1d.xml
diff --git a/recipes/switchdev/TestLib.py b/recipes/switchdev/TestLib.py new file mode 100644 index 0000000..1159a30 --- /dev/null +++ b/recipes/switchdev/TestLib.py @@ -0,0 +1,202 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +idosch@mellanox.com (Ido Schimmel) +""" + +from time import sleep + +class TestLib: + def __init__(self, ctl, aliases): + self._ctl = ctl + self._ipv = aliases["ipv"] + self._mtu = int(aliases["mtu"]) + if "netperf_duration" in aliases: + self._netperf_duration = int(aliases["netperf_duration"]) + if "netperf_num_parallel" in aliases: + self._netperf_num_parallel = int(aliases["netperf_num_parallel"]) + + def _generate_default_desc(self, if1, if2): + return "from %s->%s to %s->%s" % (if1.get_host().get_id(), if1.get_id(), + if2.get_host().get_id(), if2.get_id()) + + def linkneg(self, if1, if2, state, speed=0, timeout=5, desc=None): + if not desc: + desc = self._generate_default_desc(if1, if2) + + m2 = if2.get_host() + m2.sync_resources(modules=["LinkNeg"]) + + linkneg_mod = self._ctl.get_module("LinkNeg", + options={ + "iface": if2.get_devname(), + "state": state, + "speed": speed, + "timeout": timeout}) + + if speed: + # Make sure the link at the other end advertises all of + # its supported speeds. + if2.set_autoneg() + sleep(3) + + # Setting the speed causes the link to first go down, so make + # sure LinkNeg will only get the following up event by sleeping + # for one second. + if1.set_speed(speed) + sleep(1) + elif state: + if1.set_link_up() + else: + if1.set_link_down() + + m2.run(linkneg_mod, desc=desc) + + def ping_simple(self, if1, if2, fail_expected=False, desc=None): + if not desc: + desc = self._generate_default_desc(if1, if2) + + if1.set_mtu(self._mtu) + if2.set_mtu(self._mtu) + + m1 = if1.get_host() + m1.sync_resources(modules=["Icmp6Ping", "IcmpPing"]) + + ping_mod = self._ctl.get_module("IcmpPing", + options={ + "addr": if2.get_ip(0), + "count": 100, + "interval": 0.2, + "iface" : if1.get_devname(), + "limit_rate": 90}) + + ping_mod6 = self._ctl.get_module("Icmp6Ping", + options={ + "addr": if2.get_ip(1), + "count": 100, + "interval": 0.2, + "iface" : if1.get_ip(1), + "limit_rate": 90}) + + if self._ipv in [ 'ipv6', 'both' ]: + m1.run(ping_mod6, fail_expected=fail_expected, desc=desc) + + if self._ipv in [ 'ipv4', 'both' ]: + m1.run(ping_mod, fail_expected=fail_expected, desc=desc) + + def _get_netperf_srv_mod(self, if1, is_ipv6): + if is_ipv6: + addr_index = 1 + else: + addr_index = 0 + modules_options = { + "role" : "server", + "bind" : if1.get_ip(addr_index) + } + if is_ipv6: + modules_options["netperf_opts"] = "-6" + return self._ctl.get_module("Netperf", options = modules_options) + + def _get_netperf_cli_mod(self, if1, if2, testname, + duration, num_parallel, is_ipv6): + if is_ipv6: + ipv6_str = " -6" + addr_index = 1 + else: + ipv6_str = "" + addr_index = 0 + modules_options = { + "role" : "client", + "netperf_server" : if1.get_ip(addr_index), + "duration" : duration, + "num_parallel" : num_parallel, + "testname" : testname, + "netperf_opts" : "-L %s%s" % (if2.get_ip(addr_index), ipv6_str), + } + return self._ctl.get_module("Netperf", options = modules_options) + + def _run_netperf(self, if1, if2, testname, is_ipv6, desc): + if not desc: + desc = self._generate_default_desc(if1, if2) + + m1 = if1.get_host() + m2 = if2.get_host() + + m1.sync_resources(modules=["Netperf"]) + m2.sync_resources(modules=["Netperf"]) + + duration = self._netperf_duration + num_parallel = self._netperf_num_parallel + + server_proc = m1.run(self._get_netperf_srv_mod(if1, is_ipv6), bg=True) + self._ctl.wait(2) + netperf_cli_mod = self._get_netperf_cli_mod(if1, if2, testname, + duration, num_parallel, + is_ipv6) + m2.run(netperf_cli_mod, timeout=duration + 10, desc=desc) + server_proc.intr() + + def _netperf(self, if1, if2, testname, desc): + if1.set_mtu(self._mtu) + if2.set_mtu(self._mtu) + + if self._ipv in [ 'ipv4', 'both' ]: + self._run_netperf(if1, if2, testname, False, desc) + + if self._ipv in [ 'ipv6', 'both' ]: + self._run_netperf(if1, if2, testname, True, desc) + + def netperf_tcp(self, if1, if2, desc=None): + self._netperf(if1, if2, "TCP_STREAM", desc) + + def netperf_udp(self, if1, if2, desc=None): + self._netperf(if1, if2, "UDP_STREAM", desc) + + def pktgen(self, if1, if2, pkt_size, desc=None): + if1.set_mtu(self._mtu) + m1 = if1.get_host() + m1.sync_resources(modules=["PktgenTx"]) + + pktgen_option = ["count 10000", "clone_skb 0", "delay 0"] + pktgen_option.append("pkt_size %s" % pkt_size) + pktgen_option.append("dst_mac %s" % if2.get_hwaddr()) + pktgen_option.append("dst %s" % if2.get_ip(0)) + pktgen_mod = self._ctl.get_module("PktgenTx", + options={ + "netdev_name": if1.get_devname(), + "pktgen_option": pktgen_option}) + + m1.run(pktgen_mod, desc=desc) + + def custom(self, m1, desc, err_msg=None): + m1.sync_resources(modules=["Custom"]) + options = {} + if err_msg: + options["fail"] = "yes" + options["msg"] = err_msg + custom_mod = self._ctl.get_module("Custom", options=options) + m1.run(custom_mod, desc=desc) + + def check_fdb(self, iface, hwaddr, vlan_id, rec_type, find=True): + fdb_table = iface.get_br_fdbs() + + rec = "offload" if rec_type == "software" else "self" + found = False + for fdb in fdb_table: + if (fdb["hwaddr"] == str(hwaddr) and fdb["vlan_id"] == vlan_id and + fdb[rec]): + found = True + + if found and not find: + err_msg = "found %s record when shouldn't" % rec_type + elif find and not found: + err_msg = "didn't find %s record when should've" % rec_type + else: + err_msg = "" + + self.custom(iface.get_host(), "fdb test", err_msg) diff --git a/recipes/switchdev/basic-001-links.py b/recipes/switchdev/basic-001-links.py new file mode 100644 index 0000000..998c986 --- /dev/null +++ b/recipes/switchdev/basic-001-links.py @@ -0,0 +1,65 @@ +""" +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@mellanox.com (Ido Schimmel) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def linkneg(tl, if1, if2): + if1_drv = str(if1.get_driver()) + if2_drv = str(if2.get_driver()) + + # The mlx5_core upstream driver is currently buggy and does not support + # link negotiation. Patches were sent to the NIC team. + if 'mlx5' in if1_drv or 'mlx5' in if2_drv: + return + + if 'mlx4' in if1_drv or 'mlx4' in if2_drv: + speeds = [10000, 40000] + else: + speeds = [10000, 40000, 100000] + + for speed in speeds: + tl.linkneg(if1, if2, True, speed=speed, timeout=10) + tl.ping_simple(if1, if2) + +def do_task(ctl, hosts, ifaces, aliases): + m1, sw = hosts + m1_if1, m1_if2, m1_if3, m1_if4, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + m1_if1.reset(ip=["192.168.101.10/24", "2002::1/64"]) + m1_if2.reset(ip=["192.168.102.10/24", "2003::1/64"]) + m1_if3.reset(ip=["192.168.103.10/24", "2004::1/64"]) + m1_if4.reset(ip=["192.168.104.10/24", "2005::1/64"]) + sw_if1.reset(ip=["192.168.101.11/24", "2002::2/64"]) + sw_if2.reset(ip=["192.168.102.11/24", "2003::2/64"]) + sw_if3.reset(ip=["192.168.103.11/24", "2004::2/64"]) + sw_if4.reset(ip=["192.168.104.11/24", "2005::2/64"]) + + sleep(10) + + tl = TestLib(ctl, aliases) + + for (if1, if2) in [(sw_if1, m1_if1), (sw_if2, m1_if2), (sw_if3, m1_if3), + (sw_if4, m1_if4)]: + linkneg(tl, if1, if2) + linkneg(tl, if2, if1) + +do_task(ctl, [ctl.get_host("machine1"), + ctl.get_host("switch")], + [ctl.get_host("machine1").get_interface("if1"), + ctl.get_host("machine1").get_interface("if2"), + ctl.get_host("machine1").get_interface("if3"), + ctl.get_host("machine1").get_interface("if4"), + 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/basic-001-links.xml b/recipes/switchdev/basic-001-links.xml new file mode 100644 index 0000000..1663299 --- /dev/null +++ b/recipes/switchdev/basic-001-links.xml @@ -0,0 +1,23 @@ +<lnstrecipe xmlns:xi="http://www.w3.org/2003/XInclude"> + <xi:include href="default_aliases.xml" /> + <network> + <host id="machine1"> + <params/> + <interfaces> + <eth id="if1" label="A" /> + <eth id="if2" label="B" /> + <eth id="if3" label="C" /> + <eth id="if4" label="D" /> + </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="basic-001-links.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/basic-004-slowpath.py b/recipes/switchdev/basic-004-slowpath.py new file mode 100644 index 0000000..2408500 --- /dev/null +++ b/recipes/switchdev/basic-004-slowpath.py @@ -0,0 +1,33 @@ +""" +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@mellanox.com (Ido Schimmel) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def do_task(ctl, hosts, ifaces, aliases): + m1, sw = hosts + m1_if1, sw_if1 = ifaces + + m1_if1.reset(ip=["192.168.101.10/24", "2002::1/64"]) + sw_if1.reset(ip=["192.168.101.11/24", "2002::2/64"]) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_if1, sw_if1) + tl.netperf_tcp(m1_if1, sw_if1) + tl.netperf_udp(m1_if1, sw_if1) + +do_task(ctl, [ctl.get_host("machine1"), + ctl.get_host("switch")], + [ctl.get_host("machine1").get_interface("if1"), + ctl.get_host("switch").get_interface("if1")], + ctl.get_aliases()) diff --git a/recipes/switchdev/basic-004-slowpath.xml b/recipes/switchdev/basic-004-slowpath.xml new file mode 100644 index 0000000..a0f3587 --- /dev/null +++ b/recipes/switchdev/basic-004-slowpath.xml @@ -0,0 +1,17 @@ +<lnstrecipe xmlns:xi="http://www.w3.org/2003/XInclude"> + <xi:include href="default_aliases.xml" /> + <network> + <host id="machine1"> + <params/> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + <host id="switch"> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + </network> + <task python="basic-004-slowpath.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/basic-005-slowpath-exhaustive.py b/recipes/switchdev/basic-005-slowpath-exhaustive.py new file mode 100644 index 0000000..c8a443e --- /dev/null +++ b/recipes/switchdev/basic-005-slowpath-exhaustive.py @@ -0,0 +1,36 @@ +""" +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@mellanox.com (Ido Schimmel) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def do_task(ctl, hosts, ifaces, aliases): + m1, sw = hosts + m1_if1, sw_if1 = ifaces + + m1_if1.reset(ip=["192.168.101.10/24", "2002::1/64"]) + sw_if1.reset(ip=["192.168.101.11/24", "2002::2/64"]) + + sleep(15) + + tl = TestLib(ctl, aliases) + for x in range(64, 1500): + tl.pktgen(sw_if1, m1_if1, x) + for x in range(64, 1500): + tl.pktgen(m1_if1, sw_if1, x) + # Make sure switch is not stuck by performing ping test + tl.ping_simple(m1_if1, sw_if1) + +do_task(ctl, [ctl.get_host("machine1"), + ctl.get_host("switch")], + [ctl.get_host("machine1").get_interface("if1"), + ctl.get_host("switch").get_interface("if1")], + ctl.get_aliases()) diff --git a/recipes/switchdev/basic-005-slowpath-exhaustive.xml b/recipes/switchdev/basic-005-slowpath-exhaustive.xml new file mode 100644 index 0000000..666d911 --- /dev/null +++ b/recipes/switchdev/basic-005-slowpath-exhaustive.xml @@ -0,0 +1,17 @@ +<lnstrecipe xmlns:xi="http://www.w3.org/2003/XInclude"> + <xi:include href="default_aliases.xml" /> + <network> + <host id="machine1"> + <params/> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + <host id="switch"> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + </network> + <task python="basic-005-slowpath-exhaustive.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/basic-006-slowpath-vlan.py b/recipes/switchdev/basic-006-slowpath-vlan.py new file mode 100644 index 0000000..7f34777 --- /dev/null +++ b/recipes/switchdev/basic-006-slowpath-vlan.py @@ -0,0 +1,35 @@ +""" +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@mellanox.com (Ido Schimmel) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def do_task(ctl, hosts, ifaces, aliases): + m1, sw = hosts + m1_if1, sw_if1 = ifaces + + m1_if1_10 = m1.create_vlan(m1_if1, 10, ip=["192.168.101.10/24", + "2002::1/64"]) + sw_if1_10 = sw.create_vlan(sw_if1, 10, ip=["192.168.101.11/24", + "2002::2/64"]) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_if1_10, sw_if1_10) + tl.netperf_tcp(m1_if1_10, sw_if1_10) + tl.netperf_udp(m1_if1_10, sw_if1_10) + +do_task(ctl, [ctl.get_host("machine1"), + ctl.get_host("switch")], + [ctl.get_host("machine1").get_interface("if1"), + ctl.get_host("switch").get_interface("if1")], + ctl.get_aliases()) diff --git a/recipes/switchdev/basic-006-slowpath-vlan.xml b/recipes/switchdev/basic-006-slowpath-vlan.xml new file mode 100644 index 0000000..e6df240 --- /dev/null +++ b/recipes/switchdev/basic-006-slowpath-vlan.xml @@ -0,0 +1,17 @@ +<lnstrecipe xmlns:xi="http://www.w3.org/2003/XInclude"> + <xi:include href="default_aliases.xml" /> + <network> + <host id="machine1"> + <params/> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + <host id="switch"> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + </network> + <task python="basic-006-slowpath-vlan.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/basic-007-slowpath-vlan-exhaustive.py b/recipes/switchdev/basic-007-slowpath-vlan-exhaustive.py new file mode 100644 index 0000000..e2d8fc7 --- /dev/null +++ b/recipes/switchdev/basic-007-slowpath-vlan-exhaustive.py @@ -0,0 +1,40 @@ +""" +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@mellanox.com (Ido Schimmel) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def do_task(ctl, hosts, ifaces, aliases): + m1, sw = hosts + m1_if1, sw_if1 = ifaces + + m1_if1_20 = m1.create_vlan(m1_if1, 20, ip=["192.168.101.10/24", + "2002::1/64"]) + sw_if1_20 = sw.create_vlan(sw_if1, 20, ip=["192.168.101.11/24", + "2002::2/64"]) + + # We need to get a netlink message with the VLAN devices' info, + # so make sure we wait long enough. + sleep(30) + + tl = TestLib(ctl, aliases) + for x in range(64, 1500): + tl.pktgen(sw_if1_20, m1_if1_20, x) + for x in range(64, 1500): + tl.pktgen(m1_if1_20, sw_if1_20, x) + # Make sure switch is not stuck by performing ping test + tl.ping_simple(m1_if1_20, sw_if1_20) + +do_task(ctl, [ctl.get_host("machine1"), + ctl.get_host("switch")], + [ctl.get_host("machine1").get_interface("if1"), + ctl.get_host("switch").get_interface("if1")], + ctl.get_aliases()) diff --git a/recipes/switchdev/basic-007-slowpath-vlan-exhaustive.xml b/recipes/switchdev/basic-007-slowpath-vlan-exhaustive.xml new file mode 100644 index 0000000..26eaf46 --- /dev/null +++ b/recipes/switchdev/basic-007-slowpath-vlan-exhaustive.xml @@ -0,0 +1,17 @@ +<lnstrecipe xmlns:xi="http://www.w3.org/2003/XInclude"> + <xi:include href="default_aliases.xml" /> + <network> + <host id="machine1"> + <params/> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + <host id="switch"> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + </network> + <task python="basic-007-slowpath-vlan-exhaustive.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/default_aliases.xml b/recipes/switchdev/default_aliases.xml new file mode 100644 index 0000000..783fb5e --- /dev/null +++ b/recipes/switchdev/default_aliases.xml @@ -0,0 +1,6 @@ +<define> + <alias name="ipv" value="both" /> + <alias name="mtu" value="1500" /> + <alias name="netperf_duration" value="60" /> + <alias name="netperf_num_parallel" value="30" /> +</define> diff --git a/recipes/switchdev/l2-000-minimal.py b/recipes/switchdev/l2-000-minimal.py new file mode 100644 index 0000000..dcc9532 --- /dev/null +++ b/recipes/switchdev/l2-000-minimal.py @@ -0,0 +1,36 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +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"]) + + sw.create_bridge(slaves=[sw_if1, sw_if2], options={"vlan_filtering": 1}) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_if1, m2_if1) + +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/l2-000-minimal.xml b/recipes/switchdev/l2-000-minimal.xml new file mode 100644 index 0000000..210974e --- /dev/null +++ b/recipes/switchdev/l2-000-minimal.xml @@ -0,0 +1,24 @@ +<lnstrecipe xmlns:xi="http://www.w3.org/2003/XInclude"> + <xi:include href="default_aliases.xml" /> + <network> + <host id="machine1"> + <params/> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + <host id="machine2"> + <params/> + <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="l2-000-minimal.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-001-bridge.py b/recipes/switchdev/l2-001-bridge.py new file mode 100644 index 0000000..f92dae9 --- /dev/null +++ b/recipes/switchdev/l2-001-bridge.py @@ -0,0 +1,38 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +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"]) + + sw.create_bridge(slaves=[sw_if1, sw_if2], options={"vlan_filtering": 1}) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_if1, m2_if1) + tl.netperf_tcp(m1_if1, m2_if1) + tl.netperf_udp(m1_if1, m2_if1) + +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/l2-001-bridge.xml b/recipes/switchdev/l2-001-bridge.xml new file mode 100644 index 0000000..1fdc211 --- /dev/null +++ b/recipes/switchdev/l2-001-bridge.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="l2-001-bridge.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-002-bridge_fdb.py b/recipes/switchdev/l2-002-bridge_fdb.py new file mode 100644 index 0000000..8e35758 --- /dev/null +++ b/recipes/switchdev/l2-002-bridge_fdb.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__ = """ +jiri@mellanox.com (Jiri Pirko) +idosch@mellanox.com (Ido Schimmel) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m2_if1, sw_if1, sw_if2 = ifaces + + m1_if1.reset(ip=test_ip(1,1)) + m2_if1.reset(ip=test_ip(1,2)) + + # Ageing time is 10 seconds. + br_options = {"vlan_filtering": 1, "ageing_time": 1000} + sw_br = sw.create_bridge(slaves = [sw_if1, sw_if2], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_if1, m2_if1) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software") + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware") + + sleep(20) + + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware", False) + + # Disable learning and make sure FDB is not populated. + sw_if1.set_br_learning(on=False, self=True) + tl.ping_simple(m1_if1, m2_if1) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware", False) + + # Disable flooding and make sure ping fails. + sw_if1.set_br_flooding(on=False, self=True) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + + # Set a static FDB entry and make sure ping works again. + sw_if1.add_br_fdb(str(m1_if1.get_hwaddr()), self=True, vlan_tci=1) + tl.ping_simple(m1_if1, m2_if1) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware") + + # Remove static FDB entry. Ping should fail. + sw_if1.del_br_fdb(str(m1_if1.get_hwaddr()), self=True, vlan_tci=1) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware", False) + + # Enable learning_sync and make sure both FDBs are populated. + sw_if1.set_br_learning(on=True, self=True) + sw_if1.set_br_flooding(on=True, self=True) + sw_if1.set_br_learning_sync(on=True, self=True) + tl.ping_simple(m1_if1, m2_if1) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software") + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware") + + sleep(20) + + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware", False) + + # Disable learning_sync and make sure only hardware FDB is populated. + sw_if1.set_br_learning_sync(on=False, self=True) + tl.ping_simple(m1_if1, m2_if1) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware") + + # Remove port from bridge and add it back. Disable flooding and learning + # and make sure ping doesn't work. Note that port must be removed from + # bridge when the FDB entry exists only in the hardware table. Otherwise, + # bridge code will flush it himself, instead of driver. + sw_br.slave_del(sw_if1.get_id()) + sw_br.slave_add(sw_if1.get_id()) # Enables learning sync by default. + sw_if1.set_br_learning(on=False, self=True) + sw_if1.set_br_flooding(on=False, self=True) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + + # Enable learning and make sure ping works again. + sw_if1.set_br_learning(on=True, self=True) + tl.ping_simple(m1_if1, m2_if1) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software") + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware") + + sleep(20) + + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware", False) + + # Insert a static FDB entry and disable learning sync. Ping should work. + sw_if1.add_br_fdb(str(m1_if1.get_hwaddr()), self=True, vlan_tci=1) + sw_if1.set_br_learning_sync(on=False, self=True) + tl.ping_simple(m1_if1, m2_if1) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware") + + sleep(20) + + # Make sure static entry is not aged out. + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware") + + # Remove port from bridge and add it back. Disable flooding and learning + # and make sure ping doesn't work. Note that port must be removed from + # bridge when the FDB entry exists only in the hardware table. Otherwise, + # bridge code will flush it himself, instead of driver. Unlike the + # previous case, here we check if the driver correctly removes the static + # entry. + # XXX: This currently fails because firmware doesn't flush static FDBs. + # Uncomment it when it's introduced. + #sw_br.slave_del(sw_if1.get_id()) + #sw_br.slave_add(sw_if1.get_id()) + #sw_if1.set_br_learning(on=False, self=True) + #sw_if1.set_br_flooding(on=False, self=True) + #tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + + # XXX: Cleanup because firmware doesn't do it. + sw_if1.del_br_fdb(str(m1_if1.get_hwaddr()), self=True, vlan_tci=1) + +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/l2-002-bridge_fdb.xml b/recipes/switchdev/l2-002-bridge_fdb.xml new file mode 100644 index 0000000..eab2cf0 --- /dev/null +++ b/recipes/switchdev/l2-002-bridge_fdb.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="l2-002-bridge_fdb.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-003-bridge_stp.py b/recipes/switchdev/l2-003-bridge_stp.py new file mode 100644 index 0000000..94bd6be --- /dev/null +++ b/recipes/switchdev/l2-003-bridge_stp.py @@ -0,0 +1,93 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +idosch@mellanox.com (Ido Schimmel) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m2_if1, sw_if1, sw_if2 = ifaces + + # We can't set STP state if kernel's STP is running. + br_options = {"stp_state": 0, "vlan_filtering": 1, "ageing_time": 1000} + sw.create_bridge(slaves=[sw_if1, sw_if2], options=br_options) + + m1_if1.reset(ip=test_ip(1, 1)) + m2_if1.reset(ip=test_ip(1, 2)) + + sleep(40) + + tl = TestLib(ctl, aliases) + + # Set STP state to DISABLED and make sure ping fails and FDB is not + # populated. + sw_if1.set_br_state(0) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware", False) + + # Set STP state to LISTENING and make sure ping fails and FDB is not + # populated. + sw_if1.set_br_state(1) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware", False) + + # Set STP state to LEARNING and make sure ping fails, but FDB *is* + # populated. + sw_if1.set_br_state(2) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software") + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware") + + sleep(20) + + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware", False) + + # Set STP state to FORWARDING and make sure ping works and FDB is + # populated. + sw_if1.set_br_state(3) + tl.ping_simple(m1_if1, m2_if1) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software") + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware") + + sleep(20) + + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_if1, m1_if1.get_hwaddr(), 1, "hardware", False) + + # Make sure that even with a static FDB record we don't get traffic + # when state is DISABLED, LEARNING or LISTENING. + sw_if2.add_br_fdb(str(m2_if1.get_hwaddr()), self=True, vlan_tci=1) + sw_if1.set_br_state(0) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + sw_if1.set_br_state(1) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + sw_if1.set_br_state(2) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + + # Cleanup + sw_if2.del_br_fdb(str(m2_if1.get_hwaddr()), self=True, vlan_tci=1) + +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/l2-003-bridge_stp.xml b/recipes/switchdev/l2-003-bridge_stp.xml new file mode 100644 index 0000000..d6c8f62 --- /dev/null +++ b/recipes/switchdev/l2-003-bridge_stp.xml @@ -0,0 +1,24 @@ +<lnstrecipe xmlns:xi="http://www.w3.org/2003/XInclude"> + <xi:include href="default_aliases.xml" /> + <network> + <host id="machine1"> + <params/> + <interfaces> + <eth id="if1" label="A" /> + </interfaces> + </host> + <host id="machine2"> + <params/> + <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="l2-003-bridge_stp.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-004-bridge_bond.py b/recipes/switchdev/l2-004-bridge_bond.py new file mode 100644 index 0000000..8378bbd --- /dev/null +++ b/recipes/switchdev/l2-004-bridge_bond.py @@ -0,0 +1,48 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + bond_options = {"mode": "802.3ad", "miimon": "100"} + m1_lag1 = m1.create_bond(slaves=[m1_if1, m1_if2], options=bond_options, + ip=["192.168.101.10/24", "2002::1/64"]) + m2_lag1 = m2.create_bond(slaves=[m2_if1, m2_if2], options=bond_options, + ip=["192.168.101.11/24", "2002::2/64"]) + + sw_lag1 = sw.create_bond(slaves=[sw_if1, sw_if2], options=bond_options) + sw_lag2 = sw.create_bond(slaves=[sw_if3, sw_if4], options=bond_options) + + sw.create_bridge(slaves=[sw_lag1, sw_lag2], options={"vlan_filtering": 1}) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_lag1, m2_lag1) + tl.netperf_tcp(m1_lag1, m2_lag1) + tl.netperf_udp(m1_lag1, m2_lag1) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-004-bridge_bond.xml b/recipes/switchdev/l2-004-bridge_bond.xml new file mode 100644 index 0000000..45fb919 --- /dev/null +++ b/recipes/switchdev/l2-004-bridge_bond.xml @@ -0,0 +1,26 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-004-bridge_bond.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-005-bridge_bond_failover.py b/recipes/switchdev/l2-005-bridge_bond_failover.py new file mode 100644 index 0000000..c7b4eca --- /dev/null +++ b/recipes/switchdev/l2-005-bridge_bond_failover.py @@ -0,0 +1,64 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + bond_options = {"mode": "802.3ad", "miimon": "100"} + m1_lag1 = m1.create_bond(slaves=[m1_if1, m1_if2], options=bond_options, + ip=["192.168.101.10/24", "2002::1/64"]) + m2_lag1 = m2.create_bond(slaves=[m2_if1, m2_if2], options=bond_options, + ip=["192.168.101.11/24", "2002::2/64"]) + + sw_lag1 = sw.create_bond(slaves=[sw_if1, sw_if2], options=bond_options) + sw_lag2 = sw.create_bond(slaves=[sw_if3, sw_if4], options=bond_options) + + sw.create_bridge(slaves=[sw_lag1, sw_lag2], options={"vlan_filtering": 1}) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_lag1, m2_lag1) + + sw_if1.set_link_down() + tl.ping_simple(m1_lag1, m2_lag1) + + sw_if1.set_link_up() + sw_if2.set_link_down() + tl.ping_simple(m1_lag1, m2_lag1) + + sw_if2.set_link_up() + sw_if1.set_link_down() + sw_if3.set_link_down() + tl.ping_simple(m1_lag1, m2_lag1) + + sw_if1.set_link_up() + sw_if3.set_link_up() + sw_if2.set_link_down() + sw_if4.set_link_down() + tl.ping_simple(m1_lag1, m2_lag1) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-005-bridge_bond_failover.xml b/recipes/switchdev/l2-005-bridge_bond_failover.xml new file mode 100644 index 0000000..ba87205 --- /dev/null +++ b/recipes/switchdev/l2-005-bridge_bond_failover.xml @@ -0,0 +1,26 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-005-bridge_bond_failover.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-006-bridge_team.py b/recipes/switchdev/l2-006-bridge_team.py new file mode 100644 index 0000000..fd648c9 --- /dev/null +++ b/recipes/switchdev/l2-006-bridge_team.py @@ -0,0 +1,54 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + team_config = '{"runner" : {"name" : "lacp"}}' + m1_lag1 = m1.create_team(slaves=[m1_if1, m1_if2], + config=team_config, + ip=["192.168.101.10/24", "2002::1/64"]) + + m2_lag1 = m2.create_team(slaves=[m2_if1, m2_if2], + config=team_config, + ip=["192.168.101.11/24", "2002::2/64"]) + + sw_lag1 = sw.create_team(slaves=[sw_if1, sw_if2], + config=team_config) + + sw_lag2 = sw.create_team(slaves=[sw_if3, sw_if4], + config=team_config) + + sw.create_bridge(slaves=[sw_lag1, sw_lag2], options={"vlan_filtering": 1}) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_lag1, m2_lag1) + tl.netperf_tcp(m1_lag1, m2_lag1) + tl.netperf_udp(m1_lag1, m2_lag1) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-006-bridge_team.xml b/recipes/switchdev/l2-006-bridge_team.xml new file mode 100644 index 0000000..9df081f --- /dev/null +++ b/recipes/switchdev/l2-006-bridge_team.xml @@ -0,0 +1,26 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-006-bridge_team.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-007-bridge_team_failover.py b/recipes/switchdev/l2-007-bridge_team_failover.py new file mode 100644 index 0000000..23d1a7c --- /dev/null +++ b/recipes/switchdev/l2-007-bridge_team_failover.py @@ -0,0 +1,70 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + team_config = '{"runner" : {"name" : "lacp"}}' + m1_lag1 = m1.create_team(slaves=[m1_if1, m1_if2], + config=team_config, + ip=["192.168.101.10/24", "2002::1/64"]) + + m2_lag1 = m2.create_team(slaves=[m2_if1, m2_if2], + config=team_config, + ip=["192.168.101.11/24", "2002::2/64"]) + + sw_lag1 = sw.create_team(slaves=[sw_if1, sw_if2], + config=team_config) + + sw_lag2 = sw.create_team(slaves=[sw_if3, sw_if4], + config=team_config) + + sw.create_bridge(slaves=[sw_lag1, sw_lag2], options={"vlan_filtering": 1}) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_lag1, m2_lag1) + + sw_if1.set_link_down() + tl.ping_simple(m1_lag1, m2_lag1) + + sw_if1.set_link_up() + sw_if2.set_link_down() + tl.ping_simple(m1_lag1, m2_lag1) + + sw_if2.set_link_up() + sw_if1.set_link_down() + sw_if3.set_link_down() + tl.ping_simple(m1_lag1, m2_lag1) + + sw_if1.set_link_up() + sw_if3.set_link_up() + sw_if2.set_link_down() + sw_if4.set_link_down() + tl.ping_simple(m1_lag1, m2_lag1) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-007-bridge_team_failover.xml b/recipes/switchdev/l2-007-bridge_team_failover.xml new file mode 100644 index 0000000..3a20245 --- /dev/null +++ b/recipes/switchdev/l2-007-bridge_team_failover.xml @@ -0,0 +1,26 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-007-bridge_team_failover.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-008-bridge_vlan1q_sanity.py b/recipes/switchdev/l2-008-bridge_vlan1q_sanity.py new file mode 100644 index 0000000..740de76 --- /dev/null +++ b/recipes/switchdev/l2-008-bridge_vlan1q_sanity.py @@ -0,0 +1,86 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +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 check_vlan(tl, iface, vlan_id, pvid=False, untagged = False): + vlans = iface.get_br_vlans() + err_msg = "vlan not found" + for vlan in vlans: + if vlan_id == vlan["vlan_id"]: + if pvid != vlan["pvid"]: + err_msg = "PVID is not as expected" + elif untagged != vlan["untagged"]: + err_msg = "Untagged is not as expected" + else: + err_msg = "" + tl.custom(iface.get_host(), "vlan creation verification", err_msg) + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m2_if1, sw_if1, sw_if2 = ifaces + + m1_if1.reset(ip=test_ip(1, 1)) + + m1_if1_10 = m1.create_vlan(m1_if1, 10, ip=test_ip(2, 1)) + m1_if1_20 = m1.create_vlan(m1_if1, 20, ip=test_ip(3, 1)) + m1_if1_30 = m1.create_vlan(m1_if1, 30, ip=test_ip(4, 1)) + + m2_if1.reset(ip=test_ip(1, 2)) + m2_if1_10 = m2.create_vlan(m2_if1, 10, ip=test_ip(2, 2)) + m2_if1_20 = m2.create_vlan(m2_if1, 20, ip=test_ip(3, 2)) + m2_if1_30 = m2.create_vlan(m2_if1, 30, ip=test_ip(4, 2)) + + br_options = {"vlan_filtering": 1} + sw.create_bridge(slaves=[sw_if1, sw_if2], options=br_options) + + sw_if1.add_br_vlan(10) + sw_if2.add_br_vlan(10) + sw_if1.add_br_vlan(20) + sw_if2.add_br_vlan(20) + + sleep(15) + + tl = TestLib(ctl, aliases) + + check_vlan(tl, sw_if1, 10) + check_vlan(tl, sw_if2, 10) + check_vlan(tl, sw_if1, 20) + check_vlan(tl, sw_if2, 20) + + tl.ping_simple(m1_if1, m2_if1) + tl.ping_simple(m1_if1_10, m2_if1_10) + tl.ping_simple(m1_if1_20, m2_if1_20) + tl.ping_simple(m1_if1_30, m2_if1_30, fail_expected=True) + + sw_if1.add_br_vlan(500, pvid=True, untagged=True) + check_vlan(tl, sw_if1, 500, pvid=True, untagged=True) + sleep(1) + tl.ping_simple(m1_if1, m2_if1, fail_expected=True) + + sw_if2.add_br_vlan(500, pvid=True, untagged=True) + check_vlan(tl, sw_if2, 500, pvid=True, untagged=True) + sleep(1) + tl.ping_simple(m1_if1, m2_if1) + +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/l2-008-bridge_vlan1q_sanity.xml b/recipes/switchdev/l2-008-bridge_vlan1q_sanity.xml new file mode 100644 index 0000000..1aa7f12 --- /dev/null +++ b/recipes/switchdev/l2-008-bridge_vlan1q_sanity.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="l2-008-bridge_vlan1q_sanity.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-009-bridge_vlan1q.py b/recipes/switchdev/l2-009-bridge_vlan1q.py new file mode 100644 index 0000000..af24b8d --- /dev/null +++ b/recipes/switchdev/l2-009-bridge_vlan1q.py @@ -0,0 +1,70 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m2_if1, sw_if1, sw_if2 = ifaces + + m1_if1.reset(ip=test_ip(1, 1)) + + m1_if1_10 = m1.create_vlan(m1_if1, 10, ip=test_ip(2, 1)) + m1_if1_20 = m1.create_vlan(m1_if1, 20, ip=test_ip(3, 1)) + + m2_if1.reset(ip=test_ip(1, 2)) + m2_if1_10 = m2.create_vlan(m2_if1, 10, ip=test_ip(2, 2)) + m2_if1_20 = m2.create_vlan(m2_if1, 20, ip=test_ip(3, 2)) + + br_options = {"vlan_filtering": 1} + sw.create_bridge(slaves=[sw_if1, sw_if2], options=br_options) + + sw_if1.add_br_vlan(10) + sw_if2.add_br_vlan(10) + sw_if1.add_br_vlan(20) + sw_if2.add_br_vlan(20) + + sleep(15) + + tl = TestLib(ctl, ipv, aliases) + + tl.ping_simple(m1_if1, m2_if1) + tl.netperf_tcp(m1_if1, m2_if1) + tl.netperf_udp(m1_if1, m2_if1) + + tl.ping_simple(m1_if1_10, m2_if1_10) + tl.netperf_tcp(m1_if1_10, m2_if1_10) + tl.netperf_udp(m1_if1_10, m2_if1_10) + + tl.ping_simple(m1_if1_20, m2_if1_20) + tl.netperf_tcp(m1_if1_20, m2_if1_20) + tl.netperf_udp(m1_if1_20, m2_if1_20) + + sw_if1.add_br_vlan(500, pvid=True, untagged=True) + sw_if2.add_br_vlan(500, pvid=True, untagged=True) + sleep(1) + tl.ping_simple(m1_if1, m2_if1) + tl.netperf_tcp(m1_if1, m2_if1) + tl.netperf_udp(m1_if1, m2_if1) + +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/l2-009-bridge_vlan1q.xml b/recipes/switchdev/l2-009-bridge_vlan1q.xml new file mode 100644 index 0000000..43703a7 --- /dev/null +++ b/recipes/switchdev/l2-009-bridge_vlan1q.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="l2-009-bridge_vlan1q.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-010-bridge_vlan1d_sanity.py b/recipes/switchdev/l2-010-bridge_vlan1d_sanity.py new file mode 100644 index 0000000..2c0062f --- /dev/null +++ b/recipes/switchdev/l2-010-bridge_vlan1d_sanity.py @@ -0,0 +1,60 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m2_if1, sw_if1, sw_if2 = ifaces + + m1_if1.reset(ip=test_ip(1, 1)) + + m1_if1_10 = m1.create_vlan(m1_if1, 10, ip=test_ip(2, 1)) + m1_if1_20 = m1.create_vlan(m1_if1, 20, ip=test_ip(3, 1)) + m1_if1_30 = m1.create_vlan(m1_if1, 30, ip=test_ip(4, 1)) + + m2_if1.reset(ip=test_ip(1, 2)) + m2_if1_10 = m2.create_vlan(m2_if1, 10, ip=test_ip(2, 2)) + m2_if1_21 = m2.create_vlan(m2_if1, 21, ip=test_ip(3, 2)) + m2_if1_30 = m2.create_vlan(m2_if1, 30, ip=test_ip(4, 2)) + + br_options = {"vlan_filtering": 1} + sw.create_bridge(slaves=[sw_if1, sw_if2], options=br_options) + + sw_if1_10 = sw.create_vlan(sw_if1, 10) + sw_if2_10 = sw.create_vlan(sw_if2, 10) + sw.create_bridge(slaves=[sw_if1_10, sw_if2_10], options=br_options) + + sw_if1_20 = sw.create_vlan(sw_if1, 20) + sw_if2_21 = sw.create_vlan(sw_if2, 21) + sw.create_bridge(slaves=[sw_if1_20, sw_if2_21], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_if1, m2_if1) + tl.ping_simple(m1_if1_10, m2_if1_10) + tl.ping_simple(m1_if1_20, m2_if1_21) + tl.ping_simple(m1_if1_30, m2_if1_30, fail_expected=True) + +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/l2-010-bridge_vlan1d_sanity.xml b/recipes/switchdev/l2-010-bridge_vlan1d_sanity.xml new file mode 100644 index 0000000..4384c43 --- /dev/null +++ b/recipes/switchdev/l2-010-bridge_vlan1d_sanity.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="l2-010-bridge_vlan1d_sanity.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-011-bridge_vlan1d.py b/recipes/switchdev/l2-011-bridge_vlan1d.py new file mode 100644 index 0000000..ccacf79 --- /dev/null +++ b/recipes/switchdev/l2-011-bridge_vlan1d.py @@ -0,0 +1,66 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m2_if1, sw_if1, sw_if2 = ifaces + + m1_if1.reset(ip=test_ip(1, 1)) + + m1_if1_10 = m1.create_vlan(m1_if1, 10, ip=test_ip(2, 1)) + m1_if1_20 = m1.create_vlan(m1_if1, 20, ip=test_ip(3, 1)) + + m2_if1.reset(ip=test_ip(1, 2)) + m2_if1_10 = m2.create_vlan(m2_if1, 10, ip=test_ip(2, 2)) + m2_if1_21 = m2.create_vlan(m2_if1, 21, ip=test_ip(3, 2)) + + br_options = {"vlan_filtering": 1} + sw.create_bridge(slaves=[sw_if1, sw_if2], options=br_options) + + sw_if1_10 = sw.create_vlan(sw_if1, 10) + sw_if2_10 = sw.create_vlan(sw_if2, 10) + sw.create_bridge(slaves=[sw_if1_10, sw_if2_10], options=br_options) + + sw_if1_20 = sw.create_vlan(sw_if1, 20) + sw_if2_21 = sw.create_vlan(sw_if2, 21) + sw.create_bridge(slaves=[sw_if1_20, sw_if2_21], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + + tl.ping_simple(m1_if1, m2_if1) + tl.netperf_tcp(m1_if1, m2_if1) + tl.netperf_udp(m1_if1, m2_if1) + + tl.ping_simple(m1_if1_10, m2_if1_10) + tl.netperf_tcp(m1_if1_10, m2_if1_10) + tl.netperf_udp(m1_if1_10, m2_if1_10) + + tl.ping_simple(m1_if1_20, m2_if1_21) + tl.netperf_tcp(m1_if1_20, m2_if1_21) + tl.netperf_udp(m1_if1_20, m2_if1_21) + +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/l2-011-bridge_vlan1d.xml b/recipes/switchdev/l2-011-bridge_vlan1d.xml new file mode 100644 index 0000000..fd53578 --- /dev/null +++ b/recipes/switchdev/l2-011-bridge_vlan1d.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="l2-011-bridge_vlan1d.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-012-bridge_bond_vlan1d_sanity.py b/recipes/switchdev/l2-012-bridge_bond_vlan1d_sanity.py new file mode 100644 index 0000000..66c3eff --- /dev/null +++ b/recipes/switchdev/l2-012-bridge_bond_vlan1d_sanity.py @@ -0,0 +1,68 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + bond_options = {"mode": "802.3ad", "miimon": "100"} + m1_lag1 = m1.create_bond(slaves=[m1_if1, m1_if2], + options=bond_options, ip=test_ip(1, 1)) + m1_lag1_10 = m1.create_vlan(m1_lag1, 10, ip=test_ip(2, 1)) + m1_lag1_20 = m1.create_vlan(m1_lag1, 20, ip=test_ip(3, 1)) + m1_lag1_30 = m1.create_vlan(m1_lag1, 30, ip=test_ip(4, 1)) + + m2_lag1 = m2.create_bond(slaves=[m2_if1, m2_if2], + options=bond_options, ip=test_ip(1, 2)) + m2_lag1_10 = m2.create_vlan(m2_lag1, 10, ip=test_ip(2, 2)) + m2_lag1_21 = m2.create_vlan(m2_lag1, 21, ip=test_ip(3, 2)) + m2_lag1_30 = m2.create_vlan(m2_lag1, 30, ip=test_ip(4, 2)) + + sw_lag1 = sw.create_bond(slaves=[sw_if1, sw_if2], options=bond_options) + sw_lag2 = sw.create_bond(slaves=[sw_if3, sw_if4], options=bond_options) + br_options = {"vlan_filtering": 1} + sw.create_bridge(slaves=[sw_lag1, sw_lag2], options=br_options) + + sw_lag1_10 = sw.create_vlan(sw_lag1, 10) + sw_lag2_10 = sw.create_vlan(sw_lag2, 10) + sw.create_bridge(slaves=[sw_lag1_10, sw_lag2_10], options=br_options) + + sw_lag1_20 = sw.create_vlan(sw_lag1, 20) + sw_lag2_21 = sw.create_vlan(sw_lag2, 21) + sw.create_bridge(slaves=[sw_lag1_20, sw_lag2_21], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_lag1, m2_lag1) + tl.ping_simple(m1_lag1_10, m2_lag1_10) + tl.ping_simple(m1_lag1_20, m2_lag1_21) + tl.ping_simple(m1_lag1_30, m2_lag1_30, fail_expected=True) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-012-bridge_bond_vlan1d_sanity.xml b/recipes/switchdev/l2-012-bridge_bond_vlan1d_sanity.xml new file mode 100644 index 0000000..52c6a3f --- /dev/null +++ b/recipes/switchdev/l2-012-bridge_bond_vlan1d_sanity.xml @@ -0,0 +1,26 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-012-bridge_bond_vlan1d_sanity.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-013-bridge_bond_vlan1d.py b/recipes/switchdev/l2-013-bridge_bond_vlan1d.py new file mode 100644 index 0000000..f2f68d2 --- /dev/null +++ b/recipes/switchdev/l2-013-bridge_bond_vlan1d.py @@ -0,0 +1,74 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + bond_options = {"mode": "802.3ad", "miimon": "100"} + m1_lag1 = m1.create_bond(slaves=[m1_if1, m1_if2], + options=bond_options, ip=test_ip(1, 1)) + m1_lag1_10 = m1.create_vlan(m1_lag1, 10, ip=test_ip(2, 1)) + m1_lag1_20 = m1.create_vlan(m1_lag1, 20, ip=test_ip(3, 1)) + + m2_lag1 = m2.create_bond(slaves=[m2_if1, m2_if2], + options=bond_options, ip=test_ip(1, 2)) + m2_lag1_10 = m2.create_vlan(m2_lag1, 10, ip=test_ip(2, 2)) + m2_lag1_21 = m2.create_vlan(m2_lag1, 21, ip=test_ip(3, 2)) + + sw_lag1 = sw.create_bond(slaves=[sw_if1, sw_if2], options=bond_options) + sw_lag2 = sw.create_bond(slaves=[sw_if3, sw_if4], options=bond_options) + br_options = {"vlan_filtering": 1} + sw.create_bridge(slaves=[sw_lag1, sw_lag2], options=br_options) + + sw_lag1_10 = sw.create_vlan(sw_lag1, 10) + sw_lag2_10 = sw.create_vlan(sw_lag2, 10) + sw.create_bridge(slaves=[sw_lag1_10, sw_lag2_10], options=br_options) + + sw_lag1_20 = sw.create_vlan(sw_lag1, 20) + sw_lag2_21 = sw.create_vlan(sw_lag2, 21) + sw.create_bridge(slaves=[sw_lag1_20, sw_lag2_21], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + + tl.ping_simple(m1_lag1, m2_lag1) + tl.netperf_tcp(m1_lag1, m2_lag1) + tl.netperf_udp(m1_lag1, m2_lag1) + + tl.ping_simple(m1_lag1_10, m2_lag1_10) + tl.netperf_tcp(m1_lag1_10, m2_lag1_10) + tl.netperf_udp(m1_lag1_10, m2_lag1_10) + + tl.ping_simple(m1_lag1_20, m2_lag1_21) + tl.netperf_tcp(m1_lag1_20, m2_lag1_21) + tl.netperf_udp(m1_lag1_20, m2_lag1_21) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-013-bridge_bond_vlan1d.xml b/recipes/switchdev/l2-013-bridge_bond_vlan1d.xml new file mode 100644 index 0000000..3690d63 --- /dev/null +++ b/recipes/switchdev/l2-013-bridge_bond_vlan1d.xml @@ -0,0 +1,26 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-013-bridge_bond_vlan1d.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-014-bridge_team_vlan1d_sanity.py b/recipes/switchdev/l2-014-bridge_team_vlan1d_sanity.py new file mode 100644 index 0000000..58753ca --- /dev/null +++ b/recipes/switchdev/l2-014-bridge_team_vlan1d_sanity.py @@ -0,0 +1,68 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + team_config = '{"runner" : {"name" : "lacp"}}' + m1_lag1 = m1.create_team(slaves=[m1_if1, m1_if2], + config=team_config, ip=test_ip(1, 1)) + m1_lag1_10 = m1.create_vlan(m1_lag1, 10, ip=test_ip(2, 1)) + m1_lag1_20 = m1.create_vlan(m1_lag1, 20, ip=test_ip(3, 1)) + m1_lag1_30 = m1.create_vlan(m1_lag1, 30, ip=test_ip(4, 1)) + + m2_lag1 = m2.create_team(slaves=[m2_if1, m2_if2], + config=team_config, ip=test_ip(1, 2)) + m2_lag1_10 = m2.create_vlan(m2_lag1, 10, ip=test_ip(2, 2)) + m2_lag1_21 = m2.create_vlan(m2_lag1, 21, ip=test_ip(3, 2)) + m2_lag1_30 = m2.create_vlan(m2_lag1, 30, ip=test_ip(4, 2)) + + sw_lag1 = sw.create_team(slaves=[sw_if1, sw_if2], config=team_config) + sw_lag2 = sw.create_team(slaves=[sw_if3, sw_if4], config=team_config) + br_options = {"vlan_filtering": 1} + sw.create_bridge(slaves=[sw_lag1, sw_lag2], options=br_options) + + sw_lag1_10 = sw.create_vlan(sw_lag1, 10) + sw_lag2_10 = sw.create_vlan(sw_lag2, 10) + sw.create_bridge(slaves=[sw_lag1_10, sw_lag2_10], options=br_options) + + sw_lag1_20 = sw.create_vlan(sw_lag1, 20) + sw_lag2_21 = sw.create_vlan(sw_lag2, 21) + sw.create_bridge(slaves=[sw_lag1_20, sw_lag2_21], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_lag1, m2_lag1) + tl.ping_simple(m1_lag1_10, m2_lag1_10) + tl.ping_simple(m1_lag1_20, m2_lag1_21) + tl.ping_simple(m1_lag1_30, m2_lag1_30, fail_expected=True) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-014-bridge_team_vlan1d_sanity.xml b/recipes/switchdev/l2-014-bridge_team_vlan1d_sanity.xml new file mode 100644 index 0000000..730f0f0 --- /dev/null +++ b/recipes/switchdev/l2-014-bridge_team_vlan1d_sanity.xml @@ -0,0 +1,26 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-014-bridge_team_vlan1d_sanity.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-015-bridge_team_vlan1d.py b/recipes/switchdev/l2-015-bridge_team_vlan1d.py new file mode 100644 index 0000000..3bea6e2 --- /dev/null +++ b/recipes/switchdev/l2-015-bridge_team_vlan1d.py @@ -0,0 +1,74 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + team_config = '{"runner" : {"name" : "lacp"}}' + m1_lag1 = m1.create_team(slaves=[m1_if1, m1_if2], + config=team_config, ip=test_ip(1, 1)) + m1_lag1_10 = m1.create_vlan(m1_lag1, 10, ip=test_ip(2, 1)) + m1_lag1_20 = m1.create_vlan(m1_lag1, 20, ip=test_ip(3, 1)) + + m2_lag1 = m2.create_team(slaves=[m2_if1, m2_if2], + config=team_config, ip=test_ip(1, 2)) + m2_lag1_10 = m2.create_vlan(m2_lag1, 10, ip=test_ip(2, 2)) + m2_lag1_21 = m2.create_vlan(m2_lag1, 21, ip=test_ip(3, 2)) + + sw_lag1 = sw.create_team(slaves=[sw_if1, sw_if2], config=team_config) + sw_lag2 = sw.create_team(slaves=[sw_if3, sw_if4], config=team_config) + br_options = {"vlan_filtering": 1} + sw.create_bridge(slaves=[sw_lag1, sw_lag2], options=br_options) + + sw_lag1_10 = sw.create_vlan(sw_lag1, 10) + sw_lag2_10 = sw.create_vlan(sw_lag2, 10) + sw.create_bridge(slaves=[sw_lag1_10, sw_lag2_10], options=br_options) + + sw_lag1_20 = sw.create_vlan(sw_lag1, 20) + sw_lag2_21 = sw.create_vlan(sw_lag2, 21) + sw.create_bridge(slaves=[sw_lag1_20, sw_lag2_21], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + + tl.ping_simple(m1_lag1, m2_lag1) + tl.netperf_tcp(m1_lag1, m2_lag1) + tl.netperf_udp(m1_lag1, m2_lag1) + + tl.ping_simple(m1_lag1_10, m2_lag1_10) + tl.netperf_tcp(m1_lag1_10, m2_lag1_10) + tl.netperf_udp(m1_lag1_10, m2_lag1_10) + + tl.ping_simple(m1_lag1_20, m2_lag1_21) + tl.netperf_tcp(m1_lag1_20, m2_lag1_21) + tl.netperf_udp(m1_lag1_20, m2_lag1_21) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-015-bridge_team_vlan1d.xml b/recipes/switchdev/l2-015-bridge_team_vlan1d.xml new file mode 100644 index 0000000..14c40e3 --- /dev/null +++ b/recipes/switchdev/l2-015-bridge_team_vlan1d.xml @@ -0,0 +1,27 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <params/> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-015-bridge_team_vlan1d.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-017-bridge_fdb_vlan1d.py b/recipes/switchdev/l2-017-bridge_fdb_vlan1d.py new file mode 100644 index 0000000..3edcfc6 --- /dev/null +++ b/recipes/switchdev/l2-017-bridge_fdb_vlan1d.py @@ -0,0 +1,144 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +idosch@mellanox.com (Ido Schimmel) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m2_if1, sw_if1, sw_if2 = ifaces + + m1_if1_10 = m1.create_vlan(m1_if1, 10, ip=test_ip(1,1)) + m2_if1_20 = m2.create_vlan(m2_if1, 20, ip=test_ip(1,2)) + sw_if1_10 = sw.create_vlan(sw_if1, 10) + sw_if2_20 = sw.create_vlan(sw_if2, 20) + + # Ageing time is 10 seconds. + br_options = {"vlan_filtering": 0, "ageing_time": 1000} + sw_br = sw.create_bridge(slaves = [sw_if1_10, sw_if2_20], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_if1_10, m2_if1_20) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software") + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware") + + sleep(20) + + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware", False) + + # Disable learning and make sure FDB is not populated. + sw_if1_10.set_br_learning(on=False, self=True) + tl.ping_simple(m1_if1_10, m2_if1_20) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware", False) + + # Disable flooding and make sure ping fails. + sw_if1_10.set_br_flooding(on=False, self=True) + tl.ping_simple(m1_if1_10, m2_if1_20, fail_expected=True) + + # Set a static FDB entry and make sure ping works again. + sw_if1_10.add_br_fdb(str(m1_if1_10.get_hwaddr()), self=True) + tl.ping_simple(m1_if1_10, m2_if1_20) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware") + + # Remove static FDB entry. Ping should fail. + sw_if1_10.del_br_fdb(str(m1_if1_10.get_hwaddr()), self=True) + tl.ping_simple(m1_if1_10, m2_if1_20, fail_expected=True) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware", False) + + # Enable learning_sync and make sure both FDBs are populated. + sw_if1_10.set_br_learning(on=True, self=True) + sw_if1_10.set_br_flooding(on=True, self=True) + sw_if1_10.set_br_learning_sync(on=True, self=True) + tl.ping_simple(m1_if1_10, m2_if1_20) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software") + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware") + + sleep(20) + + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware", False) + + # Disable learning_sync and make sure only hardware FDB is populated. + sw_if1_10.set_br_learning_sync(on=False, self=True) + tl.ping_simple(m1_if1_10, m2_if1_20) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware") + + # Remove port from bridge and add it back. Disable flooding and learning + # and make sure ping doesn't work. Note that port must be removed from + # bridge when the FDB entry exists only in the hardware table. Otherwise, + # bridge code will flush it himself, instead of driver. + sw_br.slave_del(sw_if1_10.get_id()) + sw_br.slave_add(sw_if1_10.get_id()) # Enables learning sync by default. + sw_if1_10.set_br_learning(on=False, self=True) + sw_if1_10.set_br_flooding(on=False, self=True) + tl.ping_simple(m1_if1_10, m2_if1_20, fail_expected=True) + + # Enable learning and make sure ping works again. + sw_if1_10.set_br_learning(on=True, self=True) + tl.ping_simple(m1_if1_10, m2_if1_20) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software") + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware") + + sleep(20) + + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware", False) + + # Insert a static FDB entry and disable learning sync. Ping should work. + sw_if1_10.add_br_fdb(str(m1_if1_10.get_hwaddr()), self=True) + sw_if1_10.set_br_learning_sync(on=False, self=True) + tl.ping_simple(m1_if1_10, m2_if1_20) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware") + + sleep(20) + + # Make sure static entry is not aged out. + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_if1_10, m1_if1_10.get_hwaddr(), 0, "hardware") + + # Remove port from bridge and add it back. Disable flooding and learning + # and make sure ping doesn't work. Note that port must be removed from + # bridge when the FDB entry exists only in the hardware table. Otherwise, + # bridge code will flush it himself, instead of driver. Unlike the + # previous case, here we check if the driver correctly removes the static + # entry. + # XXX: This currently fails because firmware doesn't flush static FDBs. + # Uncomment it when it's introduced. + #sw_br.slave_del(sw_if1_10.get_id()) + #sw_br.slave_add(sw_if1_10.get_id()) + #sw_if1_10.set_br_learning(on=False, self=True) + #sw_if1_10.set_br_flooding(on=False, self=True) + #tl.ping_simple(m1_if1_10, m2_if1_20, fail_expected=True) + + # XXX: Cleanup because firmware doesn't do it. + sw_if1_10.del_br_fdb(str(m1_if1_10.get_hwaddr()), self=True) + +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/l2-017-bridge_fdb_vlan1d.xml b/recipes/switchdev/l2-017-bridge_fdb_vlan1d.xml new file mode 100644 index 0000000..2d3df4c --- /dev/null +++ b/recipes/switchdev/l2-017-bridge_fdb_vlan1d.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="l2-017-bridge_fdb_vlan1d.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-018-bridge_fdb_team.py b/recipes/switchdev/l2-018-bridge_fdb_team.py new file mode 100644 index 0000000..a4443f6 --- /dev/null +++ b/recipes/switchdev/l2-018-bridge_fdb_team.py @@ -0,0 +1,150 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +idosch@mellanox.com (Ido Schimmel) +""" + +from lnst.Controller.Task import ctl +from TestLib import TestLib +from time import sleep + +def do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + team_config = '{"runner" : {"name" : "lacp"}}' + m1_lag1 = m1.create_team(slaves=[m1_if1, m1_if2], config=team_config, + ip=["192.168.101.10/24", "2002::1/64"]) + + m2_lag1 = m2.create_team(slaves=[m2_if1, m2_if2], config=team_config, + ip=["192.168.101.11/24", "2002::2/64"]) + + sw_lag1 = sw.create_team(slaves=[sw_if1, sw_if2], config=team_config) + + sw_lag2 = sw.create_team(slaves=[sw_if3, sw_if4], config=team_config) + + # Ageing time is 10 seconds. + br_options = {"vlan_filtering": 1, "ageing_time": 1000} + sw_br = sw.create_bridge(slaves = [sw_lag1, sw_lag2], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_lag1, m2_lag1) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software") + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware") + + sleep(20) + + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware", False) + + # Disable learning and make sure FDB is not populated. + sw_lag1.set_br_learning(on=False, self=True) + tl.ping_simple(m1_lag1, m2_lag1) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware", False) + + # Disable flooding and make sure ping fails. + sw_lag1.set_br_flooding(on=False, self=True) + tl.ping_simple(m1_lag1, m2_lag1, fail_expected=True) + + # Set a static FDB entry and make sure ping works again. + sw_lag1.add_br_fdb(str(m1_lag1.get_hwaddr()), self=True, vlan_tci=1) + tl.ping_simple(m1_lag1, m2_lag1) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware") + + # Remove static FDB entry. Ping should fail. + sw_lag1.del_br_fdb(str(m1_lag1.get_hwaddr()), self=True, vlan_tci=1) + tl.ping_simple(m1_lag1, m2_lag1, fail_expected=True) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware", False) + + # Enable learning_sync and make sure both FDBs are populated. + sw_lag1.set_br_learning(on=True, self=True) + sw_lag1.set_br_flooding(on=True, self=True) + sw_lag1.set_br_learning_sync(on=True, self=True) + tl.ping_simple(m1_lag1, m2_lag1) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software") + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware") + + sleep(20) + + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware", False) + + # Disable learning_sync and make sure only hardware FDB is populated. + sw_lag1.set_br_learning_sync(on=False, self=True) + tl.ping_simple(m1_lag1, m2_lag1) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware") + + # Remove port from bridge and add it back. Disable flooding and learning + # and make sure ping doesn't work. Note that port must be removed from + # bridge when the FDB entry exists only in the hardware table. Otherwise, + # bridge code will flush it himself, instead of driver. + sw_br.slave_del(sw_lag1.get_id()) + sw_br.slave_add(sw_lag1.get_id()) # Enables learning sync by default. + sw_lag1.set_br_learning(on=False, self=True) + sw_lag1.set_br_flooding(on=False, self=True) + tl.ping_simple(m1_lag1, m2_lag1, fail_expected=True) + + # Enable learning and make sure ping works again. + sw_lag1.set_br_learning(on=True, self=True) + tl.ping_simple(m1_lag1, m2_lag1) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software") + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware") + + sleep(20) + + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware", False) + + # Insert a static FDB entry and disable learning sync. Ping should work. + sw_lag1.add_br_fdb(str(m1_lag1.get_hwaddr()), self=True, vlan_tci=1) + sw_lag1.set_br_learning_sync(on=False, self=True) + tl.ping_simple(m1_lag1, m2_lag1) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware") + + sleep(20) + + # Make sure static entry is not aged out. + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "software", False) + tl.check_fdb(sw_lag1, m1_lag1.get_hwaddr(), 1, "hardware") + + # Remove port from bridge and add it back. Disable flooding and learning + # and make sure ping doesn't work. Note that port must be removed from + # bridge when the FDB entry exists only in the hardware table. Otherwise, + # bridge code will flush it himself, instead of driver. Unlike the + # previous case, here we check if the driver correctly removes the static + # entry. + # XXX: This currently fails because firmware doesn't flush static FDBs. + # Uncomment it when it's introduced. + #sw_br.slave_del(sw_lag1.get_id()) + #sw_br.slave_add(sw_lag1.get_id()) + #sw_lag1.set_br_learning(on=False, self=True) + #sw_lag1.set_br_flooding(on=False, self=True) + #tl.ping_simple(m1_lag1, m2_lag1, fail_expected=True) + + # XXX: Cleanup because firmware doesn't do it. + sw_lag1.del_br_fdb(str(m1_lag1.get_hwaddr()), self=True, vlan_tci=1) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-018-bridge_fdb_team.xml b/recipes/switchdev/l2-018-bridge_fdb_team.xml new file mode 100644 index 0000000..266fed9 --- /dev/null +++ b/recipes/switchdev/l2-018-bridge_fdb_team.xml @@ -0,0 +1,26 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-018-bridge_fdb_team.py" /> +</lnstrecipe> diff --git a/recipes/switchdev/l2-019-bridge_fdb_team_vlan1d.py b/recipes/switchdev/l2-019-bridge_fdb_team_vlan1d.py new file mode 100644 index 0000000..3d588d0 --- /dev/null +++ b/recipes/switchdev/l2-019-bridge_fdb_team_vlan1d.py @@ -0,0 +1,157 @@ +""" +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__ = """ +jiri@mellanox.com (Jiri Pirko) +idosch@mellanox.com (Ido Schimmel) +""" + +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 do_task(ctl, hosts, ifaces, aliases): + m1, m2, sw = hosts + m1_if1, m1_if2, m2_if1, m2_if2, sw_if1, sw_if2, sw_if3, sw_if4 = ifaces + + team_config = '{"runner" : {"name" : "lacp"}}' + m1_lag1 = m1.create_team(slaves=[m1_if1, m1_if2], config=team_config) + + m2_lag1 = m2.create_team(slaves=[m2_if1, m2_if2], config=team_config) + + sw_lag1 = sw.create_team(slaves=[sw_if1, sw_if2], config=team_config) + + sw_lag2 = sw.create_team(slaves=[sw_if3, sw_if4], config=team_config) + + m1_lag1_10 = m1.create_vlan(m1_lag1, 10, ip=test_ip(1,1)) + m2_lag1_20 = m2.create_vlan(m2_lag1, 20, ip=test_ip(1,2)) + sw_lag1_10 = sw.create_vlan(sw_lag1, 10) + sw_lag2_20 = sw.create_vlan(sw_lag2, 20) + + # Ageing time is 10 seconds. + br_options = {"vlan_filtering": 0, "ageing_time": 1000} + sw_br = sw.create_bridge(slaves = [sw_lag1_10, sw_lag2_20], options=br_options) + + sleep(15) + + tl = TestLib(ctl, aliases) + tl.ping_simple(m1_lag1_10, m2_lag1_20) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software") + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware") + + sleep(20) + + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware", False) + + # Disable learning and make sure FDB is not populated. + sw_lag1_10.set_br_learning(on=False, self=True) + tl.ping_simple(m1_lag1_10, m2_lag1_20) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware", False) + + # Disable flooding and make sure ping fails. + sw_lag1_10.set_br_flooding(on=False, self=True) + tl.ping_simple(m1_lag1_10, m2_lag1_20, fail_expected=True) + + # Set a static FDB entry and make sure ping works again. + sw_lag1_10.add_br_fdb(str(m1_lag1_10.get_hwaddr()), self=True) + tl.ping_simple(m1_lag1_10, m2_lag1_20) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware") + + # Remove static FDB entry. Ping should fail. + sw_lag1_10.del_br_fdb(str(m1_lag1_10.get_hwaddr()), self=True) + tl.ping_simple(m1_lag1_10, m2_lag1_20, fail_expected=True) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware", False) + + # Enable learning_sync and make sure both FDBs are populated. + sw_lag1_10.set_br_learning(on=True, self=True) + sw_lag1_10.set_br_flooding(on=True, self=True) + sw_lag1_10.set_br_learning_sync(on=True, self=True) + tl.ping_simple(m1_lag1_10, m2_lag1_20) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software") + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware") + + sleep(20) + + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware", False) + + # Disable learning_sync and make sure only hardware FDB is populated. + sw_lag1_10.set_br_learning_sync(on=False, self=True) + tl.ping_simple(m1_lag1_10, m2_lag1_20) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware") + + # Remove port from bridge and add it back. Disable flooding and learning + # and make sure ping doesn't work. Note that port must be removed from + # bridge when the FDB entry exists only in the hardware table. Otherwise, + # bridge code will flush it himself, instead of driver. + sw_br.slave_del(sw_lag1_10.get_id()) + sw_br.slave_add(sw_lag1_10.get_id()) # Enables learning sync by default. + sw_lag1_10.set_br_learning(on=False, self=True) + sw_lag1_10.set_br_flooding(on=False, self=True) + tl.ping_simple(m1_lag1_10, m2_lag1_20, fail_expected=True) + + # Enable learning and make sure ping works again. + sw_lag1_10.set_br_learning(on=True, self=True) + tl.ping_simple(m1_lag1_10, m2_lag1_20) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software") + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware") + + sleep(20) + + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware", False) + + # Insert a static FDB entry and disable learning sync. Ping should work. + sw_lag1_10.add_br_fdb(str(m1_lag1_10.get_hwaddr()), self=True) + sw_lag1_10.set_br_learning_sync(on=False, self=True) + tl.ping_simple(m1_lag1_10, m2_lag1_20) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware") + + sleep(20) + + # Make sure static entry is not aged out. + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "software", False) + tl.check_fdb(sw_lag1_10, m1_lag1_10.get_hwaddr(), 0, "hardware") + + # Remove port from bridge and add it back. Disable flooding and learning + # and make sure ping doesn't work. Note that port must be removed from + # bridge when the FDB entry exists only in the hardware table. Otherwise, + # bridge code will flush it himself, instead of driver. Unlike the + # previous case, here we check if the driver correctly removes the static + # entry. + # XXX: This currently fails because firmware doesn't flush static FDBs. + # Uncomment it when it's introduced. + #sw_br.slave_del(sw_lag1_10.get_id()) + #sw_br.slave_add(sw_lag1_10.get_id()) + #sw_lag1_10.set_br_learning(on=False, self=True) + #sw_lag1_10.set_br_flooding(on=False, self=True) + #tl.ping_simple(m1_lag1_10, m2_lag1_20, fail_expected=True) + + # XXX: Cleanup because firmware doesn't do it. + sw_lag1_10.del_br_fdb(str(m1_lag1_10.get_hwaddr()), self=True) + +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("if2"), + ctl.get_host("machine2").get_interface("if1"), + ctl.get_host("machine2").get_interface("if2"), + 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-019-bridge_fdb_team_vlan1d.xml b/recipes/switchdev/l2-019-bridge_fdb_team_vlan1d.xml new file mode 100644 index 0000000..b2e3ca9 --- /dev/null +++ b/recipes/switchdev/l2-019-bridge_fdb_team_vlan1d.xml @@ -0,0 +1,26 @@ +<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" /> + <eth id="if2" label="B" /> + </interfaces> + </host> + <host id="machine2"> + <interfaces> + <eth id="if1" label="C" /> + <eth id="if2" label="D" /> + </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-019-bridge_fdb_team_vlan1d.py" /> +</lnstrecipe>
lnst-developers@lists.fedorahosted.org