LCOV - code coverage report
Current view: top level - bgp - bgp_peer_close.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 231 235 98.3 %
Date: 2026-06-04 02:06:09 Functions: 41 42 97.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <boost/foreach.hpp>
       6             : #include <boost/assign/list_of.hpp>
       7             : #include <boost/scoped_ptr.hpp>
       8             : 
       9             : #include "base/task_annotations.h"
      10             : #include "net/bgp_af.h"
      11             : #include "bgp/bgp_factory.h"
      12             : #include "bgp/bgp_path.h"
      13             : #include "bgp/bgp_log.h"
      14             : #include "bgp/bgp_peer.h"
      15             : #include "bgp/bgp_peer_close.h"
      16             : #include "bgp/bgp_peer_types.h"
      17             : #include "bgp/peer_close_manager.h"
      18             : 
      19             : using boost::assign::list_of;
      20             : using std::back_inserter;
      21             : using std::includes;
      22             : using std::string;
      23             : using std::vector;
      24             : 
      25      206982 : BgpPeerClose::BgpPeerClose(BgpPeer *peer)
      26      206982 :         : peer_(peer), flap_count_(0) {
      27      206982 : }
      28             : 
      29      217138 : BgpPeerClose::~BgpPeerClose() {
      30      217138 : }
      31             : 
      32      174599 : PeerCloseManager *BgpPeerClose::GetManager() const {
      33      174599 :     return peer_->close_manager();
      34             : }
      35             : 
      36       14837 : void BgpPeerClose::CustomClose() {
      37       14837 :     return peer_->CustomClose();
      38             : }
      39             : 
      40         689 : void BgpPeerClose::GracefulRestartStale() {
      41         689 :     negotiated_families_ = peer_->negotiated_families();
      42         689 : }
      43             : 
      44         160 : void BgpPeerClose::LongLivedGracefulRestartStale() {
      45         160 : }
      46             : 
      47         610 : void BgpPeerClose::GracefulRestartSweep() {
      48         610 :     negotiated_families_.clear();
      49         610 : }
      50             : 
      51        1652 : bool BgpPeerClose::IsReady() const {
      52        1652 :     return peer_->IsReady();
      53             : }
      54             : 
      55      565184 : IPeer *BgpPeerClose::peer() const {
      56      565184 :     return peer_;
      57             : }
      58             : 
      59             : // Return the time to wait for, in seconds to exit GR_TIMER state.
      60        6176 : int BgpPeerClose::GetGracefulRestartTime() const {
      61        6176 :     return gr_params_.time;
      62             : }
      63             : 
      64             : // Return the time to wait for, in seconds to exit LLGR_TIMER state.
      65        5647 : int BgpPeerClose::GetLongLivedGracefulRestartTime() const {
      66        5647 :     return llgr_params_.time;
      67             : }
      68             : 
      69           0 : void BgpPeerClose::ReceiveEndOfRIB(Address::Family family) {
      70           0 :     peer_->ReceiveEndOfRIB(family, 0);
      71           0 : }
      72             : 
      73      110568 : const char *BgpPeerClose::GetTaskName() const {
      74      110568 :     return "bgp::Config";
      75             : }
      76             : 
      77       10360 : int BgpPeerClose::GetTaskInstance() const {
      78       10360 :     return 0;
      79             : }
      80             : 
      81        6227 : void BgpPeerClose::MembershipRequestCallbackComplete() {
      82        6227 :     CHECK_CONCURRENCY(GetTaskName());
      83        6227 : }
      84             : 
      85       14729 : bool BgpPeerClose::IsGRHelperModeEnabled() const {
      86       14729 :     return peer_->server()->IsGRHelperModeEnabled();
      87             : }
      88             : 
      89        6283 : const std::vector<std::string> &BgpPeerClose::PeerNegotiatedFamilies() const {
      90        6283 :     return peer_->negotiated_families();
      91             : }
      92             : 
      93       14892 : bool BgpPeerClose::IsPeerDeleted() const {
      94       14892 :     return peer_->IsDeleted();
      95             : }
      96             : 
      97       14891 : bool BgpPeerClose::IsPeerAdminDown() const {
      98       14891 :     return peer_->IsAdminDown();
      99             : }
     100             : 
     101       14730 : bool BgpPeerClose::IsServerDeleted() const {
     102       14730 :     return peer_->server()->IsDeleted();
     103             : }
     104             : 
     105       14730 : bool BgpPeerClose::IsServerAdminDown() const {
     106       14730 :     return peer_->server()->admin_down();
     107             : }
     108             : 
     109        7221 : bool BgpPeerClose::IsInGRTimerWaitState() const {
     110        7221 :     return GetManager()->IsInGRTimerWaitState();
     111             : }
     112             : 
     113         641 : bool BgpPeerClose::IsInLlgrTimerWaitState() const {
     114         641 :     return GetManager()->IsInLlgrTimerWaitState();
     115             : }
     116             : 
     117        6283 : const std::vector<std::string> &BgpPeerClose::negotiated_families() const {
     118        6283 :     return negotiated_families_;
     119             : }
     120             : 
     121             : const std::vector<BgpProto::OpenMessage::Capability *> &
     122       10868 : BgpPeerClose::capabilities() const {
     123       10868 :     return peer_->capabilities();
     124             : }
     125             : 
     126      150979 : void BgpPeerClose::UpdateRouteStats(Address::Family family,
     127             :                                     const BgpPath *old_path,
     128             :                                     uint32_t path_flags) const {
     129      150979 :     GetManager()->UpdateRouteStats(family, old_path, path_flags);
     130      150982 : }
     131             : 
     132       15754 : void BgpPeerClose::Close(bool graceful) {
     133             :     // Abort GR-Closure if this request is for non-graceful closure.
     134             :     // Reset GR-Closure if previous closure is still in progress or if
     135             :     // this is a flip (from established state).
     136       15754 :     if (!graceful || flap_count_ != peer_->total_flap_count()) {
     137       13250 :         if (flap_count_ != peer_->total_flap_count()) {
     138        5342 :             flap_count_++;
     139        5342 :             assert(peer_->total_flap_count() == flap_count_);
     140             :         }
     141       13250 :         GetManager()->Close(graceful);
     142       13250 :         return;
     143             :     }
     144             : 
     145             :     // Ignore if close is already in progress.
     146        2504 :     if (GetManager()->IsCloseInProgress() && !IsInGRTimerWaitState())
     147          36 :         return;
     148             : 
     149        2467 :     if (peer_->IsDeleted()) {
     150           0 :         peer_->RetryDelete();
     151             :     } else {
     152        2467 :         CustomClose();
     153        2468 :         CloseComplete();
     154             :     }
     155             : }
     156             : 
     157       12370 : void BgpPeerClose::Delete() {
     158       12370 :     gr_params_.Initialize();
     159       12370 :     llgr_params_.Initialize();
     160       12370 :     gr_families_.clear();
     161       12370 :     llgr_families_.clear();
     162       12370 :     negotiated_families_.clear();
     163       12370 :     if (peer_->IsDeleted()) {
     164        9569 :         peer_->RetryDelete();
     165             :     } else {
     166        2801 :         CloseComplete();
     167             :     }
     168       12370 : }
     169             : 
     170      801162 : bool BgpPeerClose::IsGRReady() const {
     171             :     // Check if GR Helper mode is disabled.
     172      801162 :     if (!IsGRHelperModeEnabled()) {
     173       10474 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     174             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because it is not"
     175             :             " configured");
     176       10475 :         return false;
     177             :     }
     178             : 
     179             :     // Check if GR is supported by the peer.
     180      790687 :     if (gr_params_.families.empty()) {
     181      442368 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     182             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
     183             :             "GR address families list is empty");
     184      442368 :         return false;
     185             :     }
     186             : 
     187             :     // LLGR should be in effect to enable GR Helper mode with 0 restart time.
     188      348320 :     if (!gr_params_.time && !IsCloseLongLivedGracefulInternal()) {
     189      166666 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     190             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
     191             :             "GR restart time value is 0 seconds and (there is no applicable "
     192             :             "LLGR as well");
     193      166666 :         return false;
     194             :     }
     195             : 
     196             :     // Abort GR if currently negotiated families differ from already
     197             :     // staled address families.
     198      338923 :     if (!negotiated_families().empty() &&
     199      157269 :             PeerNegotiatedFamilies() != negotiated_families()) {
     200      135828 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     201             :             BGP_PEER_DIR_IN, "GR Helper mode is aborted because received "
     202             :             "GR families list differs from the list received last time");
     203      135828 :         return false;
     204             :     }
     205             : 
     206             :     // If GR is not supported for any of the negotiated address family,
     207             :     // then consider GR as not supported
     208       45826 :     if (PeerNegotiatedFamilies() != gr_families_) {
     209       36036 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     210             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because GR address "
     211             :             "families differs from negotiated address families");
     212       36036 :         return false;
     213             :     }
     214             : 
     215             :     // Make sure that forwarding state is preserved for all families in
     216             :     // the restarting speaker. (Except for ERMVPN)
     217       26667 :     for (auto family : gr_params_.families) {
     218             :         // Check if forwarding state was preserved during restart.
     219       19517 :         if (family.forwarding_state_preserved())
     220       16877 :             continue;
     221             : 
     222             :         // Ignore forwarding-state preservation check for certain families.
     223             :         Address::Family addr_family =
     224        2904 :             BgpAf::AfiSafiToFamily(family.afi, family.safi);
     225        2904 :         if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
     226         264 :             continue;
     227             : 
     228        2640 :         string family_str = Address::FamilyToString(addr_family);
     229        2640 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
     230             :             BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not  "
     231             :             "enabled because after restart, GR forwarding state is not "
     232             :             "preserved for address family " << family_str);
     233        2640 :         return false;
     234        2640 :     }
     235        7149 :     return true;
     236             : }
     237             : 
     238             : // If the peer is deleted or administratively held down, do not attempt
     239             : // graceful restart
     240      801329 : bool BgpPeerClose::IsCloseGraceful() const {
     241      801329 :     if (IsPeerDeleted()) {
     242           1 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     243             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
     244             :             " been deleted");
     245           1 :         return false;
     246             :     }
     247             : 
     248      801327 :     if (IsPeerAdminDown()) {
     249         162 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     250             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
     251             :             " been held administratively down");
     252         162 :         return false;
     253             :     }
     254             : 
     255      801165 :     if (IsServerDeleted()) {
     256           1 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     257             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
     258             :             "has been deletd");
     259           1 :         return false;
     260             :     }
     261             : 
     262      801164 :     if (IsServerAdminDown()) {
     263           1 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     264             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
     265             :             "has been held administratively down");
     266           1 :         return false;
     267             :     }
     268             : 
     269      801162 :     if (!IsGRReady())
     270      794013 :         return false;
     271        7148 :     return true;
     272             : }
     273             : 
     274             : // LLGR families should be identical to GR families.
     275       40893 : bool BgpPeerClose::IsLlgrSupportedForFamilies() const {
     276             :     // Keep a sorted list of unsupported families.
     277             :     static vector<string> unsupported_families = list_of
     278          36 :         (Address::FamilyToString(Address::ERMVPN))
     279       40911 :         (Address::FamilyToString(Address::MVPN));
     280             : 
     281       40893 :     if (gr_families_ == llgr_families_)
     282        8357 :         return true;
     283             : 
     284             :     // Ignore families mis-match for certain families.
     285       32536 :     vector<string> differing_families;
     286       32536 :     std::set_symmetric_difference(gr_families_.begin(), gr_families_.end(),
     287             :                                   llgr_families_.begin(), llgr_families_.end(),
     288             :                                   back_inserter(differing_families));
     289             : 
     290             :     // Ignore if differing families are only those which are unsupported.
     291       32536 :     return includes(unsupported_families.begin(), unsupported_families.end(),
     292       32536 :                     differing_families.begin(), differing_families.end());
     293       32536 : }
     294             : 
     295             : // Check if we need to trigger Long Lived Graceful Restart. In addition to
     296             : // normal GR checks, we also need to check LLGR capability was negotiated
     297             : // and non-zero restart time was inferred.
     298      406441 : bool BgpPeerClose::IsCloseLongLivedGraceful() const {
     299      406441 :     if (!IsCloseGraceful())
     300      402083 :         return false;
     301        4357 :     return BgpPeerClose::IsCloseLongLivedGracefulInternal();
     302             : }
     303             : 
     304      176411 : bool BgpPeerClose::IsCloseLongLivedGracefulInternal() const {
     305      176411 :     if (llgr_params_.families.empty()) {
     306       97578 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     307             :             BGP_PEER_DIR_IN,
     308             :             "No LLGR support due to empty LLGR address families list");
     309       97578 :         return false;
     310             :     }
     311       78833 :     if (!llgr_params_.time) {
     312       37940 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     313             :             BGP_PEER_DIR_IN, "No LLGR support due to zero time value");
     314       37940 :         return false;
     315             :     }
     316             : 
     317       40893 :     if (!IsLlgrSupportedForFamilies()) {
     318       27880 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     319             :             BGP_PEER_DIR_IN, "No LLGR support due to dissimilar "
     320             :             "GR address families and LLGR address families");
     321       27880 :         return false;
     322             :     }
     323             : 
     324             :     // Make sure that forwarding state is preserved for all families in
     325             :     // the restarting speaker.
     326       32294 :     for (auto family : llgr_params_.families) {
     327             :         // Ignore forwarding-state preservation check for certain families.
     328             :         Address::Family addr_family =
     329       23921 :             BgpAf::AfiSafiToFamily(family.afi, family.safi);
     330       23921 :         if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
     331        4623 :             continue;
     332             : 
     333       19298 :         if (!family.forwarding_state_preserved()) {
     334        4640 :             string family_str = Address::FamilyToString(addr_family);
     335        4640 :             BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
     336             :                 BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not "
     337             :                 "enabled because after restart, LLGR forwarding state is not "
     338             :                 "preserved for address family " << family_str);
     339        4640 :             return false;
     340        4640 :         }
     341             :     }
     342        8373 :     return true;
     343             : }
     344             : 
     345        5559 : void BgpPeerClose::RestartStateMachine() {
     346        5559 :     peer_->state_machine()->Initialize();
     347        5559 : }
     348             : 
     349             : // Close process for this peer is complete. Restart the state machine and
     350             : // attempt to bring up session with the neighbor
     351        6118 : void BgpPeerClose::CloseComplete() {
     352        6118 :     if (!peer_->IsDeleted() && !peer_->IsAdminDown())
     353        5623 :         RestartStateMachine();
     354        6118 : }
     355             : 
     356         689 : void BgpPeerClose::GetGracefulRestartFamilies(Families *families) const {
     357         689 :     families->clear();
     358        2246 :     for (const auto& family : gr_families_) {
     359        1557 :         families->insert(Address::FamilyFromString(family));
     360             :     }
     361         689 : }
     362             : 
     363         160 : void BgpPeerClose::GetLongLivedGracefulRestartFamilies(Families *families) const {
     364         160 :     families->clear();
     365         560 :     for (const auto& family : llgr_families_) {
     366         400 :         families->insert(Address::FamilyFromString(family));
     367             :     }
     368         160 : }
     369             : 
     370        9281 : void BgpPeerClose::AddGRCapabilities(
     371             :         BgpProto::OpenMessage::OptParam *opt_param) {
     372        9281 :     vector<Address::Family> gr_families;
     373        9284 :     vector<uint8_t> afi_flags;
     374             : 
     375             :     // Indicate to the Peer if we are in restarting phase.
     376        9283 :     bool restarted = peer_->IsServerStartingUp();
     377             : 
     378             :     // Indicate EOR support by default.
     379        9283 :     if (!peer_->server()->global_config()->gr_enable()) {
     380             :         BgpProto::OpenMessage::Capability *gr_cap =
     381        5165 :             BgpProto::OpenMessage::Capability::GR::Encode(0, restarted, false,
     382             :                                                           afi_flags,
     383        5164 :                                                           gr_families);
     384        5164 :         opt_param->capabilities.push_back(gr_cap);
     385        5164 :         return;
     386             :     }
     387             : 
     388       41179 :     for (auto family : peer_->supported_families()) {
     389       37060 :         if (!peer_->LookupFamily(family))
     390       21877 :             continue;
     391       15184 :         gr_families.push_back(family);
     392       15184 :         afi_flags.push_back(BgpProto::OpenMessage::Capability::GR::
     393             :                                 ForwardingStatePreservedFlag);
     394             :     }
     395             : 
     396        4118 :     uint16_t time = peer_->server()->GetGracefulRestartTime();
     397             :     BgpProto::OpenMessage::Capability *gr_cap =
     398        4118 :         BgpProto::OpenMessage::Capability::GR::Encode(time, restarted, true,
     399        4118 :                                                       afi_flags, gr_families);
     400        4118 :     opt_param->capabilities.push_back(gr_cap);
     401       14446 : }
     402             : 
     403             : // Process received GR and LLGR Capabilities. Return true if the values are sane
     404             : // to proceed with further processing. Return false if not to abort any ongoing
     405             : // GR and instead trigger non-graceful closure.
     406      791879 : bool BgpPeerClose::SetGRCapabilities(BgpPeerInfoData *peer_info) {
     407      791879 :     BgpProto::OpenMessage::Capability::GR::Decode(&gr_params_, capabilities());
     408      791881 :     BgpProto::OpenMessage::Capability::GR::GetFamilies(gr_params_,
     409             :                                                        &gr_families_);
     410             : 
     411      791881 :     BgpProto::OpenMessage::Capability::LLGR::Decode(&llgr_params_,
     412      791881 :                                                     capabilities());
     413      791881 :     BgpProto::OpenMessage::Capability::LLGR::GetFamilies(llgr_params_,
     414             :                                                          &llgr_families_);
     415             : 
     416      791879 :     if (peer_info) {
     417        5433 :         peer_info->set_graceful_restart_families(gr_families_);
     418        5433 :         peer_info->set_long_lived_graceful_restart_families(llgr_families_);
     419        5431 :         peer_info->set_graceful_restart_time(GetGracefulRestartTime());
     420       10862 :         peer_info->set_long_lived_graceful_restart_time(
     421        5431 :                 GetLongLivedGracefulRestartTime());
     422        5431 :         assert(!peer_info->get_name().empty());
     423        5431 :         BGP_UVE_SEND(BGPPeerInfo, *peer_info);
     424             :     }
     425             : 
     426             :     // If we are not in GR Timer waiting state, then there is no case to abort
     427             :     // GR when new session is coming up.
     428      791877 :     if (!IsInGRTimerWaitState())
     429        4799 :         return true;
     430             : 
     431             :     // If LLGR is no longer supported, terminate GR right away. This can happen
     432             :     // due to mis-match between gr and llgr afis. For now, we expect an
     433             :     // identical set.
     434      787078 :     if (IsInLlgrTimerWaitState())
     435      393349 :         return IsCloseLongLivedGraceful();
     436      393729 :     return IsCloseGraceful();
     437             : }
     438             : 
     439        9282 : void BgpPeerClose::AddLLGRCapabilities(
     440             :         BgpProto::OpenMessage::OptParam *opt_param) {
     441       13400 :     if (!peer_->server()->global_config()->gr_enable() ||
     442        4118 :             !peer_->server()->GetLongLivedGracefulRestartTime()) {
     443        5180 :         return;
     444             :     }
     445             : 
     446        4102 :     vector<Address::Family> llgr_families;
     447       41020 :     for (auto family : peer_->supported_families()) {
     448       36918 :         if (peer_->LookupFamily(family))
     449       15169 :             llgr_families.push_back(family);
     450             :     }
     451             : 
     452        4101 :     uint32_t time = peer_->server()->GetLongLivedGracefulRestartTime();
     453        4102 :     uint8_t afi_flags =
     454             :         BgpProto::OpenMessage::Capability::LLGR::ForwardingStatePreservedFlag;
     455             :     BgpProto::OpenMessage::Capability *llgr_cap =
     456        4102 :         BgpProto::OpenMessage::Capability::LLGR::Encode(time, afi_flags,
     457        4102 :                                                         llgr_families);
     458        4102 :     opt_param->capabilities.push_back(llgr_cap);
     459        4102 : }
     460             : 
     461          56 : void BgpPeerClose::FillNeighborInfo(BgpNeighborResp *bnr) const {
     462          56 :     bnr->set_graceful_restart_address_families(gr_families_);
     463          56 :     bnr->set_long_lived_graceful_restart_address_families(llgr_families_);
     464          56 :     bnr->set_graceful_restart_time(GetGracefulRestartTime());
     465         112 :     bnr->set_long_lived_graceful_restart_time(
     466          56 :             GetLongLivedGracefulRestartTime());
     467          56 : }

Generated by: LCOV version 1.14