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

Update orchagent to support new field pfcwd_sw_enable #2171

Merged
merged 17 commits into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
147 changes: 108 additions & 39 deletions cfgmgr/buffermgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,12 @@ Create/update two tables: profile (in m_cfgBufferProfileTable) and port buffer (
}
}
*/
task_process_status BufferMgr::doSpeedUpdateTask(string port, bool admin_up, const string& pfc_enable)
task_process_status BufferMgr::doSpeedUpdateTask(string port, bool admin_up)
{
string cable;
string speed;
string pfc_enable;
string applied_lossless_pg_status;
bingwang-ms marked this conversation as resolved.
Show resolved Hide resolved

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

if (m_portPfcStatus.count(port) == 0)
{
// PORT_QOS_MAP is not ready yet. retry is required
SWSS_LOG_INFO("pfc_enable status is not available for port %s", port.c_str());
bingwang-ms marked this conversation as resolved.
Show resolved Hide resolved
return task_process_status::task_need_retry;
}
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 = buffer_profile_key;

vector<string> lossless_pgs = tokenize(pfc_enable, ',');
for (auto lossless_pg : lossless_pgs)
{
vector<FieldValueTuple> fvVectorPg, fvVectorProfile;
string buffer_pg_key = port + m_cfgBufferPgTable.getTableNameSeparator() + lossless_pg;

m_cfgBufferPgTable.get(buffer_pg_key, fvVectorPg);

if (!admin_up && m_platform == "mellanox")
if (!admin_up && m_platform == "mellanox")
{
for (auto lossless_pg : lossless_pgs)
{
// 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())
{
for (auto &prop : fvVectorPg)
Expand All @@ -185,9 +195,26 @@ task_process_status BufferMgr::doSpeedUpdateTask(string port, bool admin_up, con
}
}
}

continue;
}
// Clear applied recorded
if (m_portLosslessPgs.count(port) != 0)
{
m_portLosslessPgs.erase(port);
};
// Clear recorded pg for admin_down port
if (m_portPgLookup.count(port) != 0)
{
m_portPgLookup.erase(port);
}
bingwang-ms marked this conversation as resolved.
Show resolved Hide resolved
return task_process_status::task_success;
}

for (auto lossless_pg : lossless_pgs)
{
vector<FieldValueTuple> fvVectorPg, fvVectorProfile;
string buffer_pg_key = port + m_cfgBufferPgTable.getTableNameSeparator() + lossless_pg;

m_cfgBufferPgTable.get(buffer_pg_key, fvVectorPg);
bingwang-ms marked this conversation as resolved.
Show resolved Hide resolved

if (m_pgProfileLookup.count(speed) == 0 || m_pgProfileLookup[speed].count(cable) == 0)
{
Expand Down Expand Up @@ -244,10 +271,78 @@ task_process_status BufferMgr::doSpeedUpdateTask(string port, bool admin_up, con

fvVectorPg.push_back(make_pair("profile", profile_ref));
m_cfgBufferPgTable.set(buffer_pg_key, fvVectorPg);
// Save the applied lossless PG
m_portLosslessPgs[port] = pfc_enable;
// Save the profile_ref
m_portPgLookup[port] = profile_ref;
}
return task_process_status::task_success;
}

void BufferMgr::updatePortLosslessPg(const string &port)
bingwang-ms marked this conversation as resolved.
Show resolved Hide resolved
{
string applied_lossless_pg_status;
// Read the lossless profile that has been applied to port
auto iter = m_portLosslessPgs.find(port);
if (iter == m_portLosslessPgs.end())
{
// No lossless pg is applied to port yet, no need to update
return;
}
applied_lossless_pg_status = iter->second;

string new_pfc_enable_flag = m_portPfcStatus[port];

vector<string> new_lossless_pgs = tokenize(new_pfc_enable_flag, ',');
std::sort(new_lossless_pgs.begin(), new_lossless_pgs.end());

vector<string> applied_lossless_pgs = tokenize(applied_lossless_pg_status, ',');
std::sort(applied_lossless_pgs.begin(), applied_lossless_pgs.end());

// Compare the sorted items, and update if diff is found
if (new_lossless_pgs == applied_lossless_pgs)
{
// No diff detected
return;
}

iter = m_portPgLookup.find(port);
if (iter == m_portPgLookup.end())
{
// Ignore if PG profile is not generated for the port
return;
}
string profile_ref = m_portPgLookup[port];
string buffer_pg_key;
vector<FieldValueTuple> fvVectorPg;
// Remove the already applied BUFFER_PG
for (auto pg : applied_lossless_pgs)
{
buffer_pg_key = port + m_cfgBufferPgTable.getTableNameSeparator() + pg;
fvVectorPg.clear();
m_cfgBufferPgTable.get(buffer_pg_key, fvVectorPg);

// Remove the entry in BUFFER_PG table if any
if (!fvVectorPg.empty())
{
m_cfgBufferPgTable.del(buffer_pg_key);
}
SWSS_LOG_INFO("Removed stale PG profile for port %s PG %s", port.c_str(), pg.c_str());
}

// Apply PG profile to new lossless pgs
for (auto pg : new_lossless_pgs)
{
buffer_pg_key = port + m_cfgBufferPgTable.getTableNameSeparator() + pg;
fvVectorPg.clear();
fvVectorPg.push_back(make_pair("profile", profile_ref));
m_cfgBufferPgTable.set(buffer_pg_key, fvVectorPg);
SWSS_LOG_INFO("Applied PG profile for port %s PG %s", port.c_str(), pg.c_str());
}
// Record the PGs
m_portLosslessPgs[port] = new_pfc_enable_flag;
}

void BufferMgr::transformSeperator(string &name)
{
size_t pos;
Expand Down Expand Up @@ -372,6 +467,8 @@ void BufferMgr::doPortQosTableTask(Consumer &consumer)
{
m_portPfcStatus[port_name] = fvValue(itp);
SWSS_LOG_INFO("Got pfc enable status for port %s status %s", port_name.c_str(), fvValue(itp).c_str());
// Check if pfc_enable flag is updated
updatePortLosslessPg(port_name);
break;
}
}
Expand All @@ -381,23 +478,6 @@ void BufferMgr::doPortQosTableTask(Consumer &consumer)

}

/*
Read pfc_enable entry from PORT_QOS_MAP to decide on which queue to
apply lossless PG.
Return the true if PORT_QOS_MAP is already available, otherwise return false
*/
bool BufferMgr::getPfcEnableQueuesForPort(std::string port, std::string &pfc_status)
{
auto iter = m_portPfcStatus.find(port);
if (iter != m_portPfcStatus.end())
{
pfc_status = iter->second;
return true;
}

return false;
}

void BufferMgr::doTask(Consumer &consumer)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -495,18 +575,7 @@ void BufferMgr::doTask(Consumer &consumer)

if (m_speedLookup.count(port) != 0)
{
// create/update profile for port
string pfc_enable_status;
if (!getPfcEnableQueuesForPort(port, pfc_enable_status))
{
// PORT_QOS_MAP is not ready yet. retry is required
SWSS_LOG_INFO("pfc_enable status is not available for port %s", port.c_str());
task_status = task_process_status::task_need_retry;
}
else
{
task_status = doSpeedUpdateTask(port, admin_up, pfc_enable_status);
}
task_status = doSpeedUpdateTask(port, admin_up);
}

if (task_status != task_process_status::task_success)
Expand Down
8 changes: 6 additions & 2 deletions cfgmgr/buffermgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ 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_pg_profile_t;

class BufferMgr : public Orch
{
Expand Down Expand Up @@ -61,7 +62,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, bool admin_up, const std::string &pfc_enable);
task_process_status doSpeedUpdateTask(std::string port, bool admin_up);
void doBufferTableTask(Consumer &consumer, ProducerStateTable &applTable);

void transformSeperator(std::string &name);
Expand All @@ -70,9 +71,12 @@ class BufferMgr : public Orch
void doBufferMetaTask(Consumer &consumer);

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

bool getPfcEnableQueuesForPort(std::string port, std::string &pfc_enable_status);
port_pg_profile_t m_portPgLookup;
void updatePortLosslessPg(const std::string &port_name);

};

}
Expand Down
49 changes: 38 additions & 11 deletions tests/test_buffer_traditional.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def setup_db(self, dvs):

def get_pfc_enable_queues(self):
qos_map = self.config_db.get_entry("PORT_QOS_MAP", self.INTF)
self.lossless_pgs = qos_map['pfc_enable'].split(',')
return qos_map['pfc_enable'].split(',')

def get_pg_oid(self, pg):
fvs = dict()
Expand Down Expand Up @@ -60,22 +60,25 @@ def change_cable_len(self, cable_len):
fvs[self.INTF] = cable_len
self.config_db.update_entry("CABLE_LENGTH", "AZURE", fvs)

def set_port_qos_table(self):
pfc_enable = "2,3,4,6"
def set_port_qos_table(self, pfc_enable_flag):
fvs=dict()
fvs['pfc_enable'] = pfc_enable
fvs['pfc_enable'] = pfc_enable_flag
self.config_db.update_entry("PORT_QOS_MAP", self.INTF, fvs)

self.lossless_pgs = pfc_enable_flag.split(',')

def get_pg_name_map(self):
pg_name_map = dict()
for pg in self.lossless_pgs:
pg_name = "{}:{}".format(self.INTF, pg)
pg_name_map[pg_name] = self.get_pg_oid(pg_name)
return pg_name_map

@pytest.fixture
def setup_teardown_test(self, dvs):
try:
self.setup_db(dvs)
self.set_port_qos_table()
self.get_pfc_enable_queues()
pg_name_map = dict()
for pg in self.lossless_pgs:
pg_name = "{}:{}".format(self.INTF, pg)
pg_name_map[pg_name] = self.get_pg_oid(pg_name)
self.set_port_qos_table('2,3,4,6')
pg_name_map = self.get_pg_name_map()
yield pg_name_map
finally:
self.teardown()
Expand Down Expand Up @@ -138,6 +141,30 @@ def test_zero_cable_len_profile_update(self, dvs, setup_teardown_test):
fvs["SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"] = self.buf_pg_profile[pg]
self.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", self.pg_name_map[pg], fvs)

# Verify pgs are updated if pfc_enable is updated
orig_lossless_pgs = self.lossless_pgs
orig_pg_name_map = self.pg_name_map

self.set_port_qos_table('0,2,3,7')
self.pg_name_map = self.get_pg_name_map()
time.sleep(1)
for pg in orig_lossless_pgs:
if pg not in self.lossless_pgs:
assert len(self.app_db.get_entry("BUFFER_PG_TABLE", self.INTF + ":" + pg)) == 0
for pg in orig_pg_name_map:
if pg not in self.pg_name_map:
fvs["SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"] = "oid:0x0"
self.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", orig_pg_name_map[pg], fvs)

# Update buf_pg_profile
self.get_asic_buf_pg_profiles()

for pg in self.lossless_pgs:
self.app_db.wait_for_field_match("BUFFER_PG_TABLE", self.INTF + ":" + pg, {"profile": orig_lossless_profile})
for pg in self.pg_name_map:
fvs["SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"] = self.buf_pg_profile[pg]
self.asic_db.wait_for_field_match("ASIC_STATE:SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP", self.pg_name_map[pg], fvs)
bingwang-ms marked this conversation as resolved.
Show resolved Hide resolved

# change cable length to 'cable_len_before_test'
self.change_cable_len(cable_len_before_test)

Expand Down