Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <boost/foreach.hpp>
7 : #include <boost/assign/list_of.hpp>
8 : #include <boost/scoped_ptr.hpp>
9 :
10 : #include "base/task_annotations.h"
11 : #include "net/bgp_af.h"
12 : #include "bgp/bgp_factory.h"
13 : #include "bgp/bgp_path.h"
14 : #include "bgp/bgp_log.h"
15 : #include "bgp/bgp_peer.h"
16 : #include "bgp/bgp_peer_close.h"
17 : #include "bgp/bgp_peer_types.h"
18 : #include "bgp/peer_close_manager.h"
19 :
20 : using boost::assign::list_of;
21 : using std::back_inserter;
22 : using std::includes;
23 : using std::string;
24 : using std::vector;
25 :
26 206980 : BgpPeerClose::BgpPeerClose(BgpPeer *peer)
27 206980 : : peer_(peer), flap_count_(0) {
28 206980 : }
29 :
30 217134 : BgpPeerClose::~BgpPeerClose() {
31 217134 : }
32 :
33 174746 : PeerCloseManager *BgpPeerClose::GetManager() const {
34 174746 : return peer_->close_manager();
35 : }
36 :
37 14983 : void BgpPeerClose::CustomClose() {
38 14983 : return peer_->CustomClose();
39 : }
40 :
41 698 : void BgpPeerClose::GracefulRestartStale() {
42 698 : negotiated_families_ = peer_->negotiated_families();
43 698 : }
44 :
45 160 : void BgpPeerClose::LongLivedGracefulRestartStale() {
46 160 : }
47 :
48 618 : void BgpPeerClose::GracefulRestartSweep() {
49 618 : negotiated_families_.clear();
50 618 : }
51 :
52 1668 : bool BgpPeerClose::IsReady() const {
53 1668 : return peer_->IsReady();
54 : }
55 :
56 565586 : IPeer *BgpPeerClose::peer() const {
57 565586 : return peer_;
58 : }
59 :
60 : // Return the time to wait for, in seconds to exit GR_TIMER state.
61 6180 : int BgpPeerClose::GetGracefulRestartTime() const {
62 6180 : return gr_params_.time;
63 : }
64 :
65 : // Return the time to wait for, in seconds to exit LLGR_TIMER state.
66 5642 : int BgpPeerClose::GetLongLivedGracefulRestartTime() const {
67 5642 : return llgr_params_.time;
68 : }
69 :
70 0 : void BgpPeerClose::ReceiveEndOfRIB(Address::Family family) {
71 0 : peer_->ReceiveEndOfRIB(family, 0);
72 0 : }
73 :
74 110789 : const char *BgpPeerClose::GetTaskName() const {
75 110789 : return "bgp::Config";
76 : }
77 :
78 10358 : int BgpPeerClose::GetTaskInstance() const {
79 10358 : return 0;
80 : }
81 :
82 6245 : void BgpPeerClose::MembershipRequestCallbackComplete() {
83 6245 : CHECK_CONCURRENCY(GetTaskName());
84 6245 : }
85 :
86 14744 : bool BgpPeerClose::IsGRHelperModeEnabled() const {
87 14744 : return peer_->server()->IsGRHelperModeEnabled();
88 : }
89 :
90 6295 : const std::vector<std::string> &BgpPeerClose::PeerNegotiatedFamilies() const {
91 6295 : return peer_->negotiated_families();
92 : }
93 :
94 14909 : bool BgpPeerClose::IsPeerDeleted() const {
95 14909 : return peer_->IsDeleted();
96 : }
97 :
98 14907 : bool BgpPeerClose::IsPeerAdminDown() const {
99 14907 : return peer_->IsAdminDown();
100 : }
101 :
102 14746 : bool BgpPeerClose::IsServerDeleted() const {
103 14746 : return peer_->server()->IsDeleted();
104 : }
105 :
106 14747 : bool BgpPeerClose::IsServerAdminDown() const {
107 14747 : return peer_->server()->admin_down();
108 : }
109 :
110 7274 : bool BgpPeerClose::IsInGRTimerWaitState() const {
111 7274 : return GetManager()->IsInGRTimerWaitState();
112 : }
113 :
114 636 : bool BgpPeerClose::IsInLlgrTimerWaitState() const {
115 636 : return GetManager()->IsInLlgrTimerWaitState();
116 : }
117 :
118 6294 : const std::vector<std::string> &BgpPeerClose::negotiated_families() const {
119 6294 : return negotiated_families_;
120 : }
121 :
122 : const std::vector<BgpProto::OpenMessage::Capability *> &
123 10850 : BgpPeerClose::capabilities() const {
124 10850 : return peer_->capabilities();
125 : }
126 :
127 150908 : void BgpPeerClose::UpdateRouteStats(Address::Family family,
128 : const BgpPath *old_path,
129 : uint32_t path_flags) const {
130 150908 : GetManager()->UpdateRouteStats(family, old_path, path_flags);
131 150899 : }
132 :
133 15928 : void BgpPeerClose::Close(bool graceful) {
134 : // Abort GR-Closure if this request is for non-graceful closure.
135 : // Reset GR-Closure if previous closure is still in progress or if
136 : // this is a flip (from established state).
137 15928 : if (!graceful || flap_count_ != peer_->total_flap_count()) {
138 13289 : if (flap_count_ != peer_->total_flap_count()) {
139 5351 : flap_count_++;
140 5351 : assert(peer_->total_flap_count() == flap_count_);
141 : }
142 13286 : GetManager()->Close(graceful);
143 13292 : return;
144 : }
145 :
146 : // Ignore if close is already in progress.
147 2639 : if (GetManager()->IsCloseInProgress() && !IsInGRTimerWaitState())
148 41 : return;
149 :
150 2599 : if (peer_->IsDeleted()) {
151 0 : peer_->RetryDelete();
152 : } else {
153 2599 : CustomClose();
154 2599 : CloseComplete();
155 : }
156 : }
157 :
158 12384 : void BgpPeerClose::Delete() {
159 12384 : gr_params_.Initialize();
160 12384 : llgr_params_.Initialize();
161 12384 : gr_families_.clear();
162 12384 : llgr_families_.clear();
163 12384 : negotiated_families_.clear();
164 12384 : if (peer_->IsDeleted()) {
165 9567 : peer_->RetryDelete();
166 : } else {
167 2817 : CloseComplete();
168 : }
169 12384 : }
170 :
171 801176 : bool BgpPeerClose::IsGRReady() const {
172 : // Check if GR Helper mode is disabled.
173 801176 : if (!IsGRHelperModeEnabled()) {
174 10473 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
175 : BGP_PEER_DIR_IN, "GR Helper mode is not enabled because it is not"
176 : " configured");
177 10472 : return false;
178 : }
179 :
180 : // Check if GR is supported by the peer.
181 790703 : if (gr_params_.families.empty()) {
182 442369 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
183 : BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
184 : "GR address families list is empty");
185 442368 : return false;
186 : }
187 :
188 : // LLGR should be in effect to enable GR Helper mode with 0 restart time.
189 348334 : if (!gr_params_.time && !IsCloseLongLivedGracefulInternal()) {
190 166666 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
191 : BGP_PEER_DIR_IN, "GR Helper mode is not enabled because received "
192 : "GR restart time value is 0 seconds and (there is no applicable "
193 : "LLGR as well");
194 166666 : return false;
195 : }
196 :
197 : // Abort GR if currently negotiated families differ from already
198 : // staled address families.
199 338934 : if (!negotiated_families().empty() &&
200 157266 : PeerNegotiatedFamilies() != negotiated_families()) {
201 135828 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
202 : BGP_PEER_DIR_IN, "GR Helper mode is aborted because received "
203 : "GR families list differs from the list received last time");
204 135828 : return false;
205 : }
206 :
207 : // If GR is not supported for any of the negotiated address family,
208 : // then consider GR as not supported
209 45841 : if (PeerNegotiatedFamilies() != gr_families_) {
210 36036 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
211 : BGP_PEER_DIR_IN, "GR Helper mode is not enabled because GR address "
212 : "families differs from negotiated address families");
213 36036 : return false;
214 : }
215 :
216 : // Make sure that forwarding state is preserved for all families in
217 : // the restarting speaker. (Except for ERMVPN)
218 26671 : for (auto family : gr_params_.families) {
219 : // Check if forwarding state was preserved during restart.
220 19506 : if (family.forwarding_state_preserved())
221 16865 : continue;
222 :
223 : // Ignore forwarding-state preservation check for certain families.
224 : Address::Family addr_family =
225 2904 : BgpAf::AfiSafiToFamily(family.afi, family.safi);
226 2904 : if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
227 264 : continue;
228 :
229 2640 : string family_str = Address::FamilyToString(addr_family);
230 2640 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
231 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not "
232 : "enabled because after restart, GR forwarding state is not "
233 : "preserved for address family " << family_str);
234 2640 : return false;
235 2640 : }
236 7165 : return true;
237 : }
238 :
239 : // If the peer is deleted or administratively held down, do not attempt
240 : // graceful restart
241 801343 : bool BgpPeerClose::IsCloseGraceful() const {
242 801343 : if (IsPeerDeleted()) {
243 1 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
244 : BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
245 : " been deleted");
246 1 : return false;
247 : }
248 :
249 801344 : if (IsPeerAdminDown()) {
250 162 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
251 : BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpPeer has"
252 : " been held administratively down");
253 162 : return false;
254 : }
255 :
256 801180 : if (IsServerDeleted()) {
257 1 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
258 : BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
259 : "has been deletd");
260 1 : return false;
261 : }
262 :
263 801180 : if (IsServerAdminDown()) {
264 1 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
265 : BGP_PEER_DIR_IN, "GR Helper mode is not enabled because BgpServer "
266 : "has been held administratively down");
267 1 : return false;
268 : }
269 :
270 801179 : if (!IsGRReady())
271 794012 : return false;
272 7165 : return true;
273 : }
274 :
275 : // LLGR families should be identical to GR families.
276 40899 : bool BgpPeerClose::IsLlgrSupportedForFamilies() const {
277 : // Keep a sorted list of unsupported families.
278 : static vector<string> unsupported_families = list_of
279 36 : (Address::FamilyToString(Address::ERMVPN))
280 40917 : (Address::FamilyToString(Address::MVPN));
281 :
282 40899 : if (gr_families_ == llgr_families_)
283 8364 : return true;
284 :
285 : // Ignore families mis-match for certain families.
286 32536 : vector<string> differing_families;
287 32536 : std::set_symmetric_difference(gr_families_.begin(), gr_families_.end(),
288 : llgr_families_.begin(), llgr_families_.end(),
289 : back_inserter(differing_families));
290 :
291 : // Ignore if differing families are only those which are unsupported.
292 32536 : return includes(unsupported_families.begin(), unsupported_families.end(),
293 32536 : differing_families.begin(), differing_families.end());
294 32536 : }
295 :
296 : // Check if we need to trigger Long Lived Graceful Restart. In addition to
297 : // normal GR checks, we also need to check LLGR capability was negotiated
298 : // and non-zero restart time was inferred.
299 406447 : bool BgpPeerClose::IsCloseLongLivedGraceful() const {
300 406447 : if (!IsCloseGraceful())
301 402082 : return false;
302 4363 : return BgpPeerClose::IsCloseLongLivedGracefulInternal();
303 : }
304 :
305 176417 : bool BgpPeerClose::IsCloseLongLivedGracefulInternal() const {
306 176417 : if (llgr_params_.families.empty()) {
307 97578 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
308 : BGP_PEER_DIR_IN,
309 : "No LLGR support due to empty LLGR address families list");
310 97578 : return false;
311 : }
312 78839 : if (!llgr_params_.time) {
313 37940 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
314 : BGP_PEER_DIR_IN, "No LLGR support due to zero time value");
315 37940 : return false;
316 : }
317 :
318 40899 : if (!IsLlgrSupportedForFamilies()) {
319 27880 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
320 : BGP_PEER_DIR_IN, "No LLGR support due to dissimilar "
321 : "GR address families and LLGR address families");
322 27880 : return false;
323 : }
324 :
325 : // Make sure that forwarding state is preserved for all families in
326 : // the restarting speaker.
327 32291 : for (auto family : llgr_params_.families) {
328 : // Ignore forwarding-state preservation check for certain families.
329 : Address::Family addr_family =
330 23912 : BgpAf::AfiSafiToFamily(family.afi, family.safi);
331 23912 : if (addr_family == Address::ERMVPN || addr_family == Address::MVPN)
332 4619 : continue;
333 :
334 19293 : if (!family.forwarding_state_preserved()) {
335 4640 : string family_str = Address::FamilyToString(addr_family);
336 4640 : BGP_LOG_PEER(Message, peer_, SandeshLevel::SYS_DEBUG,
337 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN, "GR Helper mode is not "
338 : "enabled because after restart, LLGR forwarding state is not "
339 : "preserved for address family " << family_str);
340 4640 : return false;
341 4640 : }
342 : }
343 8379 : return true;
344 : }
345 :
346 5715 : void BgpPeerClose::RestartStateMachine() {
347 5715 : peer_->state_machine()->Initialize();
348 5715 : }
349 :
350 : // Close process for this peer is complete. Restart the state machine and
351 : // attempt to bring up session with the neighbor
352 6274 : void BgpPeerClose::CloseComplete() {
353 6274 : if (!peer_->IsDeleted() && !peer_->IsAdminDown())
354 5779 : RestartStateMachine();
355 6274 : }
356 :
357 698 : void BgpPeerClose::GetGracefulRestartFamilies(Families *families) const {
358 698 : families->clear();
359 2260 : for (const auto& family : gr_families_) {
360 1562 : families->insert(Address::FamilyFromString(family));
361 : }
362 698 : }
363 :
364 160 : void BgpPeerClose::GetLongLivedGracefulRestartFamilies(Families *families) const {
365 160 : families->clear();
366 560 : for (const auto& family : llgr_families_) {
367 400 : families->insert(Address::FamilyFromString(family));
368 : }
369 160 : }
370 :
371 9498 : void BgpPeerClose::AddGRCapabilities(
372 : BgpProto::OpenMessage::OptParam *opt_param) {
373 9498 : vector<Address::Family> gr_families;
374 9504 : vector<uint8_t> afi_flags;
375 :
376 : // Indicate to the Peer if we are in restarting phase.
377 9502 : bool restarted = peer_->IsServerStartingUp();
378 :
379 : // Indicate EOR support by default.
380 9500 : if (!peer_->server()->global_config()->gr_enable()) {
381 : BgpProto::OpenMessage::Capability *gr_cap =
382 5339 : BgpProto::OpenMessage::Capability::GR::Encode(0, restarted, false,
383 : afi_flags,
384 5342 : gr_families);
385 5342 : opt_param->capabilities.push_back(gr_cap);
386 5345 : return;
387 : }
388 :
389 41571 : for (auto family : peer_->supported_families()) {
390 37413 : if (!peer_->LookupFamily(family))
391 21992 : continue;
392 15423 : gr_families.push_back(family);
393 15423 : afi_flags.push_back(BgpProto::OpenMessage::Capability::GR::
394 : ForwardingStatePreservedFlag);
395 : }
396 :
397 4156 : uint16_t time = peer_->server()->GetGracefulRestartTime();
398 : BgpProto::OpenMessage::Capability *gr_cap =
399 4157 : BgpProto::OpenMessage::Capability::GR::Encode(time, restarted, true,
400 4158 : afi_flags, gr_families);
401 4158 : opt_param->capabilities.push_back(gr_cap);
402 14846 : }
403 :
404 : // Process received GR and LLGR Capabilities. Return true if the values are sane
405 : // to proceed with further processing. Return false if not to abort any ongoing
406 : // GR and instead trigger non-graceful closure.
407 791873 : bool BgpPeerClose::SetGRCapabilities(BgpPeerInfoData *peer_info) {
408 791873 : BgpProto::OpenMessage::Capability::GR::Decode(&gr_params_, capabilities());
409 791872 : BgpProto::OpenMessage::Capability::GR::GetFamilies(gr_params_,
410 : &gr_families_);
411 :
412 791870 : BgpProto::OpenMessage::Capability::LLGR::Decode(&llgr_params_,
413 791870 : capabilities());
414 791870 : BgpProto::OpenMessage::Capability::LLGR::GetFamilies(llgr_params_,
415 : &llgr_families_);
416 :
417 791871 : if (peer_info) {
418 5425 : peer_info->set_graceful_restart_families(gr_families_);
419 5425 : peer_info->set_long_lived_graceful_restart_families(llgr_families_);
420 5426 : peer_info->set_graceful_restart_time(GetGracefulRestartTime());
421 10852 : peer_info->set_long_lived_graceful_restart_time(
422 5426 : GetLongLivedGracefulRestartTime());
423 5426 : assert(!peer_info->get_name().empty());
424 5426 : BGP_UVE_SEND(BGPPeerInfo, *peer_info);
425 : }
426 :
427 : // If we are not in GR Timer waiting state, then there is no case to abort
428 : // GR when new session is coming up.
429 791872 : if (!IsInGRTimerWaitState())
430 4798 : return true;
431 :
432 : // If LLGR is no longer supported, terminate GR right away. This can happen
433 : // due to mis-match between gr and llgr afis. For now, we expect an
434 : // identical set.
435 787073 : if (IsInLlgrTimerWaitState())
436 393349 : return IsCloseLongLivedGraceful();
437 393724 : return IsCloseGraceful();
438 : }
439 :
440 9502 : void BgpPeerClose::AddLLGRCapabilities(
441 : BgpProto::OpenMessage::OptParam *opt_param) {
442 13660 : if (!peer_->server()->global_config()->gr_enable() ||
443 4158 : !peer_->server()->GetLongLivedGracefulRestartTime()) {
444 5360 : return;
445 : }
446 :
447 4142 : vector<Address::Family> llgr_families;
448 41417 : for (auto family : peer_->supported_families()) {
449 37276 : if (peer_->LookupFamily(family))
450 15409 : llgr_families.push_back(family);
451 : }
452 :
453 4141 : uint32_t time = peer_->server()->GetLongLivedGracefulRestartTime();
454 4142 : uint8_t afi_flags =
455 : BgpProto::OpenMessage::Capability::LLGR::ForwardingStatePreservedFlag;
456 : BgpProto::OpenMessage::Capability *llgr_cap =
457 4142 : BgpProto::OpenMessage::Capability::LLGR::Encode(time, afi_flags,
458 4142 : llgr_families);
459 4142 : opt_param->capabilities.push_back(llgr_cap);
460 4142 : }
461 :
462 56 : void BgpPeerClose::FillNeighborInfo(BgpNeighborResp *bnr) const {
463 56 : bnr->set_graceful_restart_address_families(gr_families_);
464 56 : bnr->set_long_lived_graceful_restart_address_families(llgr_families_);
465 56 : bnr->set_graceful_restart_time(GetGracefulRestartTime());
466 112 : bnr->set_long_lived_graceful_restart_time(
467 56 : GetLongLivedGracefulRestartTime());
468 56 : }
|