[PATCH lnst 0/2] Support addresses on ovs bridge interface
by Roi Dayan
Hi,
The first patch is a fix to set device down when cleaning it instead of up.
The second patch is adding support to set addresses on the bridge interface.
Thanks,
Roi
Roi Dayan (2):
NetConfigDeviceOvsBridge: set interface down in address cleanup
NetConfigDeviceOvsBridge: support set addresses on the bridge
interface
lnst/Slave/NetConfigDevice.py | 4 +++-
schema-recipe.rng | 3 +++
2 files changed, 6 insertions(+), 1 deletions(-)
6 years
[PATCH lnst] Add basic OVS offload tests
by Roi Dayan
We currently only do minimal testing.
OVS offload is done by adding rules to TC which then offloaded to supported
hardware. so the tests start traffic and then look for matching TC rules.
Testing east-west traffic, north-source traffic, VLAN, VXLAN, VAXLN IPv6.
Signed-off-by: Roi Dayan <roid(a)mellanox.com>
---
Hi,
This commit is adding initial basic tests for OVS offload.
The series adding offloading support to OVS is still being discussed
on the ovs-dev mailing list.
The series is also available in github here:
https://github.com/roidayan/ovs/tree/hw-offload-fixes-for-v5
Thanks,
Roi
recipes/ovs_offload/01-basic.README | 21 ++++++
recipes/ovs_offload/01-basic.py | 84 +++++++++++++++++++++++
recipes/ovs_offload/01-basic.xml | 54 +++++++++++++++
recipes/ovs_offload/03-vlan_in_host.README | 33 +++++++++
recipes/ovs_offload/03-vlan_in_host.py | 72 ++++++++++++++++++++
recipes/ovs_offload/03-vlan_in_host.xml | 67 ++++++++++++++++++
recipes/ovs_offload/04-vlan_in_guest.README | 31 +++++++++
recipes/ovs_offload/04-vlan_in_guest.py | 48 +++++++++++++
recipes/ovs_offload/04-vlan_in_guest.xml | 67 ++++++++++++++++++
recipes/ovs_offload/1_virt_ovs_vxlan.README | 41 +++++++++++
recipes/ovs_offload/1_virt_ovs_vxlan.py | 71 +++++++++++++++++++
recipes/ovs_offload/1_virt_ovs_vxlan.xml | 88 ++++++++++++++++++++++++
recipes/ovs_offload/1_virt_ovs_vxlan_ipv6.xml | 89 ++++++++++++++++++++++++
recipes/ovs_offload/Testlib.py | 90 +++++++++++++++++++++++++
14 files changed, 856 insertions(+), 0 deletions(-)
create mode 100644 recipes/ovs_offload/01-basic.README
create mode 100644 recipes/ovs_offload/01-basic.py
create mode 100644 recipes/ovs_offload/01-basic.xml
create mode 100644 recipes/ovs_offload/03-vlan_in_host.README
create mode 100644 recipes/ovs_offload/03-vlan_in_host.py
create mode 100644 recipes/ovs_offload/03-vlan_in_host.xml
create mode 100644 recipes/ovs_offload/04-vlan_in_guest.README
create mode 100644 recipes/ovs_offload/04-vlan_in_guest.py
create mode 100644 recipes/ovs_offload/04-vlan_in_guest.xml
create mode 100644 recipes/ovs_offload/1_virt_ovs_vxlan.README
create mode 100644 recipes/ovs_offload/1_virt_ovs_vxlan.py
create mode 100644 recipes/ovs_offload/1_virt_ovs_vxlan.xml
create mode 100644 recipes/ovs_offload/1_virt_ovs_vxlan_ipv6.xml
create mode 100644 recipes/ovs_offload/Testlib.py
diff --git a/recipes/ovs_offload/01-basic.README b/recipes/ovs_offload/01-basic.README
new file mode 100644
index 0000000..e13c4fe
--- /dev/null
+++ b/recipes/ovs_offload/01-basic.README
@@ -0,0 +1,21 @@
+Topology:
+
++----------------------+
+| |
+| +-----------------+ |
+| | ovs_bridge | |
+| +-+-------------+-+ |
+| | | |
+| +-+-+ +-+-+ |
++-|tap|---------|tap|--+
+ +-+-+ +-+-+
+ | |
+ | |
+ | |
+ +-+-+ +-+-+
++-|nic|--+ +-|nic|--+
+| +---+ | | +---+ |
+| guest1 | | guest2 |
+| | | |
++--------+ +--------+
+
diff --git a/recipes/ovs_offload/01-basic.py b/recipes/ovs_offload/01-basic.py
new file mode 100644
index 0000000..1bbf5a0
--- /dev/null
+++ b/recipes/ovs_offload/01-basic.py
@@ -0,0 +1,84 @@
+from lnst.Controller.Task import ctl
+from Testlib import Testlib
+
+# ------
+# SETUP
+# ------
+
+tl = Testlib(ctl)
+
+h1 = ctl.get_host("host1")
+g1 = ctl.get_host("guest1")
+g2 = ctl.get_host("guest2")
+
+g1.sync_resources(modules=["IcmpPing", "Icmp6Ping", "Iperf"])
+g2.sync_resources(modules=["Iperf"])
+
+# ------
+# TESTS
+# ------
+
+ipv = ctl.get_alias("ipv")
+do_iperf = ctl.get_alias("iperf")
+
+g1_guestnic = g1.get_interface("if1")
+g1_mac = g1_guestnic.get_hwaddr()
+g2_guestnic = g2.get_interface("if1")
+g2_mac = g2_guestnic.get_hwaddr()
+
+ping_count = 30
+ping_interval = 0.2
+ping_timeout = 10
+
+def ping(options={}):
+ options = dict(options)
+ options.update({
+ "addr": g2_guestnic.get_ip(0),
+ "count": ping_count,
+ "iface": g1_guestnic.get_devname(),
+ "interval": ping_interval
+ })
+ ping_mod = ctl.get_module("IcmpPing", options=options)
+ g1.run(ping_mod, timeout=ping_timeout)
+
+
+def ping6(options={}):
+ options = dict(options)
+ options.update({
+ "addr": g2_guestnic.get_ip(1),
+ "count": ping_count,
+ "iface": g1_guestnic.get_ip(1),
+ "interval": ping_interval
+ })
+ ping_mod6 = ctl.get_module("Icmp6Ping", options=options)
+ g1.run(ping_mod6, timeout=ping_timeout)
+
+
+def verify_tc_rules(proto):
+ m = tl.find_tc_rule(h1, 'tap1', g1_mac, g2_mac, proto, 'mirred')
+ if m:
+ tl.custom(h1, "TC rule %s vm1->vm2" % proto, opts=m)
+ else:
+ tl.custom(h1, "TC rule %s vm1->vm2" % proto, 'ERROR: cannot find tc rule')
+
+ m = tl.find_tc_rule(h1, 'tap2', g2_mac, g1_mac, proto, 'mirred')
+ if m:
+ tl.custom(h1, "TC rule %s vm2->vm1" % proto, opts=m)
+ else:
+ tl.custom(h1, "TC rule %s vm2->vm1" % proto, 'ERROR: cannot find tc rule')
+
+
+if ipv in ('ipv4', 'both'):
+ ping()
+ verify_tc_rules('ip')
+ for size in (200, 400, 1000):
+ ping({'size': size})
+
+if ipv in ('ipv6', 'both'):
+ ping6()
+ verify_tc_rules('ipv6')
+ for size in (200, 400, 1000):
+ ping6({'size': size})
+
+if do_iperf:
+ tl.iperf(g1_guestnic, g2_guestnic, 30, 'vm1->vm2')
diff --git a/recipes/ovs_offload/01-basic.xml b/recipes/ovs_offload/01-basic.xml
new file mode 100644
index 0000000..b020781
--- /dev/null
+++ b/recipes/ovs_offload/01-basic.xml
@@ -0,0 +1,54 @@
+<lnstrecipe>
+ <define>
+ <alias name="ipv" value="both" />
+ <alias name="iperf" value="yes" />
+ <alias name="net" value="1.1.1"/>
+ <alias name="net6" value="fc00:0:0:0"/>
+ </define>
+ <network>
+ <host id="guest1">
+ <params>
+ <param name="machine_type" value="guest"/>
+ </params>
+ <interfaces>
+ <eth id="if1" label="A">
+ <addresses>
+ <address>{$net}.10/24</address>
+ <address>{$net6}::10/64</address>
+ </addresses>
+ </eth>
+ </interfaces>
+ </host>
+ <host id="guest2">
+ <params>
+ <param name="machine_type" value="guest"/>
+ </params>
+ <interfaces>
+ <eth id="if1" label="B">
+ <addresses>
+ <address>{$net}.11/24</address>
+ <address>{$net6}::11/64</address>
+ </addresses>
+ </eth>
+ </interfaces>
+ </host>
+ <host id="host1">
+ <params>
+ <param name="ovs_support" value="true"/>
+ <param name="order" value="1"/>
+ </params>
+ <interfaces>
+ <eth id="tap1" label="A"/>
+ <eth id="tap2" label="B"/>
+ <ovs_bridge id="ovs1">
+ <slaves>
+ <slave id="tap1"/>
+ <slave id="tap2"/>
+ </slaves>
+ </ovs_bridge>
+ </interfaces>
+ </host>
+ </network>
+
+ <task python="01-basic.py" />
+</lnstrecipe>
diff --git a/recipes/ovs_offload/03-vlan_in_host.README b/recipes/ovs_offload/03-vlan_in_host.README
new file mode 100644
index 0000000..3b25b7d
--- /dev/null
+++ b/recipes/ovs_offload/03-vlan_in_host.README
@@ -0,0 +1,33 @@
+Topology:
+
+ +----------+
+ | | VLAN10
+ +-----------------+ switch +--------------------+
+ | | | |
+ | +----------+ |
+ | |
+ +-+-+ |
++------|nic|---------+ +-+-+
+| +-+-+ | +------|nic|------+
+| | | | +---+ |
+| | | | |
+| +------+-------+ | | |
+| | vlan10 | | | host2 |
+| | | | | |
+| | ovs_bridge | | | |
+| | | | | |
+| +-+------------+ | +-----------------+
+| | |
+| +-+-+ |
++-|tap|--------------+
+ +-+-+
+ |
+ |
+ |
+ +-+-+
++-|nic|--+
+| +---+ |
+| guest1 |
+| |
++--------+
+
diff --git a/recipes/ovs_offload/03-vlan_in_host.py b/recipes/ovs_offload/03-vlan_in_host.py
new file mode 100644
index 0000000..3a2c19e
--- /dev/null
+++ b/recipes/ovs_offload/03-vlan_in_host.py
@@ -0,0 +1,72 @@
+from lnst.Controller.Task import ctl
+from Testlib import Testlib
+
+# ------
+# SETUP
+# ------
+
+tl = Testlib(ctl)
+
+h1 = ctl.get_host("host1")
+g1 = ctl.get_host("guest1")
+h2 = ctl.get_host("host2")
+
+g1.sync_resources(modules=["IcmpPing", "Icmp6Ping", "Iperf"])
+h2.sync_resources(modules=["Iperf"])
+
+# ------
+# TESTS
+# ------
+
+ipv = ctl.get_alias("ipv")
+do_iperf = ctl.get_alias("iperf")
+
+h2_vlan10 = h2.get_interface("vlan10")
+h2_mac = h2_vlan10.get_hwaddr()
+g1_guestnic = g1.get_interface("guestnic")
+g1_mac = g1_guestnic.get_hwaddr()
+
+ping_count = 100
+ping_interval = 0.2
+
+ping_mod = ctl.get_module("IcmpPing",
+ options={
+ "addr": h2_vlan10.get_ip(0),
+ "count": ping_count,
+ "iface": g1_guestnic.get_devname(),
+ "interval": ping_interval
+ })
+
+ping_mod6 = ctl.get_module("Icmp6Ping",
+ options={
+ "addr": h2_vlan10.get_ip(1),
+ "count": ping_count,
+ "iface": g1_guestnic.get_ip(1),
+ "interval": ping_interval
+ })
+
+
+def verify_tc_rules(proto):
+ m = tl.find_tc_rule(h1, 'tap', g1_mac, h2_mac, proto, 'vlan push')
+ if m:
+ tl.custom(h1, "TC rule %s vlan push" % proto)
+ else:
+ tl.custom(h1, "TC rule %s vlan push" % proto, 'ERROR: cannot find tc rule')
+
+ m = tl.find_tc_rule(h1, 'nic', h2_mac, g1_mac, '802.1Q', 'vlan pop')
+ if m:
+ tl.custom(h1, "TC rule %s vlan pop" % proto)
+ else:
+ tl.custom(h1, "TC rule %s vlan pop" % proto, 'ERROR: cannot find tc rule')
+
+
+if ipv in ('ipv4', 'both'):
+ g1.run(ping_mod)
+ verify_tc_rules('ip')
+
+if ipv in ('ipv6', 'both'):
+ g1.run(ping_mod6)
+ verify_tc_rules('ipv6')
+
+if do_iperf:
+ tl.iperf(g1_guestnic, h2_vlan10, 100, 'vm1->h2')
diff --git a/recipes/ovs_offload/03-vlan_in_host.xml b/recipes/ovs_offload/03-vlan_in_host.xml
new file mode 100644
index 0000000..5f5c8c1
--- /dev/null
+++ b/recipes/ovs_offload/03-vlan_in_host.xml
@@ -0,0 +1,67 @@
+<lnstrecipe>
+ <define>
+ <alias name="ipv" value="both" />
+ <alias name="iperf" value="yes" />
+ <alias name="vlan10_net" value="1.1.1"/>
+ <alias name="vlan10_net6" value="fc00:0:0:0"/>
+ <alias name="vlan10_tag" value="10"/>
+ </define>
+ <network>
+ <host id="host1">
+ <params>
+ <param name="machine_type" value="baremetal"/>
+ <param name="order" value="1"/>
+ </params>
+ <interfaces>
+ <eth id="nic" label="to_switch"/>
+ <eth id="tap" label="to_guest"/>
+ <ovs_bridge id="ovs_br">
+ <slaves>
+ <slave id="tap" />
+ <slave id="nic" />
+ </slaves>
+ <vlan tag="{$vlan10_tag}">
+ <slaves>
+ <slave id="tap"/>
+ </slaves>
+ </vlan>
+ </ovs_bridge>
+ </interfaces>
+ </host>
+ <host id="guest1">
+ <params>
+ <param name="machine_type" value="guest"/>
+ </params>
+ <interfaces>
+ <eth id="guestnic" label="to_guest">
+ <addresses>
+ <address>{$vlan10_net}.10/24</address>
+ <address>{$vlan10_net6}::10/64</address>
+ </addresses>
+ </eth>
+ </interfaces>
+ </host>
+ <host id="host2">
+ <params>
+ <param name="machine_type" value="baremetal"/>
+ </params>
+ <interfaces>
+ <eth id="nic" label="to_switch"/>
+ <vlan id="vlan10">
+ <options>
+ <option name="vlan_tci" value="{$vlan10_tag}" />
+ </options>
+ <slaves>
+ <slave id="nic" />
+ </slaves>
+ <addresses>
+ <address>{$vlan10_net}.11/24</address>
+ <address>{$vlan10_net6}::11/64</address>
+ </addresses>
+ </vlan>
+ </interfaces>
+ </host>
+ </network>
+
+ <task python="03-vlan_in_host.py" />
+</lnstrecipe>
diff --git a/recipes/ovs_offload/04-vlan_in_guest.README b/recipes/ovs_offload/04-vlan_in_guest.README
new file mode 100644
index 0000000..a4bf384
--- /dev/null
+++ b/recipes/ovs_offload/04-vlan_in_guest.README
@@ -0,0 +1,31 @@
+Topology:
+
+ +----------+
+ | | VLAN10
+ +-----------------+ switch +-----------------+
+ | | | |
+ | +----------+ |
+ | |
+ +-+-+ |
++------|nic|------+ +-+-+
+| +-+-+ | +------|nic|------+
+| | | | +---+ |
+| +----+ | | |
+| | | | |
+| +-+---------+ | | |
+| | ovs_bridge| | | host2 |
+| +-+---------+ | | |
+| | host1 | | |
+| +-+-+ | | |
++-|tap|-----------+ | |
+ +-+-+ +-----------------+
+ |
+ |VLAN10
+ |
+ +-+-+
++-|nic|--+
+| +---+ |
+| guest1 |
+| |
++--------+
+
diff --git a/recipes/ovs_offload/04-vlan_in_guest.py b/recipes/ovs_offload/04-vlan_in_guest.py
new file mode 100644
index 0000000..fe66b9a
--- /dev/null
+++ b/recipes/ovs_offload/04-vlan_in_guest.py
@@ -0,0 +1,48 @@
+from lnst.Controller.Task import ctl
+
+# ------
+# SETUP
+# ------
+
+h1 = ctl.get_host("host1")
+g1 = ctl.get_host("guest1")
+h2 = ctl.get_host("host2")
+
+g1.sync_resources(modules=["IcmpPing", "Icmp6Ping"])
+h2.sync_resources(modules=["IcmpPing", "Icmp6Ping"])
+
+# ------
+# TESTS
+# ------
+
+ipv = ctl.get_alias("ipv")
+h2_vlan10 = h2.get_interface("vlan10")
+g1_vlan10 = g1.get_interface("vlan10")
+
+ping_count = 100
+ping_interval = 0.2
+
+ping_mod = ctl.get_module("IcmpPing",
+ options={
+ "addr": h2_vlan10.get_ip(0),
+ "count": ping_count,
+ "iface": g1_vlan10.get_devname(),
+ "interval": ping_interval
+ })
+
+ping_mod6 = ctl.get_module("Icmp6Ping",
+ options={
+ "addr": h2_vlan10.get_ip(1),
+ "count": ping_count,
+ "iface": g1_vlan10.get_ip(1),
+ "interval": ping_interval
+ })
+
+p_opts = "-L %s" % (h2_vlan10.get_ip(0))
+p_opts6 = "-L %s -6" % (h2_vlan10.get_ip(1))
+
+if ipv in ('ipv4', 'both'):
+ g1.run(ping_mod)
+
+if ipv in ('ipv6', 'both'):
+ g1.run(ping_mod6)
diff --git a/recipes/ovs_offload/04-vlan_in_guest.xml b/recipes/ovs_offload/04-vlan_in_guest.xml
new file mode 100644
index 0000000..8b183ec
--- /dev/null
+++ b/recipes/ovs_offload/04-vlan_in_guest.xml
@@ -0,0 +1,67 @@
+<lnstrecipe>
+ <define>
+ <alias name="ipv" value="both" />
+ <alias name="vlan10_net" value="192.168.10"/>
+ <alias name="vlan10_net6" value="fc00:0:0:0"/>
+ <alias name="vlan10_tag" value="10"/>
+ </define>
+ <network>
+ <host id="host1">
+ <params>
+ <param name="machine_type" value="baremetal"/>
+ </params>
+ <interfaces>
+ <eth id="nic" label="to_switch" />
+ <eth id="tap" label="to_guest" />
+ <ovs_bridge id="br">
+ <slaves>
+ <slave id="tap" />
+ <slave id="nic" />
+ </slaves>
+ </ovs_bridge>
+ </interfaces>
+ </host>
+ <host id="guest1">
+ <params>
+ <param name="machine_type" value="guest"/>
+ </params>
+ <interfaces>
+ <eth id="guestnic" label="to_guest" />
+ <vlan id="vlan10">
+ <options>
+ <option name="vlan_tci" value="{$vlan10_tag}" />
+ </options>
+ <slaves>
+ <slave id="guestnic" />
+ </slaves>
+ <addresses>
+ <address>{$vlan10_net}.10/24</address>
+ <address>{$vlan10_net6}::10/64</address>
+ </addresses>
+ </vlan>
+ </interfaces>
+ </host>
+ <host id="host2">
+ <params>
+ <param name="machine_type" value="baremetal"/>
+ </params>
+ <interfaces>
+ <eth id="nic" label="to_switch"/>
+ <vlan id="vlan10">
+ <options>
+ <option name="vlan_tci" value="{$vlan10_tag}" />
+ </options>
+ <slaves>
+ <slave id="nic" />
+ </slaves>
+ <addresses>
+ <address>{$vlan10_net}.11/24</address>
+ <address>{$vlan10_net6}::11/64</address>
+ </addresses>
+ </vlan>
+ </interfaces>
+ </host>
+ </network>
+
+ <task python="04-vlan_in_guest.py" />
+</lnstrecipe>
diff --git a/recipes/ovs_offload/1_virt_ovs_vxlan.README b/recipes/ovs_offload/1_virt_ovs_vxlan.README
new file mode 100644
index 0000000..11a7061
--- /dev/null
+++ b/recipes/ovs_offload/1_virt_ovs_vxlan.README
@@ -0,0 +1,41 @@
+Topology:
+
+ switch
+ +--------+
+ | |
+ +--------------------+ +----------------------+
+ | | | |
+ | | | |
+ | | | |
+ | +--------+ |
+ | |
+ | |
+ +--+--+ +--+--+
++---------| eth |--------+ +---------| eth |--------+
+| +-----+ | | +-----+ |
+| | | |
+| +----------------------------------------------------+ |
+| | | | | |
+| +----------+---------+ | | +----------+---------+ |
+| | vxlan | | | | vxlan | |
+| | | | | | | |
+| | ovs_bridge | | | | ovs_bridge | |
+| |tun_id | | | | | |
+| | 100 | | | | +----+ | |
+| +--+-----------------+ | | +-------|int0|-------+ |
+| | host1 | | +----+ |
+| | | | |
+| | | | host2 |
+| +-+-+ | | |
++--+tap+-----------------+ +------------------------+
+ +-+-+
+ |
+ +-+-+
++--+eth+--+
+| +---+ |
+| |
+| guest1 |
+| |
+| |
++---------+
+
diff --git a/recipes/ovs_offload/1_virt_ovs_vxlan.py b/recipes/ovs_offload/1_virt_ovs_vxlan.py
new file mode 100644
index 0000000..adc4122
--- /dev/null
+++ b/recipes/ovs_offload/1_virt_ovs_vxlan.py
@@ -0,0 +1,71 @@
+from lnst.Controller.Task import ctl
+from lnst.RecipeCommon.ModuleWrap import ping, ping6
+from Testlib import Testlib
+import logging
+
+# ------
+# SETUP
+# ------
+
+tl = Testlib(ctl)
+
+# hosts
+host1 = ctl.get_host("h1")
+host2 = ctl.get_host("h2")
+
+# guest machines
+guest1 = ctl.get_host("test_host1")
+
+guest1.sync_resources(modules=["IcmpPing", "Icmp6Ping"])
+
+# ------
+# TESTS
+# ------
+
+ipv = ctl.get_alias("ipv")
+mtu = ctl.get_alias("mtu")
+
+g1_nic = guest1.get_interface("if1")
+h2_nic = host2.get_device("int0")
+
+vxlan_port = ctl.get_alias("vxlan_port")
+vxlan_dev = "vxlan_sys_%s" % vxlan_port
+
+
+def do_pings():
+ ping_opts = {"count": 100, "interval": 0.2}
+ if ipv in ['ipv4', 'both']:
+ ping((guest1, g1_nic, 0, {"scope": 0}),
+ (host2, h2_nic, 0, {"scope": 0}),
+ options=ping_opts, expect="pass")
+ verify_tc_rules('ip')
+
+ if ipv in ['ipv6', 'both']:
+ ping6((guest1, g1_nic, 1, {"scope": 0}),
+ (host2, h2_nic, 1, {"scope": 0}),
+ options=ping_opts, expect="pass")
+ verify_tc_rules('ipv6')
+
+
+def verify_tc_rules(proto):
+ g1_mac = g1_nic.get_hwaddr()
+ h2_mac = h2_nic.get_hwaddr()
+
+ # encap rule
+ m = tl.find_tc_rule(host1, 'tap1', g1_mac, h2_mac, proto, 'tunnel_key set')
+ desc = "TC rule %s tunnel_key set" % proto
+ if m:
+ tl.custom(host1, desc)
+ else:
+ tl.custom(host1, desc, 'ERROR: cannot find tc rule')
+
+ # decap rule
+ m = tl.find_tc_rule(host1, vxlan_dev, h2_mac, g1_mac, proto, 'tunnel_key unset')
+ desc = "TC rule %s tunnel_key unset" % proto
+ if m:
+ tl.custom(host1, desc)
+ else:
+ tl.custom(host1, desc, 'ERROR: cannot find tc rule')
+
+
+do_pings()
diff --git a/recipes/ovs_offload/1_virt_ovs_vxlan.xml b/recipes/ovs_offload/1_virt_ovs_vxlan.xml
new file mode 100644
index 0000000..b1e3357
--- /dev/null
+++ b/recipes/ovs_offload/1_virt_ovs_vxlan.xml
@@ -0,0 +1,88 @@
+<lnstrecipe>
+ <define>
+ <alias name="ipv" value="both" />
+ <alias name="mtu" value="1450" />
+ <alias name="net" value="77.77.77"/>
+ <alias name="vxlan_net" value="1.1.1"/>
+ <alias name="vxlan_net6" value="fc00:0:0:0"/>
+ <alias name="vxlan_key" value="100"/>
+ <alias name="vxlan_port" value="1478"/>
+ </define>
+ <network>
+ <host id="h1">
+ <params>
+ <param name="machine_type" value="baremetal"/>
+ <param name="order" value="1"/>
+ </params>
+ <interfaces>
+ <eth id="if1" label="n1">
+ <addresses>
+ <address value="{$net}.1/24"/>
+ </addresses>
+ </eth>
+ <eth id="tap1" label="to_guest1"/>
+ <ovs_bridge id="ovs1">
+ <slaves>
+ <slave id="tap1">
+ <options>
+ <option name="ofport_request" value="5"/>
+ </options>
+ </slave>
+ </slaves>
+ <tunnel id="vxlan1" type="vxlan">
+ <options>
+ <option name="option:remote_ip" value="{$net}.2"/>
+ <option name="option:key" value="{$vxlan_key}"/>
+ <option name="option:dst_port" value="{$vxlan_port}"/>
+ <option name="ofport_request" value="10"/>
+ </options>
+ </tunnel>
+ </ovs_bridge>
+ </interfaces>
+ </host>
+ <host id="test_host1">
+ <interfaces>
+ <eth id="if1" label="to_guest1">
+ <addresses>
+ <address value="{$vxlan_net}.1/24"/>
+ <address value="{$vxlan_net6}::1/64"/>
+ </addresses>
+ </eth>
+ </interfaces>
+ </host>
+ <host id="h2">
+ <params>
+ <param name="machine_type" value="baremetal"/>
+ </params>
+ <interfaces>
+ <eth id="if1" label="n1">
+ <addresses>
+ <address value="{$net}.2/24"/>
+ </addresses>
+ </eth>
+ <ovs_bridge id="ovs2">
+ <internal id="int0">
+ <options>
+ <option name="ofport_request" value="5"/>
+ <option name="name" value="int0"/>
+ </options>
+ <addresses>
+ <address value="{$vxlan_net}.2/24"/>
+ <address value="{$vxlan_net6}::2/24"/>
+ </addresses>
+ </internal>
+ <tunnel id="vxlan1" type="vxlan">
+ <options>
+ <option name="option:remote_ip" value="{$net}.1"/>
+ <option name="option:key" value="{$vxlan_key}"/>
+ <option name="option:dst_port" value="{$vxlan_port}"/>
+ <option name="ofport_request" value="10"/>
+ </options>
+ </tunnel>
+ </ovs_bridge>
+ </interfaces>
+ </host>
+ </network>
+
+ <task python="1_virt_ovs_vxlan.py"/>
+</lnstrecipe>
diff --git a/recipes/ovs_offload/1_virt_ovs_vxlan_ipv6.xml b/recipes/ovs_offload/1_virt_ovs_vxlan_ipv6.xml
new file mode 100644
index 0000000..ede7d66
--- /dev/null
+++ b/recipes/ovs_offload/1_virt_ovs_vxlan_ipv6.xml
@@ -0,0 +1,89 @@
+<lnstrecipe>
+ <define>
+ <alias name="ipv" value="both" />
+ <alias name="mtu" value="1450" />
+ <alias name="net" value="2002:0db8:0:f101"/>
+ <alias name="vxlan_net" value="1.1.1"/>
+ <alias name="vxlan_net6" value="fc00:0:0:0"/>
+ <alias name="vxlan_key" value="100"/>
+ <alias name="vxlan_port2" value="4789"/>
+ <alias name="vxlan_port" value="1478"/>
+ </define>
+ <network>
+ <host id="h1">
+ <params>
+ <param name="machine_type" value="baremetal"/>
+ <param name="order" value="1"/>
+ </params>
+ <interfaces>
+ <eth id="if1" label="n1">
+ <addresses>
+ <address value="{$net}::1/64"/>
+ </addresses>
+ </eth>
+ <eth id="tap1" label="to_guest1"/>
+ <ovs_bridge id="ovs1">
+ <slaves>
+ <slave id="tap1">
+ <options>
+ <option name="ofport_request" value="5"/>
+ </options>
+ </slave>
+ </slaves>
+ <tunnel id="vxlan1" type="vxlan">
+ <options>
+ <option name="option:remote_ip" value="{$net}::2"/>
+ <option name="option:key" value="{$vxlan_key}"/>
+ <option name="option:dst_port" value="{$vxlan_port}"/>
+ <option name="ofport_request" value="10"/>
+ </options>
+ </tunnel>
+ </ovs_bridge>
+ </interfaces>
+ </host>
+ <host id="test_host1">
+ <interfaces>
+ <eth id="if1" label="to_guest1">
+ <addresses>
+ <address value="{$vxlan_net}.1/24"/>
+ <address value="{$vxlan_net6}::1/64"/>
+ </addresses>
+ </eth>
+ </interfaces>
+ </host>
+ <host id="h2">
+ <params>
+ <param name="machine_type" value="baremetal"/>
+ </params>
+ <interfaces>
+ <eth id="if1" label="n1">
+ <addresses>
+ <address value="{$net}::2/64"/>
+ </addresses>
+ </eth>
+ <ovs_bridge id="ovs2">
+ <internal id="int0">
+ <options>
+ <option name="ofport_request" value="5"/>
+ <option name="name" value="int0"/>
+ </options>
+ <addresses>
+ <address value="{$vxlan_net}.2/24"/>
+ <address value="{$vxlan_net6}::2/24"/>
+ </addresses>
+ </internal>
+ <tunnel id="vxlan1" type="vxlan">
+ <options>
+ <option name="option:remote_ip" value="{$net}::1"/>
+ <option name="option:key" value="{$vxlan_key}"/>
+ <option name="option:dst_port" value="{$vxlan_port}"/>
+ <option name="ofport_request" value="10"/>
+ </options>
+ </tunnel>
+ </ovs_bridge>
+ </interfaces>
+ </host>
+ </network>
+
+ <task python="1_virt_ovs_vxlan.py"/>
+</lnstrecipe>
diff --git a/recipes/ovs_offload/Testlib.py b/recipes/ovs_offload/Testlib.py
new file mode 100644
index 0000000..e14bae7
--- /dev/null
+++ b/recipes/ovs_offload/Testlib.py
@@ -0,0 +1,90 @@
+import re
+import logging
+
+
+class Testlib:
+ def __init__(self, ctl):
+ self._ctl = ctl
+
+ def set_hw_offload(self, host, nics, state):
+ cmd = "ethtool -K {nic} hw-tc-offload %s" % state
+ for nic in nics:
+ logging.info("Set hw-tc-offload=%s for %s" % (state, nic))
+ host.run(cmd.format(nic=nic))
+
+ def enable_hw_offload(self, host, nics):
+ self.set_hw_offload(host, nics, 'on')
+
+ def disable_hw_offload(self, host, nics):
+ self.set_hw_offload(host, nics, 'off')
+
+ def custom(self, host, desc, err_msg=None, opts=None):
+ host.sync_resources(modules=["Custom"])
+ options = {}
+ if opts:
+ options.update(opts)
+ if err_msg:
+ options["fail"] = "yes"
+ options["msg"] = err_msg
+ custom_mod = self._ctl.get_module("Custom", options=options)
+ host.run(custom_mod, desc=desc)
+
+ def find_tc_rule(self, host, nic, src_mac, dst_mac, proto='.*', action='.*', tunnel=''):
+ # find dev. i.e. ens5f0
+ try:
+ if1 = host.get_interface(nic)
+ dev = if1.get_devname()
+ except KeyError:
+ dev = nic
+
+ # tc output
+ cmd = host.run("tc -s filter show dev %s parent ffff:" % dev)
+ out = cmd.out().strip()
+
+ if not out:
+ return None
+
+ # find rule
+ pat_filter = r"^protocol %s pref .* dst_mac %s\n\s*src_mac %s\n.*\n\s*action order \s*\d+\s*:\s* %s" % (
+ proto, str(dst_mac).lower(), str(src_mac).lower(), action)
+ pat_action = r".*\n\s*action order .* %s.*\n\s*Sent (?P<bytes>\d+) bytes (?P<pkts>\d+) pkt \(dropped (?P<drop>\d+), overlimits \d+ requeues \d+\)" % action
+
+ logging.debug("device %s pattern '%s' action '%s'", dev, pat_filter, pat_action)
+
+ for f in re.split('\n\s*filter\s*', out):
+ if re.match(pat_filter, f, re.S + re.M):
+ logging.debug("matched filter")
+ m = re.match(pat_action, f, re.S + re.M)
+ if m:
+ logging.debug("matched action")
+ return m.groupdict()
+ return None
+ return None
+
+ def _get_iperf_srv_mod(self):
+ modules_options = {
+ "role": "server",
+ }
+ return self._ctl.get_module("Iperf", options=modules_options)
+
+ def _get_iperf_cli_mod(self, server, duration):
+ modules_options = {
+ "role": "client",
+ "iperf_server": server,
+ "duration": duration,
+ "iperf_opts": "-l 1024k -w 512k -P 12"
+ }
+ return self._ctl.get_module("Iperf", options=modules_options)
+
+ def iperf(self, cli_if, srv_if, duration, desc):
+ srv_ip = srv_if.get_ip(0)
+ srv_m = self._get_iperf_srv_mod()
+ cli_m = self._get_iperf_cli_mod(srv_ip, duration)
+
+ cli_host = cli_if.get_host()
+ srv_host = srv_if.get_host()
+
+ srv_proc = srv_host.run(srv_m, bg=True)
+ self._ctl.wait(2)
+ cli_host.run(cli_m, timeout=duration + 15, desc=desc)
+ srv_proc.intr()
--
1.7.1
6 years
[PATCH 0/3] Netperf minor refactorization and support for RR tests
by Jiri Prochazka
Hello everyone,
this small patchset modifies LNST Netperf module. It presents minor
refactorization of the module which does not have any influence on the
functionality but it also adds support for RR tests. Since this module is
used for our ENRT testing, I'd like to ask you to review this carefully
so we don't affect our PerfRepo objects.
Support for RR tests consists of these items:
* added THROUGHPUT_UNIT omni output selector
* parsing of unit based from this selector
* when running STREAM test, keep the output same as previous version (rate in
bit/s, unit called bps)
* when running RR test, rate is Trans/sec and unit is called tps
I've run locally TCP_STREAM, UDP_STREAM, TCP_RR, TCP_CRR and I need to run
in Beaker SCTP tests so I have ready full suite of tests we are currently
using. In the pastebins below, there is test recipe, test task and debug log
from the run on this patchset. Once I'll have the results from SCTP tests,
I'll post them as well.
https://pastebin.com/bjFLs1Nj rr_test.xml
https://pastebin.com/jeCBGsrf rr_test.py
https://pastebin.com/W63GCGVj log.debug
Jiri Prochazka (3):
test_modules/netperf: use bit/s in STREAM tests and parse RR tests
test_modules/netperf: split _pretty_rate method in two and add support
for RR tests
test_modules/netperf: add TCP_CRR to supported and omni tests
test_modules/Netperf.py | 107 +++++++++++++++++++++++++++++-------------------
1 file changed, 66 insertions(+), 41 deletions(-)
--
2.9.3
6 years, 1 month
[PATCH v2] recipes: fix NIC pinning in vxlan tests
by Jan Tluka
Few recipes had incorrect devices selected for IRQ pinning.
Recipe vxlan_multicast included some of the tap devices. As these do not
have any IRQ assigned it does not make sense to do the pinning on them.
Recipe novirt_ovs_vxlan selected ovs internal devices instead of physical
devices. This impacts the performance testing.
v2: use get_interface instead of get_device method
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
recipes/regression_tests/phase3/novirt_ovs_vxlan.py | 5 ++++-
recipes/regression_tests/phase3/vxlan_multicast.py | 4 +---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/recipes/regression_tests/phase3/novirt_ovs_vxlan.py b/recipes/regression_tests/phase3/novirt_ovs_vxlan.py
index 7b4d1ec..02e5dcc 100644
--- a/recipes/regression_tests/phase3/novirt_ovs_vxlan.py
+++ b/recipes/regression_tests/phase3/novirt_ovs_vxlan.py
@@ -53,8 +53,11 @@ if nperf_cpupin:
h1.run("service irqbalance stop")
h2.run("service irqbalance stop")
+ h1_phy = h1.get_interface("if1")
+ h2_phy = h2.get_interface("if1")
+
# this will pin devices irqs to cpu #0
- for m, d in [(h1, h1_nic), (h2, h2_nic)]:
+ for m, d in [(h1, h1_phy), (h2, h2_phy)]:
pin_dev_irqs(m, d, 0)
nperf_opts = ""
diff --git a/recipes/regression_tests/phase3/vxlan_multicast.py b/recipes/regression_tests/phase3/vxlan_multicast.py
index d4c18ee..e31bd6b 100644
--- a/recipes/regression_tests/phase3/vxlan_multicast.py
+++ b/recipes/regression_tests/phase3/vxlan_multicast.py
@@ -57,10 +57,8 @@ if nperf_cpupin:
g1.run("service irqbalance stop")
m1_phy1 = m1.get_interface("eth1")
- m1_phy2 = m1.get_interface("tap1")
m2_phy1 = m2.get_interface("eth1")
- g1_phy1 = g1.get_interface("eth1")
- dev_list = [(m1, m1_phy1), (m1, m1_phy2), (m2, m2_phy1), (g1, g1_phy1)]
+ dev_list = [(m1, m1_phy1), (m2, m2_phy1)]
# this will pin devices irqs to cpu #0
for m, d in dev_list:
--
2.7.4
6 years, 1 month
[PATCH] recipes: fix NIC pinning in vxlan tests
by Jan Tluka
Few recipes had incorrect devices selected for IRQ pinning.
Recipe vxlan_multicast included some of the tap devices. As these do not
have any IRQ assigned it does not make sense to do the pinning on them.
Recipe novirt_ovs_vxlan selected ovs internal devices instead of physical
devices. This impacts the performance testing.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
recipes/regression_tests/phase3/novirt_ovs_vxlan.py | 5 ++++-
recipes/regression_tests/phase3/vxlan_multicast.py | 4 +---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/recipes/regression_tests/phase3/novirt_ovs_vxlan.py b/recipes/regression_tests/phase3/novirt_ovs_vxlan.py
index 7b4d1ec..470ef06 100644
--- a/recipes/regression_tests/phase3/novirt_ovs_vxlan.py
+++ b/recipes/regression_tests/phase3/novirt_ovs_vxlan.py
@@ -53,8 +53,11 @@ if nperf_cpupin:
h1.run("service irqbalance stop")
h2.run("service irqbalance stop")
+ h1_phy = h1.get_device("if1")
+ h2_phy = h2.get_device("if1")
+
# this will pin devices irqs to cpu #0
- for m, d in [(h1, h1_nic), (h2, h2_nic)]:
+ for m, d in [(h1, h1_phy), (h2, h2_phy)]:
pin_dev_irqs(m, d, 0)
nperf_opts = ""
diff --git a/recipes/regression_tests/phase3/vxlan_multicast.py b/recipes/regression_tests/phase3/vxlan_multicast.py
index d4c18ee..e31bd6b 100644
--- a/recipes/regression_tests/phase3/vxlan_multicast.py
+++ b/recipes/regression_tests/phase3/vxlan_multicast.py
@@ -57,10 +57,8 @@ if nperf_cpupin:
g1.run("service irqbalance stop")
m1_phy1 = m1.get_interface("eth1")
- m1_phy2 = m1.get_interface("tap1")
m2_phy1 = m2.get_interface("eth1")
- g1_phy1 = g1.get_interface("eth1")
- dev_list = [(m1, m1_phy1), (m1, m1_phy2), (m2, m2_phy1), (g1, g1_phy1)]
+ dev_list = [(m1, m1_phy1), (m2, m2_phy1)]
# this will pin devices irqs to cpu #0
for m, d in dev_list:
--
2.7.4
6 years, 1 month
Re: switchdev test
by Jiri Pirko
Tue, Apr 18, 2017 at 12:18:36PM CEST, liali(a)redhat.com wrote:
>Hi all,
>
>When i running qos-005, it always print a error: RPC connection to machine machine1 timed out
>
>2017-04-18 05:38:38 (machine1) - DEBUG: Executing: "echo "start" > /proc/net/pktgen/pgctrl"
>2017-04-18 05:39:34 (machine1) - DEBUG: Killing command with pid "51245"
>2017-04-18 05:39:34 (localhost) - INFO: Result: FAIL
>2017-04-18 05:39:34 (localhost) - INFO: Status message from slave: "RPC connection to machine machine1 timed out"
>
>
>Is this because the lnst-slave machine1 is too busy(because it is generating traffic) so the lnst-ctl lost connection to it?
>If i reduce the pktgen's thread count, this error will disappear. But then it can't generate enough traffic to make ETS to take effect.
>Anyone encountered this error ?
Ccing LNST people.
6 years, 1 month
[PATCH] SlavePool: check for duplicate MAC address in slavemachine
files
by Jan Tluka
Duplicate MAC addresses in slavemachine files are silently ignored and could cause
unpredictable behaviour. This patch adds a check for MAC duplicity.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
lnst/Controller/SlavePool.py | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index 67ccd63..5f94b07 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -208,11 +208,20 @@ class SlavePool:
if_id = iface["id"]
iface_spec = self._process_iface_xml_data(m_id, iface)
- if if_id not in machine_spec["interfaces"]:
- machine_spec["interfaces"][if_id] = iface_spec
- else:
+ # validity check, MAC and id must be unique
+ if if_id in machine_spec["interfaces"]:
msg = "Duplicate interface id '%s'." % if_id
raise SlaveMachineError(msg, iface)
+
+ if_hwaddr = iface_spec["params"]["hwaddr"]
+ hwaddr_dups = [ k for k, v in machine_spec["interfaces"].iteritems()\
+ if v["params"]["hwaddr"] == if_hwaddr ]
+ if len(hwaddr_dups) > 0:
+ msg = "Duplicate MAC address %s for interface '%s' and '%s'."\
+ % (if_hwaddr, if_id, hwaddr_dups[0])
+ raise SlaveMachineError(msg, iface)
+
+ machine_spec["interfaces"][if_id] = iface_spec
else:
if "libvirt_domain" not in machine_spec["params"]:
msg = "Machine '%s' has no testing interfaces. " \
--
2.7.4
6 years, 1 month
[PATCH v2 2/2] InterfaceManager: avoid infinite recursion when
deconfiguring veth pair
by Jan Tluka
When a user configures veth pair with both veths under root namespace the
infinite recursion is triggered.
Each device of veth pair stores a reference to it's peer in Device's
_master["other"]. It means that LNST will have two veth devices each
referencing the peer as master:
(veth1) (veth2)
Device1._if_index == 10 Device2._if_index == 20
Device1._master["other"] = [20] Device2._master["other"] = [10]
On deconfiguration of the veth pair LNST will try to deconfigure
first veth but since it references second veth as master it will start
deconfiguring this master interface. The second interface references the
first interface as master so it will attempt to deconfigure the first veth
device again, and so on until max level of recursion is reached.
This patch adds a check if the device that is deconfigured is referenced by
it's 'other' master. If the reference exists the deconfiguration of master
device will be skipped.
Fixes #187
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
lnst/Slave/InterfaceManager.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index 697119a..b21c962 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -563,7 +563,7 @@ class Device(object):
for m_id in self._master["other"]:
m_dev = self._if_manager.get_device(m_id)
- if m_dev:
+ if m_dev and self._if_index not in m_dev.get_master()["other"]:
m_dev.clear_configuration()
if self._conf != None and self._configured:
@@ -638,7 +638,7 @@ class Device(object):
for m_id in self._master["other"]:
m_dev = self._if_manager.get_device(m_id)
- if m_dev:
+ if m_dev and self._if_index not in m_dev.get_master()["other"]:
m_dev.deconfigure()
if self._conf != None and self._configured:
--
2.7.4
6 years, 1 month
[PATCH v2 1/2] InterfaceManager: add Device method get_master()
by Jan Tluka
Returns the Device's master.
v2: return the whole master attribute
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
lnst/Slave/InterfaceManager.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index 3d28070..697119a 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -593,6 +593,9 @@ class Device(object):
elif if_index not in self._master["other"]:
self._master["other"].append(if_index)
+ def get_master(self):
+ return self._master
+
def del_master(self, if_index):
if self._master["primary"] == if_index:
self._master["primary"] = None
--
2.7.4
6 years, 1 month
[PATCH] Task: optimize get_device() function
by Jiri Prochazka
Function dev_db_get_name() is here called twice and can be reduced to
only one call. Because it queries Slave machine n times, where n is
size of device database on Slave, it can take a lot of time when
database is large.
This reduces time it takes to return from this function
to a half.
Signed-off-by: Jiri Prochazka <jprochaz(a)redhat.com>
---
lnst/Controller/Task.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py
index 4f4a772..af1db96 100644
--- a/lnst/Controller/Task.py
+++ b/lnst/Controller/Task.py
@@ -314,7 +314,7 @@ class HostAPI(object):
def get_device(self, name):
dev = self._m.dev_db_get_name(name)
if dev:
- return DeviceAPI(self._m.dev_db_get_name(name), self)
+ return DeviceAPI(dev, self)
else:
raise TaskError("No device with name '%s' found." % str(name))
--
2.9.3
6 years, 1 month