-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* [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
1 parent
54a7c9a
commit 13df5a9
Showing
5 changed files
with
304 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |