Skip to content

Commit 77cbb3c

Browse files
stephenxsdaall
authored andcommitted
Improve the way of handling BUFFER_PG during PFC storm (sonic-net#1480)
* Fix the issue: failed to updating BUFFER_PG during PFC storm One action for the PFC storm is to set a zero buffer profile on the PG under PFC storm. The zero buffer won't be removed until the PFC storm has gone. If the user wants to modify the buffer profile for the PG, the bufferorch will return "task_need_retry". General speaking it doesn't matter unless that: - the system can't be warm rebooted until the PFC storm has gone. - the "task_need_retry" will block the update of the entire BUFFER_PG table from being programmed to ASIC. In this sense, we need a better solution. The new solution will: - record the new profile user wants to apply during PFC storm as the "pending profile" for that PG and return "task_success" if the PG is under PFC storm. - apply the pending profile once the PG is unlocked. - the latest pending profile will take effect in case user tries updating the profile for more than 1 times. Signed-off-by: Stephen Sun <[email protected]> * Address review comments: add a pair of brackets for the if-block Signed-off-by: Stephen Sun <[email protected]> * Fix ut error Signed-off-by: Stephen Sun <[email protected]> * Fix typo Signed-off-by: Stephen Sun <[email protected]>
1 parent dd8be97 commit 77cbb3c

File tree

5 files changed

+51
-11
lines changed

5 files changed

+51
-11
lines changed

orchagent/bufferorch.cpp

+17-8
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ task_process_status BufferOrch::processPriorityGroup(Consumer &consumer)
754754
for (string port_name : port_names)
755755
{
756756
Port port;
757+
bool portUpdated = false;
757758
SWSS_LOG_DEBUG("processing port:%s", port_name.c_str());
758759
if (!gPortsOrch->getPort(port_name, port))
759760
{
@@ -771,18 +772,26 @@ task_process_status BufferOrch::processPriorityGroup(Consumer &consumer)
771772
}
772773
if (port.m_priority_group_lock[ind])
773774
{
774-
SWSS_LOG_WARN("Priority group %zd on port %s is locked, will retry", ind, port_name.c_str());
775-
return task_process_status::task_need_retry;
775+
SWSS_LOG_WARN("Priority group %zd on port %s is locked, pending profile 0x%" PRIx64 " until unlocked", ind, port_name.c_str(), sai_buffer_profile);
776+
portUpdated = true;
777+
port.m_priority_group_pending_profile[ind] = sai_buffer_profile;
776778
}
777-
pg_id = port.m_priority_group_ids[ind];
778-
SWSS_LOG_DEBUG("Applying buffer profile:0x%" PRIx64 " to port:%s pg index:%zd, pg sai_id:0x%" PRIx64, sai_buffer_profile, port_name.c_str(), ind, pg_id);
779-
sai_status_t sai_status = sai_buffer_api->set_ingress_priority_group_attribute(pg_id, &attr);
780-
if (sai_status != SAI_STATUS_SUCCESS)
779+
else
781780
{
782-
SWSS_LOG_ERROR("Failed to set port:%s pg:%zd buffer profile attribute, status:%d", port_name.c_str(), ind, sai_status);
783-
return task_process_status::task_failed;
781+
pg_id = port.m_priority_group_ids[ind];
782+
SWSS_LOG_DEBUG("Applying buffer profile:0x%" PRIx64 " to port:%s pg index:%zd, pg sai_id:0x%" PRIx64, sai_buffer_profile, port_name.c_str(), ind, pg_id);
783+
sai_status_t sai_status = sai_buffer_api->set_ingress_priority_group_attribute(pg_id, &attr);
784+
if (sai_status != SAI_STATUS_SUCCESS)
785+
{
786+
SWSS_LOG_ERROR("Failed to set port:%s pg:%zd buffer profile attribute, status:%d", port_name.c_str(), ind, sai_status);
787+
return task_process_status::task_failed;
788+
}
784789
}
785790
}
791+
if (portUpdated)
792+
{
793+
gPortsOrch->setPort(port_name, port);
794+
}
786795
}
787796

788797
if (m_ready_list.find(key) != m_ready_list.end())

orchagent/pfcactionhandler.cpp

+17-2
Original file line numberDiff line numberDiff line change
@@ -523,10 +523,25 @@ PfcWdZeroBufferHandler::~PfcWdZeroBufferHandler(void)
523523
return;
524524
}
525525

526-
sai_object_id_t pg = portInstance.m_priority_group_ids[size_t(getQueueId())];
526+
auto idx = size_t(getQueueId());
527+
sai_object_id_t pg = portInstance.m_priority_group_ids[idx];
528+
sai_object_id_t pending_profile_id = portInstance.m_priority_group_pending_profile[idx];
527529

528530
attr.id = SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE;
529-
attr.value.oid = m_originalPgBufferProfile;
531+
532+
if (pending_profile_id != SAI_NULL_OBJECT_ID)
533+
{
534+
attr.value.oid = pending_profile_id;
535+
SWSS_LOG_NOTICE("Priority group %zd on port %s has been restored to pending profile 0x%" PRIx64,
536+
idx, portInstance.m_alias.c_str(), pending_profile_id);
537+
portInstance.m_priority_group_pending_profile[idx] = SAI_NULL_OBJECT_ID;
538+
}
539+
else
540+
{
541+
attr.value.oid = m_originalPgBufferProfile;
542+
SWSS_LOG_NOTICE("Priority group %zd on port %s has been restored to original profile 0x%" PRIx64,
543+
idx, portInstance.m_alias.c_str(), m_originalPgBufferProfile);
544+
}
530545

531546
// Set our zero buffer profile
532547
status = sai_buffer_api->set_ingress_priority_group_attribute(pg, &attr);

orchagent/port.h

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class Port
118118
*/
119119
std::vector<bool> m_queue_lock;
120120
std::vector<bool> m_priority_group_lock;
121+
std::vector<sai_object_id_t> m_priority_group_pending_profile;
121122

122123
std::unordered_set<sai_object_id_t> m_ingress_acl_tables_uset;
123124
std::unordered_set<sai_object_id_t> m_egress_acl_tables_uset;

orchagent/portsorch.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -3192,6 +3192,7 @@ void PortsOrch::initializePriorityGroups(Port &port)
31923192

31933193
port.m_priority_group_ids.resize(attr.value.u32);
31943194
port.m_priority_group_lock.resize(attr.value.u32);
3195+
port.m_priority_group_pending_profile.resize(attr.value.u32);
31953196

31963197
if (attr.value.u32 == 0)
31973198
{

tests/mock_tests/portsorch_ut.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -416,14 +416,28 @@ namespace portsorch_test
416416
// process pool, profile and PGs
417417
static_cast<Orch *>(gBufferOrch)->doTask();
418418

419+
// Port should have been updated by BufferOrch->doTask
420+
gPortsOrch->getPort("Ethernet0", port);
421+
auto profile_id = (*BufferOrch::m_buffer_type_maps["BUFFER_PROFILE"])[string("test_profile")].m_saiObjectId;
422+
ASSERT_TRUE(profile_id != SAI_NULL_OBJECT_ID);
423+
ASSERT_TRUE(port.m_priority_group_pending_profile[3] == profile_id);
424+
ASSERT_TRUE(port.m_priority_group_pending_profile[4] == SAI_NULL_OBJECT_ID);
425+
419426
auto pgConsumer = static_cast<Consumer*>(gBufferOrch->getExecutor(CFG_BUFFER_PG_TABLE_NAME));
420427
pgConsumer->dumpPendingTasks(ts);
421-
ASSERT_FALSE(ts.empty()); // PG is skipped
428+
ASSERT_TRUE(ts.empty()); // PG is stored in m_priority_group_pending_profile
422429
ts.clear();
423430

424431
// release zero buffer drop handler
425432
dropHandler.reset();
426433

434+
// re-fetch the port
435+
gPortsOrch->getPort("Ethernet0", port);
436+
437+
// pending profile should be cleared
438+
ASSERT_TRUE(port.m_priority_group_pending_profile[3] == SAI_NULL_OBJECT_ID);
439+
ASSERT_TRUE(port.m_priority_group_pending_profile[4] == SAI_NULL_OBJECT_ID);
440+
427441
// process PGs
428442
static_cast<Orch *>(gBufferOrch)->doTask();
429443

0 commit comments

Comments
 (0)