Skip to content

Commit

Permalink
[cfgmgr]: Add vrfmgrd (#621)
Browse files Browse the repository at this point in the history
* [cfgmgr]: Add vrfmgrd

vrfmgrd is responsible for VRF configuration in Linux
It creates VRF-Lite device for every VRF entry in Config DB

Signed-off-by: Marian Pritsak <marianp@mellanox.com>

* Fix comments

Signed-off-by: Marian Pritsak <marianp@mellanox.com>

* [vrfmgrd]: Recover VRF info from linux after restart

Signed-off-by: Marian Pritsak <marianp@mellanox.com>

* [vrfmgrd]: Set Table ID range from 1001 to 2000

Signed-off-by: Marian Pritsak <marianp@mellanox.com>

* Throw when cmd fails

Signed-off-by: Marian Pritsak <marianp@mellanox.com>
  • Loading branch information
marian-pritsak authored and lguohan committed Sep 19, 2018
1 parent 54a7c9a commit 13df5a9
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ intfsyncd/intfsyncd
cfgmgr/intfmgrd
cfgmgr/vlanmgrd
cfgmgr/buffermanager
cfgmgr/vrfmgrd
neighsyncd/neighsyncd
portsyncd/portsyncd
orchagent/orchagent
Expand Down
6 changes: 5 additions & 1 deletion cfgmgr/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/orchagent -I $(top_srcdir)/warmrestart
CFLAGS_SAI = -I /usr/include/sai

bin_PROGRAMS = vlanmgrd portmgrd intfmgrd buffermgrd
bin_PROGRAMS = vlanmgrd portmgrd intfmgrd buffermgrd vrfmgrd

if DEBUG
DBGFLAGS = -ggdb -DDEBUG
Expand Down Expand Up @@ -30,3 +30,7 @@ buffermgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
buffermgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
buffermgrd_LDADD = -lswsscommon

vrfmgrd_SOURCES = vrfmgrd.cpp vrfmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp shellcmd.h
vrfmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
vrfmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
vrfmgrd_LDADD = -lswsscommon
175 changes: 175 additions & 0 deletions cfgmgr/vrfmgr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#include <string.h>
#include "logger.h"
#include "dbconnector.h"
#include "producerstatetable.h"
#include "tokenize.h"
#include "ipprefix.h"
#include "vrfmgr.h"
#include "exec.h"
#include "shellcmd.h"

#define VRF_TABLE_START 1001
#define VRF_TABLE_END 2000

using namespace swss;

VrfMgr::VrfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames) :
Orch(cfgDb, tableNames)
{
for (uint32_t i = VRF_TABLE_START; i < VRF_TABLE_END; i++)
{
m_freeTables.emplace(i);
}

/* Get existing VRFs from Linux */
stringstream cmd;
string res;

cmd << IP_CMD << " -d link show type vrf";
EXEC_WITH_ERROR_THROW(cmd.str(), res);

enum IpShowRowType
{
LINK_ROW,
MAC_ROW,
DETAILS_ROW,
};

string vrfName;
uint32_t table;
IpShowRowType rowType = LINK_ROW;
const auto& rows = tokenize(res, '\n');
for (const auto& row : rows)
{
const auto& items = tokenize(row, ' ');
switch(rowType)
{
case LINK_ROW:
vrfName = items[1];
vrfName.pop_back();
rowType = MAC_ROW;
break;
case MAC_ROW:
rowType = DETAILS_ROW;
break;
case DETAILS_ROW:
table = static_cast<uint32_t>(stoul(items[6]));
m_vrfTableMap[vrfName] = table;
m_freeTables.erase(table);
rowType = LINK_ROW;
break;
}
}
}

uint32_t VrfMgr::getFreeTable(void)
{
SWSS_LOG_ENTER();

if (m_freeTables.empty())
{
return 0;
}

uint32_t table = *m_freeTables.begin();
m_freeTables.erase(table);

return table;
}

void VrfMgr::recycleTable(uint32_t table)
{
SWSS_LOG_ENTER();

m_freeTables.emplace(table);
}

bool VrfMgr::delLink(const string& vrfName)
{
SWSS_LOG_ENTER();

stringstream cmd;
string res;

if (m_vrfTableMap.find(vrfName) == m_vrfTableMap.end())
{
return false;
}

cmd << IP_CMD << " link del " << vrfName;
EXEC_WITH_ERROR_THROW(cmd.str(), res);

recycleTable(m_vrfTableMap[vrfName]);
m_vrfTableMap.erase(vrfName);

return true;
}

bool VrfMgr::setLink(const string& vrfName)
{
SWSS_LOG_ENTER();

stringstream cmd;
string res;

if (m_vrfTableMap.find(vrfName) != m_vrfTableMap.end())
{
return true;
}

uint32_t table = getFreeTable();
if (table == 0)
{
return false;
}

cmd << IP_CMD << " link add " << vrfName << " type vrf table " << table;
EXEC_WITH_ERROR_THROW(cmd.str(), res);

m_vrfTableMap.emplace(vrfName, table);

cmd.str("");
cmd.clear();
cmd << IP_CMD << " link set " << vrfName << " up";
EXEC_WITH_ERROR_THROW(cmd.str(), res);

return true;
}

void VrfMgr::doTask(Consumer &consumer)
{
SWSS_LOG_ENTER();

auto it = consumer.m_toSync.begin();
while (it != consumer.m_toSync.end())
{
KeyOpFieldsValuesTuple t = it->second;
auto vrfName = kfvKey(t);

string op = kfvOp(t);
if (op == SET_COMMAND)
{
if (!setLink(vrfName))
{
SWSS_LOG_ERROR("Failed to create vrf netdev %s", vrfName.c_str());
}

SWSS_LOG_NOTICE("Created vrf netdev %s", vrfName.c_str());
}
else if (op == DEL_COMMAND)
{
if (!delLink(vrfName))
{
SWSS_LOG_ERROR("Failed to remove vrf netdev %s", vrfName.c_str());
}

SWSS_LOG_NOTICE("Removed vrf netdev %s", vrfName.c_str());
}
else
{
SWSS_LOG_ERROR("Unknown operation: %s", op.c_str());
}

it = consumer.m_toSync.erase(it);
}
}
34 changes: 34 additions & 0 deletions cfgmgr/vrfmgr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef __VRFMGR__
#define __VRFMGR__

#include <string>
#include <map>
#include <set>
#include "dbconnector.h"
#include "producerstatetable.h"
#include "orch.h"

using namespace std;

namespace swss {

class VrfMgr : public Orch
{
public:
VrfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames);
using Orch::doTask;

private:
bool delLink(const string& vrfName);
bool setLink(const string& vrfName);
void recycleTable(uint32_t table);
uint32_t getFreeTable(void);
void doTask(Consumer &consumer);

map<string, uint32_t> m_vrfTableMap;
set<uint32_t> m_freeTables;
};

}

#endif
89 changes: 89 additions & 0 deletions cfgmgr/vrfmgrd.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include <unistd.h>
#include <vector>
#include <mutex>
#include "dbconnector.h"
#include "select.h"
#include "exec.h"
#include "schema.h"
#include "vrfmgr.h"
#include <fstream>
#include <iostream>

using namespace std;
using namespace swss;

/* select() function timeout retry time, in millisecond */
#define SELECT_TIMEOUT 1000

/*
* Following global variables are defined here for the purpose of
* using existing Orch class which is to be refactored soon to
* eliminate the direct exposure of the global variables.
*
* Once Orch class refactoring is done, these global variables
* should be removed from here.
*/
int gBatchSize = 0;
bool gSwssRecord = false;
bool gLogRotate = false;
ofstream gRecordOfs;
string gRecordFile;
/* Global database mutex */
mutex gDbMutex;

int main(int argc, char **argv)
{
Logger::linkToDbNative("vrfmgrd");
SWSS_LOG_ENTER();

SWSS_LOG_NOTICE("--- Starting vrfmgrd ---");

try
{
vector<string> cfg_vrf_tables = {
CFG_VRF_TABLE_NAME,
};

DBConnector cfgDb(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
DBConnector appDb(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
DBConnector stateDb(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);

VrfMgr vrfmgr(&cfgDb, &appDb, &stateDb, cfg_vrf_tables);

// TODO: add tables in stateDB which interface depends on to monitor list
std::vector<Orch *> cfgOrchList = {&vrfmgr};

swss::Select s;
for (Orch *o : cfgOrchList)
{
s.addSelectables(o->getSelectables());
}

SWSS_LOG_NOTICE("starting main loop");
while (true)
{
Selectable *sel;
int ret;

ret = s.select(&sel, SELECT_TIMEOUT);
if (ret == Select::ERROR)
{
SWSS_LOG_NOTICE("Error: %s!", strerror(errno));
continue;
}
if (ret == Select::TIMEOUT)
{
vrfmgr.doTask();
continue;
}

auto *c = (Executor *)sel;
c->execute();
}
}
catch(const std::exception &e)
{
SWSS_LOG_ERROR("Runtime error: %s", e.what());
}
return -1;
}

0 comments on commit 13df5a9

Please sign in to comment.