Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ deps/
teamsyncd/teamsyncd
fpmsyncd/fpmsyncd
intfsyncd/intfsyncd
cfgmgr/cfgmgrtest/cfgmgr
neighsyncd/neighsyncd
portsyncd/portsyncd
orchagent/orchagent
Expand Down
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd orchagent swssconfig
SUBDIRS = fpmsyncd neighsyncd intfsyncd portsyncd orchagent swssconfig cfgmgr

if HAVE_LIBTEAM
SUBDIRS += teamsyncd
Expand Down
23 changes: 23 additions & 0 deletions cfgmgr/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/orchagent
CFLAGS_SAI = -I /usr/include/sai

bin_PROGRAMS = vlanmgrd intfmgrd

if DEBUG
DBGFLAGS = -ggdb -DDEBUG
else
DBGFLAGS = -g
endif

vlanmgrd_SOURCES = vlanmgrd.cpp vlanmgr.cpp $(top_srcdir)/orchagent/orch.cpp shellcmd.h
vlanmgrd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
vlanmgrd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
vlanmgrd_LDADD = -lswsscommon


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

SUBDIRS = cfgmgrtest
16 changes: 16 additions & 0 deletions cfgmgr/cfgmgrtest/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/orchagent -I $(top_srcdir)/cfgmgr
CFLAGS_SAI = -I /usr/include/sai

bin_PROGRAMS = cfgmgr

if DEBUG
DBGFLAGS = -ggdb -DDEBUG
else
DBGFLAGS = -g
endif


cfgmgr_SOURCES = cfgmgr.cpp vlancfgmgr.cpp intfcfgmgr.cpp switchcfgmgr.cpp
cfgmgr_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
cfgmgr_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI)
cfgmgr_LDADD = -lswsscommon
62 changes: 62 additions & 0 deletions cfgmgr/cfgmgrtest/cfgmgr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "cfgmgr.h"

using namespace std;

[[ noreturn ]] void usage()
{
std::cout << "Usage: cfgmgr OBJECT { COMMAND | help }" << std::endl
<< "\t where OBJECT := { vlan | intf | switch }\n" << std::endl;
exit(0);
}

void incomplete_command(void)
{
std::cout << "Command line is not complete. Try option \"help\" " << std::endl;
exit(-1);
}

int matches(const char *cmd, const char *pattern)
{
size_t len = strlen(cmd);

if (len > strlen(pattern))
return -1;
return memcmp(pattern, cmd, len);
}

static int do_help(int argc, char **argv)
{
usage();
}

static const struct cmd {
const char *cmd;
int (*func)(int argc, char **argv);
} cmds[] = {
{ "intf", do_intf },
{ "vlan", do_vlan },
{ "switch", do_switch },
{ "help", do_help },
{ NULL, NULL }
};

static int do_cmd(const char *argv0, int argc, char **argv)
{
const struct cmd *c;

for (c = cmds; c->cmd; ++c) {
if (matches(argv0, c->cmd) == 0)
return c->func(argc-1, argv+1);
}

cout << "Object " << argv0 << " is unknown, try \"cfgmgr help\".\n" << std::endl;
return -1;
}

int main(int argc, char **argv)
{
if (argc > 1)
return do_cmd(argv[1], argc-1, argv+1);

usage();
}
30 changes: 30 additions & 0 deletions cfgmgr/cfgmgrtest/cfgmgr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef __CFGMGR__
#define __CFGMGR__

#include <iostream>
#include <functional>
#include <algorithm>
#include <unistd.h>
#include <net/if.h>
#include <cerrno>
#include <cstring>

typedef enum ShowOpEnum_ {
SHOW_NONE = 0,
SHOW_CONFIG,
SHOW_STATE,
} ShowOpEnum;

extern int do_intf(int argc, char **argv);
extern int do_vlan(int argc, char **argv);
extern int do_switch(int argc, char **argv);

#define NEXT_ARG() do { argv++; if (--argc <= 0) incomplete_command(); } while(0)
#define NEXT_ARG_OK() (argc - 1 > 0)
#define NEXT_ARG_FWD() do { argv++; argc--; } while(0)
#define PREV_ARG() do { argv--; argc++; } while(0)

extern void incomplete_command(void);
extern int matches(const char *cmd, const char *pattern);

#endif
219 changes: 219 additions & 0 deletions cfgmgr/cfgmgrtest/intfcfgmgr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
#include <iostream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <functional>
#include <algorithm>
#include <unistd.h>
#include <net/if.h>
#include <cerrno>
#include <cstring>
#include "schema.h"
#include "exec.h"
#include "cfgmgr.h"
#include "intfcfgmgr.h"
#include "orch.h"
#include "shellcmd.h"

using namespace std;
using namespace swss;

const string INTFS_PREFIX = "Ethernet";
const string VLAN_PREFIX = "Vlan";
const string LAG_PREFIX = "PortChannel";

[[ noreturn ]] static void usage(std::string program, int status, std::string message)
{
if (message.size() != 0)
{
std::cout << message << std::endl << std::endl;
}
std::cout << "Usage: " << program << " intf { add | del } PREFIX dev IFNAME\n" << std::endl
<< "\t" << program << " intf show <config | state> [ dev IFNAME ]" << std::endl;

exit(status);
}

int IntfCfgMgr::intf_modify(Operation cmd, int argc, char **argv)
{
char *dev = NULL;
string key;
string prefix;
string scope = "global";
string family = IPV4_NAME;
Table *table;

if (argc <= 0) {
usage("cfgmgr", -1, "Invalid option");
}

// TODO: more validity check on prefix.
prefix = *argv;

NEXT_ARG();
while (argc > 0) {
if (matches(*argv, "dev") == 0) {
NEXT_ARG();
dev = *argv;
} else {
if (matches(*argv, "help") == 0) {
usage("cfgmgr", 0, "");
}
}
argc--; argv++;
}

if (dev == NULL) {
cout << "dev IFNAME is required arguments" << endl;
usage("cfgmgr", -1, "Invalid option");
}

if (if_nametoindex(dev) == 0) {
cout << "Cannot find device " << dev << " : " << std::strerror(errno) << endl;
return -1;
}

key = dev;
key += CONFIGDB_KEY_SEPARATOR;
key += prefix;

if (!key.compare(0, INTFS_PREFIX.length(), INTFS_PREFIX))
{
table = &m_cfgIntfTable;
}
else if (!key.compare(0, LAG_PREFIX.length(), LAG_PREFIX))
{
table = &m_cfgLagIntfTable;
}
else if (!key.compare(0, VLAN_PREFIX.length(), VLAN_PREFIX))
{
table = &m_cfgVlanIntfTable;
}
else
{
cout << dev << " is not a Ethernet or PortChannel or Vlan interface, not supported for now" << endl;
return -1;
}

if (cmd == IntfCfgMgr::DELETE)
{
table->del(key);
}
else
{
std::vector<FieldValueTuple> fvVector;
FieldValueTuple f("family", family);
FieldValueTuple s("scope", scope);
fvVector.push_back(s);
fvVector.push_back(f);
table->set(key, fvVector);
}
return 0;
}

int IntfCfgMgr::intf_show(int argc, char **argv)
{
char *filter_dev = NULL;
unsigned int if_index;
ShowOpEnum show_op = SHOW_NONE;
short vid = -1;

while (argc > 0) {
if (matches(*argv, "dev") == 0) {
NEXT_ARG();
filter_dev = *argv;
}
else if (matches(*argv, "config") == 0) {
show_op = SHOW_CONFIG;
}
else if (matches(*argv, "state") == 0) {
show_op = SHOW_STATE;
}
argc--; argv++;
}

if (show_op == SHOW_NONE)
{
usage("cfgmgr", 0, "");
}

stringstream cmd;
stringstream redis_cmd_db;
stringstream redis_cmd_keys;
stringstream redis_cmd;

redis_cmd_db << REDIS_CLI_CMD << " -n " << CONFIG_DB << "";
cmd << IP_CMD << " address show ";
redis_cmd_keys << "\\*INTERFACE\\|\\*";

if (vid >= 0) {
redis_cmd_keys << vid << "\\*";
}

if (filter_dev) {
if_index = if_nametoindex(filter_dev);
if (if_index == 0) {
cout << "Cannot find bridge device " << filter_dev << " : " << std::strerror(errno) << endl;
return -1;
}
cmd << " dev " << filter_dev;

redis_cmd_keys << filter_dev << "\\*";
}

redis_cmd << redis_cmd_db.str() << " KEYS " << redis_cmd_keys.str()
<< " | " << XARGS_CMD << " -n 1 -I % sh -c 'echo \"%\"; "
<< redis_cmd_db.str() << " hgetall \"%\" | " << PASTE_CMD <<" -d '=' - - | "
<< SED_CMD <<" 's/^/$/'; " << ECHO_CMD << " '";

string res;
if (show_op == SHOW_CONFIG)
{
cout << "-----Redis ConfigDB data---" << endl;
//cout << redis_cmd <<endl;

EXEC_WITH_ERROR_THROW(redis_cmd.str(), res);
cout << res;
return 0;
}

cout << "----Linux hostenv data----" << endl;
EXEC_WITH_ERROR_THROW(cmd.str(), res);
cout << res << endl;
return 0;
}

IntfCfgMgr::IntfCfgMgr(DBConnector *db) :
m_cfgIntfTable(db, CFG_INTF_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR),
m_cfgLagIntfTable(db, CFG_LAG_INTF_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR),
m_cfgVlanIntfTable(db, CFG_VLAN_INTF_TABLE_NAME, CONFIGDB_TABLE_NAME_SEPARATOR)
{

}

int do_intf(int argc, char **argv)
{
auto exitWithUsage = std::bind(usage, "cfgmgr", std::placeholders::_1, std::placeholders::_2);

DBConnector db(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0);
IntfCfgMgr cfgmgr(&db);

if (argc > 0)
{
if (matches(*argv, "add") == 0)
return cfgmgr.intf_modify(IntfCfgMgr::ADD, argc-1, argv+1);
if (matches(*argv, "delete") == 0)
return cfgmgr.intf_modify(IntfCfgMgr::DELETE, argc-1, argv+1);
if (matches(*argv, "show") == 0)
return cfgmgr.intf_show(argc-1, argv+1);
if (matches(*argv, "help") == 0)
exitWithUsage(EXIT_SUCCESS, "");
else
exitWithUsage(EXIT_FAILURE, "Invalid option");
}
else {
exitWithUsage(EXIT_FAILURE, "Invalid option");
}

return EXIT_SUCCESS;
}
29 changes: 29 additions & 0 deletions cfgmgr/cfgmgrtest/intfcfgmgr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef __INTFCFGMGR__
#define __INTFCFGMGR__

#include "dbconnector.h"
#include "table.h"

namespace swss {

class IntfCfgMgr
{
public:
enum Operation {
ADD,
DELETE,
SHOW,
} ;
enum { MAX_ADDR_SIZE = 64 };

IntfCfgMgr(DBConnector *db);
int intf_modify(Operation cmd, int argc, char **argv);
int intf_show(int argc, char **argv);

private:
Table m_cfgIntfTable, m_cfgLagIntfTable, m_cfgVlanIntfTable;
};

}

#endif
Loading