Skip to content
Open
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
1 change: 1 addition & 0 deletions orchagent/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ orchagent_SOURCES = \
watermarkorch.cpp \
notificationconsumerstatsorch.cpp \
policerorch.cpp \
namelabelmapper.cpp \
sfloworch.cpp \
chassisorch.cpp \
debugcounterorch.cpp \
Expand Down
222 changes: 222 additions & 0 deletions orchagent/namelabelmapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
#include "namelabelmapper.h"

#include <limits>
#include <sstream>
#include <string>

#include <nlohmann/json.hpp>
#include "logger.h"
#include "sai_serialize.h"

extern "C"
{
#include "sai.h"
}

using ::nlohmann::json;

namespace
{

std::string convertToDBField(_In_ const sai_object_type_t object_type, _In_ const std::string &key)
{
return sai_serialize_object_type(object_type) + "|" + key;
}

} // namespace

NameLabelMapper::NameLabelMapper() : m_db("STATE_DB", 0), m_table(&m_db, "SAI_KEY_LABEL_MAP")
{
}

bool NameLabelMapper::setLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key, _In_ std::string &label)
{
SWSS_LOG_ENTER();

if (existsLabel(object_type, key))
{
SWSS_LOG_ERROR("Key %s with SAI object type %d already exists in label mapper", key.c_str(), object_type);
return false;
}

m_labelTables[object_type][key] = label;
SWSS_LOG_INFO("Created new label %s for Key %s with SAI object type %d", label.c_str(), key.c_str(), object_type);
return true;
}

bool NameLabelMapper::getLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key,
_Out_ std::string &label)
{
SWSS_LOG_ENTER();

if (!existsLabel(object_type, key))
{
SWSS_LOG_INFO("Key %s with SAI object type %d does not exist in label mapper", key.c_str(), object_type);
return false;
}

label = m_labelTables[object_type][key];
return true;
}

bool NameLabelMapper::eraseLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key)
{
SWSS_LOG_ENTER();

if (!existsLabel(object_type, key))
{
SWSS_LOG_ERROR("Key %s with SAI object type %d does not exist in "
"label mapper when erasing",
key.c_str(), object_type);
return false;
}

m_labelTables[object_type].erase(key);
return true;
}

void NameLabelMapper::deleteMapperInDb()
{
SWSS_LOG_ENTER();
m_table.del("");
}

size_t NameLabelMapper::getNumEntries(_In_ sai_object_type_t object_type) const
{
SWSS_LOG_ENTER();

return (m_labelTables[object_type].size());
}

bool NameLabelMapper::existsLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key) const
{
SWSS_LOG_ENTER();

return m_labelTables[object_type].find(key) != m_labelTables[object_type].end();
}

std::string NameLabelMapper::generateKeyFromTableAndObjectName(std::string table_name, std::string object_name)
{
return table_name + ":" + object_name;
}

std::string NameLabelMapper::generateUniqueLabel()
{
char label_buf[UNIQUE_LABEL_SIZE];
uint64_t msec =
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch())
.count();
snprintf(label_buf, UNIQUE_LABEL_SIZE, "%" PRIu64 "", msec);
return std::string(reinterpret_cast<char const *>(label_buf));
}

bool NameLabelMapper::allocateLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key,
_Out_ std::string &label)
{
if (!getLabel(object_type, key, label))
{
label = generateUniqueLabel();
return false;
}
return true;
}

bool NameLabelMapper::addLabelToAttr(sai_object_type_t object_type, const std::string &table_name,
const std::string &key, sai_attribute_t &attr, sai_attr_id_t attr_id,
std::string &mapper_key, std::string &label)
{
mapper_key = generateKeyFromTableAndObjectName(table_name, key);
bool label_present = allocateLabel(object_type, mapper_key, label);
attr.id = attr_id;
auto size = sizeof(attr.value.chardata);
snprintf(attr.value.chardata, size, "%s", label.c_str());
SWSS_LOG_NOTICE("Add ATTR_LABEL %s for sai object %s for %s", label.c_str(),
sai_serialize_object_type(object_type).c_str(), mapper_key.c_str());
return label_present;
}

std::string NameLabelMapper::dumpStateCache()
{
json cache = json({});
for (int i = 0; i < SAI_OBJECT_TYPE_MAX; i++)
{
if (m_labelTables[i].empty())
{
continue;
}

json label_mapper_j = json({});
for (const auto &kv_pair : m_labelTables[i])
{
label_mapper_j[kv_pair.first] = kv_pair.second;
}
std::string sai_object_type = sai_serialize_object_type(static_cast<sai_object_type_t>(i));
cache[sai_object_type] = label_mapper_j;
}
return cache.dump(4);
}

void NameLabelMapper::saveMapperToDb()
{
for (int i = 0; i < SAI_OBJECT_TYPE_MAX; i++)
{
if (m_labelTables[i].empty())
{
continue;
}
for (const auto &kv_pair : m_labelTables[i])
{
auto key = kv_pair.first;
auto label = kv_pair.second;
m_table.hset("", convertToDBField(static_cast<sai_object_type_t>(i), key), label);
SWSS_LOG_INFO("label %s for Key %s with SAI object type %d save into state_db", label.c_str(), key.c_str(),
i);
}
}
}

void NameLabelMapper::readMapperFromDb()
{
std::vector<swss::FieldValueTuple> tuples;
m_table.get("", tuples);
SWSS_LOG_INFO("m_table->get size %zd", tuples.size());
for (auto &fv : tuples)
{
std::string combo = fvField(fv);
std::string label = fvValue(fv);
SWSS_LOG_INFO("Got field %s label %s from db", combo.c_str(), label.c_str());

size_t pos = 0;
std::string obj_type_str, key;
if ((pos = combo.find("|")) != std::string::npos)
{
obj_type_str = combo.substr(0, pos);
key = combo.substr(pos + 1, combo.size() - pos - 1);

sai_object_type_t sai_object_type;
sai_deserialize_object_type(obj_type_str, sai_object_type);
setLabel(sai_object_type, key, label);
}
}
}

std::string NameLabelMapper::verifyLabelMapping(
_In_ sai_object_type_t object_type, _In_ const std::string& key,
_In_ std::string label) {
SWSS_LOG_ENTER();

std::string mapper_label;
if (!getLabel(object_type, key, mapper_label)) {
std::stringstream msg;
msg << "Label not found in mapper for key " << key;
return msg.str();
}
if (mapper_label != label) {
std::stringstream msg;
msg << "Label mismatched in mapper for key " << key << ": " << label
<< " vs " << mapper_label;
return msg.str();
}

return "";
}
92 changes: 92 additions & 0 deletions orchagent/namelabelmapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#pragma once

#include <inttypes.h>

#include <chrono>
#include <cstdint>
#include <ctime>
#include <string>
#include <unordered_map>

#include "dbconnector.h"
#include "table.h"

extern "C"
{
#include "sai.h"
}

#define UNIQUE_LABEL_SIZE 32

// Interface for mapping object name/key to unique Label.
// This class is not thread safe.
class NameLabelMapper
{
public:
NameLabelMapper();
~NameLabelMapper() = default;

// Sets label for the given key for the specific object_type. Returns false if
// the key already exists.
bool setLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key, _In_ std::string &label);

// Return true if label present in the mapper, and copy the label in the 3rd
// argument; or false, and a new unique label is allocated and saved in mapper
bool allocateLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key, _Out_ std::string &label);

// Gets label from mapper for the given key for the SAI object_type.
// Returns true on success.
bool getLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key, _Out_ std::string &label);

// Erases label for the given key for the SAI object_type.
// Returns true on success.
bool eraseLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key);

// Delete mapper table in db
void deleteMapperInDb();

// Gets the number of labels for the SAI object_type.
size_t getNumEntries(_In_ sai_object_type_t object_type) const;

// SAI object subtype and name to label mapper name
// Returns concat of (subtype + object_name)
// For example, for POLICER, there are 4 subtypes:
// COPP trap group, ACL policer, storm policer, regular policer
// One way is use APPL_DB table name in subtype field, that is
// subtype = APPL_DB table name
std::string generateKeyFromTableAndObjectName(std::string table_name, std::string object_name);

// Add the unique label to an SAI attribute
// return true if the label was already present;
// return false if a new label is generated.
bool addLabelToAttr(sai_object_type_t object_type, const std::string &table_name, const std::string &key,
sai_attribute_t &attr, sai_attr_id_t attr_id, std::string &mapper_key, std::string &label);

// Save the all entries to state db
void saveMapperToDb();

// Read the all entries from state db
void readMapperFromDb();

// Returns a json string that contains each non-empty label mapper.
std::string dumpStateCache();

// Checks whether label mapping exists for the given key for the specific
// object type.
bool existsLabel(_In_ sai_object_type_t object_type, _In_ const std::string &key) const;

// Verify the given label in the label mapper
std::string verifyLabelMapping(_In_ sai_object_type_t object_type,
_In_ const std::string& key,
_In_ std::string label);

private:
// Generate and return a unique label
std::string generateUniqueLabel();

// Buckets of map tables, one for every SAI object type.
std::unordered_map<std::string, std::string> m_labelTables[SAI_OBJECT_TYPE_MAX];

swss::DBConnector m_db;
swss::Table m_table;
};
7 changes: 6 additions & 1 deletion orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "orchdaemon.h"
#include "logger.h"
#include <sairedis.h>
#include "namelabelmapper.h"
#include "warm_restart.h"
#include <iostream>
#include "orch_zmq_config.h"
Expand Down Expand Up @@ -78,6 +79,7 @@ ShlOrch *gShlOrch;
EvpnMhOrch *gEvpnMhOrch;
L2NhgOrch *gL2NhgOrch;

NameLabelMapper *gLabelMapper;
bool gIsNatSupported = false;
event_handle_t g_events_handle;

Expand Down Expand Up @@ -189,6 +191,7 @@ void OrchDaemon::disableRingBuffer() {
bool OrchDaemon::init()
{
SWSS_LOG_ENTER();
gLabelMapper = new NameLabelMapper();

string platform = getenv("platform") ? getenv("platform") : "";

Expand Down Expand Up @@ -1138,7 +1141,8 @@ bool OrchDaemon::warmRestoreAndSyncUp()
SWSS_LOG_ENTER();

WarmStart::setWarmStartState("orchagent", WarmStart::INITIALIZED);

gLabelMapper->readMapperFromDb();
Comment thread
ksravani-hcl marked this conversation as resolved.

for (Orch *o : m_orchList)
{
o->bake();
Expand Down Expand Up @@ -1209,6 +1213,7 @@ bool OrchDaemon::warmRestoreAndSyncUp()
* The "RECONCILED" state of orchagent doesn't mean the state related to neighbor is up to date.
*/
WarmStart::setWarmStartState("orchagent", WarmStart::RECONCILED);
gLabelMapper->deleteMapperInDb();
return true;
}

Expand Down
4 changes: 3 additions & 1 deletion orchagent/p4orch/p4orch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "copporch.h"
#include "logger.h"
#include "namelabelmapper.h"
#include "orch.h"
#include "p4orch/acl_rule_manager.h"
#include "p4orch/acl_table_manager.h"
Expand All @@ -28,8 +29,9 @@
#include "sai_serialize.h"
#include "timer.h"
#include "timestamp.h"

extern NameLabelMapper *gLabelMapper;
extern PortsOrch *gPortsOrch;

#define P4_ACL_COUNTERS_STATS_POLL_TIMER_NAME "P4_ACL_COUNTERS_STATS_POLL_TIMER"
#define P4_EXT_COUNTERS_STATS_POLL_TIMER_NAME "P4_EXT_COUNTERS_STATS_POLL_TIMER"
#define APP_P4RT_EXT_TABLES_MANAGER "EXT_TABLES_MANAGER"
Expand Down
Loading
Loading