1+ extern " C" {
2+ #include < saiobject.h>
3+ #include < saistatus.h>
4+ #include < saiswitch.h>
5+ }
6+
17#include " sai.h"
28#include " copporch.h"
39#include " portsorch.h"
@@ -89,9 +95,60 @@ static map<string, sai_hostif_trap_type_t> trap_id_map = {
8995 {" dest_nat_miss" , SAI_HOSTIF_TRAP_TYPE_DNAT_MISS },
9096 {" ldp" , SAI_HOSTIF_TRAP_TYPE_LDP },
9197 {" bfd_micro" , SAI_HOSTIF_TRAP_TYPE_BFD_MICRO },
92- {" bfdv6_micro" , SAI_HOSTIF_TRAP_TYPE_BFDV6_MICRO }
98+ {" bfdv6_micro" , SAI_HOSTIF_TRAP_TYPE_BFDV6_MICRO },
99+ {" neighbor_miss" , SAI_HOSTIF_TRAP_TYPE_NEIGHBOR_MISS }
93100};
94101
102+ /*
103+ * List of default supported traps used as a fallback when the vendor SAI
104+ * does not support capability query for the HOSTIF object.
105+ */
106+ const vector<sai_hostif_trap_type_t > default_supported_trap_ids = {
107+ SAI_HOSTIF_TRAP_TYPE_STP ,
108+ SAI_HOSTIF_TRAP_TYPE_LACP ,
109+ SAI_HOSTIF_TRAP_TYPE_EAPOL ,
110+ SAI_HOSTIF_TRAP_TYPE_LLDP ,
111+ SAI_HOSTIF_TRAP_TYPE_PVRST ,
112+ SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_QUERY ,
113+ SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_LEAVE ,
114+ SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_V1_REPORT ,
115+ SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_V2_REPORT ,
116+ SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_V3_REPORT ,
117+ SAI_HOSTIF_TRAP_TYPE_SAMPLEPACKET ,
118+ SAI_HOSTIF_TRAP_TYPE_SWITCH_CUSTOM_RANGE_BASE ,
119+ SAI_HOSTIF_TRAP_TYPE_ARP_REQUEST ,
120+ SAI_HOSTIF_TRAP_TYPE_ARP_RESPONSE ,
121+ SAI_HOSTIF_TRAP_TYPE_DHCP ,
122+ SAI_HOSTIF_TRAP_TYPE_OSPF ,
123+ SAI_HOSTIF_TRAP_TYPE_PIM ,
124+ SAI_HOSTIF_TRAP_TYPE_VRRP ,
125+ SAI_HOSTIF_TRAP_TYPE_BGP ,
126+ SAI_HOSTIF_TRAP_TYPE_DHCPV6 ,
127+ SAI_HOSTIF_TRAP_TYPE_OSPFV6 ,
128+ SAI_HOSTIF_TRAP_TYPE_ISIS ,
129+ SAI_HOSTIF_TRAP_TYPE_VRRPV6 ,
130+ SAI_HOSTIF_TRAP_TYPE_BGPV6 ,
131+ SAI_HOSTIF_TRAP_TYPE_IPV6_NEIGHBOR_DISCOVERY ,
132+ SAI_HOSTIF_TRAP_TYPE_IPV6_MLD_V1_V2 ,
133+ SAI_HOSTIF_TRAP_TYPE_IPV6_MLD_V1_REPORT ,
134+ SAI_HOSTIF_TRAP_TYPE_IPV6_MLD_V1_DONE ,
135+ SAI_HOSTIF_TRAP_TYPE_MLD_V2_REPORT ,
136+ SAI_HOSTIF_TRAP_TYPE_IP2ME ,
137+ SAI_HOSTIF_TRAP_TYPE_SSH ,
138+ SAI_HOSTIF_TRAP_TYPE_SNMP ,
139+ SAI_HOSTIF_TRAP_TYPE_ROUTER_CUSTOM_RANGE_BASE ,
140+ SAI_HOSTIF_TRAP_TYPE_L3_MTU_ERROR ,
141+ SAI_HOSTIF_TRAP_TYPE_TTL_ERROR ,
142+ SAI_HOSTIF_TRAP_TYPE_UDLD ,
143+ SAI_HOSTIF_TRAP_TYPE_BFD ,
144+ SAI_HOSTIF_TRAP_TYPE_BFDV6 ,
145+ SAI_HOSTIF_TRAP_TYPE_SNAT_MISS ,
146+ SAI_HOSTIF_TRAP_TYPE_DNAT_MISS ,
147+ SAI_HOSTIF_TRAP_TYPE_LDP ,
148+ SAI_HOSTIF_TRAP_TYPE_BFD_MICRO ,
149+ SAI_HOSTIF_TRAP_TYPE_BFDV6_MICRO
150+ /* This list is intended to remain static and should not be updated with new traps. */
151+ };
95152
96153std::string get_trap_name_by_type (sai_hostif_trap_type_t trap_type)
97154{
@@ -104,7 +161,13 @@ std::string get_trap_name_by_type(sai_hostif_trap_type_t trap_type)
104161 }
105162 }
106163
107- return trap_name_to_id_map.at (trap_type);
164+ auto it = trap_name_to_id_map.find (trap_type);
165+ if (it == trap_name_to_id_map.end ())
166+ {
167+ return " " ;
168+ }
169+
170+ return it->second ;
108171}
109172
110173static map<string, sai_packet_action_t > packet_action_map = {
@@ -122,27 +185,118 @@ const string default_trap_group = "default";
122185const vector<sai_hostif_trap_type_t > default_trap_ids = {
123186 SAI_HOSTIF_TRAP_TYPE_TTL_ERROR
124187};
188+
125189const uint HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS = 10000 ;
126190
127191CoppOrch::CoppOrch (DBConnector* db, string tableName) :
128192 Orch(db, tableName),
129193 m_counter_db(std::shared_ptr<DBConnector>(new DBConnector(" COUNTERS_DB" , 0 ))),
130194 m_asic_db(std::shared_ptr<DBConnector>(new DBConnector(" ASIC_DB" , 0 ))),
195+ m_state_db(std::shared_ptr<DBConnector>(new DBConnector(" STATE_DB" , 0 ))),
131196 m_counter_table(std::unique_ptr<Table>(new Table(m_counter_db.get(), COUNTERS_TRAP_NAME_MAP))),
132197 m_vidToRidTable(std::unique_ptr<Table>(new Table(m_asic_db.get(), "VIDTORID"))),
133- m_trap_counter_manager(HOSTIF_TRAP_COUNTER_FLEX_COUNTER_GROUP , StatsMode::READ , HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS , false )
198+ m_trap_counter_manager(HOSTIF_TRAP_COUNTER_FLEX_COUNTER_GROUP , StatsMode::READ , HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS , false ),
199+ m_trapCapabilityTable(std::unique_ptr<Table>(new Table(m_state_db.get(), STATE_COPP_TRAP_CAPABILITY_TABLE_NAME))),
200+ m_trapTable(std::unique_ptr<Table>(new Table(m_state_db.get(), STATE_COPP_TRAP_TABLE_NAME)))
134201{
135202 SWSS_LOG_ENTER ();
136203 auto intervT = timespec { .tv_sec = FLEX_COUNTER_UPD_INTERVAL , .tv_nsec = 0 };
137204 m_FlexCounterUpdTimer = new SelectableTimer (intervT);
138205 auto executorT = new ExecutableTimer (m_FlexCounterUpdTimer, this , " FLEX_COUNTER_UPD_TIMER" );
139206 Orch::addExecutor (executorT);
140207
208+ /* Query SAI for supported trap IDs and publish to STATE_DB */
209+ publishTrapIdsCapability ();
210+
141211 initDefaultHostIntfTable ();
142212 initDefaultTrapGroup ();
143213 initDefaultTrapIds ();
214+
144215};
145216
217+ bool CoppOrch::isTrapIdSupported (sai_hostif_trap_type_t trap_id) const
218+ {
219+ return supported_trap_ids.find (trap_id) != supported_trap_ids.end ();
220+ }
221+
222+ void CoppOrch::updateTrapOperStatus (sai_hostif_trap_type_t trap_type, const string& hw_status)
223+ {
224+ SWSS_LOG_ENTER ();
225+
226+ string trap_name = get_trap_name_by_type (trap_type);
227+ if (trap_name.empty ())
228+ {
229+ SWSS_LOG_ERROR (" Failed to get trap name for type %d" , trap_type);
230+ return ;
231+ }
232+
233+ // Update or add the hw_status field in the table
234+ vector<FieldValueTuple> hwStatusFvs;
235+ hwStatusFvs.emplace_back (" hw_status" , hw_status);
236+ m_trapTable->set (trap_name, hwStatusFvs);
237+ }
238+
239+ // Query SAI for trap IDs capability and publish to the COPP_TRAP_CAPABILITY_TABLE
240+ void CoppOrch::publishTrapIdsCapability ()
241+ {
242+ SWSS_LOG_ENTER ();
243+
244+ sai_s32_list_t enum_values_capability;
245+
246+ supported_trap_ids.clear ();
247+
248+ const auto * meta = sai_metadata_get_attr_metadata (SAI_OBJECT_TYPE_HOSTIF_TRAP , SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE );
249+ if (!meta || !meta->isenum )
250+ {
251+ SWSS_LOG_THROW (" sai_metadata_get_attr_metadata for SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE Failed" );
252+ return ;
253+ }
254+
255+ vector<int32_t > values_list (meta->enummetadata ->valuescount );
256+ enum_values_capability.count = static_cast <uint32_t >(values_list.size ());
257+ enum_values_capability.list = values_list.data ();
258+
259+ sai_status_t status = sai_query_attribute_enum_values_capability (gSwitchId ,
260+ SAI_OBJECT_TYPE_HOSTIF_TRAP ,
261+ SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE ,
262+ &enum_values_capability);
263+ if (status != SAI_STATUS_SUCCESS )
264+ {
265+ SWSS_LOG_WARN (" SAI capability query for SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE is failed,"
266+ " falling back to default supported trap IDs" );
267+ // Populate enum_values_capability with default_supported_trap_ids
268+ enum_values_capability.count = static_cast <uint32_t >(default_supported_trap_ids.size ());
269+ values_list.assign (default_supported_trap_ids.begin (), default_supported_trap_ids.end ());
270+ enum_values_capability.list = values_list.data ();
271+ }
272+
273+ string trap_id_list_str;
274+
275+ for (uint32_t i = 0 ; i < enum_values_capability.count ; i++)
276+ {
277+
278+ auto trap_str = get_trap_name_by_type (static_cast <sai_hostif_trap_type_t >(enum_values_capability.list [i]));
279+ if (trap_str.empty ())
280+ {
281+ SWSS_LOG_NOTICE (" Unknown trap id enum value: %d" , enum_values_capability.list [i]);
282+ continue ;
283+ }
284+
285+ supported_trap_ids.insert (static_cast <sai_hostif_trap_type_t >(enum_values_capability.list [i]));
286+
287+ if (!trap_id_list_str.empty ())
288+ {
289+ trap_id_list_str += " ," ;
290+ }
291+ trap_id_list_str += trap_str;
292+ }
293+
294+ SWSS_LOG_INFO (" Publishing supported trap IDs to STATE_DB" );
295+ vector<FieldValueTuple> trapCapabilityFvs;
296+ trapCapabilityFvs.push_back (FieldValueTuple (" trap_ids" , trap_id_list_str));
297+ m_trapCapabilityTable->set (" traps" , trapCapabilityFvs);
298+ }
299+
146300void CoppOrch::initDefaultHostIntfTable ()
147301{
148302 SWSS_LOG_ENTER ();
@@ -248,6 +402,14 @@ void CoppOrch::getTrapIdList(vector<string> &trap_id_name_list, vector<sai_hosti
248402 SWSS_LOG_NOTICE (" Ignoring the trap_id: %s, as NAT is not supported" , trap_id_str.c_str ());
249403 continue ;
250404 }
405+
406+ if (!isTrapIdSupported (trap_id))
407+ {
408+ /* If the trap_id is not in supported_trap_ids, ignore it */
409+ SWSS_LOG_NOTICE (" Ignoring the trap_id: %s, since not supported by vendor SAI" , trap_id_str.c_str ());
410+ continue ;
411+ }
412+
251413 trap_id_list.push_back (trap_id);
252414 }
253415}
@@ -358,6 +520,8 @@ bool CoppOrch::applyAttributesToTrapIds(sai_object_id_t trap_group_id,
358520 return parseHandleSaiStatusFailure (handle_status);
359521 }
360522 }
523+
524+ updateTrapOperStatus (trap_id, " installed" );
361525 m_syncdTrapIds[trap_id].trap_group_obj = trap_group_id;
362526 m_syncdTrapIds[trap_id].trap_obj = hostif_trap_id;
363527 m_syncdTrapIds[trap_id].trap_type = trap_id;
@@ -803,6 +967,7 @@ void CoppOrch::getTrapAddandRemoveList(string trap_group_name,
803967{
804968
805969 vector<sai_hostif_trap_type_t > tmp_trap_ids = trap_ids;
970+
806971 if (m_trap_group_map.find (trap_group_name) == m_trap_group_map.end ())
807972 {
808973 add_trap_ids = trap_ids;
@@ -867,7 +1032,7 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
8671032 {
8681033 if (m_syncdTrapIds.find (i)!= m_syncdTrapIds.end ())
8691034 {
870- if (!removeTrap (m_syncdTrapIds[i].trap_obj ))
1035+ if (!removeTrap (m_syncdTrapIds[i].trap_obj , i ))
8711036 {
8721037 return false ;
8731038 }
@@ -912,7 +1077,7 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
9121077 */
9131078 if (m_syncdTrapIds[i].trap_group_obj == m_trap_group_map[trap_group_name])
9141079 {
915- if (!removeTrap (m_syncdTrapIds[i].trap_obj ))
1080+ if (!removeTrap (m_syncdTrapIds[i].trap_obj , i ))
9161081 {
9171082 return false ;
9181083 }
@@ -956,7 +1121,7 @@ bool CoppOrch::processTrapGroupDel (string trap_group_name)
9561121 if (it.second .trap_group_obj == m_trap_group_map[trap_group_name])
9571122 {
9581123 trap_ids_to_reset.push_back (it.first );
959- if (!removeTrap (it.second .trap_obj ))
1124+ if (!removeTrap (it.second .trap_obj , it. first ))
9601125 {
9611126 return false ;
9621127 }
@@ -1227,7 +1392,7 @@ void CoppOrch::initTrapRatePlugin()
12271392 m_trap_rate_plugin_loaded = true ;
12281393}
12291394
1230- bool CoppOrch::removeTrap (sai_object_id_t hostif_trap_id)
1395+ bool CoppOrch::removeTrap (sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type )
12311396{
12321397 unbindTrapCounter (hostif_trap_id);
12331398
@@ -1242,6 +1407,8 @@ bool CoppOrch::removeTrap(sai_object_id_t hostif_trap_id)
12421407 return parseHandleSaiStatusFailure (handle_status);
12431408 }
12441409 }
1410+
1411+ updateTrapOperStatus (trap_type, " not-installed" );
12451412
12461413 return true ;
12471414}
0 commit comments