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 : }
|