Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[orchagent] Add trap flow counter support #9

Closed
wants to merge 1 commit into from
Closed
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
5 changes: 4 additions & 1 deletion orchagent/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ INCLUDES = -I $(top_srcdir)/lib \
-I $(top_srcdir)/warmrestart \
-I flex_counter \
-I debug_counter \
-I flow_counter \
-I pbh

CFLAGS_SAI = -I /usr/include/sai
Expand All @@ -21,7 +22,8 @@ dist_swss_DATA = \
watermark_queue.lua \
watermark_pg.lua \
watermark_bufferpool.lua \
lagids.lua
lagids.lua \
trap_rates.lua

bin_PROGRAMS = orchagent routeresync orchagent_restart_check

Expand Down Expand Up @@ -81,6 +83,7 @@ orchagent_SOURCES = \

orchagent_SOURCES += flex_counter/flex_counter_manager.cpp flex_counter/flex_counter_stat_manager.cpp
orchagent_SOURCES += debug_counter/debug_counter.cpp debug_counter/drop_counter.cpp
orchagent_SOURCES += flow_counter/flow_counter_handler.cpp

orchagent_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
orchagent_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
Expand Down
210 changes: 180 additions & 30 deletions orchagent/copporch.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
#include "sai.h"
#include "copporch.h"
#include "portsorch.h"
#include "flexcounterorch.h"
#include "tokenize.h"
#include "logger.h"
#include "sai_serialize.h"
#include "schema.h"
#include "directory.h"
#include "flow_counter_handler.h"

#include <inttypes.h>
#include <sstream>
Expand All @@ -18,6 +23,7 @@ extern sai_switch_api_t* sai_switch_api;

extern sai_object_id_t gSwitchId;
extern PortsOrch* gPortsOrch;
extern Directory<Orch*> gDirectory;
extern bool gIsNatSupported;

static map<string, sai_meter_type_t> policer_meter_map = {
Expand Down Expand Up @@ -78,6 +84,21 @@ static map<string, sai_hostif_trap_type_t> trap_id_map = {
{"dest_nat_miss", SAI_HOSTIF_TRAP_TYPE_DNAT_MISS}
};


std::string get_trap_name_by_type(sai_hostif_trap_type_t trap_type)
{
static map<sai_hostif_trap_type_t, string> trap_name_to_id_map;
if (trap_name_to_id_map.empty())
{
for (const auto &kv : trap_id_map)
{
trap_name_to_id_map.emplace(kv.second, kv.first);
}
}

return trap_name_to_id_map.at(trap_type);
}

static map<string, sai_packet_action_t> packet_action_map = {
{"drop", SAI_PACKET_ACTION_DROP},
{"forward", SAI_PACKET_ACTION_FORWARD},
Expand All @@ -93,12 +114,17 @@ 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 = 1000;

CoppOrch::CoppOrch(DBConnector* db, string tableName) :
Orch(db, tableName)
Orch(db, tableName),
m_counter_db(std::shared_ptr<DBConnector>(new DBConnector("COUNTERS_DB", 0))),
m_flex_db(std::shared_ptr<DBConnector>(new DBConnector("FLEX_COUNTER_DB", 0))),
m_counter_table(std::unique_ptr<Table>(new Table(m_counter_db.get(), COUNTERS_TRAP_NAME_MAP))),
m_flex_counter_group_table(std::unique_ptr<ProducerTable>(new ProducerTable(m_flex_db.get(), FLEX_COUNTER_GROUP_TABLE))),
m_trap_counter_manager(HOSTIF_TRAP_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ, HOSTIF_TRAP_COUNTER_POLLING_INTERVAL_MS, false)
{
SWSS_LOG_ENTER();

initDefaultHostIntfTable();
initDefaultTrapGroup();
initDefaultTrapIds();
Expand Down Expand Up @@ -317,6 +343,8 @@ bool CoppOrch::applyAttributesToTrapIds(sai_object_id_t trap_group_id,
}
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;
bindTrapCounter(hostif_trap_id, trap_id);
}
return true;
}
Expand Down Expand Up @@ -773,17 +801,9 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
{
if (m_syncdTrapIds.find(i)!= m_syncdTrapIds.end())
{
sai_status_t sai_status = sai_hostif_api->remove_hostif_trap(
m_syncdTrapIds[i].trap_obj);
if (sai_status != SAI_STATUS_SUCCESS)
if (!removeTrap(m_syncdTrapIds[i].trap_obj))
{
SWSS_LOG_ERROR("Failed to remove trap object %" PRId64 "",
m_syncdTrapIds[i].trap_obj);
task_process_status handle_status = handleSaiRemoveStatus(SAI_API_HOSTIF, sai_status);
if (handle_status != task_success)
{
return parseHandleSaiStatusFailure(handle_status);
}
return false;
}
}
}
Expand Down Expand Up @@ -826,17 +846,9 @@ bool CoppOrch::trapGroupProcessTrapIdChange (string trap_group_name,
*/
if (m_syncdTrapIds[i].trap_group_obj == m_trap_group_map[trap_group_name])
{
sai_status_t sai_status = sai_hostif_api->remove_hostif_trap(
m_syncdTrapIds[i].trap_obj);
if (sai_status != SAI_STATUS_SUCCESS)
if (!removeTrap(m_syncdTrapIds[i].trap_obj))
{
SWSS_LOG_ERROR("Failed to remove trap object %" PRId64 "",
m_syncdTrapIds[i].trap_obj);
task_process_status handle_status = handleSaiRemoveStatus(SAI_API_HOSTIF, sai_status);
if (handle_status != task_success)
{
return parseHandleSaiStatusFailure(handle_status);
}
return false;
}
m_syncdTrapIds.erase(i);
}
Expand Down Expand Up @@ -878,15 +890,9 @@ 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);
sai_status_t sai_status = sai_hostif_api->remove_hostif_trap(it.second.trap_obj);
if (sai_status != SAI_STATUS_SUCCESS)
if (!removeTrap(it.second.trap_obj))
{
SWSS_LOG_ERROR("Failed to remove trap object %" PRId64 "", it.second.trap_obj);
task_process_status handle_status = handleSaiRemoveStatus(SAI_API_HOSTIF, sai_status);
if (handle_status != task_success)
{
return parseHandleSaiStatusFailure(handle_status);
}
return false;
}
}
}
Expand Down Expand Up @@ -1093,3 +1099,147 @@ bool CoppOrch::trapGroupUpdatePolicer (string trap_group_name,
return true;
}

void CoppOrch::initTrapRatePlugin()
{
if (m_trap_rate_plugin_loaded)
{
return;
}

std::string trapRatePluginName = "trap_rates.lua";
try
{
std::string trapLuaScript = swss::loadLuaScript(trapRatePluginName);
std::string trapSha = swss::loadRedisScript(m_counter_db.get(), trapLuaScript);

vector<FieldValueTuple> fieldValues;
fieldValues.emplace_back(FLOW_COUNTER_PLUGIN_FIELD, trapSha);
fieldValues.emplace_back(STATS_MODE_FIELD, STATS_MODE_READ);
m_flex_counter_group_table->set(HOSTIF_TRAP_COUNTER_FLEX_COUNTER_GROUP, fieldValues);
}
catch (const runtime_error &e)
{
SWSS_LOG_ERROR("Trap flex counter groups were not set successfully: %s", e.what());
}
m_trap_rate_plugin_loaded = true;
}

bool CoppOrch::removeTrap(sai_object_id_t hostif_trap_id)
{
unbindTrapCounter(hostif_trap_id);

sai_status_t sai_status = sai_hostif_api->remove_hostif_trap(hostif_trap_id);
if (sai_status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to remove trap object %" PRId64 "",
hostif_trap_id);
task_process_status handle_status = handleSaiRemoveStatus(SAI_API_HOSTIF, sai_status);
if (handle_status != task_success)
{
return parseHandleSaiStatusFailure(handle_status);
}
}

return true;
}

bool CoppOrch::bindTrapCounter(sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type)
{
auto flex_counters_orch = gDirectory.get<FlexCounterOrch*>();

if (!flex_counters_orch || !flex_counters_orch->getHostIfTrapCounterState())
{
return false;
}

if (m_trap_id_name_map.count(hostif_trap_id) > 0)
{
return true;
}

initTrapRatePlugin();

// Create generic counter
sai_object_id_t counter_id;
if (!FlowCounterHandler::createGenericCounter(counter_id))
{
return false;
}

// Bind generic counter to trap
sai_attribute_t trap_attr;
trap_attr.id = SAI_HOSTIF_TRAP_ATTR_COUNTER_ID;
trap_attr.value.oid = counter_id;
sai_status_t sai_status = sai_hostif_api->set_hostif_trap_attribute(hostif_trap_id, &trap_attr);
if (sai_status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_WARN("Failed to bind trap %" PRId64 " to counter %" PRId64 "", hostif_trap_id, counter_id);
return false;
}

// Update COUNTERS_TRAP_NAME_MAP
auto trap_name = get_trap_name_by_type(trap_type);
FieldValueTuple tuple(trap_name, sai_serialize_object_id(counter_id));
vector<FieldValueTuple> fields;
fields.push_back(tuple);
m_counter_table->set("", fields);

// Update FLEX_COUNTER table
std::unordered_set<std::string> counter_stats;
FlowCounterHandler::getGenericCounterIdList(counter_stats);
m_trap_counter_manager.setCounterIdList(counter_id, CounterType::HOSTIF_TRAP, counter_stats);
m_trap_id_name_map.emplace(hostif_trap_id, trap_name);
return true;
}

void CoppOrch::unbindTrapCounter(sai_object_id_t hostif_trap_id)
{
auto iter = m_trap_id_name_map.find(hostif_trap_id);
if (iter == m_trap_id_name_map.end())
{
return;
}

std::string counter_oid_str;
m_counter_table->hget("", iter->second, counter_oid_str);

// Clear FLEX_COUNTER table
sai_object_id_t counter_id;
sai_deserialize_object_id(counter_oid_str, counter_id);
m_trap_counter_manager.clearCounterIdList(counter_id);

// Remmove trap from COUNTERS_TRAP_NAME_MAP
m_counter_table->hdel("", iter->second);

// Unbind generic counter to trap
sai_attribute_t trap_attr;
trap_attr.id = SAI_HOSTIF_TRAP_ATTR_COUNTER_ID;
trap_attr.value.oid = SAI_NULL_OBJECT_ID;
sai_status_t sai_status = sai_hostif_api->set_hostif_trap_attribute(hostif_trap_id, &trap_attr);
if (sai_status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to unbind trap %" PRId64 " to counter %" PRId64 "", hostif_trap_id, counter_id);
}

// Remove generic counter
FlowCounterHandler::removeGenericCounter(counter_id);

m_trap_id_name_map.erase(iter);
}

void CoppOrch::generateHostIfTrapCounterIdList()
{
for (const auto &kv : m_syncdTrapIds)
{
bindTrapCounter(kv.second.trap_obj, kv.second.trap_type);
}
}

void CoppOrch::clearHostIfTrapCounterIdList()
{
for (const auto &kv : m_syncdTrapIds)
{
unbindTrapCounter(kv.second.trap_obj);
}
}

30 changes: 30 additions & 0 deletions orchagent/copporch.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@

#include <map>
#include <set>
#include <memory>
#include "dbconnector.h"
#include "orch.h"
#include "flex_counter_manager.h"
#include "producertable.h"
#include "table.h"

using namespace swss;

#define HOSTIF_TRAP_COUNTER_FLEX_COUNTER_GROUP "HOSTIF_TRAP_FLOW_COUNTER"

// trap fields
const std::string copp_trap_id_list = "trap_ids";
Expand Down Expand Up @@ -33,6 +42,7 @@ struct copp_trap_objects
{
sai_object_id_t trap_obj;
sai_object_id_t trap_group_obj;
sai_hostif_trap_type_t trap_type;
};

/* TrapGroupPolicerTable: trap group ID, policer ID */
Expand All @@ -45,11 +55,15 @@ typedef std::map<sai_object_id_t, sai_object_id_t> TrapGroupHostIfMap;
typedef std::map<sai_hostif_trap_type_t, sai_object_id_t> TrapIdHostIfTableMap;
/* Trap group to trap ID attributes */
typedef std::map<std::string, TrapIdAttribs> TrapGroupTrapIdAttribs;
/* Trap OID to trap name*/
typedef std::map<sai_object_id_t, std::string> TrapIdNameMap;

class CoppOrch : public Orch
{
public:
CoppOrch(swss::DBConnector* db, std::string tableName);
void generateHostIfTrapCounterIdList();
void clearHostIfTrapCounterIdList();
protected:
object_map m_trap_group_map;

Expand All @@ -59,10 +73,21 @@ class CoppOrch : public Orch
TrapGroupHostIfMap m_trap_group_hostif_map;
TrapIdHostIfTableMap m_trapid_hostif_table_map;
TrapGroupTrapIdAttribs m_trap_group_trap_id_attrs;
TrapIdNameMap m_trap_id_name_map;

std::shared_ptr<DBConnector> m_counter_db;
std::shared_ptr<DBConnector> m_flex_db;
std::unique_ptr<Table> m_counter_table;
std::unique_ptr<ProducerTable> m_flex_counter_group_table;

FlexCounterManager m_trap_counter_manager;

bool m_trap_rate_plugin_loaded = false;

void initDefaultHostIntfTable();
void initDefaultTrapGroup();
void initDefaultTrapIds();
void initTrapRatePlugin();

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 @@ -99,6 +124,11 @@ 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 bindTrapCounter(sai_object_id_t hostif_trap_id, sai_hostif_trap_type_t trap_type);
void unbindTrapCounter(sai_object_id_t hostif_trap_id);

virtual void doTask(Consumer& consumer);
};
#endif /* SWSS_COPPORCH_H */
Expand Down
1 change: 1 addition & 0 deletions orchagent/flex_counter/flex_counter_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const unordered_map<CounterType, string> FlexCounterManager::counter_id_field_lo
{ CounterType::PORT, PORT_COUNTER_ID_LIST },
{ CounterType::QUEUE, QUEUE_COUNTER_ID_LIST },
{ CounterType::MACSEC_SA_ATTR, MACSEC_SA_ATTR_ID_LIST },
{ CounterType::HOSTIF_TRAP, FLOW_COUNTER_ID_LIST },
};

FlexCounterManager::FlexCounterManager(
Expand Down
1 change: 1 addition & 0 deletions orchagent/flex_counter/flex_counter_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum class CounterType
PORT_DEBUG,
SWITCH_DEBUG,
MACSEC_SA_ATTR,
HOSTIF_TRAP,
};

// FlexCounterManager allows users to manage a group of flex counters.
Expand Down
Loading