@@ -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;
@@ -2858,6 +2940,13 @@ void PortsOrch::doPortTask(Consumer &consumer)
28582940 {
28592941 if (!an_str.empty ())
28602942 {
2943+ if (!p.m_port_cap_an )
2944+ {
2945+ SWSS_LOG_ERROR (" %s: autoneg is not supported" , p.m_alias .c_str ());
2946+ // Invalid auto negotiation mode configured, don't retry
2947+ it = consumer.m_toSync .erase (it);
2948+ continue ;
2949+ }
28612950 if (autoneg_mode_map.find (an_str) == autoneg_mode_map.end ())
28622951 {
28632952 SWSS_LOG_ERROR (" Failed to parse autoneg value: %s" , an_str.c_str ());
@@ -2899,7 +2988,15 @@ void PortsOrch::doPortTask(Consumer &consumer)
28992988 }
29002989 SWSS_LOG_NOTICE (" Set port %s AutoNeg from %d to %d" , alias.c_str (), p.m_autoneg , an);
29012990 p.m_autoneg = an;
2902- m_portList[alias] = p;
2991+ m_portStateTable.hdel (p.m_alias , " rmt_adv_speeds" );
2992+ if (an > 0 )
2993+ {
2994+ m_port_state_poll[p.m_alias ] |= PORT_STATE_POLL_AN;
2995+ }
2996+ else
2997+ {
2998+ m_port_state_poll[p.m_alias ] &= ~PORT_STATE_POLL_AN;
2999+ }
29033000 }
29043001 }
29053002
@@ -5666,6 +5763,20 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status)
56665763 if (port.m_type == Port::PHY)
56675764 {
56685765 updateDbPortOperStatus (port, status);
5766+ if (port.m_autoneg > 0 )
5767+ {
5768+ if (status == SAI_PORT_OPER_STATUS_UP)
5769+ {
5770+ updatePortStateAutoNeg (port);
5771+ m_port_state_poll[port.m_alias ] &= ~PORT_STATE_POLL_AN;
5772+ }
5773+ else
5774+ {
5775+ /* Restart autoneg state polling upon link down event */
5776+ m_portStateTable.hdel (port.m_alias , " rmt_adv_speeds" );
5777+ m_port_state_poll[port.m_alias ] |= PORT_STATE_POLL_AN;
5778+ }
5779+ }
56695780 }
56705781 port.m_oper_status = status;
56715782
@@ -6792,3 +6903,37 @@ std::unordered_set<std::string> PortsOrch::generateCounterStats(const string& ty
67926903 }
67936904 return counter_stats;
67946905}
6906+
6907+ void PortsOrch::updatePortStateAutoNeg (const Port &port)
6908+ {
6909+ SWSS_LOG_ENTER ();
6910+
6911+ if (port.m_type != Port::Type::PHY)
6912+ {
6913+ return ;
6914+ }
6915+
6916+ string adv_speeds;
6917+
6918+ if (getPortAdvSpeeds (port, true , adv_speeds))
6919+ {
6920+ m_portStateTable.hset (port.m_alias , " rmt_adv_speeds" , adv_speeds);
6921+ }
6922+ else
6923+ {
6924+ m_port_state_poll[port.m_alias ] &= ~PORT_STATE_POLL_AN;
6925+ }
6926+ }
6927+
6928+ void PortsOrch::doTask (swss::SelectableTimer &timer)
6929+ {
6930+ SWSS_LOG_ENTER ();
6931+
6932+ for (auto it = m_portList.begin (); it != m_portList.end (); ++it)
6933+ {
6934+ if (m_port_state_poll[it->second .m_alias ] & PORT_STATE_POLL_AN)
6935+ {
6936+ updatePortStateAutoNeg (it->second );
6937+ }
6938+ }
6939+ }
0 commit comments