Skip to content

Commit

Permalink
Refactored portsyncd structure to improve testability
Browse files Browse the repository at this point in the history
Signed-off-by: Vivek Reddy Karri <vkarri@nvidia.com>
  • Loading branch information
vivekrnv committed Apr 27, 2022
1 parent 841f003 commit 1c6cd64
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 101 deletions.
80 changes: 78 additions & 2 deletions portsyncd/linksync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "netmsg.h"
#include "dbconnector.h"
#include "producerstatetable.h"
#include "subscriberstatetable.h"
#include "tokenize.h"
#include "exec.h"

Expand All @@ -31,8 +32,8 @@ const string MGMT_PREFIX = "eth";
const string INTFS_PREFIX = "Ethernet";
const string LAG_PREFIX = "PortChannel";

extern set<string> g_portSet;
extern bool g_init;
set<string> g_portSet;
bool g_init;

struct if_nameindex
{
Expand Down Expand Up @@ -268,3 +269,78 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj)
SWSS_LOG_NOTICE("Cannot find %s in port table", key.c_str());
}
}

static void notifyPortConfigDone(ProducerStateTable &p)
{
/* Notify that all ports added */
FieldValueTuple finish_notice("count", to_string(g_portSet.size()));
vector<FieldValueTuple> attrs = { finish_notice };
p.set("PortConfigDone", attrs);
}

void handlePortConfigFromConfigDB(ProducerStateTable &p, DBConnector &cfgDb, bool warm)
{
SWSS_LOG_ENTER();

SWSS_LOG_NOTICE("Getting port configuration from ConfigDB...");

Table table(&cfgDb, CFG_PORT_TABLE_NAME);
std::vector<FieldValueTuple> ovalues;
std::vector<string> keys;
table.getKeys(keys);

if (keys.empty())
{
SWSS_LOG_NOTICE("ConfigDB does not have port information, "
"however ports can be added later on, continuing...");
}

for ( auto &k : keys )
{
table.get(k, ovalues);
vector<FieldValueTuple> attrs;
for ( auto &v : ovalues )
{
FieldValueTuple attr(v.first, v.second);
attrs.push_back(attr);
}
if (!warm)
{
p.set(k, attrs);
}
g_portSet.insert(k);
}
if (!warm)
{
notifyPortConfigDone(p);
}

}

void handlePortConfig(ProducerStateTable &p, map<string, KeyOpFieldsValuesTuple> &port_cfg_map)
{
auto it = port_cfg_map.begin();
while (it != port_cfg_map.end())
{
KeyOpFieldsValuesTuple entry = it->second;
string key = kfvKey(entry);
string op = kfvOp(entry);
auto values = kfvFieldsValues(entry);

/* only push down port config when port is not in hostif create pending state */
if (g_portSet.find(key) == g_portSet.end())
{
/* No support for port delete yet */
if (op == SET_COMMAND)
{
p.set(key, values);
}

it = port_cfg_map.erase(it);
}
else
{
it++;
}
}
}
9 changes: 9 additions & 0 deletions portsyncd/linksync.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@
#include "dbconnector.h"
#include "producerstatetable.h"
#include "netmsg.h"
#include "exec.h"

#include <map>
#include <set>
#include <vector>
#include <set>
#include <map>
#include <list>

namespace swss {

Expand All @@ -28,4 +34,7 @@ class LinkSync : public NetMsg

}

void handlePortConfigFromConfigDB(swss::ProducerStateTable &, swss::DBConnector &, bool );
void handlePortConfig(swss::ProducerStateTable &, std::map<std::string, swss::KeyOpFieldsValuesTuple> &);

#endif
101 changes: 2 additions & 99 deletions portsyncd/portsyncd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,22 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <sys/stat.h>
#include "dbconnector.h"
#include "select.h"
#include "netdispatcher.h"
#include "netlink.h"
#include "producerstatetable.h"
#include "portsyncd/linksync.h"
#include "subscriberstatetable.h"
#include "exec.h"
#include "warm_restart.h"

using namespace std;
using namespace swss;

#define DEFAULT_SELECT_TIMEOUT 1000 /* ms */

/*
* This g_portSet contains all the front panel ports that the corresponding
* host interfaces needed to be created. When this LinkSync class is
* initialized, we check the database to see if some of the ports' host
* interfaces are already created and remove them from this set. We will
* remove the rest of the ports in the set when receiving the first netlink
* message indicating that the host interfaces are created. After the set
* is empty, we send out the signal PortInitDone. g_init is used to limit the
* command to be run only once.
*/
set<string> g_portSet;
bool g_init = false;
extern set<string> g_portSet;
extern bool g_init;

void usage()
{
Expand All @@ -42,12 +26,6 @@ void usage()
cout << " this program will exit if configDB does not contain that info" << endl;
}

void handlePortConfigFile(ProducerStateTable &p, string file, bool warm);
void handlePortConfigFromConfigDB(ProducerStateTable &p, DBConnector &cfgDb, bool warm);
void handleVlanIntfFile(string file);
void handlePortConfig(ProducerStateTable &p, map<string, KeyOpFieldsValuesTuple> &port_cfg_map);
void checkPortInitDone(DBConnector *appl_db);

int main(int argc, char **argv)
{
Logger::linkToDbNative("portsyncd");
Expand Down Expand Up @@ -178,78 +156,3 @@ int main(int argc, char **argv)

return 1;
}

static void notifyPortConfigDone(ProducerStateTable &p)
{
/* Notify that all ports added */
FieldValueTuple finish_notice("count", to_string(g_portSet.size()));
vector<FieldValueTuple> attrs = { finish_notice };
p.set("PortConfigDone", attrs);
}

void handlePortConfigFromConfigDB(ProducerStateTable &p, DBConnector &cfgDb, bool warm)
{
SWSS_LOG_ENTER();

SWSS_LOG_NOTICE("Getting port configuration from ConfigDB...");

Table table(&cfgDb, CFG_PORT_TABLE_NAME);
std::vector<FieldValueTuple> ovalues;
std::vector<string> keys;
table.getKeys(keys);

if (keys.empty())
{
SWSS_LOG_NOTICE("ConfigDB does not have port information, "
"however ports can be added later on, continuing...");
}

for ( auto &k : keys )
{
table.get(k, ovalues);
vector<FieldValueTuple> attrs;
for ( auto &v : ovalues )
{
FieldValueTuple attr(v.first, v.second);
attrs.push_back(attr);
}
if (!warm)
{
p.set(k, attrs);
}
g_portSet.insert(k);
}
if (!warm)
{
notifyPortConfigDone(p);
}

}

void handlePortConfig(ProducerStateTable &p, map<string, KeyOpFieldsValuesTuple> &port_cfg_map)
{
auto it = port_cfg_map.begin();
while (it != port_cfg_map.end())
{
KeyOpFieldsValuesTuple entry = it->second;
string key = kfvKey(entry);
string op = kfvOp(entry);
auto values = kfvFieldsValues(entry);

/* only push down port config when port is not in hostif create pending state */
if (g_portSet.find(key) == g_portSet.end())
{
/* No support for port delete yet */
if (op == SET_COMMAND)
{
p.set(key, values);
}

it = port_cfg_map.erase(it);
}
else
{
it++;
}
}
}

0 comments on commit 1c6cd64

Please sign in to comment.