diff options
-rw-r--r-- | src/plugins/lacp/test/test_lacp.py | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/src/plugins/lacp/test/test_lacp.py b/src/plugins/lacp/test/test_lacp.py new file mode 100644 index 00000000000..fa4b0a21ca9 --- /dev/null +++ b/src/plugins/lacp/test/test_lacp.py @@ -0,0 +1,364 @@ +#!/usr/bin/env python3 + +import time +import unittest + +from scapy.contrib.lacp import LACP, SlowProtocol, MarkerProtocol +from scapy.layers.l2 import Ether + +from framework import VppTestCase, VppTestRunner +from vpp_memif import remove_all_memif_vpp_config, VppSocketFilename, VppMemif +from vpp_bond_interface import VppBondInterface +from vpp_papi import VppEnum, MACAddress + +bond_mac = "02:02:02:02:02:02" +lacp_dst_mac = '01:80:c2:00:00:02' +LACP_COLLECTION_AND_DISTRIBUTION_STATE = 63 + + +class TestMarker(VppTestCase): + """LACP Marker Protocol Test Case + + """ + + @classmethod + def setUpClass(cls): + super().setUpClass() + # Test variables + cls.pkts_per_burst = 257 # Number of packets per burst + # create 3 pg interfaces + cls.create_pg_interfaces(range(1)) + + # packet sizes + cls.pg_if_packet_sizes = [64, 512, 1518] # , 9018] + + # setup all interfaces + for i in cls.pg_interfaces: + i.admin_up() + + @classmethod + def tearDownClass(cls): + super().tearDownClass() + + def setUp(self): + super().setUp() + + def tearDown(self): + super().tearDown() + + def show_commands_at_teardown(self): + self.logger.info(self.vapi.ppcli("show interface")) + + def test_marker_request(self): + """ Marker Request test """ + + # topology + # + # +-+ +-+ + # memif1 -----|B| |B|---- memif11 + # |o| |o| + # |n|------|n| + # |d| |d| + # pg0 -----|0| |1| + # +-+ +-+ + + socket1 = VppSocketFilename( + self, + socket_id=1, + socket_filename="%s/memif.sock1" % self.tempdir) + socket1.add_vpp_config() + + socket11 = VppSocketFilename( + self, + socket_id=2, + socket_filename="%s/memif.sock1" % self.tempdir) + socket11.add_vpp_config() + + memif1 = VppMemif( + self, + role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_MASTER, + mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET, + socket_id=1) + memif1.add_vpp_config() + memif1.admin_up() + + memif11 = VppMemif( + self, + role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_SLAVE, + mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET, + socket_id=2) + memif11.add_vpp_config() + memif11.admin_up() + + bond0 = VppBondInterface( + self, + mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP, + use_custom_mac=1, + mac_address=bond_mac) + + bond0.add_vpp_config() + bond0.admin_up() + + bond1 = VppBondInterface( + self, + mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP) + bond1.add_vpp_config() + bond1.admin_up() + + bond0.enslave_vpp_bond_interface(sw_if_index=memif1.sw_if_index) + bond1.enslave_vpp_bond_interface(sw_if_index=memif11.sw_if_index) + + # wait for memif protocol exchange and hardware carrier to come up + self.assertEqual(memif1.wait_for_link_up(10), True) + self.assertEqual(memif11.wait_for_link_up(10), True) + + # verify memif1 in bond0 + intfs = self.vapi.sw_interface_slave_dump( + sw_if_index=bond0.sw_if_index) + for intf in intfs: + self.assertEqual(intf.sw_if_index, memif1.sw_if_index) + + # verify memif11 in bond1 + intfs = self.vapi.sw_interface_slave_dump( + sw_if_index=bond1.sw_if_index) + for intf in intfs: + self.assertEqual(intf.sw_if_index, memif11.sw_if_index) + + self.vapi.ppcli("trace add memif-input 100") + + # create marker request + marker = (Ether(src=bond_mac, dst=lacp_dst_mac) / + SlowProtocol() / + MarkerProtocol(marker_type=1, + requester_port=1, + requester_system=bond_mac, + requester_transaction_id=1)) + + bond1.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index) + self.pg0.add_stream(marker) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + show_trace = self.vapi.ppcli("show trace max 100") + self.assertIn("Marker Information TLV:", show_trace) + + bond0.remove_vpp_config() + bond1.remove_vpp_config() + + +class TestLACP(VppTestCase): + """LACP Test Case + + """ + + @classmethod + def setUpClass(cls): + super().setUpClass() + + @classmethod + def tearDownClass(cls): + super().tearDownClass() + + def setUp(self): + super().setUp() + + def tearDown(self): + super().tearDown() + + def show_commands_at_teardown(self): + self.logger.info(self.vapi.ppcli("show interface")) + + def wait_for_lacp_connect(self, timeout, step=1): + while 1: + intfs = self.vapi.sw_interface_lacp_dump() + all_good = 1 + for intf in intfs: + if ((intf.actor_state != + LACP_COLLECTION_AND_DISTRIBUTION_STATE) or + (intf.partner_state != + LACP_COLLECTION_AND_DISTRIBUTION_STATE)): + all_good = 0 + if (all_good == 1): + return 1 + self.sleep(step) + timeout -= step + if timeout <= 0: + return 0 + + def wait_for_slave_detach(self, bond, timeout, count, step=1): + while 1: + intfs = self.vapi.sw_interface_bond_dump() + for intf in intfs: + if (bond.sw_if_index == intf.sw_if_index): + if ((intf.slaves == count) and + (intf.active_slaves == count)): + return 1 + else: + self.sleep(1) + timeout -= step + if (timeouut <= 0): + return 0 + + def test_lacp_connect(self): + """ LACP protocol connect test """ + + # topology + # + # +-+ +-+ + # memif1 -----|B| |B|---- memif11 + # |o| |o| + # |n|------|n| + # |d| |d| + # memif2 -----|0| |1|---- memif12 + # +-+ +-+ + + socket1 = VppSocketFilename( + self, + socket_id=1, + socket_filename="%s/memif.sock1" % self.tempdir) + socket1.add_vpp_config() + + socket11 = VppSocketFilename( + self, + socket_id=2, + socket_filename="%s/memif.sock1" % self.tempdir) + socket11.add_vpp_config() + + socket2 = VppSocketFilename( + self, + socket_id=3, + socket_filename="%s/memif.sock2" % self.tempdir) + socket2.add_vpp_config() + + socket22 = VppSocketFilename( + self, + socket_id=4, + socket_filename="%s/memif.sock2" % self.tempdir) + socket22.add_vpp_config() + + memif1 = VppMemif( + self, + role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_MASTER, + mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET, + socket_id=1) + memif1.add_vpp_config() + memif1.admin_up() + + memif11 = VppMemif( + self, + role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_SLAVE, + mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET, + socket_id=2) + memif11.add_vpp_config() + memif11.admin_up() + + memif2 = VppMemif( + self, + role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_MASTER, + mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET, + socket_id=3) + memif2.add_vpp_config() + memif2.admin_up() + + memif12 = VppMemif( + self, + role=VppEnum.vl_api_memif_role_t.MEMIF_ROLE_API_SLAVE, + mode=VppEnum.vl_api_memif_mode_t.MEMIF_MODE_API_ETHERNET, + socket_id=4) + memif12.add_vpp_config() + memif12.admin_up() + + self.logger.info(self.vapi.ppcli("debug lacp on")) + bond0 = VppBondInterface( + self, + mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP, + use_custom_mac=1, + mac_address=bond_mac) + + bond0.add_vpp_config() + bond0.admin_up() + + bond1 = VppBondInterface( + self, + mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP) + bond1.add_vpp_config() + bond1.admin_up() + + # enslave memif1 and memif2 to bond0 + bond0.enslave_vpp_bond_interface(sw_if_index=memif1.sw_if_index) + bond0.enslave_vpp_bond_interface(sw_if_index=memif2.sw_if_index) + + # enslave memif11 and memif12 to bond1 + bond1.enslave_vpp_bond_interface(sw_if_index=memif11.sw_if_index) + bond1.enslave_vpp_bond_interface(sw_if_index=memif12.sw_if_index) + + # wait for memif protocol exchange and hardware carrier to come up + self.assertEqual(memif1.wait_for_link_up(10), True) + self.assertEqual(memif2.wait_for_link_up(10), True) + self.assertEqual(memif11.wait_for_link_up(10), True) + self.assertEqual(memif12.wait_for_link_up(10), True) + + # verify memif1 and memif2 in bond0 + intfs = self.vapi.sw_interface_slave_dump( + sw_if_index=bond0.sw_if_index) + for intf in intfs: + self.assertIn( + intf.sw_if_index, (memif1.sw_if_index, memif2.sw_if_index)) + + # verify memif11 and memif12 in bond1 + intfs = self.vapi.sw_interface_slave_dump( + sw_if_index=bond1.sw_if_index) + for intf in intfs: + self.assertIn( + intf.sw_if_index, (memif11.sw_if_index, memif12.sw_if_index)) + self.assertEqual(intf.is_long_timeout, 0) + self.assertEqual(intf.is_passive, 0) + + # Let LACP create the bundle + self.wait_for_lacp_connect(30) + + intfs = self.vapi.sw_interface_lacp_dump() + for intf in intfs: + self.assertEqual( + intf.actor_state, LACP_COLLECTION_AND_DISTRIBUTION_STATE) + self.assertEqual( + intf.partner_state, LACP_COLLECTION_AND_DISTRIBUTION_STATE) + + intfs = self.vapi.sw_interface_bond_dump() + for intf in intfs: + self.assertEqual(intf.slaves, 2) + self.assertEqual(intf.active_slaves, 2) + self.assertEqual( + intf.mode, VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP) + + self.logger.info(self.vapi.ppcli("show lacp")) + self.logger.info(self.vapi.ppcli("show lacp details")) + + # detach slave memif1 + bond0.detach_vpp_bond_interface(sw_if_index=memif1.sw_if_index) + + self.wait_for_slave_detach(bond0, timeout=10, count=1) + intfs = self.vapi.sw_interface_bond_dump() + for intf in intfs: + if (bond0.sw_if_index == intf.sw_if_index): + self.assertEqual(intf.slaves, 1) + self.assertEqual(intf.active_slaves, 1) + self.assertEqual( + intf.mode, VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP) + + # detach slave memif2 + bond0.detach_vpp_bond_interface(sw_if_index=memif2.sw_if_index) + self.wait_for_slave_detach(bond0, timeout=10, count=0) + + intfs = self.vapi.sw_interface_bond_dump() + for intf in intfs: + if (bond0.sw_if_index == intf.sw_if_index): + self.assertEqual(intf.slaves, 0) + self.assertEqual(intf.active_slaves, 0) + + bond0.remove_vpp_config() + bond1.remove_vpp_config() + + +if __name__ == '__main__': + unittest.main(testRunner=VppTestRunner) |