Skip to content

Commit 951f828

Browse files
committed
[autoneg] add support for capability checker and remote speed advertisement
HLD: sonic-net/SONiC#924 - What I did Add support for remote speed advertisement Add support for capability checker - How I did it Implementation is done according to the AutoNeg HLD Signed-off-by: Dante Su <[email protected]>
1 parent 1fd1dbf commit 951f828

3 files changed

Lines changed: 164 additions & 1 deletion

File tree

orchagent/port.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class Port
174174

175175
bool m_fec_cfg = false;
176176
bool m_an_cfg = false;
177+
bool m_port_cap_an = false; /* Port Capability - AutoNeg */
177178
};
178179

179180
}

orchagent/portsorch.cpp

Lines changed: 147 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

568574
void 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+
20172096
task_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+
}

orchagent/portsorch.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,12 @@ class PortsOrch : public Orch, public Subject
217217
LINE_PORT_TYPE,
218218
} dest_port_type_t;
219219

220+
typedef enum {
221+
PORT_STATE_POLL_NONE = 0,
222+
PORT_STATE_POLL_AN = 0x00000001, /* Auto Negotiation */
223+
PORT_STATE_POLL_LT = 0x00000002 /* Link Trainig */
224+
} port_state_poll_t;
225+
220226
bool m_gearboxEnabled = false;
221227
map<int, gearbox_phy_t> m_gearboxPhyMap;
222228
map<int, gearbox_interface_t> m_gearboxInterfaceMap;
@@ -245,6 +251,8 @@ class PortsOrch : public Orch, public Subject
245251

246252
NotificationConsumer* m_portStatusNotificationConsumer;
247253

254+
swss::SelectableTimer *m_timer = nullptr;
255+
248256
void doTask() override;
249257
void doTask(Consumer &consumer);
250258
void doPortTask(Consumer &consumer);
@@ -254,6 +262,7 @@ class PortsOrch : public Orch, public Subject
254262
void doLagMemberTask(Consumer &consumer);
255263

256264
void doTask(NotificationConsumer &consumer);
265+
void doTask(swss::SelectableTimer &timer);
257266

258267
void removePortFromLanesMap(string alias);
259268
void removePortFromPortListMap(sai_object_id_t port_id);
@@ -286,6 +295,8 @@ class PortsOrch : public Orch, public Subject
286295
bool initPort(const string &alias, const string &role, const int index, const set<int> &lane_set);
287296
void deInitPort(string alias, sai_object_id_t port_id);
288297

298+
void initPortCapAutoNeg(Port &port);
299+
289300
bool setPortAdminStatus(Port &port, bool up);
290301
bool getPortAdminStatus(sai_object_id_t id, bool& up);
291302
bool setPortMtu(sai_object_id_t id, sai_uint32_t mtu);
@@ -306,6 +317,8 @@ class PortsOrch : public Orch, public Subject
306317
bool setGearboxPortsAttr(Port &port, sai_port_attr_t id, void *value);
307318
bool setGearboxPortAttr(Port &port, dest_port_type_t port_type, sai_port_attr_t id, void *value);
308319

320+
bool getPortAdvSpeeds(const Port& port, bool remote, std::vector<sai_uint32_t>& speed_list);
321+
bool getPortAdvSpeeds(const Port& port, bool remote, string& adv_speeds);
309322
task_process_status setPortAdvSpeeds(sai_object_id_t port_id, std::vector<sai_uint32_t>& speed_list);
310323

311324
bool getQueueTypeAndIndex(sai_object_id_t queue_id, string &type, uint8_t &index);
@@ -331,6 +344,9 @@ class PortsOrch : public Orch, public Subject
331344
bool getPortOperSpeed(const Port& port, sai_uint32_t& speed) const;
332345
void updateDbPortOperSpeed(Port &port, sai_uint32_t speed);
333346

347+
map<string, uint32_t> m_port_state_poll;
348+
void updatePortStateAutoNeg(const Port &port);
349+
334350
void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values);
335351
bool getPortAdvSpeedsVal(const std::string &s, std::vector<uint32_t> &speed_values);
336352
bool getPortInterfaceTypeVal(const std::string &s, sai_port_interface_type_t &interface_type);

0 commit comments

Comments
 (0)