Skip to content

Commit

Permalink
incorporate autoneg support from PR#2215
Browse files Browse the repository at this point in the history
Signed-off-by: Dante Su <[email protected]>
  • Loading branch information
ds952811 committed May 19, 2022
1 parent a04594e commit 55ced7d
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 10 deletions.
1 change: 1 addition & 0 deletions orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ class Port
bool m_fec_cfg = false;
bool m_an_cfg = false;

int m_cap_an = -1; /* Capability - AutoNeg, -1 means not set */
int m_cap_lt = -1; /* Capability - LinkTraining, -1 means not set */
};

Expand Down
123 changes: 113 additions & 10 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ extern string gMyAsicName;
#define DEFAULT_VLAN_ID 1
#define MAX_VALID_VLAN_ID 4094

#define PORT_SPEED_LIST_DEFAULT_SIZE 16
#define PORT_STATE_POLLING_SEC 5
#define PORT_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS 1000
#define PORT_BUFFER_DROP_STAT_POLLING_INTERVAL_MS 60000
Expand Down Expand Up @@ -1930,29 +1931,38 @@ void PortsOrch::initPortSupportedSpeeds(const std::string& alias, sai_object_id_
m_portStateTable.set(alias, v);
}

void PortsOrch::initPortCapAutoNeg(Port &port)
{
sai_status_t status;
sai_attribute_t attr;

attr.id = SAI_PORT_ATTR_SUPPORTED_AUTO_NEG_MODE;
status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr);
if (status == SAI_STATUS_SUCCESS)
{
port.m_cap_an = attr.value.booldata ? 1 : 0;
}
else
{
port.m_cap_an = 0;
SWSS_LOG_NOTICE("Unable to get %s AN capability", port.m_alias.c_str());
}
}

void PortsOrch::initPortCapLinkTraining(Port &port)
{
sai_status_t status;
sai_attribute_t attr;

#ifdef SAI_PORT_ATTR_SUPPORTED_LINK_TRAINING_MODE
attr.id = SAI_PORT_ATTR_SUPPORTED_LINK_TRAINING_MODE;
#else
/*
* Fallback to autoneg upon legacy SAI implementation
* In the case of SFP/QSFP ports, link-training is most likely available
* if autoneg is supported.
*/
attr.id = SAI_PORT_ATTR_SUPPORTED_AUTO_NEG_MODE;
#endif
status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr);
if (status == SAI_STATUS_SUCCESS)
{
port.m_cap_lt = attr.value.booldata ? 1 : 0;
}
else
{
port.m_cap_lt = 1; /* Default to 1 for vstest */
port.m_cap_lt = 0;
SWSS_LOG_NOTICE("Unable to get %s LT capability", port.m_alias.c_str());
}
}
Expand Down Expand Up @@ -2111,6 +2121,45 @@ bool PortsOrch::getPortSpeed(sai_object_id_t id, sai_uint32_t &speed)
return true;
}

bool PortsOrch::getPortAdvSpeeds(const Port& port, bool remote, std::vector<sai_uint32_t>& speed_list)
{
sai_object_id_t port_id = port.m_port_id;
sai_object_id_t line_port_id;
sai_attribute_t attr;
sai_status_t status;
std::vector<sai_uint32_t> speeds(PORT_SPEED_LIST_DEFAULT_SIZE);

attr.id = remote ? SAI_PORT_ATTR_REMOTE_ADVERTISED_SPEED : SAI_PORT_ATTR_ADVERTISED_SPEED;
attr.value.u32list.count = static_cast<uint32_t>(speeds.size());
attr.value.u32list.list = speeds.data();

if (getDestPortId(port_id, LINE_PORT_TYPE, line_port_id))
{
status = sai_port_api->get_port_attribute(line_port_id, 1, &attr);
}
else
{
status = sai_port_api->get_port_attribute(port_id, 1, &attr);
}
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_WARN("Unable to get advertised speed for %s", port.m_alias.c_str());
return false;
}
speeds.resize(attr.value.u32list.count);
speed_list.swap(speeds);
return true;
}

bool PortsOrch::getPortAdvSpeeds(const Port& port, bool remote, string& adv_speeds)
{
std::vector<sai_uint32_t> speed_list;
bool rc = getPortAdvSpeeds(port, remote, speed_list);

adv_speeds = rc ? swss::join(',', speed_list.begin(), speed_list.end()) : "";
return rc;
}

task_process_status PortsOrch::setPortAdvSpeeds(sai_object_id_t port_id, std::vector<sai_uint32_t>& speed_list)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -3015,6 +3064,18 @@ void PortsOrch::doPortTask(Consumer &consumer)
{
if (!an_str.empty())
{
if (p.m_cap_an < 0)
{
initPortCapAutoNeg(p);
m_portList[alias] = p;
}
if (p.m_cap_an < 1)
{
SWSS_LOG_ERROR("%s: autoneg is not supported", p.m_alias.c_str());
// Invalid auto negotiation mode configured, don't retry
it = consumer.m_toSync.erase(it);
continue;
}
if (autoneg_mode_map.find(an_str) == autoneg_mode_map.end())
{
SWSS_LOG_ERROR("Failed to parse autoneg value: %s", an_str.c_str());
Expand Down Expand Up @@ -3057,6 +3118,8 @@ void PortsOrch::doPortTask(Consumer &consumer)
SWSS_LOG_NOTICE("Set port %s AutoNeg from %d to %d", alias.c_str(), p.m_autoneg, an);
p.m_autoneg = an;
m_portList[alias] = p;
m_portStateTable.hdel(p.m_alias, "rmt_adv_speeds");
updatePortStatePoll(p, PORT_STATE_POLL_AN, (an > 0));
}
}

Expand Down Expand Up @@ -5949,6 +6012,20 @@ void PortsOrch::updatePortOperStatus(Port &port, sai_port_oper_status_t status)
if (port.m_type == Port::PHY)
{
updateDbPortOperStatus(port, status);
if (port.m_admin_state_up && port.m_autoneg > 0)
{
if (status == SAI_PORT_OPER_STATUS_UP)
{
updatePortStateAutoNeg(port);
updatePortStatePoll(port, PORT_STATE_POLL_AN, false);
}
else
{
/* Restart autoneg state polling upon link down event */
m_portStateTable.hdel(port.m_alias, "rmt_adv_speeds");
updatePortStatePoll(port, PORT_STATE_POLL_AN, true);
}
}
if (port.m_admin_state_up && port.m_link_training > 0)
{
updatePortStateLinkTraining(port);
Expand Down Expand Up @@ -7147,6 +7224,28 @@ bool PortsOrch::decrFdbCount(const std::string& alias, int count)
return true;
}

void PortsOrch::updatePortStateAutoNeg(const Port &port)
{
SWSS_LOG_ENTER();

if (port.m_type != Port::Type::PHY)
{
return;
}

string adv_speeds;

if (getPortAdvSpeeds(port, true, adv_speeds))
{
m_portStateTable.hset(port.m_alias, "rmt_adv_speeds", adv_speeds);
}
else
{
m_portStateTable.hset(port.m_alias, "rmt_adv_speeds", "N/A");
updatePortStatePoll(port, PORT_STATE_POLL_AN, false);
}
}

void PortsOrch::updatePortStateLinkTraining(const Port &port)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -7221,6 +7320,10 @@ void PortsOrch::doTask(swss::SelectableTimer &timer)
++it;
continue;
}
if (it->second & PORT_STATE_POLL_AN)
{
updatePortStateAutoNeg(port);
}
if (it->second & PORT_STATE_POLL_LT)
{
updatePortStateLinkTraining(port);
Expand Down
4 changes: 4 additions & 0 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ class PortsOrch : public Orch, public Subject
bool initPort(const string &alias, const string &role, const int index, const set<int> &lane_set);
void deInitPort(string alias, sai_object_id_t port_id);

void initPortCapAutoNeg(Port &port);
void initPortCapLinkTraining(Port &port);

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

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

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

map<string, uint32_t> m_port_state_poll;
void updatePortStatePoll(const Port &port, port_state_poll_t type, bool active);
void updatePortStateAutoNeg(const Port &port);
void updatePortStateLinkTraining(const Port &port);

void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values);
Expand Down
17 changes: 17 additions & 0 deletions tests/test_port_an.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,23 @@ def test_PortAutoNegWarm(self, dvs, testlog):
# slow down crm polling
dvs.crm_poll_set("10000")

def test_PortAutoNegRemoteAdvSpeeds(self, dvs, testlog):

cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0)
sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0)

ctbl = swsscommon.Table(cdb, "PORT")
stbl = swsscommon.Table(sdb, "PORT_TABLE")

# set autoneg = true and admin_status = up
fvs = swsscommon.FieldValuePairs([("autoneg","on"),("admin_status","up")])
ctbl.set("Ethernet0", fvs)

time.sleep(10)

(status, fvs) = stbl.get("Ethernet0")
assert status == True
assert "rmt_adv_speeds" in [fv[0] for fv in fvs]

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

0 comments on commit 55ced7d

Please sign in to comment.