[PATCH] Task: add create_vxlan method
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
Follow up patch to adding vxlan support that adds the create_vxlan
HostAPI method. This can be used to create vxlan interfaces during Task
execution.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/Task.py | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py
index e47b025..f821ccf 100644
--- a/lnst/Controller/Task.py
+++ b/lnst/Controller/Task.py
@@ -433,6 +433,21 @@ class HostAPI(object):
return self._add_iface("vlan", if_id, netns, ip, {"vlan_tci": vlan_tci},
[realdev_iface])
+ def create_vxlan(self, vxlan_id, realdev_iface=None, group_ip=None,
+ remote_ip=None, if_id=None, netns=None, ip=None, options={}):
+ if group_ip is None and remote_ip is None:
+ raise TaskError("Either group_ip or remote_ip must be specified.")
+
+ options.update({"id": vxlan_id,
+ "group_ip": group_ip,
+ "remote_ip": remote_ip})
+ if realdev_iface is not None:
+ slaves = [realdev_iface]
+ else:
+ slaves = []
+
+ return self._add_iface("vxlan", if_id, netns, ip, options, slaves)
+
class InterfaceAPI(object):
def __init__(self, interface, host):
self._if = interface
--
2.6.4
8 years, 3 months
[PATCH] add support for VXLAN devices
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
This adds support for configuring VXLAN devices. Included is an example
recipe in the recipes/examples/vxlan.xml file.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Controller/Machine.py | 2 +-
lnst/Controller/RecipeParser.py | 20 ++++++++++++++
lnst/Slave/InterfaceManager.py | 2 ++
lnst/Slave/NetConfigDevice.py | 55 ++++++++++++++++++++++++++++++++++++-
lnst/Slave/NmConfigDevice.py | 9 ++++++-
recipes/examples/vxlan.xml | 60 +++++++++++++++++++++++++++++++++++++++++
schema-recipe.rng | 8 ++++++
7 files changed, 153 insertions(+), 3 deletions(-)
create mode 100644 recipes/examples/vxlan.xml
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index 7281203..f04710c 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -593,7 +593,7 @@ class Interface(object):
def add_slave(self, iface):
self._slaves[iface.get_id()] = iface
- if self._type in ["vlan"]:
+ if self._type in ["vlan", "vxlan"]:
iface.add_master(self, primary=False)
else:
iface.add_master(self)
diff --git a/lnst/Controller/RecipeParser.py b/lnst/Controller/RecipeParser.py
index 318b231..827279f 100644
--- a/lnst/Controller/RecipeParser.py
+++ b/lnst/Controller/RecipeParser.py
@@ -184,6 +184,26 @@ class RecipeParser(XmlParser):
opts = self._process_options(opts_tag)
if len(opts) > 0:
iface["options"] = opts
+ elif iface["type"] in ["vxlan"]:
+ # real_dev of the VXLAN interface
+ slaves_tag = iface_tag.find("slaves")
+ if slaves_tag is not None and len(slaves_tag) > 1:
+ msg = "VXLAN '%s' needs one or no slave definition."\
+ % iface["id"]
+ raise RecipeError(msg, iface_tag)
+
+ if slaves_tag:
+ iface["slaves"] = XmlCollection(slaves_tag)
+ slave_tag = slaves_tag[0]
+ slave = XmlData(slave_tag)
+ slave["id"] = self._get_attribute(slave_tag, "id")
+ iface["slaves"].append(slave)
+
+ # interface options
+ opts_tag = iface_tag.find("options")
+ opts = self._process_options(opts_tag)
+ if len(opts) > 0:
+ iface["options"] = opts
elif iface["type"] == "ovs_bridge":
slaves_tag = iface_tag.find("slaves")
iface["slaves"] = XmlCollection(slaves_tag)
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index a99c2ae..8bb3bae 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -266,6 +266,8 @@ class InterfaceManager(object):
return self._assign_name_generic("vti")
elif dev_type == "vti6":
return self._assign_name_generic("t_ip6vti")
+ elif dev_type == "vxlan":
+ return self._assign_name_generic("vxlan")
else:
return self._assign_name_generic("dev")
diff --git a/lnst/Slave/NetConfigDevice.py b/lnst/Slave/NetConfigDevice.py
index 809c0c5..eebcb35 100644
--- a/lnst/Slave/NetConfigDevice.py
+++ b/lnst/Slave/NetConfigDevice.py
@@ -281,6 +281,58 @@ class NetConfigDeviceVlan(NetConfigDeviceGeneric):
super(NetConfigDeviceVlan, self).up()
+class NetConfigDeviceVxlan(NetConfigDeviceGeneric):
+ _modulename = ""
+
+ def create(self):
+ config = self._dev_config
+
+ slaves = get_slaves(config)
+ if len(slaves) == 1:
+ realdev_id = slaves[0]
+ name = self._if_manager.get_mapped_device(realdev_id).get_name()
+ dev_param = "dev %s" % name
+ else:
+ dev_param = ""
+
+ dev_name = config["name"]
+ vxlan_id = int(get_option(config, "id"))
+ group_ip = get_option(config, "group_ip")
+ remote_ip = get_option(config, "remote_ip")
+
+ if group_ip:
+ group_or_remote = "group %s" % group_ip
+ elif remote_ip:
+ group_or_remote = "remote %s" % remote_ip
+ else:
+ raise Exception("group or remote must be specified for vxlan")
+
+ dstport = get_option(config, "dstport")
+ if not dstport:
+ dstport = 0
+ else:
+ dstport = int(dstport)
+
+ exec_cmd("ip link add %s type vxlan id %d %s %s dstport %d"
+ % (dev_name,
+ vxlan_id,
+ dev_param,
+ group_or_remote,
+ dstport))
+
+ def destroy(self):
+ dev_name = self._dev_config["name"]
+ exec_cmd("ip link del %s" % dev_name)
+
+ def up(self):
+ slaves = get_slaves(self._dev_config)
+ if len(slaves) == 1:
+ parent_id = get_slaves(self._dev_config)[0]
+ parent_dev = self._if_manager.get_mapped_device(parent_id)
+ parent_dev.up()
+
+ super(NetConfigDeviceVxlan, self).up()
+
def prepare_json_str(json_str):
if not json_str:
return "{}"
@@ -563,7 +615,8 @@ type_class_mapping = {
"veth": NetConfigDeviceVEth,
"vti": NetConfigDeviceVti,
"vti6": NetConfigDeviceVti6,
- "lo": NetConfigDeviceLoopback
+ "lo": NetConfigDeviceLoopback,
+ "vxlan": NetConfigDeviceVxlan
}
def NetConfigDevice(dev_config, if_manager):
diff --git a/lnst/Slave/NmConfigDevice.py b/lnst/Slave/NmConfigDevice.py
index 40c6923..cbd3420 100644
--- a/lnst/Slave/NmConfigDevice.py
+++ b/lnst/Slave/NmConfigDevice.py
@@ -850,6 +850,12 @@ class NmConfigDeviceLoopback(NmConfigDeviceGeneric):
def is_nm_managed(cls, dev_config, if_manager):
return False
+class NmConfigDeviceVxlan(NmConfigDeviceGeneric):
+ #Not supported by NetworkManager
+ @classmethod
+ def is_nm_managed(cls, dev_config, if_manager):
+ return False
+
type_class_mapping = {
"eth": NmConfigDeviceEth,
"bond": NmConfigDeviceBond,
@@ -861,7 +867,8 @@ type_class_mapping = {
"veth": NmConfigDeviceVEth,
"vti": NmConfigDeviceVti,
"vti6": NmConfigDeviceVti6,
- "lo": NmConfigDeviceLoopback
+ "lo": NmConfigDeviceLoopback,
+ "vxlan": NmConfigDeviceVxlan
}
def is_nm_managed(dev_config, if_manager):
diff --git a/recipes/examples/vxlan.xml b/recipes/examples/vxlan.xml
new file mode 100644
index 0000000..547f79b
--- /dev/null
+++ b/recipes/examples/vxlan.xml
@@ -0,0 +1,60 @@
+<lnstrecipe>
+ <network>
+ <host id="testmachine1">
+ <interfaces>
+ <eth id="1" label="tnet">
+ <addresses>
+ <address value="192.168.101.1/24"/>
+ </addresses>
+ </eth>
+ <vxlan id="testifc1">
+ <options>
+ <option name="id" value="1"/>
+ <option name="group_ip" value="239.1.1.1"/>
+ <!--<option name="remote_ip" value="192.168.101.2"/>-->
+ </options>
+ <slaves>
+ <slave id="1"/>
+ </slaves>
+ <addresses>
+ <address value="192.168.100.1/24"/>
+ </addresses>
+ </vxlan>
+ </interfaces>
+ </host>
+
+ <host id="testmachine2">
+ <interfaces>
+ <eth id="1" label="tnet">
+ <addresses>
+ <address value="192.168.101.2/24"/>
+ </addresses>
+ </eth>
+ <vxlan id="testifc2">
+ <options>
+ <option name="id" value="1"/>
+ <option name="group_ip" value="239.1.1.1"/>
+ <!--<option name="remote_ip" value="192.168.101.1"/>-->
+ </options>
+ <slaves>
+ <slave id="1"/>
+ </slaves>
+ <addresses>
+ <address value="192.168.100.2/24"/>
+ </addresses>
+ </vxlan>
+ </interfaces>
+ </host>
+ </network>
+
+ <task>
+ <run host="testmachine1" module="IcmpPing">
+ <options>
+ <option name="addr" value="{ip(testmachine2,testifc2)}"/>
+ <option name="count" value="40"/>
+ <option name="interval" value="0"/>
+ <option name="iface" value="{devname(testmachine1, testifc1)}"/>
+ </options>
+ </run>
+ </task>
+</lnstrecipe>
diff --git a/schema-recipe.rng b/schema-recipe.rng
index c1ffbed..ad841bb 100644
--- a/schema-recipe.rng
+++ b/schema-recipe.rng
@@ -139,6 +139,7 @@
<ref name="vti"/>
<ref name="vti6"/>
<ref name="lo"/>
+ <ref name="vxlan"/>
</choice>
</zeroOrMore>
</element>
@@ -292,6 +293,13 @@
</element>
</define>
+ <define name="vxlan">
+ <element name="vxlan">
+ <attribute name="id"/>
+ <ref name="softdevice"/>
+ </element>
+ </define>
+
<define name="softdevice">
<optional>
<attribute name="netns"/>
--
2.6.4
8 years, 3 months
[patch lnst] Task: allow task to get list of current aliases with values
by Jiri Pirko
From: Jiri Pirko <jiri(a)mellanox.com>
It is valuable for task to be able to get complete list of currently
defined aliases. This patch allows it.
Signed-off-by: Jiri Pirko <jiri(a)mellanox.com>
---
lnst/Controller/NetTestController.py | 4 ++++
lnst/Controller/Task.py | 9 +++++++++
lnst/Controller/XmlTemplates.py | 10 ++++++++++
3 files changed, 23 insertions(+)
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index 0051c4d..b4ab31d 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -855,6 +855,10 @@ class NetTestController:
templates = self._parser._template_proc
return templates._find_definition(alias)
+ def _get_aliases(self):
+ templates = self._parser._template_proc
+ return templates._dump_definitions()
+
class MessageDispatcher(ConnectionHandler):
def __init__(self, log_ctl):
super(MessageDispatcher, self).__init__()
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py
index e47b025..2fbc7a6 100644
--- a/lnst/Controller/Task.py
+++ b/lnst/Controller/Task.py
@@ -119,6 +119,15 @@ class ControllerAPI(object):
except XmlTemplateError:
return None
+ def get_aliases(self):
+ """
+ Get all user defined aliases.
+
+ :return: names and values of a user defined aliases
+ :rtype: dict
+ """
+ return self._ctl._get_aliases()
+
def connect_PerfRepo(self, mapping_file, url=None, username=None, password=None):
if not self._perf_repo_api.connected():
if url is None:
diff --git a/lnst/Controller/XmlTemplates.py b/lnst/Controller/XmlTemplates.py
index e4577cb..a1541db 100644
--- a/lnst/Controller/XmlTemplates.py
+++ b/lnst/Controller/XmlTemplates.py
@@ -302,6 +302,16 @@ class XmlTemplates:
err = "Alias '%s' is not defined here" % name
raise XmlTemplateError(err)
+ def _dump_definitions(self):
+ dump = self._overriden_aliases.copy()
+
+ for level in self._definitions:
+ for name in level:
+ if not name in dump:
+ dump[name] = level[name]
+
+ return dump
+
def process_aliases(self, element):
""" Expand aliases within an element and its children
--
2.4.3
8 years, 3 months
[PATCH 1/2] InterfaceManager: Add speed setting methods
by Ido Schimmel
In order to test speed negotiation it is useful to have methods that
can change the speed of an interface.
The first method, 'set_speed', allows one to specify a speed (in Mb/s,
as in ethtool) to be set on an interface. At its lowest level, it's
implemented by calling 'ethtool' with desired 'speed' parameter and
'autoneg' set to 'off'. This is needed in order to prevent the driver
from advertising any other speeds.
On the other end of the link, the 'set_autoneg' method should be used
(again, implemented via 'ethtool'). When set it basically tells the
driver to advertise all the supported speeds.
To make sure no interface is left with auto negotiation off, set auto
negotation on when the Ethernet device is deconfigured.
Note that it's possible to tell the driver which speed and duplex to
advertise in autonegotiation, but for now we omit that and simply
advertise all of them. If needed, this can be added in the future.
Reviewed-by: Jiri Pirko <jiri(a)mellanox.com>
Signed-off-by: Ido Schimmel <idosch(a)mellanox.com>
---
lnst/Controller/Machine.py | 6 ++++++
lnst/Controller/Task.py | 6 ++++++
lnst/Slave/InterfaceManager.py | 6 ++++++
lnst/Slave/NetConfigDevice.py | 1 +
lnst/Slave/NetTestSlave.py | 18 ++++++++++++++++++
5 files changed, 37 insertions(+)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index 7281203..89ea05a 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -779,6 +779,12 @@ class Interface(object):
self._machine._rpc_call_x(self._netns, "del_br_fdb",
self._id, br_fdb_info)
+ def set_speed(self, speed):
+ self._machine._rpc_call_x(self._netns, "set_speed", self._id, speed)
+
+ def set_autoneg(self):
+ self._machine._rpc_call_x(self._netns, "set_autoneg", self._id)
+
class StaticInterface(Interface):
""" Static interface
diff --git a/lnst/Controller/Task.py b/lnst/Controller/Task.py
index e47b025..0ae1b25 100644
--- a/lnst/Controller/Task.py
+++ b/lnst/Controller/Task.py
@@ -528,6 +528,12 @@ class InterfaceAPI(object):
_self._if.del_br_fdb({"hwaddr": hwaddr, "self": self, "master": master,
"vlan_id": vlan_tci})
+ def set_speed(self, speed):
+ return self._if.set_speed(speed)
+
+ def set_autoneg(self):
+ return self._if.set_autoneg()
+
class ModuleAPI(object):
""" An API class representing a module. """
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index a99c2ae..be45153 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -530,3 +530,9 @@ class Device(object):
"mtu": self._mtu,
"driver": self._driver}
return if_data
+
+ def set_speed(self, speed):
+ exec_cmd("ethtool -s %s speed %s autoneg off" % (self._name, speed))
+
+ def set_autoneg(self):
+ exec_cmd("ethtool -s %s autoneg on" % self._name)
diff --git a/lnst/Slave/NetConfigDevice.py b/lnst/Slave/NetConfigDevice.py
index 809c0c5..7d41873 100644
--- a/lnst/Slave/NetConfigDevice.py
+++ b/lnst/Slave/NetConfigDevice.py
@@ -90,6 +90,7 @@ class NetConfigDeviceEth(NetConfigDeviceGeneric):
def deconfigure(self):
config = self._dev_config
+ exec_cmd("ethtool -s %s autoneg on" % config["name"])
if "netem_cmd" in config:
exec_cmd(config["netem_cmd"].replace("add", "del"))
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index d65db5a..7a6ac88 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -729,6 +729,24 @@ class SlaveMethods:
brt.del_fdb(br_fdb_info)
return True
+ def set_speed(self, if_id, speed):
+ dev = self._if_manager.get_mapped_device(if_id)
+ if dev is not None:
+ dev.set_speed(speed)
+ else:
+ dev.error("Device with id '%s' not found." % if_id)
+ return False
+ return True
+
+ def set_autoneg(self, if_id):
+ dev = self._if_manager.get_mapped_device(if_id)
+ if dev is not None:
+ dev.set_autoneg()
+ else:
+ dev.error("Device with id '%s' not found." % if_id)
+ return False
+ return True
+
class ServerHandler(ConnectionHandler):
def __init__(self, addr):
super(ServerHandler, self).__init__()
--
2.4.10
8 years, 3 months
[PATCH] regression-tests: update config in regression-tests
by Jiri Prochazka
We now use new section [pools] in config files for specifying pool dirs,
this hasn't been updated yet in regression tests. This patch fixes that.
Signed-off-by: Jiri Prochazka <jprochaz(a)redhat.com>
---
regression-tests/env/lnst-ctl.conf | 4 +++-
regression-tests/tests/22/lnst-ctl.conf | 4 ++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/regression-tests/env/lnst-ctl.conf b/regression-tests/env/lnst-ctl.conf
index a2f9343..12db8c9 100644
--- a/regression-tests/env/lnst-ctl.conf
+++ b/regression-tests/env/lnst-ctl.conf
@@ -1,7 +1,6 @@
[environment]
mac_pool_range = 52:54:01:00:00:01 52:54:01:FF:FF:FF
rpcport = 9999
-machine_pool_dirs = ./pool/
test_tool_dirs = ./test_tools
test_module_dirs = ./test_modules
log_dir = ./Logs
@@ -12,3 +11,6 @@ allow_virtual = True
faded = extended(242) default 0
info = extended(228) default 1
warning = extended(208) default 1
+
+[pools]
+lnst = ./pool/
diff --git a/regression-tests/tests/22/lnst-ctl.conf b/regression-tests/tests/22/lnst-ctl.conf
index 81f1561..9dff9d0 100644
--- a/regression-tests/tests/22/lnst-ctl.conf
+++ b/regression-tests/tests/22/lnst-ctl.conf
@@ -1,2 +1,2 @@
-[environment]
-machine_pool_dirs += ./pool
+[pools]
+lnst = ./pool
--
2.4.3
8 years, 3 months