blob: 29ad33d7a4ec59b1c8e8771cb40c281ecb257e04 [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"))
84 self.logger.info(self.vapi.cli("show ip arp"))
85
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(
119 "set ip arp static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
120 self.logger.info(self.vapi.cli(
121 "set ip arp static BondEthernet0 10.10.10.11 abcd.abcd.0004"))
122
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)