Skip to content

Commit 44931cf

Browse files
committed
[Fast-linkup] Added orchagents support
1 parent 3ccfa62 commit 44931cf

File tree

10 files changed

+418
-0
lines changed

10 files changed

+418
-0
lines changed

orchagent/orchdaemon.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,13 @@ bool OrchDaemon::init()
176176
TableConnector conf_asic_sensors(m_configDb, CFG_ASIC_SENSORS_TABLE_NAME);
177177
TableConnector conf_switch_hash(m_configDb, CFG_SWITCH_HASH_TABLE_NAME);
178178
TableConnector conf_switch_trim(m_configDb, CFG_SWITCH_TRIMMING_TABLE_NAME);
179+
TableConnector conf_switch_fast_linkup(m_configDb, CFG_SWITCH_FAST_LINKUP_TABLE_NAME);
179180
TableConnector conf_suppress_asic_sdk_health_categories(m_configDb, CFG_SUPPRESS_ASIC_SDK_HEALTH_EVENT_NAME);
180181

181182
vector<TableConnector> switch_tables = {
182183
conf_switch_hash,
183184
conf_switch_trim,
185+
conf_switch_fast_linkup,
184186
conf_asic_sensors,
185187
conf_suppress_asic_sdk_health_categories,
186188
app_switch_table

orchagent/port/portcnt.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ class PortConfig final
9898
bool is_set = false;
9999
} link_training; // Port link training
100100

101+
struct {
102+
bool value;
103+
bool is_set = false;
104+
} fast_linkup; // Port fast link-up enable
105+
101106
struct {
102107

103108
struct {

orchagent/port/porthlpr.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,32 @@ bool PortHelper::parsePortLinkTraining(PortConfig &port, const std::string &fiel
697697
return true;
698698
}
699699

700+
bool PortHelper::parsePortFastLinkup(PortConfig &port, const std::string &field, const std::string &value) const
701+
{
702+
SWSS_LOG_ENTER();
703+
704+
if (value.empty())
705+
{
706+
SWSS_LOG_ERROR("Failed to parse field(%s): empty value is not allowed", field.c_str());
707+
return false;
708+
}
709+
if (value == "true")
710+
{
711+
port.fast_linkup.value = true;
712+
}
713+
else if (value == "false")
714+
{
715+
port.fast_linkup.value = false;
716+
}
717+
else
718+
{
719+
SWSS_LOG_ERROR("Failed to parse field(%s): invalid value(%s)", field.c_str(), value.c_str());
720+
return false;
721+
}
722+
port.fast_linkup.is_set = true;
723+
return true;
724+
}
725+
700726
template<typename T>
701727
bool PortHelper::parsePortSerdes(T &serdes, const std::string &field, const std::string &value) const
702728
{
@@ -1056,6 +1082,13 @@ bool PortHelper::parsePortConfig(PortConfig &port) const
10561082
return false;
10571083
}
10581084
}
1085+
else if (field == PORT_FAST_LINKUP)
1086+
{
1087+
if (!this->parsePortFastLinkup(port, field, value))
1088+
{
1089+
return false;
1090+
}
1091+
}
10591092
else if (field == PORT_UNRELIABLE_LOS)
10601093
{
10611094
if (!this->parsePortUnreliableLos(port, field, value))

orchagent/port/porthlpr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,5 @@ class PortHelper final
6464
bool parsePortSubport(PortConfig &port, const std::string &field, const std::string &value) const;
6565
bool parsePortPtIntfId(PortConfig &port, const std::string &field, const std::string &value) const;
6666
bool parsePortPtTimestampTemplate(PortConfig &port, const std::string &field, const std::string &value) const;
67+
bool parsePortFastLinkup(PortConfig &port, const std::string &field, const std::string &value) const;
6768
};

orchagent/port/portschema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,4 @@
103103
#define PORT_FLAP_PENALTY "flap_penalty"
104104
#define PORT_MODE "mode"
105105
#define PORT_UNRELIABLE_LOS "unreliable_los"
106+
#define PORT_FAST_LINKUP "fast_linkup"

orchagent/portsorch.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,12 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_wi
951951
m_defaultVlan = attrs[1].value.oid;
952952
}
953953

954+
//Fast link-up per-port attribute support
955+
if (gSwitchOrch->querySwitchCapability(SAI_OBJECT_TYPE_PORT, SAI_PORT_ATTR_FAST_LINKUP_ENABLED))
956+
{
957+
m_fastLinkupPortAttrSupported = true;
958+
}
959+
954960
if (gMySwitchType != "dpu")
955961
{
956962
// System Ports not supported on dpu
@@ -3424,6 +3430,28 @@ bool PortsOrch::getPortAdvSpeeds(const Port& port, bool remote, string& adv_spee
34243430
return rc;
34253431
}
34263432

3433+
task_process_status PortsOrch::setPortFastLinkupEnabled(Port &port, bool enable)
3434+
{
3435+
SWSS_LOG_ENTER();
3436+
3437+
if (!m_fastLinkupPortAttrSupported)
3438+
{
3439+
SWSS_LOG_NOTICE("Fast link-up is not supported on this platform");
3440+
return task_success;
3441+
}
3442+
sai_attribute_t attr;
3443+
attr.id = SAI_PORT_ATTR_FAST_LINKUP_ENABLED;
3444+
attr.value.booldata = enable;
3445+
sai_status_t status = sai_port_api->set_port_attribute(port.m_port_id, &attr);
3446+
if (status != SAI_STATUS_SUCCESS)
3447+
{
3448+
SWSS_LOG_ERROR("Failed to set fast_linkup %d on port %s", enable, port.m_alias.c_str());
3449+
return handleSaiSetStatus(SAI_API_PORT, status);
3450+
}
3451+
SWSS_LOG_INFO("Set port %s fast_linkup %s", port.m_alias.c_str(), enable ? "true" : "false");
3452+
return task_success;
3453+
}
3454+
34273455
task_process_status PortsOrch::setPortUnreliableLOS(Port &port, bool enabled)
34283456
{
34293457
SWSS_LOG_ENTER();
@@ -4598,6 +4626,24 @@ void PortsOrch::doPortTask(Consumer &consumer)
45984626
}
45994627
}
46004628

4629+
// Handle fast_linkup boolean
4630+
if (pCfg.fast_linkup.is_set)
4631+
{
4632+
auto status = setPortFastLinkupEnabled(p, pCfg.fast_linkup.value);
4633+
if (status != task_success)
4634+
{
4635+
if (status == task_need_retry)
4636+
{
4637+
it++;
4638+
}
4639+
else
4640+
{
4641+
it = taskMap.erase(it);
4642+
}
4643+
continue;
4644+
}
4645+
}
4646+
46014647
if (pCfg.link_event_damping_algorithm.is_set)
46024648
{
46034649
if (p.m_link_event_damping_algorithm != pCfg.link_event_damping_algorithm.value)

orchagent/portsorch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ class PortsOrch : public Orch, public Subject
257257

258258
bool setPortPtIntfId(const Port& port, sai_uint16_t intf_id);
259259
bool setPortPtTimestampTemplate(const Port& port, sai_port_path_tracing_timestamp_type_t ts_type);
260+
task_process_status setPortFastLinkupEnabled(Port &port, bool enable);
260261

261262
private:
262263
unique_ptr<CounterNameMapUpdater> m_counterNameMapUpdater;
@@ -365,6 +366,7 @@ class PortsOrch : public Orch, public Subject
365366
bool saiHwTxSignalSupported = false;
366367
bool saiTxReadyNotifySupported = false;
367368
bool m_supportsHostIfTxQueue = false;
369+
bool m_fastLinkupPortAttrSupported = false;
368370

369371
swss::SelectableTimer *m_port_state_poller = nullptr;
370372

orchagent/switchorch.cpp

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ SwitchOrch::SwitchOrch(DBConnector *db, vector<TableConnector>& connectors, Tabl
166166
querySwitchPortEgressSampleCapability();
167167
querySwitchHashDefaults();
168168
setSwitchIcmpOffloadCapability();
169+
setFastLinkupCapability();
169170

170171
auto executorT = new ExecutableTimer(m_sensorsPollerTimer, this, "ASIC_SENSORS_POLL_TIMER");
171172
Orch::addExecutor(executorT);
@@ -1475,6 +1476,10 @@ void SwitchOrch::doTask(Consumer &consumer)
14751476
{
14761477
doCfgSwitchTrimmingTableTask(consumer);
14771478
}
1479+
else if (tableName == CFG_SWITCH_FAST_LINKUP_TABLE_NAME)
1480+
{
1481+
doCfgSwitchFastLinkupTableTask(consumer);
1482+
}
14781483
else if (tableName == CFG_SUPPRESS_ASIC_SDK_HEALTH_EVENT_NAME)
14791484
{
14801485
doCfgSuppressAsicSdkHealthEventTableTask(consumer);
@@ -1993,6 +1998,196 @@ bool SwitchOrch::querySwitchCapability(sai_object_type_t sai_object, sai_attr_id
19931998
}
19941999
}
19952000

2001+
void SwitchOrch::setFastLinkupCapability()
2002+
{
2003+
SWSS_LOG_ENTER();
2004+
2005+
std::vector<FieldValueTuple> fvVector;
2006+
2007+
// Determine support by checking create/set capability on polling time attribute (enabled in real SAI)
2008+
bool supported = querySwitchCapability(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_FAST_LINKUP_POLLING_TIMEOUT);
2009+
m_fastLinkupCap.supported = supported;
2010+
2011+
if (!supported)
2012+
{
2013+
fvVector.emplace_back(SWITCH_CAPABILITY_TABLE_FAST_LINKUP_CAPABLE, "false");
2014+
set_switch_capability(fvVector);
2015+
return;
2016+
}
2017+
2018+
fvVector.emplace_back(SWITCH_CAPABILITY_TABLE_FAST_LINKUP_CAPABLE, "true");
2019+
2020+
// Query allowed ranges if supported by SAI
2021+
{
2022+
sai_attribute_t attr;
2023+
attr.id = SAI_SWITCH_ATTR_FAST_LINKUP_POLLING_TIMEOUT_RANGE;
2024+
sai_status_t status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
2025+
if (status == SAI_STATUS_SUCCESS)
2026+
{
2027+
m_fastLinkupCap.has_ranges = true;
2028+
m_fastLinkupCap.polling_min = attr.value.u16range.min;
2029+
m_fastLinkupCap.polling_max = attr.value.u16range.max;
2030+
fvVector.emplace_back(
2031+
SWITCH_CAPABILITY_TABLE_FAST_LINKUP_POLLING_TIMER_RANGE,
2032+
to_string(m_fastLinkupCap.polling_min) + "," + to_string(m_fastLinkupCap.polling_max));
2033+
}
2034+
else
2035+
{
2036+
SWSS_LOG_ERROR("Failed to get fast linkup polling range: %s", sai_serialize_status(status).c_str());
2037+
}
2038+
}
2039+
2040+
{
2041+
sai_attribute_t attr;
2042+
attr.id = SAI_SWITCH_ATTR_FAST_LINKUP_GUARD_TIMEOUT_RANGE;
2043+
sai_status_t status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
2044+
if (status == SAI_STATUS_SUCCESS)
2045+
{
2046+
m_fastLinkupCap.has_ranges = true;
2047+
m_fastLinkupCap.guard_min = attr.value.u16range.min;
2048+
m_fastLinkupCap.guard_max = attr.value.u16range.max;
2049+
fvVector.emplace_back(
2050+
SWITCH_CAPABILITY_TABLE_FAST_LINKUP_GUARD_TIMER_RANGE,
2051+
to_string(m_fastLinkupCap.guard_min) + "," + to_string(m_fastLinkupCap.guard_max));
2052+
}
2053+
else
2054+
{
2055+
SWSS_LOG_ERROR("Failed to get fast linkup guard range: %s", sai_serialize_status(status).c_str());
2056+
}
2057+
}
2058+
set_switch_capability(fvVector);
2059+
}
2060+
2061+
bool SwitchOrch::setSwitchFastLinkup(const FastLinkupConfig &cfg)
2062+
{
2063+
SWSS_LOG_ENTER();
2064+
2065+
if (!m_fastLinkupCap.supported)
2066+
{
2067+
SWSS_LOG_NOTICE("Fast link-up is not supported on this platform");
2068+
return false;
2069+
}
2070+
2071+
// Validate ranges if known
2072+
if (cfg.has_polling && m_fastLinkupCap.has_ranges)
2073+
{
2074+
if (cfg.polling_time < m_fastLinkupCap.polling_min || cfg.polling_time > m_fastLinkupCap.polling_max)
2075+
{
2076+
SWSS_LOG_NOTICE("Invalid polling_time %u; allowed [%u,%u]", cfg.polling_time, m_fastLinkupCap.polling_min, m_fastLinkupCap.polling_max);
2077+
return false;
2078+
}
2079+
}
2080+
if (cfg.has_guard && m_fastLinkupCap.has_ranges)
2081+
{
2082+
if (cfg.guard_time < m_fastLinkupCap.guard_min || cfg.guard_time > m_fastLinkupCap.guard_max)
2083+
{
2084+
SWSS_LOG_NOTICE("Invalid guard_time %u; allowed [%u,%u]", cfg.guard_time, m_fastLinkupCap.guard_min, m_fastLinkupCap.guard_max);
2085+
return false;
2086+
}
2087+
}
2088+
2089+
// Apply attributes conditionally
2090+
sai_status_t status;
2091+
if (cfg.has_polling)
2092+
{
2093+
sai_attribute_t attr;
2094+
attr.id = SAI_SWITCH_ATTR_FAST_LINKUP_POLLING_TIMEOUT;
2095+
attr.value.u16 = cfg.polling_time;
2096+
status = sai_switch_api->set_switch_attribute(gSwitchId, &attr);
2097+
if (status != SAI_STATUS_SUCCESS)
2098+
{
2099+
SWSS_LOG_NOTICE("Failed to set FAST_LINKUP_POLLING_TIME=%u: %s", cfg.polling_time, sai_serialize_status(status).c_str());
2100+
return false;
2101+
}
2102+
}
2103+
2104+
if (cfg.has_guard)
2105+
{
2106+
sai_attribute_t attr;
2107+
attr.id = SAI_SWITCH_ATTR_FAST_LINKUP_GUARD_TIMEOUT;
2108+
attr.value.u8 = cfg.guard_time;
2109+
status = sai_switch_api->set_switch_attribute(gSwitchId, &attr);
2110+
if (status != SAI_STATUS_SUCCESS)
2111+
{
2112+
SWSS_LOG_NOTICE("Failed to set FAST_LINKUP_GUARD_TIME=%u: %s", cfg.guard_time, sai_serialize_status(status).c_str());
2113+
return false;
2114+
}
2115+
}
2116+
2117+
if (cfg.has_ber)
2118+
{
2119+
sai_attribute_t attr;
2120+
attr.id = SAI_SWITCH_ATTR_FAST_LINKUP_BER_THRESHOLD;
2121+
attr.value.u8 = cfg.ber_threshold;
2122+
status = sai_switch_api->set_switch_attribute(gSwitchId, &attr);
2123+
if (status != SAI_STATUS_SUCCESS)
2124+
{
2125+
SWSS_LOG_NOTICE("Failed to set FAST_LINKUP_BER_THRESHOLD=%u: %s", cfg.ber_threshold, sai_serialize_status(status).c_str());
2126+
return false;
2127+
}
2128+
}
2129+
SWSS_LOG_INFO("Fast link-up set: polling_time=%s, guard_time=%s, ber_threshold=%s",
2130+
cfg.has_polling ? std::to_string(cfg.polling_time).c_str() : "N/A",
2131+
cfg.has_guard ? std::to_string(cfg.guard_time).c_str() : "N/A",
2132+
cfg.has_ber ? std::to_string(cfg.ber_threshold).c_str() : "N/A");
2133+
return true;
2134+
}
2135+
2136+
void SwitchOrch::doCfgSwitchFastLinkupTableTask(Consumer &consumer)
2137+
{
2138+
SWSS_LOG_ENTER();
2139+
2140+
auto &map = consumer.m_toSync;
2141+
auto it = map.begin();
2142+
2143+
while (it != map.end())
2144+
{
2145+
auto keyOpFieldsValues = it->second;
2146+
auto key = kfvKey(keyOpFieldsValues);
2147+
auto op = kfvOp(keyOpFieldsValues);
2148+
2149+
if (op == SET_COMMAND)
2150+
{
2151+
FastLinkupConfig cfg;
2152+
for (const auto &cit : kfvFieldsValues(keyOpFieldsValues))
2153+
{
2154+
auto fieldName = fvField(cit);
2155+
auto fieldValue = fvValue(cit);
2156+
if (fieldName == "polling_time")
2157+
{
2158+
try { cfg.polling_time = to_uint<uint16_t>(fieldValue); cfg.has_polling = true; }
2159+
catch (...) { SWSS_LOG_ERROR("Invalid polling_time value %s", fieldValue.c_str()); }
2160+
}
2161+
else if (fieldName == "guard_time")
2162+
{
2163+
try { cfg.guard_time = to_uint<uint8_t>(fieldValue); cfg.has_guard = true; }
2164+
catch (...) { SWSS_LOG_ERROR("Invalid guard_time value %s", fieldValue.c_str()); }
2165+
}
2166+
else if (fieldName == "ber_threshold")
2167+
{
2168+
try { cfg.ber_threshold = to_uint<uint8_t>(fieldValue); cfg.has_ber = true; }
2169+
catch (...) { SWSS_LOG_ERROR("Invalid ber_threshold value %s", fieldValue.c_str()); }
2170+
}
2171+
else
2172+
{
2173+
SWSS_LOG_WARN("Unknown field %s in SWITCH_FAST_LINKUP", fieldName.c_str());
2174+
}
2175+
}
2176+
2177+
if (!setSwitchFastLinkup(cfg))
2178+
{
2179+
SWSS_LOG_ERROR("Failed to configure fast link-up from CONFIG_DB");
2180+
}
2181+
}
2182+
else
2183+
{
2184+
SWSS_LOG_ERROR("Unsupported operation %s for SWITCH_FAST_LINKUP", op.c_str());
2185+
}
2186+
2187+
it = map.erase(it);
2188+
}
2189+
}
2190+
19962191
// Bind ACL table (with bind type switch) to switch
19972192
bool SwitchOrch::bindAclTableToSwitch(acl_stage_type_t stage, sai_object_id_t table_id)
19982193
{

0 commit comments

Comments
 (0)