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 206984 : BgpPeerClose::BgpPeerClose(BgpPeer *peer)
26 206984 : : peer_(peer), flap_count_(0) {
27 206984 : }
28 :
29 217142 : BgpPeerClose::~BgpPeerClose() {
30 217142 : }
31 :
32 174895 : PeerCloseManager *BgpPeerClose::GetManager() const {
33 174895 : return peer_->close_manager();
34 : }
35 :
36 15286 : void BgpPeerClose::CustomClose() {
37 15286 : return peer_->CustomClose();
38 : }
39 :
40 644 : void BgpPeerClose::GracefulRestartStale() {
41 644 : negotiated_families_ = peer_->negotiated_families();
42 644 : }
43 :
44 161 : void BgpPeerClose::LongLivedGracefulRestartStale() {
45 161 : }
46 :
47 565 : void BgpPeerClose::GracefulRestartSweep() {
48 565 : negotiated_families_.clear();
49 565 : }
50 :
51 1564 : bool BgpPeerClose::IsReady() const {
52 1564 : return peer_->IsReady();
53 : }
54 :
55 560668 : IPeer *BgpPeerClose::peer() const {
56 560668 : return peer_;
57 : }
58 :
59 : // Return the time to wait for, in seconds to exit GR_TIMER state.
60 6088 : int BgpPeerClose::GetGracefulRestartTime() const {
61 6088 : return gr_params_.time;
62 : }
63 :
64 : // Return the time to wait for, in seconds to exit LLGR_TIMER state.
65 5603 : int BgpPeerClose::GetLongLivedGracefulRestartTime() const {
66 5603 : return llgr_params_.time;
67 : }
68 :
69 0 : void BgpPeerClose::ReceiveEndOfRIB(Address::Family family) {
70 0 : peer_->ReceiveEndOfRIB(family, 0);
71 0 : }
72 :
73 110085 : const char *BgpPeerClose::GetTaskName() const {
74 110085 : return "bgp::Config";
75 : }
76 :
77 10362 : int BgpPeerClose::GetTaskInstance() const {
78 10362 : return 0;
79 : }
80 :
81 6148 : void BgpPeerClose::MembershipRequestCallbackComplete() {
82 6148 : CHECK_CONCURRENCY(GetTaskName());
83 6148 : }
84 :
85 14611 : bool BgpPeerClose::IsGRHelperModeEnabled() const {
86 14611 : return peer_->server()->IsGRHelperModeEnabled();
87 : }
88 :
89 6002 : const std::vector<std::string> &BgpPeerClose::PeerNegotiatedFamilies() const {
90 6002 : return peer_->negotiated_families();
91 : }
92 :
93 14781 : bool BgpPeerClose::IsPeerDeleted() const {
94 14781 : return peer_->IsDeleted();
95 : }
96 :
97 14777 : bool BgpPeerClose::IsPeerAdminDown() const {
98 14777 : return peer_->IsAdminDown();
99 : }
100 :
101 14616 : bool BgpPeerClose::IsServerDeleted() const {
102 14616 : return peer_->server()->IsDeleted();
103 : }
104 :
105 14613 : bool BgpPeerClose::IsServerAdminDown() const {
106 14613 : return peer_->server()->admin_down();
107 : }
108 :
109 7540 : bool BgpPeerClose::IsInGRTimerWaitState() const {
110 7540 : return GetManager()->IsInGRTimerWaitState();
111 : }
112 :
113 589 : bool BgpPeerClose::IsInLlgrTimerWaitState() const {
114 589 : return GetManager()->IsInLlgrTimerWaitState();
115 : }
116 :
117 6003 : const std::vector<std::string> &BgpPeerClose::negotiated_families() const {
118 6003 : return negotiated_families_;
119 : }
120 :
121 : const std::vector<BgpProto::OpenMessage::Capability *> &
122 10783 : BgpPeerClose::capabilities() const {
123 10783 : return peer_->capabilities();
124 : }
125 :
126 150615 : void BgpPeerClose::UpdateRouteStats(Address::Family family,
127 : const BgpPath *old_path,
128 : uint32_t path_flags) const {
129 150615 : GetManager()->UpdateRouteStats(family, old_path, path_flags);
130 150617 : }
131 :
132 16154 : 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 16154 : if (!graceful || flap_count_ != peer_->total_flap_count()) {
137 13214 : if (flap_count_ != peer_->total_flap_count()) {
138 5307 : flap_count_++;
139 5307 : assert(peer_->total_flap_count() == flap_count_);
140 : }
141 13213 : GetManager()->Close(graceful);
142 13219 : return;
143 : }
144 :
145 : // Ignore if close is already in progress.
146 2940 : if (GetManager()->IsCloseInProgress() && !IsInGRTimerWaitState())
147 33 : return;
148 :
149 2907 : if (peer_->IsDeleted()) {
150 0 : peer_->RetryDelete();
151 : } else {
152 2907 : CustomClose();
153 2907 : CloseComplete();
154 : }
155 : }
156 :
157 12379 : void BgpPeerClose::Delete() {
158 12379 : gr_params_.Initialize();
159 12379 : llgr_params_.Initialize();
160 12379 : gr_families_.clear();
161 12379 : llgr_families_.clear();
162 12379 : negotiated_families_.clear();
163 12379 : if (peer_->IsDeleted()) {
164 9571 : peer_->RetryDelete();
165 : } else {
166 2808 : CloseComplete();
167 : }
168 12379 : }
169 :
170 801044 : bool BgpPeerClose::IsGRReady() const {
171 : // Check if GR Helper mode is disabled.
172 801044 : if (!IsGRHelperModeEnabled()) {
173 10531 : 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 10531 : return false;
177 : }
178 :
179 : // Check if GR is supported by the peer.
180 790514 : 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 348148 : 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 338642 : if (!negotiated_families().empty() &&
199 157161 : 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 45653 : 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 26281 : for (auto family : gr_params_.families) {
218 : // Check if forwarding state was preserved during restart.
219 19304 : if (family.forwarding_state_preserved())
220 16664 : 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 6977 : return true;
236 : }
237 :
238 : // If the peer is deleted or administratively held down, do not attempt
239 : // graceful restart
240 801217 : bool BgpPeerClose::IsCloseGraceful() const {
241 801217 : if (IsPeerDeleted()) {
242 2 : 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 2 : return false;
246 : }
247 :
248 801213 : 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 801051 : 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 801047 : 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 801046 : if (!IsGRReady())
270 794070 : return false;
271 6977 : return true;
272 : }
273 :
274 : // LLGR families should be identical to GR families.
275 40841 : 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 40859 : (Address::FamilyToString(Address::MVPN));
280 :
281 40841 : if (gr_families_ == llgr_families_)
282 8305 : 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 406452 : bool BgpPeerClose::IsCloseLongLivedGraceful() const {
299 406452 : if (!IsCloseGraceful())
300 402142 : return false;
301 4305 : return BgpPeerClose::IsCloseLongLivedGracefulInternal();
302 : }
303 :
304 176359 : bool BgpPeerClose::IsCloseLongLivedGracefulInternal() const {
305 176359 : 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 78781 : 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 40841 : 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 32161 : for (auto family : llgr_params_.families) {
327 : // Ignore forwarding-state preservation check for certain families.
328 : Address::Family addr_family =
329 23840 : BgpAf::AfiSafiToFamily(family.afi, family.safi);
330 23840 : if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
331 4616 : continue;
332 :
333 19224 : 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 8321 : return true;
343 : }
344 :
345 5960 : void BgpPeerClose::RestartStateMachine() {
346 5960 : peer_->state_machine()->Initialize();
347 5960 : }
348 :
349 : // Close process for this peer is complete. Restart the state machine and
350 : // attempt to bring up session with the neighbor
351 6519 : void BgpPeerClose::CloseComplete() {
352 6519 : if (!peer_->IsDeleted() && !peer_->IsAdminDown())
353 6024 : RestartStateMachine();
354 6519 : }
355 :
356 644 : void BgpPeerClose::GetGracefulRestartFamilies(Families *families) const {
357 644 : families->clear();
358 2152 : for (const auto& family : gr_families_) {
359 1508 : families->insert(Address::FamilyFromString(family));
360 : }
361 644 : }
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 9685 : void BgpPeerClose::AddGRCapabilities(
371 : BgpProto::OpenMessage::OptParam *opt_param) {
372 9685 : vector<Address::Family> gr_families;
373 9689 : vector<uint8_t> afi_flags;
374 :
375 : // Indicate to the Peer if we are in restarting phase.
376 9688 : bool restarted = peer_->IsServerStartingUp();
377 :
378 : // Indicate EOR support by default.
379 9688 : if (!peer_->server()->global_config()->gr_enable()) {
380 : BgpProto::OpenMessage::Capability *gr_cap =
381 5250 : BgpProto::OpenMessage::Capability::GR::Encode(0, restarted, false,
382 : afi_flags,
383 5249 : gr_families);
384 5249 : opt_param->capabilities.push_back(gr_cap);
385 5250 : return;
386 : }
387 :
388 44359 : for (auto family : peer_->supported_families()) {
389 39923 : if (!peer_->LookupFamily(family))
390 22907 : continue;
391 17016 : gr_families.push_back(family);
392 17016 : afi_flags.push_back(BgpProto::OpenMessage::Capability::GR::
393 : ForwardingStatePreservedFlag);
394 : }
395 :
396 4436 : uint16_t time = peer_->server()->GetGracefulRestartTime();
397 : BgpProto::OpenMessage::Capability *gr_cap =
398 4436 : BgpProto::OpenMessage::Capability::GR::Encode(time, restarted, true,
399 4436 : afi_flags, gr_families);
400 4436 : opt_param->capabilities.push_back(gr_cap);
401 14936 : }
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 791839 : bool BgpPeerClose::SetGRCapabilities(BgpPeerInfoData *peer_info) {
407 791839 : BgpProto::OpenMessage::Capability::GR::Decode(&gr_params_, capabilities());
408 791839 : BgpProto::OpenMessage::Capability::GR::GetFamilies(gr_params_,
409 : &gr_families_);
410 :
411 791836 : BgpProto::OpenMessage::Capability::LLGR::Decode(&llgr_params_,
412 791836 : capabilities());
413 791837 : BgpProto::OpenMessage::Capability::LLGR::GetFamilies(llgr_params_,
414 : &llgr_families_);
415 :
416 791834 : if (peer_info) {
417 5388 : peer_info->set_graceful_restart_families(gr_families_);
418 5388 : peer_info->set_long_lived_graceful_restart_families(llgr_families_);
419 5388 : peer_info->set_graceful_restart_time(GetGracefulRestartTime());
420 10774 : peer_info->set_long_lived_graceful_restart_time(
421 5387 : GetLongLivedGracefulRestartTime());
422 5387 : assert(!peer_info->get_name().empty());
423 5387 : 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 791833 : if (!IsInGRTimerWaitState())
429 4807 : 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 787026 : if (IsInLlgrTimerWaitState())
435 393349 : return IsCloseLongLivedGraceful();
436 393677 : return IsCloseGraceful();
437 : }
438 :
439 9685 : void BgpPeerClose::AddLLGRCapabilities(
440 : BgpProto::OpenMessage::OptParam *opt_param) {
441 14121 : if (!peer_->server()->global_config()->gr_enable() ||
442 4436 : !peer_->server()->GetLongLivedGracefulRestartTime()) {
443 5267 : return;
444 : }
445 :
446 4419 : vector<Address::Family> llgr_families;
447 44190 : for (auto family : peer_->supported_families()) {
448 39771 : if (peer_->LookupFamily(family))
449 17000 : llgr_families.push_back(family);
450 : }
451 :
452 4419 : uint32_t time = peer_->server()->GetLongLivedGracefulRestartTime();
453 4419 : uint8_t afi_flags =
454 : BgpProto::OpenMessage::Capability::LLGR::ForwardingStatePreservedFlag;
455 : BgpProto::OpenMessage::Capability *llgr_cap =
456 4419 : BgpProto::OpenMessage::Capability::LLGR::Encode(time, afi_flags,
457 4419 : llgr_families);
458 4419 : opt_param->capabilities.push_back(llgr_cap);
459 4419 : }
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 : }
|