Skip to content

Commit 3026945

Browse files
authored
Add Break Before Make mechanism to syncd comparison logic (sonic-net#642)
* [player] Add more log info when fail response * [syncd] Send notify view response even when exception happen * [vs] Add resource limiter * [vs] Start using resource limiter * [syncd] Fix vendor sai functions names check * [syncd] Add apply view remove object sanity checks * [syncd] Lower NPU switch log to notice * [syncd] Add simlar best match candidate with most same attributes * [syncd] Add BreakConfig class * [syncd] Add break config option to command line * [syncd] Add comparison logic break before make path * [syncd] Add break config parser * [syncd] Add break config size method * [syncd] Fix command line parser help message * [syncd] Start using break config parser * Update aspell * [tests] Add unittests
1 parent caa7ab2 commit 3026945

38 files changed

+1046
-25
lines changed

saiplayer/SaiPlayer.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,8 @@ void SaiPlayer::match_list_lengths(
321321

322322
if (get_attr_count != attr_count)
323323
{
324-
SWSS_LOG_THROW("list number don't match %u != %u", get_attr_count, attr_count);
324+
SWSS_LOG_THROW("list number don't match %u != %u (%s)", get_attr_count, attr_count,
325+
sai_serialize_object_type(object_type).c_str());
325326
}
326327

327328
for (uint32_t i = 0; i < attr_count; ++i)
@@ -447,7 +448,8 @@ void SaiPlayer::match_redis_with_rec(
447448

448449
if (get_attr_count != attr_count)
449450
{
450-
SWSS_LOG_THROW("list number don't match %u != %u", get_attr_count, attr_count);
451+
SWSS_LOG_THROW("list number don't match %u != %u (%s)", get_attr_count, attr_count,
452+
sai_serialize_object_type(object_type).c_str());
451453
}
452454

453455
for (uint32_t i = 0; i < attr_count; ++i)

syncd/AsicView.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,11 @@ void AsicView::asicRemoveObject(
754754

755755
SWSS_LOG_INFO("%s: %s", currentObj->m_str_object_type.c_str(), currentObj->m_str_object_id.c_str());
756756

757+
if (currentObj->getObjectStatus() != SAI_OBJECT_STATUS_NOT_PROCESSED)
758+
{
759+
SWSS_LOG_THROW("FATAL: removing object with status: %d, logic error", currentObj->getObjectStatus());
760+
}
761+
757762
m_asicOperationId++;
758763

759764
if (currentObj->isOidObject())
@@ -763,6 +768,16 @@ void AsicView::asicRemoveObject(
763768
* that check here also as sanity check.
764769
*/
765770

771+
int count = getVidReferenceCount(currentObj->getVid());
772+
773+
if (count != 0)
774+
{
775+
SWSS_LOG_THROW("can't remove existing object %s:%s since reference count is %d, FIXME",
776+
currentObj->m_str_object_type.c_str(),
777+
currentObj->m_str_object_id.c_str(),
778+
count);
779+
}
780+
766781
m_soOids.erase(currentObj->m_str_object_id);
767782
m_oOids.erase(currentObj->m_meta_key.objectkey.key.object_id);
768783

syncd/BestCandidateFinder.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,6 +2358,117 @@ std::shared_ptr<SaiObj> BestCandidateFinder::findCurrentBestMatch(
23582358
}
23592359
}
23602360

2361+
std::shared_ptr<SaiObj> BestCandidateFinder::findSimilarBestMatch(
2362+
_In_ const std::shared_ptr<const SaiObj> &temporaryObj)
2363+
{
2364+
SWSS_LOG_ENTER();
2365+
2366+
// will find object in current view that have most same attributes
2367+
2368+
auto notProcessedObjects = m_currentView.getNotProcessedObjectsByObjectType(temporaryObj->getObjectType());
2369+
2370+
const auto attrs = temporaryObj->getAllAttributes();
2371+
2372+
SWSS_LOG_INFO("not processed objects for %s: %zu, temp attrs: %zu",
2373+
temporaryObj->m_str_object_type.c_str(),
2374+
notProcessedObjects.size(),
2375+
attrs.size());
2376+
2377+
std::vector<sai_object_compare_info_t> candidateObjects;
2378+
2379+
for (const auto &currentObj: notProcessedObjects)
2380+
{
2381+
// log how many attributes current object have
2382+
2383+
SWSS_LOG_INFO("current obj %s, attrs: %zu",
2384+
currentObj->m_str_object_id.c_str(),
2385+
currentObj->getAllAttributes().size());
2386+
2387+
sai_object_compare_info_t soci = { 0, currentObj };
2388+
2389+
/*
2390+
* NOTE: we only iterate by attributes that are present in temporary
2391+
* view. It may happen that current view has some additional attributes
2392+
* set that are create only and value can't be updated, we ignore that
2393+
* since we want to find object with most matching attributes.
2394+
*/
2395+
2396+
for (const auto &attr: attrs)
2397+
{
2398+
sai_attr_id_t attrId = attr.first;
2399+
2400+
// Function hasEqualAttribute check if attribute exists on both objects.
2401+
2402+
if (hasEqualAttribute(m_currentView, m_temporaryView, currentObj, temporaryObj, attrId))
2403+
{
2404+
soci.equal_attributes++;
2405+
2406+
SWSS_LOG_INFO("ob equal %s %s, %s: %s",
2407+
temporaryObj->m_str_object_id.c_str(),
2408+
currentObj->m_str_object_id.c_str(),
2409+
attr.second->getStrAttrId().c_str(),
2410+
attr.second->getStrAttrValue().c_str());
2411+
}
2412+
else
2413+
{
2414+
SWSS_LOG_INFO("ob not equal %s %s, %s: %s",
2415+
temporaryObj->m_str_object_id.c_str(),
2416+
currentObj->m_str_object_id.c_str(),
2417+
attr.second->getStrAttrId().c_str(),
2418+
attr.second->getStrAttrValue().c_str());
2419+
}
2420+
}
2421+
2422+
// NOTE: we could check if current object has some attributes that are
2423+
// default value on temporary object, and count them in
2424+
2425+
candidateObjects.push_back(soci);
2426+
}
2427+
2428+
SWSS_LOG_INFO("number candidate objects for %s is %zu",
2429+
temporaryObj->m_str_object_id.c_str(),
2430+
candidateObjects.size());
2431+
2432+
if (candidateObjects.size() == 0)
2433+
{
2434+
SWSS_LOG_WARN("not processed objects in current view is zero");
2435+
2436+
return nullptr;
2437+
}
2438+
2439+
if (candidateObjects.size() == 1)
2440+
{
2441+
// We found only one object so return it as candidate
2442+
2443+
return candidateObjects.begin()->obj;
2444+
}
2445+
2446+
/*
2447+
* Sort candidate objects by equal attributes in descending order, we know
2448+
* here that we have at least 2 candidates.
2449+
*/
2450+
2451+
std::sort(candidateObjects.begin(), candidateObjects.end(), compareByEqualAttributes);
2452+
2453+
if (candidateObjects.at(0).equal_attributes > candidateObjects.at(1).equal_attributes)
2454+
{
2455+
/*
2456+
* We have only 1 object with the greatest number of equal attributes
2457+
* lets choose that object as our best match.
2458+
*/
2459+
2460+
SWSS_LOG_INFO("eq attributes: %ld vs %ld",
2461+
candidateObjects.at(0).equal_attributes,
2462+
candidateObjects.at(1).equal_attributes);
2463+
2464+
return candidateObjects.begin()->obj;
2465+
}
2466+
2467+
SWSS_LOG_WARN("same number of attributes equal, selecting first");
2468+
2469+
return candidateObjects.begin()->obj;
2470+
}
2471+
23612472
int BestCandidateFinder::findAllChildsInDependencyTreeCount(
23622473
_In_ const AsicView &view,
23632474
_In_ const std::shared_ptr<const SaiObj> &obj)

syncd/BestCandidateFinder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ namespace syncd
3535
std::shared_ptr<SaiObj> findCurrentBestMatch(
3636
_In_ const std::shared_ptr<const SaiObj> &temporaryObj);
3737

38+
std::shared_ptr<SaiObj> findSimilarBestMatch(
39+
_In_ const std::shared_ptr<const SaiObj> &temporaryObj);
40+
3841
private:
3942

4043
std::shared_ptr<SaiObj> findCurrentBestMatchForGenericObject(

syncd/BreakConfig.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "BreakConfig.h"
2+
3+
#include "swss/logger.h"
4+
5+
using namespace syncd;
6+
7+
void BreakConfig::insert(
8+
_In_ sai_object_type_t objectType)
9+
{
10+
SWSS_LOG_ENTER();
11+
12+
m_set.insert(objectType);
13+
}
14+
15+
void BreakConfig::remove(
16+
_In_ sai_object_type_t objectType)
17+
{
18+
SWSS_LOG_ENTER();
19+
20+
auto it = m_set.find(objectType);
21+
22+
if (it != m_set.end())
23+
{
24+
m_set.erase(it);
25+
}
26+
}
27+
28+
void BreakConfig::clear()
29+
{
30+
SWSS_LOG_ENTER();
31+
32+
m_set.clear();
33+
}
34+
35+
bool BreakConfig::shouldBreakBeforeMake(
36+
_In_ sai_object_type_t objectType) const
37+
{
38+
SWSS_LOG_ENTER();
39+
40+
return m_set.find(objectType) != m_set.end();
41+
}
42+
43+
size_t BreakConfig::size() const
44+
{
45+
SWSS_LOG_ENTER();
46+
47+
return m_set.size();
48+
}
49+

syncd/BreakConfig.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
extern "C"{
4+
#include "sai.h"
5+
}
6+
7+
#include <set>
8+
9+
namespace syncd
10+
{
11+
class BreakConfig
12+
{
13+
public:
14+
15+
BreakConfig() = default;
16+
17+
~BreakConfig() = default;
18+
19+
public:
20+
21+
void insert(
22+
_In_ sai_object_type_t objectType);
23+
24+
void remove(
25+
_In_ sai_object_type_t objectType);
26+
27+
void clear();
28+
29+
bool shouldBreakBeforeMake(
30+
_In_ sai_object_type_t objectType) const;
31+
32+
size_t size() const;
33+
34+
private:
35+
36+
std::set<sai_object_type_t> m_set;
37+
38+
};
39+
}

syncd/BreakConfigParser.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include "BreakConfigParser.h"
2+
3+
#include "swss/logger.h"
4+
5+
#include "meta/sai_serialize.h"
6+
7+
using namespace syncd;
8+
9+
std::shared_ptr<BreakConfig> BreakConfigParser::parseBreakConfig(
10+
_In_ const std::string& filePath)
11+
{
12+
SWSS_LOG_ENTER();
13+
14+
auto config = std::make_shared<BreakConfig>();
15+
16+
if (filePath.size() == 0)
17+
{
18+
return config; // return empty config
19+
}
20+
21+
std::ifstream file(filePath);
22+
23+
if (!file.is_open())
24+
{
25+
SWSS_LOG_ERROR("failed to open break config file: %s: errno: %s, returning empty config", filePath.c_str(), strerror(errno));
26+
27+
return config;
28+
}
29+
30+
std::string line;
31+
32+
while (getline(file, line))
33+
{
34+
if (line.size() > 0 && (line[0] == '#' || line[0] == ';'))
35+
{
36+
continue;
37+
}
38+
39+
sai_object_type_t objectType;
40+
41+
try
42+
{
43+
sai_deserialize_object_type(line, objectType);
44+
45+
config->insert(objectType);
46+
47+
SWSS_LOG_INFO("inserting %s to break config", line.c_str());
48+
}
49+
catch (const std::exception& e)
50+
{
51+
SWSS_LOG_WARN("failed to parse '%s' as sai_object_type_t", line.c_str());
52+
}
53+
}
54+
55+
SWSS_LOG_NOTICE("break config parse success, contains %zu entries", config->size());
56+
57+
58+
return config;
59+
}

syncd/BreakConfigParser.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include "BreakConfig.h"
4+
5+
#include <memory>
6+
7+
namespace syncd
8+
{
9+
class BreakConfigParser
10+
{
11+
private:
12+
13+
BreakConfigParser() = delete;
14+
15+
~BreakConfigParser() = delete;
16+
17+
public:
18+
19+
static std::shared_ptr<BreakConfig> parseBreakConfig(
20+
_In_ const std::string& filePath);
21+
22+
};
23+
}

syncd/CommandLineOptions.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ CommandLineOptions::CommandLineOptions()
2727

2828
m_contextConfig = "";
2929

30+
m_breakConfig = "";
31+
3032
#ifdef SAITHRIFT
3133

3234
m_runRPCServer = false;
@@ -53,6 +55,7 @@ std::string CommandLineOptions::getCommandLineString() const
5355
ss << " ProfileMapFile=" << m_profileMapFile;
5456
ss << " GlobalContext=" << m_globalContext;
5557
ss << " ContextConfig=" << m_contextConfig;
58+
ss << " BreakConfig=" << m_breakConfig;
5659

5760
#ifdef SAITHRIFT
5861

syncd/CommandLineOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ namespace syncd
7676

7777
std::string m_contextConfig;
7878

79+
std::string m_breakConfig;
80+
7981
#ifdef SAITHRIFT
8082
bool m_runRPCServer;
8183
std::string m_portMapFile;

0 commit comments

Comments
 (0)