Skip to content

Commit

Permalink
Add support for port fec setting (sonic-net#365)
Browse files Browse the repository at this point in the history
Signed-off-by: Jipan Yang <jipan.yang@alibaba-inc.com>
  • Loading branch information
jipanyang authored and lguohan committed Nov 1, 2017
1 parent f90a4e1 commit 7d39a8b
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 0 deletions.
1 change: 1 addition & 0 deletions orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Port
int m_index = 0; // PHY_PORT: index
int m_ifindex = 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;
sai_object_id_t m_bridge_port_id = 0; // TODO: port could have multiple bridge port IDs
sai_vlan_id_t m_port_vlan_id = DEFAULT_PORT_VLAN_ID; // Port VLAN ID
Expand Down
60 changes: 60 additions & 0 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ extern sai_object_id_t gSwitchId;
#define VLAN_PREFIX "Vlan"
#define DEFAULT_VLAN_ID 1

static map<string, sai_port_fec_mode_t> fec_mode_map =
{
{ "none", SAI_PORT_FEC_MODE_NONE },
{ "rs", SAI_PORT_FEC_MODE_RS },
{ "fc", SAI_PORT_FEC_MODE_FC }
};

/*
* Initialize PortsOrch
* 0) By default, a switch has one CPU port, one 802.1Q bridge, and one default
Expand Down Expand Up @@ -356,6 +363,26 @@ bool PortsOrch::setPortMtu(sai_object_id_t id, sai_uint32_t mtu)
return true;
}

bool PortsOrch::setPortFec(sai_object_id_t id, sai_port_fec_mode_t mode)
{
SWSS_LOG_ENTER();

sai_attribute_t attr;
attr.id = SAI_PORT_ATTR_FEC_MODE;
attr.value.s32 = mode;

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

bool PortsOrch::setPortPvid(Port &port, sai_uint32_t pvid)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -688,6 +715,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
{
set<int> lane_set;
string admin_status;
string fec_mode;
uint32_t mtu = 0;
uint32_t speed = 0;

Expand Down Expand Up @@ -717,6 +745,10 @@ 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);
}

/* Collect information about all received ports */
Expand Down Expand Up @@ -883,6 +915,34 @@ void PortsOrch::doPortTask(Consumer &consumer)
continue;
}
}

if (fec_mode != "")
{
if (fec_mode_map.find(fec_mode) != fec_mode_map.end())
{
/* reset fec mode upon mode change */
if (p.m_fec_mode != fec_mode_map[fec_mode])
{
p.m_fec_mode = fec_mode_map[fec_mode];
if (setPortFec(p.m_port_id, p.m_fec_mode))
{
m_portList[alias] = p;
SWSS_LOG_NOTICE("Set port %s fec to %s", alias.c_str(), fec_mode.c_str());
}
else
{
SWSS_LOG_ERROR("Failed to set port %s fec to %s", alias.c_str(), fec_mode.c_str());
it++;
continue;
}
}
}
else
{
SWSS_LOG_ERROR("Unknown fec mode %s", fec_mode.c_str());
}

}
}
}
else
Expand Down
1 change: 1 addition & 0 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class PortsOrch : public Orch, public Subject
bool setPortMtu(sai_object_id_t id, sai_uint32_t mtu);
bool setPortPvid (Port &port, sai_uint32_t pvid);
bool getPortPvid(Port &port, sai_uint32_t &pvid);
bool setPortFec(sai_object_id_t id, sai_port_fec_mode_t mode);

bool setBridgePortAdminStatus(sai_object_id_t id, bool up);

Expand Down
58 changes: 58 additions & 0 deletions portsyncd/portsyncd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "netlink.h"
#include "producerstatetable.h"
#include "portsyncd/linksync.h"
#include "subscriberstatetable.h"

#define DEFAULT_PORT_CONFIG_FILE "port_config.ini"

Expand Down Expand Up @@ -41,12 +42,14 @@ void usage()

void handlePortConfigFile(ProducerStateTable &p, string file);
void handleVlanIntfFile(string file);
void handlePortConfig(ProducerStateTable &p, map<string, KeyOpFieldsValuesTuple> &port_cfg_map);

int main(int argc, char **argv)
{
Logger::linkToDbNative("portsyncd");
int opt;
string port_config_file = DEFAULT_PORT_CONFIG_FILE;
map<string, KeyOpFieldsValuesTuple> port_cfg_map;

while ((opt = getopt(argc, argv, "p:v:h")) != -1 )
{
Expand All @@ -64,9 +67,11 @@ int main(int argc, char **argv)
}
}

DBConnector cfgDb(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
DBConnector appl_db(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
DBConnector state_db(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
ProducerStateTable p(&appl_db, APP_PORT_TABLE_NAME);
SubscriberStateTable portCfg(&cfgDb, CFG_PORT_TABLE_NAME);

LinkSync sync(&appl_db, &state_db);
NetDispatcher::getInstance().registerMessageHandler(RTM_NEWLINK, &sync);
Expand All @@ -84,6 +89,7 @@ int main(int argc, char **argv)
handlePortConfigFile(p, port_config_file);

s.addSelectable(&netlink);
s.addSelectable(&portCfg);
while (true)
{
Selectable *temps;
Expand Down Expand Up @@ -113,6 +119,29 @@ int main(int argc, char **argv)

g_init = true;
}
if (!port_cfg_map.empty())
{
handlePortConfig(p, port_cfg_map);
}
}

if (temps == (Selectable *)&portCfg)
{
std::deque<KeyOpFieldsValuesTuple> entries;
portCfg.pops(entries);

for (auto entry: entries)
{
string key = kfvKey(entry);

if (port_cfg_map.find(key) != port_cfg_map.end())
{
/* For now we simply drop previous pending port config */
port_cfg_map.erase(key);
}
port_cfg_map[key] = entry;
}
handlePortConfig(p, port_cfg_map);
}
}
}
Expand Down Expand Up @@ -203,3 +232,32 @@ void handlePortConfigFile(ProducerStateTable &p, string file)
vector<FieldValueTuple> attrs = { finish_notice };
p.set("PortConfigDone", attrs);
}

void handlePortConfig(ProducerStateTable &p, map<string, KeyOpFieldsValuesTuple> &port_cfg_map)
{

auto it = port_cfg_map.begin();
while (it != port_cfg_map.end())
{
KeyOpFieldsValuesTuple entry = it->second;
string key = kfvKey(entry);
string op = kfvOp(entry);
auto values = kfvFieldsValues(entry);

/* only push down port config when port is not in hostif create pending state */
if (g_portSet.find(key) == g_portSet.end())
{
/* No support for port delete yet */
if (op == SET_COMMAND)
{
p.set(key, values);
}

it = port_cfg_map.erase(it);
}
else
{
it++;
}
}
}

0 comments on commit 7d39a8b

Please sign in to comment.