Skip to content

Commit

Permalink
[Reclaiming buffer] Support reclaiming buffer in traditional model (s…
Browse files Browse the repository at this point in the history
…onic-net#2011)

- What I did
It's to port sonic-net#1837 to master to reclaim reserved buffer.
As the way to do it differs among vendors, buffermgrd will:
1. Handle port admin down on Mellanox platform.
    - Not apply lossless buffer PG to an admin-down port
    - Remove lossless buffer PG (3-4) from a port when it is shut down.
2. Read lossless buffer PG (3-4) to a port when a port is started up.

- Why I did it
To support reclaiming reserved buffer when a port is shut down on Mellanox platform in traditional buffer model.

- How I verified it
sonic-mgmt test and vs test.

Signed-off-by: Stephen Sun <stephens@nvidia.com>
  • Loading branch information
stephenxs authored Nov 22, 2021
1 parent 32d7a69 commit 4f6cb05
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 36 deletions.
112 changes: 77 additions & 35 deletions cfgmgr/buffermgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ BufferMgr::BufferMgr(DBConnector *cfgDb, DBConnector *applDb, string pg_lookup_f
m_applBufferEgressProfileListTable(applDb, APP_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME)
{
readPgProfileLookupFile(pg_lookup_file);

char *platform = getenv("ASIC_VENDOR");
if (NULL == platform)
{
SWSS_LOG_WARN("Platform environment variable is not defined");
}
else
{
m_platform = platform;
}

dynamic_buffer_model = false;
}

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

Expand All @@ -142,20 +153,50 @@ task_process_status BufferMgr::doSpeedUpdateTask(string port)
}

speed = m_speedLookup[port];

string buffer_pg_key = port + m_cfgBufferPgTable.getTableNameSeparator() + LOSSLESS_PGS;
// key format is pg_lossless_<speed>_<cable>_profile
string buffer_profile_key = "pg_lossless_" + speed + "_" + cable + "_profile";
string profile_ref = buffer_profile_key;

m_cfgBufferPgTable.get(buffer_pg_key, fvVectorPg);

if (!admin_up && m_platform == "mellanox")
{
// Remove the entry in BUFFER_PG table if any
if (!fvVectorPg.empty())
{
for (auto &prop : fvVectorPg)
{
if (fvField(prop) == "profile")
{
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;
}

// Crete record in BUFFER_PROFILE table
// key format is pg_lossless_<speed>_<cable>_profile
string buffer_profile_key = "pg_lossless_" + speed + "_" + cable + "_profile";

// check if profile already exists - if yes - skip creation
m_cfgBufferProfileTable.get(buffer_profile_key, fvVector);
if (fvVector.size() == 0)
m_cfgBufferProfileTable.get(buffer_profile_key, fvVectorProfile);
// Create record in BUFFER_PROFILE table
if (fvVectorProfile.size() == 0)
{
SWSS_LOG_NOTICE("Creating new profile '%s'", buffer_profile_key.c_str());

Expand All @@ -170,32 +211,24 @@ task_process_status BufferMgr::doSpeedUpdateTask(string port)
// profile threshold field name
mode += "_th";

fvVector.push_back(make_pair("pool", INGRESS_LOSSLESS_PG_POOL_NAME));
fvVector.push_back(make_pair("xon", m_pgProfileLookup[speed][cable].xon));
fvVectorProfile.push_back(make_pair("pool", INGRESS_LOSSLESS_PG_POOL_NAME));
fvVectorProfile.push_back(make_pair("xon", m_pgProfileLookup[speed][cable].xon));
if (m_pgProfileLookup[speed][cable].xon_offset.length() > 0) {
fvVector.push_back(make_pair("xon_offset",
fvVectorProfile.push_back(make_pair("xon_offset",
m_pgProfileLookup[speed][cable].xon_offset));
}
fvVector.push_back(make_pair("xoff", m_pgProfileLookup[speed][cable].xoff));
fvVector.push_back(make_pair("size", m_pgProfileLookup[speed][cable].size));
fvVector.push_back(make_pair(mode, m_pgProfileLookup[speed][cable].threshold));
m_cfgBufferProfileTable.set(buffer_profile_key, fvVector);
fvVectorProfile.push_back(make_pair("xoff", m_pgProfileLookup[speed][cable].xoff));
fvVectorProfile.push_back(make_pair("size", m_pgProfileLookup[speed][cable].size));
fvVectorProfile.push_back(make_pair(mode, m_pgProfileLookup[speed][cable].threshold));
m_cfgBufferProfileTable.set(buffer_profile_key, fvVectorProfile);
}
else
{
SWSS_LOG_NOTICE("Reusing existing profile '%s'", buffer_profile_key.c_str());
}

fvVector.clear();

string buffer_pg_key = port + m_cfgBufferPgTable.getTableNameSeparator() + LOSSLESS_PGS;

string profile_ref = buffer_profile_key;

/* Check if PG Mapping is already then log message and return. */
m_cfgBufferPgTable.get(buffer_pg_key, fvVector);

for (auto& prop : fvVector)
for (auto& prop : fvVectorPg)
{
if ((fvField(prop) == "profile") && (profile_ref == fvValue(prop)))
{
Expand All @@ -204,10 +237,10 @@ task_process_status BufferMgr::doSpeedUpdateTask(string port)
}
}

fvVector.clear();
fvVectorPg.clear();

fvVector.push_back(make_pair("profile", profile_ref));
m_cfgBufferPgTable.set(buffer_pg_key, fvVector);
fvVectorPg.push_back(make_pair("profile", profile_ref));
m_cfgBufferPgTable.set(buffer_pg_key, fvVectorPg);
return task_process_status::task_success;
}

Expand Down Expand Up @@ -379,26 +412,35 @@ void BufferMgr::doTask(Consumer &consumer)
task_process_status task_status = task_process_status::task_success;
if (op == SET_COMMAND)
{
for (auto i : kfvFieldsValues(t))
if (table_name == CFG_PORT_CABLE_LEN_TABLE_NAME)
{
if (table_name == CFG_PORT_CABLE_LEN_TABLE_NAME)
// receive and cache cable length table
for (auto i : kfvFieldsValues(t))
{
// receive and cache cable length table
task_status = doCableTask(fvField(i), fvValue(i));
}
if (m_pgfile_processed && table_name == CFG_PORT_TABLE_NAME && (fvField(i) == "speed" || fvField(i) == "admin_status"))
}
else if (m_pgfile_processed && table_name == CFG_PORT_TABLE_NAME)
{
bool admin_up = false;
for (auto i : kfvFieldsValues(t))
{
if (fvField(i) == "speed")
{
m_speedLookup[port] = fvValue(i);
}

if (m_speedLookup.count(port) != 0)
if (fvField(i) == "admin_status")
{
// create/update profile for port
task_status = doSpeedUpdateTask(port);
admin_up = ("up" == fvValue(i));
}
}

if (m_speedLookup.count(port) != 0)
{
// create/update profile for port
task_status = doSpeedUpdateTask(port, admin_up);
}

if (task_status != task_process_status::task_success)
{
break;
Expand Down
4 changes: 3 additions & 1 deletion cfgmgr/buffermgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class BufferMgr : public Orch
using Orch::doTask;

private:
std::string m_platform;

Table m_cfgPortTable;
Table m_cfgCableLenTable;
Table m_cfgBufferProfileTable;
Expand All @@ -58,7 +60,7 @@ class BufferMgr : public Orch
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);
task_process_status doSpeedUpdateTask(std::string port, bool admin_up);
void doBufferTableTask(Consumer &consumer, ProducerStateTable &applTable);

void transformSeperator(std::string &name);
Expand Down

0 comments on commit 4f6cb05

Please sign in to comment.