Skip to content

Commit e1354fe

Browse files
authored
Add pre match to comparison logic and unittests (#423)
* Add pre match to comparison logic and unittests * Fix spelling * Address comments
1 parent 18a5ebb commit e1354fe

File tree

4 files changed

+2483
-9
lines changed

4 files changed

+2483
-9
lines changed

syncd/syncd_applyview.cpp

+200-9
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,8 @@ class AsicView
563563
sai_deserialize_route_entry(o->str_object_id, o->meta_key.objectkey.key.route_entry);
564564
soRoutes[o->str_object_id] = o;
565565

566+
routesByPrefix[sai_serialize_ip_prefix(o->meta_key.objectkey.key.route_entry.destination)].push_back(o->str_object_id);
567+
566568
break;
567569

568570
default:
@@ -850,6 +852,8 @@ class AsicView
850852
StrObjectIdToSaiObjectHash soOids;
851853
StrObjectIdToSaiObjectHash soAll;
852854

855+
std::unordered_map<std::string,std::vector<std::string>> routesByPrefix;
856+
853857
private:
854858

855859
std::map<sai_object_type_t, StrObjectIdToSaiObjectHash> sotAll;
@@ -858,6 +862,8 @@ class AsicView
858862

859863
ObjectIdToSaiObjectHash oOids;
860864

865+
std::unordered_map<sai_object_id_t, sai_object_id_t> preMatchMap;
866+
861867
/*
862868
* On temp view this needs to be used for actual NEW rids created and
863869
* then reused with rid mapping to create new rid/vid map.
@@ -2517,7 +2523,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForLag(
25172523

25182524
if (temporaryLagMemberPortVid == SAI_NULL_OBJECT_ID)
25192525
{
2520-
SWSS_LOG_WARN("failed to find temporary LAG member for LAG %s", sai_serialize_object_id(tmpLagVid).c_str());
2526+
SWSS_LOG_NOTICE("failed to find temporary LAG member for LAG %s", sai_serialize_object_id(tmpLagVid).c_str());
25212527

25222528
return nullptr;
25232529
}
@@ -2563,7 +2569,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForLag(
25632569
}
25642570
}
25652571

2566-
SWSS_LOG_WARN("failed to find best candidate for LAG using LAG member and port id: tmp %s", temporaryObj->str_object_id.c_str());
2572+
SWSS_LOG_NOTICE("failed to find best candidate for LAG using LAG member and port");
25672573

25682574
return nullptr;
25692575
}
@@ -2655,7 +2661,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForNextHopGroup(
26552661
}
26562662
}
26572663

2658-
SWSS_LOG_NOTICE("failed to find best candidate for next hop group using route_entry");
2664+
SWSS_LOG_NOTICE("failed to find best candidate for NEXT_HOP_GROUP using route_entry");
26592665

26602666
return nullptr;
26612667
}
@@ -2804,7 +2810,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForAclTableGroup(
28042810
}
28052811
}
28062812

2807-
SWSS_LOG_NOTICE("failed to find best candidate for ACL table group using port");
2813+
SWSS_LOG_NOTICE("failed to find best candidate for ACL_TABLE_GROUP using port");
28082814

28092815
return nullptr;
28102816
}
@@ -2899,7 +2905,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForAclTable(
28992905
}
29002906
}
29012907

2902-
SWSS_LOG_NOTICE("failed to find best candidate for ACL table using port");
2908+
SWSS_LOG_NOTICE("failed to find best candidate for ACL_TABLE using port");
29032909

29042910
return nullptr;
29052911
}
@@ -3095,7 +3101,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForRouterInterface(
30953101
}
30963102
}
30973103

3098-
SWSS_LOG_NOTICE("failed to find best candidate for LOOPBACK ROUTER_INTERFACE using TUNNEL");
3104+
SWSS_LOG_NOTICE("failed to find best candidate for LOOPBACK ROUTER_INTERFACE using tunnel");
30993105

31003106
return nullptr;
31013107
}
@@ -3281,7 +3287,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForHostifTrapGroup(
32813287
}
32823288
}
32833289

3284-
SWSS_LOG_NOTICE("failed to find best candidate for HOSTIF TRAP GROUP using hostif trap");
3290+
SWSS_LOG_NOTICE("failed to find best candidate for HOSTIF_TRAP_GROUP using hostif trap");
32853291

32863292
return nullptr;
32873293
}
@@ -3414,7 +3420,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForBufferPool(
34143420

34153421
}
34163422

3417-
SWSS_LOG_NOTICE("failed to find best candidate for BUFFER POOL using buffer profile, ipg and queue");
3423+
SWSS_LOG_NOTICE("failed to find best candidate for BUFFER_POOL using buffer profile, ipg and queue");
34183424

34193425
return nullptr;
34203426
}
@@ -3509,7 +3515,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForBufferProfile(
35093515
}
35103516
}
35113517

3512-
SWSS_LOG_NOTICE("failed to find best candidate for BUFFER PROFILE using queues and ipgs");
3518+
SWSS_LOG_NOTICE("failed to find best candidate for BUFFER_PROFILE using queues and ipgs");
35133519

35143520
return nullptr;
35153521
}
@@ -3571,6 +3577,38 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForWred(
35713577
return nullptr;
35723578
}
35733579

3580+
3581+
std::shared_ptr<SaiObj> findCurrentBestMatchForGenericObjectUsingPreMatchMap(
3582+
_In_ const AsicView &currentView,
3583+
_In_ const AsicView &temporaryView,
3584+
_In_ const std::shared_ptr<const SaiObj> &temporaryObj,
3585+
_In_ const std::vector<sai_object_compare_info_t> &candidateObjects)
3586+
{
3587+
SWSS_LOG_ENTER();
3588+
3589+
if (temporaryObj->isOidObject() == false)
3590+
return std::shared_ptr<SaiObj>();
3591+
3592+
auto it = temporaryView.preMatchMap.find(temporaryObj->getVid());
3593+
3594+
if (it == temporaryView.preMatchMap.end()) // no luck, there was no vid in pre match
3595+
return nullptr;
3596+
3597+
for (auto c: candidateObjects)
3598+
{
3599+
if (c.obj->getVid() == it->second)
3600+
{
3601+
SWSS_LOG_INFO("found pre match vid %s (tmp) %s (cur)",
3602+
sai_serialize_object_id(it->first).c_str(),
3603+
sai_serialize_object_id(it->second).c_str());
3604+
3605+
return c.obj;
3606+
}
3607+
}
3608+
3609+
return nullptr;
3610+
}
3611+
35743612
std::shared_ptr<SaiObj> findCurrentBestMatchForGenericObjectUsingGraph(
35753613
_In_ const AsicView &currentView,
35763614
_In_ const AsicView &temporaryView,
@@ -3581,6 +3619,11 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForGenericObjectUsingGraph(
35813619

35823620
std::shared_ptr<SaiObj> candidate = nullptr;
35833621

3622+
candidate = findCurrentBestMatchForGenericObjectUsingPreMatchMap(currentView, temporaryView, temporaryObj, candidateObjects);
3623+
3624+
if (candidate != nullptr)
3625+
return candidate;
3626+
35843627
switch (temporaryObj->getObjectType())
35853628
{
35863629
case SAI_OBJECT_TYPE_LAG:
@@ -7024,6 +7067,152 @@ void checkMap(
70247067
}
70257068
}
70267069

7070+
void createPreMatchMapForObject(
7071+
_In_ const AsicView& cur,
7072+
_Inout_ AsicView& tmp,
7073+
_In_ std::shared_ptr<const SaiObj> cObj,
7074+
_In_ std::shared_ptr<const SaiObj> tObj,
7075+
_Inout_ std::set<std::string>& processed)
7076+
{
7077+
SWSS_LOG_ENTER();
7078+
7079+
if (processed.find(tObj->str_object_id) != processed.end())
7080+
return;
7081+
7082+
processed.insert(tObj->str_object_id);
7083+
7084+
if (cObj->getObjectType() != tObj->getObjectType())
7085+
return;
7086+
7087+
// this object is matched, so it have same vid/rid in both views
7088+
// but it can have attributes with objects which are not matched
7089+
// for those we want to create pre match map
7090+
7091+
for (auto& ak: tObj->getAllAttributes())
7092+
{
7093+
auto id = ak.first;
7094+
const auto& tAttr = ak.second;
7095+
7096+
if (cObj->hasAttr(id) == false)
7097+
continue;
7098+
7099+
// both objects has the same attribute
7100+
7101+
const auto& cAttr = cObj->getSaiAttr(id);
7102+
7103+
const auto& tVids = tAttr->getOidListFromAttribute();
7104+
const auto& cVids = cAttr->getOidListFromAttribute();
7105+
7106+
if (tVids.size() != cVids.size())
7107+
continue; // if number of attributes is different then skip
7108+
7109+
if (tVids.size() != 1)
7110+
continue; // for now skip list attributes
7111+
7112+
for (size_t i = 0; i < tVids.size(); ++i)
7113+
{
7114+
sai_object_id_t tVid = tVids[i];
7115+
sai_object_id_t cVid = cVids[i];
7116+
7117+
if (tVid == SAI_NULL_OBJECT_ID || cVid == SAI_NULL_OBJECT_ID)
7118+
continue;
7119+
7120+
if (tmp.preMatchMap.find(tVid) != tmp.preMatchMap.end())
7121+
continue;
7122+
7123+
// since on one attribute sometimes different object types can be set
7124+
// check if both object types are correct
7125+
7126+
if (cur.oOids.at(cVid)->getObjectType() != tmp.oOids.at(tVid)->getObjectType())
7127+
continue;
7128+
7129+
SWSS_LOG_INFO("inserting pre match entry for %s:%s: 0x%lx (tmp) -> 0x%lx (cur)",
7130+
tObj->str_object_id.c_str(),
7131+
cAttr->getAttrMetadata()->attridname,
7132+
tVid,
7133+
cVid);
7134+
7135+
tmp.preMatchMap[tVid] = cVid;
7136+
7137+
// continue recursively through object dependency tree:
7138+
7139+
createPreMatchMapForObject(cur, tmp, cur.oOids.at(cVid), tmp.oOids.at(tVid), processed);
7140+
}
7141+
}
7142+
}
7143+
7144+
void createPreMatchMap(
7145+
_In_ const AsicView& cur,
7146+
_Inout_ AsicView& tmp)
7147+
{
7148+
SWSS_LOG_ENTER();
7149+
7150+
/*
7151+
* When comparison logic is running on object A it runs recursively on each
7152+
* object that was fount in object A attributes, because we need to make
7153+
* sure all objects are matched before actually processing object A. For
7154+
* example before processing ROUTE_ENTRY, we process first NEXT_HOP and
7155+
* before that REOUTER_INTERFACE and before that PORT. Object processing
7156+
* could be described going from down to top. But figuring out for top
7157+
* object ex. WRED could be hard since we would need to check not matched
7158+
* yet buffer profile and buffer pool before we use QUEUE or IPG as an
7159+
* anchor object. We can actually leverage that and when processing graph
7160+
* from top to bottom, we can create helper map which will contain
7161+
* predictions which object will be suitable for current processing
7162+
* objects. We can have N candidates objects and instead of choosing 1 at
7163+
* random, to reduce number of ASIC operations we will use a pre match map
7164+
* which is created in this method.
7165+
*
7166+
* This map should be almost exact match in warn boot case, but it will be
7167+
* treated only as hint, not as actual mapping.
7168+
*
7169+
* We will create map for all matched objects and for route_entry,
7170+
* fdb_entry and neighbor_entry.
7171+
*/
7172+
7173+
std::set<std::string> processed;
7174+
7175+
SWSS_LOG_TIMER("create preMatch map");
7176+
7177+
for (auto& ok: tmp.soAll)
7178+
{
7179+
auto& tObj = ok.second;
7180+
7181+
if (tObj->getObjectStatus() != SAI_OBJECT_STATUS_MATCHED)
7182+
continue;
7183+
7184+
sai_object_id_t cObjVid = cur.ridToVid.at(tmp.vidToRid.at(tObj->getVid()));
7185+
7186+
auto& cObj = cur.oOids.at(cObjVid);
7187+
7188+
createPreMatchMapForObject(cur, tmp, cObj, tObj, processed);
7189+
}
7190+
7191+
for (auto&pk: tmp.routesByPrefix)
7192+
{
7193+
auto& prefix = pk.first;
7194+
7195+
// look only for unique prefixes
7196+
7197+
if (pk.second.size() != 1)
7198+
continue;
7199+
7200+
auto it = cur.routesByPrefix.find(prefix);
7201+
7202+
if (it == cur.routesByPrefix.end())
7203+
continue;
7204+
7205+
if (it->second.size() != 1)
7206+
continue;
7207+
7208+
auto& tObj = tmp.soAll.at(pk.second.at(0));
7209+
auto& cObj = cur.soAll.at(it->second.at(0));
7210+
7211+
createPreMatchMapForObject(cur, tmp, cObj, tObj, processed);
7212+
}
7213+
7214+
SWSS_LOG_NOTICE("preMatch map size: %zu", tmp.preMatchMap.size());
7215+
}
70277216

70287217
sai_status_t syncdApplyView()
70297218
{
@@ -7167,6 +7356,8 @@ sai_status_t syncdApplyView()
71677356
temp.dumpRef("temp START");
71687357
}
71697358

7359+
createPreMatchMap(current, temp);
7360+
71707361
logViewObjectCount(current, temp);
71717362

71727363
applyViewTransition(current, temp);

tests/aspell.en.pws

+6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ config
3434
const
3535
CONST
3636
consts
37+
counterName
3738
countOnly
3839
cout
3940
cpu
@@ -87,6 +88,7 @@ inout
8788
INSEG
8889
ip
8990
IP
91+
IPG
9092
ipmc
9193
IPv
9294
isobjectid
@@ -113,6 +115,7 @@ namespaces
113115
NHG
114116
nhgm
115117
nlog
118+
ntf
116119
nullptr
117120
OA
118121
ObjectAttrHash
@@ -153,6 +156,9 @@ RIDs
153156
RIDTOVID
154157
rif
155158
RIF
159+
rifCounterIds
160+
rifId
161+
rifStats
156162
RO
157163
RPC
158164
runtime

tests/brcm.pl

+10
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,18 @@ sub test_brcm_warm_wred_queue
401401
play "wred_queue.rec", 0;
402402
}
403403

404+
sub test_empty_lag_buffer_acl
405+
{
406+
fresh_start;
407+
408+
play "empty_lag_buffer_acl.rec";
409+
410+
for (1..8) { play "empty_lag_buffer_acl.rec", 0; }
411+
}
412+
404413
# RUN TESTS
405414

415+
test_empty_lag_buffer_acl;
406416
test_brcm_config_acl;
407417
test_brcm_warm_wred_queue;
408418
test_brcm_warm_boot_full_empty;

0 commit comments

Comments
 (0)