Skip to content

Commit 07ac4e0

Browse files
rminnikantivivekrnv
authored andcommitted
[orchagent] CoPP neighbor miss trap and enhancements (sonic-net#3624)
* [orchagent] CoPP neighbor miss trap and enhancements What I did * Added neighbor_miss trap type support * enum capability query for hostif trap type * Added trap hw_status field to state_db * Added UT and mock tests HLD: sonic-net/SONiC#1943
1 parent 3ee86cb commit 07ac4e0

7 files changed

Lines changed: 274 additions & 12 deletions

File tree

orchagent/copporch.cpp

Lines changed: 176 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
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

96153
std::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

110173
static map<string, sai_packet_action_t> packet_action_map = {
@@ -122,27 +185,120 @@ const string default_trap_group = "default";
122185
const vector<sai_hostif_trap_type_t> default_trap_ids = {
123186
SAI_HOSTIF_TRAP_TYPE_TTL_ERROR
124187
};
188+
125189
const uint HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS = 10000;
126190

127191
CoppOrch::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+
146302
void 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
}

orchagent/copporch.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
#ifndef SWSS_COPPORCH_H
22
#define SWSS_COPPORCH_H
33

4+
extern "C" {
5+
#include <saiobject.h>
6+
#include <saistatus.h>
7+
#include <saiswitch.h>
8+
}
9+
410
#include <map>
511
#include <set>
612
#include <memory>
13+
#include <unordered_set>
714
#include "dbconnector.h"
815
#include "orch.h"
916
#include "flex_counter_manager.h"
@@ -99,8 +106,13 @@ class CoppOrch : public Orch
99106

100107
std::shared_ptr<DBConnector> m_counter_db;
101108
std::shared_ptr<DBConnector> m_asic_db;
109+
std::shared_ptr<DBConnector> m_state_db;
102110
std::unique_ptr<Table> m_counter_table;
103111
std::unique_ptr<Table> m_vidToRidTable;
112+
std::unique_ptr<Table> m_trapCapabilityTable;
113+
std::unique_ptr<Table> m_trapTable;
114+
115+
std::unordered_set<sai_hostif_trap_type_t> supported_trap_ids;
104116

105117
FlexCounterManager m_trap_counter_manager;
106118

@@ -112,6 +124,9 @@ class CoppOrch : public Orch
112124
void initDefaultTrapGroup();
113125
void initDefaultTrapIds();
114126
void initTrapRatePlugin();
127+
bool isTrapIdSupported(sai_hostif_trap_type_t trap_id) const;
128+
void updateTrapOperStatus(sai_hostif_trap_type_t trap_type, const std::string& hw_status);
129+
void publishTrapIdsCapability();
115130

116131
task_process_status processCoppRule(Consumer& consumer);
117132
bool isValidList(std::vector<std::string> &trap_id_list, std::vector<std::string> &all_items) const;
@@ -148,7 +163,7 @@ class CoppOrch : public Orch
148163

149164
bool trapGroupUpdatePolicer (std::string trap_group_name, std::vector<sai_attribute_t> &policer_attribs);
150165

151-
bool removeTrap(sai_object_id_t hostif_trap_id);
166+
bool removeTrap(sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type);
152167

153168
bool bindTrapCounter(sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type);
154169
void unbindTrapCounter(sai_object_id_t hostif_trap_id);

orchagent/debugcounterorch.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ void DebugCounterOrch::doTask(Consumer& consumer)
227227

228228
// publishDropCounterCapabilities queries the SAI for available drop counter
229229
// capabilities on this device and publishes the information to the
230-
// DROP_COUNTER_CAPABILITIES table in STATE_DB.
230+
// DEBUG_COUNTER_CAPABILITIES table in STATE_DB.
231231
void DebugCounterOrch::publishDropCounterCapabilities()
232232
{
233233
supported_ingress_drop_reasons = DropCounter::getSupportedDropReasons(SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST);

tests/mock_tests/copp_cfg.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@
4848
"cbs":"600",
4949
"red_action":"drop"
5050
},
51+
"queue1_group3": {
52+
"trap_action":"trap",
53+
"trap_priority":"1",
54+
"queue": "1",
55+
"meter_type":"packets",
56+
"mode":"sr_tcm",
57+
"cir":"200",
58+
"cbs":"200",
59+
"red_action":"drop"
60+
},
5161
"queue2_group1": {
5262
"cbs": "1000",
5363
"cir": "1000",
@@ -106,6 +116,11 @@
106116
"sflow": {
107117
"trap_group": "queue2_group1",
108118
"trap_ids": "sample_packet"
119+
},
120+
"neighbor_miss": {
121+
"trap_ids": "neighbor_miss",
122+
"trap_group": "queue1_group3",
123+
"always_enabled": "true"
109124
}
110125
}
111126
}

0 commit comments

Comments
 (0)