LCOV - code coverage report
Current view: top level - vnsw/agent/oper - vrf.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 516 849 60.8 %
Date: 2026-11-09 02:10:49 Functions: 76 100 76.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <cmn/agent_cmn.h>
       7             : 
       8             : #include <base/lifetime.h>
       9             : #include <base/parse_object.h>
      10             : #include <ifmap/ifmap_link.h>
      11             : #include <ifmap/ifmap_table.h>
      12             : 
      13             : #include <bgp_schema_types.h>
      14             : #include <vnc_cfg_types.h>
      15             : 
      16             : #include <init/agent_init.h>
      17             : #include <cfg/cfg_init.h>
      18             : #include <route/route.h>
      19             : #include <oper/route_common.h>
      20             : #include <oper/vn.h>
      21             : #include <oper/vrf.h>
      22             : #include <oper/peer.h>
      23             : #include <oper/mirror_table.h>
      24             : #include <oper/agent_route_walker.h>
      25             : #include <controller/controller_init.h>
      26             : #include <controller/controller_vrf_export.h>
      27             : #include <oper/agent_sandesh.h>
      28             : #include <oper/nexthop.h>
      29             : #include <oper/config_manager.h>
      30             : #include <oper/agent_route_resync.h>
      31             : #include <resource_manager/resource_manager.h>
      32             : #include <resource_manager/mpls_index.h>
      33             : #include <resource_manager/vrf_index.h>
      34             : 
      35             : #define MAX_VRF_DELETE_TIMEOUT_RETRY_COUNT 10
      36             : 
      37             : using namespace std;
      38             : using namespace autogen;
      39             : 
      40             : VrfTable *VrfTable::vrf_table_;
      41             : 
      42             : class VrfEntry::DeleteActor : public LifetimeActor {
      43             :   public:
      44          74 :     DeleteActor(VrfEntry *vrf) :
      45         148 :         LifetimeActor((static_cast<VrfTable *>(vrf->get_table()))->
      46          74 :                       agent()->lifetime_manager()), table_(vrf, this) {
      47          74 :     }
      48         148 :     virtual ~DeleteActor() {
      49         148 :     }
      50          74 :     virtual bool MayDelete() const {
      51             :         //No table present, then this VRF can be deleted
      52          74 :         return table_->AllRouteTableDeleted();
      53             :     }
      54          74 :     virtual void Shutdown() {
      55          74 :     }
      56          74 :     virtual void Destroy() {
      57          74 :         table_->SendObjectLog(AgentLogEvent::DEL);
      58          74 :         table_ = NULL;
      59          74 :     }
      60             : 
      61             :   private:
      62             :     VrfEntryRef table_;
      63             : };
      64             : 
      65       26333 : VrfEntry::VrfEntry(const string &name, uint32_t flags, Agent *agent) :
      66       52666 :         name_(name), id_(kInvalidIndex), flags_(flags),
      67       26333 :         walkid_(DBTableWalker::kInvalidWalkerId), deleter_(NULL),
      68      210664 :         rt_table_db_(), delete_timeout_timer_(NULL),
      69       26333 :         table_label_(MplsTable::kInvalidLabel),
      70       26333 :         vxlan_id_(VxLanTable::kInvalidvxlan_id),
      71       26333 :         rt_table_delete_bmap_(0),
      72       26333 :         route_resync_walker_(NULL), allow_route_add_on_deleted_vrf_(false),
      73       26333 :         layer2_control_word_(false),
      74       26333 :         rd_(0), routing_vrf_(false), retries_(0),
      75       26333 :         hbf_rintf_(Interface::kInvalidIndex),
      76       78999 :         hbf_lintf_(Interface::kInvalidIndex), deleted_(false) {
      77       26333 :         nh_.reset();
      78       26333 : }
      79             : 
      80       52666 : VrfEntry::~VrfEntry() {
      81       26333 :     if (id_ != kInvalidIndex) {
      82          74 :         VrfTable *table = static_cast<VrfTable *>(get_table());
      83          74 :         SetNotify();
      84             : 
      85             :         //In case of PBB VRF is implictly created, hence upon
      86             :         //delete get the bmac VRF and trigger a notify,
      87             :         //so that if bridge domain is reused it can be recreated
      88          74 :         if (are_flags_set(VrfData::PbbVrf)) {
      89           0 :             table->VrfReuse(bmac_vrf_name_);
      90             :         }
      91          74 :         table->FreeVrfId(id_);
      92          74 :         table->VrfReuse(GetName());
      93          74 :         vrf_node_ptr_ = NULL;
      94             :     }
      95             :     //Delete timer
      96       26333 :     if (delete_timeout_timer_)
      97          74 :         TimerManager::DeleteTimer(delete_timeout_timer_);
      98       52666 : }
      99             : 
     100      100618 : bool VrfEntry::IsLess(const DBEntry &rhs) const {
     101      100618 :     const VrfEntry &a = static_cast<const VrfEntry &>(rhs);
     102      100618 :     return (name_ < a.name_);
     103             : }
     104             : 
     105           0 : string VrfEntry::ToString() const {
     106           0 :     return "VRF";
     107             : }
     108             : 
     109         721 : bool VrfEntry::UpdateVxlanId(Agent *agent, uint32_t new_vxlan_id) {
     110         721 :     bool ret = false;
     111         721 :     if (new_vxlan_id == vxlan_id_) {
     112         588 :         return ret;
     113             :     }
     114             : 
     115         133 :     vxlan_id_ = new_vxlan_id;
     116         133 :     return ret;
     117             : }
     118             : 
     119           0 : void VrfEntry::CreateTableLabel(bool learning_enabled, bool l2,
     120             :                                 bool flood_unknown_unicast,
     121             :                                 bool layer2_control_word) {
     122           0 :     l2_ = l2;
     123           0 :     VrfTable *table = static_cast<VrfTable *>(get_table());
     124           0 :     Agent *agent = table->agent();
     125             : 
     126             :     // Create VrfNH and assign label from it
     127           0 :     DBRequest nh_req;
     128           0 :     nh_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     129           0 :     VrfNHKey *vrf_nh_key = new VrfNHKey(name_, false, l2);
     130           0 :     nh_req.key.reset(vrf_nh_key);
     131           0 :     nh_req.data.reset(new VrfNHData(flood_unknown_unicast, learning_enabled,
     132           0 :                                     layer2_control_word));
     133           0 :     agent->nexthop_table()->Process(nh_req);
     134             : 
     135             :     // Get label from nh
     136           0 :     NextHop *nh = static_cast<NextHop *>(
     137           0 :         agent->nexthop_table()->FindActiveEntry(vrf_nh_key));
     138           0 :     nh_ = nh;
     139           0 :     set_table_label(nh->mpls_label()->label());
     140           0 : }
     141             : 
     142          74 : void VrfEntry::CreateRouteTables() {
     143          74 :     DB *db = get_table()->database();
     144          74 :     VrfTable *table = static_cast<VrfTable *>(get_table());
     145             : 
     146         518 :     for (uint8_t type = (Agent::INVALID + 1); type < Agent::ROUTE_TABLE_MAX; type++) {
     147         888 :         rt_table_db_[type] = static_cast<AgentRouteTable *>
     148         444 :             (db->CreateTable(name_ +
     149         444 :                  AgentRouteTable::GetSuffix(Agent::RouteTableType(type))));
     150         444 :         rt_table_db_[type]->SetVrf(this);
     151         444 :         table->dbtree_[type].insert(VrfTable::VrfDbPair(name_, rt_table_db_[type]));
     152             :     }
     153          74 : }
     154             : 
     155          74 : void VrfEntry::DeleteRouteTables() {
     156         518 :     for (int table_type = (Agent::INVALID + 1);
     157         518 :          table_type < Agent::ROUTE_TABLE_MAX; table_type++) {
     158         444 :         VrfTable *vrf_table = ((VrfTable *) get_table());
     159             :         AgentRouteTable *route_table =
     160         444 :             vrf_table->GetRouteTable(name_, table_type);
     161         444 :         if (route_table) {
     162         444 :             vrf_table->DeleteFromDbTree(table_type, name_);
     163         444 :             vrf_table->database()->RemoveTable(route_table);
     164         444 :             delete route_table;
     165             :         }
     166             :     }
     167          74 : }
     168             : 
     169          74 : void VrfEntry::PostAdd() {
     170          74 :     VrfTable *table = static_cast<VrfTable *>(get_table());
     171          74 :     Agent *agent = table->agent();
     172             :     // get_table() would return NULL in Add(), so move dependent functions and
     173             :     // initialization to PostAdd
     174          74 :     deleter_.reset(new DeleteActor(this));
     175          74 :     if (route_resync_walker_.get() == NULL) {
     176             :         route_resync_walker_ = new AgentRouteResync("VrfRouteResyncWalker",
     177          74 :                                                     agent);
     178             :         agent->oper_db()->agent_route_walk_manager()->
     179          74 :             RegisterWalker(static_cast<AgentRouteWalker *>
     180             :                            (route_resync_walker_.get()));
     181             :     }
     182             :     // Create the route-tables and insert them into dbtree_
     183          74 :     CreateRouteTables();
     184             : 
     185          74 :     uint32_t vxlan_id = VxLanTable::kInvalidvxlan_id;
     186          74 :     if (vn_) {
     187           4 :         vxlan_id = vn_->GetVxLanId();
     188             :     }
     189          74 :     UpdateVxlanId(agent, vxlan_id);
     190             : 
     191             :     // Add the L2 Receive routes for VRRP mac
     192          74 :     BridgeAgentRouteTable *l2_table = static_cast<BridgeAgentRouteTable *>
     193             :         (rt_table_db_[Agent::BRIDGE]);
     194          74 :     l2_table->AddBridgeReceiveRoute(agent->local_vm_peer(), name_, 0,
     195             :                                     agent->vrrp_mac(), "");
     196          74 :     l2_table->AddBridgeReceiveRoute(agent->local_peer(), name_,
     197             :                                     agent->left_si_mac(), "", "pkt0", true);
     198          74 :     l2_table->AddBridgeReceiveRoute(agent->local_peer(), name_,
     199             :                                     agent->right_si_mac(), "", "pkt0", true);
     200             : 
     201             :     // Add the L2 Receive routes for xconnect interface to vhost
     202             :     // Note, vhost is not created when fabric VRF is created. We only need
     203             :     // VRRP MAC on fabric vrf. So, we are good for now
     204          74 :     const VmInterface *vhost = dynamic_cast<const VmInterface *>
     205          74 :         (agent->vhost_interface());
     206          74 :     if (vhost && vhost->parent_list().empty() == false) {
     207         140 :         for (size_t i = 0; i < vhost->parent_list().size(); i++) {
     208         210 :             l2_table->AddBridgeReceiveRoute(agent->local_vm_peer(), name_, 0,
     209         140 :                     vhost->parent_list()[i]->mac(), "");
     210             :         }
     211             :     }
     212             : 
     213             :     //Add receive route for vmware physical interface mac, so
     214             :     //that packets hitting this mac gets routed(inter-vn traffic)
     215          74 :     if (agent->isVmwareMode()) {
     216           0 :         PhysicalInterfaceKey key(agent->params()->vmware_physical_port());
     217           0 :         Interface *intf = static_cast<Interface *>
     218           0 :             (agent->interface_table()->FindActiveEntry(&key));
     219           0 :         if (intf) {
     220           0 :              l2_table->AddBridgeReceiveRoute(agent->local_vm_peer(), name_, 0,
     221             :                                              intf->mac(), "");
     222             :         }
     223           0 :     }
     224             : 
     225          74 :     SendObjectLog(AgentLogEvent::ADD);
     226          74 : }
     227             : 
     228        1769 : DBEntryBase::KeyPtr VrfEntry::GetDBRequestKey() const {
     229        1769 :     VrfKey *key = new VrfKey(name_);
     230        1769 :     return DBEntryBase::KeyPtr(key);
     231             : }
     232             : 
     233           0 : void VrfEntry::SetKey(const DBRequestKey *key) {
     234           0 :     const VrfKey *k = static_cast<const VrfKey *>(key);
     235           0 :     name_ = k->name_;
     236           0 : }
     237             : 
     238           7 : InetUnicastRouteEntry *VrfEntry::GetUcRoute(const IpAddress &addr) const {
     239           7 :     InetUnicastAgentRouteTable *table = NULL;
     240           7 :     if (addr.is_v4()) {
     241           7 :         table = GetInet4UnicastRouteTable();
     242           0 :     } else if (addr.is_v6()) {
     243           0 :         table = GetInet6UnicastRouteTable();
     244             :     }
     245           7 :     if (table == NULL)
     246           0 :         return NULL;
     247             : 
     248           7 :     return table->FindLPM(addr);
     249             : }
     250             : 
     251         414 : InetUnicastRouteEntry *VrfEntry::GetUcRoute(const InetUnicastRouteEntry &rt_key) const {
     252         414 :     InetUnicastAgentRouteTable *table = NULL;
     253             : 
     254         414 :     if (rt_key.prefix_address().is_v4()) {
     255         414 :         table = GetInet4UnicastRouteTable();
     256           0 :     } else if (rt_key.prefix_address().is_v6()) {
     257           0 :         table = GetInet6UnicastRouteTable();
     258             :     }
     259         414 :     if (table == NULL)
     260           0 :         return NULL;
     261             : 
     262         414 :     return table->FindLPM(rt_key);
     263             : }
     264             : 
     265         444 : LifetimeActor *VrfEntry::deleter() {
     266         444 :     return deleter_.get();
     267             : }
     268             : 
     269         166 : bool VrfEntry::AllRouteTableDeleted() const {
     270         610 :     for (int i = Agent::INET4_UNICAST; i < Agent::ROUTE_TABLE_MAX; i++) {
     271         536 :         if ((rt_table_delete_bmap_ & (1 << i)) == 0)
     272          92 :             return false;
     273             :     }
     274             : 
     275          74 :     return true;
     276             : }
     277             : 
     278       39366 : bool VrfEntry::RouteTableDeleted(uint8_t table_type) const {
     279       39366 :     return (rt_table_delete_bmap_ & (1 << table_type));
     280             : }
     281             : 
     282         444 : void VrfEntry::SetRouteTableDeleted(uint8_t table_type) {
     283         444 :     rt_table_delete_bmap_ |= (1 << table_type);
     284         444 : }
     285             : 
     286       39366 : AgentRouteTable *VrfEntry::GetRouteTable(uint8_t table_type) const {
     287       39366 :     return (RouteTableDeleted(table_type) ? NULL : rt_table_db_[table_type]);
     288             : }
     289             : 
     290           0 : const std::string VrfEntry::GetTableTypeString(uint8_t table_type) const {
     291           0 :     switch (table_type) {
     292           0 :       case Agent::INET4_UNICAST: {
     293           0 :           return "inet4_unicast";
     294             :           break;
     295             :       }
     296           0 :       case Agent::INET4_MPLS: {
     297           0 :           return "inet4_mpls";
     298             :           break;
     299             :       }
     300           0 :       case Agent::INET6_UNICAST: {
     301           0 :           return "inet6_unicast";
     302             :           break;
     303             :       }
     304           0 :       case Agent::INET4_MULTICAST: {
     305           0 :           return "inet4_multicast";
     306             :           break;
     307             :       }
     308           0 :       case Agent::BRIDGE: {
     309           0 :           return "bridge";
     310             :           break;
     311             :       }
     312           0 :       case Agent::EVPN: {
     313           0 :           return "evpn";
     314             :           break;
     315             :       }
     316             :     }
     317           0 :     return "None";
     318             : }
     319             : 
     320        6895 : InetUnicastAgentRouteTable *VrfEntry::GetInet4UnicastRouteTable() const {
     321        6895 :     return static_cast<InetUnicastAgentRouteTable *>(GetRouteTable(Agent::INET4_UNICAST));
     322             : }
     323             : 
     324          78 : InetUnicastAgentRouteTable *VrfEntry::GetInet4MplsUnicastRouteTable() const {
     325          78 :     return static_cast<InetUnicastAgentRouteTable *>(GetRouteTable(Agent::INET4_MPLS));
     326             : }
     327          76 : AgentRouteTable *VrfEntry::GetInet4MulticastRouteTable() const {
     328          76 :     return GetRouteTable(Agent::INET4_MULTICAST);
     329             : }
     330             : 
     331        2981 : AgentRouteTable *VrfEntry::GetEvpnRouteTable() const {
     332        2981 :     return GetRouteTable(Agent::EVPN);
     333             : }
     334             : 
     335        3937 : AgentRouteTable *VrfEntry::GetBridgeRouteTable() const {
     336        3937 :     return GetRouteTable(Agent::BRIDGE);
     337             : }
     338             : 
     339        1280 : InetUnicastAgentRouteTable *VrfEntry::GetInet6UnicastRouteTable() const {
     340        1280 :     return static_cast<InetUnicastAgentRouteTable *>(GetRouteTable(Agent::INET6_UNICAST));
     341             : }
     342             : 
     343           0 : bool VrfEntry::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
     344           0 :     VrfListResp *resp = static_cast<VrfListResp *>(sresp);
     345             : 
     346           0 :     if (name.empty() || GetName().find(name) != string::npos) {
     347           0 :         VrfSandeshData data;
     348           0 :         data.set_name(GetName());
     349           0 :         data.set_ucindex(vrf_id());
     350           0 :         data.set_mcindex(vrf_id());
     351           0 :         data.set_evpnindex(vrf_id());
     352           0 :         data.set_l2index(vrf_id());
     353           0 :         data.set_brindex(vrf_id());
     354           0 :         data.set_uc6index(vrf_id());
     355           0 :         std::string vrf_flags;
     356           0 :         if (flags() & VrfData::ConfigVrf)
     357           0 :             vrf_flags += "Config; ";
     358           0 :         if (flags() & VrfData::GwVrf)
     359           0 :             vrf_flags += "Gateway; ";
     360           0 :         if (flags() & VrfData::PbbVrf)
     361           0 :             vrf_flags += "PBB C-Vrf";
     362           0 :         data.set_source(vrf_flags);
     363           0 :         if (vn_.get()) {
     364           0 :             data.set_vn(vn_->GetName());
     365             :         } else {
     366           0 :             data.set_vn("N/A");
     367             :         }
     368           0 :         data.set_table_label(table_label());
     369           0 :         VrfTable *table = static_cast<VrfTable *>(get_table());
     370           0 :         stringstream rd;
     371           0 :         rd << table->agent()->compute_node_ip().to_string() << ":" <<
     372           0 :             RDInstanceId(table->agent()->tor_agent_enabled());
     373           0 :         data.set_RD(rd.str());
     374             : 
     375             :         std::vector<VrfSandeshData> &list =
     376           0 :                 const_cast<std::vector<VrfSandeshData>&>(resp->get_vrf_list());
     377           0 :         data.set_vxlan_id(vxlan_id_);
     378           0 :         data.set_mac_aging_time(mac_aging_time_);
     379           0 :         data.set_layer2_control_word(layer2_control_word_);
     380           0 :         if (forwarding_vrf_.get()) {
     381           0 :             data.set_forwarding_vrf(forwarding_vrf_->name_);
     382             :         }
     383           0 :         data.set_hbf_rintf(hbf_rintf());
     384           0 :         data.set_hbf_lintf(hbf_lintf());
     385           0 :         list.push_back(data);
     386           0 :         return true;
     387           0 :     }
     388             : 
     389           0 :     return false;
     390             : }
     391             : 
     392         222 : void VrfEntry::SendObjectLog(AgentLogEvent::type event) const {
     393         444 :     VrfObjectLogInfo vrf;
     394         222 :     string str;
     395         222 :     switch (event) {
     396          74 :         case AgentLogEvent::ADD:
     397          74 :             str.assign("Addition ");
     398          74 :             break;
     399          74 :         case AgentLogEvent::DEL:
     400          74 :             str.assign("Deletion ");
     401          74 :             break;
     402           0 :         case AgentLogEvent::CHANGE:
     403           0 :             str.assign("Modification ");
     404           0 :             break;
     405          74 :         case AgentLogEvent::DELETE_TRIGGER:
     406          74 :             str.assign("Deletion Triggered ");
     407          74 :             break;
     408           0 :         default:
     409           0 :             str.assign("");
     410           0 :             break;
     411             :     }
     412         222 :     vrf.set_event(str);
     413         222 :     vrf.set_name(name_);
     414         222 :     vrf.set_index(id_);
     415         222 :     VRF_OBJECT_LOG_LOG("AgentVrf", SandeshLevel::SYS_INFO, vrf);
     416         222 : }
     417             : 
     418           0 : bool VrfEntry::DeleteTimeout() {
     419           0 :     uint32_t num_routes = 0;
     420           0 :     for (uint8_t type = (Agent::INVALID + 1);
     421           0 :          type < Agent::ROUTE_TABLE_MAX;
     422             :          type++) {
     423           0 :         num_routes += rt_table_db_[type]->Size();
     424             :     }
     425           0 :     if (num_routes) {
     426           0 :         std::ostringstream str;
     427           0 :         str << "Unicast routes: " << rt_table_db_[Agent::INET4_UNICAST]->Size();
     428           0 :         str << "Unicast MPLS routes: " << rt_table_db_[Agent::INET4_MPLS]->Size();
     429           0 :         str << " Mutlicast routes: " << rt_table_db_[Agent::INET4_MULTICAST]->Size();
     430           0 :         str << " EVPN routes: " << rt_table_db_[Agent::EVPN]->Size();
     431           0 :         str << " Bridge routes: " << rt_table_db_[Agent::BRIDGE]->Size();
     432           0 :         str << "Unicast v6 routes: " << rt_table_db_[Agent::INET6_UNICAST]->Size();
     433           0 :         str << " Reference: " << GetRefCount();
     434           0 :         OPER_TRACE_ENTRY(Vrf, static_cast<const AgentDBTable *>(get_table()),
     435             :                         "VRF delete failed, " + str.str(), name_);
     436           0 :         assert(0);
     437             :         return false;
     438           0 :     }
     439             : 
     440             :     // if number of routes is 0, and VRF ref count is non zero
     441             :     // then only reschedule delete timout
     442           0 :     if (retries_ >= MAX_VRF_DELETE_TIMEOUT_RETRY_COUNT) {
     443           0 :         OPER_TRACE_ENTRY(Vrf, static_cast<const AgentDBTable *>(get_table()),
     444             :                 "VRF delete failed with max retries", name_);
     445           0 :         assert(0);
     446             :         return false;
     447             :     }
     448           0 :     retries_ = retries_+1;
     449           0 :     return true;
     450             : }
     451             : 
     452          74 : void VrfEntry::StartDeleteTimer() {
     453          74 :     Agent *agent = (static_cast<VrfTable *>(get_table()))->agent();
     454         148 :     delete_timeout_timer_ = TimerManager::CreateTimer(
     455          74 :                                 *(agent->event_manager())->io_service(),
     456             :                                 "VrfDeleteTimer");
     457          74 :     delete_timeout_timer_->Start(kDeleteTimeout,
     458             :                                  boost::bind(&VrfEntry::DeleteTimeout,
     459             :                                  this));
     460          74 : }
     461             : 
     462          74 : void VrfEntry::CancelDeleteTimer() {
     463          74 :     delete_timeout_timer_->Cancel();
     464          74 : }
     465             : 
     466           0 : bool VrfEntry::ResetVrfDelete() {
     467           0 :     delete_reuse_mutex_.lock();
     468           0 :     if (deleted_ == true) {
     469           0 :         delete_reuse_mutex_.unlock();
     470           0 :         return false;
     471             :     }
     472           0 :     if (AllRouteTablesEmpty()) {
     473           0 :         if (!AllRouteTableDeleted() ||
     474           0 :             deleter_->HasRefcount() ||
     475           0 :             deleter_->HasDependents()) {
     476           0 :             delete_reuse_mutex_.unlock();
     477           0 :             return false;
     478             :         }
     479           0 :         if (route_resync_walker_.get() != NULL) {
     480           0 :             if (route_resync_walker_.get()->refcount() > 1 ||
     481           0 :                 route_resync_walker_.get()->IsValidDeleteWalkRef() ||
     482           0 :                 route_resync_walker_.get()->IsValidVrfWalkRef() ||
     483           0 :                 route_resync_walker_.get()->IsDeregisterDone() == false) {
     484           0 :                 delete_reuse_mutex_.unlock();
     485           0 :                 return false;
     486             :             }
     487             :         }
     488           0 :         ClearDelete();
     489           0 :         delete_reuse_mutex_.unlock();
     490           0 :         CancelDeleteTimer();
     491           0 :         rt_table_delete_bmap_ = 0;
     492           0 :         DeleteRouteTables();
     493           0 :         deleter_.reset(new DeleteActor(this));
     494           0 :         CreateRouteTables();
     495           0 :         VrfTable *table = static_cast<VrfTable *>(get_table());
     496           0 :         Agent *agent = table->agent();
     497           0 :         route_resync_walker_.reset(new AgentRouteResync("VrfRouteResyncWalker",
     498           0 :                                    agent));
     499             :         agent->oper_db()->agent_route_walk_manager()->
     500           0 :             RegisterWalker(static_cast<AgentRouteWalker *>
     501             :                     (route_resync_walker_.get()));
     502           0 :         SetNotify();
     503           0 :         table->VrfReuse(GetName());
     504           0 :         vrf_node_ptr_ = NULL;
     505           0 :         retries_ = 0;
     506           0 :         if (delete_timeout_timer_)
     507           0 :             TimerManager::DeleteTimer(delete_timeout_timer_);
     508             : 
     509           0 :         OPER_TRACE_ENTRY(Vrf, static_cast<const AgentDBTable *>(get_table()),
     510             :             "Reset Vrf Deletion", GetName());
     511           0 :         return true;
     512             :     }
     513           0 :     delete_reuse_mutex_.unlock();
     514           0 :     return false;
     515             : }
     516             : 
     517          68 : void VrfEntry::ResyncRoutes() {
     518          68 :     (static_cast<AgentRouteResync *>(route_resync_walker_.get()))->
     519          68 :         UpdateRoutesInVrf(this);
     520          68 : }
     521             : 
     522             : // Used to decide RD to be sent to CN for this VRF.
     523             : // In non tor-agent case vrf-id generated is used.
     524             : // However in tor-agent vn id(network-id) is used. This is because both active
     525             : // and backup TA can publish same route which will be sent to BGP router peered
     526             : // to CN. If both these TA end up generating different vrf-id for same Vrf, then
     527             : // RD using vrf_id will be different. Hence BGP router will get same route with
     528             : // two different RD causing undefined behavior.
     529             : // To avoid this both TA should generate same RD. As VN id is generated by config
     530             : // it is unique and common across both TA so same can be used.
     531         647 : int VrfEntry::RDInstanceId(bool tor_agent_enabled) const {
     532         647 :     if (tor_agent_enabled == false) {
     533         647 :         return id_;
     534             :     }
     535             : 
     536           0 :     if (vn() == NULL)
     537           0 :         return kInvalidIndex;
     538             : 
     539           0 :     if (vn()->vnid() == 0)
     540           0 :         return kInvalidIndex;
     541             : 
     542           0 :     return vn()->vnid();
     543             : }
     544             : 
     545        1738 : void VrfEntry::RetryDelete() {
     546        1738 :     if (AllRouteTablesEmpty() == false)
     547         329 :         return;
     548             : 
     549             :     // Enqueue a DB Request to notify the entry, entry should always be
     550             :     // notified in db::DBTable task context
     551        1409 :     DBRequest req(DBRequest::DB_ENTRY_NOTIFY);
     552        1409 :     req.key = GetDBRequestKey();
     553        1409 :     (static_cast<VrfTable *>(get_table()))->Enqueue(&req);
     554        1409 : }
     555             : 
     556        3672 : bool VrfEntry::AllRouteTablesEmpty() const {
     557       12756 :     for (uint8_t type = (Agent::INVALID + 1);
     558       12756 :          type < Agent::ROUTE_TABLE_MAX;
     559             :          type++) {
     560       11338 :         if (rt_table_db_[type]->empty() == false) {
     561        2253 :             return false;
     562             :         }
     563             :     }
     564        1418 :     return true;
     565             : }
     566             : 
     567          74 : void VrfEntry::ReleaseWalker() {
     568          74 :     if (route_resync_walker_.get() != NULL) {
     569          74 :         VrfTable *table = static_cast<VrfTable *>(get_table());
     570             :         table->agent()->oper_db()->agent_route_walk_manager()->
     571          74 :             ReleaseWalker(route_resync_walker_.get());
     572             :     }
     573          74 : }
     574             : 
     575             : InetUnicastAgentRouteTable *
     576        2007 : VrfEntry::GetInetUnicastRouteTable(const IpAddress &addr) const {
     577        2007 :     if (addr.is_v4())
     578             :         return static_cast<InetUnicastAgentRouteTable *>
     579        2007 :             (GetInet4UnicastRouteTable());
     580             :     return static_cast<InetUnicastAgentRouteTable *>
     581           0 :         (GetInet6UnicastRouteTable());
     582             : }
     583             : 
     584          74 : void VrfEntry::SetNotify() {
     585          74 :     VrfTable *table = static_cast<VrfTable *>(get_table());
     586          74 :     if (vrf_node_ptr_) {
     587             :         IFMapDependencyManager *dep = table->agent()->
     588          70 :             oper_db()->dependency_manager();
     589          70 :         IFMapNodeState *state = vrf_node_ptr_.get();
     590          70 :         dep->SetNotify(state->node(), true);
     591             :     }
     592          74 : }
     593             : 
     594             : class VrfDeleteWalker : public AgentRouteWalker {
     595             : public:
     596           0 :     VrfDeleteWalker(const std::string &name, Agent *agent) :
     597           0 :         AgentRouteWalker(name, agent) {
     598           0 :     }
     599             : 
     600           0 :     ~VrfDeleteWalker() { }
     601             : 
     602             :     //Override vrf notification
     603           0 :     bool VrfWalkNotify(DBTablePartBase *partition, DBEntryBase *e) {
     604           0 :         DBRequest req(DBRequest::DB_ENTRY_DELETE);
     605           0 :         req.key = e->GetDBRequestKey();
     606           0 :         (static_cast<VrfTable *>(e->get_table()))->Process(req);
     607           0 :         return true;
     608           0 :     }
     609             : 
     610             :     //Override route notification
     611           0 :     bool RouteWalkNotify(DBTablePartBase *partition, DBEntryBase *e) {
     612           0 :         assert(0);
     613             :         return false;
     614             :     }
     615             : 
     616           0 :     static void WalkDone(VrfDeleteWalker *walker) {
     617           0 :         walker->mgr()->ReleaseWalker(walker);
     618           0 :         walker->agent()->vrf_table()->reset_vrf_delete_walker();
     619           0 :     }
     620             : 
     621             : private:
     622             : };
     623             : 
     624          74 : void VrfTable::FreeVrfId(size_t index) {
     625          74 :     agent()->resource_manager()->Release(Resource::VRF_INDEX, index);
     626          74 :     index_table_.Remove(index);
     627          74 : };
     628           0 : void VrfTable::Clear() {
     629           0 :     if (route_delete_walker_.get())
     630             :         agent()->oper_db()->agent_route_walk_manager()->
     631           0 :             ReleaseWalker(route_delete_walker_.get());
     632           0 :     if (vrf_delete_walker_.get() != NULL)
     633             :         agent()->oper_db()->agent_route_walk_manager()->
     634           0 :             ReleaseWalker(vrf_delete_walker_.get());
     635           0 : }
     636             : 
     637       26259 : std::unique_ptr<DBEntry> VrfTable::AllocEntry(const DBRequestKey *k) const {
     638       26259 :     const VrfKey *key = static_cast<const VrfKey *>(k);
     639       26259 :     VrfEntry *vrf = new VrfEntry(key->name_, 0, agent());
     640       26259 :     return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(vrf));
     641             : }
     642             : 
     643          18 : VrfTable::~VrfTable() {
     644          22 : }
     645             : 
     646          74 : DBEntry *VrfTable::OperDBAdd(const DBRequest *req) {
     647          74 :     VrfKey *key = static_cast<VrfKey *>(req->key.get());
     648          74 :     VrfData *data = static_cast<VrfData *>(req->data.get());
     649          74 :     VrfEntry *vrf = new VrfEntry(key->name_, data->flags_, agent());
     650             : 
     651             :     // Add VRF into name based tree
     652          74 :     if (FindVrfFromName(key->name_)) {
     653           0 :         delete vrf;
     654           0 :         assert(0);
     655             :         return NULL;
     656             :     }
     657          74 :     if (vrf) {
     658             :         ResourceManager::KeyPtr rkey(new VrfIndexResourceKey(
     659          74 :                                      agent()->resource_manager(), key->name_));
     660         148 :         vrf->id_ = static_cast<IndexResourceData *>(agent()->resource_manager()->
     661          74 :                                                     Allocate(rkey).get())->index();
     662          74 :         index_table_.InsertAtIndex(vrf->id_, vrf);
     663          74 :     }
     664          74 :     name_tree_.insert( VrfNamePair(key->name_, vrf));
     665             : 
     666          74 :     vrf->vn_.reset(agent()->vn_table()->Find(data->vn_uuid_));
     667          74 :     if (vrf->vn_) {
     668           4 :         vrf->set_routing_vrf(vrf->vn_->vxlan_routing_vn());
     669             :     }
     670             : 
     671          74 :     vrf->si_vn_ref_.reset(agent()->vn_table()->Find(data->si_vn_ref_uuid_));
     672             : 
     673          74 :     vrf->isid_ = data->isid_;
     674          74 :     vrf->bmac_vrf_name_ = data->bmac_vrf_name_;
     675          74 :     vrf->learning_enabled_ = data->learning_enabled_;
     676          74 :     vrf->mac_aging_time_ = data->mac_aging_time_;
     677          74 :     vrf->set_hbf_rintf(data->hbf_rintf_);
     678          74 :     vrf->set_hbf_lintf(data->hbf_lintf_);
     679          74 :     if (vrf->vn_.get()) {
     680           4 :         vrf->layer2_control_word_ = vrf->vn_->layer2_control_word();
     681             :     }
     682          74 :     vrf->set_rd(vrf->RDInstanceId(agent()->tor_agent_enabled()));
     683          74 :     if (data->forwarding_vrf_name_ != Agent::NullString()) {
     684           2 :         vrf->forwarding_vrf_ = FindVrfFromName(data->forwarding_vrf_name_);
     685             :     }
     686          74 :     return vrf;
     687             : }
     688             : 
     689         573 : bool VrfTable::OperDBOnChange(DBEntry *entry, const DBRequest *req) {
     690         573 :     bool ret = false;
     691         573 :     VrfEntry *vrf = static_cast<VrfEntry *>(entry);
     692         573 :     VrfData *data = static_cast<VrfData *>(req->data.get());
     693         573 :     vrf->set_flags(data->flags_);
     694             : 
     695         573 :     if (vrf->are_flags_set(VrfData::PbbVrf)) {
     696           0 :         if (FindVrfFromName(vrf->bmac_vrf_name_) == NULL) {
     697           0 :             assert(0);
     698             :         }
     699             :     }
     700             : 
     701         573 :     VnEntry *vn = agent()->vn_table()->Find(data->vn_uuid_);
     702         573 :     bool resync_routes = false;
     703             : 
     704         573 :     if (vn != vrf->vn_.get()) {
     705          68 :         resync_routes = true;
     706          68 :         vrf->vn_.reset(vn);
     707          68 :         ret = true;
     708             :     }
     709             : 
     710         573 :     VnEntry *si_vn_ref = agent()->vn_table()->Find(data->si_vn_ref_uuid_);
     711         573 :     if (si_vn_ref != vrf->si_vn_ref_.get()) {
     712           0 :         vrf->si_vn_ref_.reset(si_vn_ref);
     713             :     }
     714             : 
     715         573 :     if (data->ifmap_node() && vrf->ifmap_node() != data->ifmap_node()) {
     716           0 :         ret = true;
     717             :     }
     718             : 
     719         573 :     bool layer2_control_word = false;
     720         573 :     if (vn) {
     721         487 :         layer2_control_word = vn->layer2_control_word();
     722             :     }
     723             : 
     724         573 :     if (vrf->layer2_control_word_ != layer2_control_word) {
     725           0 :         vrf->layer2_control_word_ = layer2_control_word;
     726           0 :         vrf->ResyncRoutes();
     727           0 :         ret = true;
     728             :     }
     729             : 
     730         573 :     if (vrf->learning_enabled_ != data->learning_enabled_) {
     731           0 :         vrf->learning_enabled_ = data->learning_enabled_;
     732           0 :         ret = true;
     733             :     }
     734             : 
     735         573 :     if (vrf->isid_ != data->isid_) {
     736           0 :         vrf->isid_ = data->isid_;
     737           0 :         ret = true;
     738             :     }
     739             : 
     740         573 :     if (vrf->rd() != vrf->RDInstanceId(agent()->tor_agent_enabled())) {
     741           0 :         resync_routes = true;
     742           0 :         vrf->set_rd(vrf->RDInstanceId(agent()->tor_agent_enabled()));
     743           0 :         ret = true;
     744             :     }
     745             : 
     746         573 :     if (resync_routes) {
     747          68 :         vrf->ResyncRoutes();
     748             :     }
     749             : 
     750         573 :     uint32_t vxlan_id = VxLanTable::kInvalidvxlan_id;
     751         573 :     if (vn) {
     752         487 :         vxlan_id = vn->GetVxLanId();
     753             :     }
     754         573 :     vrf->UpdateVxlanId(agent(), vxlan_id);
     755             : 
     756         573 :     if (data && vrf->mac_aging_time_ != data->mac_aging_time_) {
     757           0 :         vrf->mac_aging_time_ = data->mac_aging_time_;
     758             :     }
     759             : 
     760         573 :     VrfEntry *forwarding_vrf = NULL;
     761         573 :     if (data->forwarding_vrf_name_ != Agent::NullString()) {
     762           0 :         forwarding_vrf = FindVrfFromName(data->forwarding_vrf_name_);
     763             :     }
     764             : 
     765         573 :     if (forwarding_vrf != vrf->forwarding_vrf_) {
     766           0 :         vrf->forwarding_vrf_ = forwarding_vrf;
     767           0 :         ret = true;
     768             :     }
     769             : 
     770         573 :     if (vrf->hbf_rintf() != data->hbf_rintf_) {
     771           0 :         vrf->set_hbf_rintf(data->hbf_rintf_);
     772           0 :         ret = true;
     773             :     }
     774         573 :     if (vrf->hbf_lintf() != data->hbf_lintf_) {
     775           0 :         vrf->set_hbf_lintf(data->hbf_lintf_);
     776           0 :         ret = true;
     777             :     }
     778             : 
     779         573 :     return ret;
     780             : }
     781             : 
     782          74 : bool VrfTable::OperDBDelete(DBEntry *entry, const DBRequest *req) {
     783          74 :     VrfEntry *vrf = static_cast<VrfEntry *>(entry);
     784          74 :     VrfData *data = static_cast<VrfData *>(req->data.get());
     785             : 
     786             :     // VRF can be created by both config and VGW. VRF cannot be deleted till
     787             :     // both config and VGW delete it.
     788             :     // We want to retain flags like PbbVrf, hence mask only flags which
     789             :     // are needed to delete the VRF
     790          74 :     vrf->flags_ &= ~(data->flags_ & data->ConfigFlags());
     791          74 :     if ((vrf->flags_ & data->ConfigFlags()) != 0)
     792           0 :         return false;
     793             : 
     794             :     // Delete the L2 Receive routes added by default
     795          74 :     BridgeAgentRouteTable *l2_table = static_cast<BridgeAgentRouteTable *>
     796             :         (vrf->rt_table_db_[Agent::BRIDGE]);
     797          74 :     l2_table->Delete(agent()->local_vm_peer(), vrf->GetName(),
     798          74 :                      agent()->vrrp_mac(), 0);
     799          74 :     l2_table->Delete(agent()->local_peer(), vrf->GetName(),
     800          74 :                      agent()->left_si_mac(), -1);
     801          74 :     l2_table->Delete(agent()->local_peer(), vrf->GetName(),
     802          74 :                      agent()->right_si_mac(), -1);
     803          74 :     const VmInterface *vhost = dynamic_cast<const VmInterface *>
     804          74 :         (agent()->vhost_interface());
     805          74 :     if (vhost && vhost->parent_list().empty() == false) {
     806         144 :         for (size_t i = 0; i < vhost->parent_list().size(); i++) {
     807          72 :             l2_table->Delete(agent()->local_vm_peer(), vrf->GetName(),
     808         144 :                     vhost->parent_list()[i]->mac(), 0);
     809             :         }
     810             :     }
     811             : 
     812          74 :     if (agent()->isVmwareMode()) {
     813           0 :         PhysicalInterfaceKey key(agent()->params()->vmware_physical_port());
     814           0 :         Interface *intf = static_cast<Interface *>
     815           0 :             (agent()->interface_table()->FindActiveEntry(&key));
     816           0 :         if (intf) {
     817           0 :              l2_table->Delete(agent()->local_vm_peer(), vrf->GetName(),
     818             :                               intf->mac(), 0);
     819             :         }
     820           0 :     }
     821             : 
     822          74 :     vrf->UpdateVxlanId(agent(), VxLanTable::kInvalidvxlan_id);
     823          74 :     vrf->vn_.reset(NULL);
     824          74 :     if (vrf->table_label() != MplsTable::kInvalidLabel) {
     825           0 :         vrf->nh_.reset();
     826           0 :         vrf->set_table_label(MplsTable::kInvalidLabel);
     827             :     }
     828          74 :     vrf->deleter_->Delete();
     829          74 :     vrf->StartDeleteTimer();
     830          74 :     vrf->SendObjectLog(AgentLogEvent::DELETE_TRIGGER);
     831             : 
     832             : 
     833          74 :     if (vrf->ifmap_node()) {
     834          70 :         IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager();
     835          70 :         vrf->vrf_node_ptr_ = dep->SetState(vrf->ifmap_node());
     836          70 :         dep->SetNotify(vrf->ifmap_node(), false);
     837             :     }
     838          74 :     vrf->ReleaseWalker();
     839             : 
     840          74 :     return true;
     841             : }
     842             : 
     843          74 : void VrfTable::VrfReuse(const std::string  name) {
     844          74 :     IFMapTable::RequestKey req_key;
     845          74 :     req_key.id_type = "routing-instance";
     846          74 :     req_key.id_name = name;
     847          74 :     IFMapNode *node = IFMapAgentTable::TableEntryLookup(database(), &req_key);
     848             : 
     849          74 :     if (!node || node->IsDeleted()) {
     850          74 :         return;
     851             :     }
     852             : 
     853           0 :     OPER_TRACE(Vrf, "Resyncing configuration for VRF: ", name);
     854           0 :     agent()->config_manager()->NodeResync(node);
     855          74 : }
     856             : 
     857          74 : void VrfTable::OnZeroRefcount(AgentDBEntry *e) {
     858          74 :     VrfEntry *vrf = static_cast<VrfEntry *>(e);
     859          74 :     std::scoped_lock lock(vrf->delete_reuse_mutex_);
     860          74 :     if (e->IsDeleted()) {
     861          74 :         vrf->DeleteRouteTables();
     862          74 :         name_tree_.erase(vrf->GetName());
     863          74 :         vrf->CancelDeleteTimer();
     864          74 :         vrf->deleted_ = true;
     865             :     }
     866          74 : }
     867             : 
     868           2 : DBTableBase *VrfTable::CreateTable(DB *db, const std::string &name) {
     869           2 :     vrf_table_ = new VrfTable(db, name);
     870           2 :     vrf_table_->Init();
     871           2 :     return vrf_table_;
     872             : };
     873             : 
     874       22272 : VrfEntry *VrfTable::FindVrfFromName(const string &name) {
     875       22272 :     VrfNameTree::const_iterator it;
     876             : 
     877       22272 :     it = name_tree_.find(name);
     878       22272 :     if (it == name_tree_.end()) {
     879         125 :         return NULL;
     880             :     }
     881             : 
     882       22147 :     return static_cast<VrfEntry *>(it->second);
     883             : }
     884             : 
     885       44151 : VrfEntry *VrfTable::FindVrfFromId(size_t index) {
     886       44151 :     VrfEntry *vrf = index_table_.At(index);
     887       44151 :     if (vrf && vrf->IsDeleted() == false) {
     888       39116 :         return vrf;
     889             :     }
     890        5035 :     return NULL;
     891             : }
     892             : 
     893        1548 : VrfEntry *VrfTable::FindVrfFromIdIncludingDeletedVrf(size_t index) {
     894        1548 :     VrfEntry *vrf = index_table_.At(index);
     895        1548 :     return vrf;
     896             : }
     897             : 
     898        1661 : InetUnicastAgentRouteTable *VrfTable::GetInet4UnicastRouteTable
     899             :     (const string &vrf_name) {
     900             :     return static_cast<InetUnicastAgentRouteTable *>
     901        1661 :         (GetRouteTable(vrf_name, Agent::INET4_UNICAST));
     902             : }
     903             : 
     904           2 : InetUnicastAgentRouteTable *VrfTable::GetInet4MplsUnicastRouteTable
     905             :     (const string &vrf_name) {
     906             :     return static_cast<InetUnicastAgentRouteTable *>
     907           2 :         (GetRouteTable(vrf_name, Agent::INET4_MPLS));
     908             : }
     909             : 
     910           0 : AgentRouteTable *VrfTable::GetInet4MulticastRouteTable(const string &vrf_name) {
     911           0 :     return GetRouteTable(vrf_name, Agent::INET4_MULTICAST);
     912             : }
     913             : 
     914        2004 : AgentRouteTable *VrfTable::GetEvpnRouteTable(const string &vrf_name) {
     915        2004 :     return GetRouteTable(vrf_name, Agent::EVPN);
     916             : }
     917             : 
     918        3308 : AgentRouteTable *VrfTable::GetBridgeRouteTable(const string &vrf_name) {
     919        3308 :     return GetRouteTable(vrf_name, Agent::BRIDGE);
     920             : }
     921             : 
     922         501 : InetUnicastAgentRouteTable *VrfTable::GetInet6UnicastRouteTable
     923             :     (const string &vrf_name) {
     924             :     return static_cast<InetUnicastAgentRouteTable *>
     925         501 :         (GetRouteTable(vrf_name, Agent::INET6_UNICAST));
     926             : }
     927             : 
     928        7920 : AgentRouteTable *VrfTable::GetRouteTable(const string &vrf_name,
     929             :                                          uint8_t table_type) {
     930        7920 :     VrfDbTree::const_iterator it;
     931             : 
     932        7920 :     it = dbtree_[table_type].find(vrf_name);
     933        7920 :     if (it == dbtree_[table_type].end()) {
     934           0 :         return NULL;
     935             :     }
     936             : 
     937        7920 :     return static_cast<AgentRouteTable *>(it->second);
     938             : }
     939             : 
     940           0 : void VrfTable::CreateVrfReq(const string &name, uint32_t flags) {
     941           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
     942           0 :     req.key.reset(new VrfKey(name));
     943           0 :     req.data.reset(new VrfData(agent(), NULL, flags, boost::uuids::nil_uuid(),
     944           0 :                                0, "", 0, false));
     945           0 :     Enqueue(&req);
     946           0 : }
     947             : 
     948           0 : void VrfTable::CreateVrfReq(const string &name,
     949             :                             const boost::uuids::uuid &vn_uuid,
     950             :                             uint32_t flags) {
     951           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
     952           0 :     req.key.reset(new VrfKey(name));
     953           0 :     req.data.reset(new VrfData(agent(), NULL, flags, vn_uuid,
     954           0 :                                0, "", 0, false));
     955           0 :     Enqueue(&req);
     956           0 : }
     957             : 
     958           0 : void VrfTable::CreateVrf(const string &name, const boost::uuids::uuid &vn_uuid,
     959             :                          uint32_t flags, uint32_t isid,
     960             :                          const std::string &bmac_vrf_name,
     961             :                          uint32_t aging_timeout,
     962             :                          bool learning_enabled) {
     963           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
     964           0 :     req.key.reset(new VrfKey(name));
     965           0 :     req.data.reset(new VrfData(agent(), NULL, flags, vn_uuid, isid,
     966             :                                bmac_vrf_name, aging_timeout,
     967           0 :                                learning_enabled));
     968           0 :     Process(req);
     969           0 : }
     970             : 
     971           2 : void VrfTable::CreateVrf(const string &name,
     972             :                          const boost::uuids::uuid &vn_uuid,
     973             :                          uint32_t flags) {
     974           2 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
     975           2 :     req.key.reset(new VrfKey(name));
     976           4 :     req.data.reset(new VrfData(agent(), NULL, flags, vn_uuid, 0,
     977           2 :                                "", 0, false));
     978           2 :     Process(req);
     979           2 : }
     980           6 : void VrfTable::DeleteVrfReq(const string &name, uint32_t flags) {
     981           6 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
     982           6 :     req.key.reset(new VrfKey(name));
     983          12 :     req.data.reset(new VrfData(agent(), NULL, flags, boost::uuids::nil_uuid(),
     984           6 :                                0, "", 0, false));
     985           6 :     Enqueue(&req);
     986           6 : }
     987             : 
     988           0 : void VrfTable::DeleteVrf(const string &name, uint32_t flags) {
     989           0 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
     990           0 :     req.key.reset(new VrfKey(name));
     991           0 :     req.data.reset(new VrfData(agent(), NULL, flags, boost::uuids::nil_uuid(),
     992           0 :                                0, "", 0, false));
     993           0 :     Process(req);
     994           0 : }
     995             : 
     996           2 : void VrfTable::CreateStaticVrf(const string &name) {
     997           2 :     static_vrf_set_.insert(name);
     998           2 :     CreateVrf(name, boost::uuids::nil_uuid(), VrfData::ConfigVrf);
     999           2 : }
    1000             : 
    1001           2 : void VrfTable::CreateFabricPolicyVrf(const string &name) {
    1002           2 :     static_vrf_set_.insert(name);
    1003           2 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1004           2 :     req.key.reset(new VrfKey(name));
    1005           2 :     VrfData *data = new VrfData(agent(), NULL, VrfData::ConfigVrf,
    1006           2 :                                 boost::uuids::nil_uuid(), 0, "", 0, false);
    1007           2 :     data->forwarding_vrf_name_ = agent()->fabric_vrf_name();
    1008           2 :     req.data.reset(data);
    1009           2 :     Process(req);
    1010           2 : }
    1011             : 
    1012           6 : void VrfTable::DeleteStaticVrf(const string &name) {
    1013           6 :     static_vrf_set_.erase(name);
    1014           6 :     DeleteVrfReq(name);
    1015           6 : }
    1016             : 
    1017         444 : void VrfTable::DeleteFromDbTree(int table_type, const std::string &vrf_name) {
    1018         444 :     dbtree_[table_type].erase(vrf_name);
    1019         444 : }
    1020             : 
    1021        2198 : void VrfTable::Input(DBTablePartition *partition, DBClient *client,
    1022             :                      DBRequest *req) {
    1023             : 
    1024        2198 :     VrfKey *key = static_cast<VrfKey *>(req->key.get());
    1025        2198 :     VrfEntry *entry = static_cast<VrfEntry *>(partition->Find(key));
    1026             : 
    1027        2198 :     if (entry && entry->IsDeleted()) {
    1028        1477 :         if (req->oper != DBRequest::DB_ENTRY_NOTIFY) {
    1029          68 :             OPER_TRACE(Vrf, "VRF pending delete, Ignoring DB operation for ",
    1030             :                        entry->GetName());
    1031          68 :             return;
    1032             :         } else {
    1033             :             // Allow DB Operation for DB Entry Notify, along with
    1034             :             // validation for sub op as ADD_DEL_CHANGE
    1035        1409 :             AgentKey *key = static_cast<AgentKey *>(req->key.get());
    1036        1409 :             assert(key->sub_op_ == AgentKey::ADD_DEL_CHANGE);
    1037             :         }
    1038             :     }
    1039             : 
    1040        2130 :     AgentDBTable::Input(partition, client, req);
    1041        2130 :     return;
    1042             : }
    1043             : 
    1044           0 : static void FindHbfInterfacesFromHBS(Agent* agent, IFMapNode *node,
    1045             :                               uint32_t &hbf_rintf, uint32_t &hbf_lintf) {
    1046           0 :     IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
    1047           0 :     DBGraph *graph = table->GetGraph();
    1048             : 
    1049           0 :     for (DBGraphVertex::edge_iterator iter = node->edge_list_begin(graph);
    1050           0 :          iter != node->edge_list_end(graph); ++iter) {
    1051           0 :         if (iter->IsDeleted()) {
    1052           0 :             continue;
    1053             :         }
    1054           0 :         IFMapNode *adj_node = static_cast<IFMapNode *>(iter.target());
    1055             : 
    1056           0 :         if (!strcmp(adj_node->table()->Typename(),
    1057             :                     "host-based-service-virtual-network")) {
    1058             :             autogen::HostBasedServiceVirtualNetwork *hbsvn =
    1059             :                 static_cast<HostBasedServiceVirtualNetwork *>
    1060           0 :                 (adj_node->GetObject());
    1061           0 :             ServiceVirtualNetworkType type = hbsvn->data();
    1062             : 
    1063           0 :             for (DBGraphVertex::adjacency_iterator iter =
    1064           0 :                  adj_node->begin(graph);
    1065           0 :                  iter != node->end(graph); ++iter) {
    1066             :                  IFMapNode *hbsvn_adj_node =
    1067           0 :                          static_cast<IFMapNode *>(iter.operator->());
    1068           0 :                  if (!strcmp(hbsvn_adj_node->table()->Typename(),
    1069             :                              "virtual-network")) {
    1070           0 :                      for (DBGraphVertex::adjacency_iterator iter =
    1071           0 :                                                    hbsvn_adj_node->begin(graph);
    1072           0 :                           iter != node->end(graph); ++iter) {
    1073           0 :                          if (iter->IsDeleted()) {
    1074           0 :                             continue;
    1075             :                          }
    1076             :                          IFMapNode *vmi_node =
    1077           0 :                              static_cast<IFMapNode *>(iter.operator->());
    1078           0 :                          if (!strcmp(vmi_node->table()->Typename(),
    1079             :                                     "virtual-machine-interface")) {
    1080             :                              VirtualMachineInterface *cfg =
    1081             :                                  static_cast <VirtualMachineInterface *>
    1082           0 :                                                       (vmi_node->GetObject());
    1083           0 :                              autogen::IdPermsType id_perms = cfg->id_perms();
    1084             :                              boost::uuids::uuid u;
    1085           0 :                              CfgUuidSet(id_perms.uuid.uuid_mslong,
    1086             :                                         id_perms.uuid.uuid_lslong, u);
    1087             :                              InterfaceConstRef intf =
    1088           0 :                                  agent->interface_table()->FindVmi(u);
    1089           0 :                              if (!intf) {
    1090           0 :                                  continue;
    1091             :                              }
    1092           0 :                              if (!strcmp(type.virtual_network_type.c_str(),
    1093             :                                          "right")) {
    1094           0 :                                  hbf_rintf = intf->id();
    1095           0 :                              } else if (!strcmp(
    1096             :                                  type.virtual_network_type.c_str(), "left")) {
    1097           0 :                                  hbf_lintf = intf->id();
    1098             :                              }
    1099           0 :                          }
    1100             :                      }
    1101             :                 }
    1102             :             }
    1103           0 :         }
    1104             :     }
    1105           0 : }
    1106             : 
    1107           0 : static void FindHbfInterfacesFromProject(Agent* agent, IFMapNode *node,
    1108             :                               uint32_t &hbf_rintf, uint32_t &hbf_lintf) {
    1109           0 :     IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
    1110           0 :     DBGraph *graph = table->GetGraph();
    1111             : 
    1112           0 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
    1113           0 :          iter != node->end(graph); ++iter) {
    1114           0 :         if (iter->IsDeleted()) {
    1115           0 :             continue;
    1116             :         }
    1117             :         IFMapNode *adj_node =
    1118           0 :                          static_cast<IFMapNode *>(iter.operator->());
    1119             : 
    1120           0 :         if (strcmp(adj_node->table()->Typename(), "host-based-service") == 0) {
    1121           0 :             FindHbfInterfacesFromHBS(agent, adj_node, hbf_rintf, hbf_lintf);
    1122           0 :             break;
    1123             :         }
    1124             :     }
    1125           0 : }
    1126             : 
    1127         371 : static void FindHbfInterfacesFromVmi(Agent* agent, IFMapNode *node,
    1128             :                               uint32_t &hbf_rintf, uint32_t &hbf_lintf) {
    1129         371 :     IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
    1130         371 :     DBGraph *graph = table->GetGraph();
    1131             : 
    1132         371 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
    1133        1840 :          iter != node->end(graph); ++iter) {
    1134        1469 :         if (iter->IsDeleted()) {
    1135           0 :             continue;
    1136             :         }
    1137             :         IFMapNode *adj_node =
    1138        1469 :                          static_cast<IFMapNode *>(iter.operator->());
    1139             : 
    1140        1469 :         if (strcmp(adj_node->table()->Typename(), "project") == 0) {
    1141           0 :             FindHbfInterfacesFromProject(agent, adj_node, hbf_rintf, hbf_lintf);
    1142           0 :             break;
    1143             :         }
    1144             :     }
    1145         371 : }
    1146             : 
    1147         491 : static void FindHbfInterfaces(Agent *agent, IFMapNode *vn_node,
    1148             :                               uint32_t &hbf_rintf, uint32_t &hbf_lintf) {
    1149         491 :     IFMapAgentTable *table = static_cast<IFMapAgentTable *>(vn_node->table());
    1150         491 :     DBGraph *graph = table->GetGraph();
    1151             : 
    1152         491 :     for (DBGraphVertex::adjacency_iterator iter = vn_node->begin(graph);
    1153         686 :          iter != vn_node->end(graph); ++iter) {
    1154         566 :         if (iter->IsDeleted()) {
    1155           0 :             continue;
    1156             :         }
    1157             :         IFMapNode *adj_node =
    1158         566 :                          static_cast<IFMapNode *>(iter.operator->());
    1159             : 
    1160         566 :         if (strcmp(adj_node->table()->Typename(),
    1161         566 :                    "virtual-machine-interface") == 0) {
    1162         371 :             FindHbfInterfacesFromVmi(agent, adj_node, hbf_rintf, hbf_lintf);
    1163         371 :             break;
    1164             :         }
    1165             :     }
    1166         491 : }
    1167             : 
    1168         491 : static void BuildForwardingVrf(Agent *agent, IFMapNode *vn_node,
    1169             :                                std::string &forwarding_vrf_name) {
    1170         491 :     IFMapAgentTable *table = static_cast<IFMapAgentTable *>(vn_node->table());
    1171         491 :     DBGraph *graph = table->GetGraph();
    1172         491 :     for (DBGraphVertex::adjacency_iterator iter = vn_node->begin(graph);
    1173        2057 :          iter != vn_node->end(graph); ++iter) {
    1174             :          IFMapNode *adj_node =
    1175        1566 :                          static_cast<IFMapNode *>(iter.operator->());
    1176        3132 :         if (iter->IsDeleted() ||
    1177        1566 :            (adj_node->table() != agent->cfg()->cfg_vn_table())) {
    1178        1566 :             continue;
    1179             :         }
    1180             : 
    1181             :         VirtualNetwork *cfg =
    1182           0 :             static_cast <VirtualNetwork *> (adj_node->GetObject());
    1183           0 :         if (cfg == NULL) {
    1184           0 :             continue;
    1185             :         }
    1186             : 
    1187           0 :         if (adj_node->name() == agent->fabric_vn_name()) {
    1188           0 :             forwarding_vrf_name = agent->fabric_vrf_name();
    1189             :         }
    1190             :     }
    1191         491 : }
    1192             : 
    1193         643 : static VrfData *BuildData(Agent *agent, IFMapNode *node) {
    1194         643 :     boost::uuids::uuid vn_uuid = boost::uuids::nil_uuid();
    1195         643 :     boost::uuids::uuid si_vn_uuid = boost::uuids::nil_uuid();
    1196         643 :     IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
    1197         643 :     DBGraph *graph = table->GetGraph();
    1198         643 :     bool learning_enabled = false;
    1199         643 :     std::string forwarding_vrf = "";
    1200         643 :     uint32_t hbf_rintf = Interface::kInvalidIndex;
    1201         643 :     uint32_t hbf_lintf = Interface::kInvalidIndex;
    1202             : 
    1203         643 :     uint32_t aging_timeout = 0;
    1204         643 :     for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
    1205        1450 :          iter != node->end(graph); ++iter) {
    1206             :         IFMapNode *adj_node =
    1207        1298 :             static_cast<IFMapNode *>(iter.operator->());
    1208             : 
    1209        2596 :         if (iter->IsDeleted() ||
    1210        1298 :             (adj_node->table() != agent->cfg()->cfg_vn_table())) {
    1211         807 :             continue;
    1212             :         }
    1213             : 
    1214             :         VirtualNetwork *cfg =
    1215         491 :             static_cast <VirtualNetwork *> (adj_node->GetObject());
    1216         491 :         if (cfg == NULL) {
    1217           0 :             continue;
    1218             :         }
    1219             : 
    1220         491 :         BuildForwardingVrf(agent, adj_node, forwarding_vrf);
    1221             : 
    1222         491 :         FindHbfInterfaces(agent, adj_node, hbf_rintf, hbf_lintf);
    1223             : 
    1224         491 :         if (!IsVRFServiceChainingInstance(adj_node->name(), node->name())) {
    1225         491 :             autogen::IdPermsType id_perms = cfg->id_perms();
    1226         491 :             CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
    1227             :                        vn_uuid);
    1228         491 :             aging_timeout = cfg->mac_aging_time();
    1229         491 :             break;
    1230         491 :         } else {
    1231           0 :             autogen::IdPermsType id_perms = cfg->id_perms();
    1232           0 :             CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
    1233             :                        si_vn_uuid);
    1234           0 :             break;
    1235           0 :         }
    1236             :     }
    1237             : 
    1238             :     VrfData *vrf_data = new VrfData(agent, node, VrfData::ConfigVrf,
    1239             :                                     vn_uuid, 0, "",
    1240             :                                     aging_timeout, learning_enabled,
    1241         643 :                                     hbf_rintf, hbf_lintf);
    1242         643 :     if (node->name() == agent->fabric_policy_vrf_name()) {
    1243           0 :         vrf_data->forwarding_vrf_name_ = agent->fabric_vrf_name();
    1244             :     } else {
    1245         643 :         vrf_data->forwarding_vrf_name_ = forwarding_vrf;
    1246             :     }
    1247             : 
    1248         643 :     vrf_data->si_vn_ref_uuid_ = si_vn_uuid;
    1249             : 
    1250         643 :     return vrf_data;
    1251         643 : }
    1252             : 
    1253        1056 : bool VrfTable::IFNodeToReq(IFMapNode *node, DBRequest &req,
    1254             :         const boost::uuids::uuid &u) {
    1255             :     //Trigger add or delete only for non fabric VRF
    1256        1056 :     if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
    1257         133 :         req.key.reset(new VrfKey(node->name()));
    1258         133 :         if (IsStaticVrf(node->name())) {
    1259             :             //Fabric and link-local VRF will not be deleted,
    1260             :             //upon config delete
    1261           0 :             req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1262             :         } else {
    1263         133 :             req.oper = DBRequest::DB_ENTRY_DELETE;
    1264             :         }
    1265             : 
    1266         133 :         VrfData *data = new VrfData(agent(), node, VrfData::ConfigVrf,
    1267         133 :                                     boost::uuids::nil_uuid(), 0, "", 0, false);
    1268         133 :         if (node->name() == agent()->fabric_policy_vrf_name()) {
    1269           0 :             data->forwarding_vrf_name_ = agent()->fabric_vrf_name();
    1270             :         }
    1271         133 :         req.data.reset(data);
    1272         133 :         Enqueue(&req);
    1273         133 :         return false;
    1274             :     }
    1275             : 
    1276         923 :     agent()->config_manager()->AddVrfNode(node);
    1277         923 :     return false;
    1278             : }
    1279             : 
    1280         646 : bool VrfTable::ProcessConfig(IFMapNode *node, DBRequest &req,
    1281             :         const boost::uuids::uuid &u) {
    1282         646 :     req.key.reset(new VrfKey(node->name()));
    1283             : 
    1284             :     //Trigger add or delete only for non fabric VRF
    1285         646 :     if (node->IsDeleted()) {
    1286           3 :         if (IsStaticVrf(node->name())) {
    1287             :             //Fabric and link-local VRF will not be deleted,
    1288             :             //upon config delete
    1289           0 :             req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1290             :         } else {
    1291           3 :             req.oper = DBRequest::DB_ENTRY_DELETE;
    1292             :         }
    1293             : 
    1294           3 :         VrfData *data = new VrfData(agent(), node, VrfData::ConfigVrf,
    1295           3 :                                     boost::uuids::nil_uuid(), 0, "", 0, false,
    1296             :                                     Interface::kInvalidIndex,
    1297           3 :                                     Interface::kInvalidIndex);
    1298           3 :         if (node->name() == agent()->fabric_policy_vrf_name()) {
    1299           0 :             data->forwarding_vrf_name_ = agent()->fabric_vrf_name();
    1300             :         }
    1301           3 :         req.data.reset(data);
    1302             :     } else {
    1303         643 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1304         643 :         req.data.reset(BuildData(agent(), node));
    1305             :     }
    1306             : 
    1307             :     //When VRF config delete comes, first enqueue VRF delete
    1308             :     //so that when link evaluation happens, all point to deleted VRF
    1309         646 :     Enqueue(&req);
    1310         646 :     return false;
    1311             : }
    1312             : 
    1313           0 : void VrfListReq::HandleRequest() const {
    1314           0 :     AgentSandeshPtr sand(new AgentVrfSandesh(context(), get_name()));
    1315           0 :     sand->DoSandesh(sand);
    1316           0 : }
    1317             : 
    1318           0 : AgentSandeshPtr VrfTable::GetAgentSandesh(const AgentSandeshArguments *args,
    1319             :                                           const std::string &context) {
    1320             :     return AgentSandeshPtr(new AgentVrfSandesh(context,
    1321           0 :                                                args->GetString("name")));
    1322             : }
    1323             : 
    1324             : class RouteDeleteWalker : public AgentRouteWalker {
    1325             : public:
    1326           2 :     RouteDeleteWalker(const std::string &name, Agent *agent) :
    1327           2 :         AgentRouteWalker(name, agent) {
    1328           2 :     }
    1329             : 
    1330           4 :     ~RouteDeleteWalker() { }
    1331             : 
    1332             :     //Override route notification
    1333          28 :     bool RouteWalkNotify(DBTablePartBase *partition, DBEntryBase *e) {
    1334          28 :         AgentRoute *rt = static_cast<AgentRoute *>(e);
    1335          56 :         for(Route::PathList::const_iterator it = rt->GetPathList().begin();
    1336         116 :             it != rt->GetPathList().end(); ) {
    1337             :             const AgentPath *path =
    1338          30 :                 static_cast<const AgentPath *>(it.operator->());
    1339          30 :             Route::PathList::const_iterator next = ++it;
    1340             : 
    1341          30 :             DBRequest req(DBRequest::DB_ENTRY_DELETE);
    1342          30 :             req.key = e->GetDBRequestKey();
    1343          30 :             AgentRouteKey *key = static_cast<AgentRouteKey *>(req.key.get());
    1344          30 :             key->peer_ = path->peer();
    1345          30 :             (static_cast<AgentRouteTable *>(e->get_table()))->Process(req);
    1346             :             it = next;
    1347          30 :         }
    1348             : 
    1349          28 :         return true;
    1350             :     }
    1351             : 
    1352           2 :     static void WalkDone(RouteDeleteWalker *walker) {
    1353           2 :         walk_done_++;
    1354           2 :         walker->mgr()->ReleaseWalker(walker);
    1355           2 :         walker->agent()->vrf_table()->reset_route_delete_walker();
    1356           2 :     }
    1357             : 
    1358             :     static uint32_t walk_start_;
    1359             :     static uint32_t walk_done_;
    1360             : };
    1361             : uint32_t RouteDeleteWalker::walk_start_;
    1362             : uint32_t RouteDeleteWalker::walk_done_;
    1363             : 
    1364           2 : void VrfTable::DeleteRoutes() {
    1365           2 :     if (route_delete_walker_.get() == NULL) {
    1366             :         route_delete_walker_ = new RouteDeleteWalker("RouteDeleteWalker",
    1367           2 :                                                      agent());
    1368             :         agent()->oper_db()->agent_route_walk_manager()->
    1369           2 :             RegisterWalker(static_cast<AgentRouteWalker *>
    1370             :                            (route_delete_walker_.get()));
    1371             :     }
    1372             :     route_delete_walker_->WalkDoneCallback
    1373           4 :         (boost::bind(&RouteDeleteWalker::WalkDone,
    1374           2 :                 static_cast<RouteDeleteWalker *>(route_delete_walker_.get())));
    1375           2 :     route_delete_walker_->StartVrfWalk();
    1376           2 : }
    1377             : 
    1378           0 : void VrfTable::Shutdown() {
    1379           0 :     if (vrf_delete_walker_.get() == NULL) {
    1380             :         vrf_delete_walker_ = new VrfDeleteWalker("VrfDeleteWalker",
    1381           0 :                                                  agent());
    1382             :         agent()->oper_db()->agent_route_walk_manager()->
    1383           0 :             RegisterWalker(static_cast<AgentRouteWalker *>
    1384             :                            (vrf_delete_walker_.get()));
    1385             :     }
    1386           0 :     vrf_delete_walker_.get()->WalkDoneCallback(boost::bind
    1387             :                (&VrfDeleteWalker::WalkDone,
    1388           0 :                static_cast<VrfDeleteWalker *>( vrf_delete_walker_.get())));
    1389           0 :     vrf_delete_walker_.get()->StartVrfWalk();
    1390           0 : }

Generated by: LCOV version 1.14