Skip to content

Commit 4c8e2b5

Browse files
authored
[Dynamic Buffer Calc] Avoid creating lossy PG for admin down ports during initialization (sonic-net#1776)
- What I did Avoid creating lossy PGs for admin down ports during system initialization Make ADMIN_DOWN the default state of a port in dynamic buffer manager. Explicitly remove configured PGs from an admin down port during initialization This is to make sure the items will be added to m_ready_list. Use APPL_DB as the source of initial PGs and queues for port ready deducting for warm reboot Signed-off-by: Stephen Sun [email protected] - Why I did it Lossy PGs for admin down ports should not be applied to APPL_DB. Originally, we had the logic to remove lossy/lossless PGs when shutting a port. The same logic should be applied when the system is starting. Allocating lossy PG for an admin down port doesn't affect the system negatively except for wasting buffer. So we would like to resolve it. - How I verified it Manually test
1 parent 3602124 commit 4c8e2b5

File tree

5 files changed

+81
-21
lines changed

5 files changed

+81
-21
lines changed

cfgmgr/buffermgrdyn.cpp

+19-3
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,12 @@ task_process_status BufferMgrDynamic::doUpdatePgTask(const string &pg_key, const
10521052

10531053
case PORT_ADMIN_DOWN:
10541054
SWSS_LOG_NOTICE("Skip setting BUFFER_PG for %s because the port is administratively down", port.c_str());
1055+
if (!m_portInitDone)
1056+
{
1057+
// In case the port is admin down during initialization, the PG will be removed from the port,
1058+
// which effectively notifies bufferOrch to add the item to the m_ready_list
1059+
m_applBufferPgTable.del(pg_key);
1060+
}
10551061
break;
10561062

10571063
default:
@@ -1862,9 +1868,19 @@ task_process_status BufferMgrDynamic::handleOneBufferPgEntry(const string &key,
18621868
}
18631869
else
18641870
{
1865-
SWSS_LOG_NOTICE("Inserting BUFFER_PG table entry %s into APPL_DB directly", key.c_str());
1866-
m_applBufferPgTable.set(key, fvVector);
1867-
bufferPg.running_profile_name = bufferPg.configured_profile_name;
1871+
port_info_t &portInfo = m_portInfoLookup[port];
1872+
if (PORT_ADMIN_DOWN != portInfo.state)
1873+
{
1874+
SWSS_LOG_NOTICE("Inserting BUFFER_PG table entry %s into APPL_DB directly", key.c_str());
1875+
m_applBufferPgTable.set(key, fvVector);
1876+
bufferPg.running_profile_name = bufferPg.configured_profile_name;
1877+
}
1878+
else if (!m_portInitDone)
1879+
{
1880+
// In case the port is admin down during initialization, the PG will be removed from the port,
1881+
// which effectively notifies bufferOrch to add the item to the m_ready_list
1882+
m_applBufferPgTable.del(key);
1883+
}
18681884
}
18691885

18701886
if (!bufferPg.configured_profile_name.empty())

cfgmgr/buffermgrdyn.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ typedef struct {
7979
} buffer_pg_t;
8080

8181
typedef enum {
82+
// Port is admin down. All PGs programmed to APPL_DB should be removed from the port
83+
PORT_ADMIN_DOWN,
8284
// Port is under initializing, which means its info hasn't been comprehensive for calculating headroom
8385
PORT_INITIALIZING,
8486
// All necessary information for calculating headroom is ready
85-
PORT_READY,
86-
// Port is admin down. All PGs programmed to APPL_DB should be removed from the port
87-
PORT_ADMIN_DOWN
87+
PORT_READY
8888
} port_state_t;
8989

9090
typedef struct {

orchagent/bufferorch.cpp

+44-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "bufferorch.h"
33
#include "logger.h"
44
#include "sai_serialize.h"
5+
#include "warm_restart.h"
56

67
#include <inttypes.h>
78
#include <sstream>
@@ -45,7 +46,7 @@ BufferOrch::BufferOrch(DBConnector *applDb, DBConnector *confDb, DBConnector *st
4546
{
4647
SWSS_LOG_ENTER();
4748
initTableHandlers();
48-
initBufferReadyLists(confDb);
49+
initBufferReadyLists(applDb, confDb);
4950
initFlexCounterGroupTable();
5051
initBufferConstants();
5152
};
@@ -61,31 +62,62 @@ void BufferOrch::initTableHandlers()
6162
m_bufferHandlerMap.insert(buffer_handler_pair(APP_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME, &BufferOrch::processEgressBufferProfileList));
6263
}
6364

64-
void BufferOrch::initBufferReadyLists(DBConnector *db)
65+
void BufferOrch::initBufferReadyLists(DBConnector *applDb, DBConnector *confDb)
6566
{
66-
// The motivation of m_ready_list is to get the preconfigured buffer pg and buffer queue items
67-
// from the database when system starts.
68-
// When a buffer pg or queue item is updated, if the item isn't in the m_ready_list
67+
/*
68+
Map m_ready_list and m_port_ready_list_ref are designed to track whether the ports are "ready" from buffer's POV
69+
by testing whether all configured buffer PGs and queues have been applied to SAI. The idea is:
70+
- bufferorch read initial configuration and put them into m_port_ready_list_ref.
71+
- A buffer pg or queue item will be put into m_ready_list once it is applied to SAI.
72+
The rest of port initialization won't be started before the port being ready.
73+
74+
However, the items won't be applied to admin down ports in dynamic buffer model, which means the admin down ports won't be "ready"
75+
The solution is:
76+
- buffermgr to notify bufferorch explicitly to remove the PG and queue items configured on admin down ports
77+
- bufferorch to add the items to m_ready_list on receiving notifications, which is an existing logic
78+
79+
Theoretically, the initial configuration should come from CONFIG_DB but APPL_DB is used for warm reboot, because:
80+
- For cold/fast start, buffermgr is responsible for injecting items to APPL_DB
81+
There is no guarantee that items in APPL_DB are ready when orchagent starts
82+
- For warm reboot, APPL_DB is restored from the previous boot, which means they are ready when orchagent starts
83+
In addition, bufferorch won't be notified removal of items on admin down ports during warm reboot
84+
because buffermgrd hasn't been started yet.
85+
Using APPL_DB means items of admin down ports won't be inserted into m_port_ready_list_ref
86+
and guarantees the admin down ports always be ready in dynamic buffer model
87+
*/
6988
SWSS_LOG_ENTER();
7089

71-
Table pg_table(db, CFG_BUFFER_PG_TABLE_NAME);
72-
initBufferReadyList(pg_table);
90+
if (WarmStart::isWarmStart())
91+
{
92+
Table pg_table(applDb, APP_BUFFER_PG_TABLE_NAME);
93+
initBufferReadyList(pg_table, false);
7394

74-
Table queue_table(db, CFG_BUFFER_QUEUE_TABLE_NAME);
75-
initBufferReadyList(queue_table);
95+
Table queue_table(applDb, APP_BUFFER_QUEUE_TABLE_NAME);
96+
initBufferReadyList(queue_table, false);
97+
}
98+
else
99+
{
100+
Table pg_table(confDb, CFG_BUFFER_PG_TABLE_NAME);
101+
initBufferReadyList(pg_table, true);
102+
103+
Table queue_table(confDb, CFG_BUFFER_QUEUE_TABLE_NAME);
104+
initBufferReadyList(queue_table, true);
105+
}
76106
}
77107

78-
void BufferOrch::initBufferReadyList(Table& table)
108+
void BufferOrch::initBufferReadyList(Table& table, bool isConfigDb)
79109
{
80110
SWSS_LOG_ENTER();
81111

82112
std::vector<std::string> keys;
83113
table.getKeys(keys);
84114

115+
const char dbKeyDelimiter = (isConfigDb ? config_db_key_delimiter : delimiter);
116+
85117
// populate the lists with buffer configuration information
86118
for (const auto& key: keys)
87119
{
88-
auto tokens = tokenize(key, config_db_key_delimiter);
120+
auto &&tokens = tokenize(key, dbKeyDelimiter);
89121
if (tokens.size() != 2)
90122
{
91123
SWSS_LOG_ERROR("Wrong format of a table '%s' key '%s'. Skip it", table.getTableName().c_str(), key.c_str());
@@ -96,7 +128,7 @@ void BufferOrch::initBufferReadyList(Table& table)
96128
auto appldb_key = tokens[0] + delimiter + tokens[1];
97129
m_ready_list[appldb_key] = false;
98130

99-
auto port_names = tokenize(tokens[0], list_item_delimiter);
131+
auto &&port_names = tokenize(tokens[0], list_item_delimiter);
100132

101133
for(const auto& port_name: port_names)
102134
{

orchagent/bufferorch.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ class BufferOrch : public Orch
4646
void doTask() override;
4747
virtual void doTask(Consumer& consumer);
4848
void initTableHandlers();
49-
void initBufferReadyLists(DBConnector *db);
50-
void initBufferReadyList(Table& table);
49+
void initBufferReadyLists(DBConnector *confDb, DBConnector *applDb);
50+
void initBufferReadyList(Table& table, bool isConfigDb);
5151
void initFlexCounterGroupTable(void);
5252
void initBufferConstants();
5353
task_process_status processBufferPool(KeyOpFieldsValuesTuple &tuple);

tests/test_buffer_dynamic.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,9 @@ def test_sharedHeadroomPool(self, dvs, testlog):
548548
def test_shutdownPort(self, dvs, testlog):
549549
self.setup_db(dvs)
550550

551+
lossy_pg_reference_config_db = '[BUFFER_PROFILE|ingress_lossy_profile]'
552+
lossy_pg_reference_appl_db = '[BUFFER_PROFILE_TABLE:ingress_lossy_profile]'
553+
551554
# Startup interface
552555
dvs.runcmd('config interface startup Ethernet0')
553556

@@ -558,14 +561,23 @@ def test_shutdownPort(self, dvs, testlog):
558561

559562
# Shutdown port and check whether all the PGs have been removed
560563
dvs.runcmd("config interface shutdown Ethernet0")
564+
self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:0")
561565
self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:3-4")
562566
self.app_db.wait_for_deleted_entry("BUFFER_PROFILE", expectedProfile)
563567

564-
# Add another PG when port is administratively down
568+
# Add extra lossy and lossless PGs when a port is administratively down
569+
self.config_db.update_entry('BUFFER_PG', 'Ethernet0|1', {'profile': lossy_pg_reference_config_db})
565570
self.config_db.update_entry('BUFFER_PG', 'Ethernet0|6', {'profile': 'NULL'})
566571

572+
# Make sure they have not been added to APPL_DB
573+
time.sleep(30)
574+
self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:1")
575+
self.app_db.wait_for_deleted_entry("BUFFER_PG_TABLE", "Ethernet0:6")
576+
567577
# Startup port and check whether all the PGs haved been added
568578
dvs.runcmd("config interface startup Ethernet0")
579+
self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:0", {"profile": lossy_pg_reference_appl_db})
580+
self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:1", {"profile": lossy_pg_reference_appl_db})
569581
self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:3-4", {"profile": "[BUFFER_PROFILE_TABLE:" + expectedProfile + "]"})
570582
self.app_db.wait_for_field_match("BUFFER_PG_TABLE", "Ethernet0:6", {"profile": "[BUFFER_PROFILE_TABLE:" + expectedProfile + "]"})
571583

0 commit comments

Comments
 (0)