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 self.logger.info(self.vapi.ppcli("show interface"))
46 def test_bond_traffic(self):
47 """ Bond traffic test """
53 # pg2 ------+ +------pg0 (slave)
55 # BondEthernet0 (10.10.10.1)
57 # pg3 ------+ +------pg1 (slave)
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,
69 bond0.add_vpp_config()
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,
77 self.pg2.resolve_arp()
79 self.pg3.resolve_arp()
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"))
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,
90 self.logger.info("bond enslave interface pg1 to BondEthernet0")
91 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
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))
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) /
106 self.pg2.add_stream(p2)
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) /
115 self.pg3.add_stream(p3)
117 self.pg_enable_capture(self.pg_interfaces)
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"))
126 # clear the interface counters
127 self.logger.info(self.vapi.cli("clear interfaces"))
131 self.logger.info("check the interface counters")
135 # BondEthernet0 tx bytes = 284
136 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
139 if "tx bytes" in intf and "284" in intf:
141 self.assertEqual(found, 1)
143 # BondEthernet0 tx bytes = 284
144 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
147 if "tx bytes" in intf and "284" in intf:
149 self.assertEqual(found, 1)
152 intfs = self.vapi.cli("show interface pg2").split("\n")
155 if "rx bytes" in intf and "142" in intf:
157 self.assertEqual(found, 1)
160 intfs = self.vapi.cli("show interface pg3").split("\n")
163 if "rx bytes" in intf and "142" in intf:
165 self.assertEqual(found, 1)
167 bond0.remove_vpp_config()
169 def test_bond_enslave(self):
170 """ Bond enslave/detach slave test """
172 # create interface (BondEthernet0)
173 self.logger.info("create bond")
174 bond0 = VppBondInterface(self, mode=3)
175 bond0.add_vpp_config()
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))
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,
189 self.logger.info("bond enslave interface pg1 to BondEthernet0")
190 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
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))
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)
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))
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)
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))
217 bond0.remove_vpp_config()
220 """ Bond add/delete interface test """
221 self.logger.info("Bond add interfaces")
223 # create interface 1 (BondEthernet0)
224 bond0 = VppBondInterface(self, mode=5)
225 bond0.add_vpp_config()
228 # create interface 2 (BondEthernet1)
229 bond1 = VppBondInterface(self, mode=3)
230 bond1.add_vpp_config()
233 # verify both interfaces in the show
234 ifs = self.vapi.cli("show interface")
235 self.assertIn('BondEthernet0', ifs)
236 self.assertIn('BondEthernet1', ifs)
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))
243 # delete BondEthernet1
244 self.logger.info("Deleting BondEthernet1")
245 bond1.remove_vpp_config()
247 self.logger.info("Verifying BondEthernet1 is deleted")
249 ifs = self.vapi.cli("show interface")
250 # verify BondEthernet0 still in the show
251 self.assertIn('BondEthernet0', ifs)
253 # verify BondEthernet1 not in the show
254 self.assertNotIn('BondEthernet1', ifs)
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))
260 # verify BondEthernet0 is still in the dump
261 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
263 # delete BondEthernet0
264 self.logger.info("Deleting BondEthernet0")
265 bond0.remove_vpp_config()
267 self.logger.info("Verifying BondEthernet0 is deleted")
269 # verify BondEthernet0 not in the show
270 ifs = self.vapi.cli("show interface")
271 self.assertNotIn('BondEthernet0', ifs)
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))
277 if __name__ == '__main__':
278 unittest.main(testRunner=VppTestRunner)