Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[202012][cherry-pick]Update orchagent to support new field pfcwd_sw_enable #2302

Merged
merged 9 commits into from
Jun 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 154 additions & 54 deletions cfgmgr/buffermgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "exec.h"
#include "shellcmd.h"
#include "warm_restart.h"
#include "converter.h"

using namespace std;
using namespace swss;
Expand Down Expand Up @@ -133,11 +134,11 @@ Create/update two tables: profile (in m_cfgBufferProfileTable) and port buffer (
}
}
*/
task_process_status BufferMgr::doSpeedUpdateTask(string port, bool admin_up)
task_process_status BufferMgr::doSpeedUpdateTask(string port)
{
vector<FieldValueTuple> fvVectorPg, fvVectorProfile;
string cable;
string speed;
string pfc_enable;

if (m_cableLenLookup.count(port) == 0)
{
Expand All @@ -152,9 +153,24 @@ task_process_status BufferMgr::doSpeedUpdateTask(string port, bool admin_up)
return task_process_status::task_success;
}

speed = m_speedLookup[port];
if (m_portStatusLookup.count(port) == 0)
{
// admin_status is not available yet. This can happen when notification of `PORT_QOS_MAP` table
// comes first.
SWSS_LOG_INFO("pfc_enable status is not available for port %s", port.c_str());
return task_process_status::task_need_retry;
}

string buffer_pg_key = port + m_cfgBufferPgTable.getTableNameSeparator() + LOSSLESS_PGS;
if (m_portPfcStatus.count(port) == 0)
{
// PORT_QOS_MAP is not ready yet. The notification is cleared, and buffer pg
// will be handled when `pfc_enable` in `PORT_QOS_MAP` table is available
SWSS_LOG_INFO("pfc_enable status is not available for port %s", port.c_str());
return task_process_status::task_success;
}
pfc_enable = m_portPfcStatus[port];
speed = m_speedLookup[port];

// key format is pg_lossless_<speed>_<cable>_profile
string buffer_profile_key = "pg_lossless_" + speed + "_" + cable + "_profile";
string profile_ref = string("[") +
Expand All @@ -163,40 +179,66 @@ task_process_status BufferMgr::doSpeedUpdateTask(string port, bool admin_up)
buffer_profile_key +
"]";

m_cfgBufferPgTable.get(buffer_pg_key, fvVectorPg);

vector<string> lossless_pgs = tokenize(pfc_enable, ',');
// Convert to bitmap
unsigned long lossless_pg_id = 0;
for (auto pg : lossless_pgs)
{
try
{
uint8_t cur_pg = to_uint<uint8_t>(pg);
lossless_pg_id |= (1<<cur_pg);
}
catch (const std::invalid_argument &e)
{
// Ignore invalid value
continue;
}
}
// Although we have up to 8 PGs for now, the range to check is expanded to 32 support more PGs
set<string> lossless_pg_combinations = generateIdListFromMap(lossless_pg_id, sizeof(lossless_pg_id));

if (!admin_up && m_platform == "mellanox")
if (m_portStatusLookup[port] == "down" && m_platform == "mellanox")
{
// Remove the entry in BUFFER_PG table if any
if (!fvVectorPg.empty())
for (auto lossless_pg : lossless_pg_combinations)
{
for (auto &prop : fvVectorPg)
// Remove the entry in BUFFER_PG table if any
vector<FieldValueTuple> fvVectorPg;
string buffer_pg_key = port + m_cfgBufferPgTable.getTableNameSeparator() + lossless_pg;

m_cfgBufferPgTable.get(buffer_pg_key, fvVectorPg);
if (!fvVectorPg.empty())
{
if (fvField(prop) == "profile")
for (auto &prop : fvVectorPg)
{
if (fvValue(prop) == profile_ref)
if (fvField(prop) == "profile")
{
SWSS_LOG_NOTICE("Removing PG %s from port %s which is administrative down", buffer_pg_key.c_str(), port.c_str());
m_cfgBufferPgTable.del(buffer_pg_key);
}
else
{
SWSS_LOG_NOTICE("Not default profile %s is configured on PG %s, won't reclaim buffer", fvValue(prop).c_str(), buffer_pg_key.c_str());
if (fvValue(prop) == profile_ref)
{
SWSS_LOG_NOTICE("Removing PG %s from port %s which is administrative down", buffer_pg_key.c_str(), port.c_str());
m_cfgBufferPgTable.del(buffer_pg_key);
}
else
{
SWSS_LOG_NOTICE("Not default profile %s is configured on PG %s, won't reclaim buffer", fvValue(prop).c_str(), buffer_pg_key.c_str());
}
}
}
}
}

return task_process_status::task_success;
}

if (m_pgProfileLookup.count(speed) == 0 || m_pgProfileLookup[speed].count(cable) == 0)
{
SWSS_LOG_ERROR("Unable to create/update PG profile for port %s. No PG profile configured for speed %s and cable length %s",
port.c_str(), speed.c_str(), cable.c_str());
return task_process_status::task_invalid_entry;
SWSS_LOG_ERROR("Unable to create/update PG profile for port %s. No PG profile configured for speed %s and cable length %s",
port.c_str(), speed.c_str(), cable.c_str());
return task_process_status::task_invalid_entry;
}

vector<FieldValueTuple> fvVectorProfile;
// check if profile already exists - if yes - skip creation
m_cfgBufferProfileTable.get(buffer_profile_key, fvVectorProfile);
// Create record in BUFFER_PROFILE table
Expand Down Expand Up @@ -233,22 +275,34 @@ task_process_status BufferMgr::doSpeedUpdateTask(string port, bool admin_up)
{
SWSS_LOG_NOTICE("Reusing existing profile '%s'", buffer_profile_key.c_str());
}

/* Check if PG Mapping is already then log message and return. */
for (auto& prop : fvVectorPg)

for (auto lossless_pg : lossless_pg_combinations)
{
if ((fvField(prop) == "profile") && (profile_ref == fvValue(prop)))
vector<FieldValueTuple> fvVectorPg;
string buffer_pg_key = port + m_cfgBufferPgTable.getTableNameSeparator() + lossless_pg;

m_cfgBufferPgTable.get(buffer_pg_key, fvVectorPg);
bool profile_existing = false;
/* Check if PG Mapping is already then log message and return. */
for (auto& prop : fvVectorPg)
{
SWSS_LOG_NOTICE("PG to Buffer Profile Mapping %s already present", buffer_pg_key.c_str());
return task_process_status::task_success;
if ((fvField(prop) == "profile") && (profile_ref == fvValue(prop)))
{
SWSS_LOG_NOTICE("PG to Buffer Profile Mapping %s already present", buffer_pg_key.c_str());
profile_existing = true;
break;
}
}
}

fvVectorPg.clear();
if (profile_existing)
{
continue;
}
fvVectorPg.clear();

fvVectorPg.push_back(make_pair("profile", profile_ref));
SWSS_LOG_INFO("Setting buffer profile to PG %s", buffer_pg_key.c_str());
m_cfgBufferPgTable.set(buffer_pg_key, fvVectorPg);
fvVectorPg.push_back(make_pair("profile", profile_ref));
m_cfgBufferPgTable.set(buffer_pg_key, fvVectorPg);
neethajohn marked this conversation as resolved.
Show resolved Hide resolved
SWSS_LOG_INFO("Setting buffer profile to PG %s", buffer_pg_key.c_str());
}
return task_process_status::task_success;
}

Expand Down Expand Up @@ -388,6 +442,47 @@ void BufferMgr::doBufferMetaTask(Consumer &consumer)
}
}

/*
Parse PORT_QOS_MAP to retrieve on which queue PFC is enable, and
cached in a map
*/
void BufferMgr::doPortQosTableTask(Consumer &consumer)
{
SWSS_LOG_ENTER();

auto it = consumer.m_toSync.begin();
while (it != consumer.m_toSync.end())
{
KeyOpFieldsValuesTuple tuple = it->second;
string port_name = kfvKey(tuple);
string op = kfvOp(tuple);
if (op == SET_COMMAND)
{
bool update_pfc_enable = false;
for (auto itp : kfvFieldsValues(tuple))
{
if (fvField(itp) == "pfc_enable")
{
if (m_portPfcStatus.count(port_name) == 0 || m_portPfcStatus[port_name] != fvValue(itp))
{
m_portPfcStatus[port_name] = fvValue(itp);
update_pfc_enable = true;
}
SWSS_LOG_INFO("Got pfc enable status for port %s status %s", port_name.c_str(), fvValue(itp).c_str());
break;
}
}
if (update_pfc_enable)
{
// The return status is ignored
doSpeedUpdateTask(port_name);
}
}
it = consumer.m_toSync.erase(it);
}

}

void BufferMgr::doTask(Consumer &consumer)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -441,6 +536,12 @@ void BufferMgr::doTask(Consumer &consumer)
return;
}

if (table_name == CFG_PORT_QOS_MAP_TABLE_NAME)
{
doPortQosTableTask(consumer);
return;
}

auto it = consumer.m_toSync.begin();
while (it != consumer.m_toSync.end())
{
Expand All @@ -464,7 +565,6 @@ void BufferMgr::doTask(Consumer &consumer)
}
else if (m_pgfile_processed && table_name == CFG_PORT_TABLE_NAME)
{
bool admin_up = false;
for (auto i : kfvFieldsValues(t))
{
if (fvField(i) == "speed")
Expand All @@ -473,37 +573,37 @@ void BufferMgr::doTask(Consumer &consumer)
}
if (fvField(i) == "admin_status")
{
admin_up = ("up" == fvValue(i));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the declaration in L567

m_portStatusLookup[port] = fvValue(i);
}
}

if (m_speedLookup.count(port) != 0)
{
// create/update profile for port
SWSS_LOG_DEBUG("Port %s Speed %s admin status %d", port.c_str(), m_speedLookup[port].c_str(), admin_up);
task_status = doSpeedUpdateTask(port, admin_up);
SWSS_LOG_DEBUG("Port %s Speed %s admin status %s", port.c_str(), m_speedLookup[port].c_str(), m_portStatusLookup[port].c_str());
task_status = doSpeedUpdateTask(port);
SWSS_LOG_DEBUG("Return code for doSpeedUpdateTask %d", task_status);
}

}
}

switch (task_status)
{
case task_process_status::task_failed:
SWSS_LOG_ERROR("Failed to process table update");
return;
case task_process_status::task_need_retry:
SWSS_LOG_INFO("Unable to process table update. Will retry...");
++it;
break;
case task_process_status::task_invalid_entry:
SWSS_LOG_ERROR("Failed to process invalid entry, drop it");
it = consumer.m_toSync.erase(it);
break;
default:
it = consumer.m_toSync.erase(it);
break;
switch (task_status)
{
case task_process_status::task_failed:
SWSS_LOG_ERROR("Failed to process table update");
return;
case task_process_status::task_need_retry:
SWSS_LOG_INFO("Unable to process table update. Will retry...");
++it;
break;
case task_process_status::task_invalid_entry:
SWSS_LOG_ERROR("Failed to process invalid entry, drop it");
it = consumer.m_toSync.erase(it);
break;
default:
it = consumer.m_toSync.erase(it);
break;
}
}
}
}
9 changes: 7 additions & 2 deletions cfgmgr/buffermgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
namespace swss {

#define INGRESS_LOSSLESS_PG_POOL_NAME "ingress_lossless_pool"
#define LOSSLESS_PGS "3-4"

#define BUFFERMGR_TIMER_PERIOD 10

Expand All @@ -28,6 +27,8 @@ typedef std::map<std::string, speed_map_t> pg_profile_lookup_t;

typedef std::map<std::string, std::string> port_cable_length_t;
typedef std::map<std::string, std::string> port_speed_t;
typedef std::map<std::string, std::string> port_pfc_status_t;
typedef std::map<std::string, std::string> port_admin_status_t;

class BufferMgr : public Orch
{
Expand Down Expand Up @@ -56,18 +57,22 @@ class BufferMgr : public Orch

pg_profile_lookup_t m_pgProfileLookup;
port_cable_length_t m_cableLenLookup;
port_admin_status_t m_portStatusLookup;
port_speed_t m_speedLookup;
std::string getPgPoolMode();
void readPgProfileLookupFile(std::string);
task_process_status doCableTask(std::string port, std::string cable_length);
task_process_status doSpeedUpdateTask(std::string port, bool admin_up);
task_process_status doSpeedUpdateTask(std::string port);
void doBufferTableTask(Consumer &consumer, ProducerStateTable &applTable);

void transformSeperator(std::string &name);
void transformReference(std::string &name);

void doTask(Consumer &consumer);
void doBufferMetaTask(Consumer &consumer);

port_pfc_status_t m_portPfcStatus;
void doPortQosTableTask(Consumer &consumer);
};

}
Expand Down
3 changes: 2 additions & 1 deletion cfgmgr/buffermgrd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ int main(int argc, char **argv)
CFG_BUFFER_QUEUE_TABLE_NAME,
CFG_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME,
CFG_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME,
CFG_DEVICE_METADATA_TABLE_NAME
CFG_DEVICE_METADATA_TABLE_NAME,
CFG_PORT_QOS_MAP_TABLE_NAME
};
cfgOrchList.emplace_back(new BufferMgr(&cfgDb, &applDb, pg_lookup_file, cfg_buffer_tables));
}
Expand Down
10 changes: 5 additions & 5 deletions orchagent/pfcwdorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,9 @@ void PfcWdSwOrch<DropHandler, ForwardHandler>::enableBigRedSwitchMode()
continue;
}

if (!gPortsOrch->getPortPfc(port.m_port_id, &pfcMask))
if (!gPortsOrch->getPortPfcWatchdogStatus(port.m_port_id, &pfcMask))
{
SWSS_LOG_ERROR("Failed to get PFC mask on port %s", port.m_alias.c_str());
SWSS_LOG_ERROR("Failed to get PFC watchdog mask on port %s", port.m_alias.c_str());
return;
}

Expand Down Expand Up @@ -443,9 +443,9 @@ void PfcWdSwOrch<DropHandler, ForwardHandler>::enableBigRedSwitchMode()
continue;
}

if (!gPortsOrch->getPortPfc(port.m_port_id, &pfcMask))
if (!gPortsOrch->getPortPfcWatchdogStatus(port.m_port_id, &pfcMask))
{
SWSS_LOG_ERROR("Failed to get PFC mask on port %s", port.m_alias.c_str());
SWSS_LOG_ERROR("Failed to get PFC watchdog mask on port %s", port.m_alias.c_str());
return;
}

Expand Down Expand Up @@ -489,7 +489,7 @@ bool PfcWdSwOrch<DropHandler, ForwardHandler>::registerInWdDb(const Port& port,

uint8_t pfcMask = 0;

if (!gPortsOrch->getPortPfc(port.m_port_id, &pfcMask))
if (!gPortsOrch->getPortPfcWatchdogStatus(port.m_port_id, &pfcMask))
{
SWSS_LOG_ERROR("Failed to get PFC mask on port %s", port.m_alias.c_str());
return false;
Expand Down
Loading