LCOV - code coverage report
Current view: top level - bgp - bgp_server.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 754 789 95.6 %
Date: 2026-11-09 02:10:49 Functions: 72 75 96.0 %
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/bgp_server.h"
       7             : 
       8             : #include <sys/resource.h>
       9             : 
      10             : #include <boost/foreach.hpp>
      11             : #include <boost/tuple/tuple.hpp>
      12             : 
      13             : #include "base/connection_info.h"
      14             : #include "base/misc_utils.h"
      15             : #include "base/task_annotations.h"
      16             : #include "bgp/bgp_condition_listener.h"
      17             : #include "bgp/bgp_factory.h"
      18             : #include "bgp/bgp_lifetime.h"
      19             : #include "bgp/bgp_log.h"
      20             : #include "bgp/bgp_membership.h"
      21             : #include "bgp/bgp_peer.h"
      22             : #include "bgp/bgp_ribout_updates.h"
      23             : #include "bgp/rtarget/rtarget_table.h"
      24             : #include "bgp/bgp_session_manager.h"
      25             : #include "bgp/bgp_update_sender.h"
      26             : #include "bgp/peer_stats.h"
      27             : #include "bgp/routing-instance/iservice_chain_mgr.h"
      28             : #include "bgp/routing-instance/istatic_route_mgr.h"
      29             : #include "bgp/routing-instance/peer_manager.h"
      30             : #include "bgp/routing-instance/routepath_replicator.h"
      31             : #include "bgp/routing-instance/routing_instance.h"
      32             : #include "bgp/routing-instance/rtarget_group_mgr.h"
      33             : #include "bgp/routing-policy/routing_policy.h"
      34             : 
      35             : #include "config-client-mgr/config_client_show_types.h"
      36             : #include "control-node/sandesh/control_node_types.h"
      37             : 
      38             : using boost::system::error_code;
      39             : using boost::tie;
      40             : using process::ConnectionState;
      41             : using std::boolalpha;
      42             : using std::make_pair;
      43             : using std::map;
      44             : using std::noboolalpha;
      45             : using std::sort;
      46             : using std::string;
      47             : 
      48             : // The ConfigUpdater serves as glue between the BgpConfigManager and the
      49             : // BgpServer.
      50             : class BgpServer::ConfigUpdater {
      51             : public:
      52        9743 :     explicit ConfigUpdater(BgpServer *server) : server_(server) {
      53        9743 :         BgpConfigManager::Observers obs;
      54             :         obs.instance = boost::bind(&ConfigUpdater::ProcessInstanceConfig,
      55        9743 :             this, _1, _2);
      56             :         obs.protocol = boost::bind(&ConfigUpdater::ProcessProtocolConfig,
      57        9743 :             this, _1, _2);
      58             :         obs.neighbor = boost::bind(&ConfigUpdater::ProcessNeighborConfig,
      59        9743 :             this, _1, _2);
      60             :         obs.policy = boost::bind(&ConfigUpdater::ProcessRoutingPolicyConfig,
      61        9743 :             this, _1, _2);
      62             :         obs.system= boost::bind(&ConfigUpdater::ProcessGlobalSystemConfig,
      63        9743 :             this, _1, _2);
      64             :         obs.qos = boost::bind(&ConfigUpdater::ProcessGlobalQosConfig,
      65        9743 :             this, _1, _2);
      66        9743 :         server->config_manager()->RegisterObservers(obs);
      67        9743 :     }
      68             : 
      69           9 :     void ProcessGlobalQosConfig(const BgpGlobalQosConfig *qos,
      70             :         BgpConfigManager::EventType event) {
      71           9 :         if (qos->control_dscp() != server_->global_qos()->control_dscp()) {
      72           9 :             server_->global_qos()->set_control_dscp(qos->control_dscp());
      73           9 :             server_->NotifyDSCPUpdate(qos->control_dscp());
      74             :         }
      75           9 :         server_->global_qos()->set_analytics_dscp(qos->analytics_dscp());
      76           9 :     }
      77             : 
      78         840 :     void ProcessGlobalSystemConfig(const BgpGlobalSystemConfig *new_config,
      79             :             BgpConfigManager::EventType event) {
      80         840 :         bool clear_peers = false;
      81             : 
      82         840 :         if (server_->global_config()->gr_enable() != new_config->gr_enable()) {
      83         564 :             server_->global_config()->set_gr_enable(new_config->gr_enable());
      84         564 :             clear_peers = true;
      85             :         }
      86         840 :         if (server_->global_config()->gr_time() != new_config->gr_time()) {
      87         784 :             server_->global_config()->set_gr_time(new_config->gr_time());
      88         784 :             clear_peers = true;
      89             :         }
      90         840 :         if (server_->global_config()->llgr_time() != new_config->llgr_time()) {
      91         784 :             server_->global_config()->set_llgr_time(new_config->llgr_time());
      92         784 :             clear_peers = true;
      93             :         }
      94        1680 :         if (server_->global_config()->end_of_rib_timeout() !=
      95         840 :                 new_config->end_of_rib_timeout()) {
      96        1126 :             server_->global_config()->set_end_of_rib_timeout(
      97         563 :                 new_config->end_of_rib_timeout());
      98         563 :             clear_peers = true;
      99             :         }
     100        1680 :         if (server_->global_config()->gr_bgp_helper() !=
     101         840 :                 new_config->gr_bgp_helper()) {
     102        1122 :             server_->global_config()->set_gr_bgp_helper(
     103         561 :                 new_config->gr_bgp_helper());
     104         561 :             clear_peers = true;
     105             :         }
     106        1680 :         if (server_->global_config()->enable_4byte_as() !=
     107         840 :                 new_config->enable_4byte_as()) {
     108         160 :             server_->global_config()->set_enable_4byte_as(
     109          80 :                 new_config->enable_4byte_as());
     110          80 :             clear_peers = true;
     111             :         }
     112             : 
     113        1680 :         if (server_->global_config()->fc_enabled() !=
     114         840 :                 new_config->fc_enabled()) {
     115          18 :             server_->global_config()->set_fc_enabled(
     116           9 :                 new_config->fc_enabled());
     117           9 :             clear_peers = true;
     118             :         }
     119             : 
     120        1680 :         if (server_->global_config()->nh_check_enabled() !=
     121         840 :                 new_config->nh_check_enabled()) {
     122           4 :             server_->global_config()->set_nh_check_enabled(
     123           2 :                 new_config->nh_check_enabled());
     124           2 :             clear_peers = true;
     125             :         }
     126             : 
     127             :         // Clear peers if there's a change in always-compare-med knob.
     128        1680 :         if (server_->global_config()->always_compare_med() !=
     129         840 :             new_config->always_compare_med()) {
     130          10 :             server_->global_config()->set_always_compare_med(
     131           5 :                 new_config->always_compare_med());
     132           5 :             clear_peers = true;
     133             :         }
     134             : 
     135             :         // Process a change in rd-cluster-seed knob.
     136        1680 :         if (server_->global_config()->rd_cluster_seed() !=
     137         840 :             new_config->rd_cluster_seed()) {
     138          50 :           server_->global_config()->set_rd_cluster_seed(
     139          25 :               new_config->rd_cluster_seed());
     140             :         }
     141             : 
     142             :         // Process a change in xmpp-hold-time knob.
     143        1680 :         if (server_->global_config()->xmpp_hold_time() !=
     144         840 :             new_config->xmpp_hold_time()) {
     145          22 :           server_->global_config()->set_xmpp_hold_time(
     146          11 :               new_config->xmpp_hold_time());
     147             :         }
     148             : 
     149             :         // Process a change in all-tags-are-global knob.
     150        1680 :         if (server_->global_config()->all_tags_are_global() !=
     151         840 :             new_config->all_tags_are_global()) {
     152           8 :           server_->global_config()->set_all_tags_are_global(
     153           4 :               new_config->all_tags_are_global());
     154             :         }
     155             : 
     156         840 :         bool clear_bgpaas_peers = false;
     157             : 
     158             :         // Clear bgpaas peers if there's a change in bgpaas-port-start.
     159        1680 :         if (server_->global_config()->bgpaas_port_start() !=
     160         840 :                 new_config->bgpaas_port_start()) {
     161        1352 :             server_->global_config()->set_bgpaas_port_start(
     162         676 :                 new_config->bgpaas_port_start());
     163         676 :             clear_bgpaas_peers = true;
     164             :         }
     165             : 
     166             :         // Clear bgpaas peers if there's a change in bgpaas-port-end.
     167        1680 :         if (server_->global_config()->bgpaas_port_end() !=
     168         840 :                 new_config->bgpaas_port_end()) {
     169        1352 :             server_->global_config()->set_bgpaas_port_end(
     170         676 :                 new_config->bgpaas_port_end());
     171         676 :             clear_bgpaas_peers = true;
     172             :         }
     173             : 
     174         840 :         if (clear_peers) {
     175         812 :             RoutingInstanceMgr *ri_mgr = server_->routing_instance_mgr();
     176         812 :             RoutingInstance *rti = ri_mgr->GetDefaultRoutingInstance();
     177         812 :             assert(rti);
     178         812 :             PeerManager *peer_manager = rti->LocatePeerManager();
     179         812 :             peer_manager->ClearAllPeers();
     180             :         }
     181             : 
     182         840 :         if (clear_peers || clear_bgpaas_peers)
     183         820 :             server_->ClearBgpaaSPeers();
     184         840 :     }
     185             : 
     186        9050 :     void ProcessProtocolConfig(const BgpProtocolConfig *protocol_config,
     187             :                                BgpConfigManager::EventType event) {
     188        9050 :         const string &instance_name = protocol_config->instance_name();
     189             : 
     190             :         // We only support BGP sessions in master instance for now.
     191        9050 :         if (instance_name != BgpConfigManager::kMasterInstance) {
     192           0 :             return;
     193             :         }
     194             : 
     195        9050 :         if (event == BgpConfigManager::CFG_ADD ||
     196             :             event == BgpConfigManager::CFG_CHANGE) {
     197        7671 :             BgpServerConfigUpdate(instance_name, protocol_config);
     198        1379 :         } else if (event == BgpConfigManager::CFG_DELETE) {
     199        1379 :             BgpServerConfigUpdate(instance_name, NULL);
     200             :         } else {
     201           0 :             assert(false);
     202             :         }
     203             :     }
     204             : 
     205        9050 :     void BgpServerConfigUpdate(string instance_name,
     206             :                                const BgpProtocolConfig *config) {
     207        9050 :         boost::system::error_code ec;
     208        9050 :         uint32_t config_identifier = 0;
     209        9050 :         uint32_t config_autonomous_system = 0;
     210        9050 :         uint32_t config_local_autonomous_system = 0;
     211        9050 :         uint32_t config_hold_time = 0;
     212        9050 :         uint32_t config_cluster_id = 0;
     213        9050 :         bool config_admin_down = false;
     214        9050 :         if (config) {
     215        7671 :             config_admin_down = config->admin_down();
     216        7671 :             config_identifier = config->identifier();
     217        7671 :             config_autonomous_system = config->autonomous_system();
     218        7671 :             config_local_autonomous_system = config->local_autonomous_system();
     219        7671 :             config_cluster_id = config->cluster_id();
     220        7671 :             config_hold_time = config->hold_time();
     221             :         }
     222             : 
     223        9050 :         if (server_->admin_down_ != config_admin_down) {
     224          44 :             if (server_->admin_down_) {
     225          18 :                 BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG,
     226             :                             BGP_LOG_FLAG_SYSLOG, "Updated Admin Down from " <<
     227             :                             boolalpha << server_->admin_down_ << noboolalpha <<
     228             :                             " to " <<
     229             :                             boolalpha << config_admin_down << noboolalpha);
     230             :             } else {
     231          26 :                 BGP_LOG_NOTICE_STR(BgpConfig, BGP_LOG_FLAG_SYSLOG,
     232             :                             "Updated Admin Down from " <<
     233             :                             boolalpha << server_->admin_down_ << noboolalpha <<
     234             :                             " to " <<
     235             :                             boolalpha << config_admin_down << noboolalpha);
     236             :             }
     237          44 :             server_->admin_down_ = config_admin_down;
     238          44 :             if (server_->admin_down_)
     239          26 :                 server_->NotifyAdminDown();
     240             :         }
     241             : 
     242             :         // We currently do not support bind failures or changes to listen port
     243             :         // in production mode.
     244        9450 :         if (config && !server_->session_manager()->Initialize(config->port()) &&
     245         400 :                 !bgp_log_test::unit_test()) {
     246             :             // Disable core file generation and exit.
     247             :             rlimit new_core_limit;
     248           0 :             new_core_limit.rlim_cur = 0;
     249           0 :             new_core_limit.rlim_max = 0;
     250           0 :             setrlimit(RLIMIT_CORE, &new_core_limit);
     251           0 :             BGP_LOG_WARNING_STR(BgpConfig, BGP_LOG_FLAG_SYSLOG,
     252             :                 "Process exit! due to tcp server port " << config->port() <<
     253             :                 " bind failure");
     254           0 :             if (!bgp_log_test::unit_test())
     255           0 :                 kill(getpid(), SIGTERM);
     256             :         }
     257             : 
     258        9050 :         Ip4Address identifier(ntohl(config_identifier));
     259        9050 :         if (server_->bgp_identifier_ != identifier) {
     260        7331 :             if (!server_->bgp_identifier_.is_unspecified()) {
     261        1431 :                 BGP_LOG_NOTICE_STR(BgpConfig, BGP_LOG_FLAG_SYSLOG,
     262             :                             "Updated Router ID from " <<
     263             :                             server_->bgp_identifier_.to_string() << " to " <<
     264             :                             identifier.to_string());
     265             :             } else {
     266        5900 :                 BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG,
     267             :                              BGP_LOG_FLAG_SYSLOG, "Updated Router ID from " <<
     268             :                             server_->bgp_identifier_.to_string() << " to " <<
     269             :                             identifier.to_string());
     270             :             }
     271        7331 :             server_->UpdateBgpIdentifier(identifier);
     272             :         }
     273             : 
     274        9050 :         bool notify_asn_update = false;
     275        9050 :         uint32_t old_asn = server_->autonomous_system_;
     276        9050 :         uint32_t old_local_asn = server_->local_autonomous_system_;
     277        9050 :         server_->autonomous_system_ = config_autonomous_system;
     278        9050 :         if (config_local_autonomous_system) {
     279        1190 :             server_->local_autonomous_system_ = config_local_autonomous_system;
     280             :         } else {
     281        7860 :             server_->local_autonomous_system_ = config_autonomous_system;
     282             :         }
     283             : 
     284        9050 :         if (server_->autonomous_system_ != old_asn) {
     285        7355 :             if (old_asn != 0) {
     286        1455 :                 BGP_LOG_NOTICE_STR(BgpConfig, BGP_LOG_FLAG_SYSLOG,
     287             :                             "Updated Autonomous System from " << old_asn <<
     288             :                             " to " << server_->autonomous_system_);
     289             :             } else {
     290        5900 :                 BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG,
     291             :                             BGP_LOG_FLAG_SYSLOG,
     292             :                             "Updated Autonomous System from " << old_asn <<
     293             :                             " to " << server_->autonomous_system_);
     294             :             }
     295        7355 :             notify_asn_update = true;
     296             :         }
     297             : 
     298        9050 :         if (server_->local_autonomous_system_ != old_local_asn) {
     299        7398 :             if (old_local_asn != 0) {
     300        1498 :                 BGP_LOG_NOTICE_STR(BgpConfig, BGP_LOG_FLAG_SYSLOG,
     301             :                             "Updated Local Autonomous System from " <<
     302             :                             old_local_asn << " to " <<
     303             :                             server_->local_autonomous_system_);
     304             :             } else {
     305        5900 :                 BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG,
     306             :                             BGP_LOG_FLAG_SYSLOG,
     307             :                             "Updated Local Autonomous System from " <<
     308             :                             old_local_asn << " to " <<
     309             :                             server_->local_autonomous_system_);
     310             :             }
     311        7398 :             notify_asn_update = true;
     312             :         }
     313             : 
     314        9050 :         if (notify_asn_update) {
     315        7398 :             server_->NotifyASNUpdate(old_asn, old_local_asn);
     316             :         }
     317             : 
     318        9050 :         if (server_->hold_time_ != config_hold_time) {
     319         384 :             BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
     320             :                         "Updated Hold Time from " <<
     321             :                         server_->hold_time_ << " to " << config_hold_time);
     322         384 :             server_->hold_time_ = config_hold_time;
     323             :         }
     324             : 
     325        9050 :         if (server_->cluster_id() != config_cluster_id) {
     326           2 :             BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_SYSLOG,
     327             :                         "Updated Cluster Id from " <<
     328             :                         server_->cluster_id() << " to " << config_cluster_id);
     329           2 :             server_->set_cluster_id(config_cluster_id);
     330           2 :             RoutingInstanceMgr *ri_mgr = server_->routing_instance_mgr();
     331           2 :             RoutingInstance *rti = ri_mgr->GetDefaultRoutingInstance();
     332           2 :             assert(rti);
     333           2 :             PeerManager *peer_manager = rti->LocatePeerManager();
     334           2 :             peer_manager->ClearAllInternalPeers();
     335             :         }
     336             : 
     337        9050 :         ConnectionState::GetInstance()->Update();
     338        9050 :     }
     339             : 
     340       16900 :     void ProcessNeighborConfig(const BgpNeighborConfig *neighbor_config,
     341             :                                BgpConfigManager::EventType event) {
     342       16900 :         string instance_name = neighbor_config->instance_name();
     343       16900 :         RoutingInstanceMgr *ri_mgr = server_->routing_instance_mgr();
     344       16900 :         RoutingInstance *rti = ri_mgr->GetRoutingInstance(instance_name);
     345       16900 :         if (!rti)
     346         115 :             return;
     347             : 
     348       16785 :         if (event == BgpConfigManager::CFG_ADD ||
     349             :             event == BgpConfigManager::CFG_CHANGE) {
     350       10066 :             if (rti->deleted())
     351           6 :                 return;
     352       10060 :             PeerManager *peer_manager = rti->LocatePeerManager();
     353       10060 :             BgpPeer *peer = peer_manager->PeerLocate(server_, neighbor_config);
     354       10060 :             if (peer) {
     355       10054 :                 server_->RemovePeer(peer->endpoint(), peer);
     356       10054 :                 peer->ConfigUpdate(neighbor_config);
     357       10054 :                 server_->InsertPeer(peer->endpoint(), peer);
     358             :             }
     359       16779 :         } else if (event == BgpConfigManager::CFG_DELETE) {
     360        6719 :             PeerManager *peer_manager = rti->peer_manager();
     361        6719 :             if (!peer_manager)
     362           6 :                 return;
     363        6713 :             BgpPeer *peer = peer_manager->TriggerPeerDeletion(neighbor_config);
     364        6713 :             if (peer) {
     365        6711 :                 server_->RemovePeer(peer->endpoint(), peer);
     366             :             }
     367             :         }
     368       16900 :     }
     369             : 
     370         439 :     void ProcessRoutingPolicyConfig(const BgpRoutingPolicyConfig *policy_config,
     371             :                                     BgpConfigManager::EventType event) {
     372         439 :         RoutingPolicyMgr *mgr = server_->routing_policy_mgr();
     373         439 :         if (event == BgpConfigManager::CFG_ADD) {
     374         161 :             mgr->CreateRoutingPolicy(policy_config);
     375         278 :         } else if (event == BgpConfigManager::CFG_CHANGE) {
     376         235 :             mgr->UpdateRoutingPolicy(policy_config);
     377          43 :         } else if (event == BgpConfigManager::CFG_DELETE) {
     378          43 :             mgr->DeleteRoutingPolicy(policy_config->name());
     379             :         }
     380         439 :     }
     381             : 
     382      161085 :     void ProcessInstanceConfig(const BgpInstanceConfig *instance_config,
     383             :                                BgpConfigManager::EventType event) {
     384      161085 :         RoutingInstanceMgr *mgr = server_->routing_instance_mgr();
     385      161085 :         if (event == BgpConfigManager::CFG_ADD ||
     386             :             event == BgpConfigManager::CFG_CHANGE) {
     387      150762 :             mgr->LocateRoutingInstance(instance_config->name());
     388       10323 :         } else if (event == BgpConfigManager::CFG_DELETE) {
     389       10323 :             mgr->DeleteRoutingInstance(instance_config->name());
     390             :         }
     391      161085 :     }
     392             : 
     393             : private:
     394             :     BgpServer *server_;
     395             : };
     396             : 
     397             : class BgpServer::DeleteActor : public LifetimeActor {
     398             : public:
     399        9743 :     explicit DeleteActor(BgpServer *server)
     400        9743 :         : LifetimeActor(server->lifetime_manager()), server_(server) {
     401        9743 :     }
     402        9639 :     virtual bool MayDelete() const {
     403        9639 :         CHECK_CONCURRENCY("bgp::Config");
     404        9639 :         return server_->session_manager()->MayDelete();
     405             :     }
     406        9639 :     virtual void Shutdown() {
     407        9639 :         CHECK_CONCURRENCY("bgp::Config");
     408        9639 :         server_->session_manager()->Shutdown();
     409        9639 :     }
     410        9639 :     virtual void Destroy() {
     411        9639 :         CHECK_CONCURRENCY("bgp::Config");
     412        9639 :         server_->config_manager()->Terminate();
     413        9639 :         server_->session_manager()->Terminate();
     414        9639 :         TcpServerManager::DeleteServer(server_->session_manager());
     415        9639 :         server_->session_mgr_ = NULL;
     416        9639 :         server_->set_destroyed();
     417        9639 :     }
     418             : 
     419             : private:
     420             :     BgpServer *server_;
     421             : };
     422             : 
     423       28077 : bool BgpServer::IsDeleted() const {
     424       28077 :     return deleter_->IsDeleted();
     425             : }
     426             : 
     427           0 : void BgpServer::RetryDelete() {
     428           0 :     if (!deleter_->IsDeleted())
     429           0 :         return;
     430           0 :     deleter_->RetryDelete();
     431             : }
     432             : 
     433     1911668 : bool BgpServer::IsReadyForDeletion() {
     434     1911668 :     CHECK_CONCURRENCY("bgp::Config");
     435             : 
     436     1911668 :     static TaskScheduler *scheduler = TaskScheduler::GetInstance();
     437     1911668 :     static int db_table_task_id = scheduler->GetTaskId("db::DBTable");
     438             :     static int resolver_path_task_id =
     439     1911668 :         scheduler->GetTaskId("bgp::ResolverPath");
     440             :     static int resolver_nexthop_task_id =
     441     1911668 :         scheduler->GetTaskId("bgp::ResolverNexthop");
     442             : 
     443             :     // Check if any PathResolver is active.
     444             :     // Need to ensure that there's no pending deletes of BgpPaths added by
     445             :     // PathResolver since they hold pointers to IPeer.
     446     3630505 :     if (!scheduler->IsTaskGroupEmpty(resolver_path_task_id) ||
     447     1718837 :         !scheduler->IsTaskGroupEmpty(resolver_nexthop_task_id)) {
     448      192832 :         return false;
     449             :     }
     450             : 
     451             :     // Check if the membership manager queue is empty.
     452     1718836 :     if (!membership_mgr_->IsQueueEmpty()) {
     453       52785 :         return false;
     454             :     }
     455             : 
     456             :     // Check if the Service Chain Manager Work Queues are empty.
     457     1666051 :     if (!inet_service_chain_mgr_->IsQueueEmpty() ||
     458     1665715 :         !inet6_service_chain_mgr_->IsQueueEmpty() ||
     459     4997191 :         !evpn_service_chain_mgr_->IsQueueEmpty() ||
     460     1665425 :         !evpn6_service_chain_mgr_->IsQueueEmpty()) {
     461         626 :         return false;
     462             :     }
     463             : 
     464             :     // Check if the DB requests queue and change list is empty.
     465     1665425 :     if (!db_.IsDBQueueEmpty()) {
     466      121663 :         return false;
     467             :     }
     468             : 
     469             :     // Check if the RTargetGroupManager has processed all RTargetRoute updates.
     470             :     // This is done to ensure that the InterestedPeerList of RtargetGroup gets
     471             :     // updated before allowing the peer to get deleted.
     472     1543762 :     if (!rtarget_group_mgr_->IsRTargetRoutesProcessed()) {
     473         867 :         return false;
     474             :     }
     475             : 
     476             :     // Check if any db::DBTable task is active.
     477             :     // Need to ensure that there's no pending deletes of BgpPaths added by
     478             :     // the Evpn aliasing module since they hold pointers to IPeer.
     479     1542895 :     if (!scheduler->IsTaskGroupEmpty(db_table_task_id)) {
     480       44162 :         return false;
     481             :     }
     482             : 
     483     1498733 :     return true;
     484             : }
     485             : 
     486        9743 : BgpServer::BgpServer(EventManager *evm)
     487        9743 :     : admin_down_(false),
     488        9743 :       cluster_id_(0),
     489        9743 :       autonomous_system_(0),
     490        9743 :       local_autonomous_system_(0),
     491        9743 :       bgp_identifier_(0),
     492        9743 :       bgp_identifier_u32_(0),
     493        9743 :       hold_time_(0),
     494        9743 :       gr_helper_disable_(false),
     495        9743 :       lifetime_manager_(BgpStaticObjectFactory::Create<BgpLifetimeManager>(this,
     496             :           TaskScheduler::GetInstance()->GetTaskId("bgp::Config"))),
     497        9743 :       deleter_(new DeleteActor(this)),
     498        9743 :       destroyed_(false),
     499        9743 :       logging_disabled_(false),
     500        9743 :       mvpn_ipv4_enable_(false),
     501        9743 :       ignore_aspath_(false),
     502        9743 :       aspath_db_(new AsPathDB(this)),
     503        9743 :       aspath_4byte_db_(new AsPath4ByteDB(this)),
     504        9743 :       as4path_db_(new As4PathDB(this)),
     505        9743 :       olist_db_(new BgpOListDB(this)),
     506        9743 :       cluster_list_db_(new ClusterListDB(this)),
     507        9743 :       comm_db_(new CommunityDB(this)),
     508        9743 :       edge_discovery_db_(new EdgeDiscoveryDB(this)),
     509        9743 :       edge_forwarding_db_(new EdgeForwardingDB(this)),
     510        9743 :       extcomm_db_(new ExtCommunityDB(this)),
     511        9743 :       largecomm_db_(new LargeCommunityDB(this)),
     512        9743 :       ovnpath_db_(new OriginVnPathDB(this)),
     513        9743 :       pmsi_tunnel_db_(new PmsiTunnelDB(this)),
     514        9743 :       attr_db_(new BgpAttrDB(this)),
     515        9743 :       session_mgr_(BgpStaticObjectFactory::Create<BgpSessionManager>(evm, this)),
     516        9743 :       update_sender_(new BgpUpdateSender(this)),
     517        9743 :       inst_mgr_(BgpStaticObjectFactory::Create<RoutingInstanceMgr>(this)),
     518        9743 :       policy_mgr_(BgpStaticObjectFactory::Create<RoutingPolicyMgr>(this)),
     519        9743 :       rtarget_group_mgr_(BgpStaticObjectFactory::Create<RTargetGroupMgr>(this)),
     520        9743 :       membership_mgr_(BgpStaticObjectFactory::Create<BgpMembershipManager>(this)),
     521        9743 :       inet_condition_listener_(new BgpConditionListener(this)),
     522        9743 :       inet6_condition_listener_(new BgpConditionListener(this)),
     523        9743 :       evpn_condition_listener_(new BgpConditionListener(this)),
     524        9743 :       evpn6_condition_listener_(new BgpConditionListener(this)),
     525        9743 :       inetvpn_replicator_(new RoutePathReplicator(this, Address::INETVPN)),
     526        9743 :       ermvpn_replicator_(new RoutePathReplicator(this, Address::ERMVPN)),
     527        9743 :       mvpn_replicator_(new RoutePathReplicator(this, Address::MVPN)),
     528        9743 :       evpn_replicator_(new RoutePathReplicator(this, Address::EVPN)),
     529        9743 :       inet6vpn_replicator_(new RoutePathReplicator(this, Address::INET6VPN)),
     530        9743 :       inet_service_chain_mgr_(
     531        9743 :           BgpStaticObjectFactory::Create<IServiceChainMgr, SCAddress::INET>(this)),
     532        9743 :       inet6_service_chain_mgr_(
     533        9743 :           BgpStaticObjectFactory::Create<IServiceChainMgr, SCAddress::INET6>(this)),
     534        9743 :       evpn_service_chain_mgr_(
     535        9743 :           BgpStaticObjectFactory::Create<IServiceChainMgr, SCAddress::EVPN>(this)),
     536        9743 :       evpn6_service_chain_mgr_(
     537        9743 :           BgpStaticObjectFactory::Create<IServiceChainMgr, SCAddress::EVPN6>(this)),
     538        9743 :       global_config_(new BgpGlobalSystemConfig()),
     539        9743 :       global_qos_(new BgpGlobalQosConfig()),
     540        9743 :       config_mgr_(BgpStaticObjectFactory::Create<BgpConfigManager>(this)),
     541       29229 :       updater_(new ConfigUpdater(this)) {
     542        9743 :     bgp_count_ = 0;
     543        9743 :     num_up_peer_ = 0;
     544        9743 :     deleting_count_ = 0;
     545        9743 :     bgpaas_count_ = 0;
     546        9743 :     num_up_bgpaas_peer_ = 0;
     547        9743 :     deleting_bgpaas_count_ = 0;
     548        9743 :     message_build_error_ = 0;
     549        9743 : }
     550             : 
     551       11294 : BgpServer::~BgpServer() {
     552        9743 :     assert(deleting_count_ == 0);
     553        9743 :     assert(deleting_bgpaas_count_ == 0);
     554        9743 :     assert(srt_manager_list_.empty());
     555       11294 : }
     556             : 
     557         158 : void BgpServer::Initialize() {
     558         158 :     RibOutUpdates::Initialize();
     559         158 : }
     560             : 
     561          62 : void BgpServer::Terminate() {
     562          62 :     RibOutUpdates::Terminate();
     563          62 : }
     564             : 
     565     6087098 : string BgpServer::ToString() const {
     566     6087098 :     return bgp_identifier_.to_string();
     567             : }
     568             : 
     569        9701 : void BgpServer::Shutdown() {
     570        9701 :     deleter_->Delete();
     571        9701 : }
     572             : 
     573       58458 : LifetimeActor *BgpServer::deleter() {
     574       58458 :     return deleter_.get();
     575             : }
     576             : 
     577        6501 : bool BgpServer::HasSelfConfiguration() const {
     578        6501 :     if (!bgp_identifier_u32())
     579         321 :         return false;
     580        6180 :     if (!local_autonomous_system())
     581           0 :         return false;
     582        6180 :     if (!autonomous_system())
     583           0 :         return false;
     584        6180 :     return true;
     585             : }
     586             : 
     587       10358 : int BgpServer::RegisterPeer(BgpPeer *peer) {
     588       10358 :     CHECK_CONCURRENCY("bgp::Config");
     589             : 
     590       10358 :     if (peer->IsRouterTypeBGPaaS()) {
     591         114 :         bgpaas_count_++;
     592             :     } else {
     593       10244 :         bgp_count_++;
     594             :     }
     595             : 
     596       10358 :     BgpPeerList::iterator loc;
     597             :     bool result;
     598       10358 :     tie(loc, result) = peer_list_.insert(make_pair(peer->peer_name(), peer));
     599       10358 :     assert(result);
     600       10358 :     assert(loc->second == peer);
     601             : 
     602       10358 :     size_t bit = peer_bmap_.find_first();
     603       10358 :     if (bit == peer_bmap_.npos) {
     604        9341 :         bit = peer_bmap_.size();
     605        9341 :         peer_bmap_.resize(bit + 1, true);
     606             :     }
     607       10358 :     peer_bmap_.reset(bit);
     608       10358 :     return bit;
     609             : }
     610             : 
     611        9574 : void BgpServer::UnregisterPeer(BgpPeer *peer) {
     612        9574 :     CHECK_CONCURRENCY("bgp::Config");
     613             : 
     614        9574 :     if (peer->IsRouterTypeBGPaaS()) {
     615         112 :         assert(bgpaas_count_);
     616         112 :         bgpaas_count_--;
     617             :     } else {
     618        9462 :         assert(bgp_count_);
     619        9462 :         bgp_count_--;
     620             :     }
     621             : 
     622        9574 :     BgpPeerList::iterator loc = peer_list_.find(peer->peer_name());
     623        9574 :     assert(loc != peer_list_.end());
     624        9574 :     peer_list_.erase(loc);
     625             : 
     626        9574 :     peer_bmap_.set(peer->GetIndex());
     627       18131 :     for (size_t i = peer_bmap_.size(); i != 0; i--) {
     628       15037 :         if (peer_bmap_[i-1] != true) {
     629        6480 :             if (i != peer_bmap_.size()) {
     630        1955 :                 peer_bmap_.resize(i);
     631             :             }
     632        6480 :             return;
     633             :         }
     634             :     }
     635        3094 :     peer_bmap_.clear();
     636             : }
     637             : 
     638          26 : BgpPeer *BgpServer::FindPeer(const string &name) {
     639          26 :     BgpPeerList::iterator loc = peer_list_.find(name);
     640          26 :     return (loc != peer_list_.end() ? loc->second : NULL);
     641             : }
     642             : 
     643        2854 : BgpPeer *BgpServer::FindNextPeer(const string &name) {
     644        2854 :     BgpPeerList::iterator loc = peer_list_.upper_bound(name);
     645        2854 :     return (loc != peer_list_.end() ? loc->second : NULL);
     646             : }
     647             : 
     648       10167 : void BgpServer::InsertPeer(TcpSession::Endpoint remote, BgpPeer *peer) {
     649       10167 :     if (!remote.port() && remote.address().is_unspecified())
     650        9973 :         return;
     651         194 :     endpoint_peer_list_.insert(make_pair(remote, peer));
     652             : }
     653             : 
     654       16765 : void BgpServer::RemovePeer(TcpSession::Endpoint remote, BgpPeer *peer) {
     655       16765 :     EndpointPeerList::iterator loc = endpoint_peer_list_.lower_bound(remote);
     656       16766 :     while (loc != endpoint_peer_list_.end() && loc->first == remote) {
     657         125 :         if (loc->second == peer) {
     658         124 :             endpoint_peer_list_.erase(loc);
     659         124 :             break;
     660             :         }
     661           1 :         ++loc;
     662             :     }
     663       16765 : }
     664             : 
     665         820 : void BgpServer::ClearBgpaaSPeers() {
     666         820 :     for (auto &i : endpoint_peer_list_) {
     667           0 :         i.second->Clear(BgpProto::Notification::OtherConfigChange);
     668             :     }
     669         820 : }
     670             : 
     671         847 : BgpPeer *BgpServer::FindPeer(TcpSession::Endpoint remote) const {
     672         847 :     EndpointPeerList::const_iterator loc = endpoint_peer_list_.find(remote);
     673         847 :     return (loc == endpoint_peer_list_.end() ? NULL : loc->second);
     674             : }
     675             : 
     676           4 : BgpPeer *BgpServer::FindExactPeer(const BgpPeer *peer) const {
     677             :     EndpointPeerList::const_iterator loc =
     678           4 :         endpoint_peer_list_.lower_bound(peer->endpoint());
     679           6 :     while (loc != endpoint_peer_list_.end() && loc->first == peer->endpoint()) {
     680           6 :         if (loc->second == peer)
     681           4 :             return loc->second;
     682           2 :         ++loc;
     683             :     }
     684           0 :     return NULL;
     685             : }
     686             : 
     687      661767 : const string &BgpServer::localname() const {
     688      661767 :     return config_mgr_->localname();
     689             : }
     690             : 
     691      298347 : boost::asio::io_context *BgpServer::ioservice() {
     692      298347 :     return session_manager()->event_manager()->io_service();
     693             : }
     694             : 
     695           0 : bool BgpServer::IsFastConvergenceEnabled() const {
     696           0 :     return (global_config_->fc_enabled());
     697             : }
     698             : 
     699      644455 : bool BgpServer::IsNextHopCheckEnabled() const {
     700      644455 :     if (!global_config_->fc_enabled())
     701      644303 :         return false;
     702         140 :     return (global_config_->nh_check_enabled());
     703             : }
     704             : 
     705        4161 : uint16_t BgpServer::GetGracefulRestartTime() const {
     706        4161 :     if (!global_config_->gr_enable())
     707           1 :         return 0;
     708        4160 :     return global_config_->gr_time();
     709             : }
     710             : 
     711        8304 : uint32_t BgpServer::GetLongLivedGracefulRestartTime() const {
     712        8304 :     if (!global_config_->gr_enable())
     713           1 :         return 0;
     714        8303 :     return global_config_->llgr_time();
     715             : }
     716             : 
     717           5 : uint16_t BgpServer::GetXmppHoldTime() const {
     718           5 :     if (!global_config_->fc_enabled())
     719           1 :         return XMPP_HOLD_TIME_DEFAULT;
     720           4 :     return global_config_->xmpp_hold_time();
     721             : }
     722             : 
     723       17220 : uint32_t BgpServer::GetEndOfRibReceiveTime() const {
     724       17220 :     return global_config_->end_of_rib_timeout();
     725             : }
     726             : 
     727       10247 : uint32_t BgpServer::GetEndOfRibSendTime() const {
     728       10247 :     return global_config_->end_of_rib_timeout();
     729             : }
     730             : 
     731        9845 : bool BgpServer::IsServerStartingUp() const {
     732        9845 :     return MiscUtils::GetUpTimeSeconds() < 0.20 * GetEndOfRibSendTime();
     733             : }
     734             : 
     735      220852 : bool BgpServer::enable_4byte_as() const {
     736      220852 :     return global_config()->enable_4byte_as();
     737             : }
     738             : 
     739         470 : void BgpServer::set_enable_4byte_as(bool flag) {
     740         470 :     global_config()->set_enable_4byte_as(flag);
     741         470 : }
     742             : 
     743       14744 : bool BgpServer::IsGRHelperModeEnabled() const {
     744             : 
     745             :     // Check if disabled in .conf file.
     746       14744 :     if (gr_helper_disable_)
     747        1900 :         return false;
     748             : 
     749             :     // Check if GR is disabled..
     750       12844 :     if (!global_config_->gr_enable())
     751        8572 :         return false;
     752             : 
     753             :     // Check from configuration.
     754        4272 :     return global_config_->gr_bgp_helper();
     755             : }
     756             : 
     757         177 : uint32_t BgpServer::num_routing_instance() const {
     758         177 :     assert(inst_mgr_.get());
     759         177 :     return inst_mgr_->count();
     760             : }
     761             : 
     762         177 : uint32_t BgpServer::num_deleted_routing_instance() const {
     763         177 :     assert(inst_mgr_.get());
     764         177 :     return inst_mgr_->deleted_count();
     765             : }
     766             : 
     767          58 : uint32_t BgpServer::get_output_queue_depth() const {
     768          58 :     uint32_t out_q_depth = 0;
     769          58 :     for (RoutingInstanceMgr::RoutingInstanceIterator rit = inst_mgr_->begin();
     770         232 :          rit != inst_mgr_->end(); ++rit) {
     771             :         RoutingInstance::RouteTableList const rt_list =
     772         174 :                      rit->second->GetTables();
     773         174 :         for (RoutingInstance::RouteTableList::const_iterator it =
     774        1450 :              rt_list.begin(); it != rt_list.end(); ++it) {
     775        1102 :             BgpTable *table = it->second;
     776             :             size_t markers;
     777        1102 :             out_q_depth += table->GetPendingRiboutsCount(&markers);
     778             :         }
     779         174 :     }
     780          58 :     return out_q_depth;
     781             : }
     782             : 
     783         881 : uint32_t BgpServer::num_service_chains() const {
     784         881 :     return inet_service_chain_mgr_->PendingQueueSize() +
     785         881 :         inet_service_chain_mgr_->ResolvedQueueSize() +
     786         881 :         inet6_service_chain_mgr_->PendingQueueSize() +
     787         881 :         inet6_service_chain_mgr_->ResolvedQueueSize() +
     788         881 :         evpn_service_chain_mgr_->PendingQueueSize() +
     789         881 :         evpn_service_chain_mgr_->ResolvedQueueSize() +
     790         881 :         evpn6_service_chain_mgr_->PendingQueueSize() +
     791         881 :         evpn6_service_chain_mgr_->ResolvedQueueSize();
     792             : }
     793             : 
     794         305 : uint32_t BgpServer::num_down_service_chains() const {
     795         305 :     return inet_service_chain_mgr_->PendingQueueSize() +
     796         305 :         inet_service_chain_mgr_->GetDownServiceChainCount() +
     797         305 :         inet6_service_chain_mgr_->PendingQueueSize() +
     798         305 :         inet6_service_chain_mgr_->GetDownServiceChainCount() +
     799         305 :         evpn_service_chain_mgr_->PendingQueueSize() +
     800         305 :         evpn_service_chain_mgr_->GetDownServiceChainCount() +
     801         305 :         evpn6_service_chain_mgr_->PendingQueueSize() +
     802         305 :         evpn6_service_chain_mgr_->GetDownServiceChainCount();
     803             : }
     804             : 
     805         187 : uint32_t BgpServer::num_static_routes() const {
     806         187 :     return GetStaticRouteCount();
     807             : }
     808             : 
     809         187 : uint32_t BgpServer::num_down_static_routes() const {
     810         187 :     return GetDownStaticRouteCount();
     811             : }
     812             : 
     813         177 : void BgpServer::VisitBgpPeers(BgpServer::VisitorFn fn) const {
     814         177 :     for (BgpPeerList::const_iterator loc = peer_list_.begin();
     815         334 :          loc != peer_list_.end(); ++loc) {
     816         157 :         fn(loc->second);
     817             :     }
     818         177 : }
     819             : 
     820        2084 : int BgpServer::RegisterAdminDownCallback(AdminDownCb callback) {
     821        2084 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     822        2084 :     size_t i = admin_down_bmap_.find_first();
     823        2084 :     if (i == admin_down_bmap_.npos) {
     824        2084 :         i = admin_down_listeners_.size();
     825        2084 :         admin_down_listeners_.push_back(callback);
     826             :     } else {
     827           0 :         admin_down_bmap_.reset(i);
     828           0 :         if (admin_down_bmap_.none()) {
     829           0 :             admin_down_bmap_.clear();
     830             :         }
     831           0 :         admin_down_listeners_[i] = callback;
     832             :     }
     833        2084 :     return i;
     834        2084 : }
     835             : 
     836        2084 : void BgpServer::UnregisterAdminDownCallback(int listener) {
     837        2084 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     838        2084 :     admin_down_listeners_[listener] = NULL;
     839        2084 :     if ((size_t) listener == admin_down_listeners_.size() - 1) {
     840        6252 :         while (!admin_down_listeners_.empty() &&
     841        2084 :             admin_down_listeners_.back() == NULL) {
     842        2084 :             admin_down_listeners_.pop_back();
     843             :         }
     844        2084 :         if (admin_down_bmap_.size() > admin_down_listeners_.size()) {
     845           0 :             admin_down_bmap_.resize(admin_down_listeners_.size());
     846             :         }
     847             :     } else {
     848           0 :         if ((size_t) listener >= admin_down_bmap_.size()) {
     849           0 :             admin_down_bmap_.resize(listener + 1);
     850             :         }
     851           0 :         admin_down_bmap_.set(listener);
     852             :     }
     853        2084 : }
     854             : 
     855          26 : void BgpServer::NotifyAdminDown() {
     856          26 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     857          26 :     for (AdminDownListenersList::iterator iter = admin_down_listeners_.begin();
     858          42 :          iter != admin_down_listeners_.end(); ++iter) {
     859          16 :         if (*iter != NULL) {
     860          16 :             AdminDownCb cb = *iter;
     861          16 :             (cb)();
     862          16 :         }
     863             :     }
     864          26 : }
     865             : 
     866       16041 : int BgpServer::RegisterASNUpdateCallback(ASNUpdateCb callback) {
     867       16041 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     868       16041 :     size_t i = asn_bmap_.find_first();
     869       16041 :     if (i == asn_bmap_.npos) {
     870       13994 :         i = asn_listeners_.size();
     871       13994 :         asn_listeners_.push_back(callback);
     872             :     } else {
     873        2047 :         asn_bmap_.reset(i);
     874        2047 :         if (asn_bmap_.none()) {
     875           3 :             asn_bmap_.clear();
     876             :         }
     877        2047 :         asn_listeners_[i] = callback;
     878             :     }
     879       16041 :     return i;
     880       16041 : }
     881             : 
     882       16039 : void BgpServer::UnregisterASNUpdateCallback(int listener) {
     883       16039 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     884       16039 :     asn_listeners_[listener] = NULL;
     885       16039 :     if ((size_t) listener == asn_listeners_.size() - 1) {
     886       25904 :         while (!asn_listeners_.empty() && asn_listeners_.back() == NULL) {
     887       13990 :             asn_listeners_.pop_back();
     888             :         }
     889       11914 :         if (asn_bmap_.size() > asn_listeners_.size()) {
     890          84 :             asn_bmap_.resize(asn_listeners_.size());
     891             :         }
     892             :     } else {
     893        4125 :         if ((size_t) listener >= asn_bmap_.size()) {
     894        2081 :             asn_bmap_.resize(listener + 1);
     895             :         }
     896        4125 :         asn_bmap_.set(listener);
     897             :     }
     898       16039 : }
     899             : 
     900        7398 : void BgpServer::NotifyASNUpdate(as_t old_asn, as_t old_local_asn) {
     901        7398 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     902        7398 :     for (ASNUpdateListenersList::iterator iter = asn_listeners_.begin();
     903       17261 :          iter != asn_listeners_.end(); ++iter) {
     904        9863 :         if (*iter != NULL) {
     905        9863 :             ASNUpdateCb cb = *iter;
     906        9863 :             (cb)(old_asn, old_local_asn);
     907        9863 :         }
     908             :     }
     909        7398 : }
     910             : 
     911       12442 : int BgpServer::RegisterDSCPUpdateCallback(DSCPUpdateCb callback) {
     912       12442 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     913       12442 :     size_t i = dscp_bmap_.find_first();
     914       12442 :     if (i == dscp_bmap_.npos) {
     915       11425 :         i = dscp_listeners_.size();
     916       11425 :         dscp_listeners_.push_back(callback);
     917             :     } else {
     918        1017 :         dscp_bmap_.reset(i);
     919        1017 :         if (dscp_bmap_.none()) {
     920         255 :             dscp_bmap_.clear();
     921             :         }
     922        1017 :         dscp_listeners_[i] = callback;
     923             :     }
     924       12442 :     return i;
     925       12442 : }
     926             : 
     927       11651 : void BgpServer::UnregisterDSCPUpdateCallback(int listener) {
     928       11651 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     929       11651 :     dscp_listeners_[listener] = NULL;
     930       11651 :     if ((size_t) listener == dscp_listeners_.size() - 1) {
     931       17496 :         while (!dscp_listeners_.empty() && dscp_listeners_.back() == NULL) {
     932       10634 :             dscp_listeners_.pop_back();
     933             :         }
     934        6862 :         if (dscp_bmap_.size() > dscp_listeners_.size()) {
     935        3021 :             dscp_bmap_.resize(dscp_listeners_.size());
     936             :         }
     937             :     } else {
     938        4789 :         if ((size_t) listener >= dscp_bmap_.size()) {
     939        2945 :             dscp_bmap_.resize(listener + 1);
     940             :         }
     941        4789 :         dscp_bmap_.set(listener);
     942             :     }
     943       11651 : }
     944             : 
     945           9 : void BgpServer::NotifyDSCPUpdate(int new_dscp_value) {
     946           9 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     947           9 :     for (DSCPUpdateListenersList::iterator iter = dscp_listeners_.begin();
     948          22 :          iter != dscp_listeners_.end(); ++iter) {
     949          13 :         if (*iter != NULL) {
     950          13 :             DSCPUpdateCb cb = *iter;
     951          13 :             (cb)(new_dscp_value);
     952          13 :         }
     953             :     }
     954           9 : }
     955             : 
     956       53668 : int BgpServer::RegisterIdentifierUpdateCallback(IdentifierUpdateCb callback) {
     957       53668 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     958       53668 :     size_t i = id_bmap_.find_first();
     959       53668 :     if (i == id_bmap_.npos) {
     960       53668 :         i = id_listeners_.size();
     961       53668 :         id_listeners_.push_back(callback);
     962             :     } else {
     963           0 :         id_bmap_.reset(i);
     964           0 :         if (id_bmap_.none()) {
     965           0 :             id_bmap_.clear();
     966             :         }
     967           0 :         id_listeners_[i] = callback;
     968             :     }
     969       53668 :     return i;
     970       53668 : }
     971             : 
     972       51584 : void BgpServer::UnregisterIdentifierUpdateCallback(int listener) {
     973       51584 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
     974       51584 :     id_listeners_[listener] = NULL;
     975       51584 :     if ((size_t) listener == id_listeners_.size() - 1) {
     976       64269 :         while (!id_listeners_.empty() && id_listeners_.back() == NULL) {
     977       49500 :             id_listeners_.pop_back();
     978             :         }
     979       14769 :         if (id_bmap_.size() > id_listeners_.size()) {
     980        7018 :             id_bmap_.resize(id_listeners_.size());
     981             :         }
     982             :     } else {
     983       36815 :         if ((size_t) listener >= id_bmap_.size()) {
     984       17507 :             id_bmap_.resize(listener + 1);
     985             :         }
     986       36815 :         id_bmap_.set(listener);
     987             :     }
     988       51584 : }
     989             : 
     990        7439 : void BgpServer::NotifyIdentifierUpdate(Ip4Address old_identifier) {
     991        7439 :     tbb::spin_rw_mutex::scoped_lock read_lock(rw_mutex_, false);
     992        7439 :     for (IdentifierUpdateListenersList::iterator iter = id_listeners_.begin();
     993       18456 :          iter != id_listeners_.end(); ++iter) {
     994       11017 :         if (*iter != NULL) {
     995       11017 :             IdentifierUpdateCb cb = *iter;
     996       11017 :             (cb)(old_identifier);
     997       11017 :         }
     998             :     }
     999        7439 : }
    1000             : 
    1001         122 : void BgpServer::InsertStaticRouteMgr(IStaticRouteMgr *srt_manager) {
    1002         122 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    1003         122 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
    1004         122 :     srt_manager_list_.insert(srt_manager);
    1005         122 : }
    1006             : 
    1007         122 : void BgpServer::RemoveStaticRouteMgr(IStaticRouteMgr *srt_manager) {
    1008         122 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    1009         122 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
    1010         122 :     srt_manager_list_.erase(srt_manager);
    1011         122 : }
    1012             : 
    1013      276001 : void BgpServer::NotifyAllStaticRoutes() {
    1014      276001 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    1015      276002 :     tbb::spin_rw_mutex::scoped_lock write_lock(rw_mutex_, true);
    1016      276001 :     for (StaticRouteMgrList::iterator it = srt_manager_list_.begin();
    1017      279654 :          it != srt_manager_list_.end(); ++it) {
    1018        3653 :         IStaticRouteMgr *srt_manager = *it;
    1019        3653 :         srt_manager->NotifyAllRoutes();
    1020             :     }
    1021      276001 : }
    1022             : 
    1023         187 : uint32_t BgpServer::GetStaticRouteCount() const {
    1024         187 :     CHECK_CONCURRENCY("bgp::ShowCommand");
    1025         187 :     uint32_t count = 0;
    1026         187 :     for (StaticRouteMgrList::iterator it = srt_manager_list_.begin();
    1027         195 :          it != srt_manager_list_.end(); ++it) {
    1028           8 :         IStaticRouteMgr *srt_manager = *it;
    1029           8 :         count += srt_manager->GetRouteCount();
    1030             :     }
    1031         187 :     return count;
    1032             : }
    1033             : 
    1034         187 : uint32_t BgpServer::GetDownStaticRouteCount() const {
    1035         187 :     CHECK_CONCURRENCY("bgp::ShowCommand");
    1036         187 :     uint32_t count = 0;
    1037         187 :     for (StaticRouteMgrList::iterator it = srt_manager_list_.begin();
    1038         195 :          it != srt_manager_list_.end(); ++it) {
    1039           8 :         IStaticRouteMgr *srt_manager = *it;
    1040           8 :         count += srt_manager->GetDownRouteCount();
    1041             :     }
    1042         187 :     return count;
    1043             : }
    1044             : 
    1045         157 : void BgpServer::FillPeerStats(const BgpPeer *peer) const {
    1046         157 :     PeerStatsInfo stats;
    1047         157 :     PeerStats::FillPeerDebugStats(peer->peer_stats(), &stats);
    1048             : 
    1049         314 :     BgpPeerInfoData peer_info;
    1050         157 :     peer_info.set_name(peer->ToUVEKey());
    1051         157 :     peer_info.set_peer_stats_info(stats);
    1052         157 :     assert(!peer_info.get_name().empty());
    1053         157 :     BGP_UVE_SEND(BGPPeerInfo, peer_info);
    1054             : 
    1055         314 :     PeerStatsData peer_stats_data;
    1056         157 :     peer_stats_data.set_name(peer->ToUVEKey());
    1057         157 :     peer_stats_data.set_encoding("BGP");
    1058         157 :     PeerStats::FillPeerUpdateStats(peer->peer_stats(), &peer_stats_data);
    1059         157 :     assert(!peer_stats_data.get_name().empty());
    1060         157 :     BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectBgpPeer");
    1061             : 
    1062         157 :     PeerFlapInfo flap_info;
    1063         157 :     flap_info.set_flap_count(peer->flap_count());
    1064         157 :     flap_info.set_flap_time(peer->last_flap());
    1065             : 
    1066         314 :     PeerFlapData peer_flap_data;
    1067         157 :     peer_flap_data.set_name(peer->ToUVEKey());
    1068         157 :     peer_flap_data.set_encoding("BGP");
    1069         157 :     peer_flap_data.set_flap_info(flap_info);
    1070         157 :     assert(!peer_flap_data.get_name().empty());
    1071         157 :     BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
    1072         157 : }
    1073             : 
    1074         177 : bool BgpServer::CollectStats(BgpRouterState *state, bool first) const {
    1075         177 :     CHECK_CONCURRENCY("bgp::ShowCommand");
    1076             : 
    1077         177 :     VisitBgpPeers(boost::bind(&BgpServer::FillPeerStats, this, _1));
    1078         177 :     bool change = false;
    1079         177 :     uint32_t is_admin_down = admin_down();
    1080         177 :     if (first || is_admin_down != state->get_admin_down()) {
    1081           1 :         state->set_admin_down(is_admin_down);
    1082           1 :         change = true;
    1083             :     }
    1084             : 
    1085         177 :     string router_id = bgp_identifier_string();
    1086         177 :     if (first || router_id != state->get_router_id()) {
    1087           2 :         state->set_router_id(router_id);
    1088           2 :         change = true;
    1089             :     }
    1090             : 
    1091         177 :     uint32_t local_asn = local_autonomous_system();
    1092         177 :     if (first || local_asn != state->get_local_asn()) {
    1093           2 :         state->set_local_asn(local_asn);
    1094           2 :         change = true;
    1095             :     }
    1096             : 
    1097         177 :     uint32_t global_asn = autonomous_system();
    1098         177 :     if (first || global_asn != state->get_global_asn()) {
    1099           2 :         state->set_global_asn(global_asn);
    1100           2 :         change = true;
    1101             :     }
    1102             : 
    1103         177 :     uint32_t num_bgp = num_bgp_peer();
    1104         177 :     if (first || num_bgp != state->get_num_bgp_peer()) {
    1105           4 :         state->set_num_bgp_peer(num_bgp);
    1106           4 :         change = true;
    1107             :     }
    1108             : 
    1109         177 :     uint32_t num_up_bgp_peer = NumUpPeer();
    1110         177 :     if (first || num_up_bgp_peer != state->get_num_up_bgp_peer()) {
    1111           8 :         state->set_num_up_bgp_peer(num_up_bgp_peer);
    1112           8 :         change = true;
    1113             :     }
    1114             : 
    1115         177 :     uint32_t deleting_bgp_peer = num_deleting_bgp_peer();
    1116         177 :     if (first || deleting_bgp_peer != state->get_num_deleting_bgp_peer()) {
    1117           1 :         state->set_num_deleting_bgp_peer(deleting_bgp_peer);
    1118           1 :         change = true;
    1119             :     }
    1120             : 
    1121         177 :     uint32_t num_bgpaas = num_bgpaas_peer();
    1122         177 :     if (first || num_bgpaas != state->get_num_bgpaas_peer()) {
    1123           1 :         state->set_num_bgpaas_peer(num_bgpaas);
    1124           1 :         change = true;
    1125             :     }
    1126             : 
    1127         177 :     uint32_t num_up_bgpaas_peer = NumUpBgpaasPeer();
    1128         177 :     if (first || num_up_bgpaas_peer != state->get_num_up_bgpaas_peer()) {
    1129           1 :         state->set_num_up_bgpaas_peer(num_up_bgpaas_peer);
    1130           1 :         change = true;
    1131             :     }
    1132             : 
    1133         177 :     uint32_t deleting_bgpaas_peer = num_deleting_bgpaas_peer();
    1134         353 :     if (first || deleting_bgpaas_peer !=
    1135         176 :             state->get_num_deleting_bgpaas_peer()) {
    1136           1 :         state->set_num_deleting_bgpaas_peer(deleting_bgpaas_peer);
    1137           1 :         change = true;
    1138             :     }
    1139             : 
    1140         177 :     uint32_t num_ri = num_routing_instance();
    1141         177 :     if (first || num_ri != state->get_num_routing_instance()) {
    1142          10 :         state->set_num_routing_instance(num_ri);
    1143          10 :         change = true;
    1144             :     }
    1145             : 
    1146         177 :     uint32_t num_deleted_ri = num_deleted_routing_instance();
    1147         177 :     if (first || num_deleted_ri != state->get_num_deleted_routing_instance()) {
    1148           3 :         state->set_num_deleted_routing_instance(num_deleted_ri);
    1149           3 :         change = true;
    1150             :     }
    1151             : 
    1152         177 :     uint32_t service_chains = num_service_chains();
    1153         177 :     if (first || service_chains != state->get_num_service_chains()) {
    1154           1 :         state->set_num_service_chains(service_chains);
    1155           1 :         change = true;
    1156             :     }
    1157             : 
    1158         177 :     uint32_t down_service_chains = num_down_service_chains();
    1159         177 :     if (first || down_service_chains != state->get_num_down_service_chains()) {
    1160           1 :         state->set_num_down_service_chains(down_service_chains);
    1161           1 :         change = true;
    1162             :     }
    1163             : 
    1164         177 :     uint32_t static_routes = num_static_routes();
    1165         177 :     if (first || static_routes != state->get_num_static_routes()) {
    1166           1 :         state->set_num_static_routes(static_routes);
    1167           1 :         change = true;
    1168             :     }
    1169             : 
    1170         177 :     uint32_t down_static_routes = num_down_static_routes();
    1171         177 :     if (first || down_static_routes != state->get_num_down_static_routes()) {
    1172           1 :         state->set_num_down_static_routes(down_static_routes);
    1173           1 :         change = true;
    1174             :     }
    1175             : 
    1176         177 :     uint32_t out_load = inst_mgr_->SendTableStatsUve();
    1177         177 :     if (first || out_load != state->get_output_queue_depth()) {
    1178           3 :         state->set_output_queue_depth(out_load);
    1179           3 :         change = true;
    1180             :     }
    1181             : 
    1182         177 :     vector<string> bgp_config_peer_list;
    1183         491 :     BOOST_FOREACH(BgpConfigManager::NeighborMap::value_type value,
    1184             :         config_mgr_->NeighborMapItems(BgpConfigManager::kMasterInstance)) {
    1185         157 :         const BgpNeighborConfig *neighbor = value.second;
    1186         157 :         string name(BgpConfigManager::kMasterInstance);
    1187         157 :         name += ":";
    1188         157 :         name += localname();
    1189         157 :         name += ":";
    1190         157 :         name += neighbor->name();
    1191         157 :         bgp_config_peer_list.push_back(name);
    1192         314 :     }
    1193         177 :     sort(bgp_config_peer_list.begin(), bgp_config_peer_list.end());
    1194         177 :     if (first || bgp_config_peer_list != state->get_bgp_config_peer_list()) {
    1195           4 :         state->set_bgp_config_peer_list(bgp_config_peer_list);
    1196           4 :         change = true;
    1197             :     }
    1198             : 
    1199         177 :     vector<string> bgp_oper_peer_list;
    1200         177 :     const RoutingInstance *rtinstance = inst_mgr_->GetDefaultRoutingInstance();
    1201         177 :     const PeerManager *peer_manager = rtinstance->peer_manager();
    1202         177 :     for (const BgpPeer *peer = peer_manager->NextPeer(BgpPeerKey());
    1203         334 :         peer != NULL; peer = peer_manager->NextPeer(peer->peer_key())) {
    1204         157 :         bgp_oper_peer_list.push_back(peer->ToUVEKey());
    1205             :     }
    1206         177 :     sort(bgp_oper_peer_list.begin(), bgp_oper_peer_list.end());
    1207         177 :     if (first || bgp_oper_peer_list != state->get_bgp_oper_peer_list()) {
    1208           4 :         state->set_bgp_oper_peer_list(bgp_oper_peer_list);
    1209           4 :         change = true;
    1210             :     }
    1211             : 
    1212         177 :     return change;
    1213         177 : }
    1214             : 
    1215           0 : time_t BgpServer::GetRTargetTableLastUpdatedTimeStamp() const {
    1216           0 :     const RoutingInstanceMgr *ri_mgr = routing_instance_mgr();
    1217           0 :     const RTargetTable *rtarget_table = dynamic_cast<const RTargetTable *>(
    1218           0 :             ri_mgr->GetDefaultRoutingInstance()->GetTable(Address::RTARGET));
    1219           0 :     return rtarget_table->last_updated();
    1220             : }
    1221             : 
    1222        7439 : void BgpServer::UpdateBgpIdentifier(const Ip4Address &identifier) {
    1223        7439 :     Ip4Address old_identifier = bgp_identifier_;
    1224        7439 :     bgp_identifier_ = identifier;
    1225        7439 :     bgp_identifier_u32_ = identifier.to_ulong();
    1226        7439 :     NotifyIdentifierUpdate(old_identifier);
    1227        7439 : }

Generated by: LCOV version 1.14