1
1
#include " sai.h"
2
2
#include " copporch.h"
3
3
#include " portsorch.h"
4
+ #include " flexcounterorch.h"
4
5
#include " tokenize.h"
5
6
#include " logger.h"
7
+ #include " sai_serialize.h"
8
+ #include " schema.h"
9
+ #include " directory.h"
10
+ #include " flow_counter_handler.h"
11
+ #include " timer.h"
6
12
7
13
#include < inttypes.h>
8
14
#include < sstream>
@@ -18,8 +24,11 @@ extern sai_switch_api_t* sai_switch_api;
18
24
19
25
extern sai_object_id_t gSwitchId ;
20
26
extern PortsOrch* gPortsOrch ;
27
+ extern Directory<Orch*> gDirectory ;
21
28
extern bool gIsNatSupported ;
22
29
30
+ #define FLEX_COUNTER_UPD_INTERVAL 1
31
+
23
32
static map<string, sai_meter_type_t > policer_meter_map = {
24
33
{" packets" , SAI_METER_TYPE_PACKETS},
25
34
{" bytes" , SAI_METER_TYPE_BYTES}
@@ -82,6 +91,21 @@ static map<string, sai_hostif_trap_type_t> trap_id_map = {
82
91
{" bfdv6_micro" , SAI_HOSTIF_TRAP_TYPE_BFDV6_MICRO}
83
92
};
84
93
94
+
95
+ std::string get_trap_name_by_type (sai_hostif_trap_type_t trap_type)
96
+ {
97
+ static map<sai_hostif_trap_type_t , string> trap_name_to_id_map;
98
+ if (trap_name_to_id_map.empty ())
99
+ {
100
+ for (const auto &kv : trap_id_map)
101
+ {
102
+ trap_name_to_id_map.emplace (kv.second , kv.first );
103
+ }
104
+ }
105
+
106
+ return trap_name_to_id_map.at (trap_type);
107
+ }
108
+
85
109
static map<string, sai_packet_action_t > packet_action_map = {
86
110
{" drop" , SAI_PACKET_ACTION_DROP},
87
111
{" forward" , SAI_PACKET_ACTION_FORWARD},
@@ -97,11 +121,23 @@ const string default_trap_group = "default";
97
121
const vector<sai_hostif_trap_type_t > default_trap_ids = {
98
122
SAI_HOSTIF_TRAP_TYPE_TTL_ERROR
99
123
};
124
+ const uint HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS = 10000 ;
100
125
101
126
CoppOrch::CoppOrch (DBConnector* db, string tableName) :
102
- Orch(db, tableName)
127
+ Orch(db, tableName),
128
+ m_counter_db(std::shared_ptr<DBConnector>(new DBConnector(" COUNTERS_DB" , 0 ))),
129
+ m_flex_db(std::shared_ptr<DBConnector>(new DBConnector(" FLEX_COUNTER_DB" , 0 ))),
130
+ m_asic_db(std::shared_ptr<DBConnector>(new DBConnector(" ASIC_DB" , 0 ))),
131
+ m_counter_table(std::unique_ptr<Table>(new Table(m_counter_db.get(), COUNTERS_TRAP_NAME_MAP))),
132
+ m_vidToRidTable(std::unique_ptr<Table>(new Table(m_asic_db.get(), "VIDTORID"))),
133
+ m_flex_counter_group_table(std::unique_ptr<ProducerTable>(new ProducerTable(m_flex_db.get(), FLEX_COUNTER_GROUP_TABLE))),
134
+ m_trap_counter_manager(HOSTIF_TRAP_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS, false )
103
135
{
104
136
SWSS_LOG_ENTER ();
137
+ auto intervT = timespec { .tv_sec = FLEX_COUNTER_UPD_INTERVAL , .tv_nsec = 0 };
138
+ m_FlexCounterUpdTimer = new SelectableTimer (intervT);
139
+ auto executorT = new ExecutableTimer (m_FlexCounterUpdTimer, this , " FLEX_COUNTER_UPD_TIMER" );
140
+ Orch::addExecutor (executorT);
105
141
106
142
initDefaultHostIntfTable ();
107
143
initDefaultTrapGroup ();
@@ -321,6 +357,8 @@ bool CoppOrch::applyAttributesToTrapIds(sai_object_id_t trap_group_id,
321
357
}
322
358
m_syncdTrapIds[trap_id].trap_group_obj = trap_group_id;
323
359
m_syncdTrapIds[trap_id].trap_obj = hostif_trap_id;
360
+ m_syncdTrapIds[trap_id].trap_type = trap_id;
361
+ bindTrapCounter (hostif_trap_id, trap_id);
324
362
}
325
363
return true ;
326
364
}
@@ -706,6 +744,35 @@ void CoppOrch::doTask(Consumer &consumer)
706
744
}
707
745
}
708
746
747
+ void CoppOrch::doTask (SelectableTimer &timer)
748
+ {
749
+ SWSS_LOG_ENTER ();
750
+
751
+ string value;
752
+ for (auto it = m_pendingAddToFlexCntr.begin (); it != m_pendingAddToFlexCntr.end (); )
753
+ {
754
+ const auto id = sai_serialize_object_id (it->first );
755
+ if (m_vidToRidTable->hget (" " , id, value))
756
+ {
757
+ SWSS_LOG_INFO (" Registering %s, id %s" , it->second .c_str (), id.c_str ());
758
+
759
+ std::unordered_set<std::string> counter_stats;
760
+ FlowCounterHandler::getGenericCounterStatIdList (counter_stats);
761
+ m_trap_counter_manager.setCounterIdList (it->first , CounterType::HOSTIF_TRAP, counter_stats);
762
+ it = m_pendingAddToFlexCntr.erase (it);
763
+ }
764
+ else
765
+ {
766
+ ++it;
767
+ }
768
+ }
769
+
770
+ if (m_pendingAddToFlexCntr.empty ())
771
+ {
772
+ m_FlexCounterUpdTimer->stop ();
773
+ }
774
+ }
775
+
709
776
void CoppOrch::getTrapAddandRemoveList (string trap_group_name,
710
777
vector<sai_hostif_trap_type_t > &trap_ids,
711
778
vector<sai_hostif_trap_type_t > &add_trap_ids,
@@ -777,17 +844,9 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
777
844
{
778
845
if (m_syncdTrapIds.find (i)!= m_syncdTrapIds.end ())
779
846
{
780
- sai_status_t sai_status = sai_hostif_api->remove_hostif_trap (
781
- m_syncdTrapIds[i].trap_obj );
782
- if (sai_status != SAI_STATUS_SUCCESS)
847
+ if (!removeTrap (m_syncdTrapIds[i].trap_obj ))
783
848
{
784
- SWSS_LOG_ERROR (" Failed to remove trap object %" PRId64 " " ,
785
- m_syncdTrapIds[i].trap_obj );
786
- task_process_status handle_status = handleSaiRemoveStatus (SAI_API_HOSTIF, sai_status);
787
- if (handle_status != task_success)
788
- {
789
- return parseHandleSaiStatusFailure (handle_status);
790
- }
849
+ return false ;
791
850
}
792
851
}
793
852
}
@@ -830,17 +889,9 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
830
889
*/
831
890
if (m_syncdTrapIds[i].trap_group_obj == m_trap_group_map[trap_group_name])
832
891
{
833
- sai_status_t sai_status = sai_hostif_api->remove_hostif_trap (
834
- m_syncdTrapIds[i].trap_obj );
835
- if (sai_status != SAI_STATUS_SUCCESS)
892
+ if (!removeTrap (m_syncdTrapIds[i].trap_obj ))
836
893
{
837
- SWSS_LOG_ERROR (" Failed to remove trap object %" PRId64 " " ,
838
- m_syncdTrapIds[i].trap_obj );
839
- task_process_status handle_status = handleSaiRemoveStatus (SAI_API_HOSTIF, sai_status);
840
- if (handle_status != task_success)
841
- {
842
- return parseHandleSaiStatusFailure (handle_status);
843
- }
894
+ return false ;
844
895
}
845
896
m_syncdTrapIds.erase (i);
846
897
}
@@ -882,15 +933,9 @@ bool CoppOrch::processTrapGroupDel (string trap_group_name)
882
933
if (it.second .trap_group_obj == m_trap_group_map[trap_group_name])
883
934
{
884
935
trap_ids_to_reset.push_back (it.first );
885
- sai_status_t sai_status = sai_hostif_api->remove_hostif_trap (it.second .trap_obj );
886
- if (sai_status != SAI_STATUS_SUCCESS)
936
+ if (!removeTrap (it.second .trap_obj ))
887
937
{
888
- SWSS_LOG_ERROR (" Failed to remove trap object %" PRId64 " " , it.second .trap_obj );
889
- task_process_status handle_status = handleSaiRemoveStatus (SAI_API_HOSTIF, sai_status);
890
- if (handle_status != task_success)
891
- {
892
- return parseHandleSaiStatusFailure (handle_status);
893
- }
938
+ return false ;
894
939
}
895
940
}
896
941
}
@@ -1096,3 +1141,158 @@ bool CoppOrch::trapGroupUpdatePolicer (string trap_group_name,
1096
1141
}
1097
1142
return true ;
1098
1143
}
1144
+
1145
+ void CoppOrch::initTrapRatePlugin ()
1146
+ {
1147
+ if (m_trap_rate_plugin_loaded)
1148
+ {
1149
+ return ;
1150
+ }
1151
+
1152
+ std::string trapRatePluginName = " trap_rates.lua" ;
1153
+ try
1154
+ {
1155
+ std::string trapLuaScript = swss::loadLuaScript (trapRatePluginName);
1156
+ std::string trapSha = swss::loadRedisScript (m_counter_db.get (), trapLuaScript);
1157
+
1158
+ vector<FieldValueTuple> fieldValues;
1159
+ fieldValues.emplace_back (FLOW_COUNTER_PLUGIN_FIELD, trapSha);
1160
+ fieldValues.emplace_back (STATS_MODE_FIELD, STATS_MODE_READ);
1161
+ m_flex_counter_group_table->set (HOSTIF_TRAP_COUNTER_FLEX_COUNTER_GROUP, fieldValues);
1162
+ }
1163
+ catch (const runtime_error &e)
1164
+ {
1165
+ SWSS_LOG_ERROR (" Trap flex counter groups were not set successfully: %s" , e.what ());
1166
+ }
1167
+ m_trap_rate_plugin_loaded = true ;
1168
+ }
1169
+
1170
+ bool CoppOrch::removeTrap (sai_object_id_t hostif_trap_id)
1171
+ {
1172
+ unbindTrapCounter (hostif_trap_id);
1173
+
1174
+ sai_status_t sai_status = sai_hostif_api->remove_hostif_trap (hostif_trap_id);
1175
+ if (sai_status != SAI_STATUS_SUCCESS)
1176
+ {
1177
+ SWSS_LOG_ERROR (" Failed to remove trap object %" PRId64 " " ,
1178
+ hostif_trap_id);
1179
+ task_process_status handle_status = handleSaiRemoveStatus (SAI_API_HOSTIF, sai_status);
1180
+ if (handle_status != task_success)
1181
+ {
1182
+ return parseHandleSaiStatusFailure (handle_status);
1183
+ }
1184
+ }
1185
+
1186
+ return true ;
1187
+ }
1188
+
1189
+ bool CoppOrch::bindTrapCounter (sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type)
1190
+ {
1191
+ auto flex_counters_orch = gDirectory .get <FlexCounterOrch*>();
1192
+
1193
+ if (!flex_counters_orch || !flex_counters_orch->getHostIfTrapCounterState ())
1194
+ {
1195
+ return false ;
1196
+ }
1197
+
1198
+ if (m_trap_obj_name_map.count (hostif_trap_id) > 0 )
1199
+ {
1200
+ return true ;
1201
+ }
1202
+
1203
+ initTrapRatePlugin ();
1204
+
1205
+ // Create generic counter
1206
+ sai_object_id_t counter_id;
1207
+ if (!FlowCounterHandler::createGenericCounter (counter_id))
1208
+ {
1209
+ return false ;
1210
+ }
1211
+
1212
+ // Bind generic counter to trap
1213
+ sai_attribute_t trap_attr;
1214
+ trap_attr.id = SAI_HOSTIF_TRAP_ATTR_COUNTER_ID;
1215
+ trap_attr.value .oid = counter_id;
1216
+ sai_status_t sai_status = sai_hostif_api->set_hostif_trap_attribute (hostif_trap_id, &trap_attr);
1217
+ if (sai_status != SAI_STATUS_SUCCESS)
1218
+ {
1219
+ SWSS_LOG_WARN (" Failed to bind trap %" PRId64 " to counter %" PRId64 " " , hostif_trap_id, counter_id);
1220
+ return false ;
1221
+ }
1222
+
1223
+ // Update COUNTERS_TRAP_NAME_MAP
1224
+ auto trap_name = get_trap_name_by_type (trap_type);
1225
+ vector<FieldValueTuple> nameMapFvs;
1226
+ nameMapFvs.emplace_back (trap_name, sai_serialize_object_id (counter_id));
1227
+ m_counter_table->set (" " , nameMapFvs);
1228
+
1229
+ auto was_empty = m_pendingAddToFlexCntr.empty ();
1230
+ m_pendingAddToFlexCntr[counter_id] = trap_name;
1231
+
1232
+ if (was_empty)
1233
+ {
1234
+ m_FlexCounterUpdTimer->start ();
1235
+ }
1236
+
1237
+ m_trap_obj_name_map.emplace (hostif_trap_id, trap_name);
1238
+ return true ;
1239
+ }
1240
+
1241
+ void CoppOrch::unbindTrapCounter (sai_object_id_t hostif_trap_id)
1242
+ {
1243
+ auto iter = m_trap_obj_name_map.find (hostif_trap_id);
1244
+ if (iter == m_trap_obj_name_map.end ())
1245
+ {
1246
+ return ;
1247
+ }
1248
+
1249
+ std::string counter_oid_str;
1250
+ m_counter_table->hget (" " , iter->second , counter_oid_str);
1251
+
1252
+ // Clear FLEX_COUNTER table
1253
+ sai_object_id_t counter_id;
1254
+ sai_deserialize_object_id (counter_oid_str, counter_id);
1255
+ auto update_iter = m_pendingAddToFlexCntr.find (counter_id);
1256
+ if (update_iter == m_pendingAddToFlexCntr.end ())
1257
+ {
1258
+ m_trap_counter_manager.clearCounterIdList (counter_id);
1259
+ }
1260
+ else
1261
+ {
1262
+ m_pendingAddToFlexCntr.erase (update_iter);
1263
+ }
1264
+
1265
+ // Remove trap from COUNTERS_TRAP_NAME_MAP
1266
+ m_counter_table->hdel (" " , iter->second );
1267
+
1268
+ // Unbind generic counter to trap
1269
+ sai_attribute_t trap_attr;
1270
+ trap_attr.id = SAI_HOSTIF_TRAP_ATTR_COUNTER_ID;
1271
+ trap_attr.value .oid = SAI_NULL_OBJECT_ID;
1272
+ sai_status_t sai_status = sai_hostif_api->set_hostif_trap_attribute (hostif_trap_id, &trap_attr);
1273
+ if (sai_status != SAI_STATUS_SUCCESS)
1274
+ {
1275
+ SWSS_LOG_ERROR (" Failed to unbind trap %" PRId64 " to counter %" PRId64 " " , hostif_trap_id, counter_id);
1276
+ }
1277
+
1278
+ // Remove generic counter
1279
+ FlowCounterHandler::removeGenericCounter (counter_id);
1280
+
1281
+ m_trap_obj_name_map.erase (iter);
1282
+ }
1283
+
1284
+ void CoppOrch::generateHostIfTrapCounterIdList ()
1285
+ {
1286
+ for (const auto &kv : m_syncdTrapIds)
1287
+ {
1288
+ bindTrapCounter (kv.second .trap_obj , kv.second .trap_type );
1289
+ }
1290
+ }
1291
+
1292
+ void CoppOrch::clearHostIfTrapCounterIdList ()
1293
+ {
1294
+ for (const auto &kv : m_syncdTrapIds)
1295
+ {
1296
+ unbindTrapCounter (kv.second .trap_obj );
1297
+ }
1298
+ }
0 commit comments