From: Ondrej Lichtner <olichtne(a)redhat.com>
These two new methods are used to create paired interfaces, such as
veth. Since these devices are created together LNST representation of
the devices needs to reflect that. After device creation the method also
takes care of moving the devices to the correct network namespaces.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Slave/InterfaceManager.py | 36 +++++++++++++++++
lnst/Slave/NetTestSlave.py | 89 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 125 insertions(+)
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
index 3695fe2..e30b52a 100644
--- a/lnst/Slave/InterfaceManager.py
+++ b/lnst/Slave/InterfaceManager.py
@@ -156,6 +156,24 @@ class InterfaceManager(object):
self._tmp_mapping[if_id] = device
return config["name"]
+ def create_device_pair(self, if_id1, config1, if_id2, config2):
+ name1, name2 = self.assign_name(config1)
+ config1["name"] = name1
+ config2["name"] = name2
+ config1["peer_name"] = name2
+ config2["peer_name"] = name1
+
+ device1 = Device(self)
+ device2 = Device(self)
+
+ device1.set_configuration(config1)
+ device2.set_configuration(config2)
+ device1.create()
+
+ self._tmp_mapping[if_id1] = device1
+ self._tmp_mapping[if_id2] = device2
+ return name1, name2
+
def _is_name_used(self, name):
for device in self._devices.itervalues():
if name == device.get_name():
@@ -168,6 +186,16 @@ class InterfaceManager(object):
index += 1
return prefix + str(index)
+ def _assign_name_pair(self, prefix):
+ index1 = 0
+ index2 = 0
+ while (self._is_name_used(prefix + str(index1))):
+ index1 += 1
+ index2 = index1 + 1
+ while (self._is_name_used(prefix + str(index2))):
+ index2 += 1
+ return prefix + str(index1), prefix + str(index2)
+
def assign_name(self, config):
if "name" in config:
return config["name"]
@@ -193,6 +221,10 @@ class InterfaceManager(object):
vlan_tci = get_option(config, "vlan_tci")
prefix = "%s.%s_" % (netdev_name, vlan_tci)
return self._assign_name_generic(prefix)
+ elif dev_type == "veth":
+ return self._assign_name_pair("veth")
+ else:
+ return self._assign_name_generic("dev")
class Device(object):
def __init__(self, if_manager):
@@ -306,6 +338,10 @@ class Device(object):
def get_configuration(self):
return self._conf
+ def del_configuration(self):
+ self._conf = None
+ self._conf_dict = None
+
def clear_configuration(self):
if self._master["primary"]:
primary_id = self._master["primary"]
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index ca714e2..d2f7834 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -166,6 +166,95 @@ class SlaveMethods:
dev.configure()
return dev_name
+ def create_if_pair(self, if_id1, config1, if_id2, config2):
+ dev_names = self._if_manager.create_device_pair(if_id1, config1,
+ if_id2, config2)
+ dev1 = self._if_manager.get_mapped_device(if_id1)
+ dev2 = self._if_manager.get_mapped_device(if_id2)
+
+ while dev1.get_if_index() == None and dev2.get_if_index() == None:
+ msgs = self._server_handler.get_messages_from_con('netlink')
+ for msg in msgs:
+ self._if_manager.handle_netlink_msgs(msg[1]["data"])
+
+ if config1["netns"] != None:
+ hwaddr = dev1.get_hwaddr()
+ self.set_if_netns(if_id1, config1["netns"])
+
+ msg = {"type": "command", "method_name":
"map_if_by_hwaddr",
+ "args": [if_id1, hwaddr]}
+ self._server_handler.send_data_to_netns(config1["netns"], msg)
+ result = self._slave_server.wait_for_result(config1["netns"])
+ if len(result["result"]) != 1:
+ raise Exception("Mapping failed.")
+
+ msg = {"type": "command", "method_name":
"configure_interface",
+ "args": [if_id1, config1]}
+ self._server_handler.send_data_to_netns(config1["netns"], msg)
+ result = self._slave_server.wait_for_result(config1["netns"])
+ if result["result"] != True:
+ raise Exception("Configuration failed.")
+ else:
+ dev1.configure()
+ if config2["netns"] != None:
+ hwaddr = dev2.get_hwaddr()
+ self.set_if_netns(if_id2, config2["netns"])
+
+ msg = {"type": "command", "method_name":
"map_if_by_hwaddr",
+ "args": [if_id2, hwaddr]}
+ self._server_handler.send_data_to_netns(config2["netns"], msg)
+ result = self._slave_server.wait_for_result(config2["netns"])
+ if len(result["result"]) != 1:
+ raise Exception("Mapping failed.")
+
+ msg = {"type": "command", "method_name":
"configure_interface",
+ "args": [if_id2, config2]}
+ self._server_handler.send_data_to_netns(config2["netns"], msg)
+ result = self._slave_server.wait_for_result(config2["netns"])
+ if result["result"] != True:
+ raise Exception("Configuration failed.")
+ else:
+ dev2.configure()
+ return dev_names
+
+ def deconfigure_if_pair(self, if_id1, if_id2):
+ dev1 = self._if_manager.get_mapped_device(if_id1)
+ dev2 = self._if_manager.get_mapped_device(if_id2)
+
+ if dev1.get_netns() == None:
+ dev1.deconfigure()
+ else:
+ netns = dev1.get_netns()
+
+ msg = {"type": "command", "method_name":
"deconfigure_interface",
+ "args": [if_id1]}
+ self._server_handler.send_data_to_netns(netns, msg)
+ result = self._slave_server.wait_for_result(netns)
+ if result["result"] != True:
+ raise Exception("Deconfiguration failed.")
+
+ self.return_if_netns(if_id1)
+
+ if dev2.get_netns() == None:
+ dev2.deconfigure()
+ else:
+ netns = dev2.get_netns()
+
+ msg = {"type": "command", "method_name":
"deconfigure_interface",
+ "args": [if_id2]}
+ self._server_handler.send_data_to_netns(netns, msg)
+ result = self._slave_server.wait_for_result(netns)
+ if result["result"] != True:
+ raise Exception("Deconfiguration failed.")
+
+ self.return_if_netns(if_id2)
+
+ dev1.destroy()
+ dev2.destroy()
+ dev1.del_configuration()
+ dev2.del_configuration()
+ return True
+
def deconfigure_interface(self, if_id):
device = self._if_manager.get_mapped_device(if_id)
device.clear_configuration()
--
1.9.3