From a64f9ad9d58c0978dc093260bad9f428769668be Mon Sep 17 00:00:00 2001 From: Volodymyr Samotiy Date: Thu, 18 Apr 2019 21:17:34 +0300 Subject: [PATCH] =?UTF-8?q?[vnetorch]:=20Add=20VNET=20interface=20removal?= =?UTF-8?q?=20flow=20for=20Bitmap=20VNET=20implement=E2=80=A6=20(#820)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [vnetorch]: Add VNET interface removal flow for Bitmap VNET implementation * Fix review comments Signed-off-by: Volodymyr Samotiy --- orchagent/intfsorch.cpp | 97 ++++++++++++++++++++++++--------- orchagent/intfsorch.h | 1 + orchagent/vnetorch.cpp | 117 ++++++++++++++++++++++++++++++++++++++-- orchagent/vnetorch.h | 9 ++++ 4 files changed, 195 insertions(+), 29 deletions(-) diff --git a/orchagent/intfsorch.cpp b/orchagent/intfsorch.cpp index 1617dbde15ca..d890af1eece0 100644 --- a/orchagent/intfsorch.cpp +++ b/orchagent/intfsorch.cpp @@ -206,6 +206,46 @@ bool IntfsOrch::setIntf(const string& alias, sai_object_id_t vrf_id, const IpPre return true; } +bool IntfsOrch::removeIntf(const string& alias, sai_object_id_t vrf_id, const IpPrefix *ip_prefix) +{ + SWSS_LOG_ENTER(); + + Port port; + if (!gPortsOrch->getPort(alias, port)) + { + return false; + } + + if (ip_prefix && m_syncdIntfses[alias].ip_addresses.count(*ip_prefix)) + { + removeSubnetRoute(port, *ip_prefix); + removeIp2MeRoute(vrf_id, *ip_prefix); + + if(port.m_type == Port::VLAN) + { + removeDirectedBroadcast(port, *ip_prefix); + } + + m_syncdIntfses[alias].ip_addresses.erase(*ip_prefix); + } + + /* Remove router interface that no IP addresses are associated with */ + if (m_syncdIntfses[alias].ip_addresses.size() == 0) + { + if (removeRouterIntfs(port)) + { + m_syncdIntfses.erase(alias); + return true; + } + else + { + return false; + } + } + + return true; +} + void IntfsOrch::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); @@ -379,41 +419,50 @@ void IntfsOrch::doTask(Consumer &consumer) continue; } - vrf_id = port.m_vr_id; - if (m_syncdIntfses.find(alias) != m_syncdIntfses.end()) + if (m_syncdIntfses.find(alias) == m_syncdIntfses.end()) { - if (m_syncdIntfses[alias].ip_addresses.count(ip_prefix)) - { - removeSubnetRoute(port, ip_prefix); - removeIp2MeRoute(vrf_id, ip_prefix); + /* Cannot locate the interface */ + it = consumer.m_toSync.erase(it); + continue; + } - if(port.m_type == Port::VLAN) - { - removeDirectedBroadcast(port, ip_prefix); - } + if (m_vnetInfses.find(alias) != m_vnetInfses.end()) + { + vnet_name = m_vnetInfses.at(alias); + } - m_syncdIntfses[alias].ip_addresses.erase(ip_prefix); + if (!vnet_name.empty()) + { + VNetOrch* vnet_orch = gDirectory.get(); + if (!vnet_orch->isVnetExists(vnet_name)) + { + it++; + continue; } - /* Remove router interface that no IP addresses are associated with */ - if (m_syncdIntfses[alias].ip_addresses.size() == 0) + if (vnet_orch->delIntf(alias, vnet_name, ip_prefix_in_key ? &ip_prefix : nullptr)) { - if (removeRouterIntfs(port)) - { - m_syncdIntfses.erase(alias); - it = consumer.m_toSync.erase(it); - } - else - it++; + m_vnetInfses.erase(alias); + it = consumer.m_toSync.erase(it); } else { - it = consumer.m_toSync.erase(it); + it++; + continue; } } else - /* Cannot locate the interface */ - it = consumer.m_toSync.erase(it); + { + if (removeIntf(alias, port.m_vr_id, ip_prefix_in_key ? &ip_prefix : nullptr)) + { + it = consumer.m_toSync.erase(it); + } + else + { + it++; + continue; + } + } } } } @@ -833,4 +882,4 @@ void IntfsOrch::doTask(SelectableTimer &timer) ++it; } } -} \ No newline at end of file +} diff --git a/orchagent/intfsorch.h b/orchagent/intfsorch.h index b9db02e1d080..903018638777 100644 --- a/orchagent/intfsorch.h +++ b/orchagent/intfsorch.h @@ -44,6 +44,7 @@ class IntfsOrch : public Orch void removeRifFromFlexCounter(const string&, const string&); bool setIntf(const string& alias, sai_object_id_t vrf_id = gVirtualRouterId, const IpPrefix *ip_prefix = nullptr); + bool removeIntf(const string& alias, sai_object_id_t vrf_id = gVirtualRouterId, const IpPrefix *ip_prefix = nullptr); void addIp2MeRoute(sai_object_id_t vrf_id, const IpPrefix &ip_prefix); void removeIp2MeRoute(sai_object_id_t vrf_id, const IpPrefix &ip_prefix); diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index a5d3b052d18b..a2ea7a914e93 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -640,12 +640,18 @@ bool VNetBitmapObject::addIntf(const string& alias, const IpPrefix *prefix) if (gIntfsOrch->getSyncdIntfses().find(alias) == gIntfsOrch->getSyncdIntfses().end()) { + if (intfMap_.find(alias) != intfMap_.end()) + { + SWSS_LOG_ERROR("VNET '%s' interface '%s' already exists", getVnetName().c_str(), alias.c_str()); + return false; + } + if (!gIntfsOrch->setIntf(alias, gVirtualRouterId, nullptr)) { return false; } - sai_object_id_t vnetTableEntryId; + VnetIntfInfo intfInfo; attr.id = SAI_TABLE_BITMAP_CLASSIFICATION_ENTRY_ATTR_ACTION; attr.value.s32 = SAI_TABLE_BITMAP_CLASSIFICATION_ENTRY_ACTION_SET_METADATA; @@ -660,7 +666,7 @@ bool VNetBitmapObject::addIntf(const string& alias, const IpPrefix *prefix) vnet_attrs.push_back(attr); status = sai_bmtor_api->create_table_bitmap_classification_entry( - &vnetTableEntryId, + &intfInfo.vnetTableEntryId, gSwitchId, (uint32_t)vnet_attrs.size(), vnet_attrs.data()); @@ -670,11 +676,23 @@ bool VNetBitmapObject::addIntf(const string& alias, const IpPrefix *prefix) SWSS_LOG_ERROR("Failed to create VNET table entry, SAI rc: %d", status); throw std::runtime_error("VNet interface creation failed"); } + + intfMap_.emplace(alias, intfInfo); } if (prefix) { - sai_object_id_t tunnelRouteTableEntryId; + auto& intf = intfMap_.at(alias); + + if (intf.pfxMap.find(*prefix) != intf.pfxMap.end()) + { + SWSS_LOG_WARN("VNET '%s' interface '%s' prefix '%s' already exists", + getVnetName().c_str(), alias.c_str(), prefix->getIp().to_string().c_str()); + return true; + } + + RouteInfo intfPfxInfo; + sai_ip_prefix_t saiPrefix; copy(saiPrefix, *prefix); @@ -684,8 +702,9 @@ bool VNetBitmapObject::addIntf(const string& alias, const IpPrefix *prefix) attr.value.s32 = SAI_TABLE_BITMAP_ROUTER_ENTRY_ACTION_TO_LOCAL; route_attrs.push_back(attr); + intfPfxInfo.offset = getFreeTunnelRouteTableOffset(); attr.id = SAI_TABLE_BITMAP_ROUTER_ENTRY_ATTR_PRIORITY; - attr.value.u32 = getFreeTunnelRouteTableOffset(); + attr.value.u32 = intfPfxInfo.offset; route_attrs.push_back(attr); attr.id = SAI_TABLE_BITMAP_ROUTER_ENTRY_ATTR_IN_RIF_METADATA_KEY; @@ -705,7 +724,7 @@ bool VNetBitmapObject::addIntf(const string& alias, const IpPrefix *prefix) route_attrs.push_back(attr); status = sai_bmtor_api->create_table_bitmap_router_entry( - &tunnelRouteTableEntryId, + &intfPfxInfo.routeTableEntryId, gSwitchId, (uint32_t)route_attrs.size(), route_attrs.data()); @@ -715,6 +734,67 @@ bool VNetBitmapObject::addIntf(const string& alias, const IpPrefix *prefix) SWSS_LOG_ERROR("Failed to create local VNET route entry, SAI rc: %d", status); throw std::runtime_error("VNet interface creation failed"); } + + intf.pfxMap.emplace(*prefix, intfPfxInfo); + } + + return true; +} + +bool VNetBitmapObject::removeIntf(const string& alias, const IpPrefix *prefix) +{ + SWSS_LOG_ENTER(); + + sai_status_t status; + + if (intfMap_.find(alias) == intfMap_.end()) + { + SWSS_LOG_ERROR("VNET '%s' interface '%s' doesn't exist", getVnetName().c_str(), alias.c_str()); + return false; + } + + auto& intf = intfMap_.at(alias); + + if (prefix) + { + if (intf.pfxMap.find(*prefix) == intf.pfxMap.end()) + { + SWSS_LOG_ERROR("VNET '%s' interface '%s' prefix '%s' doesn't exist", + getVnetName().c_str(), alias.c_str(), prefix->getIp().to_string().c_str()); + return true; + } + + auto& pfx = intf.pfxMap.at(*prefix); + + status = sai_bmtor_api->remove_table_bitmap_router_entry(pfx.routeTableEntryId); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to remove VNET local route entry, SAI rc: %d", status); + throw std::runtime_error("VNET interface removal failed"); + } + + gIntfsOrch->removeIp2MeRoute(gVirtualRouterId, *prefix); + + recycleTunnelRouteTableOffset(pfx.offset); + + intf.pfxMap.erase(*prefix); + } + + if (intf.pfxMap.size() == 0) + { + status = sai_bmtor_api->remove_table_bitmap_classification_entry(intf.vnetTableEntryId); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to remove VNET table entry, SAI rc: %d", status); + throw std::runtime_error("VNET interface removal failed"); + } + + intfMap_.erase(alias); + + if (!gIntfsOrch->removeIntf(alias, gVirtualRouterId, nullptr)) + { + return false; + } } return true; @@ -1164,6 +1244,33 @@ bool VNetOrch::setIntf(const string& alias, const string name, const IpPrefix *p return false; } + +bool VNetOrch::delIntf(const string& alias, const string name, const IpPrefix *prefix) +{ + SWSS_LOG_ENTER(); + + if (!isVnetExists(name)) + { + SWSS_LOG_WARN("VNET %s doesn't exist", name.c_str()); + return false; + } + + if (isVnetExecVrf()) + { + auto *vnet_obj = getTypePtr(name); + sai_object_id_t vrf_id = vnet_obj->getVRidIngress(); + + return gIntfsOrch->removeIntf(alias, vrf_id, prefix); + } + else + { + auto *vnet_obj = getTypePtr(name); + return vnet_obj->removeIntf(alias, prefix); + } + + return true; +} + bool VNetOrch::addOperation(const Request& request) { SWSS_LOG_ENTER(); diff --git a/orchagent/vnetorch.h b/orchagent/vnetorch.h index 4ee4e64f35ff..6327913f07d1 100644 --- a/orchagent/vnetorch.h +++ b/orchagent/vnetorch.h @@ -195,12 +195,19 @@ struct RouteInfo uint32_t offset; }; +struct VnetIntfInfo +{ + sai_object_id_t vnetTableEntryId; + map pfxMap; +}; + class VNetBitmapObject: public VNetObject { public: VNetBitmapObject(const string& vnet, const VNetInfo& vnetInfo, vector& attrs); bool addIntf(const string& alias, const IpPrefix *prefix); + bool removeIntf(const string& alias, const IpPrefix *prefix); bool addTunnelRoute(IpPrefix& ipPrefix, tunnelEndpoint& endp); bool removeTunnelRoute(IpPrefix& ipPrefix); @@ -247,6 +254,7 @@ class VNetBitmapObject: public VNetObject map routeMap_; map tunnelRouteMap_; + map intfMap_; uint32_t vnet_id_; string vnet_name_; @@ -262,6 +270,7 @@ class VNetOrch : public Orch2 VNetOrch(DBConnector *db, const std::string&, VNET_EXEC op = VNET_EXEC::VNET_EXEC_VRF); bool setIntf(const string& alias, const string name, const IpPrefix *prefix = nullptr); + bool delIntf(const string& alias, const string name, const IpPrefix *prefix = nullptr); bool isVnetExists(const std::string& name) const {