3 # Utility functions for QEMU tests ##
8 import multiprocessing as mp
11 def can_create_namespaces(namespace="vpp_chk_4212"):
12 """Check if the environment allows creating the namespaces"""
15 result = subprocess.run(["ip", "netns", "add", namespace], capture_output=True)
16 if result.returncode != 0:
18 result = subprocess.run(["ip", "netns", "del", namespace], capture_output=True)
19 if result.returncode != 0:
26 def create_namespace(ns):
27 """create one or more namespaces.
30 ns -- a string value or an iterable of namespace names
32 if isinstance(ns, str):
37 for namespace in namespaces:
38 result = subprocess.run(["ip", "netns", "add", namespace])
39 if result.returncode != 0:
40 raise Exception(f"Error while creating namespace {namespace}")
41 except subprocess.CalledProcessError as e:
42 raise Exception("Error creating namespace:", e.output)
45 def add_namespace_route(ns, prefix, gw_ip):
46 """Add a route to a namespace.
49 ns -- namespace string value
50 prefix -- NETWORK/MASK or "default"
55 ["ip", "netns", "exec", ns, "ip", "route", "add", prefix, "via", gw_ip],
58 except subprocess.CalledProcessError as e:
59 raise Exception("Error adding route to namespace:", e.output)
62 def delete_host_interfaces(*host_interface_names):
63 """Delete host interfaces.
66 host_interface_names - sequence of host interface names to be deleted
68 for host_interface_name in host_interface_names:
71 ["ip", "link", "del", host_interface_name], capture_output=True
73 except subprocess.CalledProcessError as e:
74 raise Exception("Error deleting host interface:", e.output)
77 def create_host_interface(
78 host_interface_name, vpp_interface_name, host_namespace, *host_ip_prefixes
80 """Create a host interface of type veth.
83 host_interface_name -- name of the veth interface on the host side
84 vpp_interface_name -- name of the veth interface on the VPP side
85 host_namespace -- host namespace into which the host_interface needs to be set
86 host_ip_prefixes -- a sequence of ip/prefix-lengths to be set
90 process = subprocess.run(
105 if process.returncode != 0:
106 print(f"Error creating host interface: {process.stderr}")
109 process = subprocess.run(
110 ["ip", "link", "set", host_interface_name, "netns", host_namespace],
113 if process.returncode != 0:
114 print(f"Error setting host interface namespace: {process.stderr}")
117 process = subprocess.run(
118 ["ip", "link", "set", "dev", vpp_interface_name, "up"], capture_output=True
120 if process.returncode != 0:
121 print(f"Error bringing up the host interface: {process.stderr}")
124 process = subprocess.run(
139 if process.returncode != 0:
141 f"Error bringing up the host interface in namespace: "
146 for host_ip_prefix in host_ip_prefixes:
147 process = subprocess.run(
162 if process.returncode != 0:
164 f"Error setting ip prefix on the host interface: "
168 except subprocess.CalledProcessError as e:
169 raise Exception("Error adding route to namespace:", e.output)
172 def set_interface_mtu(namespace, interface, mtu, logger):
173 """set an mtu number on a linux device interface."""
174 args = ["ip", "link", "set", "mtu", str(mtu), "dev", interface]
176 args = ["ip", "netns", "exec", namespace] + args
179 f"Setting mtu:{mtu} on linux interface:{interface} "
180 f"in namespace:{namespace}"
183 except subprocess.CalledProcessError as e:
184 raise Exception("Error updating mtu:", e.output)
187 def enable_interface_gso(namespace, interface):
188 """enable gso offload on a linux device interface."""
189 args = ["ethtool", "-K", interface, "rx", "on", "tx", "on"]
191 args = ["ip", "netns", "exec", namespace] + args
193 process = subprocess.run(args, capture_output=True)
194 if process.returncode != 0:
196 f"Error enabling GSO offload on linux device interface: "
200 except subprocess.CalledProcessError as e:
201 raise Exception("Error enabling gso:", e.output)
204 def disable_interface_gso(namespace, interface):
205 """disable gso offload on a linux device interface."""
206 args = ["ethtool", "-K", interface, "rx", "off", "tx", "off"]
208 args = ["ip", "netns", "exec", namespace] + args
210 process = subprocess.run(args, capture_output=True)
211 if process.returncode != 0:
213 f"Error disabling GSO offload on linux device interface: "
217 except subprocess.CalledProcessError as e:
218 raise Exception("Error disabling gso:", e.output)
221 def delete_namespace(ns):
222 """delete one or more namespaces.
225 namespaces -- a list of namespace names
227 if isinstance(ns, str):
232 for namespace in namespaces:
233 result = subprocess.run(
234 ["ip", "netns", "del", namespace], capture_output=True
236 if result.returncode != 0:
237 raise Exception(f"Error while deleting namespace {namespace}")
238 except subprocess.CalledProcessError as e:
239 raise Exception("Error deleting namespace:", e.output)
242 def list_namespace(ns):
243 """List the IP address of a namespace"""
245 subprocess.run(["ip", "netns", "exec", ns, "ip", "addr"])
246 except subprocess.CalledProcessError as e:
247 raise Exception("Error listing namespace IP:", e.output)
250 def libmemif_test_app(memif_sock_path, logger):
251 """Build & run the libmemif test_app for memif interface testing."""
252 test_dir = os.path.dirname(os.path.realpath(__file__))
253 ws_root = os.path.dirname(test_dir)
254 libmemif_app = os.path.join(
255 ws_root, "extras", "libmemif", "build", "examples", "test_app"
258 def build_libmemif_app():
259 if not os.path.exists(libmemif_app):
260 print(f"Building app:{libmemif_app} for memif interface testing")
261 libmemif_app_dir = os.path.join(ws_root, "extras", "libmemif", "build")
262 if not os.path.exists(libmemif_app_dir):
263 os.makedirs(libmemif_app_dir)
264 os.chdir(libmemif_app_dir)
266 p = subprocess.run(["cmake", ".."], capture_output=True)
267 logger.debug(p.stdout)
268 if p.returncode != 0:
269 print(f"libmemif app:{libmemif_app} cmake error:{p.stderr}")
271 p = subprocess.run(["make"], capture_output=True)
272 logger.debug(p.stdout)
273 if p.returncode != 0:
274 print(f"Error building libmemif app:{p.stderr}")
276 except subprocess.CalledProcessError as e:
277 raise Exception("Error building libmemif_test_app:", e.output)
279 def start_libmemif_app():
280 """Restart once if the initial run fails."""
283 if not os.path.exists(libmemif_app):
285 f"Error could not locate the libmemif test app:{libmemif_app}"
287 args = [libmemif_app, "-b", "9216", "-s", memif_sock_path]
288 while run < max_tries:
290 process = subprocess.run(args, capture_output=True)
291 logger.debug(process.stdout)
292 if process.returncode != 0:
293 msg = f"Error starting libmemif app:{libmemif_app}"
297 msg = f"re-starting libmemif app:{libmemif_app}"
306 process = mp.Process(target=start_libmemif_app)