Skip to content

Commit

Permalink
Add SWSS support for link event damping feature (#2933)
Browse files Browse the repository at this point in the history
What I did
Added support for link event damping in SWSS.

Required Syncd PR: sonic-net/sonic-sairedis#1297
CLI PR: sonic-net/sonic-utilities#3001
HLD: https://github.com/sonic-net/SONiC/blob/master/doc/link_event_damping/Link-event-damping-HLD.md

Why I did it

How I verified it
Use the config interface damping CLI to set the port attributes on the switch and observe that Syncd processes link event damping parameters.
  • Loading branch information
royyi8 authored Jun 4, 2024
1 parent b3ebfc4 commit 80f5207
Show file tree
Hide file tree
Showing 9 changed files with 672 additions and 0 deletions.
9 changes: 9 additions & 0 deletions orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extern "C" {
#include <unordered_set>

#include <macaddress.h>
#include <sairedis.h>

#define DEFAULT_PORT_VLAN_ID 1
/*
Expand Down Expand Up @@ -212,6 +213,14 @@ class Port
/* Path Tracing */
uint16_t m_pt_intf_id = 0;
sai_port_path_tracing_timestamp_type_t m_pt_timestamp_template = SAI_PORT_PATH_TRACING_TIMESTAMP_TYPE_16_23;

/* link event damping */
sai_redis_link_event_damping_algorithm_t m_link_event_damping_algorithm = SAI_REDIS_LINK_EVENT_DAMPING_ALGORITHM_DISABLED;
uint32_t m_max_suppress_time = 0;
uint32_t m_decay_half_life = 0;
uint32_t m_suppress_threshold = 0;
uint32_t m_reuse_threshold = 0;
uint32_t m_flap_penalty = 0;
};

}
Expand Down
34 changes: 34 additions & 0 deletions orchagent/port/portcnt.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,40 @@ class PortConfig final
bool is_set = false;
} pt_timestamp_template; // Port timestamp template for Path Tracing

struct {
sai_redis_link_event_damping_algorithm_t value;
bool is_set = false;
} link_event_damping_algorithm; // Port link event damping algorithm

struct {

struct {
uint32_t value;
bool is_set = false;
} max_suppress_time; // Max suppress time

struct {
uint32_t value;
bool is_set = false;
} decay_half_life; // Decay half life

struct {
uint32_t value;
bool is_set = false;
} suppress_threshold; // Suppress threshold

struct {
uint32_t value;
bool is_set = false;
} reuse_threshold; // Reuse threshold

struct {
uint32_t value;
bool is_set = false;
} flap_penalty; // Flap penalty

} link_event_damping_config; // Port link event damping config

std::string key;
std::string op;

Expand Down
108 changes: 108 additions & 0 deletions orchagent/port/porthlpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ using namespace swss;
// types --------------------------------------------------------------------------------------------------------------

typedef decltype(PortConfig::serdes) PortSerdes_t;
typedef decltype(PortConfig::link_event_damping_config) PortDampingConfig_t;

// constants ----------------------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -126,6 +127,12 @@ static const std::unordered_map<std::string, sai_port_path_tracing_timestamp_typ
{ PORT_PT_TIMESTAMP_TEMPLATE_4, SAI_PORT_PATH_TRACING_TIMESTAMP_TYPE_20_27 }
};

static const std::unordered_map<std::string, sai_redis_link_event_damping_algorithm_t> g_linkEventDampingAlgorithmMap =
{
{ "disabled", SAI_REDIS_LINK_EVENT_DAMPING_ALGORITHM_DISABLED },
{ "aied", SAI_REDIS_LINK_EVENT_DAMPING_ALGORITHM_AIED }
};

// functions ----------------------------------------------------------------------------------------------------------

template<typename T>
Expand Down Expand Up @@ -246,6 +253,11 @@ std::string PortHelper::getPtTimestampTemplateStr(const PortConfig &port) const
return this->getFieldValueStr(port, PORT_PT_TIMESTAMP_TEMPLATE);
}

std::string PortHelper::getDampingAlgorithm(const PortConfig &port) const
{
return this->getFieldValueStr(port, PORT_DAMPING_ALGO);
}

bool PortHelper::parsePortAlias(PortConfig &port, const std::string &field, const std::string &value) const
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -786,6 +798,60 @@ bool PortHelper::parsePortSubport(PortConfig &port, const std::string &field, co
return true;
}

bool PortHelper::parsePortLinkEventDampingAlgorithm(PortConfig &port, const std::string &field, const std::string &value) const
{
SWSS_LOG_ENTER();

if (value.empty())
{
SWSS_LOG_ERROR("Failed to parse field(%s): empty value is prohibited", field.c_str());
return false;
}

const auto &cit = g_linkEventDampingAlgorithmMap.find(value);
if (cit == g_linkEventDampingAlgorithmMap.cend())
{
SWSS_LOG_ERROR("Failed to parse field(%s): invalid value(%s)", field.c_str(), value.c_str());
return false;
}

port.link_event_damping_algorithm.value = cit->second;
port.link_event_damping_algorithm.is_set = true;

return true;
}

template<typename T>
bool PortHelper::parsePortLinkEventDampingConfig(T &damping_config_attr, const std::string &field, const std::string &value) const
{
SWSS_LOG_ENTER();

if (value.empty())
{
SWSS_LOG_ERROR("Failed to parse field(%s): empty string is prohibited", field.c_str());
return false;
}

try
{
damping_config_attr.value = to_uint<std::uint32_t>(value);
damping_config_attr.is_set = true;
}
catch (const std::exception &e)
{
SWSS_LOG_ERROR("Failed to parse field(%s): %s", field.c_str(), e.what());
return false;
}

return true;
}

template bool PortHelper::parsePortLinkEventDampingConfig(decltype(PortDampingConfig_t::max_suppress_time) &damping_config_attr, const std::string &field, const std::string &value) const;
template bool PortHelper::parsePortLinkEventDampingConfig(decltype(PortDampingConfig_t::decay_half_life) &damping_config_attr, const std::string &field, const std::string &value) const;
template bool PortHelper::parsePortLinkEventDampingConfig(decltype(PortDampingConfig_t::suppress_threshold) &damping_config_attr, const std::string &field, const std::string &value) const;
template bool PortHelper::parsePortLinkEventDampingConfig(decltype(PortDampingConfig_t::reuse_threshold) &damping_config_attr, const std::string &field, const std::string &value) const;
template bool PortHelper::parsePortLinkEventDampingConfig(decltype(PortDampingConfig_t::flap_penalty) &damping_config_attr, const std::string &field, const std::string &value) const;

bool PortHelper::parsePortPtIntfId(PortConfig &port, const std::string &field, const std::string &value) const
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -1121,6 +1187,48 @@ bool PortHelper::parsePortConfig(PortConfig &port) const
return false;
}
}
else if (field == PORT_DAMPING_ALGO)
{
if (!this->parsePortLinkEventDampingAlgorithm(port, field, value))
{
return false;
}
}
else if (field == PORT_MAX_SUPPRESS_TIME)
{
if (!this->parsePortLinkEventDampingConfig(port.link_event_damping_config.max_suppress_time, field, value))
{
return false;
}
}
else if (field == PORT_DECAY_HALF_LIFE)
{
if (!this->parsePortLinkEventDampingConfig(port.link_event_damping_config.decay_half_life, field, value))
{
return false;
}
}
else if (field == PORT_SUPPRESS_THRESHOLD)
{
if (!this->parsePortLinkEventDampingConfig(port.link_event_damping_config.suppress_threshold, field, value))
{
return false;
}
}
else if (field == PORT_REUSE_THRESHOLD)
{
if (!this->parsePortLinkEventDampingConfig(port.link_event_damping_config.reuse_threshold, field, value))
{
return false;
}
}
else if (field == PORT_FLAP_PENALTY)
{
if (!this->parsePortLinkEventDampingConfig(port.link_event_damping_config.flap_penalty, field, value))
{
return false;
}
}
else
{
SWSS_LOG_WARN("Unknown field(%s): skipping ...", field.c_str());
Expand Down
5 changes: 5 additions & 0 deletions orchagent/port/porthlpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class PortHelper final
std::string getLinkTrainingStr(const PortConfig &port) const;
std::string getAdminStatusStr(const PortConfig &port) const;
std::string getPtTimestampTemplateStr(const PortConfig &port) const;
std::string getDampingAlgorithm(const PortConfig &port) const;

bool parsePortConfig(PortConfig &port) const;
bool validatePortConfig(PortConfig &port) const;
Expand All @@ -37,6 +38,10 @@ class PortHelper final
template<typename T>
bool parsePortSerdes(T &serdes, const std::string &field, const std::string &value) const;

bool parsePortLinkEventDampingAlgorithm(PortConfig &port, const std::string &field, const std::string &value) const;
template<typename T>
bool parsePortLinkEventDampingConfig(T &damping_config_attr, const std::string &field, const std::string &value) const;

bool parsePortAlias(PortConfig &port, const std::string &field, const std::string &value) const;
bool parsePortIndex(PortConfig &port, const std::string &field, const std::string &value) const;
bool parsePortLanes(PortConfig &port, const std::string &field, const std::string &value) const;
Expand Down
6 changes: 6 additions & 0 deletions orchagent/port/portschema.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,9 @@
#define PORT_SUBPORT "subport"
#define PORT_PT_INTF_ID "pt_interface_id"
#define PORT_PT_TIMESTAMP_TEMPLATE "pt_timestamp_template"
#define PORT_DAMPING_ALGO "link_event_damping_algorithm"
#define PORT_MAX_SUPPRESS_TIME "max_suppress_time"
#define PORT_DECAY_HALF_LIFE "decay_half_life"
#define PORT_SUPPRESS_THRESHOLD "suppress_threshold"
#define PORT_REUSE_THRESHOLD "reuse_threshold"
#define PORT_FLAP_PENALTY "flap_penalty"
123 changes: 123 additions & 0 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3171,6 +3171,49 @@ task_process_status PortsOrch::setPortLinkTraining(const Port &port, bool state)
return task_success;
}

ReturnCode PortsOrch::setPortLinkEventDampingAlgorithm(Port &port,
sai_redis_link_event_damping_algorithm_t &link_event_damping_algorithm)
{
SWSS_LOG_ENTER();
sai_attribute_t attr;
attr.id = SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGORITHM;
attr.value.s32 = link_event_damping_algorithm;

CHECK_ERROR_AND_LOG_AND_RETURN(
sai_port_api->set_port_attribute(port.m_port_id, &attr),
"Failed to set link event damping algorithm (" << link_event_damping_algorithm << ") for port "
<< port.m_alias);

SWSS_LOG_INFO("Set link event damping algorithm %u for port %s", link_event_damping_algorithm, port.m_alias.c_str());
return ReturnCode();
}

ReturnCode PortsOrch::setPortLinkEventDampingAiedConfig(Port &port,
sai_redis_link_event_damping_algo_aied_config_t &config) {

SWSS_LOG_ENTER();
sai_attribute_t attr;
attr.id = SAI_REDIS_PORT_ATTR_LINK_EVENT_DAMPING_ALGO_AIED_CONFIG;
attr.value.ptr = (void *) &config;

std::stringstream msg;
msg << "link event damping algorithm aied config for port " << port.m_alias << " - ";
msg << "max_suppress_time: " << config.max_suppress_time << ", ";
msg << "decay_half_life: " << config.decay_half_life << ", ";
msg << "suppress_threshold: " << config.suppress_threshold << ", ";
msg << "reuse_threshold: " << config.reuse_threshold << ", ";
msg << "flap_penalty: " << config.flap_penalty;

std::string msg_str = msg.str();

CHECK_ERROR_AND_LOG_AND_RETURN(
sai_port_api->set_port_attribute(port.m_port_id, &attr), "Failed to set " + msg_str);

SWSS_LOG_INFO("Set %s", msg_str.c_str());

return ReturnCode();
}

bool PortsOrch::setHostIntfsOperStatus(const Port& port, bool isUp) const
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -4033,6 +4076,86 @@ void PortsOrch::doPortTask(Consumer &consumer)
}
}

if (pCfg.link_event_damping_algorithm.is_set)
{
if (p.m_link_event_damping_algorithm != pCfg.link_event_damping_algorithm.value)
{
auto status = setPortLinkEventDampingAlgorithm(p, pCfg.link_event_damping_algorithm.value);
if (!status.ok())
{
SWSS_LOG_ERROR(
"Failed to set port %s link event damping algorithm to %s",
p.m_alias.c_str(), m_portHlpr.getDampingAlgorithm(pCfg).c_str()
);
it = taskMap.erase(it);
continue;
}

p.m_link_event_damping_algorithm = pCfg.link_event_damping_algorithm.value;
m_portList[p.m_alias] = p;

SWSS_LOG_NOTICE(
"Set port %s link event damping algorithm to %s",
p.m_alias.c_str(), m_portHlpr.getDampingAlgorithm(pCfg).c_str()
);
}
}

sai_redis_link_event_damping_algo_aied_config_t aied_config = {
p.m_max_suppress_time,
p.m_suppress_threshold,
p.m_reuse_threshold,
p.m_decay_half_life,
p.m_flap_penalty,
};

if (pCfg.link_event_damping_config.max_suppress_time.is_set)
{
aied_config.max_suppress_time = pCfg.link_event_damping_config.max_suppress_time.value;
}
if (pCfg.link_event_damping_config.decay_half_life.is_set)
{
aied_config.decay_half_life = pCfg.link_event_damping_config.decay_half_life.value;
}
if (pCfg.link_event_damping_config.suppress_threshold.is_set)
{
aied_config.suppress_threshold = pCfg.link_event_damping_config.suppress_threshold.value;
}
if (pCfg.link_event_damping_config.reuse_threshold.is_set)
{
aied_config.reuse_threshold = pCfg.link_event_damping_config.reuse_threshold.value;
}
if (pCfg.link_event_damping_config.flap_penalty.is_set)
{
aied_config.flap_penalty = pCfg.link_event_damping_config.flap_penalty.value;
}

bool config_changed = !(aied_config.max_suppress_time == p.m_max_suppress_time &&
aied_config.decay_half_life == p.m_decay_half_life &&
aied_config.suppress_threshold == p.m_suppress_threshold &&
aied_config.reuse_threshold == p.m_reuse_threshold &&
aied_config.flap_penalty == p.m_flap_penalty);

if (config_changed)
{
auto status = setPortLinkEventDampingAiedConfig(p, aied_config);
if (!status.ok())
{
SWSS_LOG_ERROR("Failed to set port %s link event damping config", p.m_alias.c_str());
it = taskMap.erase(it);
continue;
}

p.m_max_suppress_time = aied_config.max_suppress_time;
p.m_decay_half_life = aied_config.decay_half_life;
p.m_suppress_threshold = aied_config.suppress_threshold;
p.m_reuse_threshold = aied_config.reuse_threshold;
p.m_flap_penalty = aied_config.flap_penalty;
m_portList[p.m_alias] = p;

SWSS_LOG_NOTICE("Set port %s link event damping config successfully", p.m_alias.c_str());
}

if (pCfg.speed.is_set)
{
if (p.m_speed != pCfg.speed.value)
Expand Down
5 changes: 5 additions & 0 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,11 @@ class PortsOrch : public Orch, public Subject
task_process_status setPortAdvInterfaceTypes(Port &port, std::set<sai_port_interface_type_t> &interface_types);
task_process_status setPortLinkTraining(const Port& port, bool state);

ReturnCode setPortLinkEventDampingAlgorithm(Port &port,
sai_redis_link_event_damping_algorithm_t &link_event_damping_algorithm);
ReturnCode setPortLinkEventDampingAiedConfig(Port &port,
sai_redis_link_event_damping_algo_aied_config_t &config);

void updatePortOperStatus(Port &port, sai_port_oper_status_t status);

bool getPortOperSpeed(const Port& port, sai_uint32_t& speed) const;
Expand Down
Loading

0 comments on commit 80f5207

Please sign in to comment.