From 1db930ad2a9b3e041f66434783252f423e2ed443 Mon Sep 17 00:00:00 2001 From: Prince Date: Thu, 24 Jan 2019 01:48:20 +0000 Subject: [PATCH 1/5] Route/NH and VNet delete handling --- orchagent/vnetorch.cpp | 221 ++++++++++++++++++++++++++++++++-------- orchagent/vnetorch.h | 48 +++++---- orchagent/vxlanorch.cpp | 179 +++++++++++++++++++++++++++++++- orchagent/vxlanorch.h | 65 ++++++++++++ 4 files changed, 446 insertions(+), 67 deletions(-) diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index 955eb24303..668ae0d57f 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -26,8 +26,8 @@ extern PortsOrch *gPortsOrch; */ std::vector vr_cntxt; -VNetVrfObject::VNetVrfObject(const std::string& vnet, string& tunnel, set& peer, - vector& attrs) : VNetObject(tunnel, peer) +VNetVrfObject::VNetVrfObject(const std::string& vnet, string& tunnel, set& peer, uint32_t vni, + vector& attrs) : VNetObject(tunnel, peer, vni) { vnet_name_ = vnet; createObj(attrs); @@ -120,6 +120,72 @@ bool VNetVrfObject::updateObj(vector& attrs) return true; } +bool VNetVrfObject::addRoute(IpPrefix& ipPrefix, tunnelEndpoint& endp) +{ + if (routes_.find(ipPrefix) != routes_.end()) + { + SWSS_LOG_INFO("VNET route '%s' exists", ipPrefix.to_string().c_str()); + return false; + } + + routes_[ipPrefix] = endp; + return true; +} + +bool VNetVrfObject::removeRoute(IpPrefix& ipPrefix) +{ + if (routes_.find(ipPrefix) == routes_.end()) + { + SWSS_LOG_INFO("VNET route '%s' does'nt exist", ipPrefix.to_string().c_str()); + return false; + } + + /* + * Remove nexthop tunnel object before removing route + */ + tunnelEndpoint endp = routes_.at(ipPrefix); + removeNextHop(endp); + + routes_.erase(ipPrefix); + return true; +} + +size_t VNetVrfObject::getRouteCount() const +{ + return routes_.size(); +} + +sai_object_id_t VNetVrfObject::getNextHop(tunnelEndpoint& endp) +{ + sai_object_id_t nh_id = SAI_NULL_OBJECT_ID; + auto tun_name = getTunnelName(); + + VxlanTunnelOrch* vxlan_orch = gDirectory.get(); + + nh_id = vxlan_orch->createNextHopTunnel(tun_name, endp.ip, endp.mac, endp.vni); + if (nh_id == SAI_NULL_OBJECT_ID) + { + throw std::runtime_error("NH Tunnel create failed for " + vnet_name_ + " ip " + endp.ip.to_string()); + } + + return nh_id; +} + +bool VNetVrfObject::removeNextHop(tunnelEndpoint& endp) +{ + auto tun_name = getTunnelName(); + + VxlanTunnelOrch* vxlan_orch = gDirectory.get(); + + if (!vxlan_orch->removeNextHopTunnel(tun_name, endp.ip, endp.mac, endp.vni)) + { + SWSS_LOG_ERROR("VNET %s NH remove failed for '%s'", vnet_name_.c_str(), endp.ip.to_string().c_str()); + return false; + } + + return true; +} + VNetVrfObject::~VNetVrfObject() { set vr_ent = getVRids(); @@ -142,9 +208,9 @@ VNetVrfObject::~VNetVrfObject() template std::unique_ptr VNetOrch::createObject(const string& vnet_name, string& tunnel, set& plist, - vector& attrs) + uint32_t vni, vector& attrs) { - std::unique_ptr vnet_obj(new T(vnet_name, tunnel, plist, attrs)); + std::unique_ptr vnet_obj(new T(vnet_name, tunnel, plist, vni, attrs)); return vnet_obj; } @@ -222,7 +288,7 @@ bool VNetOrch::addOperation(const Request& request) if (it == std::end(vnet_table_)) { - obj = createObject(vnet_name, tunnel, peer_list, attrs); + obj = createObject(vnet_name, tunnel, peer_list, vni, attrs); create = true; } @@ -279,9 +345,40 @@ bool VNetOrch::delOperation(const Request& request) return true; } + SWSS_LOG_INFO("VNET '%s' del request", vnet_name.c_str()); + + try + { + auto it = vnet_table_.find(vnet_name); + if (isVnetExecVrf()) + { + VxlanTunnelOrch* vxlan_orch = gDirectory.get(); + VNetVrfObject *vrf_obj = dynamic_cast(it->second.get()); + + if (vrf_obj->getRouteCount()) + { + SWSS_LOG_ERROR("VNET '%s': Routes are still present", vnet_name.c_str()); + return false; + } + + if (!vxlan_orch->removeVxlanTunnelMap(vrf_obj->getTunnelName(), vrf_obj->getVni())) + { + SWSS_LOG_ERROR("VNET '%s' map delete failed", vnet_name.c_str()); + } + } + else + { + // BRIDGE Handling + } + } + catch(std::runtime_error& _) + { + SWSS_LOG_ERROR("VNET del operation error for %s: error %s ", vnet_name.c_str(), _.what()); + return false; + } + vnet_table_.erase(vnet_name); - SWSS_LOG_INFO("VNET '%s' del request", vnet_name.c_str()); return true; } @@ -289,6 +386,23 @@ bool VNetOrch::delOperation(const Request& request) * Vnet Route Handling */ +static bool del_route(sai_object_id_t vr_id, sai_ip_prefix_t& ip_pfx) +{ + sai_route_entry_t route_entry; + route_entry.vr_id = vr_id; + route_entry.switch_id = gSwitchId; + route_entry.destination = ip_pfx; + + sai_status_t status = sai_route_api->remove_route_entry(&route_entry); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("SAI Failed to remove route"); + return false; + } + + return true; +} + static bool add_route(sai_object_id_t vr_id, sai_ip_prefix_t& ip_pfx, sai_object_id_t nh_id) { sai_route_entry_t route_entry; @@ -320,34 +434,9 @@ VNetRouteOrch::VNetRouteOrch(DBConnector *db, vector &tableNames, VNetOr handler_map_.insert(handler_pair(APP_VNET_RT_TUNNEL_TABLE_NAME, &VNetRouteOrch::handleTunnel)); } -sai_object_id_t VNetRouteOrch::getNextHop(const string& vnet, tunnelEndpoint& endp) -{ - auto it = nh_tunnels_.find(vnet); - if (it != nh_tunnels_.end()) - { - if (it->second.find(endp.ip) != it->second.end()) - { - return it->second.at(endp.ip); - } - } - - sai_object_id_t nh_id = SAI_NULL_OBJECT_ID; - auto tun_name = vnet_orch_->getTunnelName(vnet); - - VxlanTunnelOrch* vxlan_orch = gDirectory.get(); - - nh_id = vxlan_orch->createNextHopTunnel(tun_name, endp.ip, endp.mac, endp.vni); - if (nh_id == SAI_NULL_OBJECT_ID) - { - throw std::runtime_error("NH Tunnel create failed for " + vnet + " ip " + endp.ip.to_string()); - } - - nh_tunnels_[vnet].insert({endp.ip, nh_id}); - return nh_id; -} - template<> -bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipPrefix, tunnelEndpoint& endp) +bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipPrefix, + tunnelEndpoint& endp, string& op) { SWSS_LOG_ENTER(); @@ -377,23 +466,40 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP l_fn(peer); } + auto *vrf_obj = vnet_orch_->getTypePtr(vnet); sai_ip_prefix_t pfx; copy(pfx, ipPrefix); - sai_object_id_t nh_id = getNextHop(vnet, endp); + sai_object_id_t nh_id = (op == SET_COMMAND)?vrf_obj->getNextHop(endp):SAI_NULL_OBJECT_ID; for (auto vr_id : vr_set) { - if(!add_route(vr_id, pfx, nh_id)) + if (op == SET_COMMAND && !add_route(vr_id, pfx, nh_id)) { - SWSS_LOG_ERROR("Route add failed for %s", ipPrefix.to_string().c_str()); - break; + SWSS_LOG_ERROR("Route add failed for %s, vr_id '0x%lx", ipPrefix.to_string().c_str(), vr_id); + return false; + } + else if (op == DEL_COMMAND && !del_route(vr_id, pfx)) + { + SWSS_LOG_ERROR("Route del failed for %s, vr_id '0x%lx", ipPrefix.to_string().c_str(), vr_id); + return false; } } + + if (op == SET_COMMAND) + { + vrf_obj->addRoute(ipPrefix, endp); + } + else + { + vrf_obj->removeRoute(ipPrefix); + } + return true; } template<> -bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipPrefix, string& ifname) +bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipPrefix, + string& ifname, string& op) { SWSS_LOG_ENTER(); @@ -404,7 +510,7 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP } Port p; - if (!gPortsOrch->getPort(ifname, p) || (p.m_rif_id == SAI_NULL_OBJECT_ID)) + if (!ifname.empty() && (!gPortsOrch->getPort(ifname, p) || (p.m_rif_id == SAI_NULL_OBJECT_ID))) { SWSS_LOG_WARN("Port/RIF %s doesn't exist", ifname.c_str()); return false; @@ -436,11 +542,16 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP for (auto vr_id : vr_set) { - if(!add_route(vr_id, pfx, p.m_rif_id )) + if (op == SET_COMMAND && !add_route(vr_id, pfx, p.m_rif_id)) { SWSS_LOG_ERROR("Route add failed for %s", ipPrefix.to_string().c_str()); break; } + else if (op == DEL_COMMAND && !del_route(vr_id, pfx)) + { + SWSS_LOG_ERROR("Route del failed for %s", ipPrefix.to_string().c_str()); + break; + } } return true; @@ -467,12 +578,14 @@ void VNetRouteOrch::handleRoutes(const Request& request) const std::string& vnet_name = request.getKeyString(0); auto ip_pfx = request.getKeyIpPrefix(1); + auto op = request.getOperation(); - SWSS_LOG_INFO("VNET-RT '%s' add for ip %s", vnet_name.c_str(), ip_pfx.to_string().c_str()); + SWSS_LOG_INFO("VNET-RT '%s' op '%s' for ip %s", vnet_name.c_str(), + op.c_str(), ip_pfx.to_string().c_str()); if (vnet_orch_->isVnetExecVrf()) { - if (!doRouteTask(vnet_name, ip_pfx, ifname)) + if (!doRouteTask(vnet_name, ip_pfx, ifname, op)) { throw std::runtime_error("Route add failed"); } @@ -510,13 +623,16 @@ void VNetRouteOrch::handleTunnel(const Request& request) const std::string& vnet_name = request.getKeyString(0); auto ip_pfx = request.getKeyIpPrefix(1); + auto op = request.getOperation(); - SWSS_LOG_INFO("VNET-RT '%s' add for endpoint %s", vnet_name.c_str(), ip_pfx.to_string().c_str()); + SWSS_LOG_INFO("VNET-RT '%s' op '%s' for pfx %s", vnet_name.c_str(), + op.c_str(), ip_pfx.to_string().c_str()); tunnelEndpoint endp = { ip, mac, vni }; + if (vnet_orch_->isVnetExecVrf()) { - if (!doRouteTask(vnet_name, ip_pfx, endp)) + if (!doRouteTask(vnet_name, ip_pfx, endp, op)) { throw std::runtime_error("Route add failed"); } @@ -551,7 +667,22 @@ bool VNetRouteOrch::delOperation(const Request& request) { SWSS_LOG_ENTER(); - SWSS_LOG_ERROR("DEL operation is not implemented"); + try + { + auto& tn = request.getTableName(); + if (handler_map_.find(tn) == handler_map_.end()) + { + SWSS_LOG_ERROR(" %s handler is not initialized", tn.c_str()); + return true; + } + + (this->*(handler_map_[tn]))(request); + } + catch(std::runtime_error& _) + { + SWSS_LOG_ERROR("VNET del operation error %s ", _.what()); + return false; + } return true; } diff --git a/orchagent/vnetorch.h b/orchagent/vnetorch.h index b6939d3770..988983eda3 100644 --- a/orchagent/vnetorch.h +++ b/orchagent/vnetorch.h @@ -17,6 +17,7 @@ const request_description_t vnet_request_description = { { "vxlan_tunnel", REQ_T_STRING }, { "vni", REQ_T_UINT }, { "peer_list", REQ_T_SET }, + { "guid", REQ_T_STRING }, }, { "vxlan_tunnel", "vni" } // mandatory attributes }; @@ -47,7 +48,7 @@ class VNetRequest : public Request class VNetObject { public: - VNetObject(string& tunName, set& peer) : tunnel_(tunName), peer_list_(peer) { } + VNetObject(string& tunName, set& peer, uint32_t vni) : tunnel_(tunName), peer_list_(peer), vni_(vni) { } virtual sai_object_id_t getEncapMapId() const = 0; @@ -72,17 +73,32 @@ class VNetObject return tunnel_; } + uint32_t getVni() const + { + return vni_; + } + virtual ~VNetObject() {}; private: set peer_list_ = {}; string tunnel_; + uint32_t vni_; +}; + +struct tunnelEndpoint +{ + IpAddress ip; + MacAddress mac; + uint32_t vni; }; +typedef std::map RouteMap; + class VNetVrfObject : public VNetObject { public: - VNetVrfObject(const string& vnet, string& tunnel, set& peer, vector& attrs); + VNetVrfObject(const string& vnet, string& tunnel, set& peer, uint32_t vni, vector& attrs); sai_object_id_t getVRidIngress() const; @@ -109,11 +125,20 @@ class VNetVrfObject : public VNetObject bool updateObj(vector&); + bool addRoute(IpPrefix& ipPrefix, tunnelEndpoint& endp); + bool removeRoute(IpPrefix& ipPrefix); + size_t getRouteCount() const; + + sai_object_id_t getNextHop(tunnelEndpoint& endp); + bool removeNextHop(tunnelEndpoint& endp); + ~VNetVrfObject(); private: string vnet_name_; vrid_list_t vr_ids_; + + RouteMap routes_; }; typedef std::unique_ptr VNetObject_T; @@ -175,7 +200,7 @@ class VNetOrch : public Orch2 virtual bool delOperation(const Request& request); template - std::unique_ptr createObject(const string&, string&, set&, vector&); + std::unique_ptr createObject(const string&, string&, set&, uint32_t, vector&); VNetTable vnet_table_; VNetRequest request_; @@ -200,16 +225,6 @@ class VNetRouteRequest : public Request VNetRouteRequest() : Request(vnet_route_description, ':') { } }; -typedef map NextHopMap; -typedef map NextHopTunnels; - -struct tunnelEndpoint -{ - IpAddress ip; - MacAddress mac; - uint32_t vni; -}; - class VNetRouteOrch : public Orch2 { public: @@ -226,17 +241,14 @@ class VNetRouteOrch : public Orch2 void handleTunnel(const Request&); template - bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, tunnelEndpoint& endp); + bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, tunnelEndpoint& endp, string& op); template - bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, string& ifname); - - sai_object_id_t getNextHop(const string& vnet, tunnelEndpoint& endp); + bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, string& ifname, string& op); VNetOrch *vnet_orch_; VNetRouteRequest request_; handler_map handler_map_; - NextHopTunnels nh_tunnels_; }; #endif // __VNETORCH_H diff --git a/orchagent/vxlanorch.cpp b/orchagent/vxlanorch.cpp index 997920db6f..274c9b0545 100644 --- a/orchagent/vxlanorch.cpp +++ b/orchagent/vxlanorch.cpp @@ -155,6 +155,21 @@ static sai_object_id_t create_tunnel_map_entry( return tunnel_map_entry_id; } +void remove_tunnel_map_entry(sai_object_id_t obj_id) +{ + sai_status_t status = SAI_STATUS_SUCCESS; + + if (obj_id== SAI_NULL_OBJECT_ID) + { + status = sai_tunnel_api->remove_tunnel_map_entry(obj_id); + } + + if (status != SAI_STATUS_SUCCESS) + { + throw std::runtime_error("Can't delete a tunnel map entry object"); + } +} + static sai_status_t create_nexthop_tunnel( sai_ip_address_t host_ip, sai_uint32_t vni, // optional vni @@ -371,15 +386,111 @@ sai_object_id_t VxlanTunnel::addDecapMapperEntry(sai_object_id_t obj, uint32_t v return create_tunnel_map_entry(map_t, decap_id, vni, 0, obj); } +void VxlanTunnel::insertMapperEntry(sai_object_id_t encap, sai_object_id_t decap, uint32_t vni) +{ + tunnel_map_entries_[vni] = std::pair(encap, decap); +} + +std::pair VxlanTunnel::getMapperEntry(uint32_t vni) +{ + if (tunnel_map_entries_.find(vni) != tunnel_map_entries_.end()) + { + return tunnel_map_entries_[vni]; + } + + return std::make_pair(SAI_NULL_OBJECT_ID, SAI_NULL_OBJECT_ID); +} + +void VxlanTunnel::updateNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni, sai_object_id_t nh_id) +{ + auto key = nh_key_t(ipAddr, macAddress, vni); + + auto it = nh_tunnels_.find(key); + if (it == nh_tunnels_.end()) + { + nh_tunnels_[key] = {nh_id, 1}; + return; + } +} + +sai_object_id_t VxlanTunnel::getNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) const +{ + auto key = nh_key_t(ipAddr, macAddress, vni); + + auto it = nh_tunnels_.find(key); + if (it == nh_tunnels_.end()) + { + return SAI_NULL_OBJECT_ID; + } + + return nh_tunnels_.at(key).nh_id; +} + +void VxlanTunnel::incNHTunnelRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) +{ + auto key = nh_key_t(ipAddr, macAddress, vni); + nh_tunnels_[key].ref_count ++; +} + +void VxlanTunnel::decNHTunnelRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) +{ + auto key = nh_key_t(ipAddr, macAddress, vni); + nh_tunnels_[key].ref_count --; +} + +bool VxlanTunnel::removeNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) +{ + auto key = nh_key_t(ipAddr, macAddress, vni); + + auto it = nh_tunnels_.find(key); + if (it == nh_tunnels_.end()) + { + SWSS_LOG_INFO("NH tunnel for '%s' doesn't exist", ipAddr.to_string().c_str()); + return false; + } + + SWSS_LOG_INFO("NH tunnel for ip '%s' ref_count '%d'", ipAddr.to_string().c_str(), nh_tunnels_[key].ref_count); + + //Decrement ref count if already exists + nh_tunnels_[key].ref_count --; + + if (!nh_tunnels_[key].ref_count) + { + if (sai_next_hop_api->remove_next_hop(nh_tunnels_[key].nh_id) != SAI_STATUS_SUCCESS) + { + string err_msg = "NH tunnel delete failed for " + ipAddr.to_string(); + throw std::runtime_error(err_msg); + } + + nh_tunnels_.erase(key); + } + + SWSS_LOG_INFO("NH tunnel for ip '%s', mac '%s' updated/deleted", + ipAddr.to_string().c_str(), macAddress.to_string().c_str()); + + return true; +} + sai_object_id_t VxlanTunnelOrch::createNextHopTunnel(string tunnelName, IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) { + SWSS_LOG_ENTER(); + if(!isTunnelExists(tunnelName)) { SWSS_LOG_ERROR("Vxlan tunnel '%s' does not exists", tunnelName.c_str()); return SAI_NULL_OBJECT_ID; } + auto tunnel_obj = getVxlanTunnel(tunnelName); + sai_object_id_t nh_id, tunnel_id = tunnel_obj->getTunnelId(); + + if ((nh_id = tunnel_obj->getNHTunnel(ipAddr, macAddress, vni)) != SAI_NULL_OBJECT_ID) + { + tunnel_obj->incNHTunnelRefCount(ipAddr, macAddress, vni); + return nh_id; + } + sai_ip_address_t host_ip; swss::copy(host_ip, ipAddr); @@ -390,20 +501,36 @@ VxlanTunnelOrch::createNextHopTunnel(string tunnelName, IpAddress& ipAddr, MacAd macptr = &mac; } - auto tunnel_obj = getVxlanTunnel(tunnelName); - - sai_object_id_t nh_id, tunnel_id = tunnel_obj->getTunnelId(); - if (create_nexthop_tunnel(host_ip, vni, macptr, tunnel_id, &nh_id) != SAI_STATUS_SUCCESS) { string err_msg = "NH tunnel create failed for " + ipAddr.to_string() + " " + to_string(vni); throw std::runtime_error(err_msg); } + //Store the nh tunnel id + tunnel_obj->updateNHTunnel(ipAddr, macAddress, vni, nh_id); + SWSS_LOG_INFO("NH vxlan tunnel was created for %s, id 0x%lx", tunnelName.c_str(), nh_id); return nh_id; } +bool +VxlanTunnelOrch::removeNextHopTunnel(string tunnelName, IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) +{ + SWSS_LOG_ENTER(); + + if(!isTunnelExists(tunnelName)) + { + SWSS_LOG_ERROR("Vxlan tunnel '%s' does not exists", tunnelName.c_str()); + return true; + } + + auto tunnel_obj = getVxlanTunnel(tunnelName); + + //Delete request for the nh tunnel id + return tunnel_obj->removeNHTunnel(ipAddr, macAddress, vni); +} + bool VxlanTunnelOrch::createVxlanTunnelMap(string tunnelName, tunnel_map_type_t map, uint32_t vni, sai_object_id_t encap, sai_object_id_t decap) { @@ -437,6 +564,8 @@ bool VxlanTunnelOrch::createVxlanTunnelMap(string tunnelName, tunnel_map_type_t auto encap_id = tunnel_obj->addEncapMapperEntry(encap, vni); auto decap_id = tunnel_obj->addDecapMapperEntry(decap, vni); + tunnel_obj->insertMapperEntry(encap_id, decap_id, vni); + SWSS_LOG_DEBUG("Vxlan tunnel encap entry '%lx' decap entry '0x%lx'", encap_id, decap_id); } catch(const std::runtime_error& error) @@ -450,6 +579,48 @@ bool VxlanTunnelOrch::createVxlanTunnelMap(string tunnelName, tunnel_map_type_t return true; } +bool VxlanTunnelOrch::removeVxlanTunnelMap(string tunnelName, uint32_t vni) +{ + SWSS_LOG_ENTER(); + + if(!isTunnelExists(tunnelName)) + { + SWSS_LOG_ERROR("Vxlan tunnel '%s' does not exists", tunnelName.c_str()); + return false; + } + + auto tunnel_obj = getVxlanTunnel(tunnelName); + + if (!tunnel_obj->isActive()) + { + SWSS_LOG_ERROR("Vxlan tunnel '%s' is not Active", tunnelName.c_str()); + return false; + } + + try + { + /* + * Delete encap and decap mapper + */ + + std::pair mapper = tunnel_obj->getMapperEntry(vni); + + remove_tunnel_map_entry(mapper.first); + remove_tunnel_map_entry(mapper.second); + + SWSS_LOG_DEBUG("Vxlan tunnel encap entry '%lx' decap entry '0x%lx'", mapper.first, mapper.second); + } + catch(const std::runtime_error& error) + { + SWSS_LOG_ERROR("Error removing tunnel map entry. Tunnel: %s. Error: %s", + tunnelName.c_str(), error.what()); + return false; + } + + SWSS_LOG_NOTICE("Vxlan map entry deleted for tunnel '%s' with vni '%d'", tunnelName.c_str(), vni); + return true; +} + bool VxlanTunnelOrch::addOperation(const Request& request) { SWSS_LOG_ENTER(); diff --git a/orchagent/vxlanorch.h b/orchagent/vxlanorch.h index f5e3774e7d..30437f6b11 100644 --- a/orchagent/vxlanorch.h +++ b/orchagent/vxlanorch.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include "request_parser.h" @@ -26,6 +27,52 @@ struct tunnel_ids_t sai_object_id_t tunnel_term_id; }; +struct nh_key_t +{ + IpAddress ip_addr; + MacAddress mac_address; + uint32_t vni=0; + + nh_key_t() = default; + + nh_key_t(IpAddress ipAddr, MacAddress macAddress=MacAddress(), uint32_t vnId=0) + { + ip_addr = ipAddr; + mac_address = macAddress; + vni = vnId; + }; + + bool operator== (const nh_key_t& rhs) const + { + if (!(ip_addr == rhs.ip_addr) || mac_address != rhs.mac_address || vni != rhs.vni) + { + return false; + } + return true; + } + + +}; + +struct nh_key_hash +{ + size_t operator() (const nh_key_t& key) const + { + stringstream ss; + ss << key.ip_addr.to_string() << key.mac_address.to_string() << std::to_string(key.vni); + return std::hash() (ss.str()); + } +}; + +struct nh_tunnel_t +{ + sai_object_id_t nh_id; + int ref_count; +}; + +typedef std::map> TunnelMapEntries; +typedef std::unordered_map TunnelNHs; + class VxlanTunnel { public: @@ -41,6 +88,9 @@ class VxlanTunnel sai_object_id_t addEncapMapperEntry(sai_object_id_t obj, uint32_t vni); sai_object_id_t addDecapMapperEntry(sai_object_id_t obj, uint32_t vni); + void insertMapperEntry(sai_object_id_t encap, sai_object_id_t decap, uint32_t vni); + std::pair getMapperEntry(uint32_t vni); + sai_object_id_t getTunnelId() const { return ids_.tunnel_id; @@ -56,6 +106,13 @@ class VxlanTunnel return ids_.tunnel_encap_id; } + void updateNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni, sai_object_id_t nh_id); + bool removeNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni); + sai_object_id_t getNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) const; + + void incNHTunnelRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni); + void decNHTunnelRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni); + private: string tunnel_name_; bool active_ = false; @@ -63,6 +120,9 @@ class VxlanTunnel tunnel_ids_t ids_; std::pair tunnel_map_ = { MAP_T::MAP_TO_INVALID, MAP_T::MAP_TO_INVALID }; + TunnelMapEntries tunnel_map_entries_; + TunnelNHs nh_tunnels_; + IpAddress src_ip_; IpAddress dst_ip_ = 0x0; }; @@ -110,9 +170,14 @@ class VxlanTunnelOrch : public Orch2 bool createVxlanTunnelMap(string tunnelName, tunnel_map_type_t mapType, uint32_t vni, sai_object_id_t encap, sai_object_id_t decap); + bool removeVxlanTunnelMap(string tunnelName, uint32_t vni); + sai_object_id_t createNextHopTunnel(string tunnelName, IpAddress& ipAddr, MacAddress macAddress, uint32_t vni=0); + bool + removeNextHopTunnel(string tunnelName, IpAddress& ipAddr, MacAddress macAddress, uint32_t vni=0); + private: virtual bool addOperation(const Request& request); virtual bool delOperation(const Request& request); From 59f24985e86d81547fd0c87dfd93effab03915fe Mon Sep 17 00:00:00 2001 From: Prince Date: Sat, 26 Jan 2019 03:36:06 +0000 Subject: [PATCH 2/5] Handle VNET Route with Nexthop IP, fix route remove --- orchagent/vnetorch.cpp | 134 +++++++++++++++++++++++++++++++++++------ orchagent/vnetorch.h | 18 +++++- 2 files changed, 130 insertions(+), 22 deletions(-) diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index 5dcc42a5d4..390aa5db97 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -15,6 +15,7 @@ #include "directory.h" #include "swssnet.h" #include "intfsorch.h" +#include "neighorch.h" extern sai_virtual_router_api_t* sai_virtual_router_api; extern sai_route_api_t* sai_route_api; @@ -22,6 +23,7 @@ extern sai_object_id_t gSwitchId; extern Directory gDirectory; extern PortsOrch *gPortsOrch; extern IntfsOrch *gIntfsOrch; +extern NeighOrch *gNeighOrch; /* * VRF Modeling and VNetVrf class definitions @@ -122,39 +124,79 @@ bool VNetVrfObject::updateObj(vector& attrs) return true; } +bool VNetVrfObject::hasRoute(IpPrefix& ipPrefix) +{ + if ((routes_.find(ipPrefix) != routes_.end()) || (tunnels_.find(ipPrefix) != tunnels_.end())) + { + return true; + } + + return false; +} + bool VNetVrfObject::addRoute(IpPrefix& ipPrefix, tunnelEndpoint& endp) { - if (routes_.find(ipPrefix) != routes_.end()) + if (hasRoute(ipPrefix)) + { + SWSS_LOG_INFO("VNET route '%s' exists", ipPrefix.to_string().c_str()); + return false; + } + + tunnels_[ipPrefix] = endp; + return true; +} + +bool VNetVrfObject::addRoute(IpPrefix& ipPrefix, nextHop& nh) +{ + if (hasRoute(ipPrefix)) { SWSS_LOG_INFO("VNET route '%s' exists", ipPrefix.to_string().c_str()); return false; } - routes_[ipPrefix] = endp; + routes_[ipPrefix] = nh; return true; } bool VNetVrfObject::removeRoute(IpPrefix& ipPrefix) { - if (routes_.find(ipPrefix) == routes_.end()) + if (!hasRoute(ipPrefix)) { SWSS_LOG_INFO("VNET route '%s' does'nt exist", ipPrefix.to_string().c_str()); return false; } - /* * Remove nexthop tunnel object before removing route */ - tunnelEndpoint endp = routes_.at(ipPrefix); - removeNextHop(endp); - routes_.erase(ipPrefix); + if (tunnels_.find(ipPrefix) != tunnels_.end()) + { + auto endp = tunnels_.at(ipPrefix); + removeNextHop(endp); + tunnels_.erase(ipPrefix); + } + else + { + routes_.erase(ipPrefix); + } return true; } size_t VNetVrfObject::getRouteCount() const { - return routes_.size(); + return (routes_.size() + tunnels_.size()); +} + +bool VNetVrfObject::getRouteNH(IpPrefix& ipPrefix, nextHop& nh) +{ + if (!hasRoute(ipPrefix)) + { + SWSS_LOG_INFO("VNET route '%s' does'nt exist", ipPrefix.to_string().c_str()); + return false; + } + + nh = routes_.at(ipPrefix); + return true; } sai_object_id_t VNetVrfObject::getNextHop(tunnelEndpoint& endp) @@ -314,9 +356,9 @@ bool VNetOrch::addOperation(const Request& request) create = true; } - VNetVrfObject *vrfObj = dynamic_cast(obj.get()); + VNetVrfObject *vrf_obj = dynamic_cast(obj.get()); if (!vxlan_orch->createVxlanTunnelMap(tunnel, TUNNEL_MAP_T_VIRTUAL_ROUTER, vni, - vrfObj->getEncapMapId(), vrfObj->getDecapMapId())) + vrf_obj->getEncapMapId(), vrf_obj->getDecapMapId())) { SWSS_LOG_ERROR("VNET '%s', tunnel '%s', map create failed", vnet_name.c_str(), tunnel.c_str()); @@ -522,7 +564,7 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP template<> bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipPrefix, - string& ifname, string& op) + nextHop& nh, string& op) { SWSS_LOG_ENTER(); @@ -532,17 +574,42 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP return false; } - Port p; - if (!ifname.empty() && (!gPortsOrch->getPort(ifname, p) || (p.m_rif_id == SAI_NULL_OBJECT_ID))) + auto *vrf_obj = vnet_orch_->getTypePtr(vnet); + if (op == DEL_COMMAND && !vrf_obj->getRouteNH(ipPrefix, nh)) { - SWSS_LOG_WARN("Port/RIF %s doesn't exist", ifname.c_str()); + SWSS_LOG_WARN("VNET %s, Route %s get NH failed", vnet.c_str(), ipPrefix.to_string().c_str()); + return true; + } + + Port port; + if ((!gPortsOrch->getPort(nh.ifname, port) || (port.m_rif_id == SAI_NULL_OBJECT_ID))) + { + SWSS_LOG_WARN("Port/RIF %s doesn't exist", nh.ifname.c_str()); return false; } + bool subnet = (nh.ip.isZero())?true:false; set vr_set; auto& peer_list = vnet_orch_->getPeerList(vnet); - auto *vnet_obj = vnet_orch_->getTypePtr(vnet); - vr_set.insert(vnet_obj->getVRidEgress()); + auto vr_id = vrf_obj->getVRidIngress(); + + /* + * If RIF doesn't belong to this VRF, and if it is a replicated subnet + * route for the peering VRF, Only install in ingress VRF. + */ + + if (!subnet) + { + vr_set = vrf_obj->getVRids(); + } + else if (vr_id == port.m_vr_id) + { + vr_set.insert(vrf_obj->getVRidEgress()); + } + else + { + vr_set.insert(vr_id); + } auto l_fn = [&] (const string& vnet) { auto *vnet_obj = vnet_orch_->getTypePtr(vnet); @@ -562,10 +629,22 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP sai_ip_prefix_t pfx; copy(pfx, ipPrefix); + sai_object_id_t nh_id=port.m_rif_id; + + if (!subnet && gNeighOrch->hasNextHop(nh.ip)) + { + nh_id = gNeighOrch->getNextHopId(nh.ip); + } + else if (!subnet) + { + SWSS_LOG_INFO("Failed to get next hop %s for %s", + nh.ip.to_string().c_str(), ipPrefix.to_string().c_str()); + return false; + } for (auto vr_id : vr_set) { - if (op == SET_COMMAND && !add_route(vr_id, pfx, p.m_rif_id)) + if (op == SET_COMMAND && !add_route(vr_id, pfx, nh_id)) { SWSS_LOG_ERROR("Route add failed for %s", ipPrefix.to_string().c_str()); break; @@ -577,6 +656,15 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP } } + if (op == SET_COMMAND) + { + vrf_obj->addRoute(ipPrefix, nh); + } + else + { + vrf_obj->removeRoute(ipPrefix); + } + return true; } @@ -584,6 +672,7 @@ void VNetRouteOrch::handleRoutes(const Request& request) { SWSS_LOG_ENTER(); + IpAddress ip("0.0.0.0"); string ifname = ""; for (const auto& name: request.getAttrFieldNames()) @@ -592,6 +681,10 @@ void VNetRouteOrch::handleRoutes(const Request& request) { ifname = request.getAttrString(name); } + else if (name == "nexthop") + { + ip = request.getAttrIP(name); + } else { SWSS_LOG_WARN("Logic error: Unknown attribute: %s", name.c_str()); @@ -602,15 +695,16 @@ void VNetRouteOrch::handleRoutes(const Request& request) const std::string& vnet_name = request.getKeyString(0); auto ip_pfx = request.getKeyIpPrefix(1); auto op = request.getOperation(); + nextHop nh = { ip, ifname }; SWSS_LOG_INFO("VNET-RT '%s' op '%s' for ip %s", vnet_name.c_str(), op.c_str(), ip_pfx.to_string().c_str()); if (vnet_orch_->isVnetExecVrf()) { - if (!doRouteTask(vnet_name, ip_pfx, ifname, op)) + if (!doRouteTask(vnet_name, ip_pfx, nh, op)) { - throw std::runtime_error("Route add failed"); + throw std::runtime_error("Route update failed"); } } } @@ -657,7 +751,7 @@ void VNetRouteOrch::handleTunnel(const Request& request) { if (!doRouteTask(vnet_name, ip_pfx, endp, op)) { - throw std::runtime_error("Route add failed"); + throw std::runtime_error("Route update failed"); } } } diff --git a/orchagent/vnetorch.h b/orchagent/vnetorch.h index c9604ae0c3..7ffaadef60 100644 --- a/orchagent/vnetorch.h +++ b/orchagent/vnetorch.h @@ -87,7 +87,14 @@ struct tunnelEndpoint uint32_t vni; }; -typedef std::map RouteMap; +struct nextHop +{ + IpAddress ip; + string ifname; +}; + +typedef std::map TunnelRoutes; +typedef std::map RouteMap; class VNetVrfObject : public VNetObject { @@ -120,8 +127,12 @@ class VNetVrfObject : public VNetObject bool updateObj(vector&); bool addRoute(IpPrefix& ipPrefix, tunnelEndpoint& endp); + bool addRoute(IpPrefix& ipPrefix, nextHop& nh); bool removeRoute(IpPrefix& ipPrefix); + size_t getRouteCount() const; + bool getRouteNH(IpPrefix& ipPrefix, nextHop& nh); + bool hasRoute(IpPrefix& ipPrefix); sai_object_id_t getNextHop(tunnelEndpoint& endp); bool removeNextHop(tunnelEndpoint& endp); @@ -132,6 +143,7 @@ class VNetVrfObject : public VNetObject string vnet_name_; vrid_list_t vr_ids_; + TunnelRoutes tunnels_; RouteMap routes_; }; @@ -142,6 +154,7 @@ class VNetOrch : public Orch2 { public: VNetOrch(DBConnector *db, const std::string&, VNET_EXEC op = VNET_EXEC::VNET_EXEC_VRF); + bool setIntf(const string& alias, const string vnet_name, const IpPrefix *prefix = nullptr); bool isVnetExists(const std::string& name) const @@ -193,6 +206,7 @@ const request_description_t vnet_route_description = { { { "endpoint", REQ_T_IP }, { "ifname", REQ_T_STRING }, + { "nexthop", REQ_T_IP }, { "vni", REQ_T_UINT }, { "mac_address", REQ_T_MAC_ADDRESS }, }, @@ -224,7 +238,7 @@ class VNetRouteOrch : public Orch2 bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, tunnelEndpoint& endp, string& op); template - bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, string& ifname, string& op); + bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, nextHop& nh, string& op); VNetOrch *vnet_orch_; VNetRouteRequest request_; From e21e20202a35103c74c2e053beb1c7669c989f78 Mon Sep 17 00:00:00 2001 From: Prince Date: Tue, 29 Jan 2019 22:58:36 +0000 Subject: [PATCH 3/5] Interface delete fix, base changes for multiple nexthops --- orchagent/intfsorch.cpp | 1 + orchagent/vnetorch.cpp | 50 +++++++++++++++++++++++++++-------------- orchagent/vnetorch.h | 5 +++-- orchagent/vxlanorch.cpp | 2 +- orchagent/vxlanorch.h | 2 -- 5 files changed, 38 insertions(+), 22 deletions(-) diff --git a/orchagent/intfsorch.cpp b/orchagent/intfsorch.cpp index 4006d48511..359835dbcb 100644 --- a/orchagent/intfsorch.cpp +++ b/orchagent/intfsorch.cpp @@ -155,6 +155,7 @@ bool IntfsOrch::setIntf(const string& alias, sai_object_id_t vrf_id, const IpPre return false; } + vrf_id = port.m_vr_id; addSubnetRoute(port, *ip_prefix); addIp2MeRoute(vrf_id, *ip_prefix); diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index 390aa5db97..ee5d0ae281 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -328,7 +328,7 @@ bool VNetOrch::addOperation(const Request& request) } else { - SWSS_LOG_WARN("Logic error: Unknown attribute: %s", name.c_str()); + SWSS_LOG_INFO("Unknown attribute: %s", name.c_str()); continue; } } @@ -581,14 +581,15 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP return true; } + bool subnet = (!nh.ips.getSize())?true:false; + Port port; - if ((!gPortsOrch->getPort(nh.ifname, port) || (port.m_rif_id == SAI_NULL_OBJECT_ID))) + if (subnet && (!gPortsOrch->getPort(nh.ifname, port) || (port.m_rif_id == SAI_NULL_OBJECT_ID))) { SWSS_LOG_WARN("Port/RIF %s doesn't exist", nh.ifname.c_str()); return false; } - bool subnet = (nh.ip.isZero())?true:false; set vr_set; auto& peer_list = vnet_orch_->getPeerList(vnet); auto vr_id = vrf_obj->getVRidIngress(); @@ -629,17 +630,31 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP sai_ip_prefix_t pfx; copy(pfx, ipPrefix); - sai_object_id_t nh_id=port.m_rif_id; + sai_object_id_t nh_id=SAI_NULL_OBJECT_ID; - if (!subnet && gNeighOrch->hasNextHop(nh.ip)) + if (subnet) { - nh_id = gNeighOrch->getNextHopId(nh.ip); + nh_id = port.m_rif_id; } - else if (!subnet) + else if (nh.ips.getSize() == 1) { - SWSS_LOG_INFO("Failed to get next hop %s for %s", - nh.ip.to_string().c_str(), ipPrefix.to_string().c_str()); - return false; + IpAddress ip_address(nh.ips.to_string()); + if (gNeighOrch->hasNextHop(ip_address)) + { + nh_id = gNeighOrch->getNextHopId(ip_address); + } + else + { + SWSS_LOG_INFO("Failed to get next hop %s for %s", + ip_address.to_string().c_str(), ipPrefix.to_string().c_str()); + return false; + } + } + else + { + // FIXME - Handle ECMP routes + SWSS_LOG_WARN("VNET ECMP NHs not implemented for '%s'", ipPrefix.to_string().c_str()); + return true; } for (auto vr_id : vr_set) @@ -672,7 +687,7 @@ void VNetRouteOrch::handleRoutes(const Request& request) { SWSS_LOG_ENTER(); - IpAddress ip("0.0.0.0"); + IpAddresses ip_addresses; string ifname = ""; for (const auto& name: request.getAttrFieldNames()) @@ -683,19 +698,20 @@ void VNetRouteOrch::handleRoutes(const Request& request) } else if (name == "nexthop") { - ip = request.getAttrIP(name); + auto ipstr = request.getAttrString(name); + ip_addresses = IpAddresses(ipstr); } else { - SWSS_LOG_WARN("Logic error: Unknown attribute: %s", name.c_str()); - return; + SWSS_LOG_INFO("Unknown attribute: %s", name.c_str()); + continue; } } const std::string& vnet_name = request.getKeyString(0); auto ip_pfx = request.getKeyIpPrefix(1); auto op = request.getOperation(); - nextHop nh = { ip, ifname }; + nextHop nh = { ip_addresses, ifname }; SWSS_LOG_INFO("VNET-RT '%s' op '%s' for ip %s", vnet_name.c_str(), op.c_str(), ip_pfx.to_string().c_str()); @@ -733,8 +749,8 @@ void VNetRouteOrch::handleTunnel(const Request& request) } else { - SWSS_LOG_WARN("Logic error: Unknown attribute: %s", name.c_str()); - return; + SWSS_LOG_INFO("Unknown attribute: %s", name.c_str()); + continue; } } diff --git a/orchagent/vnetorch.h b/orchagent/vnetorch.h index 7ffaadef60..2ca6fdfaaf 100644 --- a/orchagent/vnetorch.h +++ b/orchagent/vnetorch.h @@ -7,6 +7,7 @@ #include #include "request_parser.h" +#include "ipaddresses.h" extern sai_object_id_t gVirtualRouterId; @@ -89,7 +90,7 @@ struct tunnelEndpoint struct nextHop { - IpAddress ip; + IpAddresses ips; string ifname; }; @@ -206,7 +207,7 @@ const request_description_t vnet_route_description = { { { "endpoint", REQ_T_IP }, { "ifname", REQ_T_STRING }, - { "nexthop", REQ_T_IP }, + { "nexthop", REQ_T_STRING }, { "vni", REQ_T_UINT }, { "mac_address", REQ_T_MAC_ADDRESS }, }, diff --git a/orchagent/vxlanorch.cpp b/orchagent/vxlanorch.cpp index 274c9b0545..239508d430 100644 --- a/orchagent/vxlanorch.cpp +++ b/orchagent/vxlanorch.cpp @@ -159,7 +159,7 @@ void remove_tunnel_map_entry(sai_object_id_t obj_id) { sai_status_t status = SAI_STATUS_SUCCESS; - if (obj_id== SAI_NULL_OBJECT_ID) + if (obj_id != SAI_NULL_OBJECT_ID) { status = sai_tunnel_api->remove_tunnel_map_entry(obj_id); } diff --git a/orchagent/vxlanorch.h b/orchagent/vxlanorch.h index 30437f6b11..d441949eb7 100644 --- a/orchagent/vxlanorch.h +++ b/orchagent/vxlanorch.h @@ -50,8 +50,6 @@ struct nh_key_t } return true; } - - }; struct nh_key_hash From 91d77dfd07232bf326dad4167afe297d13b926ed Mon Sep 17 00:00:00 2001 From: Prince Date: Sat, 2 Feb 2019 01:09:49 +0000 Subject: [PATCH 4/5] Address review comment, use VnetInfo --- orchagent/vnetorch.cpp | 13 +++++++------ orchagent/vnetorch.h | 17 ++++++++++++++--- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index ee5d0ae281..328f349115 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -30,8 +30,8 @@ extern NeighOrch *gNeighOrch; */ std::vector vr_cntxt; -VNetVrfObject::VNetVrfObject(const std::string& vnet, string& tunnel, set& peer, uint32_t vni, - vector& attrs) : VNetObject(tunnel, peer, vni) +VNetVrfObject::VNetVrfObject(const std::string& vnet, const VNetInfo& vnetInfo, + vector& attrs) : VNetObject(vnetInfo) { vnet_name_ = vnet; createObj(attrs); @@ -251,10 +251,10 @@ VNetVrfObject::~VNetVrfObject() */ template -std::unique_ptr VNetOrch::createObject(const string& vnet_name, string& tunnel, set& plist, - uint32_t vni, vector& attrs) +std::unique_ptr VNetOrch::createObject(const string& vnet_name, const VNetInfo& vnet_info, + vector& attrs) { - std::unique_ptr vnet_obj(new T(vnet_name, tunnel, plist, vni, attrs)); + std::unique_ptr vnet_obj(new T(vnet_name, vnet_info, attrs)); return vnet_obj; } @@ -352,7 +352,8 @@ bool VNetOrch::addOperation(const Request& request) if (it == std::end(vnet_table_)) { - obj = createObject(vnet_name, tunnel, peer_list, vni, attrs); + VNetInfo vnet_info = { tunnel, vni, peer_list }; + obj = createObject(vnet_name, vnet_info, attrs); create = true; } diff --git a/orchagent/vnetorch.h b/orchagent/vnetorch.h index 2ca6fdfaaf..2f21cb0503 100644 --- a/orchagent/vnetorch.h +++ b/orchagent/vnetorch.h @@ -37,6 +37,13 @@ enum class VR_TYPE VR_INVALID }; +struct VNetInfo +{ + string tunnel; + uint32_t vni; + set peers; +}; + typedef map vrid_list_t; extern std::vector vr_cntxt; @@ -49,7 +56,11 @@ class VNetRequest : public Request class VNetObject { public: - VNetObject(string& tunName, set& peer, uint32_t vni) : tunnel_(tunName), peer_list_(peer), vni_(vni) { } + VNetObject(const VNetInfo& vnetInfo) : + tunnel_(vnetInfo.tunnel), + peer_list_(vnetInfo.peers), + vni_(vnetInfo.vni) + { } virtual bool updateObj(vector&) = 0; @@ -100,7 +111,7 @@ typedef std::map RouteMap; class VNetVrfObject : public VNetObject { public: - VNetVrfObject(const string& vnet, string& tunnel, set& peer, uint32_t vni, vector& attrs); + VNetVrfObject(const string& vnet, const VNetInfo& vnetInfo, vector& attrs); sai_object_id_t getVRidIngress() const; @@ -194,7 +205,7 @@ class VNetOrch : public Orch2 virtual bool delOperation(const Request& request); template - std::unique_ptr createObject(const string&, string&, set&, uint32_t, vector&); + std::unique_ptr createObject(const string&, const VNetInfo&, vector&); VNetTable vnet_table_; VNetRequest request_; From 23c5fa21f7ce46033112e09df68122c4699a8d0b Mon Sep 17 00:00:00 2001 From: Prince Date: Tue, 5 Feb 2019 23:58:19 +0000 Subject: [PATCH 5/5] Address review comments, increment CRM counters --- orchagent/vnetorch.cpp | 78 ++++++++++++++++++++++++++--------------- orchagent/vnetorch.h | 16 ++++----- orchagent/vxlanorch.cpp | 18 +++++----- orchagent/vxlanorch.h | 10 +++--- 4 files changed, 71 insertions(+), 51 deletions(-) diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index 328f349115..417cce7ff5 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -16,6 +16,7 @@ #include "swssnet.h" #include "intfsorch.h" #include "neighorch.h" +#include "crmorch.h" extern sai_virtual_router_api_t* sai_virtual_router_api; extern sai_route_api_t* sai_route_api; @@ -24,6 +25,7 @@ extern Directory gDirectory; extern PortsOrch *gPortsOrch; extern IntfsOrch *gIntfsOrch; extern NeighOrch *gNeighOrch; +extern CrmOrch *gCrmOrch; /* * VRF Modeling and VNetVrf class definitions @@ -172,7 +174,7 @@ bool VNetVrfObject::removeRoute(IpPrefix& ipPrefix) if (tunnels_.find(ipPrefix) != tunnels_.end()) { auto endp = tunnels_.at(ipPrefix); - removeNextHop(endp); + removeTunnelNextHop(endp); tunnels_.erase(ipPrefix); } else @@ -187,7 +189,7 @@ size_t VNetVrfObject::getRouteCount() const return (routes_.size() + tunnels_.size()); } -bool VNetVrfObject::getRouteNH(IpPrefix& ipPrefix, nextHop& nh) +bool VNetVrfObject::getRouteNextHop(IpPrefix& ipPrefix, nextHop& nh) { if (!hasRoute(ipPrefix)) { @@ -199,7 +201,7 @@ bool VNetVrfObject::getRouteNH(IpPrefix& ipPrefix, nextHop& nh) return true; } -sai_object_id_t VNetVrfObject::getNextHop(tunnelEndpoint& endp) +sai_object_id_t VNetVrfObject::getTunnelNextHop(tunnelEndpoint& endp) { sai_object_id_t nh_id = SAI_NULL_OBJECT_ID; auto tun_name = getTunnelName(); @@ -215,7 +217,7 @@ sai_object_id_t VNetVrfObject::getNextHop(tunnelEndpoint& endp) return nh_id; } -bool VNetVrfObject::removeNextHop(tunnelEndpoint& endp) +bool VNetVrfObject::removeTunnelNextHop(tunnelEndpoint& endp) { auto tun_name = getTunnelName(); @@ -223,7 +225,8 @@ bool VNetVrfObject::removeNextHop(tunnelEndpoint& endp) if (!vxlan_orch->removeNextHopTunnel(tun_name, endp.ip, endp.mac, endp.vni)) { - SWSS_LOG_ERROR("VNET %s NH remove failed for '%s'", vnet_name_.c_str(), endp.ip.to_string().c_str()); + SWSS_LOG_ERROR("VNET %s Tunnel NextHop remove failed for '%s'", + vnet_name_.c_str(), endp.ip.to_string().c_str()); return false; } @@ -273,19 +276,19 @@ VNetOrch::VNetOrch(DBConnector *db, const std::string& tableName, VNET_EXEC op) } } -bool VNetOrch::setIntf(const string& alias, const string vnet_name, const IpPrefix *prefix) +bool VNetOrch::setIntf(const string& alias, const string name, const IpPrefix *prefix) { SWSS_LOG_ENTER(); if (isVnetExecVrf()) { - if (!isVnetExists(vnet_name)) + if (!isVnetExists(name)) { - SWSS_LOG_WARN("VNET %s doesn't exist", vnet_name.c_str()); + SWSS_LOG_WARN("VNET %s doesn't exist", name.c_str()); return false; } - auto *vnet_obj = getTypePtr(vnet_name); + auto *vnet_obj = getTypePtr(name); sai_object_id_t vrf_id = vnet_obj->getVRidIngress(); return gIntfsOrch->setIntf(alias, vrf_id, prefix); @@ -430,6 +433,7 @@ bool VNetOrch::delOperation(const Request& request) if (!vxlan_orch->removeVxlanTunnelMap(vrf_obj->getTunnelName(), vrf_obj->getVni())) { SWSS_LOG_ERROR("VNET '%s' map delete failed", vnet_name.c_str()); + return false; } } else @@ -466,6 +470,15 @@ static bool del_route(sai_object_id_t vr_id, sai_ip_prefix_t& ip_pfx) return false; } + if (route_entry.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV4) + { + gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_IPV4_ROUTE); + } + else + { + gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_IPV6_ROUTE); + } + return true; } @@ -488,6 +501,15 @@ static bool add_route(sai_object_id_t vr_id, sai_ip_prefix_t& ip_pfx, sai_object return false; } + if (route_entry.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV4) + { + gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_IPV4_ROUTE); + } + else + { + gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_IPV6_ROUTE); + } + return true; } @@ -535,7 +557,7 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP auto *vrf_obj = vnet_orch_->getTypePtr(vnet); sai_ip_prefix_t pfx; copy(pfx, ipPrefix); - sai_object_id_t nh_id = (op == SET_COMMAND)?vrf_obj->getNextHop(endp):SAI_NULL_OBJECT_ID; + sai_object_id_t nh_id = (op == SET_COMMAND)?vrf_obj->getTunnelNextHop(endp):SAI_NULL_OBJECT_ID; for (auto vr_id : vr_set) { @@ -576,16 +598,16 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP } auto *vrf_obj = vnet_orch_->getTypePtr(vnet); - if (op == DEL_COMMAND && !vrf_obj->getRouteNH(ipPrefix, nh)) + if (op == DEL_COMMAND && !vrf_obj->getRouteNextHop(ipPrefix, nh)) { SWSS_LOG_WARN("VNET %s, Route %s get NH failed", vnet.c_str(), ipPrefix.to_string().c_str()); return true; } - bool subnet = (!nh.ips.getSize())?true:false; + bool is_subnet = (!nh.ips.getSize())?true:false; Port port; - if (subnet && (!gPortsOrch->getPort(nh.ifname, port) || (port.m_rif_id == SAI_NULL_OBJECT_ID))) + if (is_subnet && (!gPortsOrch->getPort(nh.ifname, port) || (port.m_rif_id == SAI_NULL_OBJECT_ID))) { SWSS_LOG_WARN("Port/RIF %s doesn't exist", nh.ifname.c_str()); return false; @@ -600,7 +622,7 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP * route for the peering VRF, Only install in ingress VRF. */ - if (!subnet) + if (!is_subnet) { vr_set = vrf_obj->getVRids(); } @@ -633,7 +655,7 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP copy(pfx, ipPrefix); sai_object_id_t nh_id=SAI_NULL_OBJECT_ID; - if (subnet) + if (is_subnet) { nh_id = port.m_rif_id; } @@ -684,7 +706,7 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP return true; } -void VNetRouteOrch::handleRoutes(const Request& request) +bool VNetRouteOrch::handleRoutes(const Request& request) { SWSS_LOG_ENTER(); @@ -719,14 +741,13 @@ void VNetRouteOrch::handleRoutes(const Request& request) if (vnet_orch_->isVnetExecVrf()) { - if (!doRouteTask(vnet_name, ip_pfx, nh, op)) - { - throw std::runtime_error("Route update failed"); - } + return doRouteTask(vnet_name, ip_pfx, nh, op); } + + return true; } -void VNetRouteOrch::handleTunnel(const Request& request) +bool VNetRouteOrch::handleTunnel(const Request& request) { SWSS_LOG_ENTER(); @@ -766,11 +787,10 @@ void VNetRouteOrch::handleTunnel(const Request& request) if (vnet_orch_->isVnetExecVrf()) { - if (!doRouteTask(vnet_name, ip_pfx, endp, op)) - { - throw std::runtime_error("Route update failed"); - } + return doRouteTask(vnet_name, ip_pfx, endp, op); } + + return true; } bool VNetRouteOrch::addOperation(const Request& request) @@ -786,12 +806,12 @@ bool VNetRouteOrch::addOperation(const Request& request) return true; } - (this->*(handler_map_[tn]))(request); + return ((this->*(handler_map_[tn]))(request)); } catch(std::runtime_error& _) { SWSS_LOG_ERROR("VNET add operation error %s ", _.what()); - return false; + return true; } return true; @@ -810,12 +830,12 @@ bool VNetRouteOrch::delOperation(const Request& request) return true; } - (this->*(handler_map_[tn]))(request); + return ((this->*(handler_map_[tn]))(request)); } catch(std::runtime_error& _) { SWSS_LOG_ERROR("VNET del operation error %s ", _.what()); - return false; + return true; } return true; diff --git a/orchagent/vnetorch.h b/orchagent/vnetorch.h index 2f21cb0503..59e8317f45 100644 --- a/orchagent/vnetorch.h +++ b/orchagent/vnetorch.h @@ -143,11 +143,11 @@ class VNetVrfObject : public VNetObject bool removeRoute(IpPrefix& ipPrefix); size_t getRouteCount() const; - bool getRouteNH(IpPrefix& ipPrefix, nextHop& nh); + bool getRouteNextHop(IpPrefix& ipPrefix, nextHop& nh); bool hasRoute(IpPrefix& ipPrefix); - sai_object_id_t getNextHop(tunnelEndpoint& endp); - bool removeNextHop(tunnelEndpoint& endp); + sai_object_id_t getTunnelNextHop(tunnelEndpoint& endp); + bool removeTunnelNextHop(tunnelEndpoint& endp); ~VNetVrfObject(); @@ -167,7 +167,7 @@ class VNetOrch : public Orch2 public: VNetOrch(DBConnector *db, const std::string&, VNET_EXEC op = VNET_EXEC::VNET_EXEC_VRF); - bool setIntf(const string& alias, const string vnet_name, const IpPrefix *prefix = nullptr); + bool setIntf(const string& alias, const string name, const IpPrefix *prefix = nullptr); bool isVnetExists(const std::string& name) const { @@ -236,15 +236,15 @@ class VNetRouteOrch : public Orch2 public: VNetRouteOrch(DBConnector *db, vector &tableNames, VNetOrch *); - typedef pair handler_pair; - typedef map handler_map; + typedef pair handler_pair; + typedef map handler_map; private: virtual bool addOperation(const Request& request); virtual bool delOperation(const Request& request); - void handleRoutes(const Request&); - void handleTunnel(const Request&); + bool handleRoutes(const Request&); + bool handleTunnel(const Request&); template bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, tunnelEndpoint& endp, string& op); diff --git a/orchagent/vxlanorch.cpp b/orchagent/vxlanorch.cpp index 239508d430..66ae51fad1 100644 --- a/orchagent/vxlanorch.cpp +++ b/orchagent/vxlanorch.cpp @@ -401,7 +401,7 @@ std::pair VxlanTunnel::getMapperEntry(uint32_t return std::make_pair(SAI_NULL_OBJECT_ID, SAI_NULL_OBJECT_ID); } -void VxlanTunnel::updateNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni, sai_object_id_t nh_id) +void VxlanTunnel::updateNextHop(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni, sai_object_id_t nh_id) { auto key = nh_key_t(ipAddr, macAddress, vni); @@ -413,7 +413,7 @@ void VxlanTunnel::updateNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint3 } } -sai_object_id_t VxlanTunnel::getNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) const +sai_object_id_t VxlanTunnel::getNextHop(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) const { auto key = nh_key_t(ipAddr, macAddress, vni); @@ -426,19 +426,19 @@ sai_object_id_t VxlanTunnel::getNHTunnel(IpAddress& ipAddr, MacAddress macAddres return nh_tunnels_.at(key).nh_id; } -void VxlanTunnel::incNHTunnelRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) +void VxlanTunnel::incNextHopRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) { auto key = nh_key_t(ipAddr, macAddress, vni); nh_tunnels_[key].ref_count ++; } -void VxlanTunnel::decNHTunnelRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) +void VxlanTunnel::decNextHopRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) { auto key = nh_key_t(ipAddr, macAddress, vni); nh_tunnels_[key].ref_count --; } -bool VxlanTunnel::removeNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) +bool VxlanTunnel::removeNextHop(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) { auto key = nh_key_t(ipAddr, macAddress, vni); @@ -485,9 +485,9 @@ VxlanTunnelOrch::createNextHopTunnel(string tunnelName, IpAddress& ipAddr, MacAd auto tunnel_obj = getVxlanTunnel(tunnelName); sai_object_id_t nh_id, tunnel_id = tunnel_obj->getTunnelId(); - if ((nh_id = tunnel_obj->getNHTunnel(ipAddr, macAddress, vni)) != SAI_NULL_OBJECT_ID) + if ((nh_id = tunnel_obj->getNextHop(ipAddr, macAddress, vni)) != SAI_NULL_OBJECT_ID) { - tunnel_obj->incNHTunnelRefCount(ipAddr, macAddress, vni); + tunnel_obj->incNextHopRefCount(ipAddr, macAddress, vni); return nh_id; } @@ -508,7 +508,7 @@ VxlanTunnelOrch::createNextHopTunnel(string tunnelName, IpAddress& ipAddr, MacAd } //Store the nh tunnel id - tunnel_obj->updateNHTunnel(ipAddr, macAddress, vni, nh_id); + tunnel_obj->updateNextHop(ipAddr, macAddress, vni, nh_id); SWSS_LOG_INFO("NH vxlan tunnel was created for %s, id 0x%lx", tunnelName.c_str(), nh_id); return nh_id; @@ -528,7 +528,7 @@ VxlanTunnelOrch::removeNextHopTunnel(string tunnelName, IpAddress& ipAddr, MacAd auto tunnel_obj = getVxlanTunnel(tunnelName); //Delete request for the nh tunnel id - return tunnel_obj->removeNHTunnel(ipAddr, macAddress, vni); + return tunnel_obj->removeNextHop(ipAddr, macAddress, vni); } bool VxlanTunnelOrch::createVxlanTunnelMap(string tunnelName, tunnel_map_type_t map, uint32_t vni, diff --git a/orchagent/vxlanorch.h b/orchagent/vxlanorch.h index d441949eb7..e4d4bcd4ef 100644 --- a/orchagent/vxlanorch.h +++ b/orchagent/vxlanorch.h @@ -104,12 +104,12 @@ class VxlanTunnel return ids_.tunnel_encap_id; } - void updateNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni, sai_object_id_t nh_id); - bool removeNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni); - sai_object_id_t getNHTunnel(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) const; + void updateNextHop(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni, sai_object_id_t nhId); + bool removeNextHop(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni); + sai_object_id_t getNextHop(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni) const; - void incNHTunnelRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni); - void decNHTunnelRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni); + void incNextHopRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni); + void decNextHopRefCount(IpAddress& ipAddr, MacAddress macAddress, uint32_t vni); private: string tunnel_name_;