Skip to content

Commit 13df5a9

Browse files
marian-pritsaklguohan
authored andcommitted
[cfgmgr]: Add vrfmgrd (#621)
* [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 <[email protected]> * Fix comments Signed-off-by: Marian Pritsak <[email protected]> * [vrfmgrd]: Recover VRF info from linux after restart Signed-off-by: Marian Pritsak <[email protected]> * [vrfmgrd]: Set Table ID range from 1001 to 2000 Signed-off-by: Marian Pritsak <[email protected]> * Throw when cmd fails Signed-off-by: Marian Pritsak <[email protected]>
1 parent 54a7c9a commit 13df5a9

File tree

5 files changed

+304
-1
lines changed

5 files changed

+304
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ intfsyncd/intfsyncd
4848
cfgmgr/intfmgrd
4949
cfgmgr/vlanmgrd
5050
cfgmgr/buffermanager
51+
cfgmgr/vrfmgrd
5152
neighsyncd/neighsyncd
5253
portsyncd/portsyncd
5354
orchagent/orchagent

cfgmgr/Makefile.am

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/orchagent -I $(top_srcdir)/warmrestart
22
CFLAGS_SAI = -I /usr/include/sai
33

4-
bin_PROGRAMS = vlanmgrd portmgrd intfmgrd buffermgrd
4+
bin_PROGRAMS = vlanmgrd portmgrd intfmgrd buffermgrd vrfmgrd
55

66
if DEBUG
77
DBGFLAGS = -ggdb -DDEBUG
@@ -30,3 +30,7 @@ buffermgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
3030
buffermgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
3131
buffermgrd_LDADD = -lswsscommon
3232

33+
vrfmgrd_SOURCES = vrfmgrd.cpp vrfmgr.cpp $(top_srcdir)/orchagent/orch.cpp $(top_srcdir)/orchagent/request_parser.cpp shellcmd.h
34+
vrfmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
35+
vrfmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
36+
vrfmgrd_LDADD = -lswsscommon

cfgmgr/vrfmgr.cpp

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#include <string.h>
2+
#include "logger.h"
3+
#include "dbconnector.h"
4+
#include "producerstatetable.h"
5+
#include "tokenize.h"
6+
#include "ipprefix.h"
7+
#include "vrfmgr.h"
8+
#include "exec.h"
9+
#include "shellcmd.h"
10+
11+
#define VRF_TABLE_START 1001
12+
#define VRF_TABLE_END 2000
13+
14+
using namespace swss;
15+
16+
VrfMgr::VrfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames) :
17+
Orch(cfgDb, tableNames)
18+
{
19+
for (uint32_t i = VRF_TABLE_START; i < VRF_TABLE_END; i++)
20+
{
21+
m_freeTables.emplace(i);
22+
}
23+
24+
/* Get existing VRFs from Linux */
25+
stringstream cmd;
26+
string res;
27+
28+
cmd << IP_CMD << " -d link show type vrf";
29+
EXEC_WITH_ERROR_THROW(cmd.str(), res);
30+
31+
enum IpShowRowType
32+
{
33+
LINK_ROW,
34+
MAC_ROW,
35+
DETAILS_ROW,
36+
};
37+
38+
string vrfName;
39+
uint32_t table;
40+
IpShowRowType rowType = LINK_ROW;
41+
const auto& rows = tokenize(res, '\n');
42+
for (const auto& row : rows)
43+
{
44+
const auto& items = tokenize(row, ' ');
45+
switch(rowType)
46+
{
47+
case LINK_ROW:
48+
vrfName = items[1];
49+
vrfName.pop_back();
50+
rowType = MAC_ROW;
51+
break;
52+
case MAC_ROW:
53+
rowType = DETAILS_ROW;
54+
break;
55+
case DETAILS_ROW:
56+
table = static_cast<uint32_t>(stoul(items[6]));
57+
m_vrfTableMap[vrfName] = table;
58+
m_freeTables.erase(table);
59+
rowType = LINK_ROW;
60+
break;
61+
}
62+
}
63+
}
64+
65+
uint32_t VrfMgr::getFreeTable(void)
66+
{
67+
SWSS_LOG_ENTER();
68+
69+
if (m_freeTables.empty())
70+
{
71+
return 0;
72+
}
73+
74+
uint32_t table = *m_freeTables.begin();
75+
m_freeTables.erase(table);
76+
77+
return table;
78+
}
79+
80+
void VrfMgr::recycleTable(uint32_t table)
81+
{
82+
SWSS_LOG_ENTER();
83+
84+
m_freeTables.emplace(table);
85+
}
86+
87+
bool VrfMgr::delLink(const string& vrfName)
88+
{
89+
SWSS_LOG_ENTER();
90+
91+
stringstream cmd;
92+
string res;
93+
94+
if (m_vrfTableMap.find(vrfName) == m_vrfTableMap.end())
95+
{
96+
return false;
97+
}
98+
99+
cmd << IP_CMD << " link del " << vrfName;
100+
EXEC_WITH_ERROR_THROW(cmd.str(), res);
101+
102+
recycleTable(m_vrfTableMap[vrfName]);
103+
m_vrfTableMap.erase(vrfName);
104+
105+
return true;
106+
}
107+
108+
bool VrfMgr::setLink(const string& vrfName)
109+
{
110+
SWSS_LOG_ENTER();
111+
112+
stringstream cmd;
113+
string res;
114+
115+
if (m_vrfTableMap.find(vrfName) != m_vrfTableMap.end())
116+
{
117+
return true;
118+
}
119+
120+
uint32_t table = getFreeTable();
121+
if (table == 0)
122+
{
123+
return false;
124+
}
125+
126+
cmd << IP_CMD << " link add " << vrfName << " type vrf table " << table;
127+
EXEC_WITH_ERROR_THROW(cmd.str(), res);
128+
129+
m_vrfTableMap.emplace(vrfName, table);
130+
131+
cmd.str("");
132+
cmd.clear();
133+
cmd << IP_CMD << " link set " << vrfName << " up";
134+
EXEC_WITH_ERROR_THROW(cmd.str(), res);
135+
136+
return true;
137+
}
138+
139+
void VrfMgr::doTask(Consumer &consumer)
140+
{
141+
SWSS_LOG_ENTER();
142+
143+
auto it = consumer.m_toSync.begin();
144+
while (it != consumer.m_toSync.end())
145+
{
146+
KeyOpFieldsValuesTuple t = it->second;
147+
auto vrfName = kfvKey(t);
148+
149+
string op = kfvOp(t);
150+
if (op == SET_COMMAND)
151+
{
152+
if (!setLink(vrfName))
153+
{
154+
SWSS_LOG_ERROR("Failed to create vrf netdev %s", vrfName.c_str());
155+
}
156+
157+
SWSS_LOG_NOTICE("Created vrf netdev %s", vrfName.c_str());
158+
}
159+
else if (op == DEL_COMMAND)
160+
{
161+
if (!delLink(vrfName))
162+
{
163+
SWSS_LOG_ERROR("Failed to remove vrf netdev %s", vrfName.c_str());
164+
}
165+
166+
SWSS_LOG_NOTICE("Removed vrf netdev %s", vrfName.c_str());
167+
}
168+
else
169+
{
170+
SWSS_LOG_ERROR("Unknown operation: %s", op.c_str());
171+
}
172+
173+
it = consumer.m_toSync.erase(it);
174+
}
175+
}

cfgmgr/vrfmgr.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef __VRFMGR__
2+
#define __VRFMGR__
3+
4+
#include <string>
5+
#include <map>
6+
#include <set>
7+
#include "dbconnector.h"
8+
#include "producerstatetable.h"
9+
#include "orch.h"
10+
11+
using namespace std;
12+
13+
namespace swss {
14+
15+
class VrfMgr : public Orch
16+
{
17+
public:
18+
VrfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames);
19+
using Orch::doTask;
20+
21+
private:
22+
bool delLink(const string& vrfName);
23+
bool setLink(const string& vrfName);
24+
void recycleTable(uint32_t table);
25+
uint32_t getFreeTable(void);
26+
void doTask(Consumer &consumer);
27+
28+
map<string, uint32_t> m_vrfTableMap;
29+
set<uint32_t> m_freeTables;
30+
};
31+
32+
}
33+
34+
#endif

cfgmgr/vrfmgrd.cpp

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#include <unistd.h>
2+
#include <vector>
3+
#include <mutex>
4+
#include "dbconnector.h"
5+
#include "select.h"
6+
#include "exec.h"
7+
#include "schema.h"
8+
#include "vrfmgr.h"
9+
#include <fstream>
10+
#include <iostream>
11+
12+
using namespace std;
13+
using namespace swss;
14+
15+
/* select() function timeout retry time, in millisecond */
16+
#define SELECT_TIMEOUT 1000
17+
18+
/*
19+
* Following global variables are defined here for the purpose of
20+
* using existing Orch class which is to be refactored soon to
21+
* eliminate the direct exposure of the global variables.
22+
*
23+
* Once Orch class refactoring is done, these global variables
24+
* should be removed from here.
25+
*/
26+
int gBatchSize = 0;
27+
bool gSwssRecord = false;
28+
bool gLogRotate = false;
29+
ofstream gRecordOfs;
30+
string gRecordFile;
31+
/* Global database mutex */
32+
mutex gDbMutex;
33+
34+
int main(int argc, char **argv)
35+
{
36+
Logger::linkToDbNative("vrfmgrd");
37+
SWSS_LOG_ENTER();
38+
39+
SWSS_LOG_NOTICE("--- Starting vrfmgrd ---");
40+
41+
try
42+
{
43+
vector<string> cfg_vrf_tables = {
44+
CFG_VRF_TABLE_NAME,
45+
};
46+
47+
DBConnector cfgDb(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
48+
DBConnector appDb(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
49+
DBConnector stateDb(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
50+
51+
VrfMgr vrfmgr(&cfgDb, &appDb, &stateDb, cfg_vrf_tables);
52+
53+
// TODO: add tables in stateDB which interface depends on to monitor list
54+
std::vector<Orch *> cfgOrchList = {&vrfmgr};
55+
56+
swss::Select s;
57+
for (Orch *o : cfgOrchList)
58+
{
59+
s.addSelectables(o->getSelectables());
60+
}
61+
62+
SWSS_LOG_NOTICE("starting main loop");
63+
while (true)
64+
{
65+
Selectable *sel;
66+
int ret;
67+
68+
ret = s.select(&sel, SELECT_TIMEOUT);
69+
if (ret == Select::ERROR)
70+
{
71+
SWSS_LOG_NOTICE("Error: %s!", strerror(errno));
72+
continue;
73+
}
74+
if (ret == Select::TIMEOUT)
75+
{
76+
vrfmgr.doTask();
77+
continue;
78+
}
79+
80+
auto *c = (Executor *)sel;
81+
c->execute();
82+
}
83+
}
84+
catch(const std::exception &e)
85+
{
86+
SWSS_LOG_ERROR("Runtime error: %s", e.what());
87+
}
88+
return -1;
89+
}

0 commit comments

Comments
 (0)