blob: a888993584b584629a6d617e6b5e62b74964acb4 [file] [log] [blame]
Steven9cd2d7a2017-12-20 12:43:01 -08001#!/usr/bin/env python
2
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()
43 if not self.vpp_dead:
44 self.logger.info(self.vapi.ppcli("show interface"))
45
46 def test_bond_traffic(self):
47 """ Bond traffic test """
48
49 # topology
50 #
51 # RX-> TX->
52 #
53 # pg2 ------+ +------pg0 (slave)
54 # | |
55 # BondEthernet0 (10.10.10.1)
56 # | |
57 # pg3 ------+ +------pg1 (slave)
58 #
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
Steven9cd2d7a2017-12-20 12:43:01 -080064 bond0 = VppBondInterface(self,
65 mode=3,
66 lb=1,
67 use_custom_mac=1,
68 mac_address=mac)
69 bond0.add_vpp_config()
70 bond0.admin_up()
Ole Trøan3b0d7e42019-03-15 16:14:41 +000071 bond0_addr = socket.inet_pton(socket.AF_INET, "10.10.10.1")
72 self.vapi.sw_interface_add_del_address(sw_if_index=bond0.sw_if_index,
73 address=bond0_addr,
74 address_length=24)
Steven9cd2d7a2017-12-20 12:43:01 -080075
76 self.pg2.config_ip4()
77 self.pg2.resolve_arp()
78 self.pg3.config_ip4()
79 self.pg3.resolve_arp()
80
81 self.logger.info(self.vapi.cli("show interface"))
82 self.logger.info(self.vapi.cli("show interface address"))
83 self.logger.info(self.vapi.cli("show ip arp"))
84
85 # enslave pg0 and pg1 to BondEthernet0
86 self.logger.info("bond enslave interface pg0 to BondEthernet0")
87 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
88 is_passive=0,
89 is_long_timeout=0)
90 self.logger.info("bond enslave interface pg1 to BondEthernet0")
91 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
92 is_passive=0,
93 is_long_timeout=0)
94
95 # verify both slaves in BondEthernet0
96 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
97 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
98 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
99
100 # generate a packet from pg2 -> BondEthernet0 -> pg1
101 # BondEthernet0 TX hashes this packet to pg1
102 p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) /
103 IP(src=self.pg2.local_ip4, dst="10.10.10.12") /
104 UDP(sport=1235, dport=1235) /
105 Raw('\xa5' * 100))
106 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
111 p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) /
112 IP(src=self.pg3.local_ip4, dst="10.10.10.11") /
113 UDP(sport=1234, dport=1234) /
114 Raw('\xa5' * 100))
115 self.pg3.add_stream(p3)
116
117 self.pg_enable_capture(self.pg_interfaces)
118
119 # set up the static arp entries pointing to the BondEthernet0 interface
120 # so that it does not try to resolve the ip address
121 self.logger.info(self.vapi.cli(
122 "set ip arp static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
123 self.logger.info(self.vapi.cli(
124 "set ip arp static BondEthernet0 10.10.10.11 abcd.abcd.0004"))
125
126 # clear the interface counters
127 self.logger.info(self.vapi.cli("clear interfaces"))
128
129 self.pg_start()
130
131 self.logger.info("check the interface counters")
132
133 # verify counters
134
135 # BondEthernet0 tx bytes = 284
136 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
137 found = 0
138 for intf in intfs:
139 if "tx bytes" in intf and "284" in intf:
140 found = 1
141 self.assertEqual(found, 1)
142
Steven0d883012018-05-11 11:06:23 -0700143 # BondEthernet0 tx bytes = 284
144 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
Steven9cd2d7a2017-12-20 12:43:01 -0800145 found = 0
146 for intf in intfs:
Steven0d883012018-05-11 11:06:23 -0700147 if "tx bytes" in intf and "284" in intf:
Steven9cd2d7a2017-12-20 12:43:01 -0800148 found = 1
149 self.assertEqual(found, 1)
150
151 # pg2 rx bytes = 142
152 intfs = self.vapi.cli("show interface pg2").split("\n")
153 found = 0
154 for intf in intfs:
155 if "rx bytes" in intf and "142" in intf:
156 found = 1
157 self.assertEqual(found, 1)
158
159 # pg3 rx bytes = 142
160 intfs = self.vapi.cli("show interface pg3").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 bond0.remove_vpp_config()
168
169 def test_bond_enslave(self):
170 """ Bond enslave/detach slave test """
171
172 # create interface (BondEthernet0)
173 self.logger.info("create bond")
174 bond0 = VppBondInterface(self, mode=3)
175 bond0.add_vpp_config()
176 bond0.admin_up()
177
178 # verify pg0 and pg1 not in BondEthernet0
179 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
180 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
181 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
182
183 # enslave pg0 and pg1 to BondEthernet0
184 self.logger.info("bond enslave interface pg0 to BondEthernet0")
185 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
186 is_passive=0,
187 is_long_timeout=0)
188
189 self.logger.info("bond enslave interface pg1 to BondEthernet0")
190 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
191 is_passive=0,
192 is_long_timeout=0)
193
194 # verify both slaves in BondEthernet0
195 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
196 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
197 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
198
199 # detach interface pg0
200 self.logger.info("detach interface pg0")
201 bond0.detach_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
202
203 # verify pg0 is not in BondEthernet0, but pg1 is
204 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
205 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
206 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
207
208 # detach interface pg1
209 self.logger.info("detach interface pg1")
210 bond0.detach_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
211
212 # verify pg0 and pg1 not in BondEthernet0
213 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
214 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
215 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
216
217 bond0.remove_vpp_config()
218
219 def test_bond(self):
220 """ Bond add/delete interface test """
221 self.logger.info("Bond add interfaces")
222
223 # create interface 1 (BondEthernet0)
224 bond0 = VppBondInterface(self, mode=5)
225 bond0.add_vpp_config()
226 bond0.admin_up()
227
228 # create interface 2 (BondEthernet1)
229 bond1 = VppBondInterface(self, mode=3)
230 bond1.add_vpp_config()
231 bond1.admin_up()
232
233 # verify both interfaces in the show
234 ifs = self.vapi.cli("show interface")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800235 self.assertIn('BondEthernet0', ifs)
236 self.assertIn('BondEthernet1', ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800237
238 # verify they are in the dump also
239 if_dump = self.vapi.sw_interface_bond_dump()
240 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
241 self.assertTrue(bond1.is_interface_config_in_dump(if_dump))
242
243 # delete BondEthernet1
244 self.logger.info("Deleting BondEthernet1")
245 bond1.remove_vpp_config()
246
247 self.logger.info("Verifying BondEthernet1 is deleted")
248
249 ifs = self.vapi.cli("show interface")
250 # verify BondEthernet0 still in the show
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800251 self.assertIn('BondEthernet0', ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800252
253 # verify BondEthernet1 not in the show
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800254 self.assertNotIn('BondEthernet1', ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800255
256 # verify BondEthernet1 is not in the dump
257 if_dump = self.vapi.sw_interface_bond_dump()
258 self.assertFalse(bond1.is_interface_config_in_dump(if_dump))
259
260 # verify BondEthernet0 is still in the dump
261 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
262
263 # delete BondEthernet0
264 self.logger.info("Deleting BondEthernet0")
265 bond0.remove_vpp_config()
266
267 self.logger.info("Verifying BondEthernet0 is deleted")
268
269 # verify BondEthernet0 not in the show
270 ifs = self.vapi.cli("show interface")
Paul Vinciguerra9a6dafd2019-03-06 15:11:28 -0800271 self.assertNotIn('BondEthernet0', ifs)
Steven9cd2d7a2017-12-20 12:43:01 -0800272
273 # verify BondEthernet0 is not in the dump
274 if_dump = self.vapi.sw_interface_bond_dump()
275 self.assertFalse(bond0.is_interface_config_in_dump(if_dump))
276
277if __name__ == '__main__':
278 unittest.main(testRunner=VppTestRunner)