18
18
#include " crmorch.h"
19
19
#include " saihelper.h"
20
20
#include " directory.h"
21
+ #include " flex_counter_manager.h"
21
22
22
23
#include " taskworker.h"
23
24
#include " pbutils.h"
@@ -28,16 +29,45 @@ using namespace swss;
28
29
29
30
extern Directory<Orch*> gDirectory ;
30
31
extern std::unordered_map<std::string, sai_object_id_t > gVnetNameToId ;
32
+ extern sai_dash_appliance_api_t * sai_dash_appliance_api;
31
33
extern sai_dash_vip_api_t * sai_dash_vip_api;
32
34
extern sai_dash_direction_lookup_api_t * sai_dash_direction_lookup_api;
33
35
extern sai_dash_eni_api_t * sai_dash_eni_api;
34
36
extern sai_object_id_t gSwitchId ;
35
37
extern size_t gMaxBulkSize ;
36
38
extern CrmOrch *gCrmOrch ;
39
+ extern bool gTraditionalFlexCounter ;
37
40
38
- DashOrch::DashOrch (DBConnector *db, vector<string> &tableName, ZmqServer *zmqServer) : ZmqOrch(db, tableName, zmqServer)
41
+ #define FLEX_COUNTER_UPD_INTERVAL 1
42
+
43
+ DashOrch::DashOrch (DBConnector *db, vector<string> &tableName, ZmqServer *zmqServer) :
44
+ ZmqOrch(db, tableName, zmqServer),
45
+ m_eni_stat_manager(ENI_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, ENI_STAT_FLEX_COUNTER_POLLING_INTERVAL_MS, false )
39
46
{
40
47
SWSS_LOG_ENTER ();
48
+
49
+ m_asic_db = std::shared_ptr<DBConnector>(new DBConnector (" ASIC_DB" , 0 ));
50
+ m_counter_db = std::shared_ptr<DBConnector>(new DBConnector (" COUNTERS_DB" , 0 ));
51
+ m_eni_name_table = std::unique_ptr<Table>(new Table (m_counter_db.get (), COUNTERS_ENI_NAME_MAP));
52
+
53
+ if (gTraditionalFlexCounter )
54
+ {
55
+ m_vid_to_rid_table = std::make_unique<Table>(m_asic_db.get (), " VIDTORID" );
56
+ }
57
+
58
+ auto intervT = timespec { .tv_sec = FLEX_COUNTER_UPD_INTERVAL , .tv_nsec = 0 };
59
+ m_fc_update_timer = new SelectableTimer (intervT);
60
+ auto executorT = new ExecutableTimer (m_fc_update_timer, this , " FLEX_COUNTER_UPD_TIMER" );
61
+ Orch::addExecutor (executorT);
62
+
63
+ /* Fetch the available counter Ids */
64
+ m_counter_stats.clear ();
65
+ auto stat_enum_list = queryAvailableCounterStats ((sai_object_type_t )SAI_OBJECT_TYPE_ENI);
66
+ for (auto &stat_enum: stat_enum_list)
67
+ {
68
+ auto counter_id = static_cast <sai_eni_stat_t >(stat_enum);
69
+ m_counter_stats.insert (sai_serialize_eni_stat (counter_id));
70
+ }
41
71
}
42
72
43
73
bool DashOrch::getRouteTypeActions (dash::route_type::RoutingType routing_type, dash::route_type::RouteType& route_type)
@@ -66,15 +96,31 @@ bool DashOrch::addApplianceEntry(const string& appliance_id, const dash::applian
66
96
}
67
97
68
98
uint32_t attr_count = 1 ;
99
+ sai_attribute_t appliance_attr;
100
+ sai_status_t status;
101
+
102
+ // NOTE: DASH Appliance object should be the first object pushed to SAI
103
+ sai_object_id_t sai_appliance_id = 0UL ;
104
+ appliance_attr.id = SAI_DASH_APPLIANCE_ATTR_LOCAL_REGION_ID;
105
+ appliance_attr.value .u32 = entry.local_region_id ();
106
+ status = sai_dash_appliance_api->create_dash_appliance (&sai_appliance_id, gSwitchId ,
107
+ attr_count, &appliance_attr);
108
+ if (status != SAI_STATUS_SUCCESS && status != SAI_STATUS_NOT_IMPLEMENTED)
109
+ {
110
+ SWSS_LOG_ERROR (" Failed to create dash appliance object in SAI for %s" , appliance_id.c_str ());
111
+ task_process_status handle_status = handleSaiCreateStatus ((sai_api_t ) SAI_API_DASH_APPLIANCE, status);
112
+ if (handle_status != task_success)
113
+ {
114
+ return parseHandleSaiStatusFailure (handle_status);
115
+ }
116
+ }
117
+
69
118
sai_vip_entry_t vip_entry;
70
119
vip_entry.switch_id = gSwitchId ;
71
120
if (!to_sai (entry.sip (), vip_entry.vip ))
72
121
{
73
122
return false ;
74
123
}
75
- sai_attribute_t appliance_attr;
76
- vector<sai_attribute_t > appliance_attrs;
77
- sai_status_t status;
78
124
appliance_attr.id = SAI_VIP_ENTRY_ATTR_ACTION;
79
125
appliance_attr.value .u32 = SAI_VIP_ENTRY_ACTION_ACCEPT;
80
126
status = sai_dash_vip_api->create_vip_entry (&vip_entry, attr_count, &appliance_attr);
@@ -103,8 +149,8 @@ bool DashOrch::addApplianceEntry(const string& appliance_id, const dash::applian
103
149
return parseHandleSaiStatusFailure (handle_status);
104
150
}
105
151
}
106
- appliance_entries_[appliance_id] = entry;
107
- SWSS_LOG_NOTICE (" Created vip and direction lookup entries for %s" , appliance_id.c_str ());
152
+ appliance_entries_[appliance_id] = ApplianceEntry { sai_appliance_id, entry } ;
153
+ SWSS_LOG_NOTICE (" Created appliance, vip and direction lookup entries for %s" , appliance_id.c_str ());
108
154
109
155
return true ;
110
156
}
@@ -114,15 +160,14 @@ bool DashOrch::removeApplianceEntry(const string& appliance_id)
114
160
SWSS_LOG_ENTER ();
115
161
116
162
sai_status_t status;
117
- dash::appliance::Appliance entry;
118
163
119
164
if (appliance_entries_.find (appliance_id) == appliance_entries_.end ())
120
165
{
121
166
SWSS_LOG_WARN (" Appliance id does not exist: %s" , appliance_id.c_str ());
122
167
return true ;
123
168
}
124
169
125
- entry = appliance_entries_[appliance_id];
170
+ const auto & entry = appliance_entries_[appliance_id]. metadata ;
126
171
sai_vip_entry_t vip_entry;
127
172
vip_entry.switch_id = gSwitchId ;
128
173
if (!to_sai (entry.sip (), vip_entry.vip ))
@@ -153,8 +198,23 @@ bool DashOrch::removeApplianceEntry(const string& appliance_id)
153
198
return parseHandleSaiStatusFailure (handle_status);
154
199
}
155
200
}
201
+
202
+ auto sai_appliance_id = appliance_entries_[appliance_id].appliance_id ;
203
+ if (sai_appliance_id != 0UL )
204
+ {
205
+ status = sai_dash_appliance_api->remove_dash_appliance (sai_appliance_id);
206
+ if (status != SAI_STATUS_SUCCESS && status != SAI_STATUS_NOT_IMPLEMENTED)
207
+ {
208
+ SWSS_LOG_ERROR (" Failed to remove dash appliance object in SAI for %s" , appliance_id.c_str ());
209
+ task_process_status handle_status = handleSaiRemoveStatus ((sai_api_t ) SAI_API_DASH_APPLIANCE, status);
210
+ if (handle_status != task_success)
211
+ {
212
+ return parseHandleSaiStatusFailure (handle_status);
213
+ }
214
+ }
215
+ }
156
216
appliance_entries_.erase (appliance_id);
157
- SWSS_LOG_NOTICE (" Removed vip and direction lookup entries for %s" , appliance_id.c_str ());
217
+ SWSS_LOG_NOTICE (" Removed appliance, vip and direction lookup entries for %s" , appliance_id.c_str ());
158
218
159
219
return true ;
160
220
}
@@ -383,7 +443,7 @@ bool DashOrch::addEniObject(const string& eni, EniEntry& entry)
383
443
eni_attrs.push_back (eni_attr);
384
444
385
445
eni_attr.id = SAI_ENI_ATTR_VM_VNI;
386
- auto app_entry = appliance_entries_.begin ()->second ;
446
+ auto & app_entry = appliance_entries_.begin ()->second . metadata ;
387
447
eni_attr.value .u32 = app_entry.vm_vni ();
388
448
eni_attrs.push_back (eni_attr);
389
449
@@ -417,6 +477,8 @@ bool DashOrch::addEniObject(const string& eni, EniEntry& entry)
417
477
}
418
478
}
419
479
480
+ addEniToFC (eni_id, eni);
481
+
420
482
gCrmOrch ->incCrmResUsedCounter (CrmResourceType::CRM_DASH_ENI);
421
483
422
484
SWSS_LOG_NOTICE (" Created ENI object for %s" , eni.c_str ());
@@ -499,6 +561,9 @@ bool DashOrch::removeEniObject(const string& eni)
499
561
SWSS_LOG_ENTER ();
500
562
501
563
EniEntry entry = eni_entries_[eni];
564
+
565
+ removeEniFromFC (entry.eni_id , eni);
566
+
502
567
sai_status_t status = sai_dash_eni_api->remove_eni (entry.eni_id );
503
568
if (status != SAI_STATUS_SUCCESS)
504
569
{
@@ -881,3 +946,93 @@ void DashOrch::doTask(ConsumerBase& consumer)
881
946
SWSS_LOG_ERROR (" Unknown table: %s" , tn.c_str ());
882
947
}
883
948
}
949
+
950
+ void DashOrch::removeEniFromFC (sai_object_id_t oid, const string &name)
951
+ {
952
+ SWSS_LOG_ENTER ();
953
+
954
+ if (oid == SAI_NULL_OBJECT_ID)
955
+ {
956
+ SWSS_LOG_WARN (" Cannot remove counter on NULL OID for eni %s" , name.c_str ());
957
+ return ;
958
+ }
959
+
960
+ if (m_eni_stat_work_queue.find (oid) != m_eni_stat_work_queue.end ())
961
+ {
962
+ m_eni_stat_work_queue.erase (oid);
963
+ return ;
964
+ }
965
+
966
+ m_eni_name_table->hdel (" " , name);
967
+ m_eni_stat_manager.clearCounterIdList (oid);
968
+ SWSS_LOG_DEBUG (" Unregistered eni %s to Flex counter" , name.c_str ());
969
+ }
970
+
971
+ void DashOrch::clearEniFCStats ()
972
+ {
973
+ for (auto it = eni_entries_.begin (); it != eni_entries_.end (); it++)
974
+ {
975
+ removeEniFromFC (it->second .eni_id , it->first );
976
+ }
977
+ }
978
+
979
+ void DashOrch::handleFCStatusUpdate (bool enabled)
980
+ {
981
+ if (!enabled && m_eni_fc_status)
982
+ {
983
+ m_fc_update_timer->stop ();
984
+ clearEniFCStats ();
985
+ }
986
+ else if (enabled && !m_eni_fc_status)
987
+ {
988
+ m_fc_update_timer->start ();
989
+ }
990
+ m_eni_fc_status = enabled;
991
+ }
992
+
993
+ void DashOrch::addEniToFC (sai_object_id_t oid, const string &name)
994
+ {
995
+ auto was_empty = m_eni_stat_work_queue.empty ();
996
+ m_eni_stat_work_queue[oid] = name;
997
+ if (was_empty)
998
+ {
999
+ m_fc_update_timer->start ();
1000
+ }
1001
+ }
1002
+
1003
+ void DashOrch::doTask (SelectableTimer &timer)
1004
+ {
1005
+ SWSS_LOG_ENTER ();
1006
+
1007
+ if (!m_eni_fc_status)
1008
+ {
1009
+ m_fc_update_timer->stop ();
1010
+ return ;
1011
+ }
1012
+
1013
+ for (auto it = m_eni_stat_work_queue.begin (); it != m_eni_stat_work_queue.end (); )
1014
+ {
1015
+ string value;
1016
+ const auto id = sai_serialize_object_id (it->first );
1017
+
1018
+ if (!gTraditionalFlexCounter || m_vid_to_rid_table->hget (" " , id, value))
1019
+ {
1020
+ SWSS_LOG_INFO (" Registering %s, id %s" , it->second .c_str (), id.c_str ());
1021
+ std::vector<FieldValueTuple> eniNameFvs;
1022
+ eniNameFvs.emplace_back (it->second , id);
1023
+ m_eni_name_table->set (" " , eniNameFvs);
1024
+
1025
+ m_eni_stat_manager.setCounterIdList (it->first , CounterType::ENI, m_counter_stats);
1026
+ it = m_eni_stat_work_queue.erase (it);
1027
+ }
1028
+ else
1029
+ {
1030
+ ++it;
1031
+ }
1032
+ }
1033
+
1034
+ if (m_eni_stat_work_queue.empty ())
1035
+ {
1036
+ m_fc_update_timer->stop ();
1037
+ }
1038
+ }
0 commit comments