Skip to content

Commit 55ced7d

Browse files
committed
incorporate autoneg support from PR#2215
Signed-off-by: Dante Su <[email protected]>
1 parent a04594e commit 55ced7d

File tree

4 files changed

+135
-10
lines changed

4 files changed

+135
-10
lines changed

orchagent/port.h

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ class Port
180180
bool m_fec_cfg = false;
181181
bool m_an_cfg = false;
182182

183+
int m_cap_an = -1; /* Capability - AutoNeg, -1 means not set */
183184
int m_cap_lt = -1; /* Capability - LinkTraining, -1 means not set */
184185
};
185186

orchagent/portsorch.cpp

+113-10
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_SPEED_LIST_DEFAULT_SIZE 16
6465
#define PORT_STATE_POLLING_SEC 5
6566
#define PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000
6667
#define PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS 60000
@@ -1930,29 +1931,38 @@ void PortsOrch::initPortSupportedSpeeds(const std::string& alias, sai_object_id_
19301931
m_portStateTable.set(alias, v);
19311932
}
19321933

1934+
void PortsOrch::initPortCapAutoNeg(Port &port)
1935+
{
1936+
sai_status_t status;
1937+
sai_attribute_t attr;
1938+
1939+
attr.id = SAI_PORT_ATTR_SUPPORTED_AUTO_NEG_MODE;
1940+
status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr);
1941+
if (status == SAI_STATUS_SUCCESS)
1942+
{
1943+
port.m_cap_an = attr.value.booldata ? 1 : 0;
1944+
}
1945+
else
1946+
{
1947+
port.m_cap_an = 0;
1948+
SWSS_LOG_NOTICE("Unable to get %s AN capability", port.m_alias.c_str());
1949+
}
1950+
}
1951+
19331952
void PortsOrch::initPortCapLinkTraining(Port &port)
19341953
{
19351954
sai_status_t status;
19361955
sai_attribute_t attr;
19371956

1938-
#ifdef SAI_PORT_ATTR_SUPPORTED_LINK_TRAINING_MODE
19391957
attr.id = SAI_PORT_ATTR_SUPPORTED_LINK_TRAINING_MODE;
1940-
#else
1941-
/*
1942-
* Fallback to autoneg upon legacy SAI implementation
1943-
* In the case of SFP/QSFP ports, link-training is most likely available
1944-
* if autoneg is supported.
1945-
*/
1946-
attr.id = SAI_PORT_ATTR_SUPPORTED_AUTO_NEG_MODE;
1947-
#endif
19481958
status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr);
19491959
if (status == SAI_STATUS_SUCCESS)
19501960
{
19511961
port.m_cap_lt = attr.value.booldata ? 1 : 0;
19521962
}
19531963
else
19541964
{
1955-
port.m_cap_lt = 1; /* Default to 1 for vstest */
1965+
port.m_cap_lt = 0;
19561966
SWSS_LOG_NOTICE("Unable to get %s LT capability", port.m_alias.c_str());
19571967
}
19581968
}
@@ -2111,6 +2121,45 @@ bool PortsOrch::getPortSpeed(sai_object_id_t id, sai_uint32_t &speed)
21112121
return true;
21122122
}
21132123

2124+
bool PortsOrch::getPortAdvSpeeds(const Port& port, bool remote, std::vector<sai_uint32_t>& speed_list)
2125+
{
2126+
sai_object_id_t port_id = port.m_port_id;
2127+
sai_object_id_t line_port_id;
2128+
sai_attribute_t attr;
2129+
sai_status_t status;
2130+
std::vector<sai_uint32_t> speeds(PORT_SPEED_LIST_DEFAULT_SIZE);
2131+
2132+
attr.id = remote ? SAI_PORT_ATTR_REMOTE_ADVERTISED_SPEED : SAI_PORT_ATTR_ADVERTISED_SPEED;
2133+
attr.value.u32list.count = static_cast<uint32_t>(speeds.size());
2134+
attr.value.u32list.list = speeds.data();
2135+
2136+
if (getDestPortId(port_id, LINE_PORT_TYPE, line_port_id))
2137+
{
2138+
status = sai_port_api->get_port_attribute(line_port_id, 1, &attr);
2139+
}
2140+
else
2141+
{
2142+
status = sai_port_api->get_port_attribute(port_id, 1, &attr);
2143+
}
2144+
if (status != SAI_STATUS_SUCCESS)
2145+
{
2146+
SWSS_LOG_WARN("Unable to get advertised speed for %s", port.m_alias.c_str());
2147+
return false;
2148+
}
2149+
speeds.resize(attr.value.u32list.count);
2150+
speed_list.swap(speeds);
2151+
return true;
2152+
}
2153+
2154+
bool PortsOrch::getPortAdvSpeeds(const Port& port, bool remote, string& adv_speeds)
2155+
{
2156+
std::vector<sai_uint32_t> speed_list;
2157+
bool rc = getPortAdvSpeeds(port, remote, speed_list);
2158+
2159+
adv_speeds = rc ? swss::join(',', speed_list.begin(), speed_list.end()) : "";
2160+
return rc;
2161+
}
2162+
21142163
task_process_status PortsOrch::setPortAdvSpeeds(sai_object_id_t port_id, std::vector<sai_uint32_t>& speed_list)
21152164
{
21162165
SWSS_LOG_ENTER();
@@ -3015,6 +3064,18 @@ void PortsOrch::doPortTask(Consumer &consumer)
30153064
{
30163065
if (!an_str.empty())
30173066
{
3067+
if (p.m_cap_an < 0)
3068+
{
3069+
initPortCapAutoNeg(p);
3070+
m_portList[alias] = p;
3071+
}
3072+
if (p.m_cap_an < 1)
3073+
{
3074+
SWSS_LOG_ERROR("%s: autoneg is not supported", p.m_alias.c_str());
3075+
// Invalid auto negotiation mode configured, don't retry
3076+
it = consumer.m_toSync.erase(it);
3077+
continue;
3078+
}
30183079
if (autoneg_mode_map.find(an_str) == autoneg_mode_map.end())
30193080
{
30203081
SWSS_LOG_ERROR("Failed to parse autoneg value: %s", an_str.c_str());
@@ -3057,6 +3118,8 @@ void PortsOrch::doPortTask(Consumer &consumer)
30573118
SWSS_LOG_NOTICE("Set port %s AutoNeg from %d to %d", alias.c_str(), p.m_autoneg, an);
30583119
p.m_autoneg = an;
30593120
m_portList[alias] = p;
3121+
m_portStateTable.hdel(p.m_alias, "rmt_adv_speeds");
3122+
updatePortStatePoll(p, PORT_STATE_POLL_AN, (an > 0));
30603123
}
30613124
}
30623125

@@ -5949,6 +6012,20 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status)
59496012
if (port.m_type == Port::PHY)
59506013
{
59516014
updateDbPortOperStatus(port, status);
6015+
if (port.m_admin_state_up && port.m_autoneg > 0)
6016+
{
6017+
if (status == SAI_PORT_OPER_STATUS_UP)
6018+
{
6019+
updatePortStateAutoNeg(port);
6020+
updatePortStatePoll(port, PORT_STATE_POLL_AN, false);
6021+
}
6022+
else
6023+
{
6024+
/* Restart autoneg state polling upon link down event */
6025+
m_portStateTable.hdel(port.m_alias, "rmt_adv_speeds");
6026+
updatePortStatePoll(port, PORT_STATE_POLL_AN, true);
6027+
}
6028+
}
59526029
if (port.m_admin_state_up && port.m_link_training > 0)
59536030
{
59546031
updatePortStateLinkTraining(port);
@@ -7147,6 +7224,28 @@ bool PortsOrch::decrFdbCount(const std::string& alias, int count)
71477224
return true;
71487225
}
71497226

7227+
void PortsOrch::updatePortStateAutoNeg(const Port &port)
7228+
{
7229+
SWSS_LOG_ENTER();
7230+
7231+
if (port.m_type != Port::Type::PHY)
7232+
{
7233+
return;
7234+
}
7235+
7236+
string adv_speeds;
7237+
7238+
if (getPortAdvSpeeds(port, true, adv_speeds))
7239+
{
7240+
m_portStateTable.hset(port.m_alias, "rmt_adv_speeds", adv_speeds);
7241+
}
7242+
else
7243+
{
7244+
m_portStateTable.hset(port.m_alias, "rmt_adv_speeds", "N/A");
7245+
updatePortStatePoll(port, PORT_STATE_POLL_AN, false);
7246+
}
7247+
}
7248+
71507249
void PortsOrch::updatePortStateLinkTraining(const Port &port)
71517250
{
71527251
SWSS_LOG_ENTER();
@@ -7221,6 +7320,10 @@ void PortsOrch::doTask(swss::SelectableTimer &timer)
72217320
++it;
72227321
continue;
72237322
}
7323+
if (it->second & PORT_STATE_POLL_AN)
7324+
{
7325+
updatePortStateAutoNeg(port);
7326+
}
72247327
if (it->second & PORT_STATE_POLL_LT)
72257328
{
72267329
updatePortStateLinkTraining(port);

orchagent/portsorch.h

+4
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ class PortsOrch : public Orch, public Subject
293293
bool initPort(const string &alias, const string &role, const int index, const set<int> &lane_set);
294294
void deInitPort(string alias, sai_object_id_t port_id);
295295

296+
void initPortCapAutoNeg(Port &port);
296297
void initPortCapLinkTraining(Port &port);
297298

298299
bool setPortAdminStatus(Port &port, bool up);
@@ -315,6 +316,8 @@ class PortsOrch : public Orch, public Subject
315316
bool setGearboxPortsAttr(Port &port, sai_port_attr_t id, void *value);
316317
bool setGearboxPortAttr(Port &port, dest_port_type_t port_type, sai_port_attr_t id, void *value);
317318

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

320323
bool getQueueTypeAndIndex(sai_object_id_t queue_id, string &type, uint8_t &index);
@@ -352,6 +355,7 @@ class PortsOrch : public Orch, public Subject
352355

353356
map<string, uint32_t> m_port_state_poll;
354357
void updatePortStatePoll(const Port &port, port_state_poll_t type, bool active);
358+
void updatePortStateAutoNeg(const Port &port);
355359
void updatePortStateLinkTraining(const Port &port);
356360

357361
void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values);

tests/test_port_an.py

+17
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,23 @@ def test_PortAutoNegWarm(self, dvs, testlog):
293293
# slow down crm polling
294294
dvs.crm_poll_set("10000")
295295

296+
def test_PortAutoNegRemoteAdvSpeeds(self, dvs, testlog):
297+
298+
cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0)
299+
sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0)
300+
301+
ctbl = swsscommon.Table(cdb, "PORT")
302+
stbl = swsscommon.Table(sdb, "PORT_TABLE")
303+
304+
# set autoneg = true and admin_status = up
305+
fvs = swsscommon.FieldValuePairs([("autoneg","on"),("admin_status","up")])
306+
ctbl.set("Ethernet0", fvs)
307+
308+
time.sleep(10)
309+
310+
(status, fvs) = stbl.get("Ethernet0")
311+
assert status == True
312+
assert "rmt_adv_speeds" in [fv[0] for fv in fvs]
296313

297314
# Add Dummy always-pass test at end as workaroud
298315
# for issue when Flaky fail on final test it invokes module tear-down before retrying

0 commit comments

Comments
 (0)