OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bgp_peer_close.cc
Go to the documentation of this file.
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 
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 
26  : peer_(peer), flap_count_(0) {
27 }
28 
30 }
31 
33  return peer_->close_manager();
34 }
35 
37  return peer_->CustomClose();
38 }
39 
42 }
43 
45 }
46 
48  negotiated_families_.clear();
49 }
50 
51 bool BgpPeerClose::IsReady() const {
52  return peer_->IsReady();
53 }
54 
56  return peer_;
57 }
58 
59 // Return the time to wait for, in seconds to exit GR_TIMER state.
61  return gr_params_.time;
62 }
63 
64 // Return the time to wait for, in seconds to exit LLGR_TIMER state.
66  return llgr_params_.time;
67 }
68 
70  peer_->ReceiveEndOfRIB(family, 0);
71 }
72 
73 const char *BgpPeerClose::GetTaskName() const {
74  return "bgp::Config";
75 }
76 
78  return 0;
79 }
80 
83 }
84 
86  return peer_->server()->IsGRHelperModeEnabled();
87 }
88 
89 const std::vector<std::string> &BgpPeerClose::PeerNegotiatedFamilies() const {
90  return peer_->negotiated_families();
91 }
92 
94  return peer_->IsDeleted();
95 }
96 
98  return peer_->IsAdminDown();
99 }
100 
102  return peer_->server()->IsDeleted();
103 }
104 
106  return peer_->server()->admin_down();
107 }
108 
110  return GetManager()->IsInGRTimerWaitState();
111 }
112 
115 }
116 
117 const std::vector<std::string> &BgpPeerClose::negotiated_families() const {
118  return negotiated_families_;
119 }
120 
121 const std::vector<BgpProto::OpenMessage::Capability *> &
123  return peer_->capabilities();
124 }
125 
127  const BgpPath *old_path,
128  uint32_t path_flags) const {
129  GetManager()->UpdateRouteStats(family, old_path, path_flags);
130 }
131 
132 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  if (!graceful || flap_count_ != peer_->total_flap_count()) {
137  if (flap_count_ != peer_->total_flap_count()) {
138  flap_count_++;
139  assert(peer_->total_flap_count() == flap_count_);
140  }
141  GetManager()->Close(graceful);
142  return;
143  }
144 
145  // Ignore if close is already in progress.
146  if (GetManager()->IsCloseInProgress() && !IsInGRTimerWaitState())
147  return;
148 
149  if (peer_->IsDeleted()) {
150  peer_->RetryDelete();
151  } else {
152  CustomClose();
153  CloseComplete();
154  }
155 }
156 
160  gr_families_.clear();
161  llgr_families_.clear();
162  negotiated_families_.clear();
163  if (peer_->IsDeleted()) {
164  peer_->RetryDelete();
165  } else {
166  CloseComplete();
167  }
168 }
169 
171  // Check if GR Helper mode is disabled.
172  if (!IsGRHelperModeEnabled()) {
173  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  return false;
177  }
178 
179  // Check if GR is supported by the peer.
180  if (gr_params_.families.empty()) {
181  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  return false;
185  }
186 
187  // LLGR should be in effect to enable GR Helper mode with 0 restart time.
189  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  return false;
194  }
195 
196  // Abort GR if currently negotiated families differ from already
197  // staled address families.
198  if (!negotiated_families().empty() &&
200  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  return false;
204  }
205 
206  // If GR is not supported for any of the negotiated address family,
207  // then consider GR as not supported
209  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  return false;
213  }
214 
215  // Make sure that forwarding state is preserved for all families in
216  // the restarting speaker. (Except for ERMVPN)
217  for (auto family : gr_params_.families) {
218  // Check if forwarding state was preserved during restart.
219  if (family.forwarding_state_preserved())
220  continue;
221 
222  // Ignore forwarding-state preservation check for certain families.
223  Address::Family addr_family =
224  BgpAf::AfiSafiToFamily(family.afi, family.safi);
225  if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
226  continue;
227 
228  string family_str = Address::FamilyToString(addr_family);
229  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  return false;
234  }
235  return true;
236 }
237 
238 // If the peer is deleted or administratively held down, do not attempt
239 // graceful restart
241  if (IsPeerDeleted()) {
242  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  return false;
246  }
247 
248  if (IsPeerAdminDown()) {
249  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  return false;
253  }
254 
255  if (IsServerDeleted()) {
256  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  return false;
260  }
261 
262  if (IsServerAdminDown()) {
263  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  return false;
267  }
268 
269  if (!IsGRReady())
270  return false;
271  return true;
272 }
273 
274 // LLGR families should be identical to GR families.
276  // Keep a sorted list of unsupported families.
277  static vector<string> unsupported_families = list_of
280 
282  return true;
283 
284  // Ignore families mis-match for certain families.
285  vector<string> differing_families;
286  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  return includes(unsupported_families.begin(), unsupported_families.end(),
292  differing_families.begin(), differing_families.end());
293 }
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.
299  if (!IsCloseGraceful())
300  return false;
302 }
303 
305  if (llgr_params_.families.empty()) {
306  BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
308  "No LLGR support due to empty LLGR address families list");
309  return false;
310  }
311  if (!llgr_params_.time) {
312  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  return false;
315  }
316 
318  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  return false;
322  }
323 
324  // Make sure that forwarding state is preserved for all families in
325  // the restarting speaker.
326  for (auto family : llgr_params_.families) {
327  // Ignore forwarding-state preservation check for certain families.
328  Address::Family addr_family =
329  BgpAf::AfiSafiToFamily(family.afi, family.safi);
330  if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
331  continue;
332 
333  if (!family.forwarding_state_preserved()) {
334  string family_str = Address::FamilyToString(addr_family);
335  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  return false;
340  }
341  }
342  return true;
343 }
344 
347 }
348 
349 // Close process for this peer is complete. Restart the state machine and
350 // attempt to bring up session with the neighbor
352  if (!peer_->IsDeleted() && !peer_->IsAdminDown())
354 }
355 
357  families->clear();
358  for (const auto& family : gr_families_) {
359  families->insert(Address::FamilyFromString(family));
360  }
361 }
362 
364  families->clear();
365  for (const auto& family : llgr_families_) {
366  families->insert(Address::FamilyFromString(family));
367  }
368 }
369 
371  BgpProto::OpenMessage::OptParam *opt_param) {
372  vector<Address::Family> gr_families;
373  vector<uint8_t> afi_flags;
374 
375  // Indicate to the Peer if we are in restarting phase.
376  bool restarted = peer_->IsServerStartingUp();
377 
378  // Indicate EOR support by default.
379  if (!peer_->server()->global_config()->gr_enable()) {
382  afi_flags,
383  gr_families);
384  opt_param->capabilities.push_back(gr_cap);
385  return;
386  }
387 
388  for (auto family : peer_->supported_families()) {
389  if (!peer_->LookupFamily(family))
390  continue;
391  gr_families.push_back(family);
392  afi_flags.push_back(BgpProto::OpenMessage::Capability::GR::
393  ForwardingStatePreservedFlag);
394  }
395 
396  uint16_t time = peer_->server()->GetGracefulRestartTime();
398  BgpProto::OpenMessage::Capability::GR::Encode(time, restarted, true,
399  afi_flags, gr_families);
400  opt_param->capabilities.push_back(gr_cap);
401 }
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 bool BgpPeerClose::SetGRCapabilities(BgpPeerInfoData *peer_info) {
409  &gr_families_);
410 
412  capabilities());
414  &llgr_families_);
415 
416  if (peer_info) {
417  peer_info->set_graceful_restart_families(gr_families_);
418  peer_info->set_long_lived_graceful_restart_families(llgr_families_);
419  peer_info->set_graceful_restart_time(GetGracefulRestartTime());
420  peer_info->set_long_lived_graceful_restart_time(
422  assert(!peer_info->get_name().empty());
423  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  if (!IsInGRTimerWaitState())
429  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.
435  return IsCloseLongLivedGraceful();
436  return IsCloseGraceful();
437 }
438 
440  BgpProto::OpenMessage::OptParam *opt_param) {
441  if (!peer_->server()->global_config()->gr_enable() ||
443  return;
444  }
445 
446  vector<Address::Family> llgr_families;
447  for (auto family : peer_->supported_families()) {
448  if (peer_->LookupFamily(family))
449  llgr_families.push_back(family);
450  }
451 
452  uint32_t time = peer_->server()->GetLongLivedGracefulRestartTime();
453  uint8_t afi_flags =
457  llgr_families);
458  opt_param->capabilities.push_back(llgr_cap);
459 }
460 
461 void BgpPeerClose::FillNeighborInfo(BgpNeighborResp *bnr) const {
462  bnr->set_graceful_restart_address_families(gr_families_);
463  bnr->set_long_lived_graceful_restart_address_families(llgr_families_);
464  bnr->set_graceful_restart_time(GetGracefulRestartTime());
465  bnr->set_long_lived_graceful_restart_time(
467 }
std::vector< std::string > llgr_families_
virtual void GetLongLivedGracefulRestartFamilies(Families *families) const
virtual void CustomClose()
virtual bool IsGRHelperModeEnabled() const
virtual int GetLongLivedGracefulRestartTime() const
static Capability * Encode(uint16_t gr_time, bool restarted, bool notification, const std::vector< uint8_t > &gr_afi_flags, const std::vector< Address::Family > &gr_families)
Definition: bgp_proto.cc:129
PeerCloseManager * close_manager()
Definition: bgp_peer.h:355
static void GetFamilies(const LLGR &llgr_params, std::vector< std::string > *families)
Definition: bgp_proto.cc:260
virtual bool IsReady() const
virtual void LongLivedGracefulRestartStale()
bool IsInLlgrTimerWaitState() const
virtual bool IsPeerAdminDown() const
Family
Definition: address.h:24
static Family FamilyFromString(const std::string &family)
Definition: address.cc:54
bool IsInGRTimerWaitState() const
static Address::Family AfiSafiToFamily(uint16_t afi, uint8_t safi)
Definition: bgp_af.cc:71
BgpGlobalSystemConfig * global_config()
Definition: bgp_server.h:290
virtual void CloseComplete()
bool LookupFamily(Address::Family family)
Definition: bgp_peer.h:197
bool IsLlgrSupportedForFamilies() const
uint32_t GetLongLivedGracefulRestartTime() const
Definition: bgp_server.cc:702
#define BGP_UVE_SEND(type, object)
Definition: bgp_log.h:46
virtual const std::vector< std::string > & negotiated_families() const
virtual int GetGracefulRestartTime() const
bool IsAdminDown() const
Definition: bgp_peer.h:221
uint64_t total_flap_count() const
Definition: bgp_peer.h:251
virtual int GetTaskInstance() const
void RetryDelete()
Definition: bgp_peer.cc:2377
uint64_t flap_count_
static bool Decode(GR *gr_params, const std::vector< Capability * > &capabilities)
Definition: bgp_proto.cc:175
bool IsGRHelperModeEnabled() const
Definition: bgp_server.cc:734
Definition: ipeer.h:186
std::vector< std::string > gr_families_
void FillNeighborInfo(BgpNeighborResp *bnr) const
virtual BgpServer * server()
Definition: bgp_peer.h:157
bool IsCloseLongLivedGracefulInternal() const
StateMachine * state_machine()
Definition: bgp_peer.h:326
BgpProto::OpenMessage::Capability::GR gr_params_
virtual PeerCloseManager * GetManager() const
virtual bool IsCloseLongLivedGraceful() const
virtual bool IsPeerDeleted() const
bool admin_down() const
Definition: bgp_server.h:202
virtual void Delete()
virtual void ReceiveEndOfRIB(Address::Family family)
virtual void GracefulRestartStale()
const std::vector< std::string > & negotiated_families() const
Definition: bgp_peer.h:342
virtual ~BgpPeerClose()
std::vector< Family > families
Definition: bgp_proto.h:170
static void GetFamilies(const GR &gr_params, std::vector< std::string > *families)
Definition: bgp_proto.cc:156
virtual bool IsInLlgrTimerWaitState() const
virtual void UpdateRouteStats(Address::Family family, const BgpPath *old_path, uint32_t path_flags) const
bool SetGRCapabilities(BgpPeerInfoData *peer_info)
#define CHECK_CONCURRENCY(...)
virtual const std::vector< std::string > & PeerNegotiatedFamilies() const
static Capability * Encode(uint32_t llgr_time, uint8_t llgr_afi_flags, const std::vector< Address::Family > &llgr_families)
Definition: bgp_proto.cc:207
virtual bool IsServerAdminDown() const
void UpdateRouteStats(Address::Family family, const BgpPath *old_path, uint32_t path_flags) const
BgpPeer * peer_
virtual void Close(bool graceful)
virtual bool IsServerDeleted() const
static std::string FamilyToString(Family fmly)
Definition: address.cc:63
virtual bool IsCloseGraceful() const
const std::vector< BgpProto::OpenMessage::Capability * > & capabilities() const
Definition: bgp_peer.h:347
void AddGRCapabilities(BgpProto::OpenMessage::OptParam *opt_param)
BgpProto::OpenMessage::Capability::LLGR llgr_params_
virtual IPeer * peer() const
static bool Decode(LLGR *llgr_params, const std::vector< Capability * > &capabilities)
Definition: bgp_proto.cc:227
void Close(bool graceful)
virtual bool IsServerStartingUp() const
Definition: bgp_peer.cc:319
virtual const char * GetTaskName() const
virtual void MembershipRequestCallbackComplete()
std::vector< Capability * > capabilities
Definition: bgp_proto.h:217
virtual bool IsInGRTimerWaitState() const
virtual bool IsReady() const
Definition: bgp_peer.cc:1207
static const std::vector< Address::Family > & supported_families()
Definition: bgp_peer.h:351
void ReceiveEndOfRIB(Address::Family family, size_t msgsize)
Definition: bgp_peer.cc:270
virtual void GetGracefulRestartFamilies(Families *families) const
virtual void RestartStateMachine()
virtual void GracefulRestartSweep()
std::set< Address::Family > Families
uint16_t GetGracefulRestartTime() const
Definition: bgp_server.cc:696
BgpPeerClose(BgpPeer *peer)
bool IsDeleted() const
Definition: bgp_server.cc:415
virtual const std::vector< BgpProto::OpenMessage::Capability * > & capabilities() const
bool IsDeleted() const
Definition: bgp_peer.cc:1314
void CustomClose()
Definition: bgp_peer.cc:1251
bool gr_enable() const
Definition: bgp_config.h:635
std::vector< std::string > negotiated_families_
#define BGP_PEER_DIR_IN
Definition: bgp_log.h:139
#define BGP_LOG_FLAG_ALL
Definition: bgp_log.h:44
void AddLLGRCapabilities(BgpProto::OpenMessage::OptParam *opt_param)
#define BGP_LOG_PEER(type, peer, level, flags, dir, arg)
Definition: bgp_log.h:159
virtual bool IsGRReady() const