Skip to content

Commit 6e84504

Browse files
jipanyanglguohan
authored andcommitted
[configdb]: configDB enforcer for interface (#357)
* configDB enforcer for interface Support VLAN interface only for now Signed-off-by: Jipan Yang <[email protected]> * Use OrchBase for configDB intf configuration enforcer Signed-off-by: Jipan Yang <[email protected]> * Rename intfconf to intfmgr Signed-off-by: Jipan Yang <[email protected]> * Use shell full path command macros Signed-off-by: Jipan Yang <[email protected]> * Optimize shell command execution error handling Signed-off-by: Jipan Yang <[email protected]> * Use Orch class for intfmgrd orchestration Signed-off-by: Jipan Yang <[email protected]>
1 parent 021ef4f commit 6e84504

File tree

5 files changed

+259
-1
lines changed

5 files changed

+259
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ deps/
4343
teamsyncd/teamsyncd
4444
fpmsyncd/fpmsyncd
4545
intfsyncd/intfsyncd
46+
cfgmgr/intfmgrd
4647
cfgmgr/vlanmgrd
4748
neighsyncd/neighsyncd
4849
portsyncd/portsyncd

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
22
CFLAGS_SAI = -I /usr/include/sai
33

4-
bin_PROGRAMS = vlanmgrd
4+
bin_PROGRAMS = vlanmgrd intfmgrd
55

66
if DEBUG
77
DBGFLAGS = -ggdb -DDEBUG
@@ -14,3 +14,7 @@ vlanmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
1414
vlanmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
1515
vlanmgrd_LDADD = -lswsscommon
1616

17+
intfmgrd_SOURCES = intfmgrd.cpp intfmgr.cpp $(top_srcdir)/orchagent/orch.cpp shellcmd.h
18+
intfmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
19+
intfmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
20+
intfmgrd_LDADD = -lswsscommon

cfgmgr/intfmgr.cpp

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
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 "intfmgr.h"
8+
#include "exec.h"
9+
#include "shellcmd.h"
10+
11+
using namespace std;
12+
using namespace swss;
13+
14+
#define VLAN_PREFIX "Vlan"
15+
#define LAG_PREFIX "PortChannel"
16+
17+
IntfMgr::IntfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames) :
18+
Orch(cfgDb, tableNames),
19+
m_cfgIntfTable(cfgDb, CFG_INTF_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR),
20+
m_cfgVlanIntfTable(cfgDb, CFG_VLAN_INTF_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR),
21+
m_statePortTable(stateDb, STATE_PORT_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR),
22+
m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR),
23+
m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR),
24+
m_appIntfTableProducer(appDb, APP_INTF_TABLE_NAME)
25+
{
26+
}
27+
28+
bool IntfMgr::setIntfIp(const string &alias, const string &opCmd, const string &ipPrefixStr)
29+
{
30+
stringstream cmd;
31+
string res;
32+
33+
cmd << IP_CMD << " address " << opCmd << " " << ipPrefixStr << " dev " << alias;;
34+
int ret = swss::exec(cmd.str(), res);
35+
return (ret == 0);
36+
}
37+
38+
bool IntfMgr::isIntfStateOk(const string &alias)
39+
{
40+
vector<FieldValueTuple> temp;
41+
42+
if (!alias.compare(0, strlen(VLAN_PREFIX), VLAN_PREFIX))
43+
{
44+
if (m_stateVlanTable.get(alias, temp))
45+
{
46+
SWSS_LOG_DEBUG("Vlan %s is ready", alias.c_str());
47+
return true;
48+
}
49+
}
50+
else if (!alias.compare(0, strlen(LAG_PREFIX), LAG_PREFIX))
51+
{
52+
if (m_stateLagTable.get(alias, temp))
53+
{
54+
SWSS_LOG_DEBUG("Lag %s is ready", alias.c_str());
55+
return true;
56+
}
57+
}
58+
else if (m_statePortTable.get(alias, temp))
59+
{
60+
SWSS_LOG_DEBUG("Port %s is ready", alias.c_str());
61+
return true;
62+
}
63+
64+
return false;
65+
}
66+
void IntfMgr::doTask(Consumer &consumer)
67+
{
68+
SWSS_LOG_ENTER();
69+
70+
auto it = consumer.m_toSync.begin();
71+
while (it != consumer.m_toSync.end())
72+
{
73+
KeyOpFieldsValuesTuple t = it->second;
74+
75+
string keySeparator = CONFIGDB_KEY_SEPARATOR;
76+
vector<string> keys = tokenize(kfvKey(t), keySeparator[0]);
77+
string alias(keys[0]);
78+
79+
if (alias.compare(0, strlen(VLAN_PREFIX), VLAN_PREFIX))
80+
{
81+
/* handle IP over vlan Only for now, skip the rest */
82+
it = consumer.m_toSync.erase(it);
83+
continue;
84+
}
85+
86+
size_t pos = kfvKey(t).find(CONFIGDB_KEY_SEPARATOR);
87+
if (pos == string::npos)
88+
{
89+
SWSS_LOG_DEBUG("Invalid key %s", kfvKey(t).c_str());
90+
it = consumer.m_toSync.erase(it);
91+
continue;
92+
}
93+
IpPrefix ip_prefix(kfvKey(t).substr(pos+1));
94+
95+
SWSS_LOG_DEBUG("intfs doTask: %s", (dumpTuple(consumer, t)).c_str());
96+
97+
string op = kfvOp(t);
98+
if (op == SET_COMMAND)
99+
{
100+
/*
101+
* Don't proceed if port/lag/VLAN is not ready yet.
102+
* The pending task will be checked periodially and retried.
103+
* TODO: Subscribe to stateDB for port/lag/VLAN state and retry
104+
* pending tasks immediately upon state change.
105+
*/
106+
if (!isIntfStateOk(alias))
107+
{
108+
SWSS_LOG_DEBUG("Interface is not ready, skipping %s", kfvKey(t).c_str());
109+
it++;
110+
continue;
111+
}
112+
string opCmd("add");
113+
string ipPrefixStr = ip_prefix.to_string();
114+
setIntfIp(alias, opCmd, ipPrefixStr);
115+
}
116+
else if (op == DEL_COMMAND)
117+
{
118+
string opCmd("del");
119+
string ipPrefixStr = ip_prefix.to_string();
120+
setIntfIp(alias, opCmd, ipPrefixStr);
121+
}
122+
123+
it = consumer.m_toSync.erase(it);
124+
continue;
125+
}
126+
}

cfgmgr/intfmgr.h

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef __INTFMGR__
2+
#define __INTFMGR__
3+
4+
#include "dbconnector.h"
5+
#include "producerstatetable.h"
6+
#include "orch.h"
7+
8+
#include <map>
9+
#include <string>
10+
11+
namespace swss {
12+
13+
class IntfMgr : public Orch
14+
{
15+
public:
16+
IntfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames);
17+
18+
private:
19+
ProducerStateTable m_appIntfTableProducer;
20+
Table m_cfgIntfTable, m_cfgVlanIntfTable;
21+
Table m_statePortTable, m_stateLagTable, m_stateVlanTable;
22+
23+
bool setIntfIp(const string &alias, const string &opCmd, const string &ipPrefixStr);
24+
void doTask(Consumer &consumer);
25+
bool isIntfStateOk(const string &alias);
26+
};
27+
28+
}
29+
30+
#endif

cfgmgr/intfmgrd.cpp

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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 "intfmgr.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("intfmgrd");
37+
SWSS_LOG_ENTER();
38+
39+
SWSS_LOG_NOTICE("--- Starting intfmgrd ---");
40+
41+
try
42+
{
43+
vector<string> cfg_intf_tables = {
44+
CFG_INTF_TABLE_NAME,
45+
CFG_LAG_INTF_TABLE_NAME,
46+
CFG_VLAN_INTF_TABLE_NAME,
47+
};
48+
49+
DBConnector cfgDb(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
50+
DBConnector appDb(APPL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
51+
DBConnector stateDb(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
52+
53+
IntfMgr intfmgr(&cfgDb, &appDb, &stateDb, cfg_intf_tables);
54+
55+
// TODO: add tables in stateDB which interface depends on to monitor list
56+
std::vector<Orch *> cfgOrchList = {&intfmgr};
57+
58+
swss::Select s;
59+
for (Orch *o : cfgOrchList)
60+
{
61+
s.addSelectables(o->getSelectables());
62+
}
63+
64+
SWSS_LOG_NOTICE("starting main loop");
65+
while (true)
66+
{
67+
Selectable *sel;
68+
int fd, ret;
69+
70+
ret = s.select(&sel, &fd, SELECT_TIMEOUT);
71+
if (ret == Select::ERROR)
72+
{
73+
SWSS_LOG_NOTICE("Error: %s!", strerror(errno));
74+
continue;
75+
}
76+
if (ret == Select::TIMEOUT)
77+
{
78+
((Orch *)&intfmgr)->doTask();
79+
continue;
80+
}
81+
82+
for (Orch *o : cfgOrchList)
83+
{
84+
TableConsumable *c = (TableConsumable *)sel;
85+
if (o->hasSelectable(c))
86+
{
87+
o->execute(c->getTableName());
88+
}
89+
}
90+
}
91+
}
92+
catch(const std::exception &e)
93+
{
94+
SWSS_LOG_ERROR("Runtime error: %s", e.what());
95+
}
96+
return -1;
97+
}

0 commit comments

Comments
 (0)