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

Generated by: LCOV version 1.14