77#include < inttypes.h>
88#include < sstream>
99#include < iostream>
10+ #include < algorithm>
1011
1112using namespace swss ;
1213using namespace std ;
@@ -90,14 +91,15 @@ const vector<sai_hostif_trap_type_t> default_trap_ids = {
9091 SAI_HOSTIF_TRAP_TYPE_TTL_ERROR
9192};
9293
93- CoppOrch::CoppOrch (DBConnector *db, string tableName ) :
94- Orch(db, tableName )
94+ CoppOrch::CoppOrch (vector<TableConnector> &tableConnectors ) :
95+ Orch( tableConnectors )
9596{
9697 SWSS_LOG_ENTER ();
9798
9899 initDefaultHostIntfTable ();
99100 initDefaultTrapGroup ();
100101 initDefaultTrapIds ();
102+ enable_sflow_trap = false ;
101103};
102104
103105void CoppOrch::initDefaultHostIntfTable ()
@@ -191,6 +193,60 @@ void CoppOrch::getTrapIdList(vector<string> &trap_id_name_list, vector<sai_hosti
191193 }
192194}
193195
196+ bool CoppOrch::createGenetlinkHostIfTable (vector<string> &trap_id_name_list)
197+ {
198+ SWSS_LOG_ENTER ();
199+
200+ vector<sai_hostif_trap_type_t > trap_id_list;
201+
202+ getTrapIdList (trap_id_name_list, trap_id_list);
203+
204+ for (auto trap_id : trap_id_list)
205+ {
206+ auto host_tbl_entry = m_trapid_hostif_table_map.find (trap_id);
207+
208+ if (host_tbl_entry == m_trapid_hostif_table_map.end ())
209+ {
210+ sai_object_id_t trap_group_id = m_syncdTrapIds[trap_id].trap_group_obj ;
211+ auto hostif_map = m_trap_group_hostif_map.find (trap_group_id);
212+ if (hostif_map != m_trap_group_hostif_map.end ())
213+ {
214+ sai_object_id_t hostif_table_entry = SAI_NULL_OBJECT_ID;
215+ sai_attribute_t attr;
216+ vector<sai_attribute_t > sai_host_table_attr;
217+
218+ attr.id = SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE;
219+ attr.value .s32 = SAI_HOSTIF_TABLE_ENTRY_TYPE_TRAP_ID;
220+ sai_host_table_attr.push_back (attr);
221+
222+ attr.id = SAI_HOSTIF_TABLE_ENTRY_ATTR_TRAP_ID;
223+ attr.value .oid = m_syncdTrapIds[trap_id].trap_obj ;
224+ sai_host_table_attr.push_back (attr);
225+
226+ attr.id = SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE;
227+ attr.value .s32 = SAI_HOSTIF_TABLE_ENTRY_CHANNEL_TYPE_GENETLINK;
228+ sai_host_table_attr.push_back (attr);
229+
230+ attr.id = SAI_HOSTIF_TABLE_ENTRY_ATTR_HOST_IF;
231+ attr.value .oid = hostif_map->second ;
232+ sai_host_table_attr.push_back (attr);
233+
234+ sai_status_t status = sai_hostif_api->create_hostif_table_entry (&hostif_table_entry,
235+ gSwitchId ,
236+ (uint32_t )sai_host_table_attr.size (),
237+ sai_host_table_attr.data ());
238+ if (status != SAI_STATUS_SUCCESS)
239+ {
240+ SWSS_LOG_ERROR (" Failed to create hostif table entry failed, rv %d" , status);
241+ return false ;
242+ }
243+ m_trapid_hostif_table_map[trap_id] = hostif_table_entry;
244+ }
245+ }
246+ }
247+ return true ;
248+ }
249+
194250bool CoppOrch::applyAttributesToTrapIds (sai_object_id_t trap_group_id,
195251 const vector<sai_hostif_trap_type_t > &trap_id_list,
196252 vector<sai_attribute_t > &trap_id_attribs)
@@ -213,9 +269,9 @@ bool CoppOrch::applyAttributesToTrapIds(sai_object_id_t trap_group_id,
213269 SWSS_LOG_ERROR (" Failed to create trap %d, rv:%d" , trap_id, status);
214270 return false ;
215271 }
216- m_syncdTrapIds[trap_id] = trap_group_id;
272+ m_syncdTrapIds[trap_id].trap_group_obj = trap_group_id;
273+ m_syncdTrapIds[trap_id].trap_obj = hostif_trap_id;
217274 }
218-
219275 return true ;
220276}
221277
@@ -235,6 +291,7 @@ bool CoppOrch::applyTrapIds(sai_object_id_t trap_group, vector<string> &trap_id_
235291 return applyAttributesToTrapIds (trap_group, trap_id_list, trap_id_attribs);
236292}
237293
294+
238295bool CoppOrch::removePolicer (string trap_group_name)
239296{
240297 SWSS_LOG_ENTER ();
@@ -321,6 +378,69 @@ bool CoppOrch::createPolicer(string trap_group_name, vector<sai_attribute_t> &po
321378 return true ;
322379}
323380
381+ bool CoppOrch::createGenetlinkHostIf (string trap_group_name, vector<sai_attribute_t > &genetlink_attribs)
382+ {
383+ SWSS_LOG_ENTER ();
384+
385+ sai_object_id_t hostif_id;
386+ sai_status_t sai_status;
387+
388+ sai_status = sai_hostif_api->create_hostif (&hostif_id, gSwitchId ,
389+ (uint32_t )genetlink_attribs.size (),
390+ genetlink_attribs.data ());
391+ if (sai_status != SAI_STATUS_SUCCESS)
392+ {
393+ SWSS_LOG_ERROR (" Failed to create genetlink hostif for trap group %s, rc=%d" ,
394+ trap_group_name.c_str (), sai_status);
395+ return false ;
396+ }
397+
398+ m_trap_group_hostif_map[m_trap_group_map[trap_group_name]] = hostif_id;
399+ return true ;
400+ }
401+
402+ bool CoppOrch::removeGenetlinkHostIf (string trap_group_name)
403+ {
404+ SWSS_LOG_ENTER ();
405+
406+ sai_status_t sai_status;
407+
408+ for (auto it : m_syncdTrapIds)
409+ {
410+ if (it.second .trap_group_obj == m_trap_group_map[trap_group_name])
411+ {
412+ auto hostTableEntry = m_trapid_hostif_table_map.find (it.first );
413+ if (hostTableEntry != m_trapid_hostif_table_map.end ())
414+ {
415+ sai_status = sai_hostif_api->remove_hostif_table_entry (hostTableEntry->second );
416+ if (sai_status != SAI_STATUS_SUCCESS)
417+ {
418+ SWSS_LOG_ERROR (" Failed to delete hostif table entry %ld \
419+ on trap group %s. rc=%d" , hostTableEntry->second ,
420+ trap_group_name.c_str (), sai_status);
421+ return false ;
422+ }
423+ m_trapid_hostif_table_map.erase (it.first );
424+ }
425+ }
426+ }
427+
428+ auto hostInfo = m_trap_group_hostif_map.find (m_trap_group_map[trap_group_name]);
429+ if (hostInfo != m_trap_group_hostif_map.end ())
430+ {
431+ sai_status = sai_hostif_api->remove_hostif (hostInfo->second );
432+ if (sai_status != SAI_STATUS_SUCCESS)
433+ {
434+ SWSS_LOG_ERROR (" Failed to delete host info %ld on trap group %s. rc=%d" ,
435+ hostInfo->second , trap_group_name.c_str (), sai_status);
436+ return false ;
437+ }
438+ m_trap_group_hostif_map.erase (m_trap_group_map[trap_group_name]);
439+ }
440+
441+ return true ;
442+ }
443+
324444task_process_status CoppOrch::processCoppRule (Consumer& consumer)
325445{
326446 SWSS_LOG_ENTER ();
@@ -336,6 +456,7 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
336456 vector<sai_attribute_t > trap_gr_attribs;
337457 vector<sai_attribute_t > trap_id_attribs;
338458 vector<sai_attribute_t > policer_attribs;
459+ vector<sai_attribute_t > genetlink_attribs;
339460
340461 if (op == SET_COMMAND)
341462 {
@@ -346,6 +467,14 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
346467 if (fvField (*i) == copp_trap_id_list)
347468 {
348469 trap_id_list = tokenize (fvValue (*i), list_item_delimiter);
470+ auto it = std::find (trap_id_list.begin (), trap_id_list.end (), " sample_packet" );
471+ if (it != trap_id_list.end ())
472+ {
473+ if (!enable_sflow_trap)
474+ {
475+ return task_process_status::task_need_retry;
476+ }
477+ }
349478 }
350479 else if (fvField (*i) == copp_queue_field)
351480 {
@@ -443,6 +572,25 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
443572 attr.value .s32 = policer_action;
444573 policer_attribs.push_back (attr);
445574 }
575+ else if (fvField (*i) == copp_genetlink_name)
576+ {
577+ attr.id = SAI_HOSTIF_ATTR_TYPE;
578+ attr.value .s32 = SAI_HOSTIF_TYPE_GENETLINK;
579+ genetlink_attribs.push_back (attr);
580+
581+ attr.id = SAI_HOSTIF_ATTR_NAME;
582+ strncpy (attr.value .chardata , fvValue (*i).c_str (),
583+ sizeof (attr.value .chardata ));
584+ genetlink_attribs.push_back (attr);
585+
586+ }
587+ else if (fvField (*i) == copp_genetlink_mcgrp_name)
588+ {
589+ attr.id = SAI_HOSTIF_ATTR_GENETLINK_MCGRP_NAME;
590+ strncpy (attr.value .chardata , fvValue (*i).c_str (),
591+ sizeof (attr.value .chardata ));
592+ genetlink_attribs.push_back (attr);
593+ }
446594 else
447595 {
448596 SWSS_LOG_ERROR (" Unknown copp field specified:%s\n " , fvField (*i).c_str ());
@@ -519,13 +667,29 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
519667 return task_process_status::task_failed;
520668 }
521669 }
670+
671+ if (!genetlink_attribs.empty ())
672+ {
673+ if (!createGenetlinkHostIf (trap_group_name, genetlink_attribs))
674+ {
675+ return task_process_status::task_failed;
676+ }
677+ }
522678 }
523679
524680 /* Apply traps to trap group */
525681 if (!applyTrapIds (m_trap_group_map[trap_group_name], trap_id_list, trap_id_attribs))
526682 {
527683 return task_process_status::task_failed;
528684 }
685+
686+ if (!genetlink_attribs.empty ())
687+ {
688+ if (!createGenetlinkHostIfTable (trap_id_list))
689+ {
690+ return task_process_status::task_failed;
691+ }
692+ }
529693 }
530694 else if (op == DEL_COMMAND)
531695 {
@@ -536,6 +700,12 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
536700 return task_process_status::task_failed;
537701 }
538702
703+ if (!removeGenetlinkHostIf (trap_group_name))
704+ {
705+ SWSS_LOG_ERROR (" Failed to remove hostif from trap group %s" , trap_group_name.c_str ());
706+ return task_process_status::task_failed;
707+ }
708+
539709 /* Do not remove default trap group */
540710 if (trap_group_name == default_trap_group)
541711 {
@@ -547,10 +717,16 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
547717 vector<sai_hostif_trap_type_t > trap_ids_to_reset;
548718 for (auto it : m_syncdTrapIds)
549719 {
550- if (it.second == m_trap_group_map[trap_group_name])
720+ if (it.second . trap_group_obj == m_trap_group_map[trap_group_name])
551721 {
552722 trap_ids_to_reset.push_back (it.first );
553723 }
724+ sai_status = sai_hostif_api->remove_hostif_trap (it.second .trap_obj );
725+ if (sai_status != SAI_STATUS_SUCCESS)
726+ {
727+ SWSS_LOG_ERROR (" Failed to remove trap object %ld" , it.second .trap_obj );
728+ return task_process_status::task_failed;
729+ }
554730 }
555731
556732 sai_attribute_t attr;
@@ -588,9 +764,49 @@ task_process_status CoppOrch::processCoppRule(Consumer& consumer)
588764 return task_process_status::task_success;
589765}
590766
767+ /* Program Sflow trap once we get sflow enable command */
768+ void CoppOrch::coppProcessSflow (Consumer &consumer)
769+ {
770+ auto it = consumer.m_toSync .begin ();
771+
772+ while (it != consumer.m_toSync .end ())
773+ {
774+ auto tuple = it->second ;
775+ string op = kfvOp (tuple);
776+
777+ /*
778+ * Need to handled just 'config sflow enable' command to install the sflow trap group
779+ * for the first time to ensure support of genetlink attributes. Rest of the fields or
780+ * disable value or DEL command are not required to be handled
781+ *
782+ */
783+ if (op == SET_COMMAND)
784+ {
785+ for (auto i : kfvFieldsValues (tuple))
786+ {
787+ if (fvField (i) == " admin_state" )
788+ {
789+ if (fvValue (i) == " up" )
790+ {
791+ enable_sflow_trap = true ;
792+ }
793+ }
794+ }
795+ }
796+ it = consumer.m_toSync .erase (it);
797+ }
798+ }
799+
591800void CoppOrch::doTask (Consumer &consumer)
592801{
593802 SWSS_LOG_ENTER ();
803+ string table_name = consumer.getTableName ();
804+
805+ if (table_name == CFG_SFLOW_TABLE_NAME)
806+ {
807+ coppProcessSflow (consumer);
808+ return ;
809+ }
594810
595811 if (!gPortsOrch ->allPortsReady ())
596812 {
0 commit comments