Skip to content

Commit 923db73

Browse files
authored
[201911][pfcwd] Avoid ingress drop by not attaching zero profiles when pfc storm is detected (#2279)
What I did According to the current pfcwd detection logic on certain platforms, when wd fires, we create an ingress zero pool, ingress zero profile, egress zero pool, egress zero profile (if not already created) and then attach the ingress zero profile to the ingress pg and egress zero profile to the egress queue. As a result traffic ingressing that port/pg and egressing that port/queue will get dropped. The current changes are done to avoid dropping traffic that is ingressing the port/pg that is in storm. The code changes in this PR avoid creating the ingress zero pool and profile and not attach any zero profile to the ingress pg when pfcwd is triggered How I verified it Modified the pfcwd func tests (sonic-net/sonic-mgmt#5665) and testcase passed on Mellanox platform Signed-off-by: Neetha John <[email protected]>
1 parent 1c12a40 commit 923db73

File tree

6 files changed

+43
-99
lines changed

6 files changed

+43
-99
lines changed

orchagent/bufferorch.cpp

-5
Original file line numberDiff line numberDiff line change
@@ -728,11 +728,6 @@ task_process_status BufferOrch::processPriorityGroup(Consumer &consumer)
728728
SWSS_LOG_ERROR("Invalid pg index specified:%zd", ind);
729729
return task_process_status::task_invalid_entry;
730730
}
731-
if (port.m_priority_group_lock[ind])
732-
{
733-
SWSS_LOG_WARN("Priority group %zd on port %s is locked, will retry", ind, port_name.c_str());
734-
return task_process_status::task_need_retry;
735-
}
736731
pg_id = port.m_priority_group_ids[ind];
737732
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);
738733
sai_status_t sai_status = sai_buffer_api->set_ingress_priority_group_attribute(pg_id, &attr);

orchagent/pfcactionhandler.cpp

+19-63
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ PfcWdZeroBufferHandler::PfcWdZeroBufferHandler(sai_object_id_t port,
441441
return;
442442
}
443443

444-
setPriorityGroupAndQueueLockFlag(portInstance, true);
444+
setQueueLockFlag(portInstance, true);
445445

446446
sai_attribute_t attr;
447447
attr.id = SAI_QUEUE_ATTR_BUFFER_PROFILE_ID;
@@ -457,7 +457,7 @@ PfcWdZeroBufferHandler::PfcWdZeroBufferHandler(sai_object_id_t port,
457457
sai_object_id_t oldQueueProfileId = attr.value.oid;
458458

459459
attr.id = SAI_QUEUE_ATTR_BUFFER_PROFILE_ID;
460-
attr.value.oid = ZeroBufferProfile::getZeroBufferProfile(false);
460+
attr.value.oid = ZeroBufferProfile::getZeroBufferProfile();
461461

462462
// Set our zero buffer profile
463463
status = sai_queue_api->set_queue_attribute(queue, &attr);
@@ -469,35 +469,6 @@ PfcWdZeroBufferHandler::PfcWdZeroBufferHandler(sai_object_id_t port,
469469

470470
// Save original buffer profile
471471
m_originalQueueBufferProfile = oldQueueProfileId;
472-
473-
// Get PG
474-
sai_object_id_t pg = portInstance.m_priority_group_ids[static_cast <size_t> (queueId)];
475-
476-
attr.id = SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE;
477-
478-
// Get PG's buffer profile
479-
status = sai_buffer_api->get_ingress_priority_group_attribute(pg, 1, &attr);
480-
if (status != SAI_STATUS_SUCCESS)
481-
{
482-
SWSS_LOG_ERROR("Failed to get buffer profile ID on PG 0x%" PRIx64 ": %d", pg, status);
483-
return;
484-
}
485-
486-
// Set zero profile to PG
487-
sai_object_id_t oldPgProfileId = attr.value.oid;
488-
489-
attr.id = SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE;
490-
attr.value.oid = ZeroBufferProfile::getZeroBufferProfile(true);
491-
492-
status = sai_buffer_api->set_ingress_priority_group_attribute(pg, &attr);
493-
if (status != SAI_STATUS_SUCCESS)
494-
{
495-
SWSS_LOG_ERROR("Failed to set buffer profile ID on pg 0x%" PRIx64 ": %d", pg, status);
496-
return;
497-
}
498-
499-
// Save original buffer profile
500-
m_originalPgBufferProfile = oldPgProfileId;
501472
}
502473

503474
PfcWdZeroBufferHandler::~PfcWdZeroBufferHandler(void)
@@ -523,26 +494,12 @@ PfcWdZeroBufferHandler::~PfcWdZeroBufferHandler(void)
523494
return;
524495
}
525496

526-
sai_object_id_t pg = portInstance.m_priority_group_ids[size_t(getQueueId())];
527-
528-
attr.id = SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE;
529-
attr.value.oid = m_originalPgBufferProfile;
530-
531-
// Set our zero buffer profile
532-
status = sai_buffer_api->set_ingress_priority_group_attribute(pg, &attr);
533-
if (status != SAI_STATUS_SUCCESS)
534-
{
535-
SWSS_LOG_ERROR("Failed to set buffer profile ID on queue 0x%" PRIx64 ": %d", getQueue(), status);
536-
return;
537-
}
538-
539-
setPriorityGroupAndQueueLockFlag(portInstance, false);
497+
setQueueLockFlag(portInstance, false);
540498
}
541499

542-
void PfcWdZeroBufferHandler::setPriorityGroupAndQueueLockFlag(Port& port, bool isLocked) const
500+
void PfcWdZeroBufferHandler::setQueueLockFlag(Port& port, bool isLocked) const
543501
{
544-
// set lock bits on PG and queue
545-
port.m_priority_group_lock[static_cast<size_t>(getQueueId())] = isLocked;
502+
// set lock bits on queue
546503
for (size_t i = 0; i < port.m_queue_ids.size(); ++i)
547504
{
548505
if (port.m_queue_ids[i] == getQueue())
@@ -562,9 +519,8 @@ PfcWdZeroBufferHandler::ZeroBufferProfile::~ZeroBufferProfile(void)
562519
{
563520
SWSS_LOG_ENTER();
564521

565-
// Destory ingress and egress prifiles and pools
566-
destroyZeroBufferProfile(true);
567-
destroyZeroBufferProfile(false);
522+
// Destory egress profiles and pools
523+
destroyZeroBufferProfile();
568524
}
569525

570526
PfcWdZeroBufferHandler::ZeroBufferProfile &PfcWdZeroBufferHandler::ZeroBufferProfile::getInstance(void)
@@ -576,19 +532,19 @@ PfcWdZeroBufferHandler::ZeroBufferProfile &PfcWdZeroBufferHandler::ZeroBufferPro
576532
return instance;
577533
}
578534

579-
sai_object_id_t PfcWdZeroBufferHandler::ZeroBufferProfile::getZeroBufferProfile(bool ingress)
535+
sai_object_id_t PfcWdZeroBufferHandler::ZeroBufferProfile::getZeroBufferProfile(void)
580536
{
581537
SWSS_LOG_ENTER();
582538

583-
if (getInstance().getProfile(ingress) == SAI_NULL_OBJECT_ID)
539+
if (getInstance().getProfile() == SAI_NULL_OBJECT_ID)
584540
{
585-
getInstance().createZeroBufferProfile(ingress);
541+
getInstance().createZeroBufferProfile();
586542
}
587543

588-
return getInstance().getProfile(ingress);
544+
return getInstance().getProfile();
589545
}
590546

591-
void PfcWdZeroBufferHandler::ZeroBufferProfile::createZeroBufferProfile(bool ingress)
547+
void PfcWdZeroBufferHandler::ZeroBufferProfile::createZeroBufferProfile(void)
592548
{
593549
SWSS_LOG_ENTER();
594550

@@ -601,15 +557,15 @@ void PfcWdZeroBufferHandler::ZeroBufferProfile::createZeroBufferProfile(bool ing
601557
attribs.push_back(attr);
602558

603559
attr.id = SAI_BUFFER_POOL_ATTR_TYPE;
604-
attr.value.u32 = ingress ? SAI_BUFFER_POOL_TYPE_INGRESS : SAI_BUFFER_POOL_TYPE_EGRESS;
560+
attr.value.u32 = SAI_BUFFER_POOL_TYPE_EGRESS;
605561
attribs.push_back(attr);
606562

607563
attr.id = SAI_BUFFER_POOL_ATTR_THRESHOLD_MODE;
608564
attr.value.u32 = SAI_BUFFER_POOL_THRESHOLD_MODE_DYNAMIC;
609565
attribs.push_back(attr);
610566

611567
sai_status_t status = sai_buffer_api->create_buffer_pool(
612-
&getPool(ingress),
568+
&getPool(),
613569
gSwitchId,
614570
static_cast<uint32_t>(attribs.size()),
615571
attribs.data());
@@ -623,7 +579,7 @@ void PfcWdZeroBufferHandler::ZeroBufferProfile::createZeroBufferProfile(bool ing
623579
attribs.clear();
624580

625581
attr.id = SAI_BUFFER_PROFILE_ATTR_POOL_ID;
626-
attr.value.oid = getPool(ingress);
582+
attr.value.oid = getPool();
627583
attribs.push_back(attr);
628584

629585
attr.id = SAI_BUFFER_PROFILE_ATTR_THRESHOLD_MODE;
@@ -639,7 +595,7 @@ void PfcWdZeroBufferHandler::ZeroBufferProfile::createZeroBufferProfile(bool ing
639595
attribs.push_back(attr);
640596

641597
status = sai_buffer_api->create_buffer_profile(
642-
&getProfile(ingress),
598+
&getProfile(),
643599
gSwitchId,
644600
static_cast<uint32_t>(attribs.size()),
645601
attribs.data());
@@ -650,18 +606,18 @@ void PfcWdZeroBufferHandler::ZeroBufferProfile::createZeroBufferProfile(bool ing
650606
}
651607
}
652608

653-
void PfcWdZeroBufferHandler::ZeroBufferProfile::destroyZeroBufferProfile(bool ingress)
609+
void PfcWdZeroBufferHandler::ZeroBufferProfile::destroyZeroBufferProfile(void)
654610
{
655611
SWSS_LOG_ENTER();
656612

657-
sai_status_t status = sai_buffer_api->remove_buffer_profile(getProfile(ingress));
613+
sai_status_t status = sai_buffer_api->remove_buffer_profile(getProfile());
658614
if (status != SAI_STATUS_SUCCESS)
659615
{
660616
SWSS_LOG_ERROR("Failed to remove static zero buffer profile for PFC WD: %d", status);
661617
return;
662618
}
663619

664-
status = sai_buffer_api->remove_buffer_pool(getPool(ingress));
620+
status = sai_buffer_api->remove_buffer_pool(getPool());
665621
if (status != SAI_STATUS_SUCCESS)
666622
{
667623
SWSS_LOG_ERROR("Failed to remove static zero buffer pool for PFC WD: %d", status);

orchagent/pfcactionhandler.h

+9-12
Original file line numberDiff line numberDiff line change
@@ -124,42 +124,39 @@ class PfcWdZeroBufferHandler: public PfcWdLossyHandler
124124

125125
private:
126126
/*
127-
* Sets lock bits on port's priority group and queue
127+
* Sets lock bits on port's queue
128128
* to protect them from beeing changed by other Orch's
129129
*/
130-
void setPriorityGroupAndQueueLockFlag(Port& port, bool isLocked) const;
130+
void setQueueLockFlag(Port& port, bool isLocked) const;
131131

132132
// Singletone class for keeping shared data - zero buffer profiles
133133
class ZeroBufferProfile
134134
{
135135
public:
136136
~ZeroBufferProfile(void);
137-
static sai_object_id_t getZeroBufferProfile(bool ingress);
137+
static sai_object_id_t getZeroBufferProfile(void);
138138

139139
private:
140140
ZeroBufferProfile(void);
141141
static ZeroBufferProfile &getInstance(void);
142-
void createZeroBufferProfile(bool ingress);
143-
void destroyZeroBufferProfile(bool ingress);
142+
void createZeroBufferProfile(void);
143+
void destroyZeroBufferProfile(void);
144144

145-
sai_object_id_t& getProfile(bool ingress)
145+
sai_object_id_t& getProfile(void)
146146
{
147-
return ingress ? m_zeroIngressBufferProfile : m_zeroEgressBufferProfile;
147+
return m_zeroEgressBufferProfile;
148148
}
149149

150-
sai_object_id_t& getPool(bool ingress)
150+
sai_object_id_t& getPool(void)
151151
{
152-
return ingress ? m_zeroIngressBufferPool : m_zeroEgressBufferPool;
152+
return m_zeroEgressBufferPool;
153153
}
154154

155-
sai_object_id_t m_zeroIngressBufferPool = SAI_NULL_OBJECT_ID;
156155
sai_object_id_t m_zeroEgressBufferPool = SAI_NULL_OBJECT_ID;
157-
sai_object_id_t m_zeroIngressBufferProfile = SAI_NULL_OBJECT_ID;
158156
sai_object_id_t m_zeroEgressBufferProfile = SAI_NULL_OBJECT_ID;
159157
};
160158

161159
sai_object_id_t m_originalQueueBufferProfile = SAI_NULL_OBJECT_ID;
162-
sai_object_id_t m_originalPgBufferProfile = SAI_NULL_OBJECT_ID;
163160
};
164161

165162
#endif

orchagent/port.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,13 @@ class Port
100100
uint32_t m_nat_zone_id = 0;
101101

102102
/*
103-
* Following two bit vectors are used to lock
104-
* the PG/queue from being changed in BufferOrch.
103+
* Following bit vector is used to lock
104+
* the queue from being changed in BufferOrch.
105105
* The use case scenario is when PfcWdZeroBufferHandler
106-
* sets zero buffer profile it should protect PG/queue
106+
* sets zero buffer profile it should protect queue
107107
* from being overwritten in BufferOrch.
108108
*/
109109
std::vector<bool> m_queue_lock;
110-
std::vector<bool> m_priority_group_lock;
111110

112111
bool m_fec_cfg = false;
113112
bool m_an_cfg = false;

orchagent/portsorch.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -2835,7 +2835,6 @@ void PortsOrch::initializePriorityGroups(Port &port)
28352835
SWSS_LOG_INFO("Get %d priority groups for port %s", attr.value.u32, port.m_alias.c_str());
28362836

28372837
port.m_priority_group_ids.resize(attr.value.u32);
2838-
port.m_priority_group_lock.resize(attr.value.u32);
28392838

28402839
if (attr.value.u32 == 0)
28412840
{

tests/mock_tests/portsorch_ut.cpp

+12-14
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ namespace portsorch_test
318318
TEST_F(PortsOrchTest, PfcZeroBufferHandlerLocksPortPgAndQueue)
319319
{
320320
Table portTable = Table(m_app_db.get(), APP_PORT_TABLE_NAME);
321-
Table pgTable = Table(m_config_db.get(), CFG_BUFFER_PG_TABLE_NAME);
321+
Table queueTable = Table(m_config_db.get(), CFG_BUFFER_QUEUE_TABLE_NAME);
322322
Table profileTable = Table(m_config_db.get(), CFG_BUFFER_PROFILE_TABLE_NAME);
323323
Table poolTable = Table(m_config_db.get(), CFG_BUFFER_POOL_TABLE_NAME);
324324

@@ -390,15 +390,13 @@ namespace portsorch_test
390390
poolTable.set(
391391
"test_pool",
392392
{
393-
{ "type", "ingress" },
393+
{ "type", "egress" },
394394
{ "mode", "dynamic" },
395395
{ "size", "4200000" },
396396
});
397397

398398
// Create test buffer profile
399399
profileTable.set("test_profile", { { "pool", "[BUFFER_POOL|test_pool]" },
400-
{ "xon", "14832" },
401-
{ "xoff", "14832" },
402400
{ "size", "35000" },
403401
{ "dynamic_th", "0" } });
404402

@@ -407,29 +405,29 @@ namespace portsorch_test
407405
{
408406
std::ostringstream oss;
409407
oss << it.first << "|3-4";
410-
pgTable.set(oss.str(), { { "profile", "[BUFFER_PROFILE|test_profile]" } });
408+
queueTable.set(oss.str(), { { "profile", "[BUFFER_PROFILE|test_profile]" } });
411409
}
412-
gBufferOrch->addExistingData(&pgTable);
410+
gBufferOrch->addExistingData(&queueTable);
413411
gBufferOrch->addExistingData(&poolTable);
414412
gBufferOrch->addExistingData(&profileTable);
415413

416-
// process pool, profile and PGs
414+
// process pool, profile and queues
417415
static_cast<Orch *>(gBufferOrch)->doTask();
418416

419-
auto pgConsumer = static_cast<Consumer*>(gBufferOrch->getExecutor(CFG_BUFFER_PG_TABLE_NAME));
420-
pgConsumer->dumpPendingTasks(ts);
421-
ASSERT_FALSE(ts.empty()); // PG is skipped
417+
auto queueConsumer = static_cast<Consumer*>(gBufferOrch->getExecutor(CFG_BUFFER_QUEUE_TABLE_NAME));
418+
queueConsumer->dumpPendingTasks(ts);
419+
ASSERT_FALSE(ts.empty()); // Queue is skipped
422420
ts.clear();
423421

424422
// release zero buffer drop handler
425423
dropHandler.reset();
426424

427-
// process PGs
425+
// process queue
428426
static_cast<Orch *>(gBufferOrch)->doTask();
429427

430-
pgConsumer = static_cast<Consumer*>(gBufferOrch->getExecutor(CFG_BUFFER_PG_TABLE_NAME));
431-
pgConsumer->dumpPendingTasks(ts);
432-
ASSERT_TRUE(ts.empty()); // PG should be proceesed now
428+
queueConsumer = static_cast<Consumer*>(gBufferOrch->getExecutor(CFG_BUFFER_QUEUE_TABLE_NAME));
429+
queueConsumer->dumpPendingTasks(ts);
430+
ASSERT_TRUE(ts.empty()); // Queue should be proceesed now
433431
ts.clear();
434432
}
435433

0 commit comments

Comments
 (0)