Skip to content

Commit

Permalink
Add support for AN and FEC to be specified in port_config.ini (#534)
Browse files Browse the repository at this point in the history
* Add support for AN and FEC to be specified in port_config.ini

* do not set autoneg if it is already set

* set port adv speed for AN and add test

Signed-off-by: Guohan Lu <[email protected]>
  • Loading branch information
lguohan authored Jul 12, 2018
1 parent 7a2c61d commit 762e7da
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 31 deletions.
2 changes: 2 additions & 0 deletions orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class Port
int m_index = 0; // PHY_PORT: index
int m_ifindex = 0;
uint32_t m_mtu = DEFAULT_MTU;
uint32_t m_speed = 0; // Mbps
bool m_autoneg = 0;
sai_object_id_t m_port_id = 0;
sai_port_fec_mode_t m_fec_mode = SAI_PORT_FEC_MODE_NONE;
VlanInfo m_vlan_info;
Expand Down
166 changes: 138 additions & 28 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,6 @@ bool PortsOrch::isSpeedSupported(const std::string& alias, sai_object_id_t port_
bool PortsOrch::setPortSpeed(sai_object_id_t port_id, sai_uint32_t speed)
{
SWSS_LOG_ENTER();

sai_attribute_t attr;
sai_status_t status;

Expand Down Expand Up @@ -905,6 +904,23 @@ bool PortsOrch::getPortSpeed(sai_object_id_t port_id, sai_uint32_t &speed)
return status == SAI_STATUS_SUCCESS;
}

bool PortsOrch::setPortAdvSpeed(sai_object_id_t port_id, sai_uint32_t speed)
{
SWSS_LOG_ENTER();
sai_attribute_t attr;
sai_status_t status;
vector<sai_uint32_t> speeds;
speeds.push_back(speed);

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

status = sai_port_api->set_port_attribute(port_id, &attr);

return status == SAI_STATUS_SUCCESS;
}

bool PortsOrch::getQueueType(sai_object_id_t queue_id, string &type)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -938,6 +954,31 @@ bool PortsOrch::getQueueType(sai_object_id_t queue_id, string &type)
return true;
}

bool PortsOrch::setPortAutoNeg(sai_object_id_t id, int an)
{
SWSS_LOG_ENTER();

sai_attribute_t attr;
attr.id = SAI_PORT_ATTR_AUTO_NEG_MODE;
switch(an) {
case 1:
attr.value.booldata = true;
break;
default:
attr.value.booldata = false;
break;
}

sai_status_t status = sai_port_api->set_port_attribute(id, &attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to set AutoNeg %u to port pid:%lx", attr.value.booldata, id);
return false;
}
SWSS_LOG_INFO("Set AutoNeg %u to port pid:%lx", attr.value.booldata, id);
return true;
}

bool PortsOrch::setHostIntfsOperStatus(sai_object_id_t port_id, bool up)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -988,7 +1029,7 @@ void PortsOrch::updateDbPortOperStatus(sai_object_id_t id, sai_port_oper_status_
}
}

bool PortsOrch::addPort(const set<int> &lane_set, uint32_t speed)
bool PortsOrch::addPort(const set<int> &lane_set, uint32_t speed, int an, string fec_mode)
{
SWSS_LOG_ENTER();

Expand All @@ -1006,6 +1047,20 @@ bool PortsOrch::addPort(const set<int> &lane_set, uint32_t speed)
attr.value.u32list.count = static_cast<uint32_t>(lanes.size());
attrs.push_back(attr);

if (an == true)
{
attr.id = SAI_PORT_ATTR_AUTO_NEG_MODE;
attr.value.booldata = true;
attrs.push_back(attr);
}

if (!fec_mode.empty())
{
attr.id = SAI_PORT_ATTR_FEC_MODE;
attr.value.u32 = fec_mode_map[fec_mode];
attrs.push_back(attr);
}

sai_object_id_t port_id;
sai_status_t status = sai_port_api->create_port(&port_id, gSwitchId, static_cast<uint32_t>(attrs.size()), attrs.data());
if (status != SAI_STATUS_SUCCESS)
Expand Down Expand Up @@ -1165,6 +1220,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
string fec_mode;
uint32_t mtu = 0;
uint32_t speed = 0;
int an = -1;

for (auto i : kfvFieldsValues(t))
{
Expand All @@ -1179,6 +1235,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
int lane = stoi(lane_str);
lane_set.insert(lane);
}

}

/* Set port admin status */
Expand All @@ -1191,17 +1248,25 @@ void PortsOrch::doPortTask(Consumer &consumer)

/* Set port speed */
if (fvField(i) == "speed")
{
speed = (uint32_t)stoul(fvValue(i));
}

/* Set port fec */
if (fvField(i) == "fec")
fec_mode = fvValue(i);

/* Set autoneg and ignore the port speed setting */
if (fvField(i) == "autoneg")
{
an = (int)stoul(fvValue(i));
}
}

/* Collect information about all received ports */
if (lane_set.size())
{
m_lanesAliasSpeedMap[lane_set] = make_tuple(alias, speed);
m_lanesAliasSpeedMap[lane_set] = make_tuple(alias, speed, an, fec_mode);
}

/* Once all ports received, go through the each port and perform appropriate actions:
Expand Down Expand Up @@ -1247,7 +1312,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
char *platform = getenv("platform");
if (platform && strstr(platform, MLNX_PLATFORM_SUBSTRING))
{
if (!addPort(it->first, get<1>(it->second)))
if (!addPort(it->first, get<1>(it->second), get<2>(it->second), get<3>(it->second)))
{
throw runtime_error("PortsOrch initialization failure.");
}
Expand Down Expand Up @@ -1296,48 +1361,92 @@ void PortsOrch::doPortTask(Consumer &consumer)
}
else
{
/* Set port speed
if (an != -1 && an != p.m_autoneg)
{
if (setPortAutoNeg(p.m_port_id, an))
{
SWSS_LOG_NOTICE("Set port %s AutoNeg to %u", alias.c_str(), an);
p.m_autoneg = an;
m_portList[alias] = p;

/* Once AN is changed, need to reset the port speed or
port adv speed accordingly */
if (speed == 0 && p.m_speed != 0)
{
speed = p.m_speed;
}
}
else
{
SWSS_LOG_ERROR("Failed to set port %s AN to %u", alias.c_str(), an);
it++;
continue;
}
}

/*
* When AN is enabled, set the port adv speed, otherwise change the port speed.
*
* 1. Get supported speed list and validate if the target speed is within the list
* 2. Get the current port speed and check if it is the same as the target speed
* 3. Set port admin status to DOWN before changing the speed
* 4. Set port speed
*/
if (speed != 0)
{
sai_uint32_t current_speed;
p.m_speed = speed;
m_portList[alias] = p;

if (!isSpeedSupported(alias, p.m_port_id, speed))
if (p.m_autoneg)
{
it++;
continue;
if (setPortAdvSpeed(p.m_port_id, speed))
{
SWSS_LOG_NOTICE("Set port %s advertised speed to %u", alias.c_str(), speed);
}
else
{
SWSS_LOG_ERROR("Failed to set port %s advertised speed to %u", alias.c_str(), speed);
it++;
continue;
}
}

if (getPortSpeed(p.m_port_id, current_speed))
else
{
if (speed != current_speed)
sai_uint32_t current_speed;

if (!isSpeedSupported(alias, p.m_port_id, speed))
{
if (setPortAdminStatus(p.m_port_id, false))
it++;
continue;
}

if (getPortSpeed(p.m_port_id, current_speed))
{
if (speed != current_speed)
{
if (setPortSpeed(p.m_port_id, speed))
if (setPortAdminStatus(p.m_port_id, false))
{
SWSS_LOG_NOTICE("Set port %s speed to %u", alias.c_str(), speed);
if (setPortSpeed(p.m_port_id, speed))
{
SWSS_LOG_NOTICE("Set port %s speed to %u", alias.c_str(), speed);
}
else
{
SWSS_LOG_ERROR("Failed to set port %s speed to %u", alias.c_str(), speed);
it++;
continue;
}
}
else
{
SWSS_LOG_ERROR("Failed to set port %s speed to %u", alias.c_str(), speed);
it++;
continue;
SWSS_LOG_ERROR("Failed to set port admin status DOWN to set speed");
}
}
else
{
SWSS_LOG_ERROR("Failed to set port admin status DOWN to set speed");
}
}
}
else
{
SWSS_LOG_ERROR("Failed to get current speed for port %s", alias.c_str());
else
{
SWSS_LOG_ERROR("Failed to get current speed for port %s", alias.c_str());
}
}
}

Expand All @@ -1357,7 +1466,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
}
}

if (admin_status != "")
if (!admin_status.empty())
{
if (setPortAdminStatus(p.m_port_id, admin_status == "up"))
{
Expand All @@ -1371,7 +1480,8 @@ void PortsOrch::doPortTask(Consumer &consumer)
}
}

if (fec_mode != "")

if (!fec_mode.empty())
{
if (fec_mode_map.find(fec_mode) != fec_mode_map.end())
{
Expand Down
10 changes: 8 additions & 2 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

typedef std::vector<sai_uint32_t> PortSupportedSpeeds;


static const map<sai_port_oper_status_t, string> oper_status_strings =
{
{ SAI_PORT_OPER_STATUS_UNKNOWN, "unknown" },
Expand Down Expand Up @@ -90,7 +91,7 @@ class PortsOrch : public Orch, public Subject
bool m_portConfigDone = false;
sai_uint32_t m_portCount;
map<set<int>, sai_object_id_t> m_portListLaneMap;
map<set<int>, tuple<string, uint32_t>> m_lanesAliasSpeedMap;
map<set<int>, tuple<string, uint32_t, int, string>> m_lanesAliasSpeedMap;
map<string, Port> m_portList;

NotificationConsumer* m_portStatusNotificationConsumer;
Expand Down Expand Up @@ -128,7 +129,7 @@ class PortsOrch : public Orch, public Subject
bool removeLagMember(Port &lag, Port &port);
void getLagMember(Port &lag, vector<Port> &portv);

bool addPort(const set<int> &lane_set, uint32_t speed);
bool addPort(const set<int> &lane_set, uint32_t speed, int an=0, string fec="");
bool removePort(sai_object_id_t port_id);
bool initPort(const string &alias, const set<int> &lane_set);

Expand All @@ -144,10 +145,15 @@ class PortsOrch : public Orch, public Subject
bool setPortSpeed(sai_object_id_t port_id, sai_uint32_t speed);
bool getPortSpeed(sai_object_id_t port_id, sai_uint32_t &speed);

bool setPortAdvSpeed(sai_object_id_t port_id, sai_uint32_t speed);

bool getQueueType(sai_object_id_t queue_id, string &type);

bool m_isQueueMapGenerated = false;
void generateQueueMapPerPort(const Port& port);

bool setPortAutoNeg(sai_object_id_t id, int an);
bool setPortFecMode(sai_object_id_t id, int fec);
};
#endif /* SWSS_PORTSORCH_H */

14 changes: 13 additions & 1 deletion portsyncd/portsyncd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ void handlePortConfigFile(ProducerStateTable &p, string file)
throw "Port configuration file not found!";
}

list<string> header = {"name", "lanes", "alias", "speed"};
list<string> header = {"name", "lanes", "alias", "speed", "autoneg", "fec"};
string line;
while (getline(infile, line))
{
Expand Down Expand Up @@ -252,6 +252,18 @@ void handlePortConfigFile(ProducerStateTable &p, string file)
attrs.push_back(speed_attr);
}

if ((entry.find("autoneg") != entry.end()) && (entry["autoneg"] != ""))
{
FieldValueTuple autoneg_attr("autoneg", entry["autoneg"]);
attrs.push_back(autoneg_attr);
}

if ((entry.find("fec") != entry.end()) && (entry["fec"] != ""))
{
FieldValueTuple fec_attr("fec", entry["fec"]);
attrs.push_back(fec_attr);
}

p.set(entry["name"], attrs);

g_portSet.insert(entry["name"]);
Expand Down
Loading

0 comments on commit 762e7da

Please sign in to comment.