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