api: Cleanup APIs interface.api
[vpp.git] / test / test_memif.py
1 import socket
2 import unittest
3
4 from scapy.layers.l2 import Ether
5 from scapy.layers.inet import IP, ICMP
6 import six
7
8 from framework import VppTestCase, VppTestRunner, running_extended_tests
9 from remote_test import RemoteClass, RemoteVppTestCase
10 from vpp_memif import MEMIF_MODE, MEMIF_ROLE, remove_all_memif_vpp_config, \
11     VppSocketFilename, VppMemif
12 from vpp_ip_route import VppIpRoute, VppRoutePath
13
14
15 class TestMemif(VppTestCase):
16     """ Memif Test Case """
17
18     @classmethod
19     def setUpClass(cls):
20         # fork new process before client connects to VPP
21         cls.remote_test = RemoteClass(RemoteVppTestCase)
22         cls.remote_test.start_remote()
23         cls.remote_test.set_request_timeout(10)
24         super(TestMemif, cls).setUpClass()
25         cls.remote_test.setUpClass(cls.tempdir)
26         cls.create_pg_interfaces(range(1))
27         for pg in cls.pg_interfaces:
28             pg.config_ip4()
29             pg.admin_up()
30             pg.resolve_arp()
31
32     @classmethod
33     def tearDownClass(cls):
34         cls.remote_test.tearDownClass()
35         cls.remote_test.quit_remote()
36         for pg in cls.pg_interfaces:
37             pg.unconfig_ip4()
38             pg.set_table_ip4(0)
39             pg.admin_down()
40         super(TestMemif, cls).tearDownClass()
41
42     def tearDown(self):
43         remove_all_memif_vpp_config(self)
44         remove_all_memif_vpp_config(self.remote_test)
45         super(TestMemif, self).tearDown()
46
47     def _check_socket_filename(self, dump, socket_id, filename):
48         for d in dump:
49             if (d.socket_id == socket_id) and (
50                     d.socket_filename.rstrip(b"\0") == filename):
51                 return True
52         return False
53
54     def test_memif_socket_filename_add_del(self):
55         """ Memif socket filename add/del """
56
57         # dump default socket filename
58         dump = self.vapi.memif_socket_filename_dump()
59         self.assertTrue(
60             self._check_socket_filename(
61                 dump, 0, b"%s/memif.sock" % six.ensure_binary(
62                     self.tempdir, encoding='utf-8')))
63
64         memif_sockets = []
65         # existing path
66         memif_sockets.append(
67             VppSocketFilename(
68                 self, 1, b"%s/memif1.sock" % six.ensure_binary(
69                     self.tempdir, encoding='utf-8')))
70         # default path (test tempdir)
71         memif_sockets.append(
72             VppSocketFilename(
73                 self,
74                 2,
75                 b"memif2.sock",
76                 add_default_folder=True))
77         # create new folder in default folder
78         memif_sockets.append(
79             VppSocketFilename(
80                 self,
81                 3,
82                 b"sock/memif3.sock",
83                 add_default_folder=True))
84
85         for sock in memif_sockets:
86             sock.add_vpp_config()
87             dump = sock.query_vpp_config()
88             self.assertTrue(
89                 self._check_socket_filename(
90                     dump,
91                     sock.socket_id,
92                     sock.socket_filename))
93
94         for sock in memif_sockets:
95             sock.remove_vpp_config()
96
97         dump = self.vapi.memif_socket_filename_dump()
98         self.assertTrue(
99             self._check_socket_filename(
100                 dump, 0, b"%s/memif.sock" % six.ensure_binary(
101                     self.tempdir, encoding='utf-8')))
102
103     def _create_delete_test_one_interface(self, memif):
104         memif.add_vpp_config()
105
106         dump = memif.query_vpp_config()
107
108         self.assertTrue(dump)
109         self.assertEqual(dump.sw_if_index, memif.sw_if_index)
110         self.assertEqual(dump.role, memif.role)
111         self.assertEqual(dump.mode, memif.mode)
112         if (memif.socket_id is not None):
113             self.assertEqual(dump.socket_id, memif.socket_id)
114
115         memif.remove_vpp_config()
116
117         dump = memif.query_vpp_config()
118
119         self.assertFalse(dump)
120
121     def _connect_test_one_interface(self, memif):
122         self.assertTrue(memif.wait_for_link_up(5))
123         dump = memif.query_vpp_config()
124
125         if memif.role == MEMIF_ROLE.SLAVE:
126             self.assertEqual(dump.ring_size, memif.ring_size)
127             self.assertEqual(dump.buffer_size, memif.buffer_size)
128         else:
129             self.assertEqual(dump.ring_size, 1)
130             self.assertEqual(dump.buffer_size, 0)
131
132     def _connect_test_interface_pair(self, memif0, memif1):
133         memif0.add_vpp_config()
134         memif1.add_vpp_config()
135
136         memif0.admin_up()
137         memif1.admin_up()
138
139         self._connect_test_one_interface(memif0)
140         self._connect_test_one_interface(memif1)
141
142         memif0.remove_vpp_config()
143         memif1.remove_vpp_config()
144
145     def test_memif_create_delete(self):
146         """ Memif create/delete interface """
147
148         memif = VppMemif(self, MEMIF_ROLE.SLAVE, MEMIF_MODE.ETHERNET)
149         self._create_delete_test_one_interface(memif)
150         memif.role = MEMIF_ROLE.MASTER
151         self._create_delete_test_one_interface(memif)
152
153     def test_memif_create_custom_socket(self):
154         """ Memif create with non-default socket filename """
155
156         memif_sockets = []
157         # existing path
158         memif_sockets.append(
159             VppSocketFilename(
160                 self, 1, b"%s/memif1.sock" % six.ensure_binary(
161                     self.tempdir, encoding='utf-8')))
162         # default path (test tempdir)
163         memif_sockets.append(
164             VppSocketFilename(
165                 self,
166                 2,
167                 b"memif2.sock",
168                 add_default_folder=True))
169         # create new folder in default folder
170         memif_sockets.append(
171             VppSocketFilename(
172                 self,
173                 3,
174                 b"sock/memif3.sock",
175                 add_default_folder=True))
176
177         memif = VppMemif(self, MEMIF_ROLE.SLAVE, MEMIF_MODE.ETHERNET)
178
179         for sock in memif_sockets:
180             sock.add_vpp_config()
181             memif.socket_id = sock.socket_id
182             memif.role = MEMIF_ROLE.SLAVE
183             self._create_delete_test_one_interface(memif)
184             memif.role = MEMIF_ROLE.MASTER
185             self._create_delete_test_one_interface(memif)
186
187     def test_memif_connect(self):
188         """ Memif connect """
189         memif = VppMemif(self, MEMIF_ROLE.SLAVE,  MEMIF_MODE.ETHERNET,
190                          ring_size=1024, buffer_size=2048)
191
192         remote_socket = VppSocketFilename(self.remote_test, 1,
193                                           b"%s/memif.sock" % six.ensure_binary(
194                                               self.tempdir, encoding='utf-8'))
195         remote_socket.add_vpp_config()
196
197         remote_memif = VppMemif(self.remote_test, MEMIF_ROLE.MASTER,
198                                 MEMIF_MODE.ETHERNET, socket_id=1,
199                                 ring_size=1024, buffer_size=2048)
200
201         self._connect_test_interface_pair(memif, remote_memif)
202
203         memif.role = MEMIF_ROLE.MASTER
204         remote_memif.role = MEMIF_ROLE.SLAVE
205
206         self._connect_test_interface_pair(memif, remote_memif)
207
208     def _create_icmp(self, pg, memif, num):
209         pkts = []
210         for i in range(num):
211             pkt = (Ether(dst=pg.local_mac, src=pg.remote_mac) /
212                    IP(src=pg.remote_ip4, dst=memif.ip_prefix.address) /
213                    ICMP(id=memif.if_id, type='echo-request', seq=i))
214             pkts.append(pkt)
215         return pkts
216
217     def _verify_icmp(self, pg, memif, rx, seq):
218         ip = rx[IP]
219         self.assertEqual(ip.src, memif.ip_prefix.address)
220         self.assertEqual(ip.dst, pg.remote_ip4)
221         self.assertEqual(ip.proto, 1)
222         icmp = rx[ICMP]
223         self.assertEqual(icmp.type, 0)  # echo-reply
224         self.assertEqual(icmp.id, memif.if_id)
225         self.assertEqual(icmp.seq, seq)
226
227     def test_memif_ping(self):
228         """ Memif ping """
229
230         memif = VppMemif(self, MEMIF_ROLE.SLAVE,  MEMIF_MODE.ETHERNET)
231
232         remote_socket = VppSocketFilename(self.remote_test, 1,
233                                           b"%s/memif.sock" % six.ensure_binary(
234                                               self.tempdir, encoding='utf-8'))
235         remote_socket.add_vpp_config()
236
237         remote_memif = VppMemif(self.remote_test, MEMIF_ROLE.MASTER,
238                                 MEMIF_MODE.ETHERNET, socket_id=1)
239
240         memif.add_vpp_config()
241         memif.config_ip4()
242         memif.admin_up()
243
244         remote_memif.add_vpp_config()
245         remote_memif.config_ip4()
246         remote_memif.admin_up()
247
248         self.assertTrue(memif.wait_for_link_up(5))
249         self.assertTrue(remote_memif.wait_for_link_up(5))
250
251         # add routing to remote vpp
252         route = VppIpRoute(self.remote_test, self.pg0._local_ip4_subnet, 24,
253                            [VppRoutePath(memif.ip_prefix.address, 0xffffffff)],
254                            register=False)
255
256         route.add_vpp_config()
257
258         # create ICMP echo-request from local pg to remote memif
259         packet_num = 10
260         pkts = self._create_icmp(self.pg0, remote_memif, packet_num)
261
262         self.pg0.add_stream(pkts)
263         self.pg_enable_capture(self.pg_interfaces)
264         self.pg_start()
265         capture = self.pg0.get_capture(packet_num, timeout=2)
266         seq = 0
267         for c in capture:
268             self._verify_icmp(self.pg0, remote_memif, c, seq)
269             seq += 1
270
271         route.remove_vpp_config()
272
273
274 if __name__ == '__main__':
275     unittest.main(testRunner=VppTestRunner)