tests: Use errno value rather than a specific int
[vpp.git] / test / test_lacp.py
1 #!/usr/bin/env python3
2
3 import unittest
4
5 from scapy.contrib.lacp import LACP, SlowProtocol, MarkerProtocol
6 from scapy.layers.l2 import Ether
7
8 from framework import VppTestCase
9 from asfframework import VppTestRunner
10 from vpp_memif import VppSocketFilename, VppMemif
11 from vpp_bond_interface import VppBondInterface
12 from vpp_papi import VppEnum
13
14 bond_mac = "02:02:02:02:02:02"
15 lacp_dst_mac = "01:80:c2:00:00:02"
16 LACP_COLLECTION_AND_DISTRIBUTION_STATE = 63
17
18
19 class TestMarker(VppTestCase):
20     """LACP Marker Protocol Test Case"""
21
22     @classmethod
23     def setUpClass(cls):
24         super().setUpClass()
25         # Test variables
26         cls.pkts_per_burst = 257  # Number of packets per burst
27         # create 3 pg interfaces
28         cls.create_pg_interfaces(range(1))
29
30         # packet sizes
31         cls.pg_if_packet_sizes = [64, 512, 1518]  # , 9018]
32
33         # setup all interfaces
34         for i in cls.pg_interfaces:
35             i.admin_up()
36
37     @classmethod
38     def tearDownClass(cls):
39         super().tearDownClass()
40
41     def setUp(self):
42         super().setUp()
43
44     def tearDown(self):
45         super().tearDown()
46
47     def show_commands_at_teardown(self):
48         self.logger.info(self.vapi.ppcli("show interface"))
49
50     def test_marker_request(self):
51         """Marker Request test"""
52
53         # topology
54         #
55         #             +-+      +-+
56         # memif1 -----|B|      |B|---- memif11
57         #             |o|      |o|
58         #             |n|------|n|
59         #             |d|      |d|
60         # pg0    -----|0|      |1|
61         #             +-+      +-+
62
63         socket1 = VppSocketFilename(
64             self, socket_id=1, socket_filename="%s/memif.sock1" % self.tempdir
65         )
66         socket1.add_vpp_config()
67
68         socket11 = VppSocketFilename(
69             self, socket_id=2, socket_filename="%s/memif.sock1" % self.tempdir
70         )
71         socket11.add_vpp_config()
72
73         memif1 = VppMemif(
74             self,
75             role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_MASTER,
76             mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET,
77             socket_id=1,
78         )
79         memif1.add_vpp_config()
80         memif1.admin_up()
81
82         memif11 = VppMemif(
83             self,
84             role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_SLAVE,
85             mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET,
86             socket_id=2,
87         )
88         memif11.add_vpp_config()
89         memif11.admin_up()
90
91         bond0 = VppBondInterface(
92             self,
93             mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP,
94             use_custom_mac=1,
95             mac_address=bond_mac,
96         )
97
98         bond0.add_vpp_config()
99         bond0.admin_up()
100
101         bond1 = VppBondInterface(
102             self, mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP
103         )
104         bond1.add_vpp_config()
105         bond1.admin_up()
106
107         bond0.add_member_vpp_bond_interface(sw_if_index=memif1.sw_if_index)
108         bond1.add_member_vpp_bond_interface(sw_if_index=memif11.sw_if_index)
109
110         # wait for memif protocol exchange and hardware carrier to come up
111         self.assertEqual(memif1.wait_for_link_up(10), True)
112         self.assertEqual(memif11.wait_for_link_up(10), True)
113
114         # verify memif1 in bond0
115         intfs = self.vapi.sw_member_interface_dump(sw_if_index=bond0.sw_if_index)
116         for intf in intfs:
117             self.assertEqual(intf.sw_if_index, memif1.sw_if_index)
118
119         # verify memif11 in bond1
120         intfs = self.vapi.sw_member_interface_dump(sw_if_index=bond1.sw_if_index)
121         for intf in intfs:
122             self.assertEqual(intf.sw_if_index, memif11.sw_if_index)
123
124         self.vapi.ppcli("trace add memif-input 100")
125
126         # create marker request
127         marker = (
128             Ether(src=bond_mac, dst=lacp_dst_mac)
129             / SlowProtocol()
130             / MarkerProtocol(
131                 marker_type=1,
132                 requester_port=1,
133                 requester_system=bond_mac,
134                 requester_transaction_id=1,
135             )
136         )
137
138         bond1.add_member_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
139         self.pg0.add_stream(marker)
140         self.pg_enable_capture(self.pg_interfaces)
141         self.pg_start()
142
143         show_trace = self.vapi.ppcli("show trace max 100")
144         self.assertIn("Marker Information TLV:", show_trace)
145
146         bond0.remove_vpp_config()
147         bond1.remove_vpp_config()
148
149
150 class TestLACP(VppTestCase):
151     """LACP Test Case"""
152
153     @classmethod
154     def setUpClass(cls):
155         super().setUpClass()
156
157     @classmethod
158     def tearDownClass(cls):
159         super().tearDownClass()
160
161     def setUp(self):
162         super().setUp()
163
164     def tearDown(self):
165         super().tearDown()
166
167     def show_commands_at_teardown(self):
168         self.logger.info(self.vapi.ppcli("show interface"))
169
170     def wait_for_lacp_connect(self, timeout, step=1):
171         while 1:
172             intfs = self.vapi.sw_interface_lacp_dump()
173             all_good = 1
174             for intf in intfs:
175                 if (intf.actor_state != LACP_COLLECTION_AND_DISTRIBUTION_STATE) or (
176                     intf.partner_state != LACP_COLLECTION_AND_DISTRIBUTION_STATE
177                 ):
178                     all_good = 0
179             if all_good == 1:
180                 return 1
181             self.sleep(step)
182             timeout -= step
183             if timeout <= 0:
184                 return 0
185
186     def wait_for_member_detach(self, bond, timeout, count, step=1):
187         while 1:
188             intfs = self.vapi.sw_bond_interface_dump(sw_if_index=bond.sw_if_index)
189             for intf in intfs:
190                 if (intf.members == count) and (intf.active_members == count):
191                     return 1
192                 else:
193                     self.sleep(1)
194                     timeout -= step
195                     if timeouut <= 0:
196                         return 0
197
198     def test_lacp_connect(self):
199         """LACP protocol connect test"""
200
201         # topology
202         #
203         #             +-+      +-+
204         # memif1 -----|B|      |B|---- memif11
205         #             |o|      |o|
206         #             |n|------|n|
207         #             |d|      |d|
208         # memif2 -----|0|      |1|---- memif12
209         #             +-+      +-+
210
211         socket1 = VppSocketFilename(
212             self, socket_id=1, socket_filename="%s/memif.sock1" % self.tempdir
213         )
214         socket1.add_vpp_config()
215
216         socket11 = VppSocketFilename(
217             self, socket_id=2, socket_filename="%s/memif.sock1" % self.tempdir
218         )
219         socket11.add_vpp_config()
220
221         socket2 = VppSocketFilename(
222             self, socket_id=3, socket_filename="%s/memif.sock2" % self.tempdir
223         )
224         socket2.add_vpp_config()
225
226         socket22 = VppSocketFilename(
227             self, socket_id=4, socket_filename="%s/memif.sock2" % self.tempdir
228         )
229         socket22.add_vpp_config()
230
231         memif1 = VppMemif(
232             self,
233             role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_MASTER,
234             mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET,
235             socket_id=1,
236         )
237         memif1.add_vpp_config()
238         memif1.admin_up()
239
240         memif11 = VppMemif(
241             self,
242             role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_SLAVE,
243             mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET,
244             socket_id=2,
245         )
246         memif11.add_vpp_config()
247         memif11.admin_up()
248
249         memif2 = VppMemif(
250             self,
251             role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_MASTER,
252             mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET,
253             socket_id=3,
254         )
255         memif2.add_vpp_config()
256         memif2.admin_up()
257
258         memif12 = VppMemif(
259             self,
260             role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_SLAVE,
261             mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET,
262             socket_id=4,
263         )
264         memif12.add_vpp_config()
265         memif12.admin_up()
266
267         self.logger.info(self.vapi.ppcli("debug lacp on"))
268         bond0 = VppBondInterface(
269             self,
270             mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP,
271             use_custom_mac=1,
272             mac_address=bond_mac,
273         )
274
275         bond0.add_vpp_config()
276         bond0.admin_up()
277
278         bond1 = VppBondInterface(
279             self, mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP
280         )
281         bond1.add_vpp_config()
282         bond1.admin_up()
283
284         # add member memif1 and memif2 to bond0
285         bond0.add_member_vpp_bond_interface(sw_if_index=memif1.sw_if_index)
286         bond0.add_member_vpp_bond_interface(sw_if_index=memif2.sw_if_index)
287
288         # add member memif11 and memif12 to bond1
289         bond1.add_member_vpp_bond_interface(sw_if_index=memif11.sw_if_index)
290         bond1.add_member_vpp_bond_interface(sw_if_index=memif12.sw_if_index)
291
292         # wait for memif protocol exchange and hardware carrier to come up
293         self.assertEqual(memif1.wait_for_link_up(10), True)
294         self.assertEqual(memif2.wait_for_link_up(10), True)
295         self.assertEqual(memif11.wait_for_link_up(10), True)
296         self.assertEqual(memif12.wait_for_link_up(10), True)
297
298         # verify memif1 and memif2 in bond0
299         intfs = self.vapi.sw_member_interface_dump(sw_if_index=bond0.sw_if_index)
300         for intf in intfs:
301             self.assertIn(intf.sw_if_index, (memif1.sw_if_index, memif2.sw_if_index))
302
303         # verify memif11 and memif12 in bond1
304         intfs = self.vapi.sw_member_interface_dump(sw_if_index=bond1.sw_if_index)
305         for intf in intfs:
306             self.assertIn(intf.sw_if_index, (memif11.sw_if_index, memif12.sw_if_index))
307             self.assertEqual(intf.is_long_timeout, 0)
308             self.assertEqual(intf.is_passive, 0)
309
310         # Let LACP create the bundle
311         self.wait_for_lacp_connect(30)
312
313         intfs = self.vapi.sw_interface_lacp_dump()
314         for intf in intfs:
315             self.assertEqual(intf.actor_state, LACP_COLLECTION_AND_DISTRIBUTION_STATE)
316             self.assertEqual(intf.partner_state, LACP_COLLECTION_AND_DISTRIBUTION_STATE)
317
318         intfs = self.vapi.sw_bond_interface_dump(sw_if_index=0xFFFFFFFF)
319         for intf in intfs:
320             self.assertEqual(intf.members, 2)
321             self.assertEqual(intf.active_members, 2)
322             self.assertEqual(intf.mode, VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP)
323
324         self.logger.info(self.vapi.ppcli("show lacp"))
325         self.logger.info(self.vapi.ppcli("show lacp details"))
326
327         # detach member memif1
328         bond0.detach_vpp_bond_interface(sw_if_index=memif1.sw_if_index)
329
330         self.wait_for_member_detach(bond0, timeout=10, count=1)
331         intfs = self.vapi.sw_bond_interface_dump(sw_if_index=bond0.sw_if_index)
332         for intf in intfs:
333             self.assertEqual(intf.members, 1)
334             self.assertEqual(intf.active_members, 1)
335             self.assertEqual(intf.mode, VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP)
336
337         # detach member memif2
338         bond0.detach_vpp_bond_interface(sw_if_index=memif2.sw_if_index)
339         self.wait_for_member_detach(bond0, timeout=10, count=0)
340
341         intfs = self.vapi.sw_bond_interface_dump(sw_if_index=bond0.sw_if_index)
342         for intf in intfs:
343             self.assertEqual(intf.members, 0)
344             self.assertEqual(intf.active_members, 0)
345
346         bond0.remove_vpp_config()
347         bond1.remove_vpp_config()
348
349
350 if __name__ == "__main__":
351     unittest.main(testRunner=VppTestRunner)