[PATCH 0/5] Add switchdev SPAN recipe
by Yotam Gigi
Add the SPAN port mirroring recipe for switchdev, and several lnst
features that were missing and were needed for that recipe.
Among the features added:
- The lnst slave now cleans the tc qdiscs and filters at the clean
procedure.
- The PacketAssert module supports setting promiscuos flag.
- The Switchdev TestLib IcmpPing module supports setting ping
parameters.
The SPAN recipe consist of two machines connected via a bridge in the
switch, and pinging each other, while ingress/egress port mirrors are
added and tested.
Yotam Gigi (5):
Controller: Task: Add documentation for one of the flags in run func.
switchdev: TestLib: Add controllable parameters to IcmpPing module.
PacketAssert: Add the promiscuous optional param.
Slave: Add basic support for tc.
recipes: switchdev: Add the SPAN recipe.
lnst/Controller/Task.py | 2 +
lnst/Slave/InterfaceManager.py | 28 +++++++++
recipes/switchdev/TestLib.py | 10 ++--
recipes/switchdev/l2-021-span.py | 119 ++++++++++++++++++++++++++++++++++++++
recipes/switchdev/l2-021-span.xml | 26 +++++++++
test_modules/PacketAssert.py | 6 +-
6 files changed, 185 insertions(+), 6 deletions(-)
create mode 100644 recipes/switchdev/l2-021-span.py
create mode 100644 recipes/switchdev/l2-021-span.xml
--
2.4.11
7 years, 4 months
[PATCH v2 00/16] Quality of Service recipes
by Ido Schimmel
From: Ido Schimmel <idosch(a)mellanox.com>
Hi,
Patches 1-11 add the missing lldptool and devlink infrastructure to LNST
and also extend the PktgenTx module for the QoS recipes.
Patches 12-16 add the individual QoS recipes.
Please check the individual commit messages for more details.
Thanks.
v1->v2:
-------
* 01/16 - Replace lldpad enable / disable with generic service
enable / disable methods. Supports both Systemd and SysVinit based
systems (Ondrej)
* 03/16 - Return a dictionary of all the ethtool statistics instead
of just one stat (Ondrej)
* Make sure switchdev recipes set 'vlan_id' before 'vlan_p' in pktgen
options (Jan)
* Change the individual recipes according to the above changes
Ido Schimmel (16):
HostAPI: Add enable / disable service methods
HostAPI: Allow recipes to query number of CPUs
InterfaceAPI: Add ethtool statistics query
InterfaceAPI: Add LLDP support
InterfaceAPI: Add PAUSE frames setting methods
PktgenTx: Add per-thread options
PktgenTx: Remove all devices from all threads in init
recipes: switchdev: TestLib: Add wrappers for LLDP operations
recipes: switchdev: TestLib: Add wrappers for devlink operations
recipes: switchdev: TestLib: Add kwargs support for pktgen invocation
recipes: switchdev: TestLib: Set VLAN ID before PCP
recipes: switchdev: qos: Add recipe for PCP to PG mapping
recipes: switchdev: qos: Add recipe for PCP to TC mapping
recipes: switchdev: qos: Add recipe for PAUSE frames
recipes: switchdev: qos: Add recipe for PFC frames
recipes: switchdev: qos: Add recipe for ETS
lnst/Controller/Machine.py | 34 +++++++
lnst/Controller/Task.py | 21 +++++
lnst/Slave/InterfaceManager.py | 22 +++++
lnst/Slave/NetConfigDevice.py | 20 ++++
lnst/Slave/NetTestSlave.py | 54 +++++++++++
recipes/switchdev/TestLib.py | 168 +++++++++++++++++++++++++++++++++-
recipes/switchdev/default_aliases.xml | 4 +
recipes/switchdev/qos-001-pg.py | 71 ++++++++++++++
recipes/switchdev/qos-001-pg.xml | 22 +++++
recipes/switchdev/qos-002-tc.py | 71 ++++++++++++++
recipes/switchdev/qos-002-tc.xml | 22 +++++
recipes/switchdev/qos-003-pause.py | 91 ++++++++++++++++++
recipes/switchdev/qos-003-pause.xml | 22 +++++
recipes/switchdev/qos-004-pfc.py | 95 +++++++++++++++++++
recipes/switchdev/qos-004-pfc.xml | 22 +++++
recipes/switchdev/qos-005-ets.py | 133 +++++++++++++++++++++++++++
recipes/switchdev/qos-005-ets.xml | 22 +++++
test_modules/PktgenTx.py | 16 +++-
18 files changed, 904 insertions(+), 6 deletions(-)
create mode 100644 recipes/switchdev/qos-001-pg.py
create mode 100644 recipes/switchdev/qos-001-pg.xml
create mode 100644 recipes/switchdev/qos-002-tc.py
create mode 100644 recipes/switchdev/qos-002-tc.xml
create mode 100644 recipes/switchdev/qos-003-pause.py
create mode 100644 recipes/switchdev/qos-003-pause.xml
create mode 100644 recipes/switchdev/qos-004-pfc.py
create mode 100644 recipes/switchdev/qos-004-pfc.xml
create mode 100644 recipes/switchdev/qos-005-ets.py
create mode 100644 recipes/switchdev/qos-005-ets.xml
--
2.7.4
7 years, 5 months
[PATCH] regression-tests: add simple_macsec test
by Kamil Jerabek
This patch adds new test to phase3. The topology is the same as in
phase1 simple_netperf test.
This tests covers performance of macsec over ethernet. Ping and netperf is run.
Covered are both macsec options encrypt on and off.
Signed-off-by: Kamil Jerabek <kjerabek(a)redhat.com>
---
.../regression_tests/phase3/simple_macsec.README | 90 +++++++
recipes/regression_tests/phase3/simple_macsec.py | 280 +++++++++++++++++++++
recipes/regression_tests/phase3/simple_macsec.xml | 37 +++
3 files changed, 407 insertions(+)
create mode 100644 recipes/regression_tests/phase3/simple_macsec.README
create mode 100644 recipes/regression_tests/phase3/simple_macsec.py
create mode 100644 recipes/regression_tests/phase3/simple_macsec.xml
diff --git a/recipes/regression_tests/phase3/simple_macsec.README b/recipes/regression_tests/phase3/simple_macsec.README
new file mode 100644
index 0000000..571a659
--- /dev/null
+++ b/recipes/regression_tests/phase3/simple_macsec.README
@@ -0,0 +1,90 @@
+Topology:
+
+ switch
+ +------+
+ | |
+ | |
+ +-------------+ +-------------+
+ | | | |
+ | | | |
+ | +------+ |
+ | |
+ | |
+ +-+--+ +-+--+
++-------|eth1|------+ +-------|eth1|------+
+| +-+--+ | | +-+--+ |
+| | | |
+| | | |
+| | | |
+| | | |
+| | | |
+| host1 | | host2 |
+| | | |
+| | | |
+| | | |
++-------------------+ +-------------------+
+
+Number of hosts: 2
+Host #1 description:
+ One ethernet device configured with ip address {$net}.1/24
+
+ Macsec interface configured with ip addresses:
+ 192.168.100.1/24
+ fc00::1/64
+
+Host #2 description:
+ One ethernet device configured with ip address {$net}.2/24
+
+ Macsec interface configured with ip addresses:
+ 192.168.100.2/24
+ fc00::2/64
+
+Test name:
+ simple_macsec.py
+Test description:
+ Ping:
+ + count: 100
+ + interval: 0.1s
+ + between physical interfaces expecting PASS
+ + between macsec interfaces expecting PASS
+ Ping6:
+ + count: 100
+ + interval: 0.1s
+ + between macsec interfaces expecting PASS
+ Netperf:
+ + duration: 60s
+ + TCP_STREAM and UDP_STREAM
+ + ipv4 and ipv6
+ + between physical interfaces
+ Macsec
+ + tested both encryption on and off
+
+PerfRepo integration:
+ First, preparation in PerfRepo is required - you need to create Test objects
+ through the web interface that properly describe the individual Netperf
+ tests that this recipe runs. Don't forget to also add appropriate metrics.
+ For these Netperf tests it's always:
+ * throughput
+ * throughput_min
+ * throughput_max
+ * throughput_deviation
+
+ After that, to enable support for PerfRepo you need to create the file
+ vxlan_remote.mapping and define the following id mappings:
+ tcp_ipv4_id -> to store ipv4 TCP_STREAM Netperf test results, maps to TestUid of a PerfRepo Test object
+ tcp_ipv6_id -> to store ipv6 TCP_STREAM Netperf test results, maps to TestUid of a PerfRepo Test object
+ udp_ipv4_id -> to store ipv4 UDP_STREAM Netperf test results, maps to TestUid of a PerfRepo Test object
+ udp_ipv6_id -> to store ipv4 UDP_STREAM Netperf test results, maps to TestUid of a PerfRepo Test object
+
+ To enable result comparison agains baselines you need to create a Report in
+ PerfRepo that will store the baseline. Set up the Report to only contain results
+ with the same hash tag and then add a new mapping to the mapping file, with
+ this format:
+ <some_hash> = <report_id>
+
+ The hash value is automatically generated during test execution and added
+ to each result stored in PerfRepo. To get the Report id you need to open
+ that report in our browser and find if in the URL.
+
+ When running this recipe you should also define the 'product_name' alias
+ (e.g. RHEL7) in order to tag the result object in PerfRepo.
diff --git a/recipes/regression_tests/phase3/simple_macsec.py b/recipes/regression_tests/phase3/simple_macsec.py
new file mode 100644
index 0000000..9cd9c56
--- /dev/null
+++ b/recipes/regression_tests/phase3/simple_macsec.py
@@ -0,0 +1,280 @@
+from lnst.Controller.Task import ctl
+from lnst.Controller.PerfRepoUtils import perfrepo_baseline_to_dict
+from lnst.Controller.PerfRepoUtils import netperf_result_template
+
+from lnst.RecipeCommon.ModuleWrap import ping, ping6, netperf
+from lnst.RecipeCommon.IRQ import pin_dev_irqs
+from lnst.RecipeCommon.PerfRepo import generate_perfrepo_comment
+
+# ------
+# SETUP
+# ------
+
+mapping_file = ctl.get_alias("mapping_file")
+perf_api = ctl.connect_PerfRepo(mapping_file)
+
+product_name = ctl.get_alias("product_name")
+
+m1 = ctl.get_host("machine1")
+m2 = ctl.get_host("machine2")
+
+m1.sync_resources(modules=["IcmpPing", "Icmp6Ping", "Netperf"])
+m2.sync_resources(modules=["IcmpPing", "Icmp6Ping", "Netperf"])
+
+# ------
+# TESTS
+# ------
+
+ipv = ctl.get_alias("ipv")
+mtu = ctl.get_alias("mtu")
+netperf_duration = int(ctl.get_alias("netperf_duration"))
+nperf_reserve = int(ctl.get_alias("nperf_reserve"))
+nperf_confidence = ctl.get_alias("nperf_confidence")
+nperf_max_runs = int(ctl.get_alias("nperf_max_runs"))
+nperf_cpupin = ctl.get_alias("nperf_cpupin")
+nperf_cpu_util = ctl.get_alias("nperf_cpu_util")
+nperf_num_parallel = int(ctl.get_alias("nperf_num_parallel"))
+nperf_debug = ctl.get_alias("nperf_debug")
+nperf_max_dev = ctl.get_alias("nperf_max_dev")
+pr_user_comment = ctl.get_alias("perfrepo_comment")
+
+pr_comment = generate_perfrepo_comment([m1, m2], pr_user_comment)
+
+m1_phy = m1.get_interface("eth")
+m2_phy = m2.get_interface("eth")
+
+m1_phy_name = m1_phy.get_devname()
+m2_phy_name = m2_phy.get_devname()
+
+m1_phy_addr = m1_phy.get_ip()
+m2_phy_addr = m2_phy.get_ip()
+
+m1_phy_hwaddr = m1_phy.get_hwaddr()
+m2_phy_hwaddr = m2_phy.get_hwaddr()
+
+key1 = "7a16780284000775d4f0a3c0f0e092c0"
+key2 = "3212ef5c4cc5d0e4210b17208e88779e"
+
+msec_tif_name = "macsec0"
+m1_tif_addr = "192.168.100.1"
+m2_tif_addr = "192.168.100.2"
+
+m1_tif_addr6 = "fc00::1"
+m2_tif_addr6 = "fc00::2"
+
+#macsec setup
+def macsecSetup(encryption):
+ m1.run("ip link add link %s %s type macsec encrypt %s" %
+ (m1_phy_name, msec_tif_name, encryption))
+ m1.run("ip macsec add %s rx port 1 address %s" % (msec_tif_name, m2_phy_hwaddr))
+ m1.run("ip macsec add %s tx sa 0 pn 1 on key 00 %s" % (msec_tif_name, key1))
+ m1.run("ip macsec add %s rx port 1 address %s sa 0 pn 1 on key 01 %s" %
+ (msec_tif_name, m2_phy_hwaddr, key2))
+
+ m2.run("ip link add link %s %s type macsec encrypt %s" %
+ (m2_phy_name, msec_tif_name, encryption))
+ m2.run("ip macsec add %s rx port 1 address %s" % (msec_tif_name, m1_phy_hwaddr))
+ m2.run("ip macsec add %s tx sa 0 pn 1 on key 01 %s" % (msec_tif_name, key2))
+ m2.run("ip macsec add %s rx port 1 address %s sa 0 pn 1 on key 00 %s" %
+ (msec_tif_name, m1_phy_hwaddr, key1))
+
+ m1.run("ip link set %s up" % msec_tif_name)
+ m2.run("ip link set %s up" % msec_tif_name)
+
+ m1.run("ip addr add %s/24 dev %s" % (m1_tif_addr, msec_tif_name))
+ m2.run("ip addr add %s/24 dev %s" % (m2_tif_addr, msec_tif_name))
+
+ m1.run("ip -6 addr add %s/64 dev %s" % (m1_tif_addr6, msec_tif_name))
+ m2.run("ip -6 addr add %s/64 dev %s" % (m2_tif_addr6, msec_tif_name))
+
+
+if nperf_cpupin:
+ m1.run("service irqbalance stop")
+ m2.run("service irqbalance stop")
+
+ dev_list = [(m1, m1_phy), (m2, m2_phy)]
+
+ # this will pin devices irqs to cpu #0
+ for m, d in dev_list:
+ pin_dev_irqs(m, d, 0)
+
+nperf_opts = ""
+if nperf_cpupin and nperf_num_parallel == 1:
+ nperf_opts = " -T%s,%s" % (nperf_cpupin, nperf_cpupin)
+
+ctl.wait(15)
+
+ping_opts = {"count": 100, "interval": 0.1}
+
+encryption_settings = ['on', 'off']
+
+for setting in encryption_settings:
+ #macsec setup
+ macsecSetup(setting)
+ m1_tif = m1.get_device(msec_tif_name)
+ m2_tif = m2.get_device(msec_tif_name)
+
+ if ipv in [ 'ipv4', 'both' ]:
+ ping((m1, m1_tif, 0, {"scope": 0}),
+ (m2, m2_tif, 0, {"scope": 0}),
+ options=ping_opts)
+
+ ctl.wait(2)
+
+ ping((m1, m1_phy, 0, {"scope": 0}),
+ (m2, m2_phy, 0, {"scope": 0}),
+ options=ping_opts)
+
+ ctl.wait(2)
+
+ # prepare PerfRepo result for tcp
+ result_tcp = perf_api.new_result("tcp_ipv4_id",
+ "tcp_ipv4_result",
+ hash_ignore=[
+ r'kernel_release',
+ r'redhat_release'])
+ result_tcp.add_tag(product_name)
+ if nperf_num_parallel > 1:
+ result_tcp.add_tag("multithreaded")
+ result_tcp.set_parameter('num_parallel', nperf_num_parallel)
+
+ result_tcp.set_parameter('encryption', setting)
+
+ baseline = perf_api.get_baseline_of_result(result_tcp)
+ baseline = perfrepo_baseline_to_dict(baseline)
+
+ tcp_res_data = netperf((m1, m1_tif, 0, {"scope": 0}),
+ (m2, m2_tif, 0, {"scope": 0}),
+ client_opts={"duration" : netperf_duration,
+ "testname" : "TCP_STREAM",
+ "confidence" : nperf_confidence,
+ "num_parallel" : nperf_num_parallel,
+ "cpu_util" : nperf_cpu_util,
+ "runs": nperf_max_runs,
+ "debug": nperf_debug,
+ "max_deviation": nperf_max_dev,
+ "netperf_opts": nperf_opts},
+ baseline = baseline,
+ timeout = (netperf_duration + nperf_reserve)*nperf_max_runs)
+
+ netperf_result_template(result_tcp, tcp_res_data)
+ result_tcp.set_comment(pr_comment)
+ perf_api.save_result(result_tcp)
+
+ # prepare PerfRepo result for udp
+ result_udp = perf_api.new_result("udp_ipv4_id",
+ "udp_ipv4_result",
+ hash_ignore=[
+ r'kernel_release',
+ r'redhat_release'])
+ result_udp.add_tag(product_name)
+ if nperf_num_parallel > 1:
+ result_udp.add_tag("multithreaded")
+ result_udp.set_parameter('num_parallel', nperf_num_parallel)
+
+ result_udp.set_parameter('encryption', setting)
+
+ baseline = perf_api.get_baseline_of_result(result_udp)
+ baseline = perfrepo_baseline_to_dict(baseline)
+
+ udp_res_data = netperf((m1, m1_tif, 0, {"scope": 0}),
+ (m2, m2_tif, 0, {"scope": 0}),
+ client_opts={"duration" : netperf_duration,
+ "testname" : "UDP_STREAM",
+ "confidence" : nperf_confidence,
+ "num_parallel" : nperf_num_parallel,
+ "cpu_util" : nperf_cpu_util,
+ "runs": nperf_max_runs,
+ "debug": nperf_debug,
+ "max_deviation": nperf_max_dev,
+ "netperf_opts": nperf_opts},
+ baseline = baseline,
+ timeout = (netperf_duration + nperf_reserve)*nperf_max_runs)
+
+ netperf_result_template(result_udp, udp_res_data)
+ result_udp.set_comment(pr_comment)
+ perf_api.save_result(result_udp)
+
+
+ if ipv in [ 'ipv6', 'both' ]:
+ ping6((m1, m1_tif, 1, {"scope": 0}),
+ (m2, m2_tif, 1, {"scope": 0}),
+ options=ping_opts)
+
+ ctl.wait(2)
+
+ # prepare PerfRepo result for tcp ipv6
+ result_tcp = perf_api.new_result("tcp_ipv6_id",
+ "tcp_ipv6_result",
+ hash_ignore=[
+ r'kernel_release',
+ r'redhat_release'])
+ result_tcp.add_tag(product_name)
+ if nperf_num_parallel > 1:
+ result_tcp.add_tag("multithreaded")
+ result_tcp.set_parameter('num_parallel', nperf_num_parallel)
+
+ result_tcp.set_parameter('encryption', setting)
+
+ baseline = perf_api.get_baseline_of_result(result_tcp)
+ baseline = perfrepo_baseline_to_dict(baseline)
+
+ tcp_res_data = netperf((m1, m1_tif, 1, {"scope": 0}),
+ (m2, m2_tif, 1, {"scope": 0}),
+ client_opts={"duration" : netperf_duration,
+ "testname" : "TCP_STREAM",
+ "confidence" : nperf_confidence,
+ "num_parallel" : nperf_num_parallel,
+ "cpu_util" : nperf_cpu_util,
+ "runs": nperf_max_runs,
+ "debug": nperf_debug,
+ "max_deviation": nperf_max_dev,
+ "netperf_opts" : nperf_opts + " -6"},
+ baseline = baseline,
+ timeout = (netperf_duration + nperf_reserve)*nperf_max_runs)
+
+ netperf_result_template(result_tcp, tcp_res_data)
+ result_tcp.set_comment(pr_comment)
+ perf_api.save_result(result_tcp)
+
+ # prepare PerfRepo result for udp ipv6
+ result_udp = perf_api.new_result("udp_ipv6_id",
+ "udp_ipv6_result",
+ hash_ignore=[
+ r'kernel_release',
+ r'redhat_release'])
+ result_udp.add_tag(product_name)
+ if nperf_num_parallel > 1:
+ result_udp.add_tag("multithreaded")
+ result_udp.set_parameter('num_parallel', nperf_num_parallel)
+
+ result_udp.set_parameter('encryption', setting)
+
+ baseline = perf_api.get_baseline_of_result(result_udp)
+ baseline = perfrepo_baseline_to_dict(baseline)
+
+ udp_res_data = netperf((m1, m1_tif, 1, {"scope": 0}),
+ (m2, m2_tif, 1, {"scope": 0}),
+ client_opts={"duration" : netperf_duration,
+ "testname" : "UDP_STREAM",
+ "confidence" : nperf_confidence,
+ "num_parallel" : nperf_num_parallel,
+ "cpu_util" : nperf_cpu_util,
+ "runs": nperf_max_runs,
+ "debug": nperf_debug,
+ "max_deviation": nperf_max_dev,
+ "netperf_opts" : nperf_opts + "-6"},
+ baseline = baseline,
+ timeout = (netperf_duration + nperf_reserve)*nperf_max_runs)
+
+ netperf_result_template(result_udp, udp_res_data)
+ result_udp.set_comment(pr_comment)
+ perf_api.save_result(result_udp)
+
+
+ m1.run("ip link delete %s" % msec_tif_name)
+ m2.run("ip link delete %s" % msec_tif_name)
+
+if nperf_cpupin:
+ m1.run("service irqbalance start")
+ m2.run("service irqbalance start")
diff --git a/recipes/regression_tests/phase3/simple_macsec.xml b/recipes/regression_tests/phase3/simple_macsec.xml
new file mode 100644
index 0000000..275db4a
--- /dev/null
+++ b/recipes/regression_tests/phase3/simple_macsec.xml
@@ -0,0 +1,37 @@
+<lnstrecipe>
+ <define>
+ <alias name="ipv" value="both" />
+ <alias name="mtu" value="1500" />
+ <alias name="netperf_duration" value="60" />
+ <alias name="nperf_reserve" value="20" />
+ <alias name="nperf_confidence" value="99,5" />
+ <alias name="nperf_max_runs" value="5" />
+ <alias name="nperf_mode" value="default" />
+ <alias name="nperf_num_parallel" value="2" />
+ <alias name="nperf_debug" value="0"/>
+ <alias name="nperf_max_dev" value="20%"/>
+ <alias name="mapping_file" value="simple_macsec.mapping" />
+ <alias name="net" value="192.168.0" />
+ </define>
+ <network>
+ <host id="machine1">
+ <interfaces>
+ <eth id="eth" label="tnet">
+ <addresses>
+ <address>{$net}.1/24</address>
+ </addresses>
+ </eth>
+ </interfaces>
+ </host>
+ <host id="machine2">
+ <interfaces>
+ <eth id="eth" label="tnet">
+ <addresses>
+ <address>{$net}.2/24</address>
+ </addresses>
+ </eth>
+ </interfaces>
+ </host>
+ </network>
+ <task python="simple_macsec.py"/>
+</lnstrecipe>
--
2.5.5
7 years, 5 months
[PATCH v2 0/4] various minor bug fixes
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
This patchset includes various minor bugfixes for different parts of LNST.
It's technically a second version of the patchset, the first one didn't have a
cover letter...
Changes in
v2: * in [PATCH 3/4] i removed unnecessary checks in NetTestSlave and modified
the checks in the InterfaceManager
* added the 4th patch that fixes the 'default' behaviour of the
get_multi_opt method
Ondrej Lichtner (4):
NmConfigDevice: move name values to 'connection' dicts
NetTestSlave: fix SlaveMethods return values
Slave: deconfigure only created interfaces
TestsCommon: fix 'default' behaviour of get_multi_opt
lnst/Common/TestsCommon.py | 9 +++------
lnst/Slave/InterfaceManager.py | 9 ++++++---
lnst/Slave/NetTestSlave.py | 8 ++++----
lnst/Slave/NmConfigDevice.py | 12 +++++-------
4 files changed, 18 insertions(+), 20 deletions(-)
--
2.10.0
7 years, 5 months
[PATCH v3] {Net, Nm}ConfigDevice: split up() into up+address_setup
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
The up() methods of NetConfigDevice and NmConfigDevice derived classes
handled both setting the device up and applying ip addresses (activating
connections, with ip addresses). Unfortunately this approach causes
problems when using NM to configure interfaces in master-slave
relationships (e.g. bond with ipv6 address and simple ethernet with no
configuration).
The solution to our NM related issues was to activate all connections
without ip address configuration, then add ip addresses to the
connections and call Reapply().
For this to work properly I also split the corresponding up() method in
NetConfigDevice classes so that the interfaces are compatible.
I split the inverse down() method into address_cleanup+down for
consistency.
This commit also propagates these changes to the rest of the LNST code
that needs to now use these new methods.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
v2: override address_{setup, cleanup} methods of the UnusedInterface
class to fix a bug that left the Slave in an unusable state
v3: remove the workaround for L2 ethernet connections - this now works,
but having the workaround there breaks the other changes introduced
in this commit
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/Machine.py | 12 +++++
lnst/Controller/NetTestController.py | 3 ++
lnst/Slave/InterfaceManager.py | 9 ++++
lnst/Slave/NetConfigDevice.py | 36 ++++++++++++---
lnst/Slave/NetTestSlave.py | 14 ++++++
lnst/Slave/NmConfigDevice.py | 85 +++++++++++++++++++++++++-----------
6 files changed, 127 insertions(+), 32 deletions(-)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index 70295ba..204a1a8 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -835,6 +835,12 @@ class Interface(object):
def down(self):
self._machine._rpc_call_x(self._netns, "set_device_down", self._id)
+ def address_setup(self):
+ self._machine._rpc_call_x(self._netns, "device_address_setup", self._id)
+
+ def address_cleanup(self):
+ self._machine._rpc_call_x(self._netns, "device_address_cleanup", self._id)
+
def set_link_up(self):
self._machine._rpc_call_x(self._netns, "set_link_up", self._id)
@@ -1214,6 +1220,12 @@ class UnusedInterface(Interface):
def down(self):
pass
+ def address_setup(self):
+ pass
+
+ def address_cleanup(self):
+ pass
+
def cleanup(self):
pass
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index a040933..860f727 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -225,6 +225,9 @@ class NetTestController:
for iface in ifaces:
iface.up()
+ for iface in ifaces:
+ iface.address_setup()
+
m.wait_interface_init()
def provision_machines(self):
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index 3dc3314..949817c 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -566,6 +566,7 @@ class Device(object):
m_dev.clear_configuration()
if self._conf != None:
+ self.address_cleanup()
self.down()
self.deconfigure()
self._clear_tc_qdisc()
@@ -652,6 +653,14 @@ class Device(object):
else:
exec_cmd("ip link set %s down" % self._name)
+ def address_setup(self):
+ if self._conf != None:
+ self._conf.address_setup()
+
+ def address_cleanup(self):
+ if self._conf != None:
+ self._conf.address_cleanup()
+
def link_up(self):
exec_cmd("ip link set %s up" % self._name)
diff --git a/lnst/Slave/NetConfigDevice.py b/lnst/Slave/NetConfigDevice.py
index 960ff07..152764b 100644
--- a/lnst/Slave/NetConfigDevice.py
+++ b/lnst/Slave/NetConfigDevice.py
@@ -57,18 +57,24 @@ class NetConfigDeviceGeneric(object):
def up(self):
config = self._dev_config
+ exec_cmd("ip link set %s up" % config["name"])
+
+ def down(self):
+ config = self._dev_config
+ exec_cmd("ip link set %s down" % config["name"])
+
+ def address_setup(self):
+ config = self._dev_config
if "addresses" in config:
for address in config["addresses"]:
exec_cmd("ip addr add %s dev %s" % (address, config["name"]))
- exec_cmd("ip link set %s up" % config["name"])
- def down(self):
+ def address_cleanup(self):
config = self._dev_config
if "addresses" in config:
for address in config["addresses"]:
exec_cmd("ip addr del %s dev %s" % (address, config["name"]),
die_on_err=False)
- exec_cmd("ip link set %s down" % config["name"])
def set_addresses(self, ips):
self._dev_config["addresses"] = ips
@@ -432,9 +438,6 @@ class NetConfigDeviceOvsBridge(NetConfigDeviceGeneric):
int_ports = self._dev_config["ovs_conf"]["internals"]
br_name = self._dev_config["name"]
for iport in int_ports:
- if "addresses" in iport:
- for address in iport["addresses"]:
- exec_cmd("ip addr add %s dev %s" % (address, iport["name"]))
exec_cmd("ip link set %s up" % iport["name"])
def down(self):
@@ -448,6 +451,27 @@ class NetConfigDeviceOvsBridge(NetConfigDeviceGeneric):
super(NetConfigDeviceOvsBridge, self).down()
+ def address_setup(self):
+ super(NetConfigDeviceOvsBridge, self).up()
+
+ int_ports = self._dev_config["ovs_conf"]["internals"]
+ br_name = self._dev_config["name"]
+ for iport in int_ports:
+ if "addresses" in iport:
+ for address in iport["addresses"]:
+ exec_cmd("ip addr add %s dev %s" % (address, iport["name"]))
+
+ def address_cleanup(self):
+ super(NetConfigDeviceOvsBridge, self).up()
+
+ int_ports = self._dev_config["ovs_conf"]["internals"]
+ br_name = self._dev_config["name"]
+ for iport in int_ports:
+ if "addresses" in iport:
+ for address in iport["addresses"]:
+ exec_cmd("ip addr del %s dev %s" % (address, iport["name"]),
+ die_on_err=False)
+
@classmethod
def type_init(self):
super(NetConfigDeviceOvsBridge, self).type_init()
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index f0b3183..da1e2f4 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -254,6 +254,20 @@ class SlaveMethods:
return False
return True
+ def device_address_setup(self, if_id):
+ dev = self._if_manager.get_mapped_device(if_id)
+ dev.address_setup()
+ return True
+
+ def device_address_cleanup(self, if_id):
+ dev = self._if_manager.get_mapped_device(if_id)
+ if dev is not None:
+ dev.address_cleanup()
+ else:
+ logging.error("Device with id '%s' not found." % if_id)
+ return False
+ return True
+
def set_link_up(self, if_id):
dev = self._if_manager.get_mapped_device(if_id)
if dev is not None:
diff --git a/lnst/Slave/NmConfigDevice.py b/lnst/Slave/NmConfigDevice.py
index a9e0c1f..8f9170e 100644
--- a/lnst/Slave/NmConfigDevice.py
+++ b/lnst/Slave/NmConfigDevice.py
@@ -133,6 +133,34 @@ class NmConfigDeviceGeneric(object):
if self._connection_added:
self._nm_deactivate_connection()
+ def address_setup(self):
+ config = self._dev_config
+
+ if len(config["addresses"]) == 0:
+ return
+ else:
+ s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
+
+ self._connection["ipv4"] = s_ipv4
+ self._connection["ipv6"] = s_ipv6
+
+ self._nm_update_connection()
+
+ self._nm_reapply_connection()
+
+ def address_cleanup(self):
+ if self._connection['ipv4']['method'] == 'disabled' and\
+ self._connection['ipv6']['method'] == 'ignore':
+ return
+
+ self._connection["ipv4"] = dbus.Dictionary({'method': 'disabled'},
+ signature='sv')
+ self._connection["ipv6"] = dbus.Dictionary({'method': 'ignore'},
+ signature='sv')
+ self._nm_update_connection()
+
+ self._nm_reapply_connection()
+
@classmethod
def type_init(self):
pass
@@ -217,13 +245,6 @@ class NmConfigDeviceGeneric(object):
return (s_ipv4, s_ipv6)
def _nm_add_connection(self):
- #NM will succesfully add this connection but is unable to activate it...
- if self._connection["ipv4"]["method"] == "disabled" and\
- self._connection["ipv6"]["method"] == "ignore" and\
- "master" not in self._connection["connection"] and\
- self._connection["connection"]["type"] == "802-3-ethernet":
- return
-
if not self._connection_added:
bus = self._bus
settings_obj = bus.get_object(NM_BUS, OBJ_PRE + "/Settings")
@@ -302,6 +323,26 @@ class NmConfigDeviceGeneric(object):
raise e
self._acon_obj_path = None
+ def _nm_reapply_connection(self):
+ if self._acon_obj_path == None:
+ return
+
+ config = self._dev_config
+
+ bus = self._bus
+ nm_if = self._nm_if
+
+ try:
+ device_obj_path = nm_if.GetDeviceByIpIface(config["name"])
+ except:
+ logging.error("Device needed to reapply connection doesn't exist")
+ return
+
+ dev_obj = bus.get_object(NM_BUS, device_obj_path)
+ dev_if = dbus.Interface(dev_obj, IF_PRE + ".Device")
+
+ dev_if.Reapply("", 0, 0)
+
def nm_enslave(self, slave_type, master_uuid, slave_conf):
if get_nm_version() < "1.0.0":
self._connection["connection"]["slave_type"] = slave_type
@@ -367,8 +408,6 @@ class NmConfigDeviceEth(NmConfigDeviceGeneric):
hw_addr = self._convert_hwaddr(config)
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
-
s_eth = dbus.Dictionary({'mac-address': hw_addr}, signature='sv')
s_con = dbus.Dictionary({
'type': '802-3-ethernet',
@@ -379,8 +418,9 @@ class NmConfigDeviceEth(NmConfigDeviceGeneric):
connection = dbus.Dictionary({
'802-3-ethernet': s_eth,
'connection': s_con,
- 'ipv4': s_ipv4,
- 'ipv6': s_ipv6}, signature='sa{sv}')
+ 'ipv4': dbus.Dictionary({'method': 'disabled'}, signature='sv'),
+ 'ipv6': dbus.Dictionary({'method': 'ignore'}, signature='sv'),
+ }, signature='sa{sv}')
self._connection = connection
self._nm_add_connection()
@@ -468,12 +508,11 @@ class NmConfigDeviceBond(NmConfigDeviceGeneric):
s_bond = dbus.Dictionary({
'interface-name': config["name"]})
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
connection = dbus.Dictionary({
'bond': s_bond,
- 'ipv4': s_ipv4,
- 'ipv6': s_ipv6,
+ 'ipv4': dbus.Dictionary({'method': 'disabled'}, signature='sv'),
+ 'ipv6': dbus.Dictionary({'method': 'ignore'}, signature='sv'),
'connection': s_bond_con})
self._connection = connection
@@ -559,12 +598,10 @@ class NmConfigDeviceBridge(NmConfigDeviceGeneric):
'interface-name': config["name"],
'stp': dbus.Boolean(False)})
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
-
connection = dbus.Dictionary({
'bridge': s_bridge,
- 'ipv4': s_ipv4,
- 'ipv6': s_ipv6,
+ 'ipv4': dbus.Dictionary({'method': 'disabled'}, signature='sv'),
+ 'ipv6': dbus.Dictionary({'method': 'ignore'}, signature='sv'),
'connection': s_bridge_con})
self._connection = connection
@@ -686,12 +723,10 @@ class NmConfigDeviceVlan(NmConfigDeviceGeneric):
'parent': realdev,
'id': dbus.UInt32(vlan_tci)}, signature="sv")
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
-
connection = dbus.Dictionary({
'vlan': s_vlan,
- 'ipv4': s_ipv4,
- 'ipv6': s_ipv6,
+ 'ipv4': dbus.Dictionary({'method': 'disabled'}, signature='sv'),
+ 'ipv6': dbus.Dictionary({'method': 'ignore'}, signature='sv'),
'connection': s_vlan_con})
self._connection = connection
@@ -770,12 +805,10 @@ class NmConfigDeviceTeam(NmConfigDeviceGeneric):
'interface-name': config["name"],
'config': teamd_config})
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
-
connection = dbus.Dictionary({
'team': s_team,
- 'ipv4': s_ipv4,
- 'ipv6': s_ipv6,
+ 'ipv4': dbus.Dictionary({'method': 'disabled'}, signature='sv'),
+ 'ipv6': dbus.Dictionary({'method': 'ignore'}, signature='sv'),
'connection': s_team_con})
self._connection = connection
--
2.10.0
7 years, 5 months
[ANNOUNCEMENT] Feature freeze of master branch
by Ondrej Lichtner
Hi everyone,
as promised 2 weeks ago, today marks the day that we stop accepting
patches related to new features on the master branch.
Next week I want to work on doing a v12 release and update the related
packages. I still have a couple of my own bug fix patches that I've sent
to the list but haven't had a chance to apply yet, so that will also
happen next week.
If anyone has any patches fixing bugs and wants them in the next
release, please send them as soon as possible or at least let us know
you're working on something.
After the release we're still going to be accepting bug fixes for a
possible v13 release and we'll also accept new recipes.
Main development will now focus on the 'next' branch where we want to
get going with implementation of pure Python recipes.
Thanks,
-Ondrej
7 years, 5 months
meeting minutes 2016-09-26
by Jan Tluka
Ondrej, Jan, Ido, Yotam
master branch freeze will be at the end of the week
seems that no new features are expected, if you have anything really
important (crash fixes) send ASAP and let Ondrej know
next week Ondrej will create scratch rpms to test
guys from Mellanox will be unavailable (Tokyo), Ido promised to test
the rpms for Mellanox
we still have one regression test failing (test 28) due to change in
logging
we will modify the test to make it pass (remove the log check)
the proposed enhancements will be done in next branch
lnst incompatibility with latest pyroute version (0.4.x)
default in Fedora - does it work? Mellanox have no issues with lnst
upstream version + dnf install
check with peet (svinota at #lnst)
python/python3 name changes in dependent packages
python-pyroute2 => python2-pyroute2 for python2
python-pyroute2 for python3
jtluka to follow up on this issue
7 years, 5 months
[PATCH 1/3] NmConfigDevice: move name values to 'connection' dicts
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
The 'interface-name' value in device specific dictionaries was moved
into the general 'connection' dict. The old attributes are still
supported by NM (for compatibility) but since we don't use older NM
versions anymore I'm moving these to their proper place.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Slave/NmConfigDevice.py | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/lnst/Slave/NmConfigDevice.py b/lnst/Slave/NmConfigDevice.py
index 8f9170e..29c2c75 100644
--- a/lnst/Slave/NmConfigDevice.py
+++ b/lnst/Slave/NmConfigDevice.py
@@ -494,6 +494,7 @@ class NmConfigDeviceBond(NmConfigDeviceGeneric):
s_bond_con = dbus.Dictionary({
'type': 'bond',
+ 'interface-name': config["name"],
'autoconnect': dbus.Boolean(False),
'uuid': config["master_uuid"],
'id': config["name"]+"_con"})
@@ -502,12 +503,9 @@ class NmConfigDeviceBond(NmConfigDeviceGeneric):
if options:
s_bond = dbus.Dictionary({
- 'interface-name': config["name"],
'options': options})
else:
- s_bond = dbus.Dictionary({
- 'interface-name': config["name"]})
-
+ s_bond = dbus.Dictionary({})
connection = dbus.Dictionary({
'bond': s_bond,
@@ -591,11 +589,11 @@ class NmConfigDeviceBridge(NmConfigDeviceGeneric):
s_bridge_con = dbus.Dictionary({
'type': 'bridge',
'autoconnect': dbus.Boolean(False),
+ 'interface-name': config["name"],
'uuid': config["master_uuid"],
'id': config["name"]+"_con"})
s_bridge = dbus.Dictionary({
- 'interface-name': config["name"],
'stp': dbus.Boolean(False)})
connection = dbus.Dictionary({
@@ -715,11 +713,11 @@ class NmConfigDeviceVlan(NmConfigDeviceGeneric):
s_vlan_con = dbus.Dictionary({
'type': 'vlan',
'autoconnect': dbus.Boolean(False),
+ 'interface-name': dev_name,
'uuid': str(uuid.uuid4()),
'id': dev_name+"_con"})
s_vlan = dbus.Dictionary({
- 'interface-name': dev_name,
'parent': realdev,
'id': dbus.UInt32(vlan_tci)}, signature="sv")
@@ -796,13 +794,13 @@ class NmConfigDeviceTeam(NmConfigDeviceGeneric):
s_team_con = dbus.Dictionary({
'type': 'team',
'autoconnect': dbus.Boolean(False),
+ 'interface-name': config["name"],
'uuid': config["master_uuid"],
'id': config["name"]+"_con"})
teamd_config = get_option(config, "teamd_config")
s_team = dbus.Dictionary({
- 'interface-name': config["name"],
'config': teamd_config})
connection = dbus.Dictionary({
--
2.10.0
7 years, 5 months
[PATCH] SlavePool: ignore empty parameters on matching
by Jan Tluka
This should help when a user needs to bypass a parameter in requirements.
For example the default value of interface's driver parameter is ixgbe
and the user wants to run on any interface no matter what's in slave pool.
Without this fix it's impossible to do that other than editing the slave
pool xml files directly.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
lnst/Controller/SlavePool.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index 13cc34e..67ccd63 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -599,6 +599,9 @@ class SetupMapper(object):
req_machine = self._mreqs[req_id]
pool_machine = self._pool[pool_id]
for param, value in req_machine["params"].iteritems():
+ # skip empty parameters
+ if len(value) == 0:
+ continue
if param not in pool_machine["params"] or\
value != pool_machine["params"][param]:
return False
@@ -614,6 +617,9 @@ class SetupMapper(object):
req_label != req_if["network"]:
return False
for param, value in req_if["params"].iteritems():
+ # skip empty parameters
+ if len(value) == 0:
+ continue
if param not in pool_if["params"] or\
value != pool_if["params"][param]:
return False
--
2.4.11
7 years, 5 months
[PATCH] Task: handle exceptions from PerfRepo RestAPI
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
Exceptions raised by the PerfRepo library currently cause the entire
test to stop. This commit changes the behaviour by catching all these
exceptions, logging them with log level ERROR and returning to test
execution. This way the test will continue so that the tester can at
least manually confirm the results even when the result/baseline
database is unreachable.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/Task.py | 42 +++++++++++++++++++++++++++++++++---------
1 file changed, 33 insertions(+), 9 deletions(-)
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py
index f9a15f2..019acc2 100644
--- a/lnst/Controller/Task.py
+++ b/lnst/Controller/Task.py
@@ -867,9 +867,17 @@ class PerfRepoAPI(object):
logging.debug("Test key '%s' mapped to id '%s'" % (mapping_key,
mapping_id))
- test = self._rest_api.test_get_by_id(mapping_id, log=False)
+ try:
+ test = self._rest_api.test_get_by_id(mapping_id, log=False)
+ except Exception as e:
+ test = None
+ logging.error(str(e))
if test is None:
- test = self._rest_api.test_get_by_uid(mapping_id, log=False)
+ try:
+ test = self._rest_api.test_get_by_uid(mapping_id, log=False)
+ except Exception as e:
+ test = None
+ logging.error(str(e))
if test is not None:
test_url = self._rest_api.get_obj_url(test)
@@ -897,7 +905,11 @@ class PerfRepoAPI(object):
logging.debug("Adding hash '%s' as tag to result." % h)
result.add_tag(h)
logging.info("Sending TestExecution to PerfRepo.")
- self._rest_api.testExecution_create(result.get_testExecution())
+ try:
+ self._rest_api.testExecution_create(result.get_testExecution())
+ except Exception as e:
+ logging.error(str(e))
+ return
report_id = self._mapping.get_id(h)
if not report_id and result.get_testExecution().get_id() != None:
@@ -928,7 +940,11 @@ class PerfRepoAPI(object):
if report_id is None or not self.connected():
return Noop()
- report = self._rest_api.report_get_by_id(report_id, log=False)
+ try:
+ report = self._rest_api.report_get_by_id(report_id, log=False)
+ except Exception as e:
+ report = None
+ logging.error(str(e))
if report is None:
logging.debug("No report with id %s found!" % report_id)
return Noop()
@@ -943,11 +959,19 @@ class PerfRepoAPI(object):
return Noop()
baseline_exec_id = baseline["execId"]
- baseline_testExec = self._rest_api.testExecution_get(baseline_exec_id,
- log=False)
-
- logging.debug("TestExecution of baseline: %s" %\
- self._rest_api.get_obj_url(baseline_testExec))
+ try:
+ baseline_testExec = self._rest_api.testExecution_get(baseline_exec_id,
+ log=False)
+ except Exception as e:
+ baseline_testExec = None
+ logging.error(str(e))
+
+ if baseline_testExec is not None:
+ logging.debug("TestExecution of baseline: %s" %\
+ self._rest_api.get_obj_url(baseline_testExec))
+ else:
+ logging.debug("Couldn't get TestExecution of baseline.")
+ return Noop()
return PerfRepoBaseline(baseline_testExec)
def get_baseline_of_result(self, result):
--
2.9.3
7 years, 5 months