aboutsummaryrefslogtreecommitdiffstats
path: root/test/test_lacp.py
blob: b5f2dae2cd318f305231312292c1ede08f6f04d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/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.add_member_vpp_bond_interface(sw_if_index=memif1.sw_if_index)
        bond1.add_member_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_member_interface_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_member_interface_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.add_member_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_member_detach(self, bond, timeout, count, step=1):
        while 1:
            intfs = self.vapi.sw_bond_interface_dump(
                sw_if_index=bond.sw_if_index)
            for intf in intfs:
                if ((intf.members == count) and
                        (intf.active_members == 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()

        # add member memif1 and memif2 to bond0
        bond0.add_member_vpp_bond_interface(sw_if_index=memif1.sw_if_index)
        bond0.add_member_vpp_bond_interface(sw_if_index=memif2.sw_if_index)

        # add member memif11 and memif12 to bond1
        bond1.add_member_vpp_bond_interface(sw_if_index=memif11.sw_if_index)
        bond1.add_member_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_member_interface_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_member_interface_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_bond_interface_dump(sw_if_index=0xFFFFFFFF)
        for intf in intfs:
            self.assertEqual(intf.members, 2)
            self.assertEqual(intf.active_members, 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 member memif1
        bond0.detach_vpp_bond_interface(sw_if_index=memif1.sw_if_index)

        self.wait_for_member_detach(bond0, timeout=10, count=1)
        intfs = self.vapi.sw_bond_interface_dump(
            sw_if_index=bond0.sw_if_index)
        for intf in intfs:
            self.assertEqual(intf.members, 1)
            self.assertEqual(intf.active_members, 1)
            self.assertEqual(
                intf.mode, VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP)

        # detach member memif2
        bond0.detach_vpp_bond_interface(sw_if_index=memif2.sw_if_index)
        self.wait_for_member_detach(bond0, timeout=10, count=0)

        intfs = self.vapi.sw_bond_interface_dump(
            sw_if_index=bond0.sw_if_index)
        for intf in intfs:
            self.assertEqual(intf.members, 0)
            self.assertEqual(intf.active_members, 0)

        bond0.remove_vpp_config()
        bond1.remove_vpp_config()


if __name__ == '__main__':
    unittest.main(testRunner=VppTestRunner)