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

[swss] L2 Forwarding Enhancements #1716

Merged
merged 15 commits into from
Nov 20, 2021
8 changes: 3 additions & 5 deletions orchagent/fdborch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -874,10 +874,6 @@ void FdbOrch::doTask(NotificationConsumer& consumer)
{
if (op == "ALL")
{
/*
* so far only support flush all the FDB entries
* flush per port and flush per vlan will be added later.
*/
status = sai_fdb_api->flush_fdb_entries(gSwitchId, 0, NULL);
if (status != SAI_STATUS_SUCCESS)
{
Expand Down Expand Up @@ -1080,7 +1076,9 @@ void FdbOrch::updatePortOperState(const PortOperStateUpdate& update)

// Get BVID of each VLAN that this port is a member of
// and call notifyObserversFDBFlush
for (const auto& vlan_member: p.m_vlan_members)
vlan_members_t vlan_members;
m_portsOrch->getPortVlanMembers(p, vlan_members);
for (const auto& vlan_member: vlan_members)
{
swss::Port vlan;
string vlan_alias = VLAN_PREFIX + to_string(vlan_member.first);
Expand Down
2 changes: 1 addition & 1 deletion orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class Port
VlanInfo m_vlan_info;
MacAddress m_mac;
sai_object_id_t m_bridge_port_id = 0; // TODO: port could have multiple bridge port IDs
sai_object_id_t m_bridge_port_admin_state = 0; // TODO: port could have multiple bridge port IDs
sai_vlan_id_t m_port_vlan_id = DEFAULT_PORT_VLAN_ID; // Port VLAN ID
sai_object_id_t m_rif_id = 0;
sai_object_id_t m_vr_id = 0;
Expand All @@ -130,7 +131,6 @@ class Port
sai_object_id_t m_tunnel_id = 0;
sai_object_id_t m_ingress_acl_table_group_id = 0;
sai_object_id_t m_egress_acl_table_group_id = 0;
vlan_members_t m_vlan_members;
sai_object_id_t m_parent_port_id = 0;
uint32_t m_dependency_bitmap = 0;
sai_port_oper_status_t m_oper_status = SAI_PORT_OPER_STATUS_UNKNOWN;
Expand Down
108 changes: 66 additions & 42 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -745,35 +745,15 @@ bool PortsOrch::getPort(sai_object_id_t id, Port &port)
{
SWSS_LOG_ENTER();

for (const auto& portIter: m_portList)
auto itr = saiOidToAlias.find(id);
if (itr == saiOidToAlias.end())
{
switch (portIter.second.m_type)
{
case Port::PHY:
case Port::SYSTEM:
if(portIter.second.m_port_id == id)
{
port = portIter.second;
return true;
}
break;
case Port::LAG:
if(portIter.second.m_lag_id == id)
{
port = portIter.second;
return true;
}
break;
case Port::VLAN:
if (portIter.second.m_vlan_info.vlan_oid == id)
{
port = portIter.second;
return true;
}
break;
default:
continue;
}
return false;
}
else
{
getPort(itr->second, port);
return true;
}

return false;
Expand Down Expand Up @@ -813,13 +793,15 @@ bool PortsOrch::getPortByBridgePortId(sai_object_id_t bridge_port_id, Port &port
{
SWSS_LOG_ENTER();

for (auto &it: m_portList)
auto itr = saiOidToAlias.find(bridge_port_id);
if (itr == saiOidToAlias.end())
{
if (it.second.m_bridge_port_id == bridge_port_id)
{
port = it.second;
return true;
}
return false;
}
else
{
getPort(itr->second, port);
return true;
}

return false;
Expand Down Expand Up @@ -2358,6 +2340,7 @@ bool PortsOrch::initPort(const string &alias, const string &role, const int inde

/* Add port to port list */
m_portList[alias] = p;
saiOidToAlias[id] = alias;
m_port_ref_count[alias] = 0;
m_portOidToIndex[id] = index;

Expand Down Expand Up @@ -3558,7 +3541,7 @@ void PortsOrch::doVlanMemberTask(Consumer &consumer)
{
if (removeVlanMember(vlan, port))
{
if (port.m_vlan_members.empty())
if (m_portVlanMember[port.m_alias].empty())
{
removeBridgePort(port);
}
Expand Down Expand Up @@ -3661,7 +3644,6 @@ void PortsOrch::doLagTask(Consumer &consumer)
switch_id = -1;
}

// Create a new LAG when the new alias comes
if (m_portList.find(alias) == m_portList.end())
{
if (!addLag(alias, lag_id, switch_id))
Expand Down Expand Up @@ -4331,6 +4313,7 @@ bool PortsOrch::addBridgePort(Port &port)
return false;
}
m_portList[port.m_alias] = port;
saiOidToAlias[port.m_bridge_port_id] = port.m_alias;
SWSS_LOG_NOTICE("Add bridge port %s to default 1Q bridge", port.m_alias.c_str());

PortUpdate update = { port, true };
Expand Down Expand Up @@ -4387,6 +4370,7 @@ bool PortsOrch::removeBridgePort(Port &port)
return parseHandleSaiStatusFailure(handle_status);
}
}
saiOidToAlias.erase(port.m_bridge_port_id);
port.m_bridge_port_id = SAI_NULL_OBJECT_ID;

/* Remove bridge port */
Expand Down Expand Up @@ -4460,7 +4444,7 @@ bool PortsOrch::addVlan(string vlan_alias)
}
}

SWSS_LOG_NOTICE("Create an empty VLAN %s vid:%hu", vlan_alias.c_str(), vlan_id);
SWSS_LOG_NOTICE("Create an empty VLAN %s vid:%hu vlan_oid:%" PRIx64, vlan_alias.c_str(), vlan_id, vlan_oid);

Port vlan(vlan_alias, Port::VLAN);
vlan.m_vlan_info.vlan_oid = vlan_oid;
Expand All @@ -4470,6 +4454,7 @@ bool PortsOrch::addVlan(string vlan_alias)
vlan.m_members = set<string>();
m_portList[vlan_alias] = vlan;
m_port_ref_count[vlan_alias] = 0;
saiOidToAlias[vlan_oid] = vlan_alias;

return true;
}
Expand All @@ -4478,6 +4463,13 @@ bool PortsOrch::removeVlan(Port vlan)
{
SWSS_LOG_ENTER();

/* If there are still fdb entries associated with the VLAN,
return false for retry */
if (vlan.m_fdb_count > 0)
{
SWSS_LOG_NOTICE("VLAN %s still has assiciated FDB entries", vlan.m_alias.c_str());
return false;
}
if (m_port_ref_count[vlan.m_alias] > 0)
{
SWSS_LOG_ERROR("Failed to remove ref count %d VLAN %s",
Expand Down Expand Up @@ -4525,6 +4517,7 @@ bool PortsOrch::removeVlan(Port vlan)
SWSS_LOG_NOTICE("Remove VLAN %s vid:%hu", vlan.m_alias.c_str(),
vlan.m_vlan_info.vlan_id);

saiOidToAlias.erase(vlan.m_vlan_info.vlan_oid);
m_portList.erase(vlan.m_alias);
m_port_ref_count.erase(vlan.m_alias);

Expand Down Expand Up @@ -4614,7 +4607,7 @@ bool PortsOrch::addVlanMember(Port &vlan, Port &port, string &tagging_mode, stri

/* a physical port may join multiple vlans */
VlanMemberEntry vme = {vlan_member_id, sai_tagging_mode};
port.m_vlan_members[vlan.m_vlan_info.vlan_id] = vme;
m_portVlanMember[port.m_alias][vlan.m_vlan_info.vlan_id] = vme;
m_portList[port.m_alias] = port;
vlan.m_members.insert(port.m_alias);
m_portList[vlan.m_alias] = vlan;
Expand All @@ -4625,6 +4618,12 @@ bool PortsOrch::addVlanMember(Port &vlan, Port &port, string &tagging_mode, stri
return true;
}

bool PortsOrch::getPortVlanMembers(Port &port, vlan_members_t &vlan_members)
{
vlan_members = m_portVlanMember[port.m_alias];
return true;
}

bool PortsOrch::addVlanFloodGroups(Port &vlan, Port &port, string end_point_ip)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -4844,10 +4843,10 @@ bool PortsOrch::removeVlanMember(Port &vlan, Port &port, string end_point_ip)
}
sai_object_id_t vlan_member_id;
sai_vlan_tagging_mode_t sai_tagging_mode;
auto vlan_member = port.m_vlan_members.find(vlan.m_vlan_info.vlan_id);
auto vlan_member = m_portVlanMember[port.m_alias].find(vlan.m_vlan_info.vlan_id);

/* Assert the port belongs to this VLAN */
assert (vlan_member != port.m_vlan_members.end());
assert (vlan_member != m_portVlanMember[port.m_alias].end());
sai_tagging_mode = vlan_member->second.vlan_mode;
vlan_member_id = vlan_member->second.vlan_member_id;

Expand All @@ -4862,7 +4861,11 @@ bool PortsOrch::removeVlanMember(Port &vlan, Port &port, string end_point_ip)
return parseHandleSaiStatusFailure(handle_status);
}
}
port.m_vlan_members.erase(vlan_member);
m_portVlanMember[port.m_alias].erase(vlan_member);
if (m_portVlanMember[port.m_alias].empty())
{
m_portVlanMember.erase(port.m_alias);
}
SWSS_LOG_NOTICE("Remove member %s from VLAN %s lid:%hx vmid:%" PRIx64,
port.m_alias.c_str(), vlan.m_alias.c_str(), vlan.m_vlan_info.vlan_id, vlan_member_id);

Expand Down Expand Up @@ -4905,6 +4908,20 @@ bool PortsOrch::addLag(string lag_alias, uint32_t spa_id, int32_t switch_id)
{
SWSS_LOG_ENTER();

auto lagport = m_portList.find(lag_alias);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some comments. I believe this is the scenario where removeBridgePort is not yet successful due to fdb flush right?

if (lagport != m_portList.end())
{
/* The deletion of bridgeport attached to the lag may still be
* pending due to fdb entries still present on the lag. Wait
* until the cleanup is done.
*/
if (m_portList[lag_alias].m_bridge_port_id != SAI_NULL_OBJECT_ID)
{
return false;
}
return true;
}

vector<sai_attribute_t> lag_attrs;
string system_lag_alias = lag_alias;

Expand Down Expand Up @@ -4956,6 +4973,7 @@ bool PortsOrch::addLag(string lag_alias, uint32_t spa_id, int32_t switch_id)
lag.m_members = set<string>();
m_portList[lag_alias] = lag;
m_port_ref_count[lag_alias] = 0;
saiOidToAlias[lag_id] = lag_alias;

PortUpdate update = { lag, true };
notify(SUBJECT_TYPE_PORT_CHANGE, static_cast<void *>(&update));
Expand Down Expand Up @@ -5004,12 +5022,17 @@ bool PortsOrch::removeLag(Port lag)
SWSS_LOG_ERROR("Failed to remove non-empty LAG %s", lag.m_alias.c_str());
return false;
}
if (lag.m_vlan_members.size() > 0)
if (m_portVlanMember[lag.m_alias].size() > 0)
{
SWSS_LOG_ERROR("Failed to remove LAG %s, it is still in VLAN", lag.m_alias.c_str());
return false;
}

if (lag.m_bridge_port_id != SAI_NULL_OBJECT_ID)
{
return false;
}

sai_status_t status = sai_lag_api->remove_lag(lag.m_lag_id);
if (status != SAI_STATUS_SUCCESS)
{
Expand All @@ -5023,6 +5046,7 @@ bool PortsOrch::removeLag(Port lag)

SWSS_LOG_NOTICE("Remove LAG %s lid:%" PRIx64, lag.m_alias.c_str(), lag.m_lag_id);

saiOidToAlias.erase(lag.m_lag_id);
m_portList.erase(lag.m_alias);
m_port_ref_count.erase(lag.m_alias);

Expand Down
7 changes: 7 additions & 0 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ class PortsOrch : public Orch, public Subject
string m_inbandPortName = "";
bool isInbandPort(const string &alias);
bool setVoqInbandIntf(string &alias, string &type);
bool getPortVlanMembers(Port &port, vlan_members_t &vlan_members);

bool getRecircPort(Port &p, string role);

Expand Down Expand Up @@ -226,6 +227,12 @@ class PortsOrch : public Orch, public Subject
map<set<int>, sai_object_id_t> m_portListLaneMap;
map<set<int>, tuple<string, uint32_t, int, string, int, string>> m_lanesAliasSpeedMap;
map<string, Port> m_portList;
map<string, vlan_members_t> m_portVlanMember;
/* mapping from SAI object ID to Name for faster
* retrieval of Port/VLAN from object ID for events
* coming from SAI
*/
unordered_map<sai_object_id_t, string> saiOidToAlias;
unordered_map<sai_object_id_t, int> m_portOidToIndex;
map<string, uint32_t> m_port_ref_count;
unordered_set<string> m_pendingPortSet;
Expand Down