vslib/CorePortIndexMapFileParser.cpp (153 lines of code) (raw):
#include "CorePortIndexMapFileParser.h"
#include "swss/logger.h"
#include "swss/tokenize.h"
#include <net/if.h>
#include <fstream>
#include <cctype>
using namespace saivs;
// must be the same or less as SAI_VS_SWITCH_INDEX_MAX
#define MAX_SWITCH_INDEX (255)
bool CorePortIndexMapFileParser::isInterfaceNameValid(
_In_ const std::string& name)
{
SWSS_LOG_ENTER();
size_t size = name.size();
if (size == 0 || size > IFNAMSIZ)
{
SWSS_LOG_ERROR("invalid interface name %s or length: %zu", name.c_str(), size);
return false;
}
for (size_t i = 0; i < size; i++)
{
char c = name[i];
if (std::isalnum(c))
continue;
SWSS_LOG_ERROR("invalid character '%c' in interface name %s", c, name.c_str());
return false;
}
// interface name is valid
return true;
}
void CorePortIndexMapFileParser::parse(
_In_ std::shared_ptr<CorePortIndexMapContainer> container,
_In_ uint32_t switchIndex,
_In_ const std::string& ifname,
_In_ const std::string& scpidx)
{
SWSS_LOG_ENTER();
if (!isInterfaceNameValid(ifname))
{
SWSS_LOG_ERROR("interface name '%s' is invalid", ifname.c_str());
return;
}
auto tokens = swss::tokenize(scpidx, ',');
size_t n = tokens.size();
if (n != 2)
{
SWSS_LOG_ERROR("Invalid core port index map %s assigned to interface %s", scpidx.c_str(), ifname.c_str());
return;
}
std::vector<uint32_t> cpidx;
for (auto c: tokens)
{
uint32_t c_or_pidx;
if (sscanf(c.c_str(), "%u", &c_or_pidx) != 1)
{
SWSS_LOG_ERROR("failed to parse core or port index: %s", c.c_str());
continue;
}
cpidx.push_back(c_or_pidx);
}
auto corePortIndexMap = container->getCorePortIndexMap(switchIndex);
if (!corePortIndexMap)
{
corePortIndexMap = std::make_shared<CorePortIndexMap>(switchIndex);
container->insert(corePortIndexMap);
}
corePortIndexMap->add(ifname, cpidx);
}
void CorePortIndexMapFileParser::parseLineWithNoIndex(
_In_ std::shared_ptr<CorePortIndexMapContainer> container,
_In_ const std::vector<std::string>& tokens)
{
SWSS_LOG_ENTER();
auto ifname = tokens.at(0);
auto scpidx = tokens.at(1);
parse(container, CorePortIndexMap::DEFAULT_SWITCH_INDEX, ifname, scpidx);
}
void CorePortIndexMapFileParser::parseLineWithIndex(
_In_ std::shared_ptr<CorePortIndexMapContainer> container,
_In_ const std::vector<std::string>& tokens)
{
SWSS_LOG_ENTER();
auto swidx = tokens.at(0);
auto ifname = tokens.at(1);
auto scpidx = tokens.at(2);
uint32_t switchIndex;
if (sscanf(swidx.c_str(), "%u", & switchIndex) != 1)
{
SWSS_LOG_ERROR("failed to parse switchIndex: %s", swidx.c_str());
return;
}
parse(container, switchIndex, ifname, scpidx);
}
std::shared_ptr<CorePortIndexMapContainer> CorePortIndexMapFileParser::parseCorePortIndexMapFile(
_In_ const std::string& file)
{
SWSS_LOG_ENTER();
auto container = std::make_shared<CorePortIndexMapContainer>();
std::ifstream ifs(file);
if (!ifs.is_open())
{
SWSS_LOG_WARN("failed to open core port index map file: %s, using default", file.c_str());
auto def = CorePortIndexMap::getDefaultCorePortIndexMap();
container->insert(def);
return container;
}
SWSS_LOG_NOTICE("loading core port index map from: %s", file.c_str());
std::string line;
while (getline(ifs, line))
{
/*
* line can be in 2 forms:
* ethX:core, core port index
* N:ethX:core, core port index
*
* where N is switchIndex (0..255) - SAI_VS_SWITCH_INDEX_MAX
* if N is not specified then zero (0) is assumed
*/
if (line.size() > 0 && (line[0] == '#' || line[0] == ';'))
{
continue;
}
SWSS_LOG_INFO("core port index line: %s", line.c_str());
auto tokens = swss::tokenize(line, ':');
if (tokens.size() == 3)
{
parseLineWithIndex(container, tokens);
}
else if (tokens.size() == 2)
{
parseLineWithNoIndex(container, tokens);
}
else
{
SWSS_LOG_ERROR("expected 2 or 3 tokens in line %s, got %zu", line.c_str(), tokens.size());
}
}
container->removeEmptyCorePortIndexMaps();
if (container->size() == 0)
{
SWSS_LOG_WARN("no core port index map loaded, returning default core port index map");
auto def = CorePortIndexMap::getDefaultCorePortIndexMap();
container->insert(def);
return container;
}
SWSS_LOG_NOTICE("loaded %zu core port index maps to container", container->size());
return container;
}
std::shared_ptr<CorePortIndexMapContainer> CorePortIndexMapFileParser::parseCorePortIndexMapFile(
_In_ const char* file)
{
SWSS_LOG_ENTER();
if (file == nullptr)
{
auto container = std::make_shared<CorePortIndexMapContainer>();
SWSS_LOG_NOTICE("no file map file specified, loading default");
auto def = CorePortIndexMap::getDefaultCorePortIndexMap();
container->insert(def);
return container;
}
std::string name(file);
return parseCorePortIndexMapFile(name);
}