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 util import mactobinary
11 from vpp_bond_interface import VppBondInterface
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 super(TestBondInterface, self).setUp()
38 super(TestBondInterface, self).tearDown()
40 self.logger.info(self.vapi.ppcli("show interface"))
42 def test_bond_traffic(self):
43 """ Bond traffic test """
49 # pg2 ------+ +------pg0 (slave)
51 # BondEthernet0 (10.10.10.1)
53 # pg3 ------+ +------pg1 (slave)
56 # create interface (BondEthernet0)
57 # self.logger.info("create bond")
58 bond0_mac = "02:fe:38:30:59:3c"
59 mac = mactobinary(bond0_mac)
60 bond0 = VppBondInterface(self,
65 bond0.add_vpp_config()
67 bond0_addr = socket.inet_pton(socket.AF_INET, "10.10.10.1")
68 self.vapi.sw_interface_add_del_address(bond0.sw_if_index,
73 self.pg2.resolve_arp()
75 self.pg3.resolve_arp()
77 self.logger.info(self.vapi.cli("show interface"))
78 self.logger.info(self.vapi.cli("show interface address"))
79 self.logger.info(self.vapi.cli("show ip arp"))
81 # enslave pg0 and pg1 to BondEthernet0
82 self.logger.info("bond enslave interface pg0 to BondEthernet0")
83 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
86 self.logger.info("bond enslave interface pg1 to BondEthernet0")
87 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
91 # verify both slaves in BondEthernet0
92 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
93 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
94 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
96 # generate a packet from pg2 -> BondEthernet0 -> pg1
97 # BondEthernet0 TX hashes this packet to pg1
98 p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) /
99 IP(src=self.pg2.local_ip4, dst="10.10.10.12") /
100 UDP(sport=1235, dport=1235) /
102 self.pg2.add_stream(p2)
104 # generate a packet from pg3 -> BondEthernet0 -> pg0
105 # BondEthernet0 TX hashes this packet to pg0
106 # notice the ip address and ports are different than p2 packet
107 p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) /
108 IP(src=self.pg3.local_ip4, dst="10.10.10.11") /
109 UDP(sport=1234, dport=1234) /
111 self.pg3.add_stream(p3)
113 self.pg_enable_capture(self.pg_interfaces)
115 # set up the static arp entries pointing to the BondEthernet0 interface
116 # so that it does not try to resolve the ip address
117 self.logger.info(self.vapi.cli(
118 "set ip arp static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
119 self.logger.info(self.vapi.cli(
120 "set ip arp static BondEthernet0 10.10.10.11 abcd.abcd.0004"))
122 # clear the interface counters
123 self.logger.info(self.vapi.cli("clear interfaces"))
127 self.logger.info("check the interface counters")
131 # BondEthernet0 tx bytes = 284
132 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
135 if "tx bytes" in intf and "284" in intf:
137 self.assertEqual(found, 1)
139 # BondEthernet0 tx bytes = 284
140 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
143 if "tx bytes" in intf and "284" in intf:
145 self.assertEqual(found, 1)
148 intfs = self.vapi.cli("show interface pg2").split("\n")
151 if "rx bytes" in intf and "142" in intf:
153 self.assertEqual(found, 1)
156 intfs = self.vapi.cli("show interface pg3").split("\n")
159 if "rx bytes" in intf and "142" in intf:
161 self.assertEqual(found, 1)
163 bond0.remove_vpp_config()
165 def test_bond_enslave(self):
166 """ Bond enslave/detach slave test """
168 # create interface (BondEthernet0)
169 self.logger.info("create bond")
170 bond0 = VppBondInterface(self, mode=3)
171 bond0.add_vpp_config()
174 # verify pg0 and pg1 not in BondEthernet0
175 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
176 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
177 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
179 # enslave pg0 and pg1 to BondEthernet0
180 self.logger.info("bond enslave interface pg0 to BondEthernet0")
181 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index,
185 self.logger.info("bond enslave interface pg1 to BondEthernet0")
186 bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index,
190 # verify both slaves in BondEthernet0
191 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
192 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
193 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
195 # detach interface pg0
196 self.logger.info("detach interface pg0")
197 bond0.detach_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
199 # verify pg0 is not in BondEthernet0, but pg1 is
200 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
201 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
202 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
204 # detach interface pg1
205 self.logger.info("detach interface pg1")
206 bond0.detach_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
208 # verify pg0 and pg1 not in BondEthernet0
209 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index)
210 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
211 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
213 bond0.remove_vpp_config()
216 """ Bond add/delete interface test """
217 self.logger.info("Bond add interfaces")
219 # create interface 1 (BondEthernet0)
220 bond0 = VppBondInterface(self, mode=5)
221 bond0.add_vpp_config()
224 # create interface 2 (BondEthernet1)
225 bond1 = VppBondInterface(self, mode=3)
226 bond1.add_vpp_config()
229 # verify both interfaces in the show
230 ifs = self.vapi.cli("show interface")
231 self.assertNotEqual(ifs.find('BondEthernet0'), -1)
232 self.assertNotEqual(ifs.find('BondEthernet1'), -1)
234 # verify they are in the dump also
235 if_dump = self.vapi.sw_interface_bond_dump()
236 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
237 self.assertTrue(bond1.is_interface_config_in_dump(if_dump))
239 # delete BondEthernet1
240 self.logger.info("Deleting BondEthernet1")
241 bond1.remove_vpp_config()
243 self.logger.info("Verifying BondEthernet1 is deleted")
245 ifs = self.vapi.cli("show interface")
246 # verify BondEthernet0 still in the show
247 self.assertNotEqual(ifs.find('BondEthernet0'), -1)
249 # verify BondEthernet1 not in the show
250 self.assertEqual(ifs.find('BondEthernet1'), -1)
252 # verify BondEthernet1 is not in the dump
253 if_dump = self.vapi.sw_interface_bond_dump()
254 self.assertFalse(bond1.is_interface_config_in_dump(if_dump))
256 # verify BondEthernet0 is still in the dump
257 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
259 # delete BondEthernet0
260 self.logger.info("Deleting BondEthernet0")
261 bond0.remove_vpp_config()
263 self.logger.info("Verifying BondEthernet0 is deleted")
265 # verify BondEthernet0 not in the show
266 ifs = self.vapi.cli("show interface")
267 self.assertEqual(ifs.find('BondEthernet0'), -1)
269 # verify BondEthernet0 is not in the dump
270 if_dump = self.vapi.sw_interface_bond_dump()
271 self.assertFalse(bond0.is_interface_config_in_dump(if_dump))
273 if __name__ == '__main__':
274 unittest.main(testRunner=VppTestRunner)