Skip to content

Commit 2176688

Browse files
[portsorch]: Bring the physical ports up are only after buffer configuration was applied (sonic-net#515)
* Don't up ports, until buffer configuration is applied * Set MTU first, then set port state to UP * Introduce the test * Use logical operator && for boolean values
1 parent 44309ef commit 2176688

File tree

5 files changed

+138
-14
lines changed

5 files changed

+138
-14
lines changed

orchagent/bufferorch.cpp

+76-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ BufferOrch::BufferOrch(DBConnector *db, vector<string> &tableNames) : Orch(db, t
2929
{
3030
SWSS_LOG_ENTER();
3131
initTableHandlers();
32+
initBufferReadyLists(db);
3233
};
3334

3435
void BufferOrch::initTableHandlers()
@@ -42,6 +43,59 @@ void BufferOrch::initTableHandlers()
4243
m_bufferHandlerMap.insert(buffer_handler_pair(CFG_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME, &BufferOrch::processEgressBufferProfileList));
4344
}
4445

46+
void BufferOrch::initBufferReadyLists(DBConnector *db)
47+
{
48+
SWSS_LOG_ENTER();
49+
50+
Table pg_table(db, CFG_BUFFER_PG_TABLE_NAME);
51+
initBufferReadyList(pg_table);
52+
53+
Table queue_table(db, CFG_BUFFER_QUEUE_TABLE_NAME);
54+
initBufferReadyList(queue_table);
55+
}
56+
57+
void BufferOrch::initBufferReadyList(Table& table)
58+
{
59+
SWSS_LOG_ENTER();
60+
61+
std::vector<std::string> keys;
62+
table.getKeys(keys);
63+
64+
for (const auto& key: keys)
65+
{
66+
m_ready_list[key] = false;
67+
68+
auto tokens = tokenize(key, config_db_key_delimiter);
69+
if (tokens.size() != 2)
70+
{
71+
SWSS_LOG_ERROR("Wrong format of a table '%s' key '%s'. Skip it", table.getTableName().c_str(), key.c_str());
72+
continue;
73+
}
74+
75+
auto port_names = tokenize(tokens[0], list_item_delimiter);
76+
77+
for(const auto& port_name: port_names)
78+
{
79+
m_port_ready_list_ref[port_name].push_back(key);
80+
}
81+
}
82+
}
83+
84+
bool BufferOrch::isPortReady(const std::string& port_name) const
85+
{
86+
SWSS_LOG_ENTER();
87+
88+
const auto& list_of_keys = m_port_ready_list_ref.at(port_name);
89+
90+
bool result = true;
91+
for (const auto& key: list_of_keys)
92+
{
93+
result = result && m_ready_list.at(key);
94+
}
95+
96+
return result;
97+
}
98+
4599
task_process_status BufferOrch::processBufferPool(Consumer &consumer)
46100
{
47101
SWSS_LOG_ENTER();
@@ -315,7 +369,7 @@ task_process_status BufferOrch::processQueue(Consumer &consumer)
315369
auto it = consumer.m_toSync.begin();
316370
KeyOpFieldsValuesTuple tuple = it->second;
317371
sai_object_id_t sai_buffer_profile;
318-
string key = kfvKey(tuple);
372+
const string key = kfvKey(tuple);
319373
string op = kfvOp(tuple);
320374
vector<string> tokens;
321375
sai_uint32_t range_low, range_high;
@@ -374,6 +428,16 @@ task_process_status BufferOrch::processQueue(Consumer &consumer)
374428
}
375429
}
376430
}
431+
432+
if (m_ready_list.find(key) != m_ready_list.end())
433+
{
434+
m_ready_list[key] = true;
435+
}
436+
else
437+
{
438+
SWSS_LOG_ERROR("Queue profile '%s' was inserted after BufferOrch init", key.c_str());
439+
}
440+
377441
return task_process_status::task_success;
378442
}
379443

@@ -386,7 +450,7 @@ task_process_status BufferOrch::processPriorityGroup(Consumer &consumer)
386450
auto it = consumer.m_toSync.begin();
387451
KeyOpFieldsValuesTuple tuple = it->second;
388452
sai_object_id_t sai_buffer_profile;
389-
string key = kfvKey(tuple);
453+
const string key = kfvKey(tuple);
390454
string op = kfvOp(tuple);
391455
vector<string> tokens;
392456
sai_uint32_t range_low, range_high;
@@ -451,6 +515,16 @@ task_process_status BufferOrch::processPriorityGroup(Consumer &consumer)
451515
}
452516
}
453517
}
518+
519+
if (m_ready_list.find(key) != m_ready_list.end())
520+
{
521+
m_ready_list[key] = true;
522+
}
523+
else
524+
{
525+
SWSS_LOG_ERROR("PG profile '%s' was inserted after BufferOrch init", key.c_str());
526+
}
527+
454528
return task_process_status::task_success;
455529
}
456530

orchagent/bufferorch.h

+7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#ifndef SWSS_BUFFORCH_H
22
#define SWSS_BUFFORCH_H
33

4+
#include <string>
45
#include <map>
6+
#include <unordered_map>
57
#include "orch.h"
68
#include "portsorch.h"
79

@@ -26,6 +28,7 @@ class BufferOrch : public Orch
2628
{
2729
public:
2830
BufferOrch(DBConnector *db, vector<string> &tableNames);
31+
bool isPortReady(const std::string& port_name) const;
2932
static type_map m_buffer_type_maps;
3033
private:
3134
typedef task_process_status (BufferOrch::*buffer_table_handler)(Consumer& consumer);
@@ -34,6 +37,8 @@ class BufferOrch : public Orch
3437

3538
virtual void doTask(Consumer& consumer);
3639
void initTableHandlers();
40+
void initBufferReadyLists(DBConnector *db);
41+
void initBufferReadyList(Table& table);
3742
task_process_status processBufferPool(Consumer &consumer);
3843
task_process_status processBufferProfile(Consumer &consumer);
3944
task_process_status processQueue(Consumer &consumer);
@@ -42,6 +47,8 @@ class BufferOrch : public Orch
4247
task_process_status processEgressBufferProfileList(Consumer &consumer);
4348

4449
buffer_table_handler_map m_bufferHandlerMap;
50+
std::unordered_map<std::string, bool> m_ready_list;
51+
std::unordered_map<std::string, std::vector<std::string>> m_port_ready_list_ref;
4552
};
4653
#endif /* SWSS_BUFFORCH_H */
4754

orchagent/orchdaemon.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ NeighOrch *gNeighOrch;
2626
RouteOrch *gRouteOrch;
2727
AclOrch *gAclOrch;
2828
CrmOrch *gCrmOrch;
29+
BufferOrch *gBufferOrch;
2930

3031
OrchDaemon::OrchDaemon(DBConnector *applDb, DBConnector *configDb, DBConnector *stateDb) :
3132
m_applDb(applDb),
@@ -90,7 +91,7 @@ bool OrchDaemon::init()
9091
CFG_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME,
9192
CFG_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME
9293
};
93-
BufferOrch *buffer_orch = new BufferOrch(m_configDb, buffer_tables);
94+
gBufferOrch = new BufferOrch(m_configDb, buffer_tables);
9495

9596
TableConnector appDbMirrorSession(m_applDb, APP_MIRROR_SESSION_TABLE_NAME);
9697
TableConnector confDbMirrorSession(m_configDb, CFG_MIRROR_SESSION_TABLE_NAME);
@@ -109,7 +110,7 @@ bool OrchDaemon::init()
109110

110111
gAclOrch = new AclOrch(acl_table_connectors, gPortsOrch, mirror_orch, gNeighOrch, gRouteOrch);
111112

112-
m_orchList = { switch_orch, gCrmOrch, gPortsOrch, intfs_orch, gNeighOrch, gRouteOrch, copp_orch, tunnel_decap_orch, qos_orch, buffer_orch, mirror_orch, gAclOrch, gFdbOrch, vrf_orch };
113+
m_orchList = { switch_orch, gCrmOrch, gPortsOrch, intfs_orch, gNeighOrch, gRouteOrch, copp_orch, tunnel_decap_orch, qos_orch, gBufferOrch, mirror_orch, gAclOrch, gFdbOrch, vrf_orch };
113114
m_select = new Select();
114115

115116

orchagent/portsorch.cpp

+19-10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "sai_serialize.h"
1919
#include "crmorch.h"
2020
#include "countercheckorch.h"
21+
#include "bufferorch.h"
2122
#include "notifier.h"
2223

2324
extern sai_switch_api_t *sai_switch_api;
@@ -31,6 +32,7 @@ extern sai_queue_api_t *sai_queue_api;
3132
extern sai_object_id_t gSwitchId;
3233
extern NeighOrch *gNeighOrch;
3334
extern CrmOrch *gCrmOrch;
35+
extern BufferOrch *gBufferOrch;
3436

3537
#define VLAN_PREFIX "Vlan"
3638
#define DEFAULT_VLAN_ID 1
@@ -1280,6 +1282,13 @@ void PortsOrch::doPortTask(Consumer &consumer)
12801282
continue;
12811283
}
12821284

1285+
if (alias != "PortConfigDone" && !gBufferOrch->isPortReady(alias))
1286+
{
1287+
// buffer configuration hasn't been applied yet. save it for future retry
1288+
it++;
1289+
continue;
1290+
}
1291+
12831292
Port p;
12841293
if (!getPort(alias, p) && alias != "PortConfigDone")
12851294
{
@@ -1332,31 +1341,31 @@ void PortsOrch::doPortTask(Consumer &consumer)
13321341
}
13331342
}
13341343

1335-
if (admin_status != "")
1344+
if (mtu != 0)
13361345
{
1337-
if (setPortAdminStatus(p.m_port_id, admin_status == "up"))
1346+
if (setPortMtu(p.m_port_id, mtu))
13381347
{
1339-
SWSS_LOG_NOTICE("Set port %s admin status to %s", alias.c_str(), admin_status.c_str());
1348+
p.m_mtu = mtu;
1349+
m_portList[alias] = p;
1350+
SWSS_LOG_NOTICE("Set port %s MTU to %u", alias.c_str(), mtu);
13401351
}
13411352
else
13421353
{
1343-
SWSS_LOG_ERROR("Failed to set port %s admin status to %s", alias.c_str(), admin_status.c_str());
1354+
SWSS_LOG_ERROR("Failed to set port %s MTU to %u", alias.c_str(), mtu);
13441355
it++;
13451356
continue;
13461357
}
13471358
}
13481359

1349-
if (mtu != 0)
1360+
if (admin_status != "")
13501361
{
1351-
if (setPortMtu(p.m_port_id, mtu))
1362+
if (setPortAdminStatus(p.m_port_id, admin_status == "up"))
13521363
{
1353-
p.m_mtu = mtu;
1354-
m_portList[alias] = p;
1355-
SWSS_LOG_NOTICE("Set port %s MTU to %u", alias.c_str(), mtu);
1364+
SWSS_LOG_NOTICE("Set port %s admin status to %s", alias.c_str(), admin_status.c_str());
13561365
}
13571366
else
13581367
{
1359-
SWSS_LOG_ERROR("Failed to set port %s MTU to %u", alias.c_str(), mtu);
1368+
SWSS_LOG_ERROR("Failed to set port %s admin status to %s", alias.c_str(), admin_status.c_str());
13601369
it++;
13611370
continue;
13621371
}

tests/test_port_buffer_rel.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from swsscommon import swsscommon
2+
import time
3+
4+
# The test check that the ports will be up, when the admin state is UP by conf db.
5+
6+
def test_PortsAreUpAfterBuffers(dvs):
7+
num_ports = 32
8+
asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)
9+
conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)
10+
11+
conf_port_table = swsscommon.Table(conf_db, "PORT")
12+
asic_port_table = swsscommon.Table(asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT")
13+
14+
# enable all ports
15+
fvs = swsscommon.FieldValuePairs([("admin_status", "up")])
16+
for i in range(0, num_ports):
17+
conf_port_table.set("Ethernet%d" % (i*4), fvs)
18+
19+
time.sleep(5)
20+
21+
# check that the ports are enabled in ASIC
22+
asic_port_records = asic_port_table.getKeys()
23+
assert len(asic_port_records) == (num_ports + 1), "Number of port records doesn't match number of ports" # +CPU port
24+
num_set = 0
25+
for k in asic_port_records:
26+
status, fvs = asic_port_table.get(k)
27+
assert status, "Got an error when get a key"
28+
for fv in fvs:
29+
if fv[0] == "SAI_PORT_ATTR_ADMIN_STATE":
30+
assert fv[1] == "true", "The port isn't UP as expected"
31+
num_set += 1
32+
# make sure that state is set for all "num_ports" ports
33+
assert num_set == num_ports, "Not all ports are up"

0 commit comments

Comments
 (0)