Skip to content

Commit

Permalink
[intfmgr]: Support configuring IPs for all regular interfaces (#544)
Browse files Browse the repository at this point in the history
Enable configuring IPv4 and IPv6 addresses on regular ports
Add tests to test IPv4 add/remove to regular ports

Signed-off-by: Shu0T1an ChenG <[email protected]>
  • Loading branch information
Shuotian Cheng authored Aug 13, 2018
1 parent fa7008f commit c9ed2c4
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 28 deletions.
49 changes: 23 additions & 26 deletions cfgmgr/intfmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,20 @@ IntfMgr::IntfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c
{
}

bool IntfMgr::setIntfIp(const string &alias, const string &opCmd, const string &ipPrefixStr)
bool IntfMgr::setIntfIp(const string &alias, const string &opCmd,
const string &ipPrefixStr, const bool ipv4)
{
stringstream cmd;
string res;

cmd << IP_CMD << " address " << opCmd << " " << ipPrefixStr << " dev " << alias;;
if (ipv4)
{
cmd << IP_CMD << " address " << opCmd << " " << ipPrefixStr << " dev " << alias;
}
else
{
cmd << IP_CMD << " -6 address " << opCmd << " " << ipPrefixStr << " dev " << alias;
}
int ret = swss::exec(cmd.str(), res);
return (ret == 0);
}
Expand Down Expand Up @@ -72,34 +80,24 @@ void IntfMgr::doTask(Consumer &consumer)
{
KeyOpFieldsValuesTuple t = it->second;

string keySeparator = CONFIGDB_KEY_SEPARATOR;
vector<string> keys = tokenize(kfvKey(t), keySeparator[0]);
string alias(keys[0]);
vector<string> keys = tokenize(kfvKey(t), config_db_key_delimiter);

if (alias.compare(0, strlen(VLAN_PREFIX), VLAN_PREFIX))
if (keys.size() != 2)
{
/* handle IP over vlan Only for now, skip the rest */
SWSS_LOG_ERROR("Invalid key %s", kfvKey(t).c_str());
it = consumer.m_toSync.erase(it);
continue;
}

size_t pos = kfvKey(t).find(CONFIGDB_KEY_SEPARATOR);
if (pos == string::npos)
{
SWSS_LOG_DEBUG("Invalid key %s", kfvKey(t).c_str());
it = consumer.m_toSync.erase(it);
continue;
}
IpPrefix ip_prefix(kfvKey(t).substr(pos+1));

SWSS_LOG_DEBUG("intfs doTask: %s", (dumpTuple(consumer, t)).c_str());
string alias(keys[0]);
IpPrefix ip_prefix(keys[1]);

string op = kfvOp(t);
if (op == SET_COMMAND)
{
/*
* Don't proceed if port/lag/VLAN is not ready yet.
* The pending task will be checked periodially and retried.
* Don't proceed if port/LAG/VLAN is not ready yet.
* The pending task will be checked periodically and retried.
* TODO: Subscribe to stateDB for port/lag/VLAN state and retry
* pending tasks immediately upon state change.
*/
Expand All @@ -109,18 +107,17 @@ void IntfMgr::doTask(Consumer &consumer)
it++;
continue;
}
string opCmd("add");
string ipPrefixStr = ip_prefix.to_string();
setIntfIp(alias, opCmd, ipPrefixStr);
setIntfIp(alias, "add", ip_prefix.to_string(), ip_prefix.isV4());
}
else if (op == DEL_COMMAND)
{
string opCmd("del");
string ipPrefixStr = ip_prefix.to_string();
setIntfIp(alias, opCmd, ipPrefixStr);
setIntfIp(alias, "del", ip_prefix.to_string(), ip_prefix.isV4());
}
else
{
SWSS_LOG_ERROR("Unknown operation: %s", op.c_str());
}

it = consumer.m_toSync.erase(it);
continue;
}
}
2 changes: 1 addition & 1 deletion cfgmgr/intfmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class IntfMgr : public Orch
Table m_cfgIntfTable, m_cfgVlanIntfTable;
Table m_statePortTable, m_stateLagTable, m_stateVlanTable;

bool setIntfIp(const string &alias, const string &opCmd, const string &ipPrefixStr);
bool setIntfIp(const string &alias, const string &opCmd, const string &ipPrefixStr, const bool ipv4 = true);
void doTask(Consumer &consumer);
bool isIntfStateOk(const string &alias);
};
Expand Down
67 changes: 66 additions & 1 deletion tests/test_interface.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,73 @@
from swsscommon import swsscommon

import time
import re
import json

class TestInterfaceIpv4Addresses(object):
def test_InterfaceAddIpv4Address(self, dvs):
pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0)
adb = swsscommon.DBConnector(1, dvs.redis_sock, 0)
cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0)

# assign IP to interface
tbl = swsscommon.Table(cdb, "INTERFACE")
fvs = swsscommon.FieldValuePairs([("NULL", "NULL")])
tbl.set("Ethernet8|10.0.0.4/31", fvs)
time.sleep(1)

# check application database
tbl = swsscommon.Table(pdb, "INTF_TABLE:Ethernet8")
intf_entries = tbl.getKeys()
assert len(intf_entries) == 1
assert intf_entries[0] == "10.0.0.4/31"

(status, fvs) = tbl.get(tbl.getKeys()[0])
assert status == True
assert len(fvs) == 2
for fv in fvs:
if fv[0] == "scope":
assert fv[1] == "global"
elif fv[0] == "family":
assert fv[1] == "IPv4"
else:
assert False

# check asic database
tbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY")
for key in tbl.getKeys():
route = json.loads(key)
if route["dest"] == "10.0.0.4/31":
subnet_found = True
if route["dest"] == "10.0.0.4/32":
ip2me_found = True

assert subnet_found and ip2me_found

def test_InterfaceRemoveIpv4Address(self, dvs):
pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0)
adb = swsscommon.DBConnector(1, dvs.redis_sock, 0)
cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0)

# assign IP to interface
tbl = swsscommon.Table(cdb, "INTERFACE")
tbl._del("Ethernet8|10.0.0.4/31")
time.sleep(1)

# check application database
tbl = swsscommon.Table(pdb, "INTF_TABLE:Ethernet8")
intf_entries = tbl.getKeys()
assert len(intf_entries) == 0

# check asic database
tbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY")
for key in tbl.getKeys():
route = json.loads(key)
if route["dest"] == "10.0.0.4/31":
assert False
if route["dest"] == "10.0.0.4/32":
assert False


def test_InterfaceIpChange(dvs):

dvs.runcmd("ifconfig Ethernet0 10.0.0.0/31 up")
Expand Down

0 comments on commit c9ed2c4

Please sign in to comment.