Skip to content

Commit

Permalink
Merge remote-tracking branch 'msft_github/master'
Browse files Browse the repository at this point in the history
* msft_github/master:
  [portsorch]: Use sai_serialize api to write to DB (sonic-net#331)
  [portsorch]: Update comments (sonic-net#333)
  [switchorch]: Add support of ECMP and LAG hash seed attribute (sonic-net#324)
  [portsorch]: Add support of cable breakout feature (sonic-net#320)
  • Loading branch information
Rodny Molina committed Oct 5, 2017
2 parents 63dbfde + 5dd5e36 commit 9483668
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 53 deletions.
199 changes: 164 additions & 35 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
#include <sstream>
#include <set>
#include <algorithm>
#include <tuple>

#include <netinet/if_ether.h>
#include "net/if.h"

#include "logger.h"
#include "schema.h"
#include "converter.h"
#include "saiserialize.h"

extern sai_switch_api_t *sai_switch_api;
extern sai_bridge_api_t *sai_bridge_api;
Expand Down Expand Up @@ -357,6 +360,7 @@ bool PortsOrch::validatePortSpeed(sai_object_id_t port_id, sai_uint32_t speed)
attr.id = SAI_PORT_ATTR_SUPPORTED_SPEED;
attr.value.u32list.count = 0;
attr.value.u32list.list = NULL;

status = sai_port_api->get_port_attribute(port_id, 1, &attr);
if (status == SAI_STATUS_BUFFER_OVERFLOW)
{
Expand Down Expand Up @@ -470,6 +474,105 @@ void PortsOrch::updateDbPortOperStatus(sai_object_id_t id, sai_port_oper_status_
}
}

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

vector<uint32_t> lanes(lane_set.begin(), lane_set.end());

sai_attribute_t attr;
vector<sai_attribute_t> attrs;

attr.id = SAI_PORT_ATTR_SPEED;
attr.value.u32 = speed;
attrs.push_back(attr);

attr.id = SAI_PORT_ATTR_HW_LANE_LIST;
attr.value.u32list.list = lanes.data();
attr.value.u32list.count = static_cast<uint32_t>(lanes.size());
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)
{
SWSS_LOG_ERROR("Failed to create port with the speed %u, rv:%d", speed, status);
return false;
}

m_portListLaneMap[lane_set] = port_id;

SWSS_LOG_NOTICE("Create port %lx with the speed %u", port_id, speed);

return true;
}

bool PortsOrch::removePort(sai_object_id_t port_id)
{
SWSS_LOG_ENTER();

sai_status_t status = sai_port_api->remove_port(port_id);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to remove port %lx, rv:%d", port_id, status);
return false;
}

SWSS_LOG_NOTICE("Remove port %lx", port_id);

return true;
}

bool PortsOrch::initPort(const string &alias, const set<int> &lane_set)
{
SWSS_LOG_ENTER();

/* Determine if the lane combination exists in switch */
if (m_portListLaneMap.find(lane_set) != m_portListLaneMap.end())
{
sai_object_id_t id = m_portListLaneMap[lane_set];

/* Determine if the port has already been initialized before */
if (m_portList.find(alias) != m_portList.end() && m_portList[alias].m_port_id == id)
{
SWSS_LOG_INFO("Port has already been initialized before alias:%s", alias.c_str());
}
else
{
Port p(alias, Port::PHY);

p.m_index = static_cast<int32_t>(m_portList.size()); // TODO: Assume no deletion of physical port
p.m_port_id = id;

/* Initialize the port and create corresponding host interface */
if (initializePort(p))
{
/* Add port to port list */
m_portList[alias] = p;
/* Add port name map to counter table */
FieldValueTuple tuple(p.m_alias, sai_serialize_object_id(p.m_port_id));
vector<FieldValueTuple> vector;
vector.push_back(tuple);
m_counterTable->set("", vector);

SWSS_LOG_NOTICE("Initialized port %s", alias.c_str());
}
else
{
SWSS_LOG_ERROR("Failed to initialize port %s", alias.c_str());
return false;
}
}
}
else
{
SWSS_LOG_ERROR("Failed to locate port lane combination alias:%s", alias.c_str());
return false;
}

return true;
}

void PortsOrch::doPortTask(Consumer &consumer)
{
SWSS_LOG_ENTER();
Expand All @@ -482,21 +585,34 @@ void PortsOrch::doPortTask(Consumer &consumer)
string alias = kfvKey(t);
string op = kfvOp(t);

if (alias == "PortConfigDone")
{
m_portConfigDone = true;

for (auto i : kfvFieldsValues(t))
{
if (fvField(i) == "count")
{
m_portCount = to_uint<uint32_t>(fvValue(i));
}
}
}

/* Get notification from application */
/* portsyncd application:
* When portsorch receives 'ConfigDone' message, it indicates port initialization
* When portsorch receives 'PortInitDone' message, it indicates port initialization
* procedure is done. Before port initialization procedure, none of other tasks
* are executed.
*/
if (alias == "ConfigDone")
if (alias == "PortInitDone")
{
/* portsyncd restarting case:
* When portsyncd restarts, duplicate notifications may be received.
*/
if (!m_initDone)
{
m_initDone = true;
SWSS_LOG_INFO("Get ConfigDone notification from portsyncd.");
SWSS_LOG_INFO("Get PortInitDone notification from portsyncd.");
}

it = consumer.m_toSync.erase(it);
Expand All @@ -523,7 +639,6 @@ void PortsOrch::doPortTask(Consumer &consumer)
int lane = stoi(lane_str);
lane_set.insert(lane);
}

}

/* Set port admin status */
Expand All @@ -539,47 +654,52 @@ void PortsOrch::doPortTask(Consumer &consumer)
speed = (uint32_t)stoul(fvValue(i));
}

/* Collect information about all received ports */
if (lane_set.size())
{
/* Determine if the lane combination exists in switch */
if (m_portListLaneMap.find(lane_set) !=
m_portListLaneMap.end())
{
sai_object_id_t id = m_portListLaneMap[lane_set];
m_lanesAliasSpeedMap[lane_set] = make_tuple(alias, speed);
}

/* Determin if the port has already been initialized before */
if (m_portList.find(alias) != m_portList.end() && m_portList[alias].m_port_id == id)
/* Once all ports received, go through the each port and perform appropriate actions:
* 1. Remove ports which don't exist anymore
* 2. Create new ports
* 3. Initialize all ports
*/
if (m_portConfigDone && (m_lanesAliasSpeedMap.size() == m_portCount))
{
for (auto it = m_portListLaneMap.begin(); it != m_portListLaneMap.end();)
{
if (m_lanesAliasSpeedMap.find(it->first) == m_lanesAliasSpeedMap.end())
{
SWSS_LOG_INFO("Port has already been initialized before alias:%s", alias.c_str());
if (!removePort(it->second))
{
throw runtime_error("PortsOrch initialization failure.");
}
it = m_portListLaneMap.erase(it);
}
else
{
Port p(alias, Port::PHY);

p.m_index = (uint32_t)m_portList.size(); // TODO: Assume no deletion of physical port
p.m_port_id = id;
it++;
}
}

/* Initialize the port and create router interface and host interface */
if (initializePort(p))
for (auto it = m_lanesAliasSpeedMap.begin(); it != m_lanesAliasSpeedMap.end();)
{
if (m_portListLaneMap.find(it->first) == m_portListLaneMap.end())
{
if (!addPort(it->first, get<1>(it->second)))
{
/* Add port to port list */
m_portList[alias] = p;
/* Add port name map to counter table */
std::stringstream ss;
ss << hex << p.m_port_id;
FieldValueTuple tuple(p.m_alias, ss.str());
vector<FieldValueTuple> vector;
vector.push_back(tuple);
m_counterTable->set("", vector);

SWSS_LOG_NOTICE("Initialized port %s", alias.c_str());
throw runtime_error("PortsOrch initialization failure.");
}
else
SWSS_LOG_ERROR("Failed to initialize port %s", alias.c_str());
}

if (!initPort(get<0>(it->second), it->first))
{
throw runtime_error("PortsOrch initialization failure.");
}

it = m_lanesAliasSpeedMap.erase(it);
}
else
SWSS_LOG_ERROR("Failed to locate port lane combination alias:%s", alias.c_str());
}

Port p;
Expand All @@ -589,6 +709,12 @@ void PortsOrch::doPortTask(Consumer &consumer)
}
else
{
/* Set 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;
Expand All @@ -604,7 +730,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
{
if (speed != current_speed)
{
if(setPortAdminStatus(p.m_port_id, false))
if (setPortAdminStatus(p.m_port_id, false))
{
if (setPortSpeed(p.m_port_id, speed))
{
Expand All @@ -627,13 +753,14 @@ void PortsOrch::doPortTask(Consumer &consumer)
{
SWSS_LOG_ERROR("Failed to get current speed for port %s", alias.c_str());
}

}

if (admin_status != "")
{
if (setPortAdminStatus(p.m_port_id, admin_status == "up"))
{
SWSS_LOG_NOTICE("Set port %s admin status to %s", alias.c_str(), admin_status.c_str());
}
else
{
SWSS_LOG_ERROR("Failed to set port %s admin status to %s", alias.c_str(), admin_status.c_str());
Expand All @@ -645,7 +772,9 @@ void PortsOrch::doPortTask(Consumer &consumer)
if (mtu != 0)
{
if (setPortMtu(p.m_port_id, mtu))
{
SWSS_LOG_NOTICE("Set port %s MTU to %u", alias.c_str(), mtu);
}
else
{
SWSS_LOG_ERROR("Failed to set port %s MTU to %u", alias.c_str(), mtu);
Expand Down
6 changes: 6 additions & 0 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ class PortsOrch : public Orch, public Subject
sai_object_id_t m_default1QBridge;
sai_object_id_t m_defaultVlan;

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<string, Port> m_portList;

void doTask(Consumer &consumer);
Expand Down Expand Up @@ -100,6 +102,10 @@ class PortsOrch : public Orch, public Subject
bool addLagMember(Port lag, Port port);
bool removeLagMember(Port lag, Port port);

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

bool setPortAdminStatus(sai_object_id_t id, bool up);
bool setPortMtu(sai_object_id_t id, sai_uint32_t mtu);

Expand Down
36 changes: 28 additions & 8 deletions orchagent/switchorch.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <map>

#include "switchorch.h"
#include "converter.h"

using namespace std;
using namespace swss;
Expand All @@ -12,7 +13,9 @@ const map<string, sai_switch_attr_t> switch_attribute_map =
{
{"fdb_unicast_miss_packet_action", SAI_SWITCH_ATTR_FDB_UNICAST_MISS_PACKET_ACTION},
{"fdb_broadcast_miss_packet_action", SAI_SWITCH_ATTR_FDB_BROADCAST_MISS_PACKET_ACTION},
{"fdb_multicast_miss_packet_action", SAI_SWITCH_ATTR_FDB_MULTICAST_MISS_PACKET_ACTION}
{"fdb_multicast_miss_packet_action", SAI_SWITCH_ATTR_FDB_MULTICAST_MISS_PACKET_ACTION},
{"ecmp_hash_seed", SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_SEED},
{"lag_hash_seed", SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_SEED}
};

const map<string, sai_packet_action_t> packet_action_map =
Expand Down Expand Up @@ -52,16 +55,32 @@ void SwitchOrch::doTask(Consumer &consumer)
}

auto value = fvValue(i);
if (packet_action_map.find(value) == packet_action_map.end())
{
SWSS_LOG_ERROR("Unsupported packet action %s", value.c_str());
it = consumer.m_toSync.erase(it);
continue;
}

sai_attribute_t attr;
attr.id = switch_attribute_map.at(attribute);
attr.value.s32 = packet_action_map.at(value);

switch (attr.id)
{
case SAI_SWITCH_ATTR_FDB_UNICAST_MISS_PACKET_ACTION:
case SAI_SWITCH_ATTR_FDB_BROADCAST_MISS_PACKET_ACTION:
case SAI_SWITCH_ATTR_FDB_MULTICAST_MISS_PACKET_ACTION:
if (packet_action_map.find(value) == packet_action_map.end())
{
SWSS_LOG_ERROR("Unsupported packet action %s", value.c_str());
it = consumer.m_toSync.erase(it);
continue;
}
attr.value.s32 = packet_action_map.at(value);
break;

case SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_SEED:
case SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_SEED:
attr.value.u32 = to_uint<uint32_t>(value);
break;

default:
break;
}

sai_status_t status = sai_switch_api->set_switch_attribute(gSwitchId, &attr);
if (status != SAI_STATUS_SUCCESS)
Expand All @@ -83,3 +102,4 @@ void SwitchOrch::doTask(Consumer &consumer)
}
}
}

Loading

0 comments on commit 9483668

Please sign in to comment.