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 (member)
56 # BondEthernet0 (10.10.10.1)
58 # pg3 ------+ +------pg1 (memberx)
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,
71 bond0.add_vpp_config()
73 self.vapi.sw_interface_add_del_address(
74 sw_if_index=bond0.sw_if_index,
75 prefix="10.10.10.1/24")
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 neighbors"))
86 # add member pg0 and pg1 to BondEthernet0
87 self.logger.info("bond add member interface pg0 to BondEthernet0")
88 bond0.add_member_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
89 self.logger.info("bond add_member interface pg1 to BondEthernet0")
90 bond0.add_member_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
92 # verify both members in BondEthernet0
93 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
94 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
95 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
97 # generate a packet from pg2 -> BondEthernet0 -> pg1
98 # BondEthernet0 TX hashes this packet to pg1
99 p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) /
100 IP(src=self.pg2.local_ip4, dst="10.10.10.12") /
101 UDP(sport=1235, dport=1235) /
103 self.pg2.add_stream(p2)
105 # generate a packet from pg3 -> BondEthernet0 -> pg0
106 # BondEthernet0 TX hashes this packet to pg0
107 # notice the ip address and ports are different than p2 packet
108 p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) /
109 IP(src=self.pg3.local_ip4, dst="10.10.10.11") /
110 UDP(sport=1234, dport=1234) /
112 self.pg3.add_stream(p3)
114 self.pg_enable_capture(self.pg_interfaces)
116 # set up the static arp entries pointing to the BondEthernet0 interface
117 # so that it does not try to resolve the ip address
118 self.logger.info(self.vapi.cli(
119 "set ip neighbor static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
120 self.logger.info(self.vapi.cli(
121 "set ip neighbor static BondEthernet0 10.10.10.11 abcd.abcd.0004"))
123 # clear the interface counters
124 self.logger.info(self.vapi.cli("clear interfaces"))
128 self.logger.info("check the interface counters")
132 # BondEthernet0 tx bytes = 284
133 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
136 if "tx bytes" in intf and "284" in intf:
138 self.assertEqual(found, 1)
140 # BondEthernet0 tx bytes = 284
141 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
144 if "tx bytes" in intf and "284" in intf:
146 self.assertEqual(found, 1)
149 intfs = self.vapi.cli("show interface pg2").split("\n")
152 if "rx bytes" in intf and "142" in intf:
154 self.assertEqual(found, 1)
157 intfs = self.vapi.cli("show interface pg3").split("\n")
160 if "rx bytes" in intf and "142" in intf:
162 self.assertEqual(found, 1)
164 bond0.remove_vpp_config()
166 def test_bond_add_member(self):
167 """ Bond add_member/detach member test """
169 # create interface (BondEthernet0) and set bond mode to LACP
170 self.logger.info("create bond")
171 bond0 = VppBondInterface(self, mode=5)
172 bond0.add_vpp_config()
175 # verify that interfaces can be added as_member and detached two times
177 # verify pg0 and pg1 not in BondEthernet0
178 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
179 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
180 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
182 # add_member pg0 and pg1 to BondEthernet0
183 self.logger.info("bond add_member interface pg0 to BondEthernet0")
184 bond0.add_member_vpp_bond_interface(
185 sw_if_index=self.pg0.sw_if_index,
189 self.logger.info("bond add_member interface pg1 to BondEthernet0")
190 bond0.add_member_vpp_bond_interface(
191 sw_if_index=self.pg1.sw_if_index,
194 # verify both members in BondEthernet0
195 if_dump = self.vapi.sw_member_interface_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_member_interface_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_member_interface_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_bond_interface_dump(sw_if_index=0xFFFFFFFF)
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_bond_interface_dump(sw_if_index=0xFFFFFFFF)
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_bond_interface_dump(
275 sw_if_index=bond0.sw_if_index)
276 self.assertFalse(bond0.is_interface_config_in_dump(if_dump))
279 if __name__ == '__main__':
280 unittest.main(testRunner=VppTestRunner)