6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether
8 from scapy.layers.inet import IP, UDP
10 from framework import VppTestCase, VppTestRunner
11 from vpp_bond_interface import VppBondInterface
12 from vpp_papi import MACAddress, VppEnum
15 class TestBondInterface(VppTestCase):
22 super(TestBondInterface, cls).setUpClass()
24 cls.pkts_per_burst = 257 # Number of packets per burst
25 # create 3 pg interfaces
26 cls.create_pg_interfaces(range(4))
29 cls.pg_if_packet_sizes = [64, 512, 1518] # , 9018]
31 # setup all interfaces
32 for i in cls.pg_interfaces:
36 def tearDownClass(cls):
37 super(TestBondInterface, cls).tearDownClass()
40 super(TestBondInterface, self).setUp()
43 super(TestBondInterface, self).tearDown()
45 def show_commands_at_teardown(self):
46 self.logger.info(self.vapi.ppcli("show interface"))
48 def test_bond_traffic(self):
49 """ Bond traffic test """
55 # pg2 ------+ +------pg0 (member)
57 # BondEthernet0 (10.10.10.1)
59 # pg3 ------+ +------pg1 (memberx)
62 # create interface (BondEthernet0)
63 # self.logger.info("create bond")
64 bond0_mac = "02:fe:38:30:59:3c"
65 mac = MACAddress(bond0_mac).packed
66 bond0 = VppBondInterface(
68 mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_XOR,
69 lb=VppEnum.vl_api_bond_lb_algo_t.BOND_API_LB_ALGO_L34,
73 bond0.add_vpp_config()
75 self.vapi.sw_interface_add_del_address(
76 sw_if_index=bond0.sw_if_index,
77 prefix="10.10.10.1/24")
80 self.pg2.resolve_arp()
82 self.pg3.resolve_arp()
84 self.logger.info(self.vapi.cli("show interface"))
85 self.logger.info(self.vapi.cli("show interface address"))
86 self.logger.info(self.vapi.cli("show ip neighbors"))
88 # add member pg0 and pg1 to BondEthernet0
89 self.logger.info("bond add member interface pg0 to BondEthernet0")
90 bond0.add_member_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
91 self.logger.info("bond add_member interface pg1 to BondEthernet0")
92 bond0.add_member_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
94 # verify both members in BondEthernet0
95 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
96 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
97 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
99 # generate a packet from pg2 -> BondEthernet0 -> pg1
100 # BondEthernet0 TX hashes this packet to pg1
101 p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) /
102 IP(src=self.pg2.local_ip4, dst="10.10.10.12") /
103 UDP(sport=1235, dport=1235) /
105 self.pg2.add_stream(p2)
107 # generate a packet from pg3 -> BondEthernet0 -> pg0
108 # BondEthernet0 TX hashes this packet to pg0
109 # notice the ip address and ports are different than p2 packet
110 p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) /
111 IP(src=self.pg3.local_ip4, dst="10.10.10.11") /
112 UDP(sport=1234, dport=1234) /
114 self.pg3.add_stream(p3)
116 self.pg_enable_capture(self.pg_interfaces)
118 # set up the static arp entries pointing to the BondEthernet0 interface
119 # so that it does not try to resolve the ip address
120 self.logger.info(self.vapi.cli(
121 "set ip neighbor static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
122 self.logger.info(self.vapi.cli(
123 "set ip neighbor static BondEthernet0 10.10.10.11 abcd.abcd.0004"))
125 # clear the interface counters
126 self.logger.info(self.vapi.cli("clear interfaces"))
130 self.logger.info("check the interface counters")
134 # BondEthernet0 tx bytes = 284
135 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
138 if "tx bytes" in intf and "284" in intf:
140 self.assertEqual(found, 1)
142 # BondEthernet0 tx bytes = 284
143 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
146 if "tx bytes" in intf and "284" in intf:
148 self.assertEqual(found, 1)
151 intfs = self.vapi.cli("show interface pg2").split("\n")
154 if "rx bytes" in intf and "142" in intf:
156 self.assertEqual(found, 1)
159 intfs = self.vapi.cli("show interface pg3").split("\n")
162 if "rx bytes" in intf and "142" in intf:
164 self.assertEqual(found, 1)
166 bond0.remove_vpp_config()
168 def test_bond_add_member(self):
169 """ Bond add_member/detach member test """
171 # create interface (BondEthernet0) and set bond mode to LACP
172 self.logger.info("create bond")
173 bond0 = VppBondInterface(
175 mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP,
177 bond0.add_vpp_config()
180 # verify that interfaces can be added as_member and detached two times
182 # verify pg0 and pg1 not in BondEthernet0
183 if_dump = self.vapi.sw_member_interface_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))
187 # add_member pg0 and pg1 to BondEthernet0
188 self.logger.info("bond add_member interface pg0 to BondEthernet0")
189 bond0.add_member_vpp_bond_interface(
190 sw_if_index=self.pg0.sw_if_index,
194 self.logger.info("bond add_member interface pg1 to BondEthernet0")
195 bond0.add_member_vpp_bond_interface(
196 sw_if_index=self.pg1.sw_if_index,
199 # verify both members in BondEthernet0
200 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
201 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
202 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
204 # detach interface pg0
205 self.logger.info("detach interface pg0")
206 bond0.detach_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
208 # verify pg0 is not in BondEthernet0, but pg1 is
209 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
210 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
211 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
213 # detach interface pg1
214 self.logger.info("detach interface pg1")
215 bond0.detach_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
217 # verify pg0 and pg1 not in BondEthernet0
218 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
219 self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump))
220 self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump))
222 bond0.remove_vpp_config()
225 """ Bond add/delete interface test """
226 self.logger.info("Bond add interfaces")
228 # create interface 1 (BondEthernet0)
229 bond0 = VppBondInterface(
230 self, mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP)
231 bond0.add_vpp_config()
234 # create interface 2 (BondEthernet1)
235 bond1 = VppBondInterface(
236 self, mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_XOR)
237 bond1.add_vpp_config()
240 # verify both interfaces in the show
241 ifs = self.vapi.cli("show interface")
242 self.assertIn('BondEthernet0', ifs)
243 self.assertIn('BondEthernet1', ifs)
245 # verify they are in the dump also
246 if_dump = self.vapi.sw_bond_interface_dump(sw_if_index=0xFFFFFFFF)
247 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
248 self.assertTrue(bond1.is_interface_config_in_dump(if_dump))
250 # delete BondEthernet1
251 self.logger.info("Deleting BondEthernet1")
252 bond1.remove_vpp_config()
254 self.logger.info("Verifying BondEthernet1 is deleted")
256 ifs = self.vapi.cli("show interface")
257 # verify BondEthernet0 still in the show
258 self.assertIn('BondEthernet0', ifs)
260 # verify BondEthernet1 not in the show
261 self.assertNotIn('BondEthernet1', ifs)
263 # verify BondEthernet1 is not in the dump
264 if_dump = self.vapi.sw_bond_interface_dump(sw_if_index=0xFFFFFFFF)
265 self.assertFalse(bond1.is_interface_config_in_dump(if_dump))
267 # verify BondEthernet0 is still in the dump
268 self.assertTrue(bond0.is_interface_config_in_dump(if_dump))
270 # delete BondEthernet0
271 self.logger.info("Deleting BondEthernet0")
272 bond0.remove_vpp_config()
274 self.logger.info("Verifying BondEthernet0 is deleted")
276 # verify BondEthernet0 not in the show
277 ifs = self.vapi.cli("show interface")
278 self.assertNotIn('BondEthernet0', ifs)
280 # verify BondEthernet0 is not in the dump
281 if_dump = self.vapi.sw_bond_interface_dump(
282 sw_if_index=bond0.sw_if_index)
283 self.assertFalse(bond0.is_interface_config_in_dump(if_dump))
285 def test_bond_link(self):
286 """ Bond hw interface link state test """
289 bond_modes = VppEnum.vl_api_bond_mode_t
290 intf_flags = VppEnum.vl_api_if_status_flags_t
292 # create interface 1 (BondEthernet0)
293 self.logger.info("Create bond interface")
294 # use round-robin mode to avoid negotiation required by LACP
295 bond0 = VppBondInterface(self,
296 mode=bond_modes.BOND_API_MODE_ROUND_ROBIN)
297 bond0.add_vpp_config()
300 self.logger.info("set interface BondEthernet0 admin up")
303 bond0.assert_interface_state(intf_flags.IF_STATUS_API_FLAG_ADMIN_UP,
304 intf_flags.IF_STATUS_API_FLAG_LINK_UP)
306 # toggle bond admin state
307 self.logger.info("toggle interface BondEthernet0")
311 # confirm link is still up
312 bond0.assert_interface_state(intf_flags.IF_STATUS_API_FLAG_ADMIN_UP,
313 intf_flags.IF_STATUS_API_FLAG_LINK_UP)
315 # delete BondEthernet0
316 self.logger.info("Deleting BondEthernet0")
317 bond0.remove_vpp_config()
320 if __name__ == '__main__':
321 unittest.main(testRunner=VppTestRunner)