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
14 class TestBondInterface(VppTestCase):
21 super(TestBondInterface, cls).setUpClass()
23 cls.pkts_per_burst = 257 # Number of packets per burst
24 # create 3 pg interfaces
25 cls.create_pg_interfaces(range(4))
28 cls.pg_if_packet_sizes = [64, 512, 1518] # , 9018]
30 # setup all interfaces
31 for i in cls.pg_interfaces:
35 def tearDownClass(cls):
36 super(TestBondInterface, cls).tearDownClass()
39 super(TestBondInterface, self).setUp()
42 super(TestBondInterface, self).tearDown()
44 def show_commands_at_teardown(self):
45 self.logger.info(self.vapi.ppcli("show interface"))
47 def test_bond_traffic(self):
48 """ Bond traffic test """
54 # pg2 ------+ +------pg0 (slave)
56 # BondEthernet0 (10.10.10.1)
58 # pg3 ------+ +------pg1 (slave)
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,
70 bond0.add_vpp_config()
72 bond0_addr = socket.inet_pton(socket.AF_INET, "10.10.10.1")
73 self.vapi.sw_interface_add_del_address(sw_if_index=bond0.sw_if_index,
78 self.pg2.resolve_arp()
80 self.pg3.resolve_arp()
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"))
86 # enslave pg0 and pg1 to BondEthernet0
87 self.logger.info("bond enslave interface pg0 to BondEthernet0")
88 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
91 self.logger.info("bond enslave interface pg1 to BondEthernet0")
92 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
96 # verify both slaves in BondEthernet0
97 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
98 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
99 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
101 # generate a packet from pg2 -> BondEthernet0 -> pg1
102 # BondEthernet0 TX hashes this packet to pg1
103 p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) /
104 IP(src=self.pg2.local_ip4, dst="10.10.10.12") /
105 UDP(sport=1235, dport=1235) /
107 self.pg2.add_stream(p2)
109 # generate a packet from pg3 -> BondEthernet0 -> pg0
110 # BondEthernet0 TX hashes this packet to pg0
111 # notice the ip address and ports are different than p2 packet
112 p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) /
113 IP(src=self.pg3.local_ip4, dst="10.10.10.11") /
114 UDP(sport=1234, dport=1234) /
116 self.pg3.add_stream(p3)
118 self.pg_enable_capture(self.pg_interfaces)
120 # set up the static arp entries pointing to the BondEthernet0 interface
121 # so that it does not try to resolve the ip address
122 self.logger.info(self.vapi.cli(
123 "set ip arp static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
124 self.logger.info(self.vapi.cli(
125 "set ip arp static BondEthernet0 10.10.10.11 abcd.abcd.0004"))
127 # clear the interface counters
128 self.logger.info(self.vapi.cli("clear interfaces"))
132 self.logger.info("check the interface counters")
136 # BondEthernet0 tx bytes = 284
137 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
140 if "tx bytes" in intf and "284" in intf:
142 self.assertEqual(found, 1)
144 # BondEthernet0 tx bytes = 284
145 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
148 if "tx bytes" in intf and "284" in intf:
150 self.assertEqual(found, 1)
153 intfs = self.vapi.cli("show interface pg2").split("\n")
156 if "rx bytes" in intf and "142" in intf:
158 self.assertEqual(found, 1)
161 intfs = self.vapi.cli("show interface pg3").split("\n")
164 if "rx bytes" in intf and "142" in intf:
166 self.assertEqual(found, 1)
168 bond0.remove_vpp_config()
170 def test_bond_enslave(self):
171 """ Bond enslave/detach slave test """
173 # create interface (BondEthernet0)
174 self.logger.info("create bond")
175 bond0 = VppBondInterface(self, mode=3)
176 bond0.add_vpp_config()
179 # verify pg0 and pg1 not in BondEthernet0
180 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
181 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
182 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
184 # enslave pg0 and pg1 to BondEthernet0
185 self.logger.info("bond enslave interface pg0 to BondEthernet0")
186 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
190 self.logger.info("bond enslave interface pg1 to BondEthernet0")
191 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
195 # verify both slaves in BondEthernet0
196 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
197 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
198 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
200 # detach interface pg0
201 self.logger.info("detach interface pg0")
202 bond0.detach_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
204 # verify pg0 is not in BondEthernet0, but pg1 is
205 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
206 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
207 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
209 # detach interface pg1
210 self.logger.info("detach interface pg1")
211 bond0.detach_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
213 # verify pg0 and pg1 not in BondEthernet0
214 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
215 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
216 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
218 bond0.remove_vpp_config()
221 """ Bond add/delete interface test """
222 self.logger.info("Bond add interfaces")
224 # create interface 1 (BondEthernet0)
225 bond0 = VppBondInterface(self, mode=5)
226 bond0.add_vpp_config()
229 # create interface 2 (BondEthernet1)
230 bond1 = VppBondInterface(self, mode=3)
231 bond1.add_vpp_config()
234 # verify both interfaces in the show
235 ifs = self.vapi.cli("show interface")
236 self.assertIn('BondEthernet0', ifs)
237 self.assertIn('BondEthernet1', ifs)
239 # verify they are in the dump also
240 if_dump = self.vapi.sw_interface_bond_dump()
241 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
242 self.assertTrue(bond1.is_interface_config_in_dump(if_dump))
244 # delete BondEthernet1
245 self.logger.info("Deleting BondEthernet1")
246 bond1.remove_vpp_config()
248 self.logger.info("Verifying BondEthernet1 is deleted")
250 ifs = self.vapi.cli("show interface")
251 # verify BondEthernet0 still in the show
252 self.assertIn('BondEthernet0', ifs)
254 # verify BondEthernet1 not in the show
255 self.assertNotIn('BondEthernet1', ifs)
257 # verify BondEthernet1 is not in the dump
258 if_dump = self.vapi.sw_interface_bond_dump()
259 self.assertFalse(bond1.is_interface_config_in_dump(if_dump))
261 # verify BondEthernet0 is still in the dump
262 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
264 # delete BondEthernet0
265 self.logger.info("Deleting BondEthernet0")
266 bond0.remove_vpp_config()
268 self.logger.info("Verifying BondEthernet0 is deleted")
270 # verify BondEthernet0 not in the show
271 ifs = self.vapi.cli("show interface")
272 self.assertNotIn('BondEthernet0', ifs)
274 # verify BondEthernet0 is not in the dump
275 if_dump = self.vapi.sw_interface_bond_dump()
276 self.assertFalse(bond0.is_interface_config_in_dump(if_dump))
278 if __name__ == '__main__':
279 unittest.main(testRunner=VppTestRunner)