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,120 @@ 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_WARN (" 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_NOTICE (" 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+ SWSS_LOG_NOTICE (" Number of supported trap IDs: %u" , enum_values_capability.count );
274+
275+ string trap_id_list_str;
276+
277+ for (uint32_t i = 0 ; i < enum_values_capability.count ; i++)
278+ {
279+
280+ auto trap_str = get_trap_name_by_type (static_cast <sai_hostif_trap_type_t >(enum_values_capability.list [i]));
281+ if (trap_str.empty ())
282+ {
283+ SWSS_LOG_NOTICE (" Unknown trap id enum value: %d" , enum_values_capability.list [i]);
284+ continue ;
285+ }
286+
287+ supported_trap_ids.insert (static_cast <sai_hostif_trap_type_t >(enum_values_capability.list [i]));
288+
289+ if (!trap_id_list_str.empty ())
290+ {
291+ trap_id_list_str += " ," ;
292+ }
293+ trap_id_list_str += trap_str;
294+ }
295+
296+ SWSS_LOG_NOTICE (" Publishing supported trap IDs to STATE_DB" );
297+ vector<FieldValueTuple> trapCapabilityFvs;
298+ trapCapabilityFvs.push_back (FieldValueTuple (" trap_ids" , trap_id_list_str));
299+ m_trapCapabilityTable->set (" traps" , trapCapabilityFvs);
300+ }
301+
146302void CoppOrch::initDefaultHostIntfTable ()
147303{
148304 SWSS_LOG_ENTER ();
@@ -248,6 +404,14 @@ void CoppOrch::getTrapIdList(vector<string> &trap_id_name_list, vector<sai_hosti
248404 SWSS_LOG_NOTICE (" Ignoring the trap_id: %s, as NAT is not supported" , trap_id_str.c_str ());
249405 continue ;
250406 }
407+
408+ if (!isTrapIdSupported (trap_id))
409+ {
410+ /* If the trap_id is not in supported_trap_ids, ignore it */
411+ SWSS_LOG_NOTICE (" Ignoring the trap_id: %s, since not supported by vendor SAI" , trap_id_str.c_str ());
412+ continue ;
413+ }
414+
251415 trap_id_list.push_back (trap_id);
252416 }
253417}
@@ -358,6 +522,8 @@ bool CoppOrch::applyAttributesToTrapIds(sai_object_id_t trap_group_id,
358522 return parseHandleSaiStatusFailure (handle_status);
359523 }
360524 }
525+
526+ updateTrapOperStatus (trap_id, " installed" );
361527 m_syncdTrapIds[trap_id].trap_group_obj = trap_group_id;
362528 m_syncdTrapIds[trap_id].trap_obj = hostif_trap_id;
363529 m_syncdTrapIds[trap_id].trap_type = trap_id;
@@ -803,6 +969,7 @@ void CoppOrch::getTrapAddandRemoveList(string trap_group_name,
803969{
804970
805971 vector<sai_hostif_trap_type_t > tmp_trap_ids = trap_ids;
972+
806973 if (m_trap_group_map.find (trap_group_name) == m_trap_group_map.end ())
807974 {
808975 add_trap_ids = trap_ids;
@@ -867,7 +1034,7 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
8671034 {
8681035 if (m_syncdTrapIds.find (i)!= m_syncdTrapIds.end ())
8691036 {
870- if (!removeTrap (m_syncdTrapIds[i].trap_obj ))
1037+ if (!removeTrap (m_syncdTrapIds[i].trap_obj , i ))
8711038 {
8721039 return false ;
8731040 }
@@ -912,7 +1079,7 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
9121079 */
9131080 if (m_syncdTrapIds[i].trap_group_obj == m_trap_group_map[trap_group_name])
9141081 {
915- if (!removeTrap (m_syncdTrapIds[i].trap_obj ))
1082+ if (!removeTrap (m_syncdTrapIds[i].trap_obj , i ))
9161083 {
9171084 return false ;
9181085 }
@@ -956,7 +1123,7 @@ bool CoppOrch::processTrapGroupDel (string trap_group_name)
9561123 if (it.second .trap_group_obj == m_trap_group_map[trap_group_name])
9571124 {
9581125 trap_ids_to_reset.push_back (it.first );
959- if (!removeTrap (it.second .trap_obj ))
1126+ if (!removeTrap (it.second .trap_obj , it. first ))
9601127 {
9611128 return false ;
9621129 }
@@ -1227,7 +1394,7 @@ void CoppOrch::initTrapRatePlugin()
12271394 m_trap_rate_plugin_loaded = true ;
12281395}
12291396
1230- bool CoppOrch::removeTrap (sai_object_id_t hostif_trap_id)
1397+ bool CoppOrch::removeTrap (sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type )
12311398{
12321399 unbindTrapCounter (hostif_trap_id);
12331400
@@ -1242,6 +1409,8 @@ bool CoppOrch::removeTrap(sai_object_id_t hostif_trap_id)
12421409 return parseHandleSaiStatusFailure (handle_status);
12431410 }
12441411 }
1412+
1413+ updateTrapOperStatus (trap_type, " not-installed" );
12451414
12461415 return true ;
12471416}
0 commit comments