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 206980 : BgpPeerClose::BgpPeerClose(BgpPeer *peer)
26 206980 : : peer_(peer), flap_count_(0) {
27 206980 : }
28 :
29 217134 : BgpPeerClose::~BgpPeerClose() {
30 217134 : }
31 :
32 178593 : PeerCloseManager *BgpPeerClose::GetManager() const {
33 178593 : return peer_->close_manager();
34 : }
35 :
36 16014 : void BgpPeerClose::CustomClose() {
37 16014 : return peer_->CustomClose();
38 : }
39 :
40 918 : void BgpPeerClose::GracefulRestartStale() {
41 918 : negotiated_families_ = peer_->negotiated_families();
42 918 : }
43 :
44 163 : void BgpPeerClose::LongLivedGracefulRestartStale() {
45 163 : }
46 :
47 836 : void BgpPeerClose::GracefulRestartSweep() {
48 836 : negotiated_families_.clear();
49 836 : }
50 :
51 2110 : bool BgpPeerClose::IsReady() const {
52 2110 : return peer_->IsReady();
53 : }
54 :
55 588543 : IPeer *BgpPeerClose::peer() const {
56 588543 : return peer_;
57 : }
58 :
59 : // Return the time to wait for, in seconds to exit GR_TIMER state.
60 6649 : int BgpPeerClose::GetGracefulRestartTime() const {
61 6649 : return gr_params_.time;
62 : }
63 :
64 : // Return the time to wait for, in seconds to exit LLGR_TIMER state.
65 5893 : int BgpPeerClose::GetLongLivedGracefulRestartTime() const {
66 5893 : return llgr_params_.time;
67 : }
68 :
69 0 : void BgpPeerClose::ReceiveEndOfRIB(Address::Family family) {
70 0 : peer_->ReceiveEndOfRIB(family, 0);
71 0 : }
72 :
73 114445 : const char *BgpPeerClose::GetTaskName() const {
74 114445 : return "bgp::Config";
75 : }
76 :
77 10358 : int BgpPeerClose::GetTaskInstance() const {
78 10358 : return 0;
79 : }
80 :
81 6699 : void BgpPeerClose::MembershipRequestCallbackComplete() {
82 6699 : CHECK_CONCURRENCY(GetTaskName());
83 6699 : }
84 :
85 15595 : bool BgpPeerClose::IsGRHelperModeEnabled() const {
86 15595 : return peer_->server()->IsGRHelperModeEnabled();
87 : }
88 :
89 7541 : const std::vector<std::string> &BgpPeerClose::PeerNegotiatedFamilies() const {
90 7541 : return peer_->negotiated_families();
91 : }
92 :
93 15761 : bool BgpPeerClose::IsPeerDeleted() const {
94 15761 : return peer_->IsDeleted();
95 : }
96 :
97 15761 : bool BgpPeerClose::IsPeerAdminDown() const {
98 15761 : return peer_->IsAdminDown();
99 : }
100 :
101 15599 : bool BgpPeerClose::IsServerDeleted() const {
102 15599 : return peer_->server()->IsDeleted();
103 : }
104 :
105 15598 : bool BgpPeerClose::IsServerAdminDown() const {
106 15598 : return peer_->server()->admin_down();
107 : }
108 :
109 8454 : bool BgpPeerClose::IsInGRTimerWaitState() const {
110 8454 : return GetManager()->IsInGRTimerWaitState();
111 : }
112 :
113 868 : bool BgpPeerClose::IsInLlgrTimerWaitState() const {
114 868 : return GetManager()->IsInLlgrTimerWaitState();
115 : }
116 :
117 7542 : const std::vector<std::string> &BgpPeerClose::negotiated_families() const {
118 7542 : return negotiated_families_;
119 : }
120 :
121 : const std::vector<BgpProto::OpenMessage::Capability *> &
122 11350 : BgpPeerClose::capabilities() const {
123 11350 : return peer_->capabilities();
124 : }
125 :
126 152093 : void BgpPeerClose::UpdateRouteStats(Address::Family family,
127 : const BgpPath *old_path,
128 : uint32_t path_flags) const {
129 152093 : GetManager()->UpdateRouteStats(family, old_path, path_flags);
130 152087 : }
131 :
132 17180 : 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 17180 : if (!graceful || flap_count_ != peer_->total_flap_count()) {
137 13536 : if (flap_count_ != peer_->total_flap_count()) {
138 5584 : flap_count_++;
139 5584 : assert(peer_->total_flap_count() == flap_count_);
140 : }
141 13534 : GetManager()->Close(graceful);
142 13550 : return;
143 : }
144 :
145 : // Ignore if close is already in progress.
146 3644 : if (GetManager()->IsCloseInProgress() && !IsInGRTimerWaitState())
147 39 : return;
148 :
149 3601 : if (peer_->IsDeleted()) {
150 0 : peer_->RetryDelete();
151 : } else {
152 3601 : CustomClose();
153 3601 : CloseComplete();
154 : }
155 : }
156 :
157 12413 : void BgpPeerClose::Delete() {
158 12413 : gr_params_.Initialize();
159 12413 : llgr_params_.Initialize();
160 12413 : gr_families_.clear();
161 12413 : llgr_families_.clear();
162 12413 : negotiated_families_.clear();
163 12413 : if (peer_->IsDeleted()) {
164 9567 : peer_->RetryDelete();
165 : } else {
166 2846 : CloseComplete();
167 : }
168 12413 : }
169 :
170 802028 : bool BgpPeerClose::IsGRReady() const {
171 : // Check if GR Helper mode is disabled.
172 802028 : if (!IsGRHelperModeEnabled()) {
173 10536 : 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 10537 : return false;
177 : }
178 :
179 : // Check if GR is supported by the peer.
180 791490 : 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 349123 : 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 340182 : if (!negotiated_families().empty() &&
199 157725 : 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 46628 : 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 28249 : for (auto family : gr_params_.families) {
218 : // Check if forwarding state was preserved during restart.
219 20297 : if (family.forwarding_state_preserved())
220 17657 : 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 7952 : return true;
236 : }
237 :
238 : // If the peer is deleted or administratively held down, do not attempt
239 : // graceful restart
240 802197 : bool BgpPeerClose::IsCloseGraceful() const {
241 802197 : 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 802197 : 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 802034 : 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 802032 : 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 802029 : if (!IsGRReady())
270 794074 : return false;
271 7952 : return true;
272 : }
273 :
274 : // LLGR families should be identical to GR families.
275 41124 : 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 41142 : (Address::FamilyToString(Address::MVPN));
280 :
281 41124 : if (gr_families_ == llgr_families_)
282 8589 : 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 406744 : bool BgpPeerClose::IsCloseLongLivedGraceful() const {
299 406744 : if (!IsCloseGraceful())
300 402150 : return false;
301 4588 : return BgpPeerClose::IsCloseLongLivedGracefulInternal();
302 : }
303 :
304 176642 : bool BgpPeerClose::IsCloseLongLivedGracefulInternal() const {
305 176642 : 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 79064 : 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 41124 : 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 32750 : for (auto family : llgr_params_.families) {
327 : // Ignore forwarding-state preservation check for certain families.
328 : Address::Family addr_family =
329 24145 : BgpAf::AfiSafiToFamily(family.afi, family.safi);
330 24145 : if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
331 4620 : continue;
332 :
333 19525 : 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 8605 : return true;
343 : }
344 :
345 6964 : void BgpPeerClose::RestartStateMachine() {
346 6964 : peer_->state_machine()->Initialize();
347 6964 : }
348 :
349 : // Close process for this peer is complete. Restart the state machine and
350 : // attempt to bring up session with the neighbor
351 7527 : void BgpPeerClose::CloseComplete() {
352 7527 : if (!peer_->IsDeleted() && !peer_->IsAdminDown())
353 7028 : RestartStateMachine();
354 7527 : }
355 :
356 918 : void BgpPeerClose::GetGracefulRestartFamilies(Families *families) const {
357 918 : families->clear();
358 2700 : for (const auto& family : gr_families_) {
359 1782 : families->insert(Address::FamilyFromString(family));
360 : }
361 918 : }
362 :
363 162 : void BgpPeerClose::GetLongLivedGracefulRestartFamilies(Families *families) const {
364 162 : families->clear();
365 566 : for (const auto& family : llgr_families_) {
366 404 : families->insert(Address::FamilyFromString(family));
367 : }
368 162 : }
369 :
370 10736 : void BgpPeerClose::AddGRCapabilities(
371 : BgpProto::OpenMessage::OptParam *opt_param) {
372 10736 : vector<Address::Family> gr_families;
373 10737 : vector<uint8_t> afi_flags;
374 :
375 : // Indicate to the Peer if we are in restarting phase.
376 10737 : bool restarted = peer_->IsServerStartingUp();
377 :
378 : // Indicate EOR support by default.
379 10737 : if (!peer_->server()->global_config()->gr_enable()) {
380 : BgpProto::OpenMessage::Capability *gr_cap =
381 5437 : BgpProto::OpenMessage::Capability::GR::Encode(0, restarted, false,
382 : afi_flags,
383 5432 : gr_families);
384 5432 : opt_param->capabilities.push_back(gr_cap);
385 5436 : return;
386 : }
387 :
388 52997 : for (auto family : peer_->supported_families()) {
389 47698 : if (!peer_->LookupFamily(family))
390 28053 : continue;
391 19645 : gr_families.push_back(family);
392 19645 : afi_flags.push_back(BgpProto::OpenMessage::Capability::GR::
393 : ForwardingStatePreservedFlag);
394 : }
395 :
396 5299 : uint16_t time = peer_->server()->GetGracefulRestartTime();
397 : BgpProto::OpenMessage::Capability *gr_cap =
398 5300 : BgpProto::OpenMessage::Capability::GR::Encode(time, restarted, true,
399 5300 : afi_flags, gr_families);
400 5300 : opt_param->capabilities.push_back(gr_cap);
401 16171 : }
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 792121 : bool BgpPeerClose::SetGRCapabilities(BgpPeerInfoData *peer_info) {
407 792121 : BgpProto::OpenMessage::Capability::GR::Decode(&gr_params_, capabilities());
408 792122 : BgpProto::OpenMessage::Capability::GR::GetFamilies(gr_params_,
409 : &gr_families_);
410 :
411 792121 : BgpProto::OpenMessage::Capability::LLGR::Decode(&llgr_params_,
412 792121 : capabilities());
413 792121 : BgpProto::OpenMessage::Capability::LLGR::GetFamilies(llgr_params_,
414 : &llgr_families_);
415 :
416 792119 : if (peer_info) {
417 5673 : peer_info->set_graceful_restart_families(gr_families_);
418 5674 : peer_info->set_long_lived_graceful_restart_families(llgr_families_);
419 5676 : peer_info->set_graceful_restart_time(GetGracefulRestartTime());
420 11351 : peer_info->set_long_lived_graceful_restart_time(
421 5675 : GetLongLivedGracefulRestartTime());
422 5676 : assert(!peer_info->get_name().empty());
423 5676 : 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 792120 : if (!IsInGRTimerWaitState())
429 4816 : 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 787305 : if (IsInLlgrTimerWaitState())
435 393351 : return IsCloseLongLivedGraceful();
436 393954 : return IsCloseGraceful();
437 : }
438 :
439 10735 : void BgpPeerClose::AddLLGRCapabilities(
440 : BgpProto::OpenMessage::OptParam *opt_param) {
441 16035 : if (!peer_->server()->global_config()->gr_enable() ||
442 5300 : !peer_->server()->GetLongLivedGracefulRestartTime()) {
443 5452 : return;
444 : }
445 :
446 5284 : vector<Address::Family> llgr_families;
447 52840 : for (auto family : peer_->supported_families()) {
448 47556 : if (peer_->LookupFamily(family))
449 19631 : llgr_families.push_back(family);
450 : }
451 :
452 5284 : uint32_t time = peer_->server()->GetLongLivedGracefulRestartTime();
453 5284 : uint8_t afi_flags =
454 : BgpProto::OpenMessage::Capability::LLGR::ForwardingStatePreservedFlag;
455 : BgpProto::OpenMessage::Capability *llgr_cap =
456 5284 : BgpProto::OpenMessage::Capability::LLGR::Encode(time, afi_flags,
457 5284 : llgr_families);
458 5284 : opt_param->capabilities.push_back(llgr_cap);
459 5284 : }
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 : }
|