Skip to content

Commit 36a90c3

Browse files
authored
[portorch] Add capability to add unreliable LOS setting to a PORT via config (#3472)
* [portorch] Add capability to add unrealible LOS setting to a PORT via config What I did This pull request introduces a new capability in the SONiC system: support for handling ports with "unreliable loss of signal" (unreliable LOS). The aim is to improve how the system manages situations where ports intermittently fail to detect signals reliably. Why I did it The implementation includes new helper methods. Functions like getUnreliableLosStr and parsePortUnreliableLos have been introduced to handle the conversion and parsing of the unreliable LOS field during configuration processing. The existing parsePortConfig method has been updated to integrate these changes seamlessly, ensuring the system correctly interprets and applies the new settings. A new schema entry, PORT_UNRELIABLE_LOS, has been defined to standardize how this configuration is represented and handled across the system
1 parent 47e9b2f commit 36a90c3

File tree

9 files changed

+148
-17
lines changed

9 files changed

+148
-17
lines changed

orchagent/port.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class Port
172172
uint32_t m_speed = 0; // Mbps
173173
port_learn_mode_t m_learn_mode = SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW;
174174
bool m_autoneg = false;
175+
bool m_unreliable_los = false;
175176
bool m_link_training = false;
176177
bool m_admin_state_up = false;
177178
bool m_init = false;

orchagent/port/portcnt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ class PortConfig final
185185
bool is_set = false;
186186
} regn_bfm1n; // Port serdes regn_bfm1n
187187

188+
struct {
189+
bool value;
190+
bool is_set = false;
191+
} unreliable_los; // Port unreliable_los
192+
188193
} serdes; // Port serdes
189194

190195
struct {

orchagent/port/porthlpr.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ std::string PortHelper::getAutonegStr(const PortConfig &port) const
213213
return this->getFieldValueStr(port, PORT_AUTONEG);
214214
}
215215

216+
std::string PortHelper::getUnreliableLosStr(const PortConfig &port) const
217+
{
218+
return this->getFieldValueStr(port, PORT_UNRELIABLE_LOS);
219+
}
220+
216221
std::string PortHelper::getPortInterfaceTypeStr(const PortConfig &port) const
217222
{
218223
return this->getFieldValueStr(port, PORT_INTERFACE_TYPE);
@@ -389,6 +394,31 @@ bool PortHelper::parsePortAutoneg(PortConfig &port, const std::string &field, co
389394
return true;
390395
}
391396

397+
398+
bool PortHelper::parsePortUnreliableLos(PortConfig &port, const std::string &field, const std::string &value) const
399+
{
400+
SWSS_LOG_ENTER();
401+
402+
if (value.empty())
403+
{
404+
SWSS_LOG_ERROR("Failed to parse field(%s): empty value is prohibited", field.c_str());
405+
return false;
406+
}
407+
408+
const auto &cit = portModeMap.find(value);
409+
if (cit == portModeMap.cend())
410+
{
411+
SWSS_LOG_ERROR("Failed to parse field(%s): invalid value(%s)", field.c_str(), value.c_str());
412+
return false;
413+
}
414+
415+
port.serdes.unreliable_los.value = cit->second;
416+
port.serdes.unreliable_los.is_set = true;
417+
418+
return true;
419+
}
420+
421+
392422
bool PortHelper::parsePortAdvSpeeds(PortConfig &port, const std::string &field, const std::string &value) const
393423
{
394424
SWSS_LOG_ENTER();
@@ -1026,6 +1056,13 @@ bool PortHelper::parsePortConfig(PortConfig &port) const
10261056
return false;
10271057
}
10281058
}
1059+
else if (field == PORT_UNRELIABLE_LOS)
1060+
{
1061+
if (!this->parsePortUnreliableLos(port, field, value))
1062+
{
1063+
return false;
1064+
}
1065+
}
10291066
else if (field == PORT_PREEMPHASIS)
10301067
{
10311068
if (!this->parsePortSerdes(port.serdes.preemphasis, field, value))

orchagent/port/porthlpr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class PortHelper final
1919
bool fecIsOverrideRequired(const std::string &str) const;
2020

2121
std::string getAutonegStr(const PortConfig &port) const;
22+
std::string getUnreliableLosStr(const PortConfig &port) const;
2223
std::string getPortInterfaceTypeStr(const PortConfig &port) const;
2324
std::string getAdvInterfaceTypesStr(const PortConfig &port) const;
2425
std::string getFecStr(const PortConfig &port) const;
@@ -47,6 +48,7 @@ class PortHelper final
4748
bool parsePortLanes(PortConfig &port, const std::string &field, const std::string &value) const;
4849
bool parsePortSpeed(PortConfig &port, const std::string &field, const std::string &value) const;
4950
bool parsePortAutoneg(PortConfig &port, const std::string &field, const std::string &value) const;
51+
bool parsePortUnreliableLos(PortConfig &port, const std::string &field, const std::string &value) const;
5052
bool parsePortAdvSpeeds(PortConfig &port, const std::string &field, const std::string &value) const;
5153
bool parsePortInterfaceType(PortConfig &port, const std::string &field, const std::string &value) const;
5254
bool parsePortAdvInterfaceTypes(PortConfig &port, const std::string &field, const std::string &value) const;

orchagent/port/portschema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,4 @@
102102
#define PORT_REUSE_THRESHOLD "reuse_threshold"
103103
#define PORT_FLAP_PENALTY "flap_penalty"
104104
#define PORT_MODE "mode"
105+
#define PORT_UNRELIABLE_LOS "unreliable_los"

orchagent/portsorch.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3253,6 +3253,21 @@ bool PortsOrch::getPortAdvSpeeds(const Port& port, bool remote, string& adv_spee
32533253
return rc;
32543254
}
32553255

3256+
task_process_status PortsOrch::setPortUnreliableLOS(Port &port, bool enabled)
3257+
{
3258+
SWSS_LOG_ENTER();
3259+
sai_attribute_t attr;
3260+
sai_status_t status;
3261+
attr.id = SAI_PORT_ATTR_UNRELIABLE_LOS;
3262+
attr.value.booldata = enabled;
3263+
status = sai_port_api->set_port_attribute(port.m_port_id, &attr);
3264+
if (status != SAI_STATUS_SUCCESS)
3265+
{
3266+
return handleSaiSetStatus(SAI_API_PORT, status);
3267+
}
3268+
return task_success;
3269+
}
3270+
32563271
task_process_status PortsOrch::setPortAdvSpeeds(Port &port, std::set<sai_uint32_t> &speed_list)
32573272
{
32583273
SWSS_LOG_ENTER();
@@ -4614,6 +4629,27 @@ void PortsOrch::doPortTask(Consumer &consumer)
46144629
}
46154630
}
46164631

4632+
if (pCfg.serdes.unreliable_los.is_set)
4633+
{
4634+
auto status = setPortUnreliableLOS(p, pCfg.serdes.unreliable_los.value);
4635+
if (status != task_success)
4636+
{
4637+
SWSS_LOG_ERROR(
4638+
"Failed to set port %s unreliable from %d to %d",
4639+
p.m_alias.c_str(), p.m_unreliable_los, pCfg.serdes.unreliable_los.value
4640+
);
4641+
p.m_unreliable_los = false;
4642+
} else {
4643+
4644+
p.m_unreliable_los = pCfg.serdes.unreliable_los.value;
4645+
SWSS_LOG_INFO(
4646+
"Set port %s unreliable los to %s",
4647+
p.m_alias.c_str(), m_portHlpr.getUnreliableLosStr(pCfg).c_str()
4648+
);
4649+
}
4650+
m_portStateTable.hset(p.m_alias, "phy_ctrl_unreliable_los", p.m_unreliable_los ? "true":"false");
4651+
}
4652+
46174653
if (pCfg.adv_interface_types.is_set)
46184654
{
46194655
if (!p.m_adv_intf_cfg || p.m_adv_interface_types != pCfg.adv_interface_types.value)

orchagent/portsorch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ class PortsOrch : public Orch, public Subject
483483

484484
bool isAutoNegEnabled(sai_object_id_t id);
485485
task_process_status setPortAutoNeg(Port &port, bool autoneg);
486+
task_process_status setPortUnreliableLOS(Port &port, bool enabled);
486487
task_process_status setPortInterfaceType(Port &port, sai_port_interface_type_t interface_type);
487488
task_process_status setPortAdvInterfaceTypes(Port &port, std::set<sai_port_interface_type_t> &interface_types);
488489
task_process_status setPortLinkTraining(const Port& port, bool state);

tests/mock_tests/portsorch_ut.cpp

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,7 @@ namespace portsorch_test
883883
{ "lanes", lanes.str() },
884884
{ "speed", "100000" },
885885
{ "autoneg", "off" },
886+
{ "unreliable_los", "off" },
886887
{ "adv_speeds", "all" },
887888
{ "interface_type", "none" },
888889
{ "adv_interface_types", "all" },
@@ -956,6 +957,7 @@ namespace portsorch_test
956957
SET_COMMAND, {
957958
{ "speed", "100000" },
958959
{ "autoneg", "on" },
960+
{ "unreliable_los", "on" },
959961
{ "adv_speeds", "1000,10000,100000" },
960962
{ "interface_type", "CR" },
961963
{ "adv_interface_types", "CR,CR2,CR4,CR8" },
@@ -985,6 +987,9 @@ namespace portsorch_test
985987
// Verify auto-negotiation
986988
ASSERT_TRUE(p.m_autoneg);
987989

990+
// Verify unreliablelos
991+
ASSERT_TRUE(p.m_unreliable_los);
992+
988993
// Verify advertised speed
989994
std::set<std::uint32_t> adv_speeds = { 1000, 10000, 100000 };
990995
ASSERT_EQ(p.m_adv_speeds, adv_speeds);
@@ -1058,23 +1063,24 @@ namespace portsorch_test
10581063
std::deque<KeyOpFieldsValuesTuple> kfvList = {{
10591064
"Ethernet0",
10601065
SET_COMMAND, {
1061-
{ "preemphasis", "0xcad0,0xc6e0,0xc6e0,0xd2b0" },
1062-
{ "idriver", "0x5,0x3,0x4,0x1" },
1063-
{ "ipredriver", "0x1,0x4,0x3,0x5" },
1064-
{ "pre1", "0xfff0,0xfff2,0xfff1,0xfff3" },
1065-
{ "pre2", "0xfff0,0xfff2,0xfff1,0xfff3" },
1066-
{ "pre3", "0xfff0,0xfff2,0xfff1,0xfff3" },
1067-
{ "main", "0x90,0x92,0x91,0x93" },
1068-
{ "post1", "0x10,0x12,0x11,0x13" },
1069-
{ "post2", "0x10,0x12,0x11,0x13" },
1070-
{ "post3", "0x10,0x12,0x11,0x13" },
1071-
{ "attn", "0x80,0x82,0x81,0x83" },
1072-
{ "ob_m2lp", "0x4,0x6,0x5,0x7" },
1073-
{ "ob_alev_out", "0xf,0x11,0x10,0x12" },
1074-
{ "obplev", "0x69,0x6b,0x6a,0x6c" },
1075-
{ "obnlev", "0x5f,0x61,0x60,0x62" },
1076-
{ "regn_bfm1p", "0x1e,0x20,0x1f,0x21" },
1077-
{ "regn_bfm1n", "0xaa,0xac,0xab,0xad" }
1066+
{ "preemphasis", "0xcad0,0xc6e0,0xc6e0,0xd2b0" },
1067+
{ "idriver", "0x5,0x3,0x4,0x1" },
1068+
{ "ipredriver", "0x1,0x4,0x3,0x5" },
1069+
{ "pre1", "0xfff0,0xfff2,0xfff1,0xfff3" },
1070+
{ "pre2", "0xfff0,0xfff2,0xfff1,0xfff3" },
1071+
{ "pre3", "0xfff0,0xfff2,0xfff1,0xfff3" },
1072+
{ "main", "0x90,0x92,0x91,0x93" },
1073+
{ "post1", "0x10,0x12,0x11,0x13" },
1074+
{ "post2", "0x10,0x12,0x11,0x13" },
1075+
{ "post3", "0x10,0x12,0x11,0x13" },
1076+
{ "attn", "0x80,0x82,0x81,0x83" },
1077+
{ "unreliable_los","off" },
1078+
{ "ob_m2lp", "0x4,0x6,0x5,0x7" },
1079+
{ "ob_alev_out", "0xf,0x11,0x10,0x12" },
1080+
{ "obplev", "0x69,0x6b,0x6a,0x6c" },
1081+
{ "obnlev", "0x5f,0x61,0x60,0x62" },
1082+
{ "regn_bfm1p", "0x1e,0x20,0x1f,0x21" },
1083+
{ "regn_bfm1n", "0xaa,0xac,0xab,0xad" }
10781084
}
10791085
}};
10801086

@@ -1157,6 +1163,9 @@ namespace portsorch_test
11571163
std::vector<std::uint32_t> regn_bfm1n = { 0xaa, 0xac, 0xab, 0xad };
11581164
ASSERT_EQ(p.m_preemphasis.at(SAI_PORT_SERDES_ATTR_TX_NMOS_VLTG_REG), regn_bfm1n);
11591165

1166+
// Verify unreliablelos
1167+
ASSERT_EQ(p.m_unreliable_los, false);
1168+
11601169
// Dump pending tasks
11611170
std::vector<std::string> taskList;
11621171
gPortsOrch->dumpPendingTasks(taskList);

tests/test_port_unlos.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from swsscommon import swsscommon
2+
3+
4+
class TestPortUnreliableLos(object):
5+
def test_PortUnreliableLosForce(self, dvs, testlog):
6+
7+
db = swsscommon.DBConnector(0, dvs.redis_sock, 0)
8+
adb = dvs.get_asic_db()
9+
10+
tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE")
11+
fvs = swsscommon.FieldValuePairs([("unreliable_los","off")])
12+
tbl.set("Ethernet0", fvs)
13+
14+
tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE")
15+
fvs = swsscommon.FieldValuePairs([("unreliable_los","on")])
16+
tbl.set("Ethernet4", fvs)
17+
18+
tbl = swsscommon.ProducerStateTable(db, "PORT_TABLE")
19+
fvs = swsscommon.FieldValuePairs([("unreliable_los","err")])
20+
tbl.set("Ethernet8", fvs)
21+
22+
# validate if unreliable false is pushed to asic db when set first time
23+
port_oid = adb.port_name_map["Ethernet0"]
24+
expected_fields = {'NULL': 'NULL', 'SAI_PORT_ATTR_ADMIN_STATE': 'false', 'SAI_PORT_ATTR_AUTO_NEG_MODE': 'true', 'SAI_PORT_ATTR_MTU': '9122', 'SAI_PORT_ATTR_SPEED': '100000', 'SAI_PORT_ATTR_UNRELIABLE_LOS': 'false'}
25+
adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields)
26+
27+
# validate if unreliable true is pushed to asic db when set first time
28+
port_oid = adb.port_name_map["Ethernet4"]
29+
expected_fields = {'NULL': 'NULL', 'SAI_PORT_ATTR_ADMIN_STATE': 'false', 'SAI_PORT_ATTR_AUTO_NEG_MODE': 'true', 'SAI_PORT_ATTR_MTU': '9122', 'SAI_PORT_ATTR_SPEED': '100000', 'SAI_PORT_ATTR_UNRELIABLE_LOS': 'true'}
30+
adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields)
31+
32+
port_oid = adb.port_name_map["Ethernet8"]
33+
expected_fields = {'NULL': 'NULL', 'SAI_PORT_ATTR_ADMIN_STATE': 'false', 'SAI_PORT_ATTR_AUTO_NEG_MODE': 'true', 'SAI_PORT_ATTR_MTU': '9122', 'SAI_PORT_ATTR_SPEED': '100000'}
34+
adb.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields)
35+
36+
# Add Dummy always-pass test at end as workaroud
37+
# for issue when Flaky fail on final test it invokes module tear-down before retrying
38+
def test_nonflaky_dummy():
39+
pass

0 commit comments

Comments
 (0)