Skip to content

Commit bd132ec

Browse files
authored
Add synchronous mode to sairedis library (sonic-net#617)
* [saiplayer] Add sync mode to saiplayer * [syncd] Add RedisClient more redis methods * [syncd] Update redis db in syncd only when success * [test] Add sync mode unittest
1 parent 0a77a09 commit bd132ec

10 files changed

+231
-11
lines changed

saiplayer/CommandLineOptions.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ CommandLineOptions::CommandLineOptions()
1717
m_skipNotifySyncd = false;
1818
m_enableDebug = false;
1919
m_sleep = false;
20+
m_syncMode = false;
2021
}
2122

2223
std::string CommandLineOptions::getCommandLineString() const
@@ -30,6 +31,7 @@ std::string CommandLineOptions::getCommandLineString() const
3031
ss << " SkipNotifySyncd=" << (m_skipNotifySyncd ? "YES" : "NO");
3132
ss << " EnableDebug=" << (m_enableDebug ? "YES" : "NO");
3233
ss << " Sleep=" << (m_sleep ? "YES" : "NO");
34+
ss << " SyncMode=" << (m_syncMode ? "YES" : "NO");
3335

3436
return ss.str();
3537
}

saiplayer/CommandLineOptions.h

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ namespace saiplayer
3131

3232
bool m_sleep;
3333

34+
bool m_syncMode;
35+
3436
std::vector<std::string> m_files;
3537
};
3638
}

saiplayer/CommandLineOptionsParser.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ std::shared_ptr<CommandLineOptions> CommandLineOptionsParser::parseCommandLine(
1616

1717
auto options = std::make_shared<CommandLineOptions>();
1818

19-
const char* const optstring = "uiCdsh";
19+
const char* const optstring = "uiCdsmh";
2020

2121
while(true)
2222
{
@@ -27,6 +27,7 @@ std::shared_ptr<CommandLineOptions> CommandLineOptionsParser::parseCommandLine(
2727
{ "skipNotifySyncd", no_argument, 0, 'C' },
2828
{ "enableDebug", no_argument, 0, 'd' },
2929
{ "sleep", no_argument, 0, 's' },
30+
{ "syncMode", no_argument, 0, 'm' },
3031
{ "help", no_argument, 0, 'h' },
3132
};
3233

@@ -61,6 +62,10 @@ std::shared_ptr<CommandLineOptions> CommandLineOptionsParser::parseCommandLine(
6162
options->m_sleep = true;
6263
break;
6364

65+
case 'm':
66+
options->m_syncMode = true;
67+
break;
68+
6469
case 'h':
6570
printUsage();
6671
exit(EXIT_SUCCESS);
@@ -95,7 +100,7 @@ void CommandLineOptionsParser::printUsage()
95100
{
96101
SWSS_LOG_ENTER();
97102

98-
std::cout << "Usage: saiplayer [-u] [-i] [-C] [-d] [-s] [-h] recordfile" << std::endl << std::endl;
103+
std::cout << "Usage: saiplayer [-u] [-i] [-C] [-d] [-s] [-m] [-h] recordfile" << std::endl << std::endl;
99104

100105
std::cout << " -u --useTempView:" << std::endl;
101106
std::cout << " Enable temporary view between init and apply" << std::endl << std::endl;
@@ -107,6 +112,8 @@ void CommandLineOptionsParser::printUsage()
107112
std::cout << " Enable syslog debug messages" << std::endl << std::endl;
108113
std::cout << " -s --sleep:" << std::endl;
109114
std::cout << " Sleep after success reply, to notice any switch notifications" << std::endl << std::endl;
115+
std::cout << " -m --syncMode:" << std::endl;
116+
std::cout << " Enable synchronous mode" << std::endl << std::endl;
110117

111118
std::cout << " -h --help:" << std::endl;
112119
std::cout << " Print out this message" << std::endl << std::endl;

saiplayer/SaiPlayer.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,14 @@ int SaiPlayer::run()
15241524
EXIT_ON_ERROR(m_sai->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr));
15251525
}
15261526

1527+
if (m_commandLineOptions->m_syncMode)
1528+
{
1529+
attr.id = SAI_REDIS_SWITCH_ATTR_SYNC_MODE;
1530+
attr.value.booldata = true;
1531+
1532+
EXIT_ON_ERROR(m_sai->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr));
1533+
}
1534+
15271535
int exitcode = 0;
15281536

15291537
if (m_commandLineOptions->m_files.size() > 0)

syncd/RedisClient.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,16 @@ void RedisClient::removeAsicObject(
479479
m_redisClient->del(key);
480480
}
481481

482+
void RedisClient::removeTempAsicObject(
483+
_In_ const sai_object_meta_key_t& metaKey)
484+
{
485+
SWSS_LOG_ENTER();
486+
487+
std::string key = (TEMP_PREFIX ASIC_STATE_TABLE ":") + sai_serialize_object_meta_key(metaKey);
488+
489+
m_redisClient->del(key);
490+
}
491+
482492
void RedisClient::setAsicObject(
483493
_In_ const sai_object_meta_key_t& metaKey,
484494
_In_ const std::string& attr,
@@ -523,6 +533,26 @@ void RedisClient::createAsicObject(
523533
}
524534
}
525535

536+
void RedisClient::createTempAsicObject(
537+
_In_ const sai_object_meta_key_t& metaKey,
538+
_In_ const std::vector<swss::FieldValueTuple>& attrs)
539+
{
540+
SWSS_LOG_ENTER();
541+
542+
std::string key = (TEMP_PREFIX ASIC_STATE_TABLE ":") + sai_serialize_object_meta_key(metaKey);
543+
544+
if (attrs.size() == 0)
545+
{
546+
m_redisClient->hset(key, "NULL", "NULL");
547+
return;
548+
}
549+
550+
for (const auto& e: attrs)
551+
{
552+
m_redisClient->hset(key, fvField(e), fvValue(e));
553+
}
554+
}
555+
526556
void RedisClient::setVidAndRidMap(
527557
_In_ const std::unordered_map<sai_object_id_t, sai_object_id_t>& map)
528558
{

syncd/RedisClient.h

+7
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,17 @@ namespace syncd
8383
void removeAsicObject(
8484
_In_ const sai_object_meta_key_t& metaKey);
8585

86+
void removeTempAsicObject(
87+
_In_ const sai_object_meta_key_t& metaKey);
88+
8689
void createAsicObject(
8790
_In_ const sai_object_meta_key_t& metaKey,
8891
_In_ const std::vector<swss::FieldValueTuple>& attrs);
8992

93+
void createTempAsicObject(
94+
_In_ const sai_object_meta_key_t& metaKey,
95+
_In_ const std::vector<swss::FieldValueTuple>& attrs);
96+
9097
void setVidAndRidMap(
9198
_In_ const std::unordered_map<sai_object_id_t, sai_object_id_t>& map);
9299

syncd/Syncd.cpp

+109-7
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ Syncd::Syncd(
8585
m_asicState = std::make_shared<swss::ConsumerTable>(m_dbAsic.get(), ASIC_STATE_TABLE);
8686
m_restartQuery = std::make_shared<swss::NotificationConsumer>(m_dbAsic.get(), SYNCD_NOTIFICATION_CHANNEL_RESTARTQUERY);
8787

88+
m_asicState->setModifyRedis(m_commandLineOptions->m_enableSyncMode ? false : true);
89+
8890
// TODO to be moved to ASIC_DB
8991
m_dbFlexCounter = std::make_shared<swss::DBConnector>(m_contextConfig->m_dbFlex, 0);
9092
m_flexCounter = std::make_shared<swss::ConsumerTable>(m_dbFlexCounter.get(), FLEX_COUNTER_TABLE);
@@ -663,6 +665,13 @@ sai_status_t Syncd::processBulkQuadEventInInitViewMode(
663665
{
664666
SWSS_LOG_ENTER();
665667

668+
std::vector<sai_status_t> statuses(object_ids.size());
669+
670+
for (auto &a: statuses)
671+
{
672+
a = SAI_STATUS_SUCCESS;
673+
}
674+
666675
auto info = sai_metadata_get_object_type_info(objectType);
667676

668677
switch (api)
@@ -673,7 +682,7 @@ sai_status_t Syncd::processBulkQuadEventInInitViewMode(
673682

674683
if (info->isnonobjectid)
675684
{
676-
sendApiResponse(api, SAI_STATUS_SUCCESS);
685+
sendApiResponse(api, SAI_STATUS_SUCCESS, (uint32_t)statuses.size(), statuses.data());
677686
return SAI_STATUS_SUCCESS;
678687
}
679688

@@ -689,7 +698,7 @@ sai_status_t Syncd::processBulkQuadEventInInitViewMode(
689698

690699
default:
691700

692-
sendApiResponse(api, SAI_STATUS_SUCCESS);
701+
sendApiResponse(api, SAI_STATUS_SUCCESS, (uint32_t)statuses.size(), statuses.data());
693702
return SAI_STATUS_SUCCESS;
694703
}
695704

@@ -1280,6 +1289,88 @@ void Syncd::processFlexCounterEvent( // TODO must be moved to go via ASIC channe
12801289
}
12811290
}
12821291

1292+
void Syncd::syncUpdateRedisQuadEvent(
1293+
_In_ sai_status_t status,
1294+
_In_ sai_common_api_t api,
1295+
_In_ const swss::KeyOpFieldsValuesTuple &kco)
1296+
{
1297+
SWSS_LOG_ENTER();
1298+
1299+
if (!m_commandLineOptions->m_enableSyncMode)
1300+
{
1301+
return;
1302+
}
1303+
1304+
if (status != SAI_STATUS_SUCCESS)
1305+
{
1306+
return;
1307+
}
1308+
1309+
// When in synchronous mode, we need to modify redis database when status
1310+
// is success, since consumer table on synchronous mode is not making redis
1311+
// changes and we only want to apply changes when api succeeded. This
1312+
// applies to init view mode and apply view mode.
1313+
1314+
const std::string& key = kfvKey(kco);
1315+
1316+
auto& values = kfvFieldsValues(kco);
1317+
1318+
const std::string& strObjectId = key.substr(key.find(":") + 1);
1319+
1320+
sai_object_meta_key_t metaKey;
1321+
sai_deserialize_object_meta_key(key, metaKey);
1322+
1323+
const bool initView = isInitViewMode();
1324+
1325+
switch (api)
1326+
{
1327+
case SAI_COMMON_API_CREATE:
1328+
1329+
{
1330+
if (initView)
1331+
m_client->createTempAsicObject(metaKey, values);
1332+
else
1333+
m_client->createAsicObject(metaKey, values);
1334+
1335+
return;
1336+
}
1337+
1338+
case SAI_COMMON_API_REMOVE:
1339+
1340+
{
1341+
if (initView)
1342+
m_client->removeTempAsicObject(metaKey);
1343+
else
1344+
m_client->removeAsicObject(metaKey);
1345+
1346+
return;
1347+
}
1348+
1349+
case SAI_COMMON_API_SET:
1350+
1351+
{
1352+
auto& first = values.at(0);
1353+
1354+
auto& attr = fvField(first);
1355+
auto& value = fvValue(first);
1356+
1357+
if (initView)
1358+
m_client->setTempAsicObject(metaKey, attr, value);
1359+
else
1360+
m_client->setAsicObject(metaKey, attr, value);
1361+
1362+
return;
1363+
}
1364+
1365+
case SAI_COMMON_API_GET:
1366+
return; // ignore get since get is not modifying db
1367+
1368+
default:
1369+
1370+
SWSS_LOG_THROW("api %d is not supported", api);
1371+
}
1372+
}
1373+
12831374
sai_status_t Syncd::processQuadEvent(
12841375
_In_ sai_common_api_t api,
12851376
_In_ const swss::KeyOpFieldsValuesTuple &kco)
@@ -1338,7 +1429,11 @@ sai_status_t Syncd::processQuadEvent(
13381429

13391430
if (isInitViewMode())
13401431
{
1341-
return processQuadEventInInitViewMode(metaKey.objecttype, strObjectId, api, attr_count, attr_list);
1432+
sai_status_t status = processQuadEventInInitViewMode(metaKey.objecttype, strObjectId, api, attr_count, attr_list);
1433+
1434+
syncUpdateRedisQuadEvent(status, api, kco);
1435+
1436+
return status;
13421437
}
13431438

13441439
if (api != SAI_COMMON_API_GET)
@@ -1402,16 +1497,23 @@ sai_status_t Syncd::processQuadEvent(
14021497
SWSS_LOG_ERROR("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str());
14031498
}
14041499

1405-
SWSS_LOG_THROW("failed to execute api: %s, key: %s, status: %s",
1406-
op.c_str(),
1407-
key.c_str(),
1408-
sai_serialize_status(status).c_str());
1500+
if (!m_commandLineOptions->m_enableSyncMode)
1501+
{
1502+
// throw only when sync mode is not enabled
1503+
1504+
SWSS_LOG_THROW("failed to execute api: %s, key: %s, status: %s",
1505+
op.c_str(),
1506+
key.c_str(),
1507+
sai_serialize_status(status).c_str());
1508+
}
14091509
}
14101510
else // non GET api, status is SUCCESS
14111511
{
14121512
sendApiResponse(api, status);
14131513
}
14141514

1515+
syncUpdateRedisQuadEvent(status, api, kco);
1516+
14151517
return status;
14161518
}
14171519

syncd/Syncd.h

+7
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ namespace syncd
214214
_In_ uint32_t attr_count,
215215
_In_ sai_attribute_t *attr_list);
216216

217+
private:
218+
219+
void syncUpdateRedisQuadEvent(
220+
_In_ sai_status_t status,
221+
_In_ sai_common_api_t api,
222+
_In_ const swss::KeyOpFieldsValuesTuple &kco);
223+
217224
public: // TODO to private
218225

219226
sai_status_t processEntry(

tests/brcm.pl

+15
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,20 @@ sub test_brcm_warm_boot_port_remove
504504
request_warm_shutdown;
505505
}
506506

507+
sub test_sync_brcm_warm_boot_port_remove
508+
{
509+
sync_fresh_start;
510+
511+
sync_play "wb_port_remove_a.rec";
512+
513+
request_warm_shutdown;
514+
sync_start_syncd_warm;
515+
516+
sync_play "wb_port_remove_b.rec";
517+
518+
request_warm_shutdown;
519+
}
520+
507521
sub test_brcm_warm_boot_port_create
508522
{
509523
fresh_start;
@@ -534,6 +548,7 @@ sub test_brcm_query_object_type_get_availability
534548

535549
# RUN TESTS
536550

551+
test_sync_brcm_warm_boot_port_remove;
537552
test_brcm_warm_boot_port_remove;
538553
test_brcm_warm_boot_port_create;
539554
test_remove_port;

0 commit comments

Comments
 (0)