Skip to content

Commit

Permalink
[vlan] Add support of VLAN host interface (sonic-net#1645)
Browse files Browse the repository at this point in the history
* [vlan] Add support of VLAN host interface
* Infrastructure needed for the VNET ping tool

Signed-off-by: Volodymyr Samotiy <[email protected]>
  • Loading branch information
volodymyrsamotiy authored Apr 8, 2021
1 parent 5c63670 commit ca8ba6d
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 0 deletions.
8 changes: 8 additions & 0 deletions cfgmgr/vlanmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ void VlanMgr::doVlanTask(Consumer &consumer)
string admin_status;
string mtu = DEFAULT_MTU_STR;
string mac = gMacAddress.to_string();
string hostif_name = "";
vector<FieldValueTuple> fvVector;
string members;

Expand Down Expand Up @@ -362,6 +363,10 @@ void VlanMgr::doVlanTask(Consumer &consumer)
mac = fvValue(i);
setHostVlanMac(vlan_id, mac);
}
else if (fvField(i) == "hostif_name")
{
hostif_name = fvValue(i);
}
}
/* fvVector should not be empty */
if (fvVector.empty())
Expand All @@ -376,6 +381,9 @@ void VlanMgr::doVlanTask(Consumer &consumer)
FieldValueTuple mc("mac", mac);
fvVector.push_back(mc);

FieldValueTuple hostif_name_fvt("hostif_name", hostif_name);
fvVector.push_back(hostif_name_fvt);

m_appVlanTableProducer.set(key, fvVector);
m_vlans.insert(key);

Expand Down
1 change: 1 addition & 0 deletions orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct VlanInfo
{
sai_object_id_t vlan_oid = 0;
sai_vlan_id_t vlan_id = 0;
sai_object_id_t host_intf_id = SAI_NULL_OBJECT_ID;
};

struct SystemPortInfo
Expand Down
71 changes: 71 additions & 0 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1932,6 +1932,55 @@ bool PortsOrch::setHostIntfsOperStatus(const Port& port, bool isUp) const
return true;
}

bool PortsOrch::createVlanHostIntf(Port& vl, string hostif_name)
{
SWSS_LOG_ENTER();

if (vl.m_vlan_info.host_intf_id != SAI_NULL_OBJECT_ID)
{
SWSS_LOG_ERROR("Host interface already assigned to VLAN %d", vl.m_vlan_info.vlan_id);
return false;
}

vector<sai_attribute_t> attrs;
sai_attribute_t attr;

attr.id = SAI_HOSTIF_ATTR_TYPE;
attr.value.s32 = SAI_HOSTIF_TYPE_NETDEV;
attrs.push_back(attr);

attr.id = SAI_HOSTIF_ATTR_OBJ_ID;
attr.value.oid = vl.m_vlan_info.vlan_oid;
attrs.push_back(attr);

attr.id = SAI_HOSTIF_ATTR_NAME;
strncpy(attr.value.chardata, hostif_name.c_str(), sizeof(attr.value.chardata));
attrs.push_back(attr);

sai_status_t status = sai_hostif_api->create_hostif(&vl.m_vlan_info.host_intf_id, gSwitchId, (uint32_t)attrs.size(), attrs.data());
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to create host interface %s for VLAN %d", hostif_name.c_str(), vl.m_vlan_info.vlan_id);
return false;
}

m_portList[vl.m_alias] = vl;

return true;
}

bool PortsOrch::removeVlanHostIntf(Port vl)
{
sai_status_t status = sai_hostif_api->remove_hostif(vl.m_vlan_info.host_intf_id);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to remove VLAN %d host interface", vl.m_vlan_info.vlan_id);
return false;
}

return true;
}

void PortsOrch::updateDbPortOperStatus(const Port& port, sai_port_oper_status_t status) const
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -2870,6 +2919,7 @@ void PortsOrch::doVlanTask(Consumer &consumer)
// Retrieve attributes
uint32_t mtu = 0;
MacAddress mac;
string hostif_name = "";
for (auto i : kfvFieldsValues(t))
{
if (fvField(i) == "mtu")
Expand All @@ -2880,6 +2930,10 @@ void PortsOrch::doVlanTask(Consumer &consumer)
{
mac = MacAddress(fvValue(i));
}
if (fvField(i) == "hostif_name")
{
hostif_name = fvValue(i);
}
}

/*
Expand Down Expand Up @@ -2922,6 +2976,16 @@ void PortsOrch::doVlanTask(Consumer &consumer)
gIntfsOrch->setRouterIntfsMac(vl);
}
}
if (!hostif_name.empty())
{
if (!createVlanHostIntf(vl, hostif_name))
{
// No need to fail in case of error as this is for monitoring VLAN.
// Error message is printed by "createVlanHostIntf" so just handle failure gracefully.
it = consumer.m_toSync.erase(it);
continue;
}
}
}

it = consumer.m_toSync.erase(it);
Expand Down Expand Up @@ -3914,6 +3978,13 @@ bool PortsOrch::removeVlan(Port vlan)
return false;
}


if (vlan.m_vlan_info.host_intf_id && !removeVlanHostIntf(vlan))
{
SWSS_LOG_ERROR("Failed to remove VLAN %d host interface", vlan.m_vlan_info.vlan_id);
return false;
}

sai_status_t status = sai_vlan_api->remove_vlan(vlan.m_vlan_info.vlan_oid);
if (status != SAI_STATUS_SUCCESS)
{
Expand Down
3 changes: 3 additions & 0 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ class PortsOrch : public Orch, public Subject
bool setHostIntfsOperStatus(const Port& port, bool up) const;
void updateDbPortOperStatus(const Port& port, sai_port_oper_status_t status) const;

bool createVlanHostIntf(Port& vl, string hostif_name);
bool removeVlanHostIntf(Port vl);

bool createBindAclTableGroup(sai_object_id_t port_oid,
sai_object_id_t acl_table_oid,
sai_object_id_t &group_oid,
Expand Down
24 changes: 24 additions & 0 deletions tests/dvslib/dvs_vlan.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ def create_vlan(self, vlan):
vlan_entry = {"vlanid": vlan}
self.config_db.create_entry("VLAN", vlan, vlan_entry)

def create_vlan_hostif(self, vlan, hostif_name):
vlan = "Vlan{}".format(vlan)
vlan_entry = {"vlanid": vlan, "hostif_name": hostif_name}
self.config_db.update_entry("VLAN", vlan, vlan_entry)

def remove_vlan(self, vlan):
vlan = "Vlan{}".format(vlan)
self.config_db.delete_entry("VLAN", vlan)
Expand Down Expand Up @@ -53,6 +58,7 @@ def get_and_verify_vlan_ids(self,
vlan_entries = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_VLAN",
expected_num + 1,
polling_config)

return [v for v in vlan_entries if v != self.asic_db.default_vlan_id]

def verify_vlan_member(self, vlan_oid, iface, tagging_mode="SAI_VLAN_TAGGING_MODE_UNTAGGED"):
Expand All @@ -74,3 +80,21 @@ def get_bridge_port_id(self, expected_iface):
assert self.asic_db.port_to_id_map[bridge_port["SAI_BRIDGE_PORT_ATTR_PORT_ID"]] == expected_iface
return bridge_port_id

def verify_vlan_hostif(self, hostif_name, hostifs_oid, vlan_oid):
hostif = {}

for hostif_oid in hostifs_oid:
hostif = self.asic_db.wait_for_entry("ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF", hostif_oid)
if hostif.get("SAI_HOSTIF_ATTR_NAME") == hostif_name:
break

assert hostif.get("SAI_HOSTIF_ATTR_TYPE") == "SAI_HOSTIF_TYPE_NETDEV"
assert hostif.get("SAI_HOSTIF_ATTR_OBJ_ID") == vlan_oid
assert hostif.get("SAI_HOSTIF_ATTR_NAME") == hostif_name

def get_and_verify_vlan_hostif_ids(self, expected_num, polling_config=PollingConfig()):
hostif_entries = self.asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_HOSTIF",
expected_num + 1,
polling_config)
return hostif_entries

16 changes: 16 additions & 0 deletions tests/test_vlan.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,22 @@ def test_VlanMemberDbData(self, dvs, test_input, expected):
self.dvs_vlan.remove_vlan(vlan)
self.dvs_vlan.get_and_verify_vlan_ids(0)

def test_VlanHostIf(self, dvs):

vlan = "2"
hostif_name = "MonVlan2"

self.dvs_vlan.create_vlan(vlan)
vlan_oid = self.dvs_vlan.get_and_verify_vlan_ids(1)[0]
self.dvs_vlan.verify_vlan(vlan_oid, vlan)

self.dvs_vlan.create_vlan_hostif(vlan, hostif_name)
hostif_oid = self.dvs_vlan.get_and_verify_vlan_hostif_ids(len(dvs.asic_db.hostif_name_map))
self.dvs_vlan.verify_vlan_hostif(hostif_name, hostif_oid, vlan_oid)

self.dvs_vlan.remove_vlan(vlan)
self.dvs_vlan.get_and_verify_vlan_ids(0)
self.dvs_vlan.get_and_verify_vlan_hostif_ids(len(dvs.asic_db.hostif_name_map) - 1)

# Add Dummy always-pass test at end as workaroud
# for issue when Flaky fail on final test it invokes module tear-down before retrying
Expand Down

0 comments on commit ca8ba6d

Please sign in to comment.