@@ -61,6 +61,7 @@ extern string gMyAsicName;
6161#define DEFAULT_VLAN_ID 1
6262#define MAX_VALID_VLAN_ID 4094
6363
64+ #define PORT_STAT_POLLING_SEC 1
6465#define PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000
6566#define PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS 60000
6667#define QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 10000
@@ -298,7 +299,8 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_wi
298299 m_portStateTable(stateDb, STATE_PORT_TABLE_NAME),
299300 port_stat_manager(PORT_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false ),
300301 port_buffer_drop_stat_manager(PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP, StatsMode::READ, PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS, false ),
301- queue_stat_manager(QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false )
302+ queue_stat_manager(QUEUE_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, QUEUE_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false ),
303+ m_timer(new SelectableTimer(timespec { .tv_sec = PORT_STAT_POLLING_SEC, .tv_nsec = 0 }))
302304{
303305 SWSS_LOG_ENTER ();
304306
@@ -563,6 +565,10 @@ PortsOrch::PortsOrch(DBConnector *db, DBConnector *stateDb, vector<table_name_wi
563565
564566 m_lagIdAllocator = unique_ptr<LagIdAllocator> (new LagIdAllocator (chassisAppDb));
565567 }
568+
569+ auto executor = new ExecutableTimer (m_timer, this , " PORT_STATE_POLL" );
570+ Orch::addExecutor (executor);
571+ m_timer->start ();
566572}
567573
568574void PortsOrch::removeDefaultVlanMembers ()
@@ -1860,6 +1866,24 @@ void PortsOrch::initPortSupportedSpeeds(const std::string& alias, sai_object_id_
18601866 m_portStateTable.set (alias, v);
18611867}
18621868
1869+ void PortsOrch::initPortCapAutoNeg (Port &port)
1870+ {
1871+ sai_status_t status;
1872+ sai_attribute_t attr;
1873+
1874+ attr.id = SAI_PORT_ATTR_SUPPORTED_AUTO_NEG_MODE;
1875+ status = sai_port_api->set_port_attribute (port.m_port_id , &attr);
1876+ if (status == SAI_STATUS_SUCCESS)
1877+ {
1878+ port.m_port_cap_an = attr.value .booldata ;
1879+ }
1880+ else
1881+ {
1882+ port.m_port_cap_an = false ;
1883+ SWSS_LOG_NOTICE (" Unable to get %s AN capability" , port.m_alias .c_str ());
1884+ }
1885+ }
1886+
18631887/*
18641888 * If Gearbox is enabled and this is a Gearbox port then set the attributes accordingly.
18651889 */
@@ -2014,6 +2038,61 @@ bool PortsOrch::getPortSpeed(sai_object_id_t id, sai_uint32_t &speed)
20142038 return true ;
20152039}
20162040
2041+ bool PortsOrch::getPortAdvSpeeds (const Port& port, bool remote, std::vector<sai_uint32_t >& speed_list)
2042+ {
2043+ sai_object_id_t port_id = port.m_port_id ;
2044+ sai_object_id_t line_port_id;
2045+ sai_attribute_t attr;
2046+ sai_status_t status;
2047+ const auto size_guess = 16 ; // Guess the size which could be enough
2048+ std::vector<sai_uint32_t > speeds (size_guess);
2049+
2050+ attr.id = remote ? SAI_PORT_ATTR_REMOTE_ADVERTISED_SPEED : SAI_PORT_ATTR_ADVERTISED_SPEED;
2051+ attr.value .u32list .count = static_cast <uint32_t >(speeds.size ());
2052+ attr.value .u32list .list = speeds.data ();
2053+
2054+ if (getDestPortId (port_id, LINE_PORT_TYPE, line_port_id))
2055+ {
2056+ status = sai_port_api->get_port_attribute (line_port_id, 1 , &attr);
2057+ }
2058+ else
2059+ {
2060+ status = sai_port_api->get_port_attribute (port_id, 1 , &attr);
2061+ }
2062+ if (status != SAI_STATUS_SUCCESS)
2063+ {
2064+ return false ;
2065+ }
2066+ speeds.resize (attr.value .u32list .count );
2067+
2068+ speed_list.clear ();
2069+ for (auto it = speeds.begin (); it != speeds.end (); ++it)
2070+ {
2071+ speed_list.push_back (*it);
2072+ }
2073+ return true ;
2074+ }
2075+
2076+ bool PortsOrch::getPortAdvSpeeds (const Port& port, bool remote, string& adv_speeds)
2077+ {
2078+ std::vector<sai_uint32_t > speed_list;
2079+ bool rc = getPortAdvSpeeds (port, remote, speed_list);
2080+
2081+ adv_speeds = " " ;
2082+ if (rc)
2083+ {
2084+ for (auto it = speed_list.begin (); it != speed_list.end (); ++it)
2085+ {
2086+ adv_speeds += std::to_string (*it);
2087+ if (it + 1 != speed_list.end ())
2088+ {
2089+ adv_speeds += " ," ;
2090+ }
2091+ }
2092+ }
2093+ return rc;
2094+ }
2095+
20172096task_process_status PortsOrch::setPortAdvSpeeds (sai_object_id_t port_id, std::vector<sai_uint32_t >& speed_list)
20182097{
20192098 SWSS_LOG_ENTER ();
@@ -2351,6 +2430,9 @@ bool PortsOrch::initPort(const string &alias, const string &role, const int inde
23512430 /* Create associated Gearbox lane mapping */
23522431 initGearboxPort (p);
23532432
2433+ /* Initialize port capabilities */
2434+ initPortCapAutoNeg (p);
2435+
23542436 /* Add port to port list */
23552437 m_portList[alias] = p;
23562438 saiOidToAlias[id] = alias;
@@ -2885,6 +2967,13 @@ void PortsOrch::doPortTask(Consumer &consumer)
28852967 {
28862968 if (!an_str.empty ())
28872969 {
2970+ if (!p.m_port_cap_an )
2971+ {
2972+ SWSS_LOG_ERROR (" %s: autoneg is not supported" , p.m_alias .c_str ());
2973+ // Invalid auto negotiation mode configured, don't retry
2974+ it = consumer.m_toSync .erase (it);
2975+ continue ;
2976+ }
28882977 if (autoneg_mode_map.find (an_str) == autoneg_mode_map.end ())
28892978 {
28902979 SWSS_LOG_ERROR (" Failed to parse autoneg value: %s" , an_str.c_str ());
@@ -2927,6 +3016,15 @@ void PortsOrch::doPortTask(Consumer &consumer)
29273016 SWSS_LOG_NOTICE (" Set port %s AutoNeg from %d to %d" , alias.c_str (), p.m_autoneg , an);
29283017 p.m_autoneg = an;
29293018 m_portList[alias] = p;
3019+ m_portStateTable.hdel (p.m_alias , " rmt_adv_speeds" );
3020+ if (an > 0 )
3021+ {
3022+ m_port_state_poll[p.m_alias ] |= PORT_STATE_POLL_AN;
3023+ }
3024+ else
3025+ {
3026+ m_port_state_poll[p.m_alias ] &= ~PORT_STATE_POLL_AN;
3027+ }
29303028 }
29313029 }
29323030
@@ -5757,6 +5855,20 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status)
57575855 if (port.m_type == Port::PHY)
57585856 {
57595857 updateDbPortOperStatus (port, status);
5858+ if (port.m_autoneg > 0 )
5859+ {
5860+ if (status == SAI_PORT_OPER_STATUS_UP)
5861+ {
5862+ updatePortStateAutoNeg (port);
5863+ m_port_state_poll[port.m_alias ] &= ~PORT_STATE_POLL_AN;
5864+ }
5865+ else
5866+ {
5867+ /* Restart autoneg state polling upon link down event */
5868+ m_portStateTable.hdel (port.m_alias , " rmt_adv_speeds" );
5869+ m_port_state_poll[port.m_alias ] |= PORT_STATE_POLL_AN;
5870+ }
5871+ }
57605872 }
57615873 port.m_oper_status = status;
57625874
@@ -6883,3 +6995,37 @@ std::unordered_set<std::string> PortsOrch::generateCounterStats(const string& ty
68836995 }
68846996 return counter_stats;
68856997}
6998+
6999+ void PortsOrch::updatePortStateAutoNeg (const Port &port)
7000+ {
7001+ SWSS_LOG_ENTER ();
7002+
7003+ if (port.m_type != Port::Type::PHY)
7004+ {
7005+ return ;
7006+ }
7007+
7008+ string adv_speeds;
7009+
7010+ if (getPortAdvSpeeds (port, true , adv_speeds))
7011+ {
7012+ m_portStateTable.hset (port.m_alias , " rmt_adv_speeds" , adv_speeds);
7013+ }
7014+ else
7015+ {
7016+ m_port_state_poll[port.m_alias ] &= ~PORT_STATE_POLL_AN;
7017+ }
7018+ }
7019+
7020+ void PortsOrch::doTask (swss::SelectableTimer &timer)
7021+ {
7022+ SWSS_LOG_ENTER ();
7023+
7024+ for (auto it = m_portList.begin (); it != m_portList.end (); ++it)
7025+ {
7026+ if (m_port_state_poll[it->second .m_alias ] & PORT_STATE_POLL_AN)
7027+ {
7028+ updatePortStateAutoNeg (it->second );
7029+ }
7030+ }
7031+ }
0 commit comments