Skip to content

Commit 3b43772

Browse files
author
Kannan Selvaraj
committed
Signed-off-by: Kannan Selvaraj <in62012518@celestica.com>
Why ? Static lag support changes in SWSS module sonic-net/SONiC#1039 Patch explanation 1. static lag supported with option roundrobin. 2. tlm_teamd -> teamdctl changes to handle json dump for static lag. 3. test cases -> updated UT:- Test cases 1 Create static port channel with static flag pass pass 2 verify static has option flag true or false pass pass 3 Add static member see the portchannel is up pass pass 4 verify teamd is created with round-robin option by default pass pass 5 Remove last portchannel member check port channel down pass pass 6 Remove portchannel member check port channel still up pass pass 7 verify teamdctl config dump pass pass 8 verify teamdctl state dump pass pass 9 shutdown the portchannel check the kernel state pass pass 10 no shutdown the portchannel check the kernel state pass pass 11 "Check the show output matches the review comment root@sonic:~# show inter port Flags: A - active, I - inactive, Up - up, Dw - Down, N/A - not available, S - selected, D - deselected, * - not synced No. Team Dev Protocol Ports ----- ------------- ----------- ----------------------------------------- 01 PortChannel01 LACP(A)(Up) Ethernet16(S) 02 PortChannel02 NONE(A)(Up) Ethernet48(S) Ethernet64(S) Ethernet32(S) root@sonic:~# 12 teamnl is set to roundrobin pass pass 13 save and reload and verify portchannel is up pass pass 14 "docker restart teamd teamd stopped swss stopped syncd stopped swss started syncd started teamd started" pass pass 15 warm-reboot fails even without any port channel config fail 16 verify teamd settles doesnt hog cpu with 100% cpu usage pass 17 "trying with static port channel config on non supported branches port channel will be configured as LACP." pass Not Supported Options 1. Min links and 2. fall back are not supported
1 parent 91bacca commit 3b43772

File tree

6 files changed

+188
-9
lines changed

6 files changed

+188
-9
lines changed

cfgmgr/teammgr.cpp

+22-7
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ void TeamMgr::doLagTask(Consumer &consumer)
253253
int min_links = 0;
254254
bool fallback = false;
255255
bool fast_rate = false;
256+
bool static_lag = false;
256257
string admin_status = DEFAULT_ADMIN_STATUS_STR;
257258
string mtu = DEFAULT_MTU_STR;
258259
string learn_mode;
@@ -301,11 +302,16 @@ void TeamMgr::doLagTask(Consumer &consumer)
301302
SWSS_LOG_INFO("Get fast_rate `%s`",
302303
fast_rate ? "true" : "false");
303304
}
305+
else if (fvField(i) == "static")
306+
{
307+
static_lag = true;
308+
SWSS_LOG_INFO ("static %d", static_lag);
309+
}
304310
}
305311

306312
if (m_lagList.find(alias) == m_lagList.end())
307313
{
308-
if (addLag(alias, min_links, fallback, fast_rate) == task_need_retry)
314+
if (addLag(alias, min_links, fallback, fast_rate, static_lag) == task_need_retry)
309315
{
310316
// If LAG creation fails, we need to clean up any potentially orphaned teamd processes
311317
removeLag(alias);
@@ -562,7 +568,7 @@ bool TeamMgr::setLagLearnMode(const string &alias, const string &learn_mode)
562568
return true;
563569
}
564570

565-
task_process_status TeamMgr::addLag(const string &alias, int min_links, bool fallback, bool fast_rate)
571+
task_process_status TeamMgr::addLag(const string &alias, int min_links, bool fallback, bool fast_rate, bool static_lag)
566572
{
567573
SWSS_LOG_ENTER();
568574

@@ -603,11 +609,20 @@ task_process_status TeamMgr::addLag(const string &alias, int min_links, bool fal
603609
}
604610
}
605611

606-
conf << "'{\"device\":\"" << alias << "\","
607-
<< "\"hwaddr\":\"" << mac_boot.to_string() << "\","
608-
<< "\"runner\":{"
609-
<< "\"active\":true,"
610-
<< "\"name\":\"lacp\"";
612+
if (static_lag) {
613+
conf << "'{\"device\":\"" << alias << "\","
614+
<< "\"hwaddr\":\"" << mac_boot.to_string() << "\","
615+
<< "\"runner\":{"
616+
<< "\"name\":\"roundrobin\"";
617+
618+
} else {
619+
620+
conf << "'{\"device\":\"" << alias << "\","
621+
<< "\"hwaddr\":\"" << mac_boot.to_string() << "\","
622+
<< "\"runner\":{"
623+
<< "\"active\":true,"
624+
<< "\"name\":\"lacp\"";
625+
}
611626

612627
if (min_links != 0)
613628
{

cfgmgr/teammgr.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class TeamMgr : public Orch
4141
void doLagMemberTask(Consumer &consumer);
4242
void doPortUpdateTask(Consumer &consumer);
4343

44-
task_process_status addLag(const std::string &alias, int min_links, bool fall_back, bool fast_rate);
44+
task_process_status addLag(const std::string &alias, int min_links, bool fall_back, bool fast_rate, bool static_lag);
4545
bool removeLag(const std::string &alias);
4646
task_process_status addLagMember(const std::string &lag, const std::string &member);
4747
bool removeLagMember(const std::string &lag, const std::string &member);

tests/mock_tests/teammgrd/teammgr_ut.cpp

+19-1
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,22 @@ namespace teammgr_ut
7575
}
7676
ASSERT_EQ(kill_cmd_called, 1);
7777
}
78-
}
78+
79+
TEST_F(TeamMgrTest, testProcessKilledAfterAddStaticFailure)
80+
{
81+
swss::TeamMgr teammgr(m_config_db.get(), m_app_db.get(), m_state_db.get(), cfg_lag_tables);
82+
swss::Table cfg_lag_table = swss::Table(m_config_db.get(), CFG_LAG_TABLE_NAME);
83+
cfg_lag_table.set("PortChannel1", { { "admin_status", "up" },
84+
{ "mtu", "9100" },
85+
{ "static", "true" } });
86+
teammgr.addExistingData(&cfg_lag_table);
87+
teammgr.doTask();
88+
int kill_cmd_called = 0;
89+
for (auto cmd : mockCallArgs){
90+
if (cmd.find("kill -TERM 1234") != std::string::npos){
91+
kill_cmd_called++;
92+
}
93+
}
94+
ASSERT_EQ(kill_cmd_called, 1);
95+
}
96+
}

tests/test_portchannel.py

+69
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,75 @@ def test_portchannel_member_netdev_oper_status(self, dvs, testlog):
464464
# wait for port-channel deletion
465465
time.sleep(1)
466466

467+
468+
def test_static_portchannel_member_netdev_oper_status(self, dvs, testlog):
469+
config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)
470+
state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0)
471+
app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)
472+
473+
# create port-channel
474+
tbl = swsscommon.Table(config_db, "PORTCHANNEL")
475+
fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up"),("static": "true")])
476+
tbl.set("PortChannel111", fvs)
477+
478+
# set port-channel oper status
479+
tbl = swsscommon.ProducerStateTable(app_db, "LAG_TABLE")
480+
fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up")])
481+
tbl.set("PortChannel111", fvs)
482+
483+
# add members to port-channel
484+
tbl = swsscommon.Table(config_db, "PORTCHANNEL_MEMBER")
485+
fvs = swsscommon.FieldValuePairs([("NULL", "NULL")])
486+
tbl.set("PortChannel111|Ethernet0", fvs)
487+
tbl.set("PortChannel111|Ethernet4", fvs)
488+
489+
# wait for port-channel netdev creation
490+
time.sleep(1)
491+
492+
# set netdev oper status
493+
(exitcode, _) = dvs.runcmd("ip link set up dev Ethernet0")
494+
assert exitcode == 0, "ip link set failed"
495+
496+
(exitcode, _) = dvs.runcmd("ip link set up dev Ethernet4")
497+
assert exitcode == 0, "ip link set failed"
498+
499+
(exitcode, _) = dvs.runcmd("ip link set dev PortChannel111 carrier on")
500+
assert exitcode == 0, "ip link set failed"
501+
502+
# verify port-channel members netdev oper status
503+
tbl = swsscommon.Table(state_db, "PORT_TABLE")
504+
status, fvs = tbl.get("Ethernet0")
505+
assert status is True
506+
fvs = dict(fvs)
507+
assert fvs['netdev_oper_status'] == 'up'
508+
509+
status, fvs = tbl.get("Ethernet4")
510+
assert status is True
511+
fvs = dict(fvs)
512+
assert fvs['netdev_oper_status'] == 'up'
513+
514+
# wait for port-channel netdev creation
515+
time.sleep(1)
516+
517+
(exit_code, output) = dvs.runcmd("teamdctl " + "PortChannel111" + " state dump")
518+
port_state_dump = json.loads(output)
519+
runner_name = port_state_dump["setup"]["runner_name"]
520+
assert runner_name == "roundrobin"
521+
522+
523+
# remove port-channel members
524+
tbl = swsscommon.Table(config_db, "PORTCHANNEL_MEMBER")
525+
tbl._del("PortChannel111|Ethernet0")
526+
tbl._del("PortChannel111|Ethernet4")
527+
528+
# remove port-channel
529+
tbl = swsscommon.Table(config_db, "PORTCHANNEL")
530+
tbl._del("PortChannel111")
531+
532+
# wait for port-channel deletion
533+
time.sleep(1)
534+
535+
467536
# Add Dummy always-pass test at end as workaroud
468537
# for issue when Flaky fail on final test it invokes module tear-down before retrying
469538
def test_nonflaky_dummy():

tlm_teamd/values_store.cpp

+63
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,47 @@ std::string ValuesStore::get_value(json_t * root, const std::string & path, Valu
144144
throw std::runtime_error("Reach the end of the ValuesStore::get_value. Path=" + path);
145145
}
146146

147+
///
148+
/// Extract static lag values for LAG with name lag_name, from the parsed json tree with root, to the temporary storage
149+
/// @param lag_name a name of the LAG
150+
/// @param root a pointer to the parsed json tree
151+
/// @param storage a reference to the temporary storage
152+
///
153+
154+
void ValuesStore::extract_values_static(const std::string & lag_name, json_t * root, HashOfRecords & storage)
155+
{
156+
157+
const std::string key = "LAG_TABLE|" + lag_name;
158+
Records lag_values;
159+
160+
for (const auto & p: m_lag_static_paths)
161+
{
162+
const auto & path = p.first;
163+
const auto & type = p.second;
164+
const auto & value = get_value(root, path, type);
165+
lag_values.emplace(path, value);
166+
}
167+
storage.emplace(key, lag_values);
168+
169+
const auto & ports = get_ports(root);
170+
for (const auto & port: ports)
171+
{
172+
const std::string key = "LAG_MEMBER_TABLE|" + lag_name + "|" + port;
173+
Records member_values;
174+
for (const auto & p: m_member_static_paths)
175+
{
176+
const auto & path = p.first;
177+
const auto & type = p.second;
178+
const std::string full_path = "ports." + port + "." + path;
179+
const auto & value = get_value(root, full_path, type);
180+
member_values.emplace(path, value);
181+
}
182+
storage.emplace(key, member_values);
183+
}
184+
185+
return;
186+
}
187+
147188
///
148189
/// Extract values for LAG with name lag_name, from the parsed json tree with root, to the temporary storage
149190
/// @param lag_name a name of the LAG
@@ -155,6 +196,28 @@ void ValuesStore::extract_values(const std::string & lag_name, json_t * root, Ha
155196

156197
const std::string key = "LAG_TABLE|" + lag_name;
157198
Records lag_values;
199+
200+
201+
bool is_static = false;
202+
203+
for (const auto & p: m_lag_static_paths)
204+
{
205+
const auto & path = p.first;
206+
const auto & type = p.second;
207+
if (path == "setup.runner_name") {
208+
const auto & value = get_value(root, path, type);
209+
if(value == "loadbalance" ||
210+
value == "roundrobin")
211+
is_static = true;
212+
break;
213+
}
214+
}
215+
216+
if (is_static) {
217+
extract_values_static(lag_name, root, storage);
218+
return;
219+
}
220+
158221
for (const auto & p: m_lag_paths)
159222
{
160223
const auto & path = p.first;

tlm_teamd/values_store.h

+14
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class ValuesStore
4141
std::vector<std::string> update_storage(const HashOfRecords & storage);
4242
void update_db(const HashOfRecords & storage, const std::vector<std::string> & keys_to_refresh);
4343
void extract_values(const std::string & lag_name, json_t * root, HashOfRecords & storage);
44+
void extract_values_static(const std::string & lag_name, json_t * root, HashOfRecords & storage);
4445

4546
HashOfRecords m_storage; // our main storage
4647
const swss::DBConnector * m_db;
@@ -70,4 +71,17 @@ class ValuesStore
7071
{ "runner.selected", ValuesStore::json_type::boolean },
7172
{ "runner.state", ValuesStore::json_type::string },
7273
};
74+
const std::vector<std::pair<std::string, ValuesStore::json_type>> m_lag_static_paths = {
75+
{ "setup.runner_name", ValuesStore::json_type::string },
76+
{ "setup.kernel_team_mode_name", ValuesStore::json_type::string },
77+
{ "setup.pid", ValuesStore::json_type::integer },
78+
{ "team_device.ifinfo.dev_addr", ValuesStore::json_type::string },
79+
{ "team_device.ifinfo.ifindex", ValuesStore::json_type::integer },
80+
};
81+
const std::vector<std::pair<std::string, ValuesStore::json_type>> m_member_static_paths = {
82+
{ "ifinfo.dev_addr", ValuesStore::json_type::string },
83+
{ "ifinfo.ifindex", ValuesStore::json_type::integer },
84+
{ "link.up", ValuesStore::json_type::boolean },
85+
{ "link_watches.list.link_watch_0.up", ValuesStore::json_type::boolean },
86+
};
7387
};

0 commit comments

Comments
 (0)