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: 83 133 62.4 %
Date: 2026-09-28 02:13:17 Functions: 11 17 64.7 %
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         998 : BgpPeer *PeerManager::PeerLocate(BgpServer *server,
      29             :     const BgpNeighborConfig *config) {
      30         998 :     BgpPeerKey key(config);
      31             : 
      32         998 :     BgpPeerNameMap::iterator loc = peers_by_name_.find(config->name());
      33         998 :     if (loc != peers_by_name_.end()) {
      34         378 :         if (loc->second->IsDeleted())
      35           0 :             return NULL;
      36         378 :         RemovePeerByKey(loc->second->peer_key(), loc->second);
      37         378 :         InsertPeerByKey(key, loc->second);
      38         378 :         return loc->second;
      39             :     }
      40             : 
      41             :     BgpPeer *peer =
      42         620 :         BgpStaticObjectFactory::Create<BgpPeer>(server, instance(), config);
      43         620 :     peer->Initialize();
      44         620 :     InsertPeerByKey(key, peer);
      45         620 :     InsertPeerByName(config->name(), peer);
      46         620 :     RoutingInstanceInfo info = instance_->GetDataCollection("Add");
      47         620 :     info.set_peer(peer->ToString());
      48         620 :     ROUTING_INSTANCE_COLLECTOR_INFO(info);
      49             : 
      50         620 :     BGP_LOG_PEER(Config, peer, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
      51             :                  BGP_PEER_DIR_NA, "Created peer");
      52         620 :     RTINSTANCE_LOG_PEER(Create, instance_, peer,
      53             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
      54         620 :     return peer;
      55         620 : }
      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         620 : void PeerManager::PeerResurrect(string name) {
      65         620 :     CHECK_CONCURRENCY("bgp::Config");
      66             : 
      67         620 :     if (instance_->deleted())
      68         614 :         return;
      69             : 
      70             :     const BgpConfigManager *config_manager =
      71           6 :             instance_->manager()->server()->config_manager();
      72             :     const BgpNeighborConfig *config =
      73           6 :             config_manager->FindNeighbor(instance_->name(), name);
      74           6 :     if (!config)
      75           6 :         return;
      76             : 
      77           0 :     BgpPeer *peer = PeerLocate(server(), config);
      78           0 :     assert(peer);
      79           0 :     server()->InsertPeer(peer->endpoint(), peer);
      80             : }
      81             : 
      82             : //
      83             : // Delete the BgpPeer corresponding to the given BgpNeighborConfig.
      84             : //
      85           6 : BgpPeer *PeerManager::TriggerPeerDeletion(const BgpNeighborConfig *config) {
      86           6 :     CHECK_CONCURRENCY("bgp::Config");
      87             : 
      88           6 :     BgpPeerNameMap::iterator loc = peers_by_name_.find(config->name());
      89           6 :     if (loc == peers_by_name_.end())
      90           0 :         return NULL;
      91             : 
      92           6 :     BgpPeer *peer = loc->second;
      93           6 :     peer->ManagedDelete();
      94             : 
      95           6 :     RoutingInstanceInfo info = instance_->GetDataCollection("Delete");
      96           6 :     info.set_peer(peer->ToString());
      97           6 :     ROUTING_INSTANCE_COLLECTOR_INFO(info);
      98             : 
      99           6 :     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           6 :     peer->ClearConfig();
     105           6 :     return peer;
     106           6 : }
     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         620 : void PeerManager::DestroyIPeer(IPeer *ipeer) {
     115         620 :     CHECK_CONCURRENCY("bgp::Config");
     116             : 
     117         620 :     BgpPeer *peer = static_cast<BgpPeer *>(ipeer);
     118         620 :     string peer_name = peer->peer_name();
     119         620 :     BGP_LOG_PEER(Config, peer, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
     120             :                  BGP_PEER_DIR_NA, "Destroyed peer");
     121         620 :     RTINSTANCE_LOG_PEER(Destroy, instance_, peer,
     122             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL);
     123         620 :     RemovePeerByKey(peer->peer_key(), peer);
     124         620 :     RemovePeerByName(peer->peer_name(), peer);
     125         620 :     delete peer;
     126             : 
     127         620 :     PeerResurrect(peer_name);
     128         620 : }
     129             : 
     130             : //
     131             : // Insert the BgpPeer info the BgpPeerKeyMap.
     132             : //
     133         998 : void PeerManager::InsertPeerByKey(const BgpPeerKey key, BgpPeer *peer) {
     134         998 :     peers_by_key_.insert(make_pair(key, peer));
     135         998 : }
     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         998 : void PeerManager::RemovePeerByKey(const BgpPeerKey key, BgpPeer *peer) {
     142         998 :     for (BgpPeerKeyMap::iterator loc = peers_by_key_.find(key);
     143         998 :          loc != peers_by_key_.end() && loc->first == key; ++loc) {
     144         998 :         if (loc->second == peer) {
     145         998 :             peers_by_key_.erase(loc);
     146         998 :             return;
     147             :         }
     148             :     }
     149           0 :     assert(false);
     150             : }
     151             : 
     152             : //
     153             : // Insert the BgpPeer info the BgpPeerNameMap.
     154             : //
     155         620 : void PeerManager::InsertPeerByName(const string name, BgpPeer *peer) {
     156         620 :     peers_by_name_.insert(make_pair(name, peer));
     157         620 : }
     158             : 
     159             : //
     160             : // Remove the BgpPeer from the BgpPeerNameMap.
     161             : //
     162         620 : void PeerManager::RemovePeerByName(const string name, BgpPeer *peer) {
     163         620 :     BgpPeerNameMap::iterator loc = peers_by_name_.find(name);
     164         620 :     assert(loc != peers_by_name_.end() && loc->second == peer);
     165         620 :     peers_by_name_.erase(loc);
     166         620 : }
     167             : 
     168           0 : BgpPeer *PeerManager::PeerFind(string ip_address) const {
     169           0 :     if (ip_address.empty())
     170           0 :         return NULL;
     171             : 
     172           0 :     boost::system::error_code ec;
     173           0 :     boost::asio::ip::tcp::endpoint endpoint;
     174           0 :     endpoint.address(AddressFromString(ip_address, &ec));
     175           0 :     if (ec)
     176           0 :         return NULL;
     177             : 
     178           0 :     return PeerLookup(endpoint);
     179             : }
     180             : 
     181           0 : BgpPeer *PeerManager::PeerLookup(string name) const {
     182           0 :     BgpPeerNameMap::const_iterator loc = peers_by_name_.find(name);
     183           0 :     return (loc != peers_by_name_.end() ? loc->second : NULL);
     184             : }
     185             : 
     186           0 : size_t PeerManager::GetNeighborCount(string up_or_down) {
     187           0 :     size_t count = 0;
     188           0 :     BgpPeerNameMap::iterator iter;
     189             : 
     190           0 :     for (iter = peers_by_name_.begin(); iter != peers_by_name_.end(); iter++) {
     191           0 :         BgpPeer *peer = iter->second;
     192           0 :         if (boost::iequals(up_or_down, "up") && !peer->IsReady())
     193           0 :             continue;
     194           0 :         if (boost::iequals(up_or_down, "down") && peer->IsReady())
     195           0 :             continue;
     196           0 :         count += 1;
     197             :     }
     198             : 
     199           0 :     return count;
     200             : }
     201             : 
     202         246 : void PeerManager::ClearAllPeers() {
     203         246 :     BgpPeerNameMap::iterator iter;
     204             : 
     205         270 :     for (iter = peers_by_name_.begin(); iter != peers_by_name_.end(); iter++) {
     206          24 :         BgpPeer *peer = iter->second;
     207          24 :         peer->Clear(BgpProto::Notification::OtherConfigChange);
     208             :     }
     209         246 : }
     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           0 : BgpPeer *PeerManager::PeerLookup(TcpSession::Endpoint remote_endpoint) const {
     225           0 :     BgpPeer    *peer = NULL;
     226           0 :     BgpPeerKey  peer_key;
     227             : 
     228             :     // Bail if the instance is undergoing deletion.
     229           0 :     if (instance_->deleted())
     230           0 :         return NULL;
     231             : 
     232           0 :     peer_key.endpoint.address(remote_endpoint.address());
     233             : 
     234             :     // Do a partial match, as we do not know the peer's port yet.
     235           0 :     BgpPeerKeyMap::const_iterator loc = peers_by_key_.lower_bound(peer_key);
     236           0 :     while (loc != peers_by_key_.end()) {
     237             :         // Check if the address does indeed match as we are doing a partial
     238             :         // match here
     239           0 :         if (loc->second->peer_key().endpoint.address() !=
     240           0 :             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           0 :         peer = loc->second;
     247           0 :         break;
     248             :     }
     249             : 
     250           0 :     return peer;
     251             : }
     252             : 
     253           0 : const BgpPeer *PeerManager::NextPeer(const BgpPeerKey &peer_key) const {
     254             :     // Do a partial match
     255           0 :     BgpPeerKeyMap::const_iterator loc = peers_by_key_.upper_bound(peer_key);
     256           0 :     if (loc != peers_by_key_.end()) {
     257           0 :         return loc->second;
     258             :     }
     259             : 
     260           0 :     return NULL;
     261             : }
     262             : 
     263           0 : const string &PeerManager::name() const {
     264           0 :     return instance_->name();
     265             : }
     266             : 
     267         808 : BgpServer *PeerManager::server() const {
     268         808 :     return instance_->server();
     269             : }

Generated by: LCOV version 1.14