Skip to content

Commit e77503c

Browse files
authored
[syncd] Comparison logic workaround for empty buffer profile (#906) (#941)
1 parent ca6cdf0 commit e77503c

11 files changed

+317
-18
lines changed

syncd/AsicView.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ std::vector<std::shared_ptr<SaiObj>> AsicView::getAllNotProcessedObjects() const
501501
* @param[in] rid Real ID
502502
* @param[in] vid Virtual ID
503503
*/
504-
void AsicView::createDummyExistingObject(
504+
std::shared_ptr<SaiObj> AsicView::createDummyExistingObject(
505505
_In_ sai_object_id_t rid,
506506
_In_ sai_object_id_t vid)
507507
{
@@ -535,6 +535,8 @@ void AsicView::createDummyExistingObject(
535535

536536
m_ridToVid[rid] = vid;
537537
m_vidToRid[vid] = rid;
538+
539+
return o;
538540
}
539541

540542
/**
@@ -1276,10 +1278,10 @@ void AsicView::checkObjectsStatus() const
12761278
{
12771279
const auto &o = *p.second;
12781280

1279-
SWSS_LOG_ERROR("object was not processed: %s %s, status: %d (ref: %d)",
1281+
SWSS_LOG_ERROR("object was not processed: %s %s, status: %s (ref: %d)",
12801282
o.m_str_object_type.c_str(),
12811283
o.m_str_object_id.c_str(),
1282-
o.getObjectStatus(),
1284+
ObjectStatus::sai_serialize_object_status(o.getObjectStatus()).c_str(),
12831285
o.isOidObject() ? getVidReferenceCount(o.getVid()): -1);
12841286

12851287
count++;

syncd/AsicView.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ namespace syncd
188188
* @param[in] rid Real ID
189189
* @param[in] vid Virtual ID
190190
*/
191-
void createDummyExistingObject(
191+
std::shared_ptr<SaiObj> createDummyExistingObject(
192192
_In_ sai_object_id_t rid,
193193
_In_ sai_object_id_t vid);
194194

syncd/ComparisonLogic.cpp

+174-11
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,13 @@ void ComparisonLogic::compareViews()
122122

123123
applyViewTransition(current, temp);
124124

125+
transferNotProcessed(current, temp);
126+
127+
// TODO have a method to check for not processed objects
128+
// and maybe add them to list on processing attributes
129+
// and move note processed objects to temporary view as well
130+
// we need to check oid attributes as well
131+
125132
SWSS_LOG_NOTICE("ASIC operations to execute: %zu", current.asicGetOperationsCount());
126133

127134
temp.checkObjectsStatus();
@@ -183,6 +190,8 @@ void ComparisonLogic::matchOids(
183190
{
184191
SWSS_LOG_ENTER();
185192

193+
auto coldBootDiscoveredVids = m_switch->getColdBootDiscoveredVids();
194+
186195
for (const auto &temporaryIt: temporaryView.m_oOids)
187196
{
188197
sai_object_id_t temporaryVid = temporaryIt.first;
@@ -211,6 +220,37 @@ void ComparisonLogic::matchOids(
211220
currentIt->second->m_str_object_type.c_str(),
212221
sai_serialize_object_id(rid).c_str(),
213222
sai_serialize_object_id(vid).c_str());
223+
224+
if (coldBootDiscoveredVids.find(vid) == coldBootDiscoveredVids.end())
225+
{
226+
auto ot = currentIt->second->getObjectType();
227+
228+
switch (ot)
229+
{
230+
case SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP:
231+
case SAI_OBJECT_TYPE_SCHEDULER_GROUP:
232+
case SAI_OBJECT_TYPE_QUEUE:
233+
case SAI_OBJECT_TYPE_PORT:
234+
break;
235+
236+
default:
237+
238+
// Should we also add check if also not in removed?
239+
// This is for case of only GET:
240+
// 1. cold boot:
241+
// - OA assigns buffer profile to Queue
242+
// 2. warm boot:
243+
// - OA do GET on Queue and got previous buffer profile
244+
// - OA assigns new buffer profile on Queue
245+
//
246+
// Question: what should happen to old buffer profile? should it be removed?
247+
// No, since OA still hold's the reference to that VID and may use it later.
248+
SWSS_LOG_INFO("matched %s VID %s was not in cold boot, possible only GET?",
249+
sai_serialize_object_id(vid).c_str(),
250+
currentIt->second->m_str_object_type.c_str());
251+
break;
252+
}
253+
}
214254
}
215255

216256
SWSS_LOG_NOTICE("matched oids");
@@ -1121,8 +1161,8 @@ void ComparisonLogic::updateObjectStatus(
11211161
bool ComparisonLogic::performObjectSetTransition(
11221162
_In_ AsicView &currentView,
11231163
_In_ AsicView &temporaryView,
1124-
_In_ const std::shared_ptr<SaiObj> &currentBestMatch,
1125-
_In_ const std::shared_ptr<const SaiObj> &temporaryObj,
1164+
_In_ const std::shared_ptr<SaiObj> currentBestMatch,
1165+
_In_ std::shared_ptr<SaiObj> temporaryObj,
11261166
_In_ bool performTransition)
11271167
{
11281168
SWSS_LOG_ENTER();
@@ -1382,6 +1422,8 @@ bool ComparisonLogic::performObjectSetTransition(
13821422
return false;
13831423
}
13841424

1425+
const bool beginTempSizeZero = temporaryObj->getAllAttributes().size() == 0;
1426+
13851427
/*
13861428
* Current best match can have more attributes than temporary object.
13871429
* let see if we can bring them to default value if possible.
@@ -1526,14 +1568,38 @@ bool ComparisonLogic::performObjectSetTransition(
15261568
continue;
15271569
}
15281570

1529-
// SAI_QUEUE_ATTR_PARENT_SCHEDULER_NODE
1530-
// SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID*
1531-
// SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE
1532-
// SAI_BRIDGE_PORT_ATTR_BRIDGE_ID
1533-
//
1534-
// TODO matched by ID (MATCHED state) should always be updatable
1535-
// except those 4 above (at least for those above since they can have
1536-
// default value present after switch creation
1571+
// current best match is MATCHED
1572+
1573+
//auto vid = currentBestMatch->getVid();
1574+
1575+
// TODO don't transfer oid attributes, we don't know how to handle this yet
1576+
// If OA did GET on any attributes, snoop in syncd should catch that and write
1577+
// to database so we would have some attributes here.
1578+
1579+
if (beginTempSizeZero && !meta->isoidattribute)
1580+
{
1581+
SWSS_LOG_WARN("current attr is MoC|CaS and object is MATCHED: %s transferring %s:%s to temp object (was empty)",
1582+
currentBestMatch->m_str_object_id.c_str(),
1583+
meta->attridname,
1584+
currentAttr->getStrAttrValue().c_str());
1585+
1586+
std::shared_ptr<SaiAttr> transferedAttr = std::make_shared<SaiAttr>(
1587+
currentAttr->getStrAttrId(),
1588+
currentAttr->getStrAttrValue());
1589+
1590+
temporaryObj->setAttr(transferedAttr);
1591+
1592+
continue;
1593+
}
1594+
1595+
// SAI_QUEUE_ATTR_PARENT_SCHEDULER_NODE
1596+
// SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID*
1597+
// SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE
1598+
// SAI_BRIDGE_PORT_ATTR_BRIDGE_ID
1599+
//
1600+
// TODO matched by ID (MATCHED state) should always be updatable
1601+
// except those 4 above (at least for those above since they can have
1602+
// default value present after switch creation
15371603

15381604
// TODO SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID is mandatory on create but also SET
15391605
// if attribute is set we and object is in MATCHED state then that means we are able to
@@ -1567,6 +1633,21 @@ bool ComparisonLogic::performObjectSetTransition(
15671633
meta->attridname,
15681634
currentAttr->getStrAttrValue().c_str());
15691635

1636+
// don't produce too much noise for queues
1637+
if (currentAttr->getStrAttrId() != "SAI_QUEUE_ATTR_TYPE")
1638+
{
1639+
SWSS_LOG_WARN("current attr is CREATE_ONLY and object is MATCHED: %s transferring %s:%s to temp object",
1640+
currentBestMatch->m_str_object_id.c_str(),
1641+
meta->attridname,
1642+
currentAttr->getStrAttrValue().c_str());
1643+
}
1644+
1645+
std::shared_ptr<SaiAttr> transferedAttr = std::make_shared<SaiAttr>(
1646+
currentAttr->getStrAttrId(),
1647+
currentAttr->getStrAttrValue());
1648+
1649+
temporaryObj->setAttr(transferedAttr);
1650+
15701651
continue;
15711652
}
15721653
}
@@ -1705,7 +1786,7 @@ bool ComparisonLogic::performObjectSetTransition(
17051786
void ComparisonLogic::processObjectForViewTransition(
17061787
_In_ AsicView &currentView,
17071788
_In_ AsicView &temporaryView,
1708-
_In_ const std::shared_ptr<SaiObj> &temporaryObj)
1789+
_Inout_ std::shared_ptr<SaiObj> temporaryObj)
17091790
{
17101791
SWSS_LOG_ENTER();
17111792

@@ -2269,6 +2350,10 @@ void ComparisonLogic::populateExistingObjects(
22692350

22702351
if (temporaryView.hasRid(rid))
22712352
{
2353+
SWSS_LOG_INFO("temporary view has existing %s RID %s",
2354+
sai_serialize_object_type(m_vendorSai->objectTypeQuery(rid)).c_str(),
2355+
sai_serialize_object_id(rid).c_str());
2356+
22722357
continue;
22732358
}
22742359

@@ -2291,6 +2376,11 @@ void ComparisonLogic::populateExistingObjects(
22912376
* from current view as well.
22922377
*/
22932378

2379+
SWSS_LOG_INFO("object was removed in init view: %s RID %s VID %s",
2380+
sai_serialize_object_type(m_vendorSai->objectTypeQuery(rid)).c_str(),
2381+
sai_serialize_object_id(rid).c_str(),
2382+
sai_serialize_object_id(vid).c_str());
2383+
22942384
continue;
22952385
}
22962386

@@ -2726,6 +2816,79 @@ void ComparisonLogic::createPreMatchMap(
27262816
count);
27272817
}
27282818

2819+
void ComparisonLogic::transferNotProcessed(
2820+
_In_ AsicView& current,
2821+
_In_ AsicView& temp)
2822+
{
2823+
SWSS_LOG_ENTER();
2824+
2825+
SWSS_LOG_NOTICE("calling transferNotProcessed");
2826+
2827+
/*
2828+
* It may happen that after performing view transition, some objects will
2829+
* not be processed. This may happen is scenario where buffer pool is
2830+
* assigned to buffer profile, and then buffer profile is assigned to
2831+
* queue. If OA will query only for oid for that buffer profile, then
2832+
* buffer pool will not be processed. Normally if it would be removed by
2833+
* comparison logic. More on this issue can be found on github:
2834+
* https://github.com/Azure/sonic-sairedis/issues/899
2835+
*
2836+
* So what we will do, we will transfer all not processed objects to
2837+
* temporary view with the same RID and VID. If nothing will happen to them,
2838+
* they will stay there until next warm boot where they will be removed.
2839+
*/
2840+
2841+
/*
2842+
* We need a loop (or recursion) since not processed objects may have oid
2843+
* attributes as well.
2844+
*/
2845+
2846+
while (current.getAllNotProcessedObjects().size())
2847+
{
2848+
SWSS_LOG_WARN("we have %zu not processed objects on current view, moving to temp view", current.getAllNotProcessedObjects().size());
2849+
2850+
for (const auto& obj: current.getAllNotProcessedObjects())
2851+
{
2852+
auto vid = obj->getVid();
2853+
2854+
auto rid = current.m_vidToRid.at(vid);
2855+
2856+
/*
2857+
* We should have only oid objects here, since all non oid objects
2858+
* are leafs in graph and has been removed.
2859+
*/
2860+
2861+
auto tmp = temp.createDummyExistingObject(rid, vid);
2862+
2863+
/*
2864+
* Move both objects to matched state since match oids was already
2865+
* called, and here we created some new objects that should be matched.
2866+
*/
2867+
2868+
current.m_oOids.at(vid)->setObjectStatus(SAI_OBJECT_STATUS_FINAL);
2869+
temp.m_oOids.at(vid)->setObjectStatus(SAI_OBJECT_STATUS_FINAL);
2870+
2871+
SWSS_LOG_WARN("moved %s VID %s RID %s to temporary view, and marked FINAL",
2872+
obj->m_str_object_type.c_str(),
2873+
obj->m_str_object_id.c_str(),
2874+
sai_serialize_object_id(rid).c_str());
2875+
2876+
for (auto& kvp: obj->getAllAttributes())
2877+
{
2878+
auto& sh = kvp.second;
2879+
2880+
auto attr = std::make_shared<SaiAttr>(sh->getStrAttrId(), sh->getStrAttrValue());
2881+
2882+
tmp->setAttr(attr);
2883+
2884+
SWSS_LOG_WARN(" * with attr: %s: %s",
2885+
sh->getStrAttrId().c_str(),
2886+
sh->getStrAttrValue().c_str());
2887+
}
2888+
2889+
}
2890+
}
2891+
}
27292892

27302893
void ComparisonLogic::applyViewTransition(
27312894
_In_ AsicView &current,

syncd/ComparisonLogic.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ namespace syncd
5858
_In_ AsicView& current,
5959
_In_ AsicView& temp);
6060

61+
void transferNotProcessed(
62+
_In_ AsicView& current,
63+
_In_ AsicView& temp);
64+
6165
void checkInternalObjects(
6266
_In_ const AsicView& cv,
6367
_In_ const AsicView& tv);
@@ -136,8 +140,8 @@ namespace syncd
136140
bool performObjectSetTransition(
137141
_In_ AsicView& currentView,
138142
_In_ AsicView& temporaryView,
139-
_In_ const std::shared_ptr<SaiObj>& currentBestMatch,
140-
_In_ const std::shared_ptr<const SaiObj>& temporaryObj,
143+
_In_ const std::shared_ptr<SaiObj> currentBestMatch,
144+
_In_ const std::shared_ptr<SaiObj> temporaryObj,
141145
_In_ bool performTransition);
142146

143147
void breakBeforeMake(
@@ -154,7 +158,7 @@ namespace syncd
154158
void processObjectForViewTransition(
155159
_In_ AsicView& currentView,
156160
_In_ AsicView& temporaryView,
157-
_In_ const std::shared_ptr<SaiObj>& temporaryObj);
161+
_Inout_ std::shared_ptr<SaiObj> temporaryObj);
158162

159163
void checkSwitch(
160164
_In_ const AsicView& currentView,

syncd/SaiObj.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,30 @@
44

55
using namespace syncd;
66

7+
std::string ObjectStatus::sai_serialize_object_status(
8+
_In_ sai_object_status_t os)
9+
{
10+
SWSS_LOG_ENTER();
11+
12+
switch (os)
13+
{
14+
case SAI_OBJECT_STATUS_NOT_PROCESSED:
15+
return "not-processed";
16+
17+
case SAI_OBJECT_STATUS_MATCHED:
18+
return "matched";
19+
20+
case SAI_OBJECT_STATUS_REMOVED:
21+
return "removed";
22+
23+
case SAI_OBJECT_STATUS_FINAL:
24+
return "final";
25+
26+
default:
27+
SWSS_LOG_THROW("unknown object status: %d", os);
28+
}
29+
}
30+
731
SaiObj::SaiObj():
832
m_createdObject(false),
933
m_objectStatus(SAI_OBJECT_STATUS_NOT_PROCESSED)

syncd/SaiObj.h

+13
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ namespace syncd
5555

5656
} sai_object_status_t;
5757

58+
class ObjectStatus
59+
{
60+
private:
61+
62+
ObjectStatus() = delete;
63+
~ObjectStatus() = delete;
64+
65+
public:
66+
67+
static std::string sai_serialize_object_status(
68+
_In_ sai_object_status_t os);
69+
};
70+
5871
class SaiObj
5972
{
6073
private:

0 commit comments

Comments
 (0)