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

[FC] Support Policer counter #3415

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
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 @@ -50,6 +50,7 @@ const unordered_map<CounterType, string> FlexCounterManager::counter_id_field_lo
{ CounterType::HOSTIF_TRAP, FLOW_COUNTER_ID_LIST },
{ CounterType::ROUTE, FLOW_COUNTER_ID_LIST },
{ CounterType::ENI, ENI_COUNTER_ID_LIST },
{ CounterType::POLICER, POLICER_COUNTER_ID_LIST },
};

FlexManagerDirectory g_FlexManagerDirectory;
Expand Down
3 changes: 2 additions & 1 deletion orchagent/flex_counter/flex_counter_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ enum class CounterType
TUNNEL,
HOSTIF_TRAP,
ROUTE,
ENI
ENI,
POLICER,
};

// FlexCounterManager allows users to manage a group of flex counters.
Expand Down
7 changes: 7 additions & 0 deletions orchagent/flexcounterorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extern IntfsOrch *gIntfsOrch;
extern BufferOrch *gBufferOrch;
extern Directory<Orch*> gDirectory;
extern CoppOrch *gCoppOrch;
extern PolicerOrch *gPolicerOrch;
extern FlowCounterRouteOrch *gFlowCounterRouteOrch;
extern sai_object_id_t gSwitchId;

Expand All @@ -41,6 +42,7 @@ extern sai_object_id_t gSwitchId;
#define FLOW_CNT_TRAP_KEY "FLOW_CNT_TRAP"
#define FLOW_CNT_ROUTE_KEY "FLOW_CNT_ROUTE"
#define ENI_KEY "ENI"
#define POLICER_KEY "POLICER"

unordered_map<string, string> flexCounterGroupMap =
{
Expand All @@ -63,6 +65,7 @@ unordered_map<string, string> flexCounterGroupMap =
{"MACSEC_SA", COUNTERS_MACSEC_SA_GROUP},
{"MACSEC_SA_ATTR", COUNTERS_MACSEC_SA_ATTR_GROUP},
{"MACSEC_FLOW", COUNTERS_MACSEC_FLOW_GROUP},
{POLICER_KEY, POLICER_STAT_COUNTER_FLEX_COUNTER_GROUP},
{"ENI", ENI_STAT_COUNTER_FLEX_COUNTER_GROUP}
};

Expand Down Expand Up @@ -208,6 +211,10 @@ void FlexCounterOrch::doTask(Consumer &consumer)
{
dash_orch->handleFCStatusUpdate((value == "enable"));
}
if (gPolicerOrch && (key== POLICER_KEY) && (value == "enable"))
{
gPolicerOrch->generatePolicerCounterMap();
}
if (gCoppOrch && (key == FLOW_CNT_TRAP_KEY))
{
if (value == "enable")
Expand Down
123 changes: 121 additions & 2 deletions orchagent/policerorch.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "sai.h"
#include "policerorch.h"

#include "sai_serialize.h"
#include "flow_counter_handler.h"
#include "aclorch.h"
#include "converter.h"
#include <inttypes.h>

Expand Down Expand Up @@ -31,6 +33,8 @@ static const string storm_broadcast = "broadcast";
static const string storm_unknown_unicast = "unknown-unicast";
static const string storm_unknown_mcast = "unknown-multicast";

extern bool gTraditionalFlexCounter;

static const map<string, sai_meter_type_t> meter_type_map = {
{"PACKETS", SAI_METER_TYPE_PACKETS},
{"BYTES", SAI_METER_TYPE_BYTES}
Expand Down Expand Up @@ -58,6 +62,19 @@ static const map<string, sai_packet_action_t> packet_action_map = {
{"TRANSIT", SAI_PACKET_ACTION_TRANSIT}
};

const vector<sai_policer_stat_t> policer_stat_ids = {

SAI_POLICER_STAT_PACKETS,
SAI_POLICER_STAT_ATTR_BYTES,
SAI_POLICER_STAT_GREEN_PACKETS,
SAI_POLICER_STAT_GREEN_BYTES,
SAI_POLICER_STAT_YELLOW_PACKETS,
SAI_POLICER_STAT_YELLOW_BYTES,
SAI_POLICER_STAT_RED_PACKETS,
SAI_POLICER_STAT_RED_BYTES

};

bool PolicerOrch::policerExists(const string &name)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -113,11 +130,24 @@ bool PolicerOrch::decreaseRefCount(const string &name)
return true;
}

PolicerOrch::PolicerOrch(vector<TableConnector> &tableNames, PortsOrch *portOrch) : Orch(tableNames), m_portsOrch(portOrch)

PolicerOrch::PolicerOrch( vector<TableConnector> &tableNames, PortsOrch *portOrch) :
Orch(tableNames),
m_portsOrch(portOrch),
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_counter_table(std::unique_ptr<Table>(new Table(m_counter_db.get(), COUNTERS_POLICER_NAME_MAP))),
m_vidToRidTable(std::unique_ptr<Table>(new Table(m_asic_db.get(), "VIDTORID"))),
m_policer_counter_manager(POLICER_STAT_COUNTER_FLEX_COUNTER_GROUP, StatsMode::READ,10000,false)
{
SWSS_LOG_ENTER();
auto intervT = timespec { .tv_sec = 1 , .tv_nsec = 0 };
m_FlexCounterUpdTimer = new SelectableTimer(intervT);
auto executorT = new ExecutableTimer(m_FlexCounterUpdTimer, this, "FLEX_COUNTER_UPD_TIMER");
Orch::addExecutor(executorT);
}


task_process_status PolicerOrch::handlePortStormControlTable(swss::KeyOpFieldsValuesTuple tuple)
{
auto key = kfvKey(tuple);
Expand Down Expand Up @@ -238,6 +268,7 @@ task_process_status PolicerOrch::handlePortStormControlTable(swss::KeyOpFieldsVa
SWSS_LOG_DEBUG("Created storm-control policer %s", storm_policer_name.c_str());
m_syncdPolicers[storm_policer_name] = policer_id;
m_policerRefCounts[storm_policer_name] = 0;

}
// Update an existing policer
else
Expand Down Expand Up @@ -371,6 +402,90 @@ task_process_status PolicerOrch::handlePortStormControlTable(swss::KeyOpFieldsVa
return task_process_status::task_success;
}

string PolicerOrch::getPolicerFlexCounterTableKey(string key)
{
return string(POLICER_STAT_COUNTER_FLEX_COUNTER_GROUP) + ":" + key;
}

void PolicerOrch::removePCFromFlexCounter(sai_object_id_t id, const string &name)
{
SWSS_LOG_ENTER();

std::string counter_oid_str;
counter_oid_str = sai_serialize_object_id(id);

auto update_iter = m_pendingPcAddToFlexCntr.find(id);
if (update_iter == m_pendingPcAddToFlexCntr.end())
{
m_policer_counter_manager.clearCounterIdList(id);
}
else
{
m_pendingPcAddToFlexCntr.erase(update_iter);
}

/* remove it from COUNTERS_DB maps */
m_counter_table->hdel("", name);
m_vidToRidTable->hdel("", counter_oid_str);

SWSS_LOG_DEBUG("Unregistered interface %s from Flex counter", name.c_str());
}

void PolicerOrch::doTask(SelectableTimer &timer)
{
string value;
for (auto it = m_pendingPcAddToFlexCntr.begin(); it != m_pendingPcAddToFlexCntr.end(); )
{
const auto id = sai_serialize_object_id(it->first);
if (!gTraditionalFlexCounter || m_vidToRidTable->hget("", id, value))
{
vector<FieldValueTuple> policerNameVector;

policerNameVector.emplace_back(it->second.c_str(), id);
m_counter_table->set("", policerNameVector);
m_counter_db->hset(COUNTERS_POLICER_NAME_MAP, it->second.c_str(), id.c_str());

auto pcounter_stats = generatePCounterStats();
m_policer_counter_manager.setCounterIdList(it->first, CounterType::POLICER, pcounter_stats, gSwitchId);
SWSS_LOG_DEBUG("inserted %s to flex counter", it->second.c_str());
it = m_pendingPcAddToFlexCntr.erase(it);
}
else
{
++it;
}
}
}


std::unordered_set<std::string> PolicerOrch::generatePCounterStats()
{
std::unordered_set<std::string> counter_stats;
for (const auto& it: policer_stat_ids)
{
counter_stats.emplace(sai_serialize_policer_stat(it));
}
return counter_stats;
}

void PolicerOrch::generatePolicerCounterMap()
{
if (m_isPolicerCounterMapGenerated)
{
return;
}

m_FlexCounterUpdTimer->start();

m_isPolicerCounterMapGenerated = true;
}

void PolicerOrch::addPolicerToFlexCounter(sai_object_id_t oid, const string &name)
{
m_pendingPcAddToFlexCntr[oid] = name;
}


void PolicerOrch::doTask(Consumer &consumer)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -511,6 +626,8 @@ void PolicerOrch::doTask(Consumer &consumer)
SWSS_LOG_NOTICE("Created policer %s", key.c_str());
m_syncdPolicers[key] = policer_id;
m_policerRefCounts[key] = 0;

addPolicerToFlexCounter(policer_id, key.c_str());
}
// Update an existing policer
else
Expand Down Expand Up @@ -567,6 +684,8 @@ void PolicerOrch::doTask(Consumer &consumer)
continue;
}

removePCFromFlexCounter(m_syncdPolicers[key], key);

sai_status_t status = sai_policer_api->remove_policer(
m_syncdPolicers.at(key));
if (status != SAI_STATUS_SUCCESS)
Expand Down
28 changes: 28 additions & 0 deletions orchagent/policerorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
#include <map>
#include <string>

#include "flex_counter_manager.h"
#include "dbconnector.h"
#include "orch.h"
#include "portsorch.h"


using namespace std;

#define POLICER_STAT_COUNTER_FLEX_COUNTER_GROUP "POLICER_STAT_COUNTER"

typedef map<string, sai_object_id_t> PolicerTable;
typedef map<string, int> PolicerRefCountTable;

Expand All @@ -22,12 +27,35 @@ class PolicerOrch : public Orch
bool increaseRefCount(const string &name);
bool decreaseRefCount(const string &name);
task_process_status handlePortStormControlTable(swss::KeyOpFieldsValuesTuple tuple);
void addPolicerToFlexCounter(sai_object_id_t oid, const string &name);
void generatePolicerCounterMap();

private:
PortsOrch *m_portsOrch;
virtual void doTask(Consumer& consumer);
void doTask(swss::SelectableTimer&) override;

PolicerTable m_syncdPolicers;
PolicerRefCountTable m_policerRefCounts;
FlexCounterManager m_policer_counter_manager;
bool m_isPolicerCounterMapGenerated = false;

void getPolicerCounter(void);
void initPolicerCounterPlugin(void);
void removePCFromFlexCounter(sai_object_id_t id, const string &name);
string getPolicerFlexCounterTableKey(string key);
std::unordered_set<std::string> generatePCounterStats();

protected:
std::shared_ptr<DBConnector> m_counter_db;
std::shared_ptr<DBConnector> m_flex_db;
std::shared_ptr<DBConnector> m_asic_db;
std::unique_ptr<Table> m_counter_table;
std::unique_ptr<Table> m_vidToRidTable;
std::unique_ptr<ProducerTable> m_flex_counter_group_table;
std::map<sai_object_id_t, std::string> m_pendingPcAddToFlexCntr;

SelectableTimer* m_FlexCounterUpdTimer = nullptr;
};


33 changes: 33 additions & 0 deletions tests/mock_tests/flexcounter_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,12 @@ namespace flexcounter_test

ASSERT_EQ(gIntfsOrch, nullptr);
gIntfsOrch = new IntfsOrch(m_app_db.get(), APP_INTF_TABLE_NAME, gVrfOrch, m_chassis_app_db.get());

vector<TableConnector> policer_tables = {
TableConnector(m_config_db.get(), CFG_POLICER_TABLE_NAME),
TableConnector(m_config_db.get(), CFG_PORT_STORM_CONTROL_TABLE_NAME)
};
gPolicerOrch = new PolicerOrch(policer_tables, gPortsOrch);
}

virtual void TearDown() override
Expand All @@ -357,6 +363,8 @@ namespace flexcounter_test
gQosOrch = nullptr;
delete gSwitchOrch;
gSwitchOrch = nullptr;
delete gPolicerOrch;
gPolicerOrch = nullptr;

// clear orchs saved in directory
gDirectory.m_values.clear();
Expand Down Expand Up @@ -450,6 +458,14 @@ namespace flexcounter_test
{RIF_PLUGIN_FIELD, ""},
}));

ASSERT_TRUE(checkFlexCounterGroup(POLICER_STAT_COUNTER_FLEX_COUNTER_GROUP,
{
{POLL_INTERVAL_FIELD, "10000"},
{STATS_MODE_FIELD, STATS_MODE_READ},
{FLEX_COUNTER_STATUS_FIELD, "disable"}
}
));

Table portTable = Table(m_app_db.get(), APP_PORT_TABLE_NAME);
Table sendToIngressPortTable = Table(m_app_db.get(), APP_SEND_TO_INGRESS_PORT_TABLE_NAME);
Table pgTable = Table(m_app_db.get(), APP_BUFFER_PG_TABLE_NAME);
Expand Down Expand Up @@ -548,6 +564,7 @@ namespace flexcounter_test
flexCounterCfg.set("PORT", values);
flexCounterCfg.set("BUFFER_POOL_WATERMARK", values);
flexCounterCfg.set("PFCWD", values);
flexCounterCfg.set("POLICER", values);

auto flexCounterOrch = gDirectory.get<FlexCounterOrch*>();
flexCounterOrch->addExistingData(&flexCounterCfg);
Expand Down Expand Up @@ -600,6 +617,14 @@ namespace flexcounter_test
{FLEX_COUNTER_STATUS_FIELD, "enable"},
}));

ASSERT_TRUE(checkFlexCounterGroup(POLICER_STAT_COUNTER_FLEX_COUNTER_GROUP,
{
{POLL_INTERVAL_FIELD, "10000"},
{STATS_MODE_FIELD, STATS_MODE_READ},
{FLEX_COUNTER_STATUS_FIELD, "enable"}
}
));

sai_object_id_t pool_oid;
pool_oid = (*BufferOrch::m_buffer_type_maps[APP_BUFFER_POOL_TABLE_NAME])["ingress_lossless_pool"].m_saiObjectId;
ASSERT_TRUE(checkFlexCounter(BUFFER_POOL_WATERMARK_STAT_COUNTER_FLEX_COUNTER_GROUP, pool_oid, BUFFER_POOL_COUNTER_ID_LIST));
Expand Down Expand Up @@ -833,6 +858,14 @@ namespace flexcounter_test
entries.clear();
static_cast<Orch *>(gBufferOrch)->doTask();
ASSERT_TRUE(checkFlexCounter(BUFFER_POOL_WATERMARK_STAT_COUNTER_FLEX_COUNTER_GROUP, pool_oid));

string policer_name = "policer_1";
auto consumer_policer = dynamic_cast<Consumer *>(gPolicerOrch->getExecutor(CFG_POLICER_TABLE_NAME));
consumer_policer->addToSync({{policer_name, "SET", {{"meter_type", "packets"}, {"mode", "sr_tcm"}, {"cir", "600"}, {"cbs", "600"}}}});
static_cast<Orch *>(gPolicerOrch)->doTask();
sai_object_id_t policer_oid;
gPolicerOrch->getPolicerOid(policer_name, policer_oid);
ASSERT_TRUE(checkFlexCounter(POLICER_STAT_COUNTER_FLEX_COUNTER_GROUP, policer_oid));
}

INSTANTIATE_TEST_CASE_P(
Expand Down
Loading
Loading