LCOV - code coverage report
Current view: top level - bgp/routing-instance - peer_manager.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 125 133 94.0 %
Date: 2026-06-08 02:02:55 Functions: 16 17 94.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/routing-instance/peer_manager.h"
       6             : 
       7             : #include "base/task_annotations.h"
       8             : #include "base/address_util.h"
       9             : #include "bgp/bgp_factory.h"
      10             : #include "bgp/bgp_log.h"
      11             : #include "bgp/bgp_peer.h"
      12             : #include "bgp/bgp_peer_types.h"
      13             : #include "bgp/bgp_server.h"
      14             : #include "bgp/routing-instance/routing_instance.h"
      15             : #include "bgp/routing-instance/routing_instance_log.h"
      16             : 
      17             : struct BgpSandeshContext;
      18             : 
      19             : using std::make_pair;
      20             : using std::string;
      21             : using std::vector;
      22             : 
      23             : //
      24             : // Find or create a BgpPeer for the given BgpNeighborConfig.
      25             : // Return NULL if the peer already exists and is being deleted. The BgpPeer
      26             : // will eventually get created in this case via PeerResurrect.
      27             : //
      28       10335 : BgpPeer *PeerManager::PeerLocate(BgpServer *server,
      29             :     const BgpNeighborConfig *config) {
      30       10335 :     BgpPeerKey key(config);
      31             : 
      32       10335 :     BgpPeerNameMap::iterator loc = peers_by_name_.find(config->name());
      33       10335 :     if (loc != peers_by_name_.end()) {
      34         768 :         if (loc->second->IsDeleted())
      35           6 :             return NULL;
      36         762 :         RemovePeerByKey(loc->second->peer_key(), loc->second);
      37         762 :         InsertPeerByKey(key, loc->second);
      38         762 :         return loc->second;
      39             :     }
      40             : 
      41             :     BgpPeer *peer =
      42        9567 :         BgpStaticObjectFactory::Create<BgpPeer>(server, instance(), config);
      43        9567 :     peer->Initialize();
      44        9567 :     InsertPeerByKey(key, peer);
      45        9567 :     InsertPeerByName(config->name(), peer);
      46        9567 :     RoutingInstanceInfo info = instance_->GetDataCollection("Add");
      47        9567 :     info.set_peer(peer->ToString());
      48        9567 :     ROUTING_INSTANCE_COLLECTOR_INFO(info);
      49             : 
      50        9567 :     BGP_LOG_PEER(Config, peer, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
      51             :                  BGP_PEER_DIR_NA, "Created peer");
      52        9567 :     RTINSTANCE_LOG_PEER(Create, instance_, peer,
      53             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
      54        9567 :     return peer;
      55        9567 : }
      56             : 
      57             : //
      58             : // Resurrect the BgpPeer with given name if we have configuration for it.
      59             : // Also insert it into the BgpServer's EndpointPeerList - in case it is
      60             : // a BGPaaS peer. This needs to happen here since we would not have been
      61             : // able to do it from BgpServer::ConfigUpdater::ProcessNeighborConfig since
      62             : // old incarnation of the BgpPeer still existed at that point.
      63             : //
      64        9674 : void PeerManager::PeerResurrect(string name) {
      65        9674 :     CHECK_CONCURRENCY("bgp::Config");
      66             : 
      67        9674 :     if (instance_->deleted())
      68        2891 :         return;
      69             : 
      70             :     const BgpConfigManager *config_manager =
      71        6783 :             instance_->manager()->server()->config_manager();
      72             :     const BgpNeighborConfig *config =
      73        6783 :             config_manager->FindNeighbor(instance_->name(), name);
      74        6783 :     if (!config)
      75        6672 :         return;
      76             : 
      77         111 :     BgpPeer *peer = PeerLocate(server(), config);
      78         111 :     assert(peer);
      79         111 :     server()->InsertPeer(peer->endpoint(), peer);
      80             : }
      81             : 
      82             : //
      83             : // Delete the BgpPeer corresponding to the given BgpNeighborConfig.
      84             : //
      85        6713 : BgpPeer *PeerManager::TriggerPeerDeletion(const BgpNeighborConfig *config) {
      86        6713 :     CHECK_CONCURRENCY("bgp::Config");
      87             : 
      88        6713 :     BgpPeerNameMap::iterator loc = peers_by_name_.find(config->name());
      89        6713 :     if (loc == peers_by_name_.end())
      90           2 :         return NULL;
      91             : 
      92        6711 :     BgpPeer *peer = loc->second;
      93        6711 :     peer->ManagedDelete();
      94             : 
      95        6711 :     RoutingInstanceInfo info = instance_->GetDataCollection("Delete");
      96        6711 :     info.set_peer(peer->ToString());
      97        6711 :     ROUTING_INSTANCE_COLLECTOR_INFO(info);
      98             : 
      99        6711 :     RTINSTANCE_LOG_PEER(Delete, instance_, peer,
     100             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
     101             : 
     102             :     // Configuration is deleted by the config manager (parser)
     103             :     // Do not hold reference to it any more
     104        6711 :     peer->ClearConfig();
     105        6711 :     return peer;
     106        6711 : }
     107             : 
     108             : //
     109             : // Concurrency: Called from bgp config task
     110             : //
     111             : // Complete the deletion process of a peer.  Remove it from BgpPeerKeyMap and
     112             : // BgpPeerNameMap.
     113             : //
     114        9567 : void PeerManager::DestroyIPeer(IPeer *ipeer) {
     115        9567 :     CHECK_CONCURRENCY("bgp::Config");
     116             : 
     117        9567 :     BgpPeer *peer = static_cast<BgpPeer *>(ipeer);
     118        9567 :     string peer_name = peer->peer_name();
     119        9567 :     BGP_LOG_PEER(Config, peer, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
     120             :                  BGP_PEER_DIR_NA, "Destroyed peer");
     121        9567 :     RTINSTANCE_LOG_PEER(Destroy, instance_, peer,
     122             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
     123        9567 :     RemovePeerByKey(peer->peer_key(), peer);
     124        9567 :     RemovePeerByName(peer->peer_name(), peer);
     125        9567 :     delete peer;
     126             : 
     127        9567 :     PeerResurrect(peer_name);
     128        9567 : }
     129             : 
     130             : //
     131             : // Insert the BgpPeer info the BgpPeerKeyMap.
     132             : //
     133       10329 : void PeerManager::InsertPeerByKey(const BgpPeerKey key, BgpPeer *peer) {
     134       10329 :     peers_by_key_.insert(make_pair(key, peer));
     135       10329 : }
     136             : 
     137             : //
     138             : // Remove the BgpPeer from the BgpPeerKeyMap.  There may be more than
     139             : // one BgpPeer with the same key, so we need to find the right one.
     140             : //
     141       10329 : void PeerManager::RemovePeerByKey(const BgpPeerKey key, BgpPeer *peer) {
     142       10329 :     for (BgpPeerKeyMap::iterator loc = peers_by_key_.find(key);
     143       17194 :          loc != peers_by_key_.end() && loc->first == key; ++loc) {
     144       17194 :         if (loc->second == peer) {
     145       10329 :             peers_by_key_.erase(loc);
     146       10329 :             return;
     147             :         }
     148             :     }
     149           0 :     assert(false);
     150             : }
     151             : 
     152             : //
     153             : // Insert the BgpPeer info the BgpPeerNameMap.
     154             : //
     155        9567 : void PeerManager::InsertPeerByName(const string name, BgpPeer *peer) {
     156        9567 :     peers_by_name_.insert(make_pair(name, peer));
     157        9567 : }
     158             : 
     159             : //
     160             : // Remove the BgpPeer from the BgpPeerNameMap.
     161             : //
     162        9567 : void PeerManager::RemovePeerByName(const string name, BgpPeer *peer) {
     163        9567 :     BgpPeerNameMap::iterator loc = peers_by_name_.find(name);
     164        9567 :     assert(loc != peers_by_name_.end() && loc->second == peer);
     165        9567 :     peers_by_name_.erase(loc);
     166        9567 : }
     167             : 
     168           5 : BgpPeer *PeerManager::PeerFind(string ip_address) const {
     169           5 :     if (ip_address.empty())
     170           0 :         return NULL;
     171             : 
     172           5 :     boost::system::error_code ec;
     173           5 :     boost::asio::ip::tcp::endpoint endpoint;
     174           5 :     endpoint.address(AddressFromString(ip_address, &ec));
     175           5 :     if (ec)
     176           0 :         return NULL;
     177             : 
     178           5 :     return PeerLookup(endpoint);
     179             : }
     180             : 
     181         274 : BgpPeer *PeerManager::PeerLookup(string name) const {
     182         274 :     BgpPeerNameMap::const_iterator loc = peers_by_name_.find(name);
     183         274 :     return (loc != peers_by_name_.end() ? loc->second : NULL);
     184             : }
     185             : 
     186           3 : size_t PeerManager::GetNeighborCount(string up_or_down) {
     187           3 :     size_t count = 0;
     188           3 :     BgpPeerNameMap::iterator iter;
     189             : 
     190           6 :     for (iter = peers_by_name_.begin(); iter != peers_by_name_.end(); iter++) {
     191           3 :         BgpPeer *peer = iter->second;
     192           3 :         if (boost::iequals(up_or_down, "up") && !peer->IsReady())
     193           0 :             continue;
     194           3 :         if (boost::iequals(up_or_down, "down") && peer->IsReady())
     195           1 :             continue;
     196           2 :         count += 1;
     197             :     }
     198             : 
     199           3 :     return count;
     200             : }
     201             : 
     202         812 : void PeerManager::ClearAllPeers() {
     203         812 :     BgpPeerNameMap::iterator iter;
     204             : 
     205        1056 :     for (iter = peers_by_name_.begin(); iter != peers_by_name_.end(); iter++) {
     206         244 :         BgpPeer *peer = iter->second;
     207         244 :         peer->Clear(BgpProto::Notification::OtherConfigChange);
     208             :     }
     209         812 : }
     210             : 
     211           2 : void PeerManager::ClearAllInternalPeers() {
     212           2 :     BgpPeerNameMap::iterator iter;
     213             : 
     214           6 :     for (iter = peers_by_name_.begin(); iter != peers_by_name_.end(); iter++) {
     215           4 :         BgpPeer *peer = iter->second;
     216           4 :         if (peer->PeerType() ==  BgpProto::IBGP)
     217           4 :             peer->Clear(BgpProto::Notification::OtherConfigChange);
     218             :     }
     219           2 : }
     220             : 
     221             : //
     222             : // Concurrency: Called from state machine thread
     223             : //
     224          36 : BgpPeer *PeerManager::PeerLookup(TcpSession::Endpoint remote_endpoint) const {
     225          36 :     BgpPeer    *peer = NULL;
     226          36 :     BgpPeerKey  peer_key;
     227             : 
     228             :     // Bail if the instance is undergoing deletion.
     229          36 :     if (instance_->deleted())
     230           0 :         return NULL;
     231             : 
     232          36 :     peer_key.endpoint.address(remote_endpoint.address());
     233             : 
     234             :     // Do a partial match, as we do not know the peer's port yet.
     235          36 :     BgpPeerKeyMap::const_iterator loc = peers_by_key_.lower_bound(peer_key);
     236          36 :     while (loc != peers_by_key_.end()) {
     237             :         // Check if the address does indeed match as we are doing a partial
     238             :         // match here
     239          32 :         if (loc->second->peer_key().endpoint.address() !=
     240          64 :             peer_key.endpoint.address()) {
     241           0 :             break;
     242             :         }
     243             : 
     244             :         // This peer certainly matches with the IP address. If we do not find
     245             :         // an exact match with the peer-id, then just use this.
     246          32 :         peer = loc->second;
     247          32 :         break;
     248             :     }
     249             : 
     250          36 :     return peer;
     251             : }
     252             : 
     253         333 : const BgpPeer *PeerManager::NextPeer(const BgpPeerKey &peer_key) const {
     254             :     // Do a partial match
     255         333 :     BgpPeerKeyMap::const_iterator loc = peers_by_key_.upper_bound(peer_key);
     256         333 :     if (loc != peers_by_key_.end()) {
     257         150 :         return loc->second;
     258             :     }
     259             : 
     260         183 :     return NULL;
     261             : }
     262             : 
     263           0 : const string &PeerManager::name() const {
     264           0 :     return instance_->name();
     265             : }
     266             : 
     267        6556 : BgpServer *PeerManager::server() const {
     268        6556 :     return instance_->server();
     269             : }

Generated by: LCOV version 1.14