11#include " ut_helper.h"
22#include " mock_orchagent_main.h"
33#include " mock_table.h"
4+ #include " pfcactionhandler.h"
45
56#include < sstream>
67
@@ -14,12 +15,15 @@ namespace portsorch_test
1415 shared_ptr<swss::DBConnector> m_app_db;
1516 shared_ptr<swss::DBConnector> m_config_db;
1617 shared_ptr<swss::DBConnector> m_state_db;
18+ shared_ptr<swss::DBConnector> m_counters_db;
1719
1820 PortsOrchTest ()
1921 {
2022 // FIXME: move out from constructor
2123 m_app_db = make_shared<swss::DBConnector>(
2224 " APPL_DB" , 0 );
25+ m_counters_db = make_shared<swss::DBConnector>(
26+ " COUNTERS_DB" , 0 );
2327 m_config_db = make_shared<swss::DBConnector>(
2428 " CONFIG_DB" , 0 );
2529 m_state_db = make_shared<swss::DBConnector>(
@@ -310,4 +314,122 @@ namespace portsorch_test
310314 gBufferOrch ->dumpPendingTasks (ts);
311315 ASSERT_TRUE (ts.empty ());
312316 }
317+
318+ TEST_F (PortsOrchTest, PfcZeroBufferHandlerLocksPortPgAndQueue)
319+ {
320+ Table portTable = Table (m_app_db.get (), APP_PORT_TABLE_NAME);
321+ Table pgTable = Table (m_config_db.get (), CFG_BUFFER_PG_TABLE_NAME);
322+ Table profileTable = Table (m_config_db.get (), CFG_BUFFER_PROFILE_TABLE_NAME);
323+ Table poolTable = Table (m_config_db.get (), CFG_BUFFER_POOL_TABLE_NAME);
324+
325+ // Get SAI default ports to populate DB
326+ auto ports = ut_helper::getInitialSaiPorts ();
327+
328+ // Create dependencies ...
329+
330+ const int portsorch_base_pri = 40 ;
331+
332+ vector<table_name_with_pri_t > ports_tables = {
333+ { APP_PORT_TABLE_NAME, portsorch_base_pri + 5 },
334+ { APP_VLAN_TABLE_NAME, portsorch_base_pri + 2 },
335+ { APP_VLAN_MEMBER_TABLE_NAME, portsorch_base_pri },
336+ { APP_LAG_TABLE_NAME, portsorch_base_pri + 4 },
337+ { APP_LAG_MEMBER_TABLE_NAME, portsorch_base_pri }
338+ };
339+
340+ ASSERT_EQ (gPortsOrch , nullptr );
341+ gPortsOrch = new PortsOrch (m_app_db.get (), ports_tables);
342+ vector<string> buffer_tables = { CFG_BUFFER_POOL_TABLE_NAME,
343+ CFG_BUFFER_PROFILE_TABLE_NAME,
344+ CFG_BUFFER_QUEUE_TABLE_NAME,
345+ CFG_BUFFER_PG_TABLE_NAME,
346+ CFG_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME,
347+ CFG_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME };
348+
349+ ASSERT_EQ (gBufferOrch , nullptr );
350+ gBufferOrch = new BufferOrch (m_config_db.get (), buffer_tables);
351+
352+ // Populate port table with SAI ports
353+ for (const auto &it : ports)
354+ {
355+ portTable.set (it.first , it.second );
356+ }
357+
358+ // Set PortConfigDone, PortInitDone
359+ portTable.set (" PortConfigDone" , { { " count" , to_string (ports.size ()) } });
360+ portTable.set (" PortInitDone" , { { " lanes" , " 0" } });
361+
362+ // refill consumer
363+ gPortsOrch ->addExistingData (&portTable);
364+
365+ // Apply configuration :
366+ // create ports
367+
368+ static_cast <Orch *>(gPortsOrch )->doTask ();
369+
370+ // Apply configuration
371+ // ports
372+ static_cast <Orch *>(gPortsOrch )->doTask ();
373+
374+ ASSERT_TRUE (gPortsOrch ->allPortsReady ());
375+
376+ // No more tasks
377+ vector<string> ts;
378+ gPortsOrch ->dumpPendingTasks (ts);
379+ ASSERT_TRUE (ts.empty ());
380+ ts.clear ();
381+
382+ // Simulate storm drop handler started on Ethernet0 TC 3
383+ Port port;
384+ gPortsOrch ->getPort (" Ethernet0" , port);
385+
386+ auto countersTable = make_shared<Table>(m_counters_db.get (), COUNTERS_TABLE);
387+ auto dropHandler = make_unique<PfcWdZeroBufferHandler>(port.m_port_id , port.m_queue_ids [3 ], 3 , countersTable);
388+
389+ // Create test buffer pool
390+ poolTable.set (
391+ " test_pool" ,
392+ {
393+ { " type" , " ingress" },
394+ { " mode" , " dynamic" },
395+ { " size" , " 4200000" },
396+ });
397+
398+ // Create test buffer profile
399+ profileTable.set (" test_profile" , { { " pool" , " [BUFFER_POOL|test_pool]" },
400+ { " xon" , " 14832" },
401+ { " xoff" , " 14832" },
402+ { " size" , " 35000" },
403+ { " dynamic_th" , " 0" } });
404+
405+ // Apply profile on PGs 3-4 all ports
406+ for (const auto &it : ports)
407+ {
408+ std::ostringstream oss;
409+ oss << it.first << " |3-4" ;
410+ pgTable.set (oss.str (), { { " profile" , " [BUFFER_PROFILE|test_profile]" } });
411+ }
412+ gBufferOrch ->addExistingData (&pgTable);
413+ gBufferOrch ->addExistingData (&poolTable);
414+ gBufferOrch ->addExistingData (&profileTable);
415+
416+ // process pool, profile and PGs
417+ static_cast <Orch *>(gBufferOrch )->doTask ();
418+
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
422+ ts.clear ();
423+
424+ // release zero buffer drop handler
425+ dropHandler.reset ();
426+
427+ // process PGs
428+ static_cast <Orch *>(gBufferOrch )->doTask ();
429+
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
433+ ts.clear ();
434+ }
313435}
0 commit comments