Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[portsyncd] Remove the port_config.ini dependency from portsyncd #1107

Merged
merged 2 commits into from
Oct 27, 2019
Merged
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
111 changes: 7 additions & 104 deletions portsyncd/portsyncd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ bool g_init = false;

void usage()
{
cout << "Usage: portsyncd [-p port_config.ini]" << endl;
cout << " -p port_config.ini: import port lane mapping" << endl;
cout << " use configDB data if not specified" << endl;
cout << "Usage: portsyncd" << endl;
cout << " port lane mapping is from configDB" << endl;
cout << " this program will exit if configDB does not contain that info" << endl;
}

void handlePortConfigFile(ProducerStateTable &p, string file, bool warm);
Expand All @@ -50,16 +50,12 @@ int main(int argc, char **argv)
{
Logger::linkToDbNative("portsyncd");
int opt;
string port_config_file;
map<string, KeyOpFieldsValuesTuple> port_cfg_map;

while ((opt = getopt(argc, argv, "p:v:h")) != -1 )
while ((opt = getopt(argc, argv, "v:h")) != -1 )
{
switch (opt)
{
case 'p':
port_config_file.assign(optarg);
break;
case 'h':
usage();
return 1;
Expand Down Expand Up @@ -91,11 +87,9 @@ int main(int argc, char **argv)
if (!handlePortConfigFromConfigDB(p, cfgDb, warm))
{
// if port config is missing in ConfigDB
// attempt to use port_config.ini
if (!port_config_file.empty())
{
handlePortConfigFile(p, port_config_file, warm);
}
// program will exit with failure
SWSS_LOG_THROW("ConfigDB does not have port information, exiting...");
return EXIT_FAILURE;
}

LinkSync sync(&appl_db, &state_db);
Expand Down Expand Up @@ -222,97 +216,6 @@ bool handlePortConfigFromConfigDB(ProducerStateTable &p, DBConnector &cfgDb, boo
return true;
}

void handlePortConfigFile(ProducerStateTable &p, string file, bool warm)
{
cout << "Read port configuration file..." << endl;

ifstream infile(file);
if (!infile.is_open())
{
usage();
throw runtime_error("Port configuration file not found!");
}

list<string> header = {"name", "lanes", "alias", "speed", "autoneg", "fec"};
string line;
while (getline(infile, line))
{
if (line.at(0) == '#')
{
// Take this line as column header line
istringstream iss_hdr(line.substr(1));
string hdr;

header.clear();
while (! iss_hdr.eof()) {
iss_hdr >> hdr;
cout << "Adding column header '" << hdr << "'" << endl;
header.push_back(hdr);
}

continue;
}

istringstream iss(line);
map<string, string> entry;

/* Read port configuration entry */
for (auto column : header)
{
iss >> entry[column];
}

if (!warm)
{
/* If port has no alias, then use its name as alias */
string alias;
if ((entry.find("alias") != entry.end()) && (entry["alias"] != ""))
{
alias = entry["alias"];
}
else
{
alias = entry["name"];
}

FieldValueTuple lanes_attr("lanes", entry["lanes"]);
FieldValueTuple alias_attr("alias", alias);

vector<FieldValueTuple> attrs;
attrs.push_back(lanes_attr);
attrs.push_back(alias_attr);

if ((entry.find("speed") != entry.end()) && (entry["speed"] != ""))
{
FieldValueTuple speed_attr("speed", entry["speed"]);
attrs.push_back(speed_attr);
}

if ((entry.find("autoneg") != entry.end()) && (entry["autoneg"] != ""))
{
FieldValueTuple autoneg_attr("autoneg", entry["autoneg"]);
attrs.push_back(autoneg_attr);
}

if ((entry.find("fec") != entry.end()) && (entry["fec"] != ""))
{
FieldValueTuple fec_attr("fec", entry["fec"]);
attrs.push_back(fec_attr);
}

p.set(entry["name"], attrs);
}

g_portSet.insert(entry["name"]);
}

infile.close();
if (!warm)
{
notifyPortConfigDone(p);
}
}

void handlePortConfig(ProducerStateTable &p, map<string, KeyOpFieldsValuesTuple> &port_cfg_map)
{

Expand Down
101 changes: 73 additions & 28 deletions tests/test_port_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,44 +55,89 @@ def test_port_hw_lane(self, dvs):

def test_port_breakout(self, dvs, port_config):

# check port_config.ini
(exitcode, output) = dvs.runcmd(['sh', '-c', "cat %s | tail -n 1" % (port_config)])
try:
name_str, lanes_str, alias_str, index_str, speed_str = list(output.split())
except:
print "parse port_config.ini fail"

LANES_L = list(lanes_str.split(","))
assert len(LANES_L) == 4
assert int(speed_str) == 40000

# modify port_config.ini
eth = int(name_str.replace("Ethernet", ""))
index = int(index_str)
speed_str = "tenGigE0"
speed = 10000
dvs.runcmd("sed -i '$d' %s" % (port_config)) == 0
for i in range(0,4):
dvs.runcmd("sed -i '$a Ethernet%-7d %-17d %s/%-8d %-11d %d' %s" %
(eth+i, int(LANES_L[i]), speed_str, eth+i, index+i, speed, port_config)) == 0

# delete port config
# Breakout the port from 1 to 4
'''
"Ethernet0": {
"alias": "fortyGigE0/0",
"index": "0",
"lanes": "25,26,27,28",
"speed": "40000"
},

to:
"Ethernet0": {
"alias": "tenGigE0",
"index": "0",
"lanes": "25",
"speed": "10000"
},

"Ethernet1": {
"alias": "tenGigE1",
"index": "0",
"lanes": "26",
"speed": "10000"
},

"Ethernet2": {
"alias": "tenGigE2",
"index": "0",
"lanes": "27",
"speed": "10000"
},

"Ethernet3": {
"alias": "tenGigE3",
"index": "0",
"lanes": "28",
"speed": "10000"
},
'''
# Get port config from configDB
conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)
portTbl = swsscommon.Table(conf_db, swsscommon.CFG_PORT_TABLE_NAME)

chg_port = "Ethernet0"

keys = portTbl.getKeys()
assert len(keys) > 0
for key in keys:
portTbl._del(key)
assert chg_port in keys

(status, fvs) = portTbl.get(chg_port)
assert(status == True)

for fv in fvs:
if fv[0] == "index":
new_index = fv[1]
if fv[0] == "lanes":
new_lanes = fv[1].split(",")

# restart to apply new port_config.ini
# Stop swss before modifing the configDB
dvs.stop_swss()
time.sleep(1)

# breakout the port in configDB
portTbl._del(chg_port)

new_ports = ["Ethernet0","Ethernet1","Ethernet2","Ethernet3"]
new_speed = "10000"
new_alias = ["tenGigE0", "tenGigE1", "tenGigE2", "tenGigE3"]

for i in range (0 ,4):
fvs = swsscommon.FieldValuePairs([("alias", new_alias[i]),
("lanes", new_lanes[i]),
("speed", new_speed),
("index", new_index)])

portTbl.set(new_ports[i], fvs)

# start to apply new port_config.ini
dvs.start_swss()
time.sleep(5)

asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)

for i in range(0,4):
port_name = 'Ethernet{0}'.format(eth+i)
port_name = 'Ethernet{0}'.format(i)
port_oid = self.getPortOid(dvs, port_name)
port_tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_PORT:{0}'.format(port_oid))
hw_lane_value = None
Expand All @@ -102,6 +147,6 @@ def test_port_breakout(self, dvs, port_config):
hw_lane_value = k[1]

assert hw_lane_value, "Can't get hw_lane list"
assert hw_lane_value == "1:%s" % (LANES_L[i])
assert hw_lane_value == "1:%s" % (new_lanes[i])