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-11-09 02:10:49 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             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <boost/foreach.hpp>
       7             : #include <boost/assign/list_of.hpp>
       8             : #include <boost/scoped_ptr.hpp>
       9             : 
      10             : #include "base/task_annotations.h"
      11             : #include "net/bgp_af.h"
      12             : #include "bgp/bgp_factory.h"
      13             : #include "bgp/bgp_path.h"
      14             : #include "bgp/bgp_log.h"
      15             : #include "bgp/bgp_peer.h"
      16             : #include "bgp/bgp_peer_close.h"
      17             : #include "bgp/bgp_peer_types.h"
      18             : #include "bgp/peer_close_manager.h"
      19             : 
      20             : using boost::assign::list_of;
      21             : using std::back_inserter;
      22             : using std::includes;
      23             : using std::string;
      24             : using std::vector;
      25             : 
      26      206980 : BgpPeerClose::BgpPeerClose(BgpPeer *peer)
      27      206980 :         : peer_(peer), flap_count_(0) {
      28      206980 : }
      29             : 
      30      217134 : BgpPeerClose::~BgpPeerClose() {
      31      217134 : }
      32             : 
      33      174746 : PeerCloseManager *BgpPeerClose::GetManager() const {
      34      174746 :     return peer_->close_manager();
      35             : }
      36             : 
      37       14983 : void BgpPeerClose::CustomClose() {
      38       14983 :     return peer_->CustomClose();
      39             : }
      40             : 
      41         698 : void BgpPeerClose::GracefulRestartStale() {
      42         698 :     negotiated_families_ = peer_->negotiated_families();
      43         698 : }
      44             : 
      45         160 : void BgpPeerClose::LongLivedGracefulRestartStale() {
      46         160 : }
      47             : 
      48         618 : void BgpPeerClose::GracefulRestartSweep() {
      49         618 :     negotiated_families_.clear();
      50         618 : }
      51             : 
      52        1668 : bool BgpPeerClose::IsReady() const {
      53        1668 :     return peer_->IsReady();
      54             : }
      55             : 
      56      565586 : IPeer *BgpPeerClose::peer() const {
      57      565586 :     return peer_;
      58             : }
      59             : 
      60             : // Return the time to wait for, in seconds to exit GR_TIMER state.
      61        6180 : int BgpPeerClose::GetGracefulRestartTime() const {
      62        6180 :     return gr_params_.time;
      63             : }
      64             : 
      65             : // Return the time to wait for, in seconds to exit LLGR_TIMER state.
      66        5642 : int BgpPeerClose::GetLongLivedGracefulRestartTime() const {
      67        5642 :     return llgr_params_.time;
      68             : }
      69             : 
      70           0 : void BgpPeerClose::ReceiveEndOfRIB(Address::Family family) {
      71           0 :     peer_->ReceiveEndOfRIB(family, 0);
      72           0 : }
      73             : 
      74      110789 : const char *BgpPeerClose::GetTaskName() const {
      75      110789 :     return "bgp::Config";
      76             : }
      77             : 
      78       10358 : int BgpPeerClose::GetTaskInstance() const {
      79       10358 :     return 0;
      80             : }
      81             : 
      82        6245 : void BgpPeerClose::MembershipRequestCallbackComplete() {
      83        6245 :     CHECK_CONCURRENCY(GetTaskName());
      84        6245 : }
      85             : 
      86       14744 : bool BgpPeerClose::IsGRHelperModeEnabled() const {
      87       14744 :     return peer_->server()->IsGRHelperModeEnabled();
      88             : }
      89             : 
      90        6295 : const std::vector<std::string> &BgpPeerClose::PeerNegotiatedFamilies() const {
      91        6295 :     return peer_->negotiated_families();
      92             : }
      93             : 
      94       14909 : bool BgpPeerClose::IsPeerDeleted() const {
      95       14909 :     return peer_->IsDeleted();
      96             : }
      97             : 
      98       14907 : bool BgpPeerClose::IsPeerAdminDown() const {
      99       14907 :     return peer_->IsAdminDown();
     100             : }
     101             : 
     102       14746 : bool BgpPeerClose::IsServerDeleted() const {
     103       14746 :     return peer_->server()->IsDeleted();
     104             : }
     105             : 
     106       14747 : bool BgpPeerClose::IsServerAdminDown() const {
     107       14747 :     return peer_->server()->admin_down();
     108             : }
     109             : 
     110        7274 : bool BgpPeerClose::IsInGRTimerWaitState() const {
     111        7274 :     return GetManager()->IsInGRTimerWaitState();
     112             : }
     113             : 
     114         636 : bool BgpPeerClose::IsInLlgrTimerWaitState() const {
     115         636 :     return GetManager()->IsInLlgrTimerWaitState();
     116             : }
     117             : 
     118        6294 : const std::vector<std::string> &BgpPeerClose::negotiated_families() const {
     119        6294 :     return negotiated_families_;
     120             : }
     121             : 
     122             : const std::vector<BgpProto::OpenMessage::Capability *> &
     123       10850 : BgpPeerClose::capabilities() const {
     124       10850 :     return peer_->capabilities();
     125             : }
     126             : 
     127      150908 : void BgpPeerClose::UpdateRouteStats(Address::Family family,
     128             :                                     const BgpPath *old_path,
     129             :                                     uint32_t path_flags) const {
     130      150908 :     GetManager()->UpdateRouteStats(family, old_path, path_flags);
     131      150899 : }
     132             : 
     133       15928 : void BgpPeerClose::Close(bool graceful) {
     134             :     // Abort GR-Closure if this request is for non-graceful closure.
     135             :     // Reset GR-Closure if previous closure is still in progress or if
     136             :     // this is a flip (from established state).
     137       15928 :     if (!graceful || flap_count_ != peer_->total_flap_count()) {
     138       13289 :         if (flap_count_ != peer_->total_flap_count()) {
     139        5351 :             flap_count_++;
     140        5351 :             assert(peer_->total_flap_count() == flap_count_);
     141             :         }
     142       13286 :         GetManager()->Close(graceful);
     143       13292 :         return;
     144             :     }
     145             : 
     146             :     // Ignore if close is already in progress.
     147        2639 :     if (GetManager()->IsCloseInProgress() && !IsInGRTimerWaitState())
     148          41 :         return;
     149             : 
     150        2599 :     if (peer_->IsDeleted()) {
     151           0 :         peer_->RetryDelete();
     152             :     } else {
     153        2599 :         CustomClose();
     154        2599 :         CloseComplete();
     155             :     }
     156             : }
     157             : 
     158       12384 : void BgpPeerClose::Delete() {
     159       12384 :     gr_params_.Initialize();
     160       12384 :     llgr_params_.Initialize();
     161       12384 :     gr_families_.clear();
     162       12384 :     llgr_families_.clear();
     163       12384 :     negotiated_families_.clear();
     164       12384 :     if (peer_->IsDeleted()) {
     165        9567 :         peer_->RetryDelete();
     166             :     } else {
     167        2817 :         CloseComplete();
     168             :     }
     169       12384 : }
     170             : 
     171      801176 : bool BgpPeerClose::IsGRReady() const {
     172             :     // Check if GR Helper mode is disabled.
     173      801176 :     if (!IsGRHelperModeEnabled()) {
     174       10473 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     175             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because it is not"
     176             :             " configured");
     177       10472 :         return false;
     178             :     }
     179             : 
     180             :     // Check if GR is supported by the peer.
     181      790703 :     if (gr_params_.families.empty()) {
     182      442369 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     183             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
     184             :             "GR address families list is empty");
     185      442368 :         return false;
     186             :     }
     187             : 
     188             :     // LLGR should be in effect to enable GR Helper mode with 0 restart time.
     189      348334 :     if (!gr_params_.time && !IsCloseLongLivedGracefulInternal()) {
     190      166666 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     191             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
     192             :             "GR restart time value is 0 seconds and (there is no applicable "
     193             :             "LLGR as well");
     194      166666 :         return false;
     195             :     }
     196             : 
     197             :     // Abort GR if currently negotiated families differ from already
     198             :     // staled address families.
     199      338934 :     if (!negotiated_families().empty() &&
     200      157266 :             PeerNegotiatedFamilies() != negotiated_families()) {
     201      135828 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     202             :             BGP_PEER_DIR_IN, "GR Helper mode is aborted because received "
     203             :             "GR families list differs from the list received last time");
     204      135828 :         return false;
     205             :     }
     206             : 
     207             :     // If GR is not supported for any of the negotiated address family,
     208             :     // then consider GR as not supported
     209       45841 :     if (PeerNegotiatedFamilies() != gr_families_) {
     210       36036 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     211             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because GR address "
     212             :             "families differs from negotiated address families");
     213       36036 :         return false;
     214             :     }
     215             : 
     216             :     // Make sure that forwarding state is preserved for all families in
     217             :     // the restarting speaker. (Except for ERMVPN)
     218       26671 :     for (auto family : gr_params_.families) {
     219             :         // Check if forwarding state was preserved during restart.
     220       19506 :         if (family.forwarding_state_preserved())
     221       16865 :             continue;
     222             : 
     223             :         // Ignore forwarding-state preservation check for certain families.
     224             :         Address::Family addr_family =
     225        2904 :             BgpAf::AfiSafiToFamily(family.afi, family.safi);
     226        2904 :         if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
     227         264 :             continue;
     228             : 
     229        2640 :         string family_str = Address::FamilyToString(addr_family);
     230        2640 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
     231             :             BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not  "
     232             :             "enabled because after restart, GR forwarding state is not "
     233             :             "preserved for address family " << family_str);
     234        2640 :         return false;
     235        2640 :     }
     236        7165 :     return true;
     237             : }
     238             : 
     239             : // If the peer is deleted or administratively held down, do not attempt
     240             : // graceful restart
     241      801343 : bool BgpPeerClose::IsCloseGraceful() const {
     242      801343 :     if (IsPeerDeleted()) {
     243           1 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     244             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
     245             :             " been deleted");
     246           1 :         return false;
     247             :     }
     248             : 
     249      801344 :     if (IsPeerAdminDown()) {
     250         162 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     251             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
     252             :             " been held administratively down");
     253         162 :         return false;
     254             :     }
     255             : 
     256      801180 :     if (IsServerDeleted()) {
     257           1 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     258             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
     259             :             "has been deletd");
     260           1 :         return false;
     261             :     }
     262             : 
     263      801180 :     if (IsServerAdminDown()) {
     264           1 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     265             :             BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
     266             :             "has been held administratively down");
     267           1 :         return false;
     268             :     }
     269             : 
     270      801179 :     if (!IsGRReady())
     271      794012 :         return false;
     272        7165 :     return true;
     273             : }
     274             : 
     275             : // LLGR families should be identical to GR families.
     276       40899 : bool BgpPeerClose::IsLlgrSupportedForFamilies() const {
     277             :     // Keep a sorted list of unsupported families.
     278             :     static vector<string> unsupported_families = list_of
     279          36 :         (Address::FamilyToString(Address::ERMVPN))
     280       40917 :         (Address::FamilyToString(Address::MVPN));
     281             : 
     282       40899 :     if (gr_families_ == llgr_families_)
     283        8364 :         return true;
     284             : 
     285             :     // Ignore families mis-match for certain families.
     286       32536 :     vector<string> differing_families;
     287       32536 :     std::set_symmetric_difference(gr_families_.begin(), gr_families_.end(),
     288             :                                   llgr_families_.begin(), llgr_families_.end(),
     289             :                                   back_inserter(differing_families));
     290             : 
     291             :     // Ignore if differing families are only those which are unsupported.
     292       32536 :     return includes(unsupported_families.begin(), unsupported_families.end(),
     293       32536 :                     differing_families.begin(), differing_families.end());
     294       32536 : }
     295             : 
     296             : // Check if we need to trigger Long Lived Graceful Restart. In addition to
     297             : // normal GR checks, we also need to check LLGR capability was negotiated
     298             : // and non-zero restart time was inferred.
     299      406447 : bool BgpPeerClose::IsCloseLongLivedGraceful() const {
     300      406447 :     if (!IsCloseGraceful())
     301      402082 :         return false;
     302        4363 :     return BgpPeerClose::IsCloseLongLivedGracefulInternal();
     303             : }
     304             : 
     305      176417 : bool BgpPeerClose::IsCloseLongLivedGracefulInternal() const {
     306      176417 :     if (llgr_params_.families.empty()) {
     307       97578 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     308             :             BGP_PEER_DIR_IN,
     309             :             "No LLGR support due to empty LLGR address families list");
     310       97578 :         return false;
     311             :     }
     312       78839 :     if (!llgr_params_.time) {
     313       37940 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     314             :             BGP_PEER_DIR_IN, "No LLGR support due to zero time value");
     315       37940 :         return false;
     316             :     }
     317             : 
     318       40899 :     if (!IsLlgrSupportedForFamilies()) {
     319       27880 :         BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     320             :             BGP_PEER_DIR_IN, "No LLGR support due to dissimilar "
     321             :             "GR address families and LLGR address families");
     322       27880 :         return false;
     323             :     }
     324             : 
     325             :     // Make sure that forwarding state is preserved for all families in
     326             :     // the restarting speaker.
     327       32291 :     for (auto family : llgr_params_.families) {
     328             :         // Ignore forwarding-state preservation check for certain families.
     329             :         Address::Family addr_family =
     330       23912 :             BgpAf::AfiSafiToFamily(family.afi, family.safi);
     331       23912 :         if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
     332        4619 :             continue;
     333             : 
     334       19293 :         if (!family.forwarding_state_preserved()) {
     335        4640 :             string family_str = Address::FamilyToString(addr_family);
     336        4640 :             BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
     337             :                 BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not "
     338             :                 "enabled because after restart, LLGR forwarding state is not "
     339             :                 "preserved for address family " << family_str);
     340        4640 :             return false;
     341        4640 :         }
     342             :     }
     343        8379 :     return true;
     344             : }
     345             : 
     346        5715 : void BgpPeerClose::RestartStateMachine() {
     347        5715 :     peer_->state_machine()->Initialize();
     348        5715 : }
     349             : 
     350             : // Close process for this peer is complete. Restart the state machine and
     351             : // attempt to bring up session with the neighbor
     352        6274 : void BgpPeerClose::CloseComplete() {
     353        6274 :     if (!peer_->IsDeleted() && !peer_->IsAdminDown())
     354        5779 :         RestartStateMachine();
     355        6274 : }
     356             : 
     357         698 : void BgpPeerClose::GetGracefulRestartFamilies(Families *families) const {
     358         698 :     families->clear();
     359        2260 :     for (const auto& family : gr_families_) {
     360        1562 :         families->insert(Address::FamilyFromString(family));
     361             :     }
     362         698 : }
     363             : 
     364         160 : void BgpPeerClose::GetLongLivedGracefulRestartFamilies(Families *families) const {
     365         160 :     families->clear();
     366         560 :     for (const auto& family : llgr_families_) {
     367         400 :         families->insert(Address::FamilyFromString(family));
     368             :     }
     369         160 : }
     370             : 
     371        9498 : void BgpPeerClose::AddGRCapabilities(
     372             :         BgpProto::OpenMessage::OptParam *opt_param) {
     373        9498 :     vector<Address::Family> gr_families;
     374        9504 :     vector<uint8_t> afi_flags;
     375             : 
     376             :     // Indicate to the Peer if we are in restarting phase.
     377        9502 :     bool restarted = peer_->IsServerStartingUp();
     378             : 
     379             :     // Indicate EOR support by default.
     380        9500 :     if (!peer_->server()->global_config()->gr_enable()) {
     381             :         BgpProto::OpenMessage::Capability *gr_cap =
     382        5339 :             BgpProto::OpenMessage::Capability::GR::Encode(0, restarted, false,
     383             :                                                           afi_flags,
     384        5342 :                                                           gr_families);
     385        5342 :         opt_param->capabilities.push_back(gr_cap);
     386        5345 :         return;
     387             :     }
     388             : 
     389       41571 :     for (auto family : peer_->supported_families()) {
     390       37413 :         if (!peer_->LookupFamily(family))
     391       21992 :             continue;
     392       15423 :         gr_families.push_back(family);
     393       15423 :         afi_flags.push_back(BgpProto::OpenMessage::Capability::GR::
     394             :                                 ForwardingStatePreservedFlag);
     395             :     }
     396             : 
     397        4156 :     uint16_t time = peer_->server()->GetGracefulRestartTime();
     398             :     BgpProto::OpenMessage::Capability *gr_cap =
     399        4157 :         BgpProto::OpenMessage::Capability::GR::Encode(time, restarted, true,
     400        4158 :                                                       afi_flags, gr_families);
     401        4158 :     opt_param->capabilities.push_back(gr_cap);
     402       14846 : }
     403             : 
     404             : // Process received GR and LLGR Capabilities. Return true if the values are sane
     405             : // to proceed with further processing. Return false if not to abort any ongoing
     406             : // GR and instead trigger non-graceful closure.
     407      791873 : bool BgpPeerClose::SetGRCapabilities(BgpPeerInfoData *peer_info) {
     408      791873 :     BgpProto::OpenMessage::Capability::GR::Decode(&gr_params_, capabilities());
     409      791872 :     BgpProto::OpenMessage::Capability::GR::GetFamilies(gr_params_,
     410             :                                                        &gr_families_);
     411             : 
     412      791870 :     BgpProto::OpenMessage::Capability::LLGR::Decode(&llgr_params_,
     413      791870 :                                                     capabilities());
     414      791870 :     BgpProto::OpenMessage::Capability::LLGR::GetFamilies(llgr_params_,
     415             :                                                          &llgr_families_);
     416             : 
     417      791871 :     if (peer_info) {
     418        5425 :         peer_info->set_graceful_restart_families(gr_families_);
     419        5425 :         peer_info->set_long_lived_graceful_restart_families(llgr_families_);
     420        5426 :         peer_info->set_graceful_restart_time(GetGracefulRestartTime());
     421       10852 :         peer_info->set_long_lived_graceful_restart_time(
     422        5426 :                 GetLongLivedGracefulRestartTime());
     423        5426 :         assert(!peer_info->get_name().empty());
     424        5426 :         BGP_UVE_SEND(BGPPeerInfo, *peer_info);
     425             :     }
     426             : 
     427             :     // If we are not in GR Timer waiting state, then there is no case to abort
     428             :     // GR when new session is coming up.
     429      791872 :     if (!IsInGRTimerWaitState())
     430        4798 :         return true;
     431             : 
     432             :     // If LLGR is no longer supported, terminate GR right away. This can happen
     433             :     // due to mis-match between gr and llgr afis. For now, we expect an
     434             :     // identical set.
     435      787073 :     if (IsInLlgrTimerWaitState())
     436      393349 :         return IsCloseLongLivedGraceful();
     437      393724 :     return IsCloseGraceful();
     438             : }
     439             : 
     440        9502 : void BgpPeerClose::AddLLGRCapabilities(
     441             :         BgpProto::OpenMessage::OptParam *opt_param) {
     442       13660 :     if (!peer_->server()->global_config()->gr_enable() ||
     443        4158 :             !peer_->server()->GetLongLivedGracefulRestartTime()) {
     444        5360 :         return;
     445             :     }
     446             : 
     447        4142 :     vector<Address::Family> llgr_families;
     448       41417 :     for (auto family : peer_->supported_families()) {
     449       37276 :         if (peer_->LookupFamily(family))
     450       15409 :             llgr_families.push_back(family);
     451             :     }
     452             : 
     453        4141 :     uint32_t time = peer_->server()->GetLongLivedGracefulRestartTime();
     454        4142 :     uint8_t afi_flags =
     455             :         BgpProto::OpenMessage::Capability::LLGR::ForwardingStatePreservedFlag;
     456             :     BgpProto::OpenMessage::Capability *llgr_cap =
     457        4142 :         BgpProto::OpenMessage::Capability::LLGR::Encode(time, afi_flags,
     458        4142 :                                                         llgr_families);
     459        4142 :     opt_param->capabilities.push_back(llgr_cap);
     460        4142 : }
     461             : 
     462          56 : void BgpPeerClose::FillNeighborInfo(BgpNeighborResp *bnr) const {
     463          56 :     bnr->set_graceful_restart_address_families(gr_families_);
     464          56 :     bnr->set_long_lived_graceful_restart_address_families(llgr_families_);
     465          56 :     bnr->set_graceful_restart_time(GetGracefulRestartTime());
     466         112 :     bnr->set_long_lived_graceful_restart_time(
     467          56 :             GetLongLivedGracefulRestartTime());
     468          56 : }

Generated by: LCOV version 1.14