ipsec: fix AES CBC IV generation (CVE-2022-46397)
[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
44     def show_commands_at_teardown(self):
45         self.logger.info(self.vapi.ppcli("show interface"))
46
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"
64         mac = MACAddress(bond0_mac).packed
65         bond0 = VppBondInterface(self,
66                                  mode=3,
67                                  lb=1,
68                                  numa_only=0,
69                                  use_custom_mac=1,
70                                  mac_address=mac)
71         bond0.add_vpp_config()
72         bond0.admin_up()
73         bond0_addr = socket.inet_pton(socket.AF_INET, "10.10.10.1")
74         self.vapi.sw_interface_add_del_address(sw_if_index=bond0.sw_if_index,
75                                                address=bond0_addr,
76                                                address_length=24)
77
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"))
85         self.logger.info(self.vapi.cli("show ip arp"))
86
87         # enslave pg0 and pg1 to BondEthernet0
88         self.logger.info("bond enslave interface pg0 to BondEthernet0")
89         bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
90                                          is_passive=0,
91                                          is_long_timeout=0)
92         self.logger.info("bond enslave interface pg1 to BondEthernet0")
93         bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
94                                          is_passive=0,
95                                          is_long_timeout=0)
96
97         # verify both slaves in BondEthernet0
98         if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
99         self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
100         self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
101
102         # generate a packet from pg2 -> BondEthernet0 -> pg1
103         # BondEthernet0 TX hashes this packet to pg1
104         p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) /
105               IP(src=self.pg2.local_ip4, dst="10.10.10.12") /
106               UDP(sport=1235, dport=1235) /
107               Raw('\xa5' * 100))
108         self.pg2.add_stream(p2)
109
110         # generate a packet from pg3 -> BondEthernet0 -> pg0
111         # BondEthernet0 TX hashes this packet to pg0
112         # notice the ip address and ports are different than p2 packet
113         p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) /
114               IP(src=self.pg3.local_ip4, dst="10.10.10.11") /
115               UDP(sport=1234, dport=1234) /
116               Raw('\xa5' * 100))
117         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
123         self.logger.info(self.vapi.cli(
124             "set ip arp static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
125         self.logger.info(self.vapi.cli(
126             "set ip arp static BondEthernet0 10.10.10.11 abcd.abcd.0004"))
127
128         # clear the interface counters
129         self.logger.info(self.vapi.cli("clear interfaces"))
130
131         self.pg_start()
132
133         self.logger.info("check the interface counters")
134
135         # verify counters
136
137         # BondEthernet0 tx bytes = 284
138         intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
139         found = 0
140         for intf in intfs:
141             if "tx bytes" in intf and "284" in intf:
142                 found = 1
143         self.assertEqual(found, 1)
144
145         # BondEthernet0 tx bytes = 284
146         intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
147         found = 0
148         for intf in intfs:
149             if "tx bytes" in intf and "284" in intf:
150                 found = 1
151         self.assertEqual(found, 1)
152
153         # pg2 rx bytes = 142
154         intfs = self.vapi.cli("show interface pg2").split("\n")
155         found = 0
156         for intf in intfs:
157             if "rx bytes" in intf and "142" in intf:
158                 found = 1
159         self.assertEqual(found, 1)
160
161         # pg3 rx bytes = 142
162         intfs = self.vapi.cli("show interface pg3").split("\n")
163         found = 0
164         for intf in intfs:
165             if "rx bytes" in intf and "142" in intf:
166                 found = 1
167         self.assertEqual(found, 1)
168
169         bond0.remove_vpp_config()
170
171     def test_bond_enslave(self):
172         """ Bond enslave/detach slave test """
173
174         # create interface (BondEthernet0) and set bond mode to LACP
175         self.logger.info("create bond")
176         bond0 = VppBondInterface(self, mode=5)
177         bond0.add_vpp_config()
178         bond0.admin_up()
179
180         # verify that interfaces can be enslaved and detached two times
181         for i in range(2):
182             # verify pg0 and pg1 not in BondEthernet0
183             if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
184             self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
185             self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
186
187             # enslave pg0 and pg1 to BondEthernet0
188             self.logger.info("bond enslave interface pg0 to BondEthernet0")
189             bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
190                                              is_passive=0,
191                                              is_long_timeout=0)
192
193             self.logger.info("bond enslave interface pg1 to BondEthernet0")
194             bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
195                                              is_passive=0,
196                                              is_long_timeout=0)
197             # verify both slaves in BondEthernet0
198             if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
199             self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
200             self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
201
202             # detach interface pg0
203             self.logger.info("detach interface pg0")
204             bond0.detach_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
205
206             # verify pg0 is not in BondEthernet0, but pg1 is
207             if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
208             self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
209             self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
210
211             # detach interface pg1
212             self.logger.info("detach interface pg1")
213             bond0.detach_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
214
215             # verify pg0 and pg1 not in BondEthernet0
216             if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
217             self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
218             self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
219
220         bond0.remove_vpp_config()
221
222     def test_bond(self):
223         """ Bond add/delete interface test """
224         self.logger.info("Bond add interfaces")
225
226         # create interface 1 (BondEthernet0)
227         bond0 = VppBondInterface(self, mode=5)
228         bond0.add_vpp_config()
229         bond0.admin_up()
230
231         # create interface 2 (BondEthernet1)
232         bond1 = VppBondInterface(self, mode=3)
233         bond1.add_vpp_config()
234         bond1.admin_up()
235
236         # verify both interfaces in the show
237         ifs = self.vapi.cli("show interface")
238         self.assertIn('BondEthernet0', ifs)
239         self.assertIn('BondEthernet1', ifs)
240
241         # verify they are in the dump also
242         if_dump = self.vapi.sw_interface_bond_dump()
243         self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
244         self.assertTrue(bond1.is_interface_config_in_dump(if_dump))
245
246         # delete BondEthernet1
247         self.logger.info("Deleting BondEthernet1")
248         bond1.remove_vpp_config()
249
250         self.logger.info("Verifying BondEthernet1 is deleted")
251
252         ifs = self.vapi.cli("show interface")
253         # verify BondEthernet0 still in the show
254         self.assertIn('BondEthernet0', ifs)
255
256         # verify BondEthernet1 not in the show
257         self.assertNotIn('BondEthernet1', ifs)
258
259         # verify BondEthernet1 is not in the dump
260         if_dump = self.vapi.sw_interface_bond_dump()
261         self.assertFalse(bond1.is_interface_config_in_dump(if_dump))
262
263         # verify BondEthernet0 is still in the dump
264         self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
265
266         # delete BondEthernet0
267         self.logger.info("Deleting BondEthernet0")
268         bond0.remove_vpp_config()
269
270         self.logger.info("Verifying BondEthernet0 is deleted")
271
272         # verify BondEthernet0 not in the show
273         ifs = self.vapi.cli("show interface")
274         self.assertNotIn('BondEthernet0', ifs)
275
276         # verify BondEthernet0 is not in the dump
277         if_dump = self.vapi.sw_interface_bond_dump()
278         self.assertFalse(bond0.is_interface_config_in_dump(if_dump))
279
280 if __name__ == '__main__':
281     unittest.main(testRunner=VppTestRunner)