Skip to content

Commit 0429778

Browse files
kcudnikVolodymyr Samotiy
authored and
Volodymyr Samotiy
committed
Add check ASIC vs DB state after comparison logic (sonic-net#393)
* Add check ASIC vs DB state after comparison logic * Add aspell exceptions * Add cmd flag to enable consistency check explicitly
1 parent 9b00f38 commit 0429778

File tree

5 files changed

+245
-19
lines changed

5 files changed

+245
-19
lines changed

meta/sai_meta.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -2431,6 +2431,10 @@ sai_status_t meta_generic_validation_get(
24312431
// primitives
24322432
break;
24332433

2434+
case SAI_ATTR_VALUE_TYPE_ACL_CAPABILITY:
2435+
VALIDATION_LIST(md, value.aclcapability.action_list);
2436+
break;
2437+
24342438
default:
24352439

24362440
// acl capability will is more complex since is in/out we need to check stage

syncd/syncd.cpp

+35-13
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ std::map<sai_object_id_t, std::shared_ptr<SaiSwitch>> switches;
7070
*/
7171
std::set<sai_object_id_t> initViewRemovedVidSet;
7272

73+
/*
74+
* When set to true will enable DB vs ASIC consistency check after comparison
75+
* logic.
76+
*/
77+
bool g_enableConsistencyCheck = false;
78+
7379
/*
7480
* By default we are in APPLY mode.
7581
*/
@@ -1358,12 +1364,20 @@ sai_status_t handle_generic(
13581364
}
13591365

13601366
void translate_vid_to_rid_non_object_id(
1361-
_In_ sai_object_meta_key_t &meta_key)
1367+
_Inout_ sai_object_meta_key_t &meta_key)
13621368
{
13631369
SWSS_LOG_ENTER();
13641370

13651371
auto info = sai_metadata_get_object_type_info(meta_key.objecttype);
13661372

1373+
if (info->isobjectid)
1374+
{
1375+
meta_key.objectkey.key.object_id =
1376+
translate_vid_to_rid(meta_key.objectkey.key.object_id);
1377+
1378+
return;
1379+
}
1380+
13671381
for (size_t j = 0; j < info->structmemberscount; ++j)
13681382
{
13691383
const sai_struct_member_info_t *m = info->structmembers[j];
@@ -2942,6 +2956,8 @@ void printUsage()
29422956
std::cout << " Disable sleep when syncd crashes" << std::endl;
29432957
std::cout << " -U --eableUnittests" << std::endl;
29442958
std::cout << " Metadata enable unittests" << std::endl;
2959+
std::cout << " -C --eableConsistencyCheck" << std::endl;
2960+
std::cout << " Enable consisteny check DB vs ASIC after comparison logic" << std::endl;
29452961
#ifdef SAITHRIFT
29462962
std::cout << " -r --rpcserver" << std::endl;
29472963
std::cout << " Enable rpcserver" << std::endl;
@@ -2961,27 +2977,28 @@ void handleCmdLine(int argc, char **argv)
29612977

29622978
#ifdef SAITHRIFT
29632979
options.run_rpc_server = false;
2964-
const char* const optstring = "dNUt:p:i:rm:huS";
2980+
const char* const optstring = "dNUCt:p:i:rm:huS";
29652981
#else
2966-
const char* const optstring = "dNUt:p:i:huS";
2982+
const char* const optstring = "dNUCt:p:i:huS";
29672983
#endif // SAITHRIFT
29682984

29692985
while(true)
29702986
{
29712987
static struct option long_options[] =
29722988
{
2973-
{ "useTempView", no_argument, 0, 'u' },
2974-
{ "diag", no_argument, 0, 'd' },
2975-
{ "startType", required_argument, 0, 't' },
2976-
{ "profile", required_argument, 0, 'p' },
2977-
{ "help", no_argument, 0, 'h' },
2978-
{ "disableExitSleep", no_argument, 0, 'S' },
2979-
{ "enableUnittests", no_argument, 0, 'U' },
2989+
{ "useTempView", no_argument, 0, 'u' },
2990+
{ "diag", no_argument, 0, 'd' },
2991+
{ "startType", required_argument, 0, 't' },
2992+
{ "profile", required_argument, 0, 'p' },
2993+
{ "help", no_argument, 0, 'h' },
2994+
{ "disableExitSleep", no_argument, 0, 'S' },
2995+
{ "enableUnittests", no_argument, 0, 'U' },
2996+
{ "enableConsistencyCheck", no_argument, 0, 'C' },
29802997
#ifdef SAITHRIFT
2981-
{ "rpcserver", no_argument, 0, 'r' },
2982-
{ "portmap", required_argument, 0, 'm' },
2998+
{ "rpcserver", no_argument, 0, 'r' },
2999+
{ "portmap", required_argument, 0, 'm' },
29833000
#endif // SAITHRIFT
2984-
{ 0, 0, 0, 0 }
3001+
{ 0, 0, 0, 0 }
29853002
};
29863003

29873004
int option_index = 0;
@@ -3000,6 +3017,11 @@ void handleCmdLine(int argc, char **argv)
30003017
options.enableUnittests = true;
30013018
break;
30023019

3020+
case 'C':
3021+
SWSS_LOG_NOTICE("enable consistency check");
3022+
g_enableConsistencyCheck = true;
3023+
break;
3024+
30033025
case 'u':
30043026
SWSS_LOG_NOTICE("enable use temp view");
30053027
options.useTempView = true;

syncd/syncd.h

+10
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ void performWarmRestart();
7777

7878
sai_object_id_t translate_vid_to_rid(_In_ sai_object_id_t vid);
7979

80+
void translate_vid_to_rid_list(
81+
_In_ sai_object_type_t object_type,
82+
_In_ uint32_t attr_count,
83+
_In_ sai_attribute_t *attr_list);
84+
85+
void translate_vid_to_rid_non_object_id(
86+
_Inout_ sai_object_meta_key_t &meta_key);
87+
8088
void redisClearVidToRidMap();
8189
void redisClearRidToVidMap();
8290

@@ -86,6 +94,8 @@ sai_object_type_t getObjectTypeFromVid(
8694
extern std::shared_ptr<swss::NotificationProducer> notifications;
8795
extern std::shared_ptr<swss::RedisClient> g_redisClient;
8896

97+
extern bool g_enableConsistencyCheck;
98+
8999
sai_object_id_t redis_create_virtual_object_id(
90100
_In_ sai_object_id_t switch_id,
91101
_In_ sai_object_type_t object_type);

syncd/syncd_applyview.cpp

+192-5
Original file line numberDiff line numberDiff line change
@@ -2062,14 +2062,11 @@ bool hasEqualObjectList(
20622062
* @return True if attributes are equal, false otherwise.
20632063
*/
20642064
bool hasEqualQosMapList(
2065-
_In_ const std::shared_ptr<const SaiAttr> &current,
2066-
_In_ const std::shared_ptr<const SaiAttr> &temporary)
2065+
_In_ const sai_qos_map_list_t& c,
2066+
_In_ const sai_qos_map_list_t& t)
20672067
{
20682068
SWSS_LOG_ENTER();
20692069

2070-
auto c = current->getSaiAttr()->value.qosmap;
2071-
auto t = temporary->getSaiAttr()->value.qosmap;
2072-
20732070
if (c.count != t.count)
20742071
return false;
20752072

@@ -2102,6 +2099,18 @@ bool hasEqualQosMapList(
21022099
return true;
21032100
}
21042101

2102+
bool hasEqualQosMapList(
2103+
_In_ const std::shared_ptr<const SaiAttr> &current,
2104+
_In_ const std::shared_ptr<const SaiAttr> &temporary)
2105+
{
2106+
SWSS_LOG_ENTER();
2107+
2108+
auto c = current->getSaiAttr()->value.qosmap;
2109+
auto t = temporary->getSaiAttr()->value.qosmap;
2110+
2111+
return hasEqualQosMapList(c, t);
2112+
}
2113+
21052114
/**
21062115
* @brief Check if current and temporary object has
21072116
* the same attribute and attribute has the same value on both.
@@ -5992,6 +6001,9 @@ void processObjectForViewTransition(
59926001
*/
59936002
}
59946003

6004+
// No need to store VID since at this point we don't have RID yet, it will be
6005+
// created on execute asic and RID will be saved to maps in both views.
6006+
59956007
createNewObjectFromTemporaryObject(currentView, temporaryView, temporaryObj);
59966008

59976009
return;
@@ -6026,6 +6038,10 @@ void processObjectForViewTransition(
60266038
sai_object_id_t vid = temporaryObj->getVid();
60276039

60286040
currentView.insertNewVidReference(vid);
6041+
6042+
// save temporary vid to rid after match
6043+
// can't be here since vim to rid map will not match
6044+
// currentView.vidToRid[vid] = currentView.vidToRid.at(currentBestMatch->getVid());
60296045
}
60306046

60316047
performObjectSetTransition(currentView, temporaryView, currentBestMatch, temporaryObj, true);
@@ -6573,6 +6589,162 @@ void logViewObjectCount(
65736589
}
65746590
}
65756591

6592+
void checkAsicVsDatabaseConsistency(
6593+
_In_ const AsicView cur,
6594+
_In_ const AsicView &tmp)
6595+
{
6596+
SWSS_LOG_ENTER();
6597+
6598+
bool hasErrors = false;
6599+
6600+
{
6601+
SWSS_LOG_TIMER("consistency check");
6602+
6603+
SWSS_LOG_WARN("performing consistency check");
6604+
6605+
for (const auto &pair: tmp.soAll)
6606+
{
6607+
const auto &obj = pair.second;
6608+
6609+
const auto &attrs = obj->getAllAttributes();
6610+
6611+
// get object meta key for get (object id or *entry)
6612+
6613+
sai_object_meta_key_t meta_key = obj->meta_key;
6614+
6615+
// translate all VID's to RIDs in non object is's
6616+
6617+
translate_vid_to_rid_non_object_id(meta_key);
6618+
6619+
auto info = sai_metadata_get_object_type_info(obj->getObjectType());
6620+
6621+
sai_attribute_t attr;
6622+
6623+
memset(&attr, 0, sizeof(attr));
6624+
6625+
if (attrs.size() == 0)
6626+
{
6627+
// get first attribute and do a get query to see if object exist's
6628+
6629+
auto meta = info->attrmetadata[0];
6630+
6631+
sai_status_t status = info->get(&meta_key, 1, &attr);
6632+
6633+
switch (status)
6634+
{
6635+
case SAI_STATUS_SUCCESS:
6636+
case SAI_STATUS_BUFFER_OVERFLOW:
6637+
continue;
6638+
6639+
case SAI_STATUS_NOT_IMPLEMENTED:
6640+
case SAI_STATUS_NOT_SUPPORTED:
6641+
6642+
SWSS_LOG_WARN("GET api for %s is not implemented on %s",
6643+
meta->attridname,
6644+
obj->str_object_id.c_str());
6645+
continue;
6646+
}
6647+
6648+
SWSS_LOG_ERROR("failed to get %s on %s: %s",
6649+
meta->attridname,
6650+
obj->str_object_id.c_str(),
6651+
sai_serialize_status(status).c_str());
6652+
6653+
hasErrors = true;
6654+
6655+
continue;
6656+
}
6657+
6658+
for (const auto &ap: attrs)
6659+
{
6660+
const auto &saiAttr = ap.second;
6661+
6662+
auto meta = saiAttr->getAttrMetadata();
6663+
6664+
// deserialize existing attribute so deserialize will allocate
6665+
// memory for all list's
6666+
6667+
attr.id = meta->attrid;
6668+
6669+
sai_deserialize_attr_value(saiAttr->getStrAttrValue(), *meta, attr, false);
6670+
6671+
// translate all VIDs from DB to RIDs for compare
6672+
6673+
translate_vid_to_rid_list(obj->getObjectType(), 1, &attr);
6674+
6675+
// get attr value with RIDs
6676+
6677+
const std::string& dbValue = sai_serialize_attr_value(*meta, attr);
6678+
6679+
sai_status_t status = info->get(&meta_key, 1, &attr);
6680+
6681+
if (meta->attrid == SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST && meta->objecttype == SAI_OBJECT_TYPE_QOS_MAP && status == SAI_STATUS_SUCCESS)
6682+
{
6683+
// order does not matter on this list
6684+
6685+
if (hasEqualQosMapList(attr.value.qosmap, saiAttr->getSaiAttr()->value.qosmap))
6686+
{
6687+
sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
6688+
continue;
6689+
}
6690+
}
6691+
6692+
// free possible allocated lists
6693+
6694+
if (status != SAI_STATUS_SUCCESS)
6695+
{
6696+
SWSS_LOG_ERROR("failed to get %s on %s %s",
6697+
meta->attridname,
6698+
obj->str_object_id.c_str(),
6699+
sai_serialize_status(status).c_str());
6700+
6701+
hasErrors = true;
6702+
6703+
sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
6704+
continue;
6705+
}
6706+
6707+
const std::string &asicValue = sai_serialize_attr_value(*meta, attr);
6708+
6709+
sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
6710+
6711+
// pointers will not be equal since those will be from
6712+
// different process memory maps so just check if both pointers
6713+
// are NULL or both are SET
6714+
6715+
if (meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_POINTER)
6716+
{
6717+
if (attr.value.ptr == NULL && saiAttr->getSaiAttr()->value.ptr == NULL)
6718+
continue;
6719+
6720+
if (attr.value.ptr != NULL && saiAttr->getSaiAttr()->value.ptr != NULL)
6721+
continue;
6722+
}
6723+
6724+
if (asicValue == dbValue)
6725+
continue;
6726+
6727+
SWSS_LOG_ERROR("value missmatch: %s on %s: ASIC: %s DB: %s, inconsistent state!",
6728+
meta->attridname,
6729+
obj->str_object_id.c_str(),
6730+
asicValue.c_str(),
6731+
dbValue.c_str());
6732+
6733+
hasErrors = true;
6734+
}
6735+
}
6736+
6737+
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_INFO);
6738+
}
6739+
6740+
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE);
6741+
6742+
if (hasErrors && enableUnittests())
6743+
{
6744+
SWSS_LOG_THROW("ASIC content is differnt than DB content!");
6745+
}
6746+
}
6747+
65766748
sai_status_t syncdApplyView()
65776749
{
65786750
SWSS_LOG_ENTER();
@@ -6792,6 +6964,11 @@ sai_status_t syncdApplyView()
67926964

67936965
updateRedisDatabase(current, temp);
67946966

6967+
if (g_enableConsistencyCheck)
6968+
{
6969+
checkAsicVsDatabaseConsistency(current, temp);
6970+
}
6971+
67956972
return SAI_STATUS_SUCCESS;
67966973
}
67976974

@@ -6845,6 +7022,8 @@ sai_object_id_t asic_translate_vid_to_rid(
68457022

68467023
sai_object_id_t rid = currentIt->second;
68477024

7025+
SWSS_LOG_INFO("translated VID 0x%lx to RID 0x%lx", vid, rid);
7026+
68487027
return rid;
68497028
}
68507029

@@ -7099,6 +7278,14 @@ void asic_translate_vid_to_rid_non_object_id(
70997278

71007279
auto info = sai_metadata_get_object_type_info(meta_key.objecttype);
71017280

7281+
if (info->isobjectid)
7282+
{
7283+
meta_key.objectkey.key.object_id =
7284+
asic_translate_vid_to_rid(current, temporary, meta_key.objectkey.key.object_id);
7285+
7286+
return;
7287+
}
7288+
71027289
for (size_t idx = 0; idx < info->structmemberscount; ++idx)
71037290
{
71047291
const sai_struct_member_info_t *m = info->structmembers[idx];

0 commit comments

Comments
 (0)