ipsec: allow receiving encrypted IP packets with TFC padding
[vpp.git] / test / vpp_qemu_utils.py
1 #!/usr/bin/env python
2
3 # Utility functions for QEMU tests ##
4
5 import subprocess
6 import sys
7
8
9 def can_create_namespaces(namespace="vpp_chk_4212"):
10     """Check if the environment allows creating the namespaces"""
11
12     try:
13         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
20     except Exception:
21         return False
22
23
24 def create_namespace(ns):
25     """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
34     try:
35         for namespace in namespaces:
36             result = subprocess.run(["ip", "netns", "add", namespace])
37             if result.returncode != 0:
38                 raise Exception(f"Error while creating namespace {namespace}")
39     except subprocess.CalledProcessError as e:
40         raise Exception("Error creating namespace:", e.output)
41
42
43 def 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
60 def 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
75 def 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
170 def 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
185 def 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
202 def 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
219 def delete_namespace(ns):
220     """delete one or more namespaces.
221
222     arguments:
223     namespaces -- a list of namespace names
224     """
225     if isinstance(ns, str):
226         namespaces = [ns]
227     else:
228         namespaces = ns
229     try:
230         for namespace in namespaces:
231             result = subprocess.run(
232                 ["ip", "netns", "del", namespace], capture_output=True
233             )
234             if result.returncode != 0:
235                 raise Exception(f"Error while deleting namespace {namespace}")
236     except subprocess.CalledProcessError as e:
237         raise Exception("Error deleting namespace:", e.output)
238
239
240 def list_namespace(ns):
241     """List the IP address of a namespace"""
242     try:
243         subprocess.run(["ip", "netns", "exec", ns, "ip", "addr"])
244     except subprocess.CalledProcessError as e:
245         raise Exception("Error listing namespace IP:", e.output)