blob: e7e21a01b7359fee8121e7a38905d6eed409025a [file] [log] [blame]
Naveen Joy7ea7ab52021-05-11 10:31:18 -07001#!/usr/bin/env python
2
3# Utility functions for QEMU tests ##
4
5import subprocess
Naveen Joye4168932022-10-04 14:22:05 -07006import sys
Naveen Joy7ea7ab52021-05-11 10:31:18 -07007
8
adrianvillin30f26002023-10-24 12:53:10 +02009def can_create_namespaces(namespace="vpp_chk_4212"):
Andrew Yourtchenko9ba6dcf2023-06-20 14:52:08 +000010 """Check if the environment allows creating the namespaces"""
11
12 try:
Andrew Yourtchenko9ba6dcf2023-06-20 14:52:08 +000013 result = subprocess.run(["ip", "netns", "add", namespace], capture_output=True)
14 if result.returncode != 0:
15 return False
16 result = subprocess.run(["ip", "netns", "del", namespace], capture_output=True)
17 if result.returncode != 0:
18 return False
19 return True
adrianvillin30f26002023-10-24 12:53:10 +020020 except Exception:
Andrew Yourtchenko9ba6dcf2023-06-20 14:52:08 +000021 return False
22
23
Naveen Joy7ea7ab52021-05-11 10:31:18 -070024def create_namespace(ns):
Naveen Joye4168932022-10-04 14:22:05 -070025 """create one or more namespaces.
26
27 arguments:
28 ns -- a string value or an iterable of namespace names
29 """
30 if isinstance(ns, str):
31 namespaces = [ns]
32 else:
33 namespaces = ns
Naveen Joy7ea7ab52021-05-11 10:31:18 -070034 try:
Naveen Joye4168932022-10-04 14:22:05 -070035 for namespace in namespaces:
Andrew Yourtchenko9ba6dcf2023-06-20 14:52:08 +000036 result = subprocess.run(["ip", "netns", "add", namespace])
37 if result.returncode != 0:
38 raise Exception(f"Error while creating namespace {namespace}")
Naveen Joy7ea7ab52021-05-11 10:31:18 -070039 except subprocess.CalledProcessError as e:
40 raise Exception("Error creating namespace:", e.output)
41
42
Naveen Joye4168932022-10-04 14:22:05 -070043def add_namespace_route(ns, prefix, gw_ip):
44 """Add a route to a namespace.
45
46 arguments:
47 ns -- namespace string value
48 prefix -- NETWORK/MASK or "default"
49 gw_ip -- Gateway IP
50 """
51 try:
52 subprocess.run(
53 ["ip", "netns", "exec", ns, "ip", "route", "add", prefix, "via", gw_ip],
54 capture_output=True,
55 )
56 except subprocess.CalledProcessError as e:
57 raise Exception("Error adding route to namespace:", e.output)
58
59
60def delete_host_interfaces(*host_interface_names):
61 """Delete host interfaces.
62
63 arguments:
64 host_interface_names - sequence of host interface names to be deleted
65 """
66 for host_interface_name in host_interface_names:
67 try:
68 subprocess.run(
69 ["ip", "link", "del", host_interface_name], capture_output=True
70 )
71 except subprocess.CalledProcessError as e:
72 raise Exception("Error deleting host interface:", e.output)
73
74
75def create_host_interface(
76 host_interface_name, vpp_interface_name, host_namespace, *host_ip_prefixes
77):
78 """Create a host interface of type veth.
79
80 arguments:
81 host_interface_name -- name of the veth interface on the host side
82 vpp_interface_name -- name of the veth interface on the VPP side
83 host_namespace -- host namespace into which the host_interface needs to be set
84 host_ip_prefixes -- a sequence of ip/prefix-lengths to be set
85 on the host_interface
86 """
87 try:
88 process = subprocess.run(
89 [
90 "ip",
91 "link",
92 "add",
93 "name",
94 vpp_interface_name,
95 "type",
96 "veth",
97 "peer",
98 "name",
99 host_interface_name,
100 ],
101 capture_output=True,
102 )
103 if process.returncode != 0:
104 print(f"Error creating host interface: {process.stderr}")
105 sys.exit(1)
106
107 process = subprocess.run(
108 ["ip", "link", "set", host_interface_name, "netns", host_namespace],
109 capture_output=True,
110 )
111 if process.returncode != 0:
112 print(f"Error setting host interface namespace: {process.stderr}")
113 sys.exit(1)
114
115 process = subprocess.run(
116 ["ip", "link", "set", "dev", vpp_interface_name, "up"], capture_output=True
117 )
118 if process.returncode != 0:
119 print(f"Error bringing up the host interface: {process.stderr}")
120 sys.exit(1)
121
122 process = subprocess.run(
123 [
124 "ip",
125 "netns",
126 "exec",
127 host_namespace,
128 "ip",
129 "link",
130 "set",
131 "dev",
132 host_interface_name,
133 "up",
134 ],
135 capture_output=True,
136 )
137 if process.returncode != 0:
138 print(
139 f"Error bringing up the host interface in namespace: "
140 f"{process.stderr}"
141 )
142 sys.exit(1)
143
144 for host_ip_prefix in host_ip_prefixes:
145 process = subprocess.run(
146 [
147 "ip",
148 "netns",
149 "exec",
150 host_namespace,
151 "ip",
152 "addr",
153 "add",
154 host_ip_prefix,
155 "dev",
156 host_interface_name,
157 ],
158 capture_output=True,
159 )
160 if process.returncode != 0:
161 print(
162 f"Error setting ip prefix on the host interface: "
163 f"{process.stderr}"
164 )
165 sys.exit(1)
166 except subprocess.CalledProcessError as e:
167 raise Exception("Error adding route to namespace:", e.output)
168
169
170def set_interface_mtu(namespace, interface, mtu, logger):
171 """set an mtu number on a linux device interface."""
172 args = ["ip", "link", "set", "mtu", str(mtu), "dev", interface]
173 if namespace:
174 args = ["ip", "netns", "exec", namespace] + args
175 try:
176 logger.debug(
177 f"Setting mtu:{mtu} on linux interface:{interface} "
178 f"in namespace:{namespace}"
179 )
180 subprocess.run(args)
181 except subprocess.CalledProcessError as e:
182 raise Exception("Error updating mtu:", e.output)
183
184
185def enable_interface_gso(namespace, interface):
186 """enable gso offload on a linux device interface."""
187 args = ["ethtool", "-K", interface, "rx", "on", "tx", "on"]
188 if namespace:
189 args = ["ip", "netns", "exec", namespace] + args
190 try:
191 process = subprocess.run(args, capture_output=True)
192 if process.returncode != 0:
193 print(
194 f"Error enabling GSO offload on linux device interface: "
195 f"{process.stderr}"
196 )
197 sys.exit(1)
198 except subprocess.CalledProcessError as e:
199 raise Exception("Error enabling gso:", e.output)
200
201
202def disable_interface_gso(namespace, interface):
203 """disable gso offload on a linux device interface."""
204 args = ["ethtool", "-K", interface, "rx", "off", "tx", "off"]
205 if namespace:
206 args = ["ip", "netns", "exec", namespace] + args
207 try:
208 process = subprocess.run(args, capture_output=True)
209 if process.returncode != 0:
210 print(
211 f"Error disabling GSO offload on linux device interface: "
212 f"{process.stderr}"
213 )
214 sys.exit(1)
215 except subprocess.CalledProcessError as e:
216 raise Exception("Error disabling gso:", e.output)
217
218
219def delete_namespace(namespaces):
220 """delete one or more namespaces.
221
222 arguments:
223 namespaces -- a list of namespace names
224 """
225 try:
226 for namespace in namespaces:
Andrew Yourtchenko9ba6dcf2023-06-20 14:52:08 +0000227 result = subprocess.run(
228 ["ip", "netns", "del", namespace], capture_output=True
229 )
230 if result.returncode != 0:
231 raise Exception(f"Error while deleting namespace {namespace}")
Naveen Joye4168932022-10-04 14:22:05 -0700232 except subprocess.CalledProcessError as e:
233 raise Exception("Error deleting namespace:", e.output)
234
235
Naveen Joy7ea7ab52021-05-11 10:31:18 -0700236def list_namespace(ns):
237 """List the IP address of a namespace"""
238 try:
239 subprocess.run(["ip", "netns", "exec", ns, "ip", "addr"])
240 except subprocess.CalledProcessError as e:
241 raise Exception("Error listing namespace IP:", e.output)