From dc477fb0c4ae61bd4a92576361aa98bb59ddba4a Mon Sep 17 00:00:00 2001 From: "anton.novikau" Date: Wed, 3 Aug 2022 22:40:40 +0300 Subject: [PATCH] [swss/cfgmgr] teammgr configure lacp rate (#2121) * add lacp_rate config * add lacp_rate to teammgr addLag params * docs for portchannel db config * add test Co-authored-by: Anton Co-authored-by: Myron Sosyak --- cfgmgr/teammgr.cpp | 20 ++++++++++++++++---- cfgmgr/teammgr.h | 2 +- tests/conftest.py | 7 ++++--- tests/dvslib/dvs_lag.py | 18 +++++++++++++++--- tests/test_portchannel.py | 26 +++++++++++++++++++++++++- 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/cfgmgr/teammgr.cpp b/cfgmgr/teammgr.cpp index 31f911741cbf..273674fbee52 100644 --- a/cfgmgr/teammgr.cpp +++ b/cfgmgr/teammgr.cpp @@ -252,6 +252,7 @@ void TeamMgr::doLagTask(Consumer &consumer) { int min_links = 0; bool fallback = false; + bool fast_rate = false; string admin_status = DEFAULT_ADMIN_STATUS_STR; string mtu = DEFAULT_MTU_STR; string learn_mode; @@ -293,12 +294,18 @@ void TeamMgr::doLagTask(Consumer &consumer) { tpid = fvValue(i); SWSS_LOG_INFO("Get TPID %s", tpid.c_str()); - } + } + else if (fvField(i) == "fast_rate") + { + fast_rate = fvValue(i) == "true"; + SWSS_LOG_INFO("Get fast_rate `%s`", + fast_rate ? "true" : "false"); + } } if (m_lagList.find(alias) == m_lagList.end()) { - if (addLag(alias, min_links, fallback) == task_need_retry) + if (addLag(alias, min_links, fallback, fast_rate) == task_need_retry) { it++; continue; @@ -553,7 +560,7 @@ bool TeamMgr::setLagLearnMode(const string &alias, const string &learn_mode) return true; } -task_process_status TeamMgr::addLag(const string &alias, int min_links, bool fallback) +task_process_status TeamMgr::addLag(const string &alias, int min_links, bool fallback, bool fast_rate) { SWSS_LOG_ENTER(); @@ -610,6 +617,11 @@ task_process_status TeamMgr::addLag(const string &alias, int min_links, bool fal conf << ",\"fallback\":true"; } + if (fast_rate) + { + conf << ",\"fast_rate\":true"; + } + conf << "}}'"; SWSS_LOG_INFO("Port channel %s teamd configuration: %s", @@ -652,7 +664,7 @@ bool TeamMgr::removeLag(const string &alias) } // Port-channel names are in the pattern of "PortChannel####" -// +// // The LACP key could be generated in 3 ways based on the value in config DB: // 1. "auto" - LACP key is extracted from the port-channel name and is set to be the number at the end of the port-channel name // We are adding 1 at the beginning to avoid LACP key collisions between similar LACP keys e.g. PortChannel10 and PortChannel010. diff --git a/cfgmgr/teammgr.h b/cfgmgr/teammgr.h index db87fdd1f4df..3c98f87dc5eb 100644 --- a/cfgmgr/teammgr.h +++ b/cfgmgr/teammgr.h @@ -41,7 +41,7 @@ class TeamMgr : public Orch void doLagMemberTask(Consumer &consumer); void doPortUpdateTask(Consumer &consumer); - task_process_status addLag(const std::string &alias, int min_links, bool fall_back); + task_process_status addLag(const std::string &alias, int min_links, bool fall_back, bool fast_rate); bool removeLag(const std::string &alias); task_process_status addLagMember(const std::string &lag, const std::string &member); bool removeLagMember(const std::string &lag, const std::string &member); diff --git a/tests/conftest.py b/tests/conftest.py index 6e6939d41c96..437190a68926 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -412,7 +412,7 @@ def create_servers(self): for i in range(NUM_PORTS): server = VirtualServer(self.ctn_sw.name, self.ctn_sw_pid, i) self.servers.append(server) - + def reset_dbs(self): # DB wrappers are declared here, lazy-loaded in the tests self.app_db = None @@ -1853,7 +1853,8 @@ def dvs_route(request, dvs) -> DVSRoute: @pytest.yield_fixture(scope="class") def dvs_lag_manager(request, dvs): request.cls.dvs_lag = dvs_lag.DVSLag(dvs.get_asic_db(), - dvs.get_config_db()) + dvs.get_config_db(), + dvs) @pytest.yield_fixture(scope="class") @@ -1868,7 +1869,7 @@ def dvs_vlan_manager(request, dvs): def dvs_port_manager(request, dvs): request.cls.dvs_port = dvs_port.DVSPort(dvs.get_asic_db(), dvs.get_config_db()) - + @pytest.yield_fixture(scope="class") def dvs_mirror_manager(request, dvs): request.cls.dvs_mirror = dvs_mirror.DVSMirror(dvs.get_asic_db(), diff --git a/tests/dvslib/dvs_lag.py b/tests/dvslib/dvs_lag.py index 06dd0c421783..3e8c27f11dd4 100644 --- a/tests/dvslib/dvs_lag.py +++ b/tests/dvslib/dvs_lag.py @@ -1,11 +1,14 @@ +import json + class DVSLag(object): - def __init__(self, adb, cdb): + def __init__(self, adb, cdb, dvs): self.asic_db = adb self.config_db = cdb + self.dvs = dvs - def create_port_channel(self, lag_id, admin_status="up", mtu="1500"): + def create_port_channel(self, lag_id, admin_status="up", mtu="1500", fast_rate=False): lag = "PortChannel{}".format(lag_id) - lag_entry = {"admin_status": admin_status, "mtu": mtu} + lag_entry = {"admin_status": admin_status, "mtu": mtu, "fast_rate": str(fast_rate).lower()} self.config_db.create_entry("PORTCHANNEL", lag, lag_entry) def remove_port_channel(self, lag_id): @@ -27,3 +30,12 @@ def get_and_verify_port_channel_members(self, expected_num): def get_and_verify_port_channel(self, expected_num): return self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_LAG", expected_num) + def dump_portchannel(self, lag_id): + lag = "PortChannel{}".format(lag_id) + output = self.dvs.runcmd("teamdctl {} state dump".format(lag))[1] + port_state_dump = json.loads(output) + return port_state_dump + + def get_and_verify_port_channel_fast_rate(self, lag_id, fast_rate): + assert self.dump_portchannel(lag_id)["runner"]["fast_rate"] == fast_rate + diff --git a/tests/test_portchannel.py b/tests/test_portchannel.py index 3e24b6a34000..0a922e6936e8 100644 --- a/tests/test_portchannel.py +++ b/tests/test_portchannel.py @@ -1,3 +1,4 @@ +import pytest import time import re import json @@ -6,6 +7,7 @@ from swsscommon import swsscommon +@pytest.mark.usefixtures('dvs_lag_manager') class TestPortchannel(object): def test_Portchannel(self, dvs, testlog): @@ -89,6 +91,28 @@ def test_Portchannel(self, dvs, testlog): lagms = lagmtbl.getKeys() assert len(lagms) == 0 + @pytest.mark.parametrize("fast_rate", [False, True]) + def test_Portchannel_fast_rate(self, dvs, testlog, fast_rate): + po_id = "0003" + po_member = "Ethernet16" + + # Create PortChannel + self.dvs_lag.create_port_channel(po_id, fast_rate=fast_rate) + self.dvs_lag.get_and_verify_port_channel(1) + + # Add member to PortChannel + self.dvs_lag.create_port_channel_member(po_id, po_member) + self.dvs_lag.get_and_verify_port_channel_members(1) + + # test fast rate configuration + self.dvs_lag.get_and_verify_port_channel_fast_rate(po_id, fast_rate) + + # remove PortChannel + self.dvs_lag.create_port_channel_member(po_id, po_member) + self.dvs_lag.remove_port_channel(po_id) + self.dvs_lag.get_and_verify_port_channel(0) + + def test_Portchannel_lacpkey(self, dvs, testlog): portchannelNamesAuto = [("PortChannel001", "Ethernet0", 1001), ("PortChannel002", "Ethernet4", 1002), @@ -108,7 +132,7 @@ def test_Portchannel_lacpkey(self, dvs, testlog): for portchannel in portchannelNamesAuto: tbl.set(portchannel[0], fvs) - + fvs_no_lacp_key = swsscommon.FieldValuePairs( [("admin_status", "up"), ("mtu", "9100"), ("oper_status", "up")]) tbl.set(portchannelNames[0][0], fvs_no_lacp_key)