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

Generated by: LCOV version 1.14