@@ -563,6 +563,8 @@ class AsicView
563
563
sai_deserialize_route_entry (o->str_object_id , o->meta_key .objectkey .key .route_entry );
564
564
soRoutes[o->str_object_id ] = o;
565
565
566
+ routesByPrefix[sai_serialize_ip_prefix (o->meta_key .objectkey .key .route_entry .destination )].push_back (o->str_object_id );
567
+
566
568
break ;
567
569
568
570
default :
@@ -850,6 +852,8 @@ class AsicView
850
852
StrObjectIdToSaiObjectHash soOids;
851
853
StrObjectIdToSaiObjectHash soAll;
852
854
855
+ std::unordered_map<std::string,std::vector<std::string>> routesByPrefix;
856
+
853
857
private:
854
858
855
859
std::map<sai_object_type_t , StrObjectIdToSaiObjectHash> sotAll;
@@ -858,6 +862,8 @@ class AsicView
858
862
859
863
ObjectIdToSaiObjectHash oOids;
860
864
865
+ std::unordered_map<sai_object_id_t , sai_object_id_t > preMatchMap;
866
+
861
867
/*
862
868
* On temp view this needs to be used for actual NEW rids created and
863
869
* then reused with rid mapping to create new rid/vid map.
@@ -2517,7 +2523,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForLag(
2517
2523
2518
2524
if (temporaryLagMemberPortVid == SAI_NULL_OBJECT_ID)
2519
2525
{
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 ());
2521
2527
2522
2528
return nullptr ;
2523
2529
}
@@ -2563,7 +2569,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForLag(
2563
2569
}
2564
2570
}
2565
2571
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" );
2567
2573
2568
2574
return nullptr ;
2569
2575
}
@@ -2655,7 +2661,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForNextHopGroup(
2655
2661
}
2656
2662
}
2657
2663
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" );
2659
2665
2660
2666
return nullptr ;
2661
2667
}
@@ -2804,7 +2810,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForAclTableGroup(
2804
2810
}
2805
2811
}
2806
2812
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" );
2808
2814
2809
2815
return nullptr ;
2810
2816
}
@@ -2899,7 +2905,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForAclTable(
2899
2905
}
2900
2906
}
2901
2907
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" );
2903
2909
2904
2910
return nullptr ;
2905
2911
}
@@ -3095,7 +3101,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForRouterInterface(
3095
3101
}
3096
3102
}
3097
3103
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 " );
3099
3105
3100
3106
return nullptr ;
3101
3107
}
@@ -3281,7 +3287,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForHostifTrapGroup(
3281
3287
}
3282
3288
}
3283
3289
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" );
3285
3291
3286
3292
return nullptr ;
3287
3293
}
@@ -3414,7 +3420,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForBufferPool(
3414
3420
3415
3421
}
3416
3422
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" );
3418
3424
3419
3425
return nullptr ;
3420
3426
}
@@ -3509,7 +3515,7 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForBufferProfile(
3509
3515
}
3510
3516
}
3511
3517
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" );
3513
3519
3514
3520
return nullptr ;
3515
3521
}
@@ -3571,6 +3577,38 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForWred(
3571
3577
return nullptr ;
3572
3578
}
3573
3579
3580
+
3581
+ std::shared_ptr<SaiObj> findCurrentBestMatchForGenericObjectUsingPreMatchMap (
3582
+ _In_ const AsicView ¤tView,
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
+
3574
3612
std::shared_ptr<SaiObj> findCurrentBestMatchForGenericObjectUsingGraph (
3575
3613
_In_ const AsicView ¤tView,
3576
3614
_In_ const AsicView &temporaryView,
@@ -3581,6 +3619,11 @@ std::shared_ptr<SaiObj> findCurrentBestMatchForGenericObjectUsingGraph(
3581
3619
3582
3620
std::shared_ptr<SaiObj> candidate = nullptr ;
3583
3621
3622
+ candidate = findCurrentBestMatchForGenericObjectUsingPreMatchMap (currentView, temporaryView, temporaryObj, candidateObjects);
3623
+
3624
+ if (candidate != nullptr )
3625
+ return candidate;
3626
+
3584
3627
switch (temporaryObj->getObjectType ())
3585
3628
{
3586
3629
case SAI_OBJECT_TYPE_LAG:
@@ -7024,6 +7067,152 @@ void checkMap(
7024
7067
}
7025
7068
}
7026
7069
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
+ }
7027
7216
7028
7217
sai_status_t syncdApplyView ()
7029
7218
{
@@ -7167,6 +7356,8 @@ sai_status_t syncdApplyView()
7167
7356
temp.dumpRef (" temp START" );
7168
7357
}
7169
7358
7359
+ createPreMatchMap (current, temp);
7360
+
7170
7361
logViewObjectCount (current, temp);
7171
7362
7172
7363
applyViewTransition (current, temp);
0 commit comments