blob: 5ef865f26d431f2dcb6a7a33acb9f32baf2df745 [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
6from framework import VppTestCase, VppTestRunner
7from scapy.packet import Raw
8from scapy.layers.l2 import Ether
9from scapy.layers.inet import IP, UDP
Steven9cd2d7a2017-12-20 12:43:01 -080010from vpp_bond_interface import VppBondInterface
Ole Troan8006c6a2018-12-17 12:02:26 +010011from vpp_papi import MACAddress
Steven9cd2d7a2017-12-20 12:43:01 -080012
13
14class TestBondInterface(VppTestCase):
15 """Bond Test Case
16
17 """
18
19 @classmethod
20 def setUpClass(cls):
21 super(TestBondInterface, cls).setUpClass()
22 # Test variables
23 cls.pkts_per_burst = 257 # Number of packets per burst
24 # create 3 pg interfaces
25 cls.create_pg_interfaces(range(4))
26
27 # packet sizes
28 cls.pg_if_packet_sizes = [64, 512, 1518] # , 9018]
29
30 # setup all interfaces
31 for i in cls.pg_interfaces:
32 i.admin_up()
33
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070034 @classmethod
35 def tearDownClass(cls):
36 super(TestBondInterface, cls).tearDownClass()
37
Steven9cd2d7a2017-12-20 12:43:01 -080038 def setUp(self):
39 super(TestBondInterface, self).setUp()
40
41 def tearDown(self):
42 super(TestBondInterface, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -070043
44 def show_commands_at_teardown(self):
45 self.logger.info(self.vapi.ppcli("show interface"))
Steven9cd2d7a2017-12-20 12:43:01 -080046
47 def test_bond_traffic(self):
48 """ Bond traffic test """
49
50 # topology
51 #
52 # RX-> TX->
53 #
54 # pg2 ------+ +------pg0 (slave)
55 # | |
56 # BondEthernet0 (10.10.10.1)
57 # | |
58 # pg3 ------+ +------pg1 (slave)
59 #
60
61 # create interface (BondEthernet0)
62 # self.logger.info("create bond")
63 bond0_mac = "02:fe:38:30:59:3c"
Ole Troan8006c6a2018-12-17 12:02:26 +010064 mac = MACAddress(bond0_mac).packed
Steven9cd2d7a2017-12-20 12:43:01 -080065 bond0 = VppBondInterface(self,
66 mode=3,
67 lb=1,
Zhiyong Yang751e3f32019-06-26 05:49:14 -040068 numa_only=0,
Steven9cd2d7a2017-12-20 12:43:01 -080069 use_custom_mac=1,
70 mac_address=mac)
71 bond0.add_vpp_config()
72 bond0.admin_up()
Jakub Grajciar053204a2019-03-18 13:17:53 +010073 self.vapi.sw_interface_add_del_address(
74 sw_if_index=bond0.sw_if_index,
Neale Rannsefd7bc22019-11-11 08:32:34 +000075 prefix="10.10.10.1/24")
Steven9cd2d7a2017-12-20 12:43:01 -080076
77 self.pg2.config_ip4()
78 self.pg2.resolve_arp()
79 self.pg3.config_ip4()
80 self.pg3.resolve_arp()
81
82 self.logger.info(self.vapi.cli("show interface"))
83 self.logger.info(self.vapi.cli("show interface address"))
Neale Rannscbe25aa2019-09-30 10:53:31 +000084 self.logger.info(self.vapi.cli("show ip neighbors"))
Steven9cd2d7a2017-12-20 12:43:01 -080085
86 # enslave pg0 and pg1 to BondEthernet0
87 self.logger.info("bond enslave interface pg0 to BondEthernet0")
Steven Luonga1876b82019-08-20 16:58:00 -070088 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
Steven9cd2d7a2017-12-20 12:43:01 -080089 self.logger.info("bond enslave interface pg1 to BondEthernet0")
Steven Luonga1876b82019-08-20 16:58:00 -070090 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
Steven9cd2d7a2017-12-20 12:43:01 -080091
92 # verify both slaves in BondEthernet0
93 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
94 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
95 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
96
97 # generate a packet from pg2 -> BondEthernet0 -> pg1
98 # BondEthernet0 TX hashes this packet to pg1
99 p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) /
100 IP(src=self.pg2.local_ip4, dst="10.10.10.12") /
101 UDP(sport=1235, dport=1235) /
Ole Troanf6dee6c2019-10-21 20:41:44 +0200102 Raw(b'\xa5' * 100))
Steven9cd2d7a2017-12-20 12:43:01 -0800103 self.pg2.add_stream(p2)
104
105 # generate a packet from pg3 -> BondEthernet0 -> pg0
106 # BondEthernet0 TX hashes this packet to pg0
107 # notice the ip address and ports are different than p2 packet
108 p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) /
109 IP(src=self.pg3.local_ip4, dst="10.10.10.11") /
110 UDP(sport=1234, dport=1234) /
Ole Troanf6dee6c2019-10-21 20:41:44 +0200111 Raw(b'\xa5' * 100))
Steven9cd2d7a2017-12-20 12:43:01 -0800112 self.pg3.add_stream(p3)
113
114 self.pg_enable_capture(self.pg_interfaces)
115
116 # set up the static arp entries pointing to the BondEthernet0 interface
117 # so that it does not try to resolve the ip address
118 self.logger.info(self.vapi.cli(
Neale Rannscbe25aa2019-09-30 10:53:31 +0000119 "set ip neighbor static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
Steven9cd2d7a2017-12-20 12:43:01 -0800120 self.logger.info(self.vapi.cli(
Neale Rannscbe25aa2019-09-30 10:53:31 +0000121 "set ip neighbor static BondEthernet0 10.10.10.11 abcd.abcd.0004"))
Steven9cd2d7a2017-12-20 12:43:01 -0800122
123 # clear the interface counters
124 self.logger.info(self.vapi.cli("clear interfaces"))
125
126 self.pg_start()
127
128 self.logger.info("check the interface counters")
129
130 # verify counters
131
132 # BondEthernet0 tx bytes = 284
133 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
134 found = 0
135 for intf in intfs:
136 if "tx bytes" in intf and "284" in intf:
137 found = 1
138 self.assertEqual(found, 1)
139
Steven0d883012018-05-11 11:06:23 -0700140 # BondEthernet0 tx bytes = 284
141 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
Steven9cd2d7a2017-12-20 12:43:01 -0800142 found = 0
143 for intf in intfs:
Steven0d883012018-05-11 11:06:23 -0700144 if "tx bytes" in intf and "284" in intf:
Steven9cd2d7a2017-12-20 12:43:01 -0800145 found = 1
146 self.assertEqual(found, 1)
147
148 # pg2 rx bytes = 142
149 intfs = self.vapi.cli("show interface pg2").split("\n")
150 found = 0
151 for intf in intfs:
152 if "rx bytes" in intf and "142" in intf:
153 found = 1
154 self.assertEqual(found, 1)
155
156 # pg3 rx bytes = 142
157 intfs = self.vapi.cli("show interface pg3").split("\n")
158 found = 0
159 for intf in intfs:
160 if "rx bytes" in intf and "142" in intf:
161 found = 1
162 self.assertEqual(found, 1)
163
164 bond0.remove_vpp_config()
165
166 def test_bond_enslave(self):
167 """ Bond enslave/detach slave test """
168
169 # create interface (BondEthernet0)
170 self.logger.info("create bond")
171 bond0 = VppBondInterface(self, mode=3)
172 bond0.add_vpp_config()
173 bond0.admin_up()
174
175 # verify pg0 and pg1 not in BondEthernet0
176 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
177 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
178 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
179
180 # enslave pg0 and pg1 to BondEthernet0
181 self.logger.info("bond enslave interface pg0 to BondEthernet0")
182 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
183 is_passive=0,
184 is_long_timeout=0)
185
186 self.logger.info("bond enslave interface pg1 to BondEthernet0")
187 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
188 is_passive=0,
189 is_long_timeout=0)
190
191 # verify both slaves in BondEthernet0
192 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
193 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
194 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
195
196 # detach interface pg0
197 self.logger.info("detach interface pg0")
198 bond0.detach_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
199
200 # verify pg0 is not in BondEthernet0, but pg1 is
201 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
202 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
203 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
204
205 # detach interface pg1
206 self.logger.info("detach interface pg1")
207 bond0.detach_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
208
209 # verify pg0 and pg1 not in BondEthernet0
210 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
211 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
212 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
213
214 bond0.remove_vpp_config()
215
216 def test_bond(self):
217 """ Bond add/delete interface test """
218 self.logger.info("Bond add interfaces")
219
220 # create interface 1 (BondEthernet0)
221 bond0 = VppBondInterface(self, mode=5)
222 bond0.add_vpp_config()
223 bond0.admin_up()
224
225 # create interface 2 (BondEthernet1)
226 bond1 = VppBondInterface(self, mode=3)
227 bond1.add_vpp_config()
228 bond1.admin_up()
229
230 # verify both interfaces in the show
231 ifs = self.vapi.cli("show interface")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800232 self.assertIn('BondEthernet0', ifs)
233 self.assertIn('BondEthernet1', ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800234
235 # verify they are in the dump also
236 if_dump = self.vapi.sw_interface_bond_dump()
237 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
238 self.assertTrue(bond1.is_interface_config_in_dump(if_dump))
239
240 # delete BondEthernet1
241 self.logger.info("Deleting BondEthernet1")
242 bond1.remove_vpp_config()
243
244 self.logger.info("Verifying BondEthernet1 is deleted")
245
246 ifs = self.vapi.cli("show interface")
247 # verify BondEthernet0 still in the show
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800248 self.assertIn('BondEthernet0', ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800249
250 # verify BondEthernet1 not in the show
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800251 self.assertNotIn('BondEthernet1', ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800252
253 # verify BondEthernet1 is not in the dump
254 if_dump = self.vapi.sw_interface_bond_dump()
255 self.assertFalse(bond1.is_interface_config_in_dump(if_dump))
256
257 # verify BondEthernet0 is still in the dump
258 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
259
260 # delete BondEthernet0
261 self.logger.info("Deleting BondEthernet0")
262 bond0.remove_vpp_config()
263
264 self.logger.info("Verifying BondEthernet0 is deleted")
265
266 # verify BondEthernet0 not in the show
267 ifs = self.vapi.cli("show interface")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800268 self.assertNotIn('BondEthernet0', ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800269
270 # verify BondEthernet0 is not in the dump
271 if_dump = self.vapi.sw_interface_bond_dump()
272 self.assertFalse(bond0.is_interface_config_in_dump(if_dump))
273
Steven Luonga1876b82019-08-20 16:58:00 -0700274
Steven9cd2d7a2017-12-20 12:43:01 -0800275if __name__ == '__main__':
276 unittest.main(testRunner=VppTestRunner)