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

Generated by: LCOV version 1.14