blob: 159bae5fea0a2be1012eea3189f364835291fc27 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Steven9cd2d7a2017-12-20 12:43:01 -08002
3import socket
4import unittest
5
Steven9cd2d7a2017-12-20 12:43:01 -08006from scapy.packet import Raw
7from scapy.layers.l2 import Ether
8from scapy.layers.inet import IP, UDP
Steven Luongdc2abbe2020-07-28 12:28:03 -07009
10from framework import VppTestCase, VppTestRunner
Steven9cd2d7a2017-12-20 12:43:01 -080011from vpp_bond_interface import VppBondInterface
Steven Luongdc2abbe2020-07-28 12:28:03 -070012from vpp_papi import MACAddress, VppEnum
Steven9cd2d7a2017-12-20 12:43:01 -080013
14
15class TestBondInterface(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020016 """Bond Test Case"""
Steven9cd2d7a2017-12-20 12:43:01 -080017
18 @classmethod
19 def setUpClass(cls):
20 super(TestBondInterface, cls).setUpClass()
21 # Test variables
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020022 cls.pkts_per_burst = 257 # Number of packets per burst
Steven9cd2d7a2017-12-20 12:43:01 -080023 # create 3 pg interfaces
24 cls.create_pg_interfaces(range(4))
25
26 # packet sizes
27 cls.pg_if_packet_sizes = [64, 512, 1518] # , 9018]
28
29 # setup all interfaces
30 for i in cls.pg_interfaces:
31 i.admin_up()
32
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070033 @classmethod
34 def tearDownClass(cls):
35 super(TestBondInterface, cls).tearDownClass()
36
Steven9cd2d7a2017-12-20 12:43:01 -080037 def setUp(self):
38 super(TestBondInterface, self).setUp()
39
40 def tearDown(self):
41 super(TestBondInterface, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -070042
43 def show_commands_at_teardown(self):
44 self.logger.info(self.vapi.ppcli("show interface"))
Steven9cd2d7a2017-12-20 12:43:01 -080045
46 def test_bond_traffic(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020047 """Bond traffic test"""
Steven9cd2d7a2017-12-20 12:43:01 -080048
49 # topology
50 #
51 # RX-> TX->
52 #
Steven Luong4c4223e2020-07-15 08:44:54 -070053 # pg2 ------+ +------pg0 (member)
Steven9cd2d7a2017-12-20 12:43:01 -080054 # | |
55 # BondEthernet0 (10.10.10.1)
56 # | |
Steven Luong4c4223e2020-07-15 08:44:54 -070057 # pg3 ------+ +------pg1 (memberx)
Steven9cd2d7a2017-12-20 12:43:01 -080058 #
59
60 # create interface (BondEthernet0)
61 # self.logger.info("create bond")
62 bond0_mac = "02:fe:38:30:59:3c"
Ole Troan8006c6a2018-12-17 12:02:26 +010063 mac = MACAddress(bond0_mac).packed
Steven Luongea717862020-07-30 07:31:40 -070064 bond0 = VppBondInterface(
65 self,
66 mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_XOR,
67 lb=VppEnum.vl_api_bond_lb_algo_t.BOND_API_LB_ALGO_L34,
68 numa_only=0,
69 use_custom_mac=1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020070 mac_address=mac,
71 )
Steven9cd2d7a2017-12-20 12:43:01 -080072 bond0.add_vpp_config()
73 bond0.admin_up()
Jakub Grajciar053204a2019-03-18 13:17:53 +010074 self.vapi.sw_interface_add_del_address(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020075 sw_if_index=bond0.sw_if_index, prefix="10.10.10.1/24"
76 )
Steven9cd2d7a2017-12-20 12:43:01 -080077
78 self.pg2.config_ip4()
79 self.pg2.resolve_arp()
80 self.pg3.config_ip4()
81 self.pg3.resolve_arp()
82
83 self.logger.info(self.vapi.cli("show interface"))
84 self.logger.info(self.vapi.cli("show interface address"))
Neale Rannscbe25aa2019-09-30 10:53:31 +000085 self.logger.info(self.vapi.cli("show ip neighbors"))
Steven9cd2d7a2017-12-20 12:43:01 -080086
Steven Luong4c4223e2020-07-15 08:44:54 -070087 # add member pg0 and pg1 to BondEthernet0
88 self.logger.info("bond add member interface pg0 to BondEthernet0")
89 bond0.add_member_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
90 self.logger.info("bond add_member interface pg1 to BondEthernet0")
91 bond0.add_member_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
Steven9cd2d7a2017-12-20 12:43:01 -080092
Steven Luong4c4223e2020-07-15 08:44:54 -070093 # verify both members in BondEthernet0
94 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
Steven9cd2d7a2017-12-20 12:43:01 -080095 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
96 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
97
98 # generate a packet from pg2 -> BondEthernet0 -> pg1
99 # BondEthernet0 TX hashes this packet to pg1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200100 p2 = (
101 Ether(src=bond0_mac, dst=self.pg2.local_mac)
102 / IP(src=self.pg2.local_ip4, dst="10.10.10.12")
103 / UDP(sport=1235, dport=1235)
104 / Raw(b"\xa5" * 100)
105 )
Steven9cd2d7a2017-12-20 12:43:01 -0800106 self.pg2.add_stream(p2)
107
108 # generate a packet from pg3 -> BondEthernet0 -> pg0
109 # BondEthernet0 TX hashes this packet to pg0
110 # notice the ip address and ports are different than p2 packet
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200111 p3 = (
112 Ether(src=bond0_mac, dst=self.pg3.local_mac)
113 / IP(src=self.pg3.local_ip4, dst="10.10.10.11")
114 / UDP(sport=1234, dport=1234)
115 / Raw(b"\xa5" * 100)
116 )
Steven9cd2d7a2017-12-20 12:43:01 -0800117 self.pg3.add_stream(p3)
118
119 self.pg_enable_capture(self.pg_interfaces)
120
121 # set up the static arp entries pointing to the BondEthernet0 interface
122 # so that it does not try to resolve the ip address
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200123 self.logger.info(
124 self.vapi.cli(
125 "set ip neighbor static BondEthernet0 10.10.10.12 abcd.abcd.0002"
126 )
127 )
128 self.logger.info(
129 self.vapi.cli(
130 "set ip neighbor static BondEthernet0 10.10.10.11 abcd.abcd.0004"
131 )
132 )
Steven9cd2d7a2017-12-20 12:43:01 -0800133
134 # clear the interface counters
135 self.logger.info(self.vapi.cli("clear interfaces"))
136
137 self.pg_start()
138
139 self.logger.info("check the interface counters")
140
141 # verify counters
142
143 # BondEthernet0 tx bytes = 284
144 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
145 found = 0
146 for intf in intfs:
147 if "tx bytes" in intf and "284" in intf:
148 found = 1
149 self.assertEqual(found, 1)
150
Steven0d883012018-05-11 11:06:23 -0700151 # BondEthernet0 tx bytes = 284
152 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
Steven9cd2d7a2017-12-20 12:43:01 -0800153 found = 0
154 for intf in intfs:
Steven0d883012018-05-11 11:06:23 -0700155 if "tx bytes" in intf and "284" in intf:
Steven9cd2d7a2017-12-20 12:43:01 -0800156 found = 1
157 self.assertEqual(found, 1)
158
159 # pg2 rx bytes = 142
160 intfs = self.vapi.cli("show interface pg2").split("\n")
161 found = 0
162 for intf in intfs:
163 if "rx bytes" in intf and "142" in intf:
164 found = 1
165 self.assertEqual(found, 1)
166
167 # pg3 rx bytes = 142
168 intfs = self.vapi.cli("show interface pg3").split("\n")
169 found = 0
170 for intf in intfs:
171 if "rx bytes" in intf and "142" in intf:
172 found = 1
173 self.assertEqual(found, 1)
174
175 bond0.remove_vpp_config()
176
Steven Luong4c4223e2020-07-15 08:44:54 -0700177 def test_bond_add_member(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200178 """Bond add_member/detach member test"""
Steven9cd2d7a2017-12-20 12:43:01 -0800179
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300180 # create interface (BondEthernet0) and set bond mode to LACP
Steven9cd2d7a2017-12-20 12:43:01 -0800181 self.logger.info("create bond")
Steven Luongea717862020-07-30 07:31:40 -0700182 bond0 = VppBondInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200183 self, mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP, enable_gso=0
184 )
Steven9cd2d7a2017-12-20 12:43:01 -0800185 bond0.add_vpp_config()
186 bond0.admin_up()
187
Steven Luong4c4223e2020-07-15 08:44:54 -0700188 # verify that interfaces can be added as_member and detached two times
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300189 for i in range(2):
190 # verify pg0 and pg1 not in BondEthernet0
Steven Luong4c4223e2020-07-15 08:44:54 -0700191 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300192 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
193 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
Steven9cd2d7a2017-12-20 12:43:01 -0800194
Steven Luong4c4223e2020-07-15 08:44:54 -0700195 # add_member pg0 and pg1 to BondEthernet0
196 self.logger.info("bond add_member interface pg0 to BondEthernet0")
197 bond0.add_member_vpp_bond_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200198 sw_if_index=self.pg0.sw_if_index, is_passive=0, is_long_timeout=0
199 )
Steven9cd2d7a2017-12-20 12:43:01 -0800200
Steven Luong4c4223e2020-07-15 08:44:54 -0700201 self.logger.info("bond add_member interface pg1 to BondEthernet0")
202 bond0.add_member_vpp_bond_interface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200203 sw_if_index=self.pg1.sw_if_index, is_passive=0, is_long_timeout=0
204 )
Steven Luong4c4223e2020-07-15 08:44:54 -0700205 # verify both members in BondEthernet0
206 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300207 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
208 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
Steven9cd2d7a2017-12-20 12:43:01 -0800209
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300210 # detach interface pg0
211 self.logger.info("detach interface pg0")
212 bond0.detach_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
Steven9cd2d7a2017-12-20 12:43:01 -0800213
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300214 # verify pg0 is not in BondEthernet0, but pg1 is
Steven Luong4c4223e2020-07-15 08:44:54 -0700215 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300216 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
217 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
Steven9cd2d7a2017-12-20 12:43:01 -0800218
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300219 # detach interface pg1
220 self.logger.info("detach interface pg1")
221 bond0.detach_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
Steven9cd2d7a2017-12-20 12:43:01 -0800222
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300223 # verify pg0 and pg1 not in BondEthernet0
Steven Luong4c4223e2020-07-15 08:44:54 -0700224 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
Vladimir Isaev72e31bc2020-02-04 11:54:27 +0300225 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
226 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
Steven9cd2d7a2017-12-20 12:43:01 -0800227
228 bond0.remove_vpp_config()
229
230 def test_bond(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200231 """Bond add/delete interface test"""
Steven9cd2d7a2017-12-20 12:43:01 -0800232 self.logger.info("Bond add interfaces")
233
234 # create interface 1 (BondEthernet0)
Steven Luongea717862020-07-30 07:31:40 -0700235 bond0 = VppBondInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200236 self, mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP
237 )
Steven9cd2d7a2017-12-20 12:43:01 -0800238 bond0.add_vpp_config()
239 bond0.admin_up()
240
241 # create interface 2 (BondEthernet1)
Steven Luongea717862020-07-30 07:31:40 -0700242 bond1 = VppBondInterface(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200243 self, mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_XOR
244 )
Steven9cd2d7a2017-12-20 12:43:01 -0800245 bond1.add_vpp_config()
246 bond1.admin_up()
247
248 # verify both interfaces in the show
249 ifs = self.vapi.cli("show interface")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200250 self.assertIn("BondEthernet0", ifs)
251 self.assertIn("BondEthernet1", ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800252
253 # verify they are in the dump also
Steven Luong4c4223e2020-07-15 08:44:54 -0700254 if_dump = self.vapi.sw_bond_interface_dump(sw_if_index=0xFFFFFFFF)
Steven9cd2d7a2017-12-20 12:43:01 -0800255 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
256 self.assertTrue(bond1.is_interface_config_in_dump(if_dump))
257
258 # delete BondEthernet1
259 self.logger.info("Deleting BondEthernet1")
260 bond1.remove_vpp_config()
261
262 self.logger.info("Verifying BondEthernet1 is deleted")
263
264 ifs = self.vapi.cli("show interface")
265 # verify BondEthernet0 still in the show
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200266 self.assertIn("BondEthernet0", ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800267
268 # verify BondEthernet1 not in the show
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200269 self.assertNotIn("BondEthernet1", ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800270
271 # verify BondEthernet1 is not in the dump
Steven Luong4c4223e2020-07-15 08:44:54 -0700272 if_dump = self.vapi.sw_bond_interface_dump(sw_if_index=0xFFFFFFFF)
Steven9cd2d7a2017-12-20 12:43:01 -0800273 self.assertFalse(bond1.is_interface_config_in_dump(if_dump))
274
275 # verify BondEthernet0 is still in the dump
276 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
277
278 # delete BondEthernet0
279 self.logger.info("Deleting BondEthernet0")
280 bond0.remove_vpp_config()
281
282 self.logger.info("Verifying BondEthernet0 is deleted")
283
284 # verify BondEthernet0 not in the show
285 ifs = self.vapi.cli("show interface")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200286 self.assertNotIn("BondEthernet0", ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800287
288 # verify BondEthernet0 is not in the dump
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200289 if_dump = self.vapi.sw_bond_interface_dump(sw_if_index=bond0.sw_if_index)
Steven9cd2d7a2017-12-20 12:43:01 -0800290 self.assertFalse(bond0.is_interface_config_in_dump(if_dump))
291
Steven Luongdc2abbe2020-07-28 12:28:03 -0700292 def test_bond_link(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200293 """Bond hw interface link state test"""
Steven Luongdc2abbe2020-07-28 12:28:03 -0700294
295 # for convenience
296 bond_modes = VppEnum.vl_api_bond_mode_t
297 intf_flags = VppEnum.vl_api_if_status_flags_t
298
299 # create interface 1 (BondEthernet0)
300 self.logger.info("Create bond interface")
301 # use round-robin mode to avoid negotiation required by LACP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200302 bond0 = VppBondInterface(self, mode=bond_modes.BOND_API_MODE_ROUND_ROBIN)
Steven Luongdc2abbe2020-07-28 12:28:03 -0700303 bond0.add_vpp_config()
304
305 # set bond admin up.
306 self.logger.info("set interface BondEthernet0 admin up")
307 bond0.admin_up()
308 # confirm link up
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200309 bond0.assert_interface_state(
310 intf_flags.IF_STATUS_API_FLAG_ADMIN_UP,
311 intf_flags.IF_STATUS_API_FLAG_LINK_UP,
312 )
Steven Luongdc2abbe2020-07-28 12:28:03 -0700313
314 # toggle bond admin state
315 self.logger.info("toggle interface BondEthernet0")
316 bond0.admin_down()
317 bond0.admin_up()
318
319 # confirm link is still up
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200320 bond0.assert_interface_state(
321 intf_flags.IF_STATUS_API_FLAG_ADMIN_UP,
322 intf_flags.IF_STATUS_API_FLAG_LINK_UP,
323 )
Steven Luongdc2abbe2020-07-28 12:28:03 -0700324
325 # delete BondEthernet0
326 self.logger.info("Deleting BondEthernet0")
327 bond0.remove_vpp_config()
328
Steven Luonga1876b82019-08-20 16:58:00 -0700329
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200330if __name__ == "__main__":
Steven9cd2d7a2017-12-20 12:43:01 -0800331 unittest.main(testRunner=VppTestRunner)