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 173799 : PeerCloseManager *BgpPeerClose::GetManager() const {
33 173799 : return peer_->close_manager();
34 : }
35 :
36 14780 : void BgpPeerClose::CustomClose() {
37 14780 : return peer_->CustomClose();
38 : }
39 :
40 596 : void BgpPeerClose::GracefulRestartStale() {
41 596 : negotiated_families_ = peer_->negotiated_families();
42 596 : }
43 :
44 160 : void BgpPeerClose::LongLivedGracefulRestartStale() {
45 160 : }
46 :
47 517 : void BgpPeerClose::GracefulRestartSweep() {
48 517 : negotiated_families_.clear();
49 517 : }
50 :
51 1467 : bool BgpPeerClose::IsReady() const {
52 1467 : return peer_->IsReady();
53 : }
54 :
55 555223 : IPeer *BgpPeerClose::peer() const {
56 555223 : return peer_;
57 : }
58 :
59 : // Return the time to wait for, in seconds to exit GR_TIMER state.
60 5975 : int BgpPeerClose::GetGracefulRestartTime() const {
61 5975 : return gr_params_.time;
62 : }
63 :
64 : // Return the time to wait for, in seconds to exit LLGR_TIMER state.
65 5539 : int BgpPeerClose::GetLongLivedGracefulRestartTime() const {
66 5539 : return llgr_params_.time;
67 : }
68 :
69 3 : void BgpPeerClose::ReceiveEndOfRIB(Address::Family family) {
70 3 : peer_->ReceiveEndOfRIB(family, 0);
71 3 : }
72 :
73 109094 : const char *BgpPeerClose::GetTaskName() const {
74 109094 : return "bgp::Config";
75 : }
76 :
77 10358 : int BgpPeerClose::GetTaskInstance() const {
78 10358 : return 0;
79 : }
80 :
81 6042 : void BgpPeerClose::MembershipRequestCallbackComplete() {
82 6042 : CHECK_CONCURRENCY(GetTaskName());
83 6042 : }
84 :
85 14389 : bool BgpPeerClose::IsGRHelperModeEnabled() const {
86 14389 : return peer_->server()->IsGRHelperModeEnabled();
87 : }
88 :
89 5743 : const std::vector<std::string> &BgpPeerClose::PeerNegotiatedFamilies() const {
90 5743 : return peer_->negotiated_families();
91 : }
92 :
93 14557 : bool BgpPeerClose::IsPeerDeleted() const {
94 14557 : return peer_->IsDeleted();
95 : }
96 :
97 14559 : bool BgpPeerClose::IsPeerAdminDown() const {
98 14559 : return peer_->IsAdminDown();
99 : }
100 :
101 14393 : bool BgpPeerClose::IsServerDeleted() const {
102 14393 : return peer_->server()->IsDeleted();
103 : }
104 :
105 14393 : bool BgpPeerClose::IsServerAdminDown() const {
106 14393 : return peer_->server()->admin_down();
107 : }
108 :
109 7052 : bool BgpPeerClose::IsInGRTimerWaitState() const {
110 7052 : return GetManager()->IsInGRTimerWaitState();
111 : }
112 :
113 536 : bool BgpPeerClose::IsInLlgrTimerWaitState() const {
114 536 : return GetManager()->IsInLlgrTimerWaitState();
115 : }
116 :
117 5743 : const std::vector<std::string> &BgpPeerClose::negotiated_families() const {
118 5743 : return negotiated_families_;
119 : }
120 :
121 : const std::vector<BgpProto::OpenMessage::Capability *> &
122 10648 : BgpPeerClose::capabilities() const {
123 10648 : return peer_->capabilities();
124 : }
125 :
126 150587 : void BgpPeerClose::UpdateRouteStats(Address::Family family,
127 : const BgpPath *old_path,
128 : uint32_t path_flags) const {
129 150587 : GetManager()->UpdateRouteStats(family, old_path, path_flags);
130 150599 : }
131 :
132 15609 : 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 15609 : if (!graceful || flap_count_ != peer_->total_flap_count()) {
137 13153 : if (flap_count_ != peer_->total_flap_count()) {
138 5249 : flap_count_++;
139 5249 : assert(peer_->total_flap_count() == flap_count_);
140 : }
141 13152 : GetManager()->Close(graceful);
142 13156 : return;
143 : }
144 :
145 : // Ignore if close is already in progress.
146 2456 : if (GetManager()->IsCloseInProgress() && !IsInGRTimerWaitState())
147 39 : return;
148 :
149 2419 : if (peer_->IsDeleted()) {
150 0 : peer_->RetryDelete();
151 : } else {
152 2419 : CustomClose();
153 2419 : CloseComplete();
154 : }
155 : }
156 :
157 12361 : void BgpPeerClose::Delete() {
158 12361 : gr_params_.Initialize();
159 12361 : llgr_params_.Initialize();
160 12361 : gr_families_.clear();
161 12361 : llgr_families_.clear();
162 12361 : negotiated_families_.clear();
163 12361 : if (peer_->IsDeleted()) {
164 9567 : peer_->RetryDelete();
165 : } else {
166 2794 : CloseComplete();
167 : }
168 12361 : }
169 :
170 800823 : bool BgpPeerClose::IsGRReady() const {
171 : // Check if GR Helper mode is disabled.
172 800823 : if (!IsGRHelperModeEnabled()) {
173 10471 : 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 10472 : return false;
177 : }
178 :
179 : // Check if GR is supported by the peer.
180 790351 : 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 347983 : 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 338383 : if (!negotiated_families().empty() &&
199 157066 : 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 45489 : 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 25980 : for (auto family : gr_params_.families) {
218 : // Check if forwarding state was preserved during restart.
219 19168 : if (family.forwarding_state_preserved())
220 16528 : 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 6812 : return true;
236 : }
237 :
238 : // If the peer is deleted or administratively held down, do not attempt
239 : // graceful restart
240 800993 : bool BgpPeerClose::IsCloseGraceful() const {
241 800993 : 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 800994 : if (IsPeerAdminDown()) {
249 166 : 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 166 : return false;
253 : }
254 :
255 800828 : 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 800826 : 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 800826 : if (!IsGRReady())
270 794010 : return false;
271 6812 : return true;
272 : }
273 :
274 : // LLGR families should be identical to GR families.
275 40801 : 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 40819 : (Address::FamilyToString(Address::MVPN));
280 :
281 40801 : if (gr_families_ == llgr_families_)
282 8265 : 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 406355 : bool BgpPeerClose::IsCloseLongLivedGraceful() const {
299 406355 : if (!IsCloseGraceful())
300 402089 : return false;
301 4265 : return BgpPeerClose::IsCloseLongLivedGracefulInternal();
302 : }
303 :
304 176319 : bool BgpPeerClose::IsCloseLongLivedGracefulInternal() const {
305 176319 : 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 78741 : 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 40801 : 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 32110 : for (auto family : llgr_params_.families) {
327 : // Ignore forwarding-state preservation check for certain families.
328 : Address::Family addr_family =
329 23829 : BgpAf::AfiSafiToFamily(family.afi, family.safi);
330 23830 : if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
331 4623 : continue;
332 :
333 19207 : 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 8282 : return true;
343 : }
344 :
345 5409 : void BgpPeerClose::RestartStateMachine() {
346 5409 : peer_->state_machine()->Initialize();
347 5409 : }
348 :
349 : // Close process for this peer is complete. Restart the state machine and
350 : // attempt to bring up session with the neighbor
351 5969 : void BgpPeerClose::CloseComplete() {
352 5969 : if (!peer_->IsDeleted() && !peer_->IsAdminDown())
353 5473 : RestartStateMachine();
354 5969 : }
355 :
356 596 : void BgpPeerClose::GetGracefulRestartFamilies(Families *families) const {
357 596 : families->clear();
358 2056 : for (const auto& family : gr_families_) {
359 1460 : families->insert(Address::FamilyFromString(family));
360 : }
361 596 : }
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 9122 : void BgpPeerClose::AddGRCapabilities(
371 : BgpProto::OpenMessage::OptParam *opt_param) {
372 9122 : vector<Address::Family> gr_families;
373 9124 : vector<uint8_t> afi_flags;
374 :
375 : // Indicate to the Peer if we are in restarting phase.
376 9124 : bool restarted = peer_->IsServerStartingUp();
377 :
378 : // Indicate EOR support by default.
379 9124 : if (!peer_->server()->global_config()->gr_enable()) {
380 : BgpProto::OpenMessage::Capability *gr_cap =
381 5210 : BgpProto::OpenMessage::Capability::GR::Encode(0, restarted, false,
382 : afi_flags,
383 5211 : gr_families);
384 5211 : opt_param->capabilities.push_back(gr_cap);
385 5209 : return;
386 : }
387 :
388 39115 : for (auto family : peer_->supported_families()) {
389 35201 : if (!peer_->LookupFamily(family))
390 20350 : continue;
391 14854 : gr_families.push_back(family);
392 14855 : afi_flags.push_back(BgpProto::OpenMessage::Capability::GR::
393 : ForwardingStatePreservedFlag);
394 : }
395 :
396 3911 : uint16_t time = peer_->server()->GetGracefulRestartTime();
397 : BgpProto::OpenMessage::Capability *gr_cap =
398 3912 : BgpProto::OpenMessage::Capability::GR::Encode(time, restarted, true,
399 3912 : afi_flags, gr_families);
400 3912 : opt_param->capabilities.push_back(gr_cap);
401 14329 : }
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 791771 : bool BgpPeerClose::SetGRCapabilities(BgpPeerInfoData *peer_info) {
407 791771 : BgpProto::OpenMessage::Capability::GR::Decode(&gr_params_, capabilities());
408 791770 : BgpProto::OpenMessage::Capability::GR::GetFamilies(gr_params_,
409 : &gr_families_);
410 :
411 791766 : BgpProto::OpenMessage::Capability::LLGR::Decode(&llgr_params_,
412 791766 : capabilities());
413 791767 : BgpProto::OpenMessage::Capability::LLGR::GetFamilies(llgr_params_,
414 : &llgr_families_);
415 :
416 791767 : if (peer_info) {
417 5321 : peer_info->set_graceful_restart_families(gr_families_);
418 5321 : peer_info->set_long_lived_graceful_restart_families(llgr_families_);
419 5323 : peer_info->set_graceful_restart_time(GetGracefulRestartTime());
420 10646 : peer_info->set_long_lived_graceful_restart_time(
421 5323 : GetLongLivedGracefulRestartTime());
422 5323 : assert(!peer_info->get_name().empty());
423 5323 : 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 791769 : if (!IsInGRTimerWaitState())
429 4798 : 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 786973 : if (IsInLlgrTimerWaitState())
435 393349 : return IsCloseLongLivedGraceful();
436 393624 : return IsCloseGraceful();
437 : }
438 :
439 9118 : void BgpPeerClose::AddLLGRCapabilities(
440 : BgpProto::OpenMessage::OptParam *opt_param) {
441 13030 : if (!peer_->server()->global_config()->gr_enable() ||
442 3912 : !peer_->server()->GetLongLivedGracefulRestartTime()) {
443 5223 : return;
444 : }
445 :
446 3895 : vector<Address::Family> llgr_families;
447 38947 : for (auto family : peer_->supported_families()) {
448 35052 : if (peer_->LookupFamily(family))
449 14837 : llgr_families.push_back(family);
450 : }
451 :
452 3892 : uint32_t time = peer_->server()->GetLongLivedGracefulRestartTime();
453 3894 : uint8_t afi_flags =
454 : BgpProto::OpenMessage::Capability::LLGR::ForwardingStatePreservedFlag;
455 : BgpProto::OpenMessage::Capability *llgr_cap =
456 3894 : BgpProto::OpenMessage::Capability::LLGR::Encode(time, afi_flags,
457 3896 : llgr_families);
458 3896 : opt_param->capabilities.push_back(llgr_cap);
459 3896 : }
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 : }
|