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