Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 176 additions & 7 deletions orchagent/copporch.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
extern "C" {
#include <saiobject.h>
#include <saistatus.h>
#include <saiswitch.h>
}

#include "sai.h"
#include "copporch.h"
#include "portsorch.h"
Expand Down Expand Up @@ -89,9 +95,60 @@ static map<string, sai_hostif_trap_type_t> trap_id_map = {
{"dest_nat_miss", SAI_HOSTIF_TRAP_TYPE_DNAT_MISS},
{"ldp", SAI_HOSTIF_TRAP_TYPE_LDP},
{"bfd_micro", SAI_HOSTIF_TRAP_TYPE_BFD_MICRO},
{"bfdv6_micro", SAI_HOSTIF_TRAP_TYPE_BFDV6_MICRO}
{"bfdv6_micro", SAI_HOSTIF_TRAP_TYPE_BFDV6_MICRO},
{"neighbor_miss", SAI_HOSTIF_TRAP_TYPE_NEIGHBOR_MISS}
};

/*
* List of default supported traps used as a fallback when the vendor SAI
* does not support capability query for the HOSTIF object.
*/
const vector<sai_hostif_trap_type_t> default_supported_trap_ids = {
SAI_HOSTIF_TRAP_TYPE_STP,
SAI_HOSTIF_TRAP_TYPE_LACP,
SAI_HOSTIF_TRAP_TYPE_EAPOL,
SAI_HOSTIF_TRAP_TYPE_LLDP,
SAI_HOSTIF_TRAP_TYPE_PVRST,
SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_QUERY,
SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_LEAVE,
SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_V1_REPORT,
SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_V2_REPORT,
SAI_HOSTIF_TRAP_TYPE_IGMP_TYPE_V3_REPORT,
SAI_HOSTIF_TRAP_TYPE_SAMPLEPACKET,
SAI_HOSTIF_TRAP_TYPE_SWITCH_CUSTOM_RANGE_BASE,
SAI_HOSTIF_TRAP_TYPE_ARP_REQUEST,
SAI_HOSTIF_TRAP_TYPE_ARP_RESPONSE,
SAI_HOSTIF_TRAP_TYPE_DHCP,
SAI_HOSTIF_TRAP_TYPE_OSPF,
SAI_HOSTIF_TRAP_TYPE_PIM,
SAI_HOSTIF_TRAP_TYPE_VRRP,
SAI_HOSTIF_TRAP_TYPE_BGP,
SAI_HOSTIF_TRAP_TYPE_DHCPV6,
SAI_HOSTIF_TRAP_TYPE_OSPFV6,
SAI_HOSTIF_TRAP_TYPE_ISIS,
SAI_HOSTIF_TRAP_TYPE_VRRPV6,
SAI_HOSTIF_TRAP_TYPE_BGPV6,
SAI_HOSTIF_TRAP_TYPE_IPV6_NEIGHBOR_DISCOVERY,
SAI_HOSTIF_TRAP_TYPE_IPV6_MLD_V1_V2,
SAI_HOSTIF_TRAP_TYPE_IPV6_MLD_V1_REPORT,
SAI_HOSTIF_TRAP_TYPE_IPV6_MLD_V1_DONE,
SAI_HOSTIF_TRAP_TYPE_MLD_V2_REPORT,
SAI_HOSTIF_TRAP_TYPE_IP2ME,
SAI_HOSTIF_TRAP_TYPE_SSH,
SAI_HOSTIF_TRAP_TYPE_SNMP,
SAI_HOSTIF_TRAP_TYPE_ROUTER_CUSTOM_RANGE_BASE,
SAI_HOSTIF_TRAP_TYPE_L3_MTU_ERROR,
SAI_HOSTIF_TRAP_TYPE_TTL_ERROR,
SAI_HOSTIF_TRAP_TYPE_UDLD,
SAI_HOSTIF_TRAP_TYPE_BFD,
SAI_HOSTIF_TRAP_TYPE_BFDV6,
SAI_HOSTIF_TRAP_TYPE_SNAT_MISS,
SAI_HOSTIF_TRAP_TYPE_DNAT_MISS,
SAI_HOSTIF_TRAP_TYPE_LDP,
SAI_HOSTIF_TRAP_TYPE_BFD_MICRO,
SAI_HOSTIF_TRAP_TYPE_BFDV6_MICRO
/* This list is intended to remain static and should not be updated with new traps. */
};

std::string get_trap_name_by_type(sai_hostif_trap_type_t trap_type)
{
Expand All @@ -104,7 +161,13 @@ std::string get_trap_name_by_type(sai_hostif_trap_type_t trap_type)
}
}

return trap_name_to_id_map.at(trap_type);
auto it = trap_name_to_id_map.find(trap_type);
if (it == trap_name_to_id_map.end())
{
return "";
}

return it->second;
}

static map<string, sai_packet_action_t> packet_action_map = {
Expand All @@ -122,27 +185,120 @@ const string default_trap_group = "default";
const vector<sai_hostif_trap_type_t> default_trap_ids = {
SAI_HOSTIF_TRAP_TYPE_TTL_ERROR
};

const uint HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS = 10000;

CoppOrch::CoppOrch(DBConnector* db, string tableName) :
Orch(db, tableName),
m_counter_db(std::shared_ptr<DBConnector>(new DBConnector("COUNTERS_DB", 0))),
m_asic_db(std::shared_ptr<DBConnector>(new DBConnector("ASIC_DB", 0))),
m_state_db(std::shared_ptr<DBConnector>(new DBConnector("STATE_DB", 0))),
m_counter_table(std::unique_ptr<Table>(new Table(m_counter_db.get(), COUNTERS_TRAP_NAME_MAP))),
m_vidToRidTable(std::unique_ptr<Table>(new Table(m_asic_db.get(), "VIDTORID"))),
m_trap_counter_manager(HOSTIF_TRAP_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS, false)
m_trap_counter_manager(HOSTIF_TRAP_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS, false),
m_trapCapabilityTable(std::unique_ptr<Table>(new Table(m_state_db.get(), STATE_COPP_TRAP_CAPABILITY_TABLE_NAME))),
m_trapTable(std::unique_ptr<Table>(new Table(m_state_db.get(), STATE_COPP_TRAP_TABLE_NAME)))
{
SWSS_LOG_ENTER();
auto intervT = timespec { .tv_sec = FLEX_COUNTER_UPD_INTERVAL , .tv_nsec = 0 };
m_FlexCounterUpdTimer = new SelectableTimer(intervT);
auto executorT = new ExecutableTimer(m_FlexCounterUpdTimer, this, "FLEX_COUNTER_UPD_TIMER");
Orch::addExecutor(executorT);

/* Query SAI for supported trap IDs and publish to STATE_DB */
publishTrapIdsCapability();

initDefaultHostIntfTable();
initDefaultTrapGroup();
initDefaultTrapIds();

};

bool CoppOrch::isTrapIdSupported(sai_hostif_trap_type_t trap_id) const
{
return supported_trap_ids.find(trap_id) != supported_trap_ids.end();
}

void CoppOrch::updateTrapOperStatus(sai_hostif_trap_type_t trap_type, const string& hw_status)
{
SWSS_LOG_ENTER();

string trap_name = get_trap_name_by_type(trap_type);
if (trap_name.empty())
{
SWSS_LOG_ERROR("Failed to get trap name for type %d", trap_type);
return;
}

// Update or add the hw_status field in the table
vector<FieldValueTuple> hwStatusFvs;
hwStatusFvs.emplace_back("hw_status", hw_status);
m_trapTable->set(trap_name, hwStatusFvs);
}

// Query SAI for trap IDs capability and publish to the COPP_TRAP_CAPABILITY_TABLE
void CoppOrch::publishTrapIdsCapability()
{
SWSS_LOG_ENTER();

sai_s32_list_t enum_values_capability;

supported_trap_ids.clear();

const auto* meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF_TRAP, SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE);
if (!meta || !meta->isenum)
{
SWSS_LOG_WARN("sai_metadata_get_attr_metadata for SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE Failed");
return;
}

vector<int32_t> values_list(meta->enummetadata->valuescount);
enum_values_capability.count = static_cast<uint32_t>(values_list.size());
enum_values_capability.list = values_list.data();

sai_status_t status = sai_query_attribute_enum_values_capability(gSwitchId,
SAI_OBJECT_TYPE_HOSTIF_TRAP,
SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE,
&enum_values_capability);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_NOTICE("SAI capability query for SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE is failed,"
" falling back to default supported trap IDs");
// Populate enum_values_capability with default_supported_trap_ids
enum_values_capability.count = static_cast<uint32_t>(default_supported_trap_ids.size());
values_list.assign(default_supported_trap_ids.begin(), default_supported_trap_ids.end());
enum_values_capability.list = values_list.data();
}

SWSS_LOG_NOTICE("Number of supported trap IDs: %u", enum_values_capability.count);

string trap_id_list_str;

for (uint32_t i = 0; i < enum_values_capability.count; i++)
{

auto trap_str = get_trap_name_by_type(static_cast<sai_hostif_trap_type_t>(enum_values_capability.list[i]));
if (trap_str.empty())
{
SWSS_LOG_NOTICE("Unknown trap id enum value: %d", enum_values_capability.list[i]);
continue;
}

supported_trap_ids.insert(static_cast<sai_hostif_trap_type_t>(enum_values_capability.list[i]));

if (!trap_id_list_str.empty())
{
trap_id_list_str += ",";
}
trap_id_list_str += trap_str;
}

SWSS_LOG_NOTICE("Publishing supported trap IDs to STATE_DB");
vector<FieldValueTuple> trapCapabilityFvs;
trapCapabilityFvs.push_back(FieldValueTuple("trap_ids", trap_id_list_str));
m_trapCapabilityTable->set("traps", trapCapabilityFvs);
}

void CoppOrch::initDefaultHostIntfTable()
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -248,6 +404,14 @@ void CoppOrch::getTrapIdList(vector<string> &trap_id_name_list, vector<sai_hosti
SWSS_LOG_NOTICE("Ignoring the trap_id: %s, as NAT is not supported", trap_id_str.c_str());
continue;
}

if (!isTrapIdSupported(trap_id))
{
/* If the trap_id is not in supported_trap_ids, ignore it */
SWSS_LOG_NOTICE("Ignoring the trap_id: %s, since not supported by vendor SAI", trap_id_str.c_str());
continue;
}

trap_id_list.push_back(trap_id);
}
}
Expand Down Expand Up @@ -358,6 +522,8 @@ bool CoppOrch::applyAttributesToTrapIds(sai_object_id_t trap_group_id,
return parseHandleSaiStatusFailure(handle_status);
}
}

updateTrapOperStatus(trap_id, "installed");
m_syncdTrapIds[trap_id].trap_group_obj = trap_group_id;
m_syncdTrapIds[trap_id].trap_obj = hostif_trap_id;
m_syncdTrapIds[trap_id].trap_type = trap_id;
Expand Down Expand Up @@ -803,6 +969,7 @@ void CoppOrch::getTrapAddandRemoveList(string trap_group_name,
{

vector<sai_hostif_trap_type_t> tmp_trap_ids = trap_ids;

if(m_trap_group_map.find(trap_group_name) == m_trap_group_map.end())
{
add_trap_ids = trap_ids;
Expand Down Expand Up @@ -867,7 +1034,7 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
{
if (m_syncdTrapIds.find(i)!= m_syncdTrapIds.end())
{
if (!removeTrap(m_syncdTrapIds[i].trap_obj))
if (!removeTrap(m_syncdTrapIds[i].trap_obj, i))
{
return false;
}
Expand Down Expand Up @@ -912,7 +1079,7 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
*/
if (m_syncdTrapIds[i].trap_group_obj == m_trap_group_map[trap_group_name])
{
if (!removeTrap(m_syncdTrapIds[i].trap_obj))
if (!removeTrap(m_syncdTrapIds[i].trap_obj, i))
{
return false;
}
Expand Down Expand Up @@ -956,7 +1123,7 @@ bool CoppOrch::processTrapGroupDel (string trap_group_name)
if (it.second.trap_group_obj == m_trap_group_map[trap_group_name])
{
trap_ids_to_reset.push_back(it.first);
if (!removeTrap(it.second.trap_obj))
if (!removeTrap(it.second.trap_obj, it.first))
{
return false;
}
Expand Down Expand Up @@ -1227,7 +1394,7 @@ void CoppOrch::initTrapRatePlugin()
m_trap_rate_plugin_loaded = true;
}

bool CoppOrch::removeTrap(sai_object_id_t hostif_trap_id)
bool CoppOrch::removeTrap(sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type)
{
unbindTrapCounter(hostif_trap_id);

Expand All @@ -1242,6 +1409,8 @@ bool CoppOrch::removeTrap(sai_object_id_t hostif_trap_id)
return parseHandleSaiStatusFailure(handle_status);
}
}

updateTrapOperStatus(trap_type, "not-installed");

return true;
}
Expand Down
17 changes: 16 additions & 1 deletion orchagent/copporch.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#ifndef SWSS_COPPORCH_H
#define SWSS_COPPORCH_H

extern "C" {
#include <saiobject.h>
#include <saistatus.h>
#include <saiswitch.h>
}

#include <map>
#include <set>
#include <memory>
#include <unordered_set>
#include "dbconnector.h"
#include "orch.h"
#include "flex_counter_manager.h"
Expand Down Expand Up @@ -99,8 +106,13 @@ class CoppOrch : public Orch

std::shared_ptr<DBConnector> m_counter_db;
std::shared_ptr<DBConnector> m_asic_db;
std::shared_ptr<DBConnector> m_state_db;
std::unique_ptr<Table> m_counter_table;
std::unique_ptr<Table> m_vidToRidTable;
std::unique_ptr<Table> m_trapCapabilityTable;
std::unique_ptr<Table> m_trapTable;

std::unordered_set<sai_hostif_trap_type_t> supported_trap_ids;

FlexCounterManager m_trap_counter_manager;

Expand All @@ -112,6 +124,9 @@ class CoppOrch : public Orch
void initDefaultTrapGroup();
void initDefaultTrapIds();
void initTrapRatePlugin();
bool isTrapIdSupported(sai_hostif_trap_type_t trap_id) const;
void updateTrapOperStatus(sai_hostif_trap_type_t trap_type, const std::string& hw_status);
void publishTrapIdsCapability();

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

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

bool removeTrap(sai_object_id_t hostif_trap_id);
bool removeTrap(sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type);

bool bindTrapCounter(sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type);
void unbindTrapCounter(sai_object_id_t hostif_trap_id);
Expand Down
2 changes: 1 addition & 1 deletion orchagent/debugcounterorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ void DebugCounterOrch::doTask(Consumer& consumer)

// publishDropCounterCapabilities queries the SAI for available drop counter
// capabilities on this device and publishes the information to the
// DROP_COUNTER_CAPABILITIES table in STATE_DB.
// DEBUG_COUNTER_CAPABILITIES table in STATE_DB.
void DebugCounterOrch::publishDropCounterCapabilities()
{
supported_ingress_drop_reasons = DropCounter::getSupportedDropReasons(SAI_DEBUG_COUNTER_ATTR_IN_DROP_REASON_LIST);
Expand Down
15 changes: 15 additions & 0 deletions tests/mock_tests/copp_cfg.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@
"cbs":"600",
"red_action":"drop"
},
"queue1_group3": {
"trap_action":"trap",
"trap_priority":"1",
"queue": "1",
"meter_type":"packets",
"mode":"sr_tcm",
"cir":"200",
"cbs":"200",
"red_action":"drop"
},
"queue2_group1": {
"cbs": "1000",
"cir": "1000",
Expand Down Expand Up @@ -106,6 +116,11 @@
"sflow": {
"trap_group": "queue2_group1",
"trap_ids": "sample_packet"
},
"neighbor_miss": {
"trap_ids": "neighbor_miss",
"trap_group": "queue1_group3",
"always_enabled": "true"
}
}
}
Loading
Loading