Tests Cleanup: Fix missing calls to setUpClass/tearDownClass.
[vpp.git] / test / test_bond.py
1 #!/usr/bin/env python
2
3 import socket
4 import unittest
5
6 from framework import VppTestCase, VppTestRunner
7 from scapy.packet import Raw
8 from scapy.layers.l2 import Ether
9 from scapy.layers.inet import IP, UDP
10 from vpp_bond_interface import VppBondInterface
11 from vpp_papi import MACAddress
12
13
14 class 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
34     @classmethod
35     def tearDownClass(cls):
36         super(TestBondInterface, cls).tearDownClass()
37
38     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"
63         mac = MACAddress(bond0_mac).packed
64         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()
71         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)
75
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
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
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")
235         self.assertIn('BondEthernet0', ifs)
236         self.assertIn('BondEthernet1', ifs)
237
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
251         self.assertIn('BondEthernet0', ifs)
252
253         # verify BondEthernet1 not in the show
254         self.assertNotIn('BondEthernet1', ifs)
255
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")
271         self.assertNotIn('BondEthernet0', ifs)
272
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
277 if __name__ == '__main__':
278     unittest.main(testRunner=VppTestRunner)