From 1ef3e818975962770dd3cb0cad28fb260e5693fe Mon Sep 17 00:00:00 2001 From: Volodymyr Samotiy Date: Wed, 16 Aug 2017 15:25:37 +0300 Subject: [PATCH 1/3] [portsorch]: Add support of cable breakout feature --- orchagent/portsorch.cpp | 179 +++++++++++++++++++++++++++++++++------- orchagent/portsorch.h | 6 ++ portsyncd/portsyncd.cpp | 51 ++++++++++-- 3 files changed, 199 insertions(+), 37 deletions(-) diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index eb96c1239ad..3962be1cffd 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "net/if.h" @@ -461,6 +462,107 @@ void PortsOrch::updateDbPortOperStatus(sai_object_id_t id, sai_port_oper_status_ } } +bool PortsOrch::createPort(const set &lane_set, uint32_t speed) +{ + SWSS_LOG_ENTER(); + + vector lanes(lane_set.begin(), lane_set.end()); + + sai_attribute_t attr; + vector 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 = lanes.size(); + attrs.push_back(attr); + + sai_object_id_t port_id; + sai_status_t status = sai_port_api->create_port(&port_id, gSwitchId, 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_INFO("Create port %lx with the speed %u", port_id, speed); + + return true; +} + +bool PortsOrch::removePort(const set &lane_set) +{ + SWSS_LOG_ENTER(); + + sai_status_t status = sai_port_api->remove_port(m_portListLaneMap[lane_set]); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to remove port %lx, rv:%d", m_portListLaneMap[lane_set], status); + return false; + } + + SWSS_LOG_INFO("Remove port %lx", m_portListLaneMap[lane_set]); + + return true; +} + +bool PortsOrch::initPort(const string &alias, const set &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 = m_portList.size(); // TODO: Assume no deletion of physical port + p.m_port_id = id; + + /* Initialize the port and create router interface and host interface */ + if (initializePort(p)) + { + /* 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 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(); @@ -473,6 +575,19 @@ 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 = stoul(fvValue(i)); + } + } + } + /* Get notification from application */ /* portsyncd application: * When portsorch receives 'ConfigDone' message, it indicates port initialization @@ -514,7 +629,6 @@ void PortsOrch::doPortTask(Consumer &consumer) int lane = stoi(lane_str); lane_set.insert(lane); } - } /* Set port admin status */ @@ -530,47 +644,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->first)) + { + 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 (!createPort(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 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; diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index b5e78297e27..77bf64fb8d5 100644 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -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, sai_object_id_t> m_portListLaneMap; + map, tuple> m_lanesALiasSpeedMap; map m_portList; void doTask(Consumer &consumer); @@ -100,6 +102,10 @@ class PortsOrch : public Orch, public Subject bool addLagMember(Port lag, Port port); bool removeLagMember(Port lag, Port port); + bool createPort(const set &lane_set, uint32_t speed); + bool removePort(const set &lane_set); + bool initPort(const string &alias, const set &lane_set); + bool setPortAdminStatus(sai_object_id_t id, bool up); bool setPortMtu(sai_object_id_t id, sai_uint32_t mtu); diff --git a/portsyncd/portsyncd.cpp b/portsyncd/portsyncd.cpp index f10c03ba6bb..aaa353a6590 100644 --- a/portsyncd/portsyncd.cpp +++ b/portsyncd/portsyncd.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "dbconnector.h" #include "select.h" #include "netdispatcher.h" @@ -134,34 +135,70 @@ void handlePortConfigFile(ProducerStateTable &p, string file) throw "Port configuration file not found!"; } + list header = {"name", "lanes", "alias", "speed"}; string line; while (getline(infile, line)) { if (line.at(0) == '#') { + /* Find out what info is specified in the configuration file */ + for (auto it = header.begin(); it != header.end();) + { + if (line.find(*it) == string::npos) + { + it = header.erase(it); + } + else + { + ++it; + } + } + continue; } istringstream iss(line); - string name, lanes, alias; - iss >> name >> lanes >> alias; + map entry; + + /* Read port configuration entry */ + for (auto column : header) + { + iss >> entry[column]; + } /* If port has no alias, then use its' name as alias */ - if (alias == "") + string alias; + if ((entry.find("alias") != entry.end()) && (entry["alias"] != "")) + { + alias = entry["alias"]; + } + else { - alias = name; + alias = entry["name"]; } - FieldValueTuple lanes_attr("lanes", lanes); + + FieldValueTuple lanes_attr("lanes", entry["lanes"]); FieldValueTuple alias_attr("alias", alias); vector attrs; attrs.push_back(lanes_attr); attrs.push_back(alias_attr); - p.set(name, attrs); + if ((entry.find("speed") != entry.end()) && (entry["speed"] != "")) + { + FieldValueTuple speed_attr("speed", entry["speed"]); + attrs.push_back(speed_attr); + } - g_portSet.insert(name); + p.set(entry["name"], attrs); + + g_portSet.insert(entry["name"]); } infile.close(); + + /* Notify that all ports added */ + FieldValueTuple finish_notice("count", to_string(g_portSet.size())); + vector attrs = { finish_notice }; + p.set("PortConfigDone", attrs); } From 3432121ed21013d884d75a40a57b8e09eb00b5fb Mon Sep 17 00:00:00 2001 From: Volodymyr Samotiy Date: Wed, 6 Sep 2017 16:16:13 +0300 Subject: [PATCH 2/3] [portsorch]: Add support of cable breakout feature * Fix comments --- orchagent/portsorch.cpp | 24 ++++++++++++------------ orchagent/portsorch.h | 4 ++-- portsyncd/portsyncd.cpp | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 3962be1cffd..fe0f56dd65b 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -462,7 +462,7 @@ void PortsOrch::updateDbPortOperStatus(sai_object_id_t id, sai_port_oper_status_ } } -bool PortsOrch::createPort(const set &lane_set, uint32_t speed) +bool PortsOrch::addPort(const set &lane_set, uint32_t speed) { SWSS_LOG_ENTER(); @@ -490,7 +490,7 @@ bool PortsOrch::createPort(const set &lane_set, uint32_t speed) m_portListLaneMap[lane_set] = port_id; - SWSS_LOG_INFO("Create port %lx with the speed %u", port_id, speed); + SWSS_LOG_NOTICE("Create port %lx with the speed %u", port_id, speed); return true; } @@ -506,7 +506,7 @@ bool PortsOrch::removePort(const set &lane_set) return false; } - SWSS_LOG_INFO("Remove port %lx", m_portListLaneMap[lane_set]); + SWSS_LOG_NOTICE("Remove port %lx", m_portListLaneMap[lane_set]); return true; } @@ -590,11 +590,11 @@ void PortsOrch::doPortTask(Consumer &consumer) /* 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. @@ -602,7 +602,7 @@ void PortsOrch::doPortTask(Consumer &consumer) 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); @@ -647,7 +647,7 @@ void PortsOrch::doPortTask(Consumer &consumer) /* 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); } /* Once all ports received, go through the each port and perform appropriate actions: @@ -655,11 +655,11 @@ void PortsOrch::doPortTask(Consumer &consumer) * 2. Create new ports * 3. Initialize all ports */ - if (m_portConfigDone && (m_lanesALiasSpeedMap.size() == m_portCount)) + 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()) + if (m_lanesAliasSpeedMap.find(it->first) == m_lanesAliasSpeedMap.end()) { if (!removePort(it->first)) { @@ -673,11 +673,11 @@ void PortsOrch::doPortTask(Consumer &consumer) } } - for (auto it = m_lanesALiasSpeedMap.begin(); it != m_lanesALiasSpeedMap.end();) + for (auto it = m_lanesAliasSpeedMap.begin(); it != m_lanesAliasSpeedMap.end();) { if (m_portListLaneMap.find(it->first) == m_portListLaneMap.end()) { - if (!createPort(it->first, get<1>(it->second))) + if (!addPort(it->first, get<1>(it->second))) { throw runtime_error("PortsOrch initialization failure."); } @@ -688,7 +688,7 @@ void PortsOrch::doPortTask(Consumer &consumer) throw runtime_error("PortsOrch initialization failure."); } - it = m_lanesALiasSpeedMap.erase(it); + it = m_lanesAliasSpeedMap.erase(it); } } diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 77bf64fb8d5..a5f8ec39867 100644 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -70,7 +70,7 @@ class PortsOrch : public Orch, public Subject bool m_portConfigDone = false; sai_uint32_t m_portCount; map, sai_object_id_t> m_portListLaneMap; - map, tuple> m_lanesALiasSpeedMap; + map, tuple> m_lanesAliasSpeedMap; map m_portList; void doTask(Consumer &consumer); @@ -102,7 +102,7 @@ class PortsOrch : public Orch, public Subject bool addLagMember(Port lag, Port port); bool removeLagMember(Port lag, Port port); - bool createPort(const set &lane_set, uint32_t speed); + bool addPort(const set &lane_set, uint32_t speed); bool removePort(const set &lane_set); bool initPort(const string &alias, const set &lane_set); diff --git a/portsyncd/portsyncd.cpp b/portsyncd/portsyncd.cpp index aaa353a6590..c62550fd7f3 100644 --- a/portsyncd/portsyncd.cpp +++ b/portsyncd/portsyncd.cpp @@ -25,7 +25,7 @@ using namespace swss; * interfaces are already created and remove them from this set. We will * remove the rest of the ports in the set when receiving the first netlink * message indicating that the host interfaces are created. After the set - * is empty, we send out the signal ConfigDone. g_init is used to limit the + * is empty, we send out the signal PortInitDone. g_init is used to limit the * command to be run only once. */ set g_portSet; @@ -108,7 +108,7 @@ int main(int argc, char **argv) */ FieldValueTuple finish_notice("lanes", "0"); vector attrs = { finish_notice }; - p.set("ConfigDone", attrs); + p.set("PortInitDone", attrs); g_init = true; } @@ -166,7 +166,7 @@ void handlePortConfigFile(ProducerStateTable &p, string file) iss >> entry[column]; } - /* If port has no alias, then use its' name as alias */ + /* If port has no alias, then use its name as alias */ string alias; if ((entry.find("alias") != entry.end()) && (entry["alias"] != "")) { From 50e9a1d3ad63e7047a4130456bc176bd2ef99f68 Mon Sep 17 00:00:00 2001 From: Volodymyr Samotiy Date: Mon, 11 Sep 2017 17:19:53 +0300 Subject: [PATCH 3/3] [portsorch]: Add support of cable breakout feature * Fix comments --- orchagent/portsorch.cpp | 10 +++++----- orchagent/portsorch.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index fe0f56dd65b..43d700acfba 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -495,18 +495,18 @@ bool PortsOrch::addPort(const set &lane_set, uint32_t speed) return true; } -bool PortsOrch::removePort(const set &lane_set) +bool PortsOrch::removePort(sai_object_id_t port_id) { SWSS_LOG_ENTER(); - sai_status_t status = sai_port_api->remove_port(m_portListLaneMap[lane_set]); + 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", m_portListLaneMap[lane_set], status); + SWSS_LOG_ERROR("Failed to remove port %lx, rv:%d", port_id, status); return false; } - SWSS_LOG_NOTICE("Remove port %lx", m_portListLaneMap[lane_set]); + SWSS_LOG_NOTICE("Remove port %lx", port_id); return true; } @@ -661,7 +661,7 @@ void PortsOrch::doPortTask(Consumer &consumer) { if (m_lanesAliasSpeedMap.find(it->first) == m_lanesAliasSpeedMap.end()) { - if (!removePort(it->first)) + if (!removePort(it->second)) { throw runtime_error("PortsOrch initialization failure."); } diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index a5f8ec39867..959f9bf77c7 100644 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -103,7 +103,7 @@ class PortsOrch : public Orch, public Subject bool removeLagMember(Port lag, Port port); bool addPort(const set &lane_set, uint32_t speed); - bool removePort(const set &lane_set); + bool removePort(sai_object_id_t port_id); bool initPort(const string &alias, const set &lane_set); bool setPortAdminStatus(sai_object_id_t id, bool up);