LCOV - code coverage report
Current view: top level - vnsw/agent/oper - peer.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 189 0.0 %
Date: 2026-06-22 02:21:21 Functions: 0 40 0.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             : #include <oper/vrf.h>
       7             : #include <oper/route_common.h>
       8             : #include <oper/peer.h>
       9             : #include <oper/agent_route_walker.h>
      10             : #include <oper/mirror_table.h>
      11             : 
      12             : #include <controller/controller_route_walker.h>
      13             : #include <controller/controller_peer.h>
      14             : #include <controller/controller_vrf_export.h>
      15             : #include <controller/controller_export.h>
      16             : #include <controller/controller_init.h>
      17             : 
      18           0 : Peer::Peer(Type type, const std::string &name, bool export_to_controller) :
      19           0 :     type_(type), name_(name), export_to_controller_(export_to_controller) {
      20           0 :     refcount_ = 0;
      21           0 :     sequence_number_ = 0;
      22           0 : }
      23             : 
      24           0 : Peer::~Peer() {
      25           0 : }
      26             : 
      27           0 : bool Peer::DeleteOnZeroRefcount() const {
      28           0 :     return false;
      29             : }
      30             : 
      31           0 : void intrusive_ptr_add_ref(const Peer *p) {
      32           0 :     p->refcount_++;
      33             :     // validate that reference is not taken while delete is in progress
      34           0 :     assert(!p->IsDeleted());
      35           0 : }
      36             : 
      37           0 : void intrusive_ptr_release(const Peer *p) {
      38           0 :     if (p->refcount_.fetch_sub(1) == 1 && p->DeleteOnZeroRefcount()) {
      39           0 :         delete p;
      40             :     }
      41           0 : }
      42             : 
      43           0 : DynamicPeer::DynamicPeer(Agent *agent, Type type, const std::string &name,
      44           0 :                          bool export_to_controller) :
      45           0 :     Peer(type, name, export_to_controller) {
      46           0 :     delete_timeout_timer_ = TimerManager::CreateTimer(
      47           0 :                                 *(agent->event_manager())->io_service(),
      48             :                                 "Dynamic Peer Delete Timer",
      49             :                                 agent->task_scheduler()->\
      50             :                                 GetTaskId("db::DBTable"), 0);
      51           0 :     deleted_ = false;
      52           0 :     skip_add_change_ = false;
      53           0 : }
      54             : 
      55           0 : DynamicPeer::~DynamicPeer() {
      56             :     // Dynamic Peer should be marked deleted and will free
      57             :     // automatically once all the references go away
      58           0 :     assert(deleted_);
      59           0 :     assert(refcount() == 0);
      60           0 :     TimerManager::DeleteTimer(delete_timeout_timer_);
      61           0 : }
      62             : 
      63           0 : void DynamicPeer::ProcessDelete(DynamicPeer *p) {
      64           0 :     p->StopRouteExports();
      65             : 
      66           0 :     if (p->deleted_.exchange(true)) {
      67           0 :         return;
      68             :     }
      69             : 
      70           0 :     if (p->refcount() != 0) {
      71             :         // still pending references are there start delete timeout timer
      72           0 :         p->delete_timeout_timer_->Start(kDeleteTimeout,
      73             :                                      boost::bind(&DynamicPeer::DeleteTimeout,
      74             :                                      p));
      75           0 :         return;
      76             :     }
      77             : 
      78             :     // no pending references delete the peer inline and return
      79           0 :     delete p;
      80             : }
      81             : 
      82           0 : bool DynamicPeer::DeleteTimeout() {
      83           0 :     assert(0);
      84             :     return false;
      85             : }
      86             : 
      87           0 : bool DynamicPeer::DeleteOnZeroRefcount() const {
      88           0 :     if (!deleted_) {
      89           0 :         return false;
      90             :     }
      91             : 
      92             :     // last reference has gone, cancel the timer and delete peer
      93           0 :     delete_timeout_timer_->Cancel();
      94             : 
      95           0 :     return true;
      96             : }
      97             : 
      98           0 : const Ip4Address *Peer::NexthopIp(Agent *agent, const AgentPath *path) const {
      99           0 :     return agent->router_ip_ptr();
     100             : }
     101             : 
     102           0 : BgpPeer::BgpPeer(AgentXmppChannel *channel, const Ip4Address &server_ip,
     103             :                  const std::string &name, DBTableBase::ListenerId id,
     104           0 :                  Peer::Type bgp_peer_type) :
     105             :     DynamicPeer(channel->agent(), bgp_peer_type, name, false),
     106           0 :     channel_(channel), server_ip_(server_ip), id_(id),
     107           0 :     delete_stale_walker_(NULL), route_walker_cb_(NULL),
     108           0 :     delete_stale_walker_cb_(NULL) {
     109           0 :         AllocPeerNotifyWalker();
     110           0 :         AllocDeleteStaleWalker();
     111           0 :         AllocDeletePeerWalker();
     112           0 :         setup_time_ = UTCTimestampUsec();
     113           0 : }
     114             : 
     115           0 : BgpPeer::~BgpPeer() {
     116           0 :     const Agent *agent = route_walker()->agent();
     117             :     // TODO verify if this unregister can be done in walkdone callback
     118             :     // for delpeer
     119           0 :     if ((id_ != -1) && agent->vrf_table()) {
     120           0 :         agent->vrf_table()->Unregister(id_);
     121             :     }
     122           0 :     ReleaseDeleteStaleWalker();
     123           0 :     ReleaseDeletePeerWalker();
     124           0 :     ReleasePeerNotifyWalker();
     125           0 : }
     126             : 
     127             : // Route notify walker routines
     128           0 : void BgpPeer::AllocPeerNotifyWalker() {
     129           0 :     if (!route_walker()) {
     130           0 :         Agent *agent = channel_->agent();
     131           0 :         route_walker_ = new ControllerRouteWalker(server_ip_.to_string(),
     132           0 :                                                   this);
     133             :         agent->oper_db()->agent_route_walk_manager()->
     134           0 :             RegisterWalker(static_cast<AgentRouteWalker *>
     135             :                            (route_walker_.get()));
     136             :     }
     137           0 : }
     138             : 
     139           0 : void BgpPeer::ReleasePeerNotifyWalker() {
     140           0 :     if (!route_walker()) {
     141           0 :         return;
     142             :     }
     143             : 
     144           0 :     Agent *agent = Agent::GetInstance();
     145           0 :     agent->oper_db()->agent_route_walk_manager()->ReleaseWalker(route_walker());
     146           0 :     route_walker_.reset();
     147             : }
     148             : 
     149           0 : void BgpPeer::PeerNotifyRoutes(WalkDoneCb cb) {
     150           0 :     route_walker_cb_ = cb;
     151           0 :     route_walker()->Start(ControllerRouteWalker::NOTIFYALL, true,
     152           0 :                           route_walker_cb_);
     153           0 : }
     154             : 
     155           0 : void BgpPeer::StopPeerNotifyRoutes() {
     156             :     //No implementation of stop, to stop a walk release walker. Re-allocate for
     157             :     //further use.
     158           0 :     ReleasePeerNotifyWalker();
     159           0 :     AllocPeerNotifyWalker();
     160           0 : }
     161             : 
     162           0 : void BgpPeer::PeerNotifyMulticastRoutes(bool associate) {
     163           0 :     route_walker()->Start(ControllerRouteWalker::NOTIFYMULTICAST, associate,
     164             :                           NULL);
     165           0 : }
     166             : 
     167             : // Delete stale walker routines
     168           0 : void BgpPeer::AllocDeleteStaleWalker() {
     169           0 :     if (!delete_stale_walker()) {
     170           0 :         Agent *agent = channel_->agent();
     171           0 :         delete_stale_walker_ = new ControllerRouteWalker(server_ip_.to_string(),
     172           0 :                                                          this);
     173             :         agent->oper_db()->agent_route_walk_manager()->
     174           0 :             RegisterWalker(static_cast<AgentRouteWalker *>
     175             :                            (delete_stale_walker_.get()));
     176             :     }
     177           0 : }
     178             : 
     179           0 : void BgpPeer::ReleaseDeleteStaleWalker() {
     180           0 :     if (!delete_stale_walker()) {
     181           0 :         return;
     182             :     }
     183             : 
     184           0 :     Agent *agent = Agent::GetInstance();
     185             :     agent->oper_db()->agent_route_walk_manager()->
     186           0 :         ReleaseWalker(delete_stale_walker());
     187           0 :     delete_stale_walker_.reset();
     188             : }
     189             : 
     190             : // Delete stale walker routines
     191           0 : void BgpPeer::AllocDeletePeerWalker() {
     192           0 :     if (!delete_peer_walker()) {
     193           0 :         Agent *agent = channel_->agent();
     194           0 :         delete_peer_walker_ = new ControllerRouteWalker(server_ip_.to_string(),
     195           0 :                                                          this);
     196             :         agent->oper_db()->agent_route_walk_manager()->
     197           0 :             RegisterWalker(static_cast<AgentRouteWalker *>
     198             :                            (delete_peer_walker_.get()));
     199             :     }
     200           0 : }
     201             : 
     202           0 : void BgpPeer::ReleaseDeletePeerWalker() {
     203           0 :     if (!delete_peer_walker()) {
     204           0 :         return;
     205             :     }
     206             : 
     207           0 :     Agent *agent = Agent::GetInstance();
     208             :     agent->oper_db()->agent_route_walk_manager()->
     209           0 :         ReleaseWalker(delete_peer_walker());
     210           0 :     delete_peer_walker_.reset();
     211             : }
     212             : 
     213           0 : void BgpPeer::DelPeerRoutes(WalkDoneCb walk_done_cb,
     214             :                             uint64_t sequence_number) {
     215             :     //Since peer is getting deleted no need of seperate walk to delete stale or
     216             :     //non stale paths.
     217           0 :     ReleaseDeleteStaleWalker();
     218           0 :     delete_peer_walker_cb_ = walk_done_cb;
     219           0 :     delete_peer_walker()->set_sequence_number(sequence_number);
     220           0 :     delete_peer_walker()->Start(ControllerRouteWalker::DELPEER, false,
     221           0 :                           delete_peer_walker_cb_);
     222           0 : }
     223             : 
     224           0 : void BgpPeer::DeleteStale() {
     225             :     //If peer is marked for deletion skip. Deletion should take care of removing
     226             :     //routes.
     227           0 :     if (SkipAddChangeRequest())
     228           0 :         return;
     229             : 
     230           0 :     delete_stale_walker()->set_sequence_number(sequence_number());
     231           0 :     delete_stale_walker()->Start(ControllerRouteWalker::DELSTALE, false,
     232           0 :                                 delete_stale_walker_cb_);
     233             : }
     234             : 
     235           0 : void BgpPeer::StopDeleteStale() {
     236             :     //No implementation of stop, to stop a walk release walker. Re-allocate for
     237             :     //further use.
     238           0 :     ReleaseDeleteStaleWalker();
     239           0 :     AllocDeleteStaleWalker();
     240           0 : }
     241             : 
     242           0 : ControllerRouteWalker *BgpPeer::route_walker() const {
     243           0 :     return static_cast<ControllerRouteWalker *>(route_walker_.get());
     244             : }
     245             : 
     246           0 : ControllerRouteWalker *BgpPeer::delete_stale_walker() const {
     247           0 :     return static_cast<ControllerRouteWalker *>(delete_stale_walker_.get());
     248             : }
     249             : 
     250           0 : ControllerRouteWalker *BgpPeer::delete_peer_walker() const {
     251           0 :     return static_cast<ControllerRouteWalker *>(delete_peer_walker_.get());
     252             : }
     253             : /*
     254             :  * Get the VRF state and unregister from all route table using
     255             :  * rt_export listener id. This will be called for active and non active bgp
     256             :  * peers. In case of active bgp peers send unsubscribe to control node(request
     257             :  * came via vrf delete).
     258             :  */
     259           0 : void BgpPeer::DeleteVrfState(DBTablePartBase *partition,
     260             :                              DBEntryBase *entry) {
     261           0 :     VrfEntry *vrf = static_cast<VrfEntry *>(entry);
     262             : 
     263           0 :     DBTableBase::ListenerId id = GetVrfExportListenerId();
     264             :     VrfExport::State *vrf_state = static_cast<VrfExport::State *>
     265           0 :         (GetVrfExportState(partition, entry));
     266             : 
     267           0 :     if (vrf_state == NULL)
     268           0 :         return;
     269             : 
     270           0 :     for (uint8_t table_type = (Agent::INVALID + 1);
     271           0 :          table_type < Agent::ROUTE_TABLE_MAX; table_type++) {
     272           0 :         if (vrf_state->rt_export_[table_type])
     273           0 :             vrf_state->rt_export_[table_type]->Unregister();
     274             :     }
     275             : 
     276           0 :     if (vrf_state->exported_ == true) {
     277             :         // Check if the notification is for active bgp peer or not.
     278             :         // Send unsubscribe only for active bgp peer.
     279             :         // If skip_add_change is set for this dynamic peer, then dont export.
     280           0 :         if (SkipAddChangeRequest() == false) {
     281           0 :             AgentXmppChannel::ControllerSendSubscribe(GetAgentXmppChannel(),
     282             :                                                       vrf,
     283             :                                                       false);
     284             :         }
     285             :     }
     286             : 
     287           0 :     vrf->ClearState(partition->parent(), id);
     288           0 :     delete vrf_state;
     289             : 
     290           0 :     return;
     291             : }
     292             : 
     293             : // For given peer return the dbstate for given VRF and partition
     294           0 : DBState *BgpPeer::GetVrfExportState(DBTablePartBase *partition,
     295             :                                     DBEntryBase *entry) {
     296           0 :     DBTableBase::ListenerId id = GetVrfExportListenerId();
     297           0 :     VrfEntry *vrf = static_cast<VrfEntry *>(entry);
     298           0 :     return (static_cast<VrfExport::State *>(vrf->GetState(partition->parent(),
     299           0 :                                                           id)));
     300             : }
     301             : 
     302             : // For given route return the dbstate for given partiton
     303           0 : DBState *BgpPeer::GetRouteExportState(DBTablePartBase *partition,
     304             :                                       DBEntryBase *entry) {
     305           0 :     AgentRoute *route = static_cast<AgentRoute *>(entry);
     306           0 :     VrfEntry *vrf = route->vrf();
     307             : 
     308           0 :     DBTablePartBase *vrf_partition = agent()->vrf_table()->
     309           0 :         GetTablePartition(vrf);
     310             : 
     311             :     VrfExport::State *vs = static_cast<VrfExport::State *>
     312           0 :         (GetVrfExportState(vrf_partition, vrf));
     313             : 
     314           0 :     if (vs == NULL)
     315           0 :         return NULL;
     316             : 
     317           0 :     Agent::RouteTableType table_type = route->GetTableType();
     318           0 :     RouteExport::State *state = NULL;
     319           0 :     if (vs->rt_export_[table_type]) {
     320           0 :         state = static_cast<RouteExport::State *>(route->GetState(partition->
     321             :                                                                   parent(),
     322           0 :                             vs->rt_export_[table_type]->GetListenerId()));
     323             :     }
     324           0 :     return state;
     325             : }
     326             : 
     327           0 : Agent *BgpPeer::agent() const {
     328           0 :     return channel_->agent();
     329             : }
     330             : 
     331           0 : AgentXmppChannel *BgpPeer::GetAgentXmppChannel() const {
     332           0 :     return channel_;
     333             : }
     334             : 
     335           0 : uint64_t BgpPeer::ChannelSequenceNumber() const {
     336           0 :     return GetAgentXmppChannel()->sequence_number();
     337             : }
     338             : 
     339           0 : void BgpPeer::set_route_walker_cb(WalkDoneCb cb) {
     340           0 :     route_walker_cb_ = cb;
     341           0 : }
     342             : 
     343           0 : void BgpPeer::set_delete_stale_walker_cb(WalkDoneCb cb) {
     344           0 :     delete_stale_walker_cb_ = cb;
     345           0 : }
     346           0 : void BgpPeer::set_delete_peer_walker_cb(WalkDoneCb cb) {
     347           0 :     delete_peer_walker_cb_ = cb;
     348           0 : }

Generated by: LCOV version 1.14