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(self,
72 bond0.add_vpp_config()
74 self.vapi.sw_interface_add_del_address(
75 sw_if_index=bond0.sw_if_index,
76 prefix="10.10.10.1/24")
79 self.pg2.resolve_arp()
81 self.pg3.resolve_arp()
83 self.logger.info(self.vapi.cli("show interface"))
84 self.logger.info(self.vapi.cli("show interface address"))
85 self.logger.info(self.vapi.cli("show ip neighbors"))
87 # add member pg0 and pg1 to BondEthernet0
88 self.logger.info("bond add member interface pg0 to BondEthernet0")
89 bond0.add_member_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index)
90 self.logger.info("bond add_member interface pg1 to BondEthernet0")
91 bond0.add_member_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index)
93 # verify both members in BondEthernet0
94 if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index)
95 self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump))
96 self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump))
98 # generate a packet from pg2 -> BondEthernet0 -> pg1
99 # BondEthernet0 TX hashes this packet to pg1
100 p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) /
101 IP(src=self.pg2.local_ip4, dst="10.10.10.12") /
102 UDP(sport=1235, dport=1235) /
104 self.pg2.add_stream(p2)
106 # generate a packet from pg3 -> BondEthernet0 -> pg0
107 # BondEthernet0 TX hashes this packet to pg0
108 # notice the ip address and ports are different than p2 packet
109 p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) /
110 IP(src=self.pg3.local_ip4, dst="10.10.10.11") /
111 UDP(sport=1234, dport=1234) /
113 self.pg3.add_stream(p3)
115 self.pg_enable_capture(self.pg_interfaces)
117 # set up the static arp entries pointing to the BondEthernet0 interface
118 # so that it does not try to resolve the ip address
119 self.logger.info(self.vapi.cli(
120 "set ip neighbor static BondEthernet0 10.10.10.12 abcd.abcd.0002"))
121 self.logger.info(self.vapi.cli(
122 "set ip neighbor static BondEthernet0 10.10.10.11 abcd.abcd.0004"))
124 # clear the interface counters
125 self.logger.info(self.vapi.cli("clear interfaces"))
129 self.logger.info("check the interface counters")
133 # BondEthernet0 tx bytes = 284
134 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
137 if "tx bytes" in intf and "284" in intf:
139 self.assertEqual(found, 1)
141 # BondEthernet0 tx bytes = 284
142 intfs = self.vapi.cli("show interface BondEthernet0").split("\n")
145 if "tx bytes" in intf and "284" in intf:
147 self.assertEqual(found, 1)
150 intfs = self.vapi.cli("show interface pg2").split("\n")
153 if "rx bytes" in intf and "142" in intf:
155 self.assertEqual(found, 1)
158 intfs = self.vapi.cli("show interface pg3").split("\n")
161 if "rx bytes" in intf and "142" in intf:
163 self.assertEqual(found, 1)
165 bond0.remove_vpp_config()
167 def test_bond_add_member(self):
168 """ Bond add_member/detach member test """
170 # create interface (BondEthernet0) and set bond mode to LACP
171 self.logger.info("create bond")
172 bond0 = VppBondInterface(self, mode=5)
173 bond0.add_vpp_config()
176 # verify that interfaces can be added as_member and detached two times
178 # verify pg0 and pg1 not in BondEthernet0
179 if_dump = self.vapi.sw_member_interface_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 # add_member pg0 and pg1 to BondEthernet0
184 self.logger.info("bond add_member interface pg0 to BondEthernet0")
185 bond0.add_member_vpp_bond_interface(
186 sw_if_index=self.pg0.sw_if_index,
190 self.logger.info("bond add_member interface pg1 to BondEthernet0")
191 bond0.add_member_vpp_bond_interface(
192 sw_if_index=self.pg1.sw_if_index,
195 # verify both members in BondEthernet0
196 if_dump = self.vapi.sw_member_interface_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_member_interface_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_member_interface_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_bond_interface_dump(sw_if_index=0xFFFFFFFF)
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_bond_interface_dump(sw_if_index=0xFFFFFFFF)
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_bond_interface_dump(
276 sw_if_index=bond0.sw_if_index)
277 self.assertFalse(bond0.is_interface_config_in_dump(if_dump))
279 def test_bond_link(self):
280 """ Bond hw interface link state test """
283 bond_modes = VppEnum.vl_api_bond_mode_t
284 intf_flags = VppEnum.vl_api_if_status_flags_t
286 # create interface 1 (BondEthernet0)
287 self.logger.info("Create bond interface")
288 # use round-robin mode to avoid negotiation required by LACP
289 bond0 = VppBondInterface(self,
290 mode=bond_modes.BOND_API_MODE_ROUND_ROBIN)
291 bond0.add_vpp_config()
294 self.logger.info("set interface BondEthernet0 admin up")
297 bond0.assert_interface_state(intf_flags.IF_STATUS_API_FLAG_ADMIN_UP,
298 intf_flags.IF_STATUS_API_FLAG_LINK_UP)
300 # toggle bond admin state
301 self.logger.info("toggle interface BondEthernet0")
305 # confirm link is still up
306 bond0.assert_interface_state(intf_flags.IF_STATUS_API_FLAG_ADMIN_UP,
307 intf_flags.IF_STATUS_API_FLAG_LINK_UP)
309 # delete BondEthernet0
310 self.logger.info("Deleting BondEthernet0")
311 bond0.remove_vpp_config()
314 if __name__ == '__main__':
315 unittest.main(testRunner=VppTestRunner)