Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/bgp_peer.h"
6 :
7 : #include <algorithm>
8 : #include <limits>
9 : #include <map>
10 :
11 : #include <boost/assign/list_of.hpp>
12 : #include <boost/foreach.hpp>
13 : #include <boost/tuple/tuple.hpp>
14 :
15 : #include "base/set_util.h"
16 : #include "base/task_annotations.h"
17 : #include "bgp/bgp_factory.h"
18 : #include "bgp/bgp_log.h"
19 : #include "bgp/bgp_membership.h"
20 : #include "bgp/bgp_peer_close.h"
21 : #include "bgp/bgp_sandesh.h"
22 : #include "bgp/bgp_server.h"
23 : #include "bgp/bgp_session.h"
24 : #include "bgp/bgp_session_manager.h"
25 : #include "bgp/bgp_peer_types.h"
26 : #include "bgp/community.h"
27 : #include "bgp/ermvpn/ermvpn_table.h"
28 : #include "bgp/evpn/evpn_table.h"
29 : #include "bgp/inet/inet_table.h"
30 : #include "bgp/inet6/inet6_table.h"
31 : #include "bgp/inet6vpn/inet6vpn_table.h"
32 : #include "bgp/l3vpn/inetvpn_table.h"
33 : #include "bgp/mvpn/mvpn_table.h"
34 : #include "bgp/peer_close_manager.h"
35 : #include "bgp/routing-instance/peer_manager.h"
36 : #include "bgp/routing-instance/routing_instance.h"
37 : #include "bgp/routing-policy/routing_policy_match.h"
38 : #include "bgp/rtarget/rtarget_table.h"
39 : #include "bgp/tunnel_encap/tunnel_encap.h"
40 : #include "control-node/control_node.h"
41 : #include "config-client-mgr/config_client_manager.h"
42 : using boost::assign::list_of;
43 : using boost::assign::map_list_of;
44 : using boost::system::error_code;
45 : using boost::tie;
46 : using std::copy;
47 : using std::dec;
48 : using std::map;
49 : using std::numeric_limits;
50 : using std::ostringstream;
51 : using std::string;
52 : using std::vector;
53 :
54 : class BgpPeer::PeerStats : public IPeerDebugStats {
55 : public:
56 684 : explicit PeerStats(BgpPeer *peer)
57 3420 : : peer_(peer) {
58 684 : }
59 :
60 : // Used when peer flaps.
61 : // Reset all counters.
62 : // Socket counters are implicitly cleared because we use a new socket.
63 1113 : virtual void Clear() {
64 1113 : error_stats_ = ErrorStats();
65 1112 : proto_stats_[0] = ProtoStats();
66 1112 : proto_stats_[1] = ProtoStats();
67 1113 : update_stats_[0] = UpdateStats();
68 1113 : update_stats_[1] = UpdateStats();
69 1110 : }
70 :
71 : // Printable name
72 0 : virtual string ToString() const {
73 0 : return peer_->ToString();
74 : }
75 : // Previous State of the peer
76 0 : virtual string last_state() const {
77 0 : return peer_->state_machine()->LastStateName();
78 : }
79 0 : virtual string last_state_change_at() const {
80 0 : return peer_->state_machine()->last_state_change_at();
81 : }
82 : // Last error on this peer
83 0 : virtual string last_error() const {
84 0 : return peer_->state_machine()->last_notification_in_error();
85 : }
86 : // Last Event on this peer
87 0 : virtual string last_event() const {
88 0 : return peer_->state_machine()->last_event();
89 : }
90 :
91 : // When was the Last
92 0 : virtual string last_flap() const {
93 0 : return peer_->last_flap_at();
94 : }
95 :
96 : // Total number of flaps
97 0 : virtual uint64_t num_flaps() const {
98 0 : return peer_->flap_count();
99 : }
100 :
101 0 : virtual void GetRxProtoStats(ProtoStats *stats) const {
102 0 : *stats = proto_stats_[0];
103 0 : }
104 :
105 0 : virtual void GetTxProtoStats(ProtoStats *stats) const {
106 0 : *stats = proto_stats_[1];
107 0 : }
108 :
109 0 : virtual void GetRxRouteUpdateStats(UpdateStats *stats) const {
110 0 : *stats = update_stats_[0];
111 0 : }
112 :
113 0 : virtual void GetTxRouteUpdateStats(UpdateStats *stats) const {
114 0 : *stats = update_stats_[1];
115 0 : }
116 :
117 0 : virtual void GetRxSocketStats(IPeerDebugStats::SocketStats *stats) const {
118 0 : if (peer_->session()) {
119 0 : const io::SocketStats &socket_stats = peer_->session()->GetSocketStats();
120 0 : stats->calls = socket_stats.read_calls;
121 0 : stats->bytes = socket_stats.read_bytes;
122 : }
123 0 : }
124 :
125 0 : virtual void GetTxSocketStats(IPeerDebugStats::SocketStats *stats) const {
126 0 : if (peer_->session()) {
127 0 : const io::SocketStats &socket_stats = peer_->session()->GetSocketStats();
128 0 : stats->calls = socket_stats.write_calls;
129 0 : stats->bytes = socket_stats.write_bytes;
130 0 : stats->blocked_count = socket_stats.write_blocked;
131 0 : stats->blocked_duration_usecs =
132 0 : socket_stats.write_blocked_duration_usecs;
133 : }
134 0 : }
135 :
136 17166 : virtual void UpdateTxUnreachRoute(uint64_t count) {
137 17166 : update_stats_[1].unreach += count;
138 17166 : }
139 :
140 17166 : virtual void UpdateTxReachRoute(uint64_t count) {
141 17166 : update_stats_[1].reach += count;
142 17166 : }
143 :
144 : // Do nothing for bgp peers.
145 0 : virtual void GetRxErrorStats(RxErrorStats *stats) const {
146 0 : }
147 :
148 0 : virtual void GetRxRouteStats(RxRouteStats *stats) const {
149 0 : stats->total_path_count = peer_->GetTotalPathCount();
150 0 : stats->primary_path_count = peer_->GetPrimaryPathCount();
151 0 : }
152 :
153 : private:
154 : friend class BgpPeer;
155 :
156 : BgpPeer *peer_;
157 : ErrorStats error_stats_;
158 : ProtoStats proto_stats_[2];
159 : UpdateStats update_stats_[2];
160 : };
161 :
162 : class BgpPeer::DeleteActor : public LifetimeActor {
163 : public:
164 684 : explicit DeleteActor(BgpPeer *peer)
165 684 : : LifetimeActor(peer->server_->lifetime_manager()),
166 684 : peer_(peer) {
167 684 : }
168 :
169 1758 : virtual bool MayDelete() const {
170 1758 : CHECK_CONCURRENCY("bgp::Config");
171 1758 : if (!peer_->close_manager_->IsQueueEmpty())
172 398 : return false;
173 1360 : if (peer_->IsCloseInProgress())
174 0 : return false;
175 1360 : if (!peer_->state_machine_->IsQueueEmpty())
176 676 : return false;
177 684 : if (peer_->prefix_limit_trigger_.IsSet())
178 0 : return false;
179 684 : return true;
180 : }
181 :
182 684 : virtual void Shutdown() {
183 684 : CHECK_CONCURRENCY("bgp::Config");
184 684 : peer_->Clear(BgpProto::Notification::PeerDeconfigured);
185 684 : }
186 :
187 684 : virtual void Destroy() {
188 684 : CHECK_CONCURRENCY("bgp::Config");
189 684 : peer_->PostCloseRelease();
190 684 : if (peer_->IsRouterTypeBGPaaS()) {
191 0 : peer_->server()->decrement_deleting_bgpaas_count();
192 : } else {
193 684 : peer_->server()->decrement_deleting_count();
194 : }
195 684 : if (peer_->dscp_listener_id_ >= 0) {
196 684 : peer_->server()->UnregisterDSCPUpdateCallback(
197 684 : peer_->dscp_listener_id_);
198 684 : peer_->dscp_listener_id_ = -1;
199 : }
200 684 : if (peer_->instance_op_ >= 0) {
201 0 : peer_->server()->routing_instance_mgr()->
202 0 : UnregisterInstanceOpCallback(peer_->instance_op_);
203 0 : peer_->instance_op_ = -1;
204 : }
205 684 : if (peer_->asn_listener_id_ >= 0) {
206 0 : peer_->server()->UnregisterASNUpdateCallback(
207 0 : peer_->asn_listener_id_);
208 0 : peer_->asn_listener_id_ = -1;
209 : }
210 684 : assert(!peer_->membership_req_pending());
211 684 : assert(!peer_->close_manager_->IsMembershipInUse());
212 684 : peer_->rtinstance_->peer_manager()->DestroyIPeer(peer_);
213 684 : }
214 :
215 : private:
216 : BgpPeer *peer_;
217 : };
218 :
219 : //
220 : // Constructor for BgpPeerFamilyAttributes.
221 : //
222 2630 : BgpPeerFamilyAttributes::BgpPeerFamilyAttributes(
223 : const BgpNeighborConfig *config,
224 2630 : const BgpFamilyAttributesConfig &family_config) {
225 2630 : if (family_config.loop_count) {
226 0 : loop_count = family_config.loop_count;
227 : } else {
228 2630 : loop_count = config->loop_count();
229 : }
230 2630 : prefix_limit = family_config.prefix_limit;
231 2630 : idle_timeout = family_config.idle_timeout;
232 2630 : default_tunnel_encap_list = family_config.default_tunnel_encap_list;
233 :
234 2630 : if (config->router_type() == "bgpaas-client") {
235 0 : if (family_config.family == "inet") {
236 0 : gateway_address = config->gateway_address(Address::INET);
237 0 : } else if (family_config.family == "inet6") {
238 0 : gateway_address = config->gateway_address(Address::INET6);
239 : }
240 : }
241 2630 : }
242 :
243 1681 : RibExportPolicy BgpPeer::BuildRibExportPolicy(Address::Family family) const {
244 1681 : RibExportPolicy policy;
245 : BgpPeerFamilyAttributes *family_attributes =
246 1682 : family_attributes_list_[family];
247 1681 : if (!family_attributes) {
248 0 : policy = RibExportPolicy(peer_type_, RibExportPolicy::BGP, peer_as_,
249 0 : as_override_, peer_close_->IsCloseLongLivedGraceful(),
250 0 : as4_supported_, -1, cluster_id_, local_as_);
251 : } else {
252 1678 : policy = RibExportPolicy(peer_type_, RibExportPolicy::BGP, peer_as_,
253 1682 : as_override_, peer_close_->IsCloseLongLivedGraceful(),
254 1682 : as4_supported_, family_attributes->gateway_address,
255 1681 : -1, cluster_id_, family_attributes->default_tunnel_encap_list,
256 3361 : local_as_);
257 : }
258 :
259 1676 : if (private_as_action_ == "remove") {
260 0 : policy.SetRemovePrivatePolicy(false, false, true);
261 1677 : } else if (private_as_action_ == "remove-all") {
262 0 : policy.SetRemovePrivatePolicy(true, false, true);
263 1676 : } else if (private_as_action_ == "replace-all") {
264 0 : policy.SetRemovePrivatePolicy(true, true, true);
265 : }
266 :
267 1677 : return policy;
268 0 : }
269 :
270 1660 : void BgpPeer::ReceiveEndOfRIB(Address::Family family, size_t msgsize) {
271 1660 : close_manager_->ProcessEORMarkerReceived(family);
272 1660 : eor_receive_timer_[family]->Cancel();
273 :
274 : // If EoR for RTarget is received, start registration for other families.
275 1661 : if (family == Address::RTARGET)
276 110 : RegisterToVpnTables();
277 1661 : }
278 :
279 1672 : void BgpPeer::SendEndOfRIBActual(Address::Family family) {
280 1672 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
281 :
282 : // Bail if there's no session for the peer anymore.
283 1672 : if (!session_)
284 0 : return;
285 :
286 1672 : BgpProto::Update update;
287 : uint16_t afi;
288 : uint8_t safi;
289 1672 : tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
290 1672 : BgpMpNlri *nlri = new BgpMpNlri(BgpAttribute::MPUnreachNlri, afi, safi);
291 1672 : update.path_attributes.push_back(nlri);
292 : uint8_t data[256];
293 3344 : int msgsize = BgpProto::Encode(&update, data, sizeof(data), NULL,
294 1672 : Is4ByteAsSupported());
295 1672 : assert(msgsize > BgpProto::kMinMessageSize);
296 1672 : session_->Send(data, msgsize, NULL);
297 1672 : inc_tx_end_of_rib();
298 1672 : inc_tx_update();
299 1672 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO,
300 : BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_OUT,
301 : "EndOfRib marker family " << Address::FamilyToString(family) <<
302 : " size " << msgsize);
303 1672 : }
304 :
305 0 : uint32_t BgpPeer::GetOutputQueueDepth(Address::Family family) const {
306 0 : BgpTable *table = GetRoutingInstance()->GetTable(family);
307 0 : return server_->membership_mgr()->GetRibOutQueueDepth(this, table);
308 : }
309 :
310 0 : time_t BgpPeer::GetEorSendTimerElapsedTime() const {
311 0 : return UTCTimestamp() - eor_send_timer_start_time_;
312 : }
313 :
314 2125 : uint32_t BgpPeer::GetEndOfRibReceiveTime(Address::Family family) const {
315 2125 : return family == Address::RTARGET ?
316 2125 : kRouteTargetEndOfRibTimeSecs : server_->GetEndOfRibReceiveTime();
317 : }
318 :
319 1670 : bool BgpPeer::IsServerStartingUp() const {
320 1670 : return server_->IsServerStartingUp();
321 : }
322 :
323 3 : bool BgpPeer::IsCloseGraceful() const {
324 3 : return peer_close_->IsCloseGraceful();
325 : }
326 :
327 0 : time_t BgpPeer::GetRTargetTableLastUpdatedTimeStamp() const {
328 0 : return server_->GetRTargetTableLastUpdatedTimeStamp();
329 : }
330 :
331 0 : bool BgpPeer::EndOfRibSendTimerExpired(Address::Family family) {
332 0 : if (!IsReady())
333 0 : return false;
334 :
335 : // Send EoR if wait time has exceeded the configured maximum.
336 0 : if (GetEorSendTimerElapsedTime() >= server_->GetEndOfRibSendTime()) {
337 0 : SendEndOfRIBActual(family);
338 0 : return false;
339 : }
340 :
341 : // Defer if output queue has not been fully drained yet.
342 0 : uint32_t output_depth = GetOutputQueueDepth(family);
343 0 : if (output_depth) {
344 0 : eor_send_timer_[family]->Reschedule(kEndOfRibSendRetryTime * 1000);
345 0 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO,
346 : BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_OUT,
347 : "EndOfRib Send Timer rescheduled for family " <<
348 : Address::FamilyToString(family) << " to fire after " <<
349 : kEndOfRibSendRetryTime << " second(s) " <<
350 : "due to non-empty output queue (" << output_depth << ")");
351 0 : return true;
352 : }
353 :
354 : // Send EoR if we are not still under [re-]starting phase.
355 0 : if (!IsServerStartingUp()) {
356 0 : SendEndOfRIBActual(family);
357 0 : return false;
358 : }
359 :
360 : // Defer if configuration processing is not complete yet.
361 0 : if (!ConfigClientManager::end_of_rib_computed()) {
362 0 : eor_send_timer_[family]->Reschedule(kEndOfRibSendRetryTime * 1000);
363 0 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO,
364 : BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_OUT,
365 : "EndOfRib Send Timer rescheduled for family " <<
366 : Address::FamilyToString(family) << " to fire after " <<
367 : kEndOfRibSendRetryTime << " second(s) " <<
368 : "as bgp (under restart) has not completed initial configuration"
369 : " processing");
370 0 : return true;
371 : }
372 :
373 : // For all families except route-target, wait for a certain amount of time
374 : // before sending eor as bgp is still in [re-]starting phase (60s).
375 0 : if (family != Address::RTARGET) {
376 0 : eor_send_timer_[family]->Reschedule(kEndOfRibSendRetryTime * 1000);
377 0 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO,
378 : BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_OUT,
379 : "EndOfRib Send Timer rescheduled for family " <<
380 : Address::FamilyToString(family) << " to fire after " <<
381 : kEndOfRibSendRetryTime << " second(s) " <<
382 : "as bgp is still under [re-]starting phase");
383 0 : return true;
384 : }
385 :
386 : // Defer EoR if any new route-target was added to the table recently (6s).
387 0 : if (UTCTimestamp() - GetRTargetTableLastUpdatedTimeStamp() <
388 0 : 0.02 * server_->GetEndOfRibSendTime()) {
389 0 : eor_send_timer_[family]->Reschedule(kEndOfRibSendRetryTime * 1000);
390 0 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO,
391 : BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_OUT,
392 : "EndOfRib Send Timer rescheduled for family " <<
393 : Address::FamilyToString(family) << " to fire after " <<
394 : kEndOfRibSendRetryTime << " second(s) " <<
395 : "as new route-targets are still being added to the table");
396 0 : return true;
397 : }
398 :
399 : // Send eor as [re-]starting phase is complete for this family.
400 0 : SendEndOfRIBActual(family);
401 0 : return false;
402 : }
403 :
404 0 : void BgpPeer::SendEndOfRIB(Address::Family family) {
405 0 : eor_send_timer_start_time_ = UTCTimestamp();
406 0 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO,
407 : BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_OUT,
408 : "EndOfRib Send Timer scheduled for family " <<
409 : Address::FamilyToString(family) <<
410 : " to fire after " << kEndOfRibSendRetryTime << " second(s)");
411 0 : eor_send_timer_[family]->Start(kEndOfRibSendRetryTime * 1000,
412 : boost::bind(&BgpPeer::EndOfRibSendTimerExpired, this, family),
413 : boost::bind(&BgpPeer::EndOfRibTimerErrorHandler, this, _1, _2));
414 0 : }
415 :
416 5057 : void BgpPeer::BGPPeerInfoSend(const BgpPeerInfoData &peer_info) const {
417 5057 : assert(!peer_info.get_name().empty());
418 5057 : BGP_UVE_SEND(BGPPeerInfo, peer_info);
419 5056 : }
420 :
421 1712 : bool BgpPeer::CanUseMembershipManager() const {
422 1712 : return !membership_req_pending_;
423 : }
424 :
425 : //
426 : // Callback from BgpMembershipManager.
427 : // Update pending membership request count and send EndOfRib for the family
428 : // in question.
429 : //
430 3582 : void BgpPeer::MembershipRequestCallback(BgpTable *table) {
431 3582 : if (close_manager_->IsMembershipInUse()) {
432 1896 : close_manager_->MembershipRequestCallback();
433 1896 : return;
434 : }
435 :
436 1686 : assert(membership_req_pending_ > 0);
437 1686 : membership_req_pending_--;
438 :
439 : // Resume if CloseManager is waiting to use membership manager.
440 2880 : if (!membership_req_pending_ &&
441 1194 : close_manager_->IsMembershipInWait()) {
442 0 : close_manager_->MembershipRequest();
443 : }
444 :
445 : // Resume close if it was deferred and this is the last pending callback.
446 : // Don't bother sending EndOfRib if close is deferred.
447 1686 : if (defer_close_) {
448 14 : if (!membership_req_pending_) {
449 8 : defer_close_ = false;
450 8 : trigger_.Set();
451 : }
452 14 : return;
453 : }
454 :
455 1672 : SendEndOfRIB(table->family());
456 : }
457 :
458 13742 : bool BgpPeer::MembershipPathCallback(DBTablePartBase *tpart, BgpRoute *route,
459 : BgpPath *path) {
460 13742 : return close_manager_->MembershipPathCallback(tpart, route, path);
461 : }
462 :
463 8 : bool BgpPeer::ResumeClose() {
464 8 : peer_close_->Close(graceful_close_);
465 8 : graceful_close_ = true;
466 8 : return true;
467 : }
468 :
469 684 : BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,
470 684 : const BgpNeighborConfig *config)
471 684 : : server_(server),
472 684 : rtinstance_(instance),
473 684 : peer_key_(config),
474 684 : peer_port_(config->source_port()),
475 684 : peer_name_(config->name()),
476 684 : router_type_(config->router_type()),
477 684 : config_(config),
478 684 : index_(server->RegisterPeer(this)),
479 684 : trigger_(boost::bind(&BgpPeer::ResumeClose, this),
480 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
481 : GetTaskInstance()),
482 684 : prefix_limit_idle_timer_(
483 684 : TimerManager::CreateTimer(*server->ioservice(),
484 : "BGP prefix limit idle timer",
485 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
486 : GetTaskInstance())),
487 684 : prefix_limit_trigger_(boost::bind(&BgpPeer::CheckPrefixLimits, this),
488 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
489 : GetTaskInstance()),
490 684 : buffer_capacity_(GetBufferCapacity()),
491 684 : session_(NULL),
492 684 : keepalive_timer_(TimerManager::CreateTimer(*server->ioservice(),
493 : "BGP keepalive timer",
494 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
495 : GetTaskInstance())),
496 684 : eor_send_timer_start_time_(0),
497 684 : send_ready_(true),
498 684 : admin_down_(config->admin_down()),
499 684 : passive_(config->passive()),
500 684 : resolve_paths_(config->router_type() == "bgpaas-client"),
501 684 : as_override_(config->as_override()),
502 684 : cluster_id_(config->cluster_id()),
503 684 : origin_override_(config->origin_override()),
504 684 : defer_close_(false),
505 684 : graceful_close_(true),
506 684 : as4_supported_(false),
507 684 : vpn_tables_registered_(false),
508 684 : hold_time_(config->hold_time()),
509 684 : local_as_(config->local_as()),
510 684 : peer_as_(config->peer_as()),
511 684 : local_bgp_id_(config->local_identifier()),
512 684 : peer_bgp_id_(0),
513 684 : peer_type_((config->peer_as() == config->local_as()) ?
514 : BgpProto::IBGP : BgpProto::EBGP),
515 684 : state_machine_(BgpStaticObjectFactory::Create<StateMachine>(this)),
516 684 : peer_close_(BgpStaticObjectFactory::Create<BgpPeerClose>(this)),
517 684 : peer_stats_(new PeerStats(this)),
518 684 : deleter_(new DeleteActor(this)),
519 684 : instance_delete_ref_(this, instance ? instance->deleter() : NULL),
520 684 : flap_count_(0),
521 684 : total_flap_count_(0),
522 684 : last_flap_(0),
523 684 : dscp_listener_id_(-1),
524 684 : inuse_authkey_type_(AuthenticationData::NIL),
525 684 : asn_listener_id_(-1),
526 13680 : instance_op_(-1) {
527 684 : buffer_.reserve(buffer_capacity_);
528 684 : close_manager_.reset(
529 684 : BgpStaticObjectFactory::Create<PeerCloseManager>(static_cast<IPeerClose*>(peer_close_.get())));
530 684 : ostringstream oss1;
531 684 : oss1 << peer_key_.endpoint.address();
532 684 : if (peer_key_.endpoint.port() != BgpConfigManager::kDefaultPort)
533 684 : oss1 << ":" << dec << peer_key_.endpoint.port();
534 684 : to_str_ = oss1.str();
535 :
536 684 : ostringstream oss2;
537 684 : if (rtinstance_)
538 684 : oss2 << rtinstance_->name() << ":";
539 684 : oss2 << server_->localname() << ":";
540 684 : oss2 << peer_name();
541 684 : uve_key_str_ = oss2.str();
542 :
543 1368 : if (router_type_ == "control-node" ||
544 684 : router_type_ == "external-control-node") {
545 0 : peer_is_control_node_ = true;
546 : } else {
547 684 : peer_is_control_node_ = false;
548 : }
549 :
550 684 : dscp_listener_id_ = server_->RegisterDSCPUpdateCallback(boost::bind(
551 : &BgpPeer::DSCPUpdateCallback, this, _1));
552 684 : if (IsRouterTypeBGPaaS()) {
553 0 : asn_listener_id_ = server->RegisterASNUpdateCallback(boost::bind(
554 : &BgpPeer::ASNUpdateCallback, this, _1, _2));
555 0 : instance_op_=server->routing_instance_mgr()->RegisterInstanceOpCallback(
556 : boost::bind(&BgpPeer::RoutingInstanceCallback, this, _1, _2));
557 : }
558 :
559 684 : membership_req_pending_ = 0;
560 684 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
561 : BGP_PEER_DIR_NA, "Created");
562 :
563 684 : if (rtinstance_ && peer_name_.find(rtinstance_->name()) == 0) {
564 684 : peer_basename_ = peer_name_.substr(rtinstance_->name().size() + 1);
565 : } else {
566 0 : peer_basename_ = peer_name_;
567 : }
568 :
569 684 : for (Address::Family family = Address::UNSPEC;
570 7524 : family < Address::NUM_FAMILIES;
571 6840 : family = static_cast<Address::Family>(family + 1)) {
572 6840 : family_primary_path_count_[family] = 0;
573 13680 : eor_send_timer_[family] =
574 20520 : TimerManager::CreateTimer(*server->ioservice(),
575 13680 : "BGP EoR Send timer for " + Address::FamilyToString(family),
576 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
577 : GetTaskInstance());
578 13680 : eor_receive_timer_[family] =
579 20520 : TimerManager::CreateTimer(*server->ioservice(),
580 13680 : "BGP EoR Receive timer for " + Address::FamilyToString(family),
581 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
582 : GetTaskInstance());
583 : }
584 :
585 684 : total_path_count_ = 0;
586 684 : primary_path_count_ = 0;
587 :
588 : // Check rtinstance_ to accommodate unit tests.
589 684 : if (resolve_paths_ && rtinstance_) {
590 0 : rtinstance_->GetTable(Address::INET)->LocatePathResolver();
591 0 : rtinstance_->GetTable(Address::INET6)->LocatePathResolver();
592 : }
593 :
594 684 : ProcessEndpointConfig(config);
595 684 : ProcessAuthKeyChainConfig(config);
596 684 : ProcessFamilyAttributesConfig(config);
597 :
598 1368 : BgpPeerInfoData peer_info;
599 684 : peer_info.set_name(ToUVEKey());
600 684 : peer_info.set_admin_down(admin_down_);
601 684 : peer_info.set_passive(passive_);
602 684 : peer_info.set_as_override(as_override_);
603 684 : peer_info.set_origin_override(origin_override_.origin_override);
604 684 : if (origin_override_.origin_override) {
605 0 : peer_info.set_route_origin(
606 0 : BgpAttr::OriginToString(origin_override_.origin));
607 : } else {
608 684 : peer_info.set_route_origin("-");
609 : }
610 684 : peer_info.set_router_type(router_type_);
611 684 : peer_info.set_cluster_id(Ip4Address(cluster_id_).to_string());
612 1368 : peer_info.set_peer_type(
613 684 : PeerType() == BgpProto::IBGP ? "internal" : "external");
614 684 : peer_info.set_local_asn(local_as_);
615 684 : peer_info.set_peer_asn(peer_as_);
616 684 : peer_info.set_peer_port(peer_port_);
617 684 : peer_info.set_hold_time(hold_time_);
618 684 : peer_info.set_local_id(local_bgp_id_);
619 684 : peer_info.set_configured_families(configured_families_);
620 684 : peer_info.set_peer_address(peer_key_.endpoint.address().to_string());
621 684 : BGPPeerInfoSend(peer_info);
622 684 : }
623 :
624 684 : BgpPeer::~BgpPeer() {
625 684 : assert(!close_manager()->IsCloseInProgress());
626 684 : assert(!IsCloseInProgress());
627 684 : assert(GetTotalPathCount() == 0);
628 684 : STLDeleteValues(&family_attributes_list_);
629 684 : ClearListenSocketAuthKey();
630 1368 : BgpPeerInfoData peer_info;
631 684 : peer_info.set_name(ToUVEKey());
632 684 : peer_info.set_deleted(true);
633 684 : BGPPeerInfoSend(peer_info);
634 :
635 1368 : PeerStatsData peer_stats_data;
636 684 : peer_stats_data.set_name(ToUVEKey());
637 684 : peer_stats_data.set_deleted(true);
638 684 : assert(!peer_stats_data.get_name().empty());
639 684 : BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectBgpPeer");
640 :
641 1368 : PeerFlapData peer_flap_data;
642 684 : peer_flap_data.set_name(ToUVEKey());
643 684 : peer_flap_data.set_deleted(true);
644 684 : assert(!peer_flap_data.get_name().empty());
645 684 : BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
646 :
647 684 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
648 : BGP_PEER_DIR_NA, "Deleted");
649 684 : }
650 :
651 684 : void BgpPeer::Initialize() {
652 684 : if (!admin_down_)
653 654 : state_machine_->Initialize();
654 684 : }
655 :
656 684 : size_t BgpPeer::GetBufferCapacity() const {
657 : // For testing only - configure through environment variable.
658 684 : char *buffer_capacity_str = getenv("BGP_PEER_BUFFER_SIZE");
659 684 : if (buffer_capacity_str) {
660 0 : size_t env_buffer_capacity = strtoul(buffer_capacity_str, NULL, 0);
661 0 : if (env_buffer_capacity < kMinBufferCapacity)
662 0 : env_buffer_capacity = kMinBufferCapacity;
663 0 : if (env_buffer_capacity > kMaxBufferCapacity)
664 0 : env_buffer_capacity = kMaxBufferCapacity;
665 0 : return env_buffer_capacity;
666 : }
667 :
668 : // Return internal default based on peer router-type.
669 684 : if (IsRouterTypeBGPaaS()) {
670 0 : return kMinBufferCapacity;
671 : } else {
672 684 : return kMaxBufferCapacity;
673 : }
674 : }
675 :
676 38 : bool BgpPeer::CheckSplitHorizon(uint32_t server_cluster_id,
677 : uint32_t ribout_cid) const {
678 38 : if (PeerType() == BgpProto::IBGP) {
679 : // check if router is a route reflector
680 38 : if (!server_cluster_id) return true;
681 : // check if received from client or non-client by comparing the clusterId
682 : // of router with that of peer from which we this route is received
683 2 : if (server_cluster_id != cluster_id_) {
684 : // If received from non-client, reflect to all the clients only
685 2 : if (ribout_cid && ribout_cid != server_cluster_id) {
686 0 : return true;
687 : }
688 : }
689 : }
690 2 : return false;
691 : }
692 :
693 0 : BgpTable *BgpPeer::GetRTargetTable() {
694 0 : RoutingInstanceMgr *instance_mgr = server_->routing_instance_mgr();
695 0 : if (!instance_mgr)
696 0 : return NULL;
697 0 : RoutingInstance *master = instance_mgr->GetDefaultRoutingInstance();
698 0 : if (!master)
699 0 : return NULL;
700 0 : return master->GetTable(Address::RTARGET);
701 : }
702 :
703 0 : BgpAttrPtr BgpPeer::GetRouteTargetRouteAttr() const {
704 0 : BgpAttrSpec attrs;
705 0 : BgpAttrNextHop nexthop(server_->bgp_identifier());
706 0 : attrs.push_back(&nexthop);
707 0 : BgpAttrOrigin origin(BgpAttrOrigin::IGP);
708 0 : attrs.push_back(&origin);
709 0 : return server_->attr_db()->Locate(attrs);
710 0 : }
711 :
712 : // Add one route-target route to bgp.rtarget.0 table.
713 0 : void BgpPeer::BGPaaSAddRTarget(as_t as, BgpTable *table, BgpAttrPtr attr,
714 : RouteTargetList::const_iterator it) {
715 0 : const RouteTarget rtarget = *it;
716 0 : DBRequest req;
717 0 : RTargetPrefix rt_prefix(as, rtarget);
718 0 : req.key.reset(new RTargetTable::RequestKey(rt_prefix, this));
719 0 : req.data.reset(new RTargetTable::RequestData(attr, 0, 0, 0, 0));
720 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
721 0 : table->Enqueue(&req);
722 0 : }
723 :
724 : // Add import route-targets of associated routing-instance in order to attract
725 : // the VN routes, if bgpaas session comes up within the instance.
726 0 : void BgpPeer::AddRTargets(as_t as) {
727 0 : if (!IsRouterTypeBGPaaS())
728 0 : return;
729 0 : assert(IsReady());
730 0 : BgpTable *table = GetRTargetTable();
731 0 : assert(table);
732 0 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
733 0 : rtargets_ = rtinstance_->GetImportList();
734 0 : for (RouteTargetList::const_iterator it = rtargets_.begin();
735 0 : it != rtargets_.end(); it++) {
736 0 : BGPaaSAddRTarget(as, table, attr, it);
737 : }
738 0 : }
739 :
740 : // Delete one route-target route from bgp.rtarget.0 table.
741 0 : void BgpPeer::BGPaaSDeleteRTarget(as_t as, BgpTable *table,
742 : RouteTargetList::const_iterator it) {
743 0 : const RouteTarget rtarget = *it;
744 0 : DBRequest req;
745 0 : RTargetPrefix rt_prefix(as, rtarget);
746 0 : req.key.reset(new RTargetTable::RequestKey(rt_prefix, this));
747 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
748 0 : table->Enqueue(&req);
749 0 : }
750 :
751 : // Delete import route-targets of associated routing-instance in order to
752 : // not to attract the VN routes any more, if bgpaas session goes down within
753 : // the instance.
754 1684 : void BgpPeer::DeleteRTargets(as_t as) {
755 1684 : if (!IsRouterTypeBGPaaS())
756 1684 : return;
757 0 : BgpTable *table = GetRTargetTable();
758 0 : if (!table)
759 0 : return;
760 0 : for (RouteTargetList::const_iterator it = rtargets_.begin();
761 0 : it != rtargets_.end(); it++) {
762 0 : BGPaaSDeleteRTarget(as, table, it);
763 : }
764 0 : rtargets_.clear();
765 : }
766 :
767 0 : void BgpPeer::ASNUpdateCallback(as_t old_asn, as_t old_local_asn) {
768 0 : CHECK_CONCURRENCY("bgp::Config");
769 0 : DeleteRTargets(old_local_asn);
770 0 : if (!IsReady())
771 0 : return;
772 0 : AddRTargets(server_->local_autonomous_system());
773 : }
774 :
775 : // Process changes to routing-instance configuration. Specifically, we need
776 : // to track all import route-targets so that they can be correctly updated
777 : // when bgpaas sessions come up or go down.
778 0 : void BgpPeer::RoutingInstanceCallback(const std::string &vrf_name, int op) {
779 0 : assert(IsRouterTypeBGPaaS());
780 0 : if (op != RoutingInstanceMgr::INSTANCE_UPDATE || !IsReady())
781 0 : return;
782 0 : if (vrf_name != rtinstance_->name())
783 0 : return;
784 0 : RoutingInstanceMgr *instance_mgr = server_->routing_instance_mgr();
785 0 : RoutingInstance *master = instance_mgr->GetDefaultRoutingInstance();
786 0 : BgpTable *table = master->GetTable(Address::RTARGET);
787 0 : assert(table);
788 0 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
789 0 : set_synchronize(&rtargets_, &rtinstance_->GetImportList(),
790 0 : boost::bind(&BgpPeer::BGPaaSAddRTarget, this,
791 0 : server_->local_autonomous_system(), table, attr, _1),
792 : boost::bind(&BgpPeer::BGPaaSDeleteRTarget, this,
793 0 : server_->local_autonomous_system(), table, _1));
794 0 : rtargets_ = rtinstance_->GetImportList();
795 0 : }
796 :
797 2227 : void BgpPeer::NotifyEstablished(bool established) {
798 2227 : if (established) {
799 1114 : if (IsRouterTypeBGPaaS()) {
800 0 : server_->IncrementUpBgpaasPeerCount();
801 0 : AddRTargets(server_->local_autonomous_system());
802 : } else {
803 1114 : server_->IncrementUpPeerCount();
804 : }
805 : } else {
806 1113 : if (IsRouterTypeBGPaaS()) {
807 0 : server_->DecrementUpBgpaasPeerCount();
808 : } else {
809 1113 : server_->DecrementUpPeerCount();
810 : }
811 : }
812 2226 : }
813 :
814 0 : void BgpPeer::BindLocalEndpoint(BgpSession *session) {
815 0 : }
816 :
817 : // Just return the first entry for now.
818 0 : bool BgpPeer::GetBestAuthKey(AuthenticationKey *auth_key,
819 : KeyType *key_type) const {
820 0 : if (auth_data_.Empty()) {
821 0 : return false;
822 : }
823 0 : assert(auth_key);
824 0 : AuthenticationData::const_iterator iter = auth_data_.begin();
825 0 : *auth_key = *iter;
826 0 : *key_type = auth_data_.key_type();
827 0 : return true;
828 : }
829 :
830 1746 : bool BgpPeer::ProcessAuthKeyChainConfig(const BgpNeighborConfig *config) {
831 1746 : const AuthenticationData &input_auth_data = config->auth_data();
832 :
833 1746 : if (auth_data_ == input_auth_data) {
834 1746 : return false;
835 : }
836 :
837 0 : auth_data_ = input_auth_data;
838 0 : return InstallAuthKeys();
839 : }
840 :
841 0 : bool BgpPeer::InstallAuthKeys() {
842 0 : if (!PeerAddress()) {
843 0 : return false;
844 : }
845 :
846 0 : AuthenticationKey auth_key;
847 : KeyType key_type;
848 0 : bool valid = GetBestAuthKey(&auth_key, &key_type);
849 0 : if (valid) {
850 0 : if (key_type == AuthenticationData::MD5) {
851 0 : LogInstallAuthKeys("Listen", "add", auth_key, key_type);
852 0 : SetListenSocketAuthKey(auth_key, key_type);
853 0 : SetInuseAuthKeyInfo(auth_key, key_type);
854 : }
855 : } else {
856 : // If there are no valid available keys but an older one is currently
857 : // installed, un-install it.
858 0 : if (inuse_authkey_type_ == AuthenticationData::MD5) {
859 0 : LogInstallAuthKeys("Listen", "delete", inuse_auth_key_,
860 : inuse_authkey_type_);
861 0 : ClearListenSocketAuthKey();
862 : // Resetting the key information must be done last.
863 0 : ResetInuseAuthKeyInfo();
864 : }
865 : }
866 0 : return true;
867 0 : }
868 :
869 0 : void BgpPeer::SetInuseAuthKeyInfo(const AuthenticationKey &key, KeyType type) {
870 0 : inuse_auth_key_ = key;
871 0 : inuse_authkey_type_ = type;
872 0 : }
873 :
874 0 : void BgpPeer::ResetInuseAuthKeyInfo() {
875 0 : inuse_auth_key_.Reset();
876 0 : inuse_authkey_type_ = AuthenticationData::NIL;
877 0 : }
878 :
879 0 : void BgpPeer::SetListenSocketAuthKey(const AuthenticationKey &auth_key,
880 : KeyType key_type) {
881 0 : if (key_type == AuthenticationData::MD5) {
882 0 : server_->session_manager()->
883 0 : SetListenSocketMd5Option(PeerAddress(), auth_key.value);
884 : }
885 0 : }
886 :
887 687 : void BgpPeer::ClearListenSocketAuthKey() {
888 687 : if (inuse_authkey_type_ == AuthenticationData::MD5) {
889 0 : server_->session_manager()->SetListenSocketMd5Option(PeerAddress(), "");
890 : }
891 687 : }
892 :
893 1893 : void BgpPeer::SetSessionSocketAuthKey(TcpSession *session) {
894 1893 : if ((inuse_authkey_type_ == AuthenticationData::MD5) && PeerAddress()) {
895 0 : assert(!inuse_auth_key_.value.empty());
896 0 : LogInstallAuthKeys("Session", "add", inuse_auth_key_,
897 : inuse_authkey_type_);
898 0 : session->SetMd5SocketOption(PeerAddress(), inuse_auth_key_.value);
899 : }
900 1893 : }
901 :
902 737 : void BgpPeer::SetSessionSocketOptionDscp(TcpSession *session) {
903 737 : uint8_t dscp_value = server_->global_qos()->control_dscp();
904 :
905 737 : if (!session->socket()) {
906 0 : return;
907 : }
908 737 : if (dscp_value != 0xFF) {
909 737 : session->SetDscpSocketOption(server_->global_qos()->control_dscp());
910 : }
911 : }
912 :
913 0 : string BgpPeer::GetInuseAuthKeyValue() const {
914 0 : return inuse_auth_key_.value;
915 : }
916 :
917 0 : void BgpPeer::LogInstallAuthKeys(const string &socket_name,
918 : const string &oper, const AuthenticationKey &auth_key,
919 : KeyType key_type) {
920 0 : string logstr = socket_name + " socket kernel " + oper + " of key id "
921 0 : + integerToString(auth_key.id) + ", type "
922 0 : + AuthenticationData::KeyTypeToString(key_type)
923 0 : + ", peer " + peer_name_;
924 0 : BGP_LOG_PEER(Config, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
925 : BGP_PEER_DIR_NA, logstr);
926 0 : }
927 :
928 : //
929 : // Check if the configured prefix limit for any address family has been
930 : // exceeded. If yes, clear the peer by sending a notification with a cease
931 : // subcode of MaxPrefixes.
932 : //
933 1048 : bool BgpPeer::CheckPrefixLimits() {
934 1048 : RetryDelete();
935 1049 : if (!IsReady())
936 891 : return true;
937 1701 : for (size_t idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
938 : BgpPeerFamilyAttributes *family_attributes =
939 1544 : family_attributes_list_[idx];
940 1544 : if (!family_attributes || family_attributes->prefix_limit == 0)
941 1544 : continue;
942 0 : if (family_primary_path_count_[idx] <= family_attributes->prefix_limit)
943 0 : continue;
944 0 : Clear(BgpProto::Notification::MaxPrefixes);
945 0 : StartPrefixLimitIdleTimer(family_attributes->idle_timeout * 1000);
946 0 : break;
947 : }
948 156 : return true;
949 : }
950 :
951 : //
952 : // Process family attributes configuration and update the family attributes
953 : // list.
954 : //
955 : // Return true is there's a change, false otherwise.
956 : //
957 1746 : bool BgpPeer::ProcessFamilyAttributesConfig(const BgpNeighborConfig *config) {
958 1746 : FamilyAttributesList family_attributes_list(Address::NUM_FAMILIES);
959 7006 : BOOST_FOREACH(const BgpFamilyAttributesConfig family_config,
960 : config->family_attributes_list()) {
961 : Address::Family family =
962 2630 : Address::FamilyFromString(family_config.family);
963 2630 : assert(family != Address::UNSPEC);
964 : BgpPeerFamilyAttributes *family_attributes =
965 2630 : new BgpPeerFamilyAttributes(config, family_config);
966 2630 : family_attributes_list[family] = family_attributes;
967 2630 : }
968 :
969 1746 : int ret = STLSortedCompare(
970 : family_attributes_list.begin(), family_attributes_list.end(),
971 : family_attributes_list_.begin(), family_attributes_list_.end(),
972 : BgpPeerFamilyAttributesCompare());
973 1746 : STLDeleteValues(&family_attributes_list_);
974 1746 : family_attributes_list_ = family_attributes_list;
975 1746 : configured_families_ = config->GetAddressFamilies();
976 1746 : return (ret != 0);
977 1746 : }
978 :
979 1746 : void BgpPeer::ProcessEndpointConfig(const BgpNeighborConfig *config) {
980 1746 : if (config->router_type() == "bgpaas-client") {
981 0 : endpoint_ = TcpSession::Endpoint(Ip4Address(), config->source_port());
982 : } else {
983 1746 : endpoint_ = TcpSession::Endpoint();
984 : }
985 1746 : }
986 :
987 1050 : void BgpPeer::TriggerPrefixLimitCheck() const {
988 1050 : prefix_limit_trigger_.Set();
989 1050 : }
990 :
991 1062 : void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
992 1062 : if (IsDeleted())
993 0 : return;
994 :
995 1062 : config_ = config;
996 :
997 : // During peer deletion, configuration gets completely deleted. In that
998 : // case, there is no need to update the rest and flap the peer.
999 1062 : if (!config_)
1000 0 : return;
1001 :
1002 1062 : bool clear_session = false;
1003 1062 : bool admin_down_changed = false;
1004 2124 : BgpPeerInfoData peer_info;
1005 1062 : peer_info.set_name(ToUVEKey());
1006 :
1007 1062 : if (admin_down_ != config->admin_down()) {
1008 120 : SetAdminState(config->admin_down());
1009 120 : peer_info.set_admin_down(admin_down_);
1010 120 : admin_down_changed = true;
1011 : }
1012 :
1013 1062 : if (passive_ != config->passive()) {
1014 24 : passive_ = config->passive();
1015 24 : peer_info.set_passive(passive_);
1016 24 : clear_session = true;
1017 : }
1018 :
1019 1062 : if (as_override_ != config->as_override()) {
1020 0 : as_override_ = config->as_override();
1021 0 : peer_info.set_as_override(as_override_);
1022 0 : clear_session = true;
1023 : }
1024 :
1025 1062 : if (cluster_id_ != config->cluster_id()) {
1026 0 : cluster_id_ = config->cluster_id();
1027 0 : peer_info.set_cluster_id(Ip4Address(cluster_id_).to_string());
1028 0 : clear_session = true;
1029 : }
1030 :
1031 1062 : OriginOverride origin_override(config->origin_override());
1032 1062 : if (origin_override_ != origin_override) {
1033 0 : origin_override_ = origin_override;
1034 0 : peer_info.set_origin_override(origin_override_.origin_override);
1035 0 : if (origin_override_.origin_override) {
1036 0 : peer_info.set_route_origin(config->origin_override().origin);
1037 : } else {
1038 0 : peer_info.set_route_origin("-");
1039 : }
1040 0 : clear_session = true;
1041 : }
1042 :
1043 1062 : if (router_type_ != config->router_type()) {
1044 0 : router_type_ = config->router_type();
1045 0 : peer_info.set_router_type(router_type_);
1046 0 : resolve_paths_ = (config->router_type() == "bgpaas-client");
1047 0 : clear_session = true;
1048 : }
1049 2124 : if (router_type_ == "control-node" ||
1050 1062 : router_type_ == "external-control-node") {
1051 0 : peer_is_control_node_ = true;
1052 : } else {
1053 1062 : peer_is_control_node_ = false;
1054 : }
1055 :
1056 : // Check if there is any change in the peer address.
1057 : // If the peer address is changing, remove the key for the older address.
1058 : // Update with the new peer address and then process the key chain info
1059 : // for the new peer below.
1060 1062 : BgpPeerKey key(config);
1061 1062 : if (peer_key_ != key) {
1062 3 : ClearListenSocketAuthKey();
1063 3 : peer_key_ = key;
1064 3 : peer_info.set_peer_address(peer_key_.endpoint.address().to_string());
1065 3 : clear_session = true;
1066 : }
1067 1062 : if (ProcessAuthKeyChainConfig(config)) {
1068 0 : clear_session = true;
1069 : }
1070 :
1071 1062 : if (peer_port_ != config->source_port()) {
1072 0 : peer_port_ = config->source_port();
1073 0 : peer_info.set_peer_port(peer_port_);
1074 0 : clear_session = true;
1075 : }
1076 1062 : ProcessEndpointConfig(config);
1077 :
1078 1062 : if (local_as_ != config->local_as()) {
1079 72 : BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG,
1080 : BGP_LOG_FLAG_SYSLOG,
1081 : "Updated Local Autonomous System from " <<
1082 : local_as_ << " to " <<
1083 : config->local_as());
1084 :
1085 72 : local_as_ = config->local_as();
1086 72 : peer_info.set_local_asn(local_as_);
1087 72 : clear_session = true;
1088 : }
1089 :
1090 1062 : if (hold_time_ != config->hold_time()) {
1091 108 : BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG,
1092 : BGP_LOG_FLAG_SYSLOG,
1093 : "Updated Hold Time from " <<
1094 : hold_time_ << " to " <<
1095 : config->hold_time());
1096 :
1097 108 : hold_time_ = config->hold_time();
1098 108 : peer_info.set_hold_time(hold_time_);
1099 108 : clear_session = true;
1100 : }
1101 :
1102 1062 : if (peer_as_ != config->peer_as()) {
1103 72 : BGP_LOG_STR(BgpConfig, SandeshLevel::SYS_DEBUG,
1104 : BGP_LOG_FLAG_SYSLOG,
1105 : "Updated Peer Autonomous System from " <<
1106 : peer_as_ << " to " <<
1107 : config->peer_as());
1108 :
1109 72 : peer_as_ = config->peer_as();
1110 72 : peer_info.set_peer_asn(peer_as_);
1111 72 : clear_session = true;
1112 : }
1113 :
1114 1062 : boost::system::error_code ec;
1115 1062 : uint32_t local_bgp_id = config->local_identifier();
1116 1062 : if (local_bgp_id_ != local_bgp_id) {
1117 18 : local_bgp_id_ = local_bgp_id;
1118 18 : peer_info.set_local_id(local_bgp_id_);
1119 18 : clear_session = true;
1120 : }
1121 :
1122 1062 : BgpProto::BgpPeerType old_type = PeerType();
1123 1062 : peer_type_ = (peer_as_ == local_as_) ? BgpProto::IBGP : BgpProto::EBGP;
1124 1062 : if (old_type != PeerType()) {
1125 96 : peer_info.set_peer_type(
1126 48 : PeerType() == BgpProto::IBGP ? "internal" : "external");
1127 48 : clear_session = true;
1128 : }
1129 :
1130 : // Check if there is any change in private-as-action configuration.
1131 1062 : if (private_as_action_ != config->private_as_action()) {
1132 0 : private_as_action_ = config->private_as_action();
1133 0 : clear_session = true;
1134 : }
1135 :
1136 : // Check if there is any change in the configured address families.
1137 1062 : if (ProcessFamilyAttributesConfig(config)) {
1138 12 : peer_info.set_configured_families(configured_families_);
1139 12 : clear_session = true;
1140 : } else {
1141 1050 : TriggerPrefixLimitCheck();
1142 : }
1143 :
1144 : // Note that the state machine would have been stopped via SetAdminDown
1145 : // if admin down was set to true above. Further, it's not necessary to
1146 : // clear the peer if it's already admin down.
1147 1062 : if (!admin_down_changed && !admin_down_ && clear_session) {
1148 258 : BGP_LOG_PEER(Config, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
1149 : BGP_PEER_DIR_NA,
1150 : "Session cleared due to configuration change");
1151 258 : Clear(BgpProto::Notification::OtherConfigChange);
1152 : }
1153 :
1154 : // Send the UVE as appropriate.
1155 1062 : if (admin_down_changed || clear_session) {
1156 378 : StopPrefixLimitIdleTimer();
1157 378 : BGPPeerInfoSend(peer_info);
1158 : }
1159 1062 : }
1160 :
1161 6 : void BgpPeer::ClearConfig() {
1162 6 : CHECK_CONCURRENCY("bgp::Config");
1163 6 : config_ = NULL;
1164 6 : }
1165 :
1166 1125 : LifetimeActor *BgpPeer::deleter() {
1167 1125 : return deleter_.get();
1168 : }
1169 :
1170 : //
1171 : // Check if the given address family has been negotiated with the peer.
1172 : //
1173 62451 : bool BgpPeer::IsFamilyNegotiated(Address::Family family) {
1174 : // Bail if the family is not configured locally.
1175 62451 : if (!LookupFamily(family))
1176 8537 : return false;
1177 :
1178 : // Check if the peer advertised it in his Open message.
1179 : uint16_t afi;
1180 : uint8_t safi;
1181 53914 : tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
1182 53913 : return MpNlriAllowed(afi, safi);
1183 : }
1184 :
1185 : // Release resources for a peer that is going to be deleted.
1186 684 : void BgpPeer::PostCloseRelease() {
1187 684 : if (index_ != -1) {
1188 684 : server_->UnregisterPeer(this);
1189 684 : index_ = -1;
1190 : }
1191 684 : TimerManager::DeleteTimer(keepalive_timer_);
1192 684 : TimerManager::DeleteTimer(prefix_limit_idle_timer_);
1193 :
1194 684 : for (Address::Family family = Address::UNSPEC;
1195 7524 : family < Address::NUM_FAMILIES;
1196 6840 : family = static_cast<Address::Family>(family + 1)) {
1197 6840 : TimerManager::DeleteTimer(eor_send_timer_[family]);
1198 6840 : TimerManager::DeleteTimer(eor_receive_timer_[family]);
1199 : }
1200 684 : }
1201 :
1202 : // IsReady
1203 : //
1204 : // Check whether this peer is up and ready
1205 : //
1206 98260 : bool BgpPeer::IsReady() const {
1207 98260 : return state_machine_->get_state() == StateMachine::ESTABLISHED;
1208 : }
1209 :
1210 64846 : bool BgpPeer::IsXmppPeer() const {
1211 64846 : return false;
1212 : }
1213 :
1214 0 : uint32_t BgpPeer::local_bgp_identifier() const {
1215 0 : return ntohl(local_bgp_id_);
1216 : }
1217 :
1218 0 : string BgpPeer::local_bgp_identifier_string() const {
1219 0 : return Ip4Address(ntohl(local_bgp_id_)).to_string();
1220 : }
1221 :
1222 688 : uint32_t BgpPeer::bgp_identifier() const {
1223 688 : return ntohl(peer_bgp_id_);
1224 : }
1225 :
1226 0 : string BgpPeer::bgp_identifier_string() const {
1227 0 : return Ip4Address(ntohl(peer_bgp_id_)).to_string();
1228 : }
1229 :
1230 0 : string BgpPeer::transport_address_string() const {
1231 0 : TcpSession::Endpoint endpoint;
1232 0 : ostringstream oss;
1233 0 : if (session_)
1234 0 : endpoint = session_->remote_endpoint();
1235 0 : oss << endpoint;
1236 0 : return oss.str();
1237 0 : }
1238 :
1239 0 : string BgpPeer::gateway_address_string(Address::Family family) const {
1240 0 : if (!family_attributes_list_[family])
1241 0 : return string();
1242 0 : return family_attributes_list_[family]->gateway_address.to_string();
1243 : }
1244 :
1245 : //
1246 : // Customized close routing for BgpPeers.
1247 : //
1248 : // Reset all stored capabilities information and cancel outstanding timers.
1249 : //
1250 2092 : void BgpPeer::CustomClose() {
1251 2092 : ResetCapabilities();
1252 2092 : keepalive_timer_->Cancel();
1253 :
1254 2092 : for (Address::Family family = Address::UNSPEC;
1255 23012 : family < Address::NUM_FAMILIES;
1256 20920 : family = static_cast<Address::Family>(family + 1)) {
1257 20920 : eor_send_timer_[family]->Cancel();
1258 20920 : eor_receive_timer_[family]->Cancel();
1259 : }
1260 :
1261 2092 : if (close_manager_->IsInDeleteState())
1262 1684 : DeleteRTargets(server_->local_autonomous_system());
1263 2092 : }
1264 :
1265 : //
1266 : // Close this peer by closing all of it's RIBs.
1267 : //
1268 2112 : void BgpPeer::Close(bool graceful) {
1269 2112 : send_ready_ = true;
1270 2112 : if (membership_req_pending_ && !close_manager_->IsMembershipInUse()) {
1271 8 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
1272 : BGP_PEER_DIR_NA, "Close procedure deferred");
1273 8 : defer_close_ = true;
1274 :
1275 : // Note down non-graceful closures. Once a close is non-graceful,
1276 : // it shall remain as non-graceful.
1277 8 : graceful_close_ &= graceful;
1278 8 : return;
1279 : }
1280 :
1281 2104 : peer_close_->Close(graceful);
1282 : }
1283 :
1284 0 : IPeerClose *BgpPeer::peer_close() {
1285 0 : return peer_close_.get();
1286 : }
1287 :
1288 17213 : IPeerClose *BgpPeer::peer_close() const {
1289 17213 : return peer_close_.get();
1290 : }
1291 :
1292 17213 : void BgpPeer::UpdateCloseRouteStats(Address::Family family,
1293 : const BgpPath *old_path, uint32_t path_flags) const {
1294 17213 : peer_close()->UpdateRouteStats(family, old_path, path_flags);
1295 17214 : }
1296 :
1297 18278 : IPeerDebugStats *BgpPeer::peer_stats() {
1298 18278 : return peer_stats_.get();
1299 : }
1300 :
1301 0 : const IPeerDebugStats *BgpPeer::peer_stats() const {
1302 0 : return peer_stats_.get();
1303 : }
1304 :
1305 1014 : void BgpPeer::Clear(int subcode) {
1306 1014 : CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine");
1307 1014 : state_machine_->Shutdown(subcode);
1308 1014 : }
1309 :
1310 : //
1311 : // Check whether this peer has been marked for deletion from configuration
1312 : //
1313 7821 : bool BgpPeer::IsDeleted() const {
1314 7821 : return deleter_->IsDeleted();
1315 : }
1316 :
1317 127 : bool BgpPeer::IsInGRTimerWaitState() const {
1318 127 : return close_manager_->IsInGRTimerWaitState();
1319 : }
1320 :
1321 4057 : bool BgpPeer::IsCloseInProgress() const {
1322 4057 : CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine");
1323 :
1324 : // trigger is set only after defer_close is reset
1325 4057 : assert(!(defer_close_ && trigger_.IsSet()));
1326 8159 : return defer_close_ || trigger_.IsSet() ||
1327 4039 : (close_manager_->IsCloseInProgress() &&
1328 4120 : !IsInGRTimerWaitState());
1329 : }
1330 :
1331 3247 : StateMachine::State BgpPeer::GetState() const {
1332 3247 : return state_machine_->get_state();
1333 : }
1334 :
1335 0 : const string BgpPeer::GetStateName() const {
1336 0 : return state_machine_->StateName();
1337 : }
1338 :
1339 1228 : BgpSession *BgpPeer::CreateSession() {
1340 1228 : if (PrefixLimitIdleTimerRunning())
1341 0 : return NULL;
1342 :
1343 1228 : TcpSession *session = server_->session_manager()->CreateSession();
1344 1228 : if (session == NULL)
1345 72 : return NULL;
1346 :
1347 : // Set valid keys, if any, in the socket.
1348 1156 : SetSessionSocketAuthKey(session);
1349 :
1350 1156 : BgpSession *bgp_session = static_cast<BgpSession *>(session);
1351 1156 : BindLocalEndpoint(bgp_session);
1352 1156 : bgp_session->set_peer(this);
1353 1156 : return bgp_session;
1354 : }
1355 :
1356 232 : void BgpPeer::SetAdminState(bool down, int subcode) {
1357 232 : CHECK_CONCURRENCY("bgp::Config");
1358 232 : if (admin_down_ == down)
1359 0 : return;
1360 232 : admin_down_ = down;
1361 232 : state_machine_->SetAdminState(down, subcode);
1362 232 : if (admin_down_) {
1363 126 : BGP_LOG_PEER(Config, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
1364 : BGP_PEER_DIR_NA, "Session cleared due to admin down");
1365 : }
1366 : }
1367 :
1368 737 : bool BgpPeer::AcceptSession(BgpSession *session) {
1369 737 : session->set_peer(this);
1370 :
1371 : // Set valid keys, if any, in the socket.
1372 737 : SetSessionSocketAuthKey(session);
1373 :
1374 : // Set control dscp, if any
1375 737 : SetSessionSocketOptionDscp(session);
1376 :
1377 737 : return state_machine_->PassiveOpen(session);
1378 : }
1379 :
1380 1677 : void BgpPeer::Register(BgpTable *table, const RibExportPolicy &policy) {
1381 : // In a highly corner case scenario, GR timer could fire right after a
1382 : // session comes back up. In that case, CloseManager possibly could still
1383 : // be using membership manager. Instead of creating a queue of these
1384 : // register requests until close manager is done processing and process
1385 : // them later, we could just as well just reset the session.
1386 1677 : if (close_manager_->IsMembershipInUse()) {
1387 0 : BGP_LOG_PEER(Config, this, SandeshLevel::SYS_NOTICE, BGP_LOG_FLAG_ALL,
1388 : BGP_PEER_DIR_IN, "Session cleared due to GR not ready");
1389 0 : Close(true);
1390 : }
1391 :
1392 1678 : if (close_manager_->IsMembershipInWait())
1393 0 : assert(membership_req_pending_ > 0);
1394 1678 : BgpMembershipManager *membership_mgr = server_->membership_mgr();
1395 1677 : membership_req_pending_++;
1396 1686 : membership_mgr->Register(this, table, policy);
1397 :
1398 : // Start EndOfRib receive timer.
1399 1686 : StartEndOfRibReceiveTimer(table->family());
1400 1686 : }
1401 :
1402 440 : void BgpPeer::Register(BgpTable *table) {
1403 440 : if (close_manager_->IsMembershipInUse()) {
1404 0 : BGP_LOG_PEER(Config, this, SandeshLevel::SYS_NOTICE, BGP_LOG_FLAG_ALL,
1405 : BGP_PEER_DIR_IN, "Session cleared due to GR not ready");
1406 0 : Close(true);
1407 : }
1408 :
1409 440 : if (close_manager_->IsMembershipInWait())
1410 0 : assert(membership_req_pending_ > 0);
1411 440 : BgpMembershipManager *membership_mgr = server_->membership_mgr();
1412 440 : membership_mgr->RegisterRibIn(this, table);
1413 :
1414 : // Start EndOfRib receive timer.
1415 440 : StartEndOfRibReceiveTimer(table->family());
1416 440 : }
1417 :
1418 : //
1419 : // Register to tables for negotiated address families.
1420 : //
1421 : // If the route-target family is negotiated, defer ribout registration
1422 : // to VPN tables till we receive End-Of-RIB marker for the route-target
1423 : // NLRI or till the EndOfRibTimer expires. This ensures that we do not
1424 : // start sending VPN routes to the peer till we know what route targets
1425 : // the peer is interested in.
1426 : //
1427 : // Note that we do ribin registration right away even if the route-target
1428 : // family is negotiated. This allows received VPN routes to be processed
1429 : // normally before ribout registration to VPN tables is completed.
1430 : //
1431 1114 : void BgpPeer::RegisterAllTables() {
1432 1114 : RoutingInstance *instance = GetRoutingInstance();
1433 :
1434 1114 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
1435 : BGP_PEER_DIR_NA, "Established");
1436 :
1437 : vector<Address::Family> family_list = list_of
1438 1114 : (Address::INET)(Address::INETMPLS)(Address::INET6);
1439 7787 : BOOST_FOREACH(Address::Family family, family_list) {
1440 3335 : if (!IsFamilyNegotiated(family))
1441 2450 : continue;
1442 892 : BgpTable *table = instance->GetTable(family);
1443 888 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
1444 : table, "Register peer with the table");
1445 888 : Register(table, BuildRibExportPolicy(family));
1446 : }
1447 :
1448 :
1449 2228 : if (((router_type_ == "bgpaas-client") ||
1450 2228 : (router_type_ == "bgpaas-server")) &&
1451 0 : (instance->routing_instance_vxlan() != "")) {
1452 0 : RoutingInstanceMgr *mgr = server()->routing_instance_mgr();
1453 0 : if (mgr != nullptr) {
1454 : RoutingInstance *vxlan_ri =
1455 0 : mgr->GetRoutingInstance(instance->routing_instance_vxlan());
1456 0 : if (vxlan_ri != nullptr) {
1457 0 : BgpTable *table = vxlan_ri->GetTable(Address::EVPN);
1458 0 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_TRACE,
1459 : table, "Register ribin for peer with the table");
1460 0 : Register(table);
1461 : }
1462 : }
1463 : }
1464 :
1465 1114 : vpn_tables_registered_ = false;
1466 1114 : if (!IsFamilyNegotiated(Address::RTARGET)) {
1467 1004 : RegisterToVpnTables();
1468 1003 : return;
1469 : }
1470 :
1471 110 : Address::Family family = Address::RTARGET;
1472 110 : BgpTable *table = instance->GetTable(family);
1473 165 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
1474 : table, "Register peer with the table");
1475 110 : Register(table, BuildRibExportPolicy(family));
1476 :
1477 : vector<Address::Family> vpn_family_list = list_of
1478 110 : (Address::INETVPN)(Address::INET6VPN)(Address::ERMVPN)(Address::EVPN)
1479 110 : (Address::MVPN);
1480 1210 : BOOST_FOREACH(Address::Family vpn_family, vpn_family_list) {
1481 550 : if (!IsFamilyNegotiated(vpn_family))
1482 110 : continue;
1483 440 : BgpTable *table = instance->GetTable(vpn_family);
1484 660 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_TRACE,
1485 : table, "Register ribin for peer with the table");
1486 440 : Register(table);
1487 : }
1488 1113 : }
1489 :
1490 : const vector<Address::Family> BgpPeer::supported_families_ = list_of
1491 : (Address::INET)
1492 : (Address::INETMPLS)
1493 : (Address::INETVPN)
1494 : (Address::EVPN)
1495 : (Address::RTARGET)
1496 : (Address::ERMVPN)
1497 : (Address::MVPN)
1498 : (Address::INET6)
1499 : (Address::INET6VPN);
1500 :
1501 1670 : void BgpPeer::SendOpen(TcpSession *session) {
1502 1670 : BgpProto::OpenMessage openmsg;
1503 1670 : openmsg.as_num = local_as_ > 0xffff ? AS_TRANS : local_as_;
1504 1670 : openmsg.holdtime = state_machine_->GetConfiguredHoldTime();
1505 1670 : openmsg.identifier = ntohl(local_bgp_id_);
1506 : BgpProto::OpenMessage::OptParam *opt_param =
1507 1670 : new BgpProto::OpenMessage::OptParam;
1508 :
1509 : static const uint8_t cap_mp[][4] = {
1510 3 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[0]), 0,
1511 3 : BgpAf::FamilyToSafi(supported_families_[0]) },
1512 3 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[1]), 0,
1513 3 : BgpAf::FamilyToSafi(supported_families_[1]) },
1514 3 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[2]), 0,
1515 3 : BgpAf::FamilyToSafi(supported_families_[2]) },
1516 3 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[3]), 0,
1517 3 : BgpAf::FamilyToSafi(supported_families_[3]) },
1518 3 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[4]), 0,
1519 3 : BgpAf::FamilyToSafi(supported_families_[4]) },
1520 3 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[5]), 0,
1521 3 : BgpAf::FamilyToSafi(supported_families_[5]) },
1522 3 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[6]), 0,
1523 3 : BgpAf::FamilyToSafi(supported_families_[6]) },
1524 3 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[7]), 0,
1525 3 : BgpAf::FamilyToSafi(supported_families_[7]) },
1526 3 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[8]), 0,
1527 3 : BgpAf::FamilyToSafi(supported_families_[8]) },
1528 1724 : };
1529 :
1530 : static const FamilyToCapabilityMap family_to_cap_map = map_list_of
1531 6 : (supported_families_[0], cap_mp[0])
1532 3 : (supported_families_[1], cap_mp[1])
1533 3 : (supported_families_[2], cap_mp[2])
1534 3 : (supported_families_[3], cap_mp[3])
1535 3 : (supported_families_[4], cap_mp[4])
1536 3 : (supported_families_[5], cap_mp[5])
1537 3 : (supported_families_[6], cap_mp[6])
1538 3 : (supported_families_[7], cap_mp[7])
1539 1673 : (supported_families_[8], cap_mp[8]);
1540 :
1541 : // Add capabilities for configured address families.
1542 31716 : BOOST_FOREACH(const FamilyToCapabilityMap::value_type &val,
1543 : family_to_cap_map) {
1544 15022 : if (!LookupFamily(val.first))
1545 11573 : continue;
1546 : BgpProto::OpenMessage::Capability *cap =
1547 : new BgpProto::OpenMessage::Capability(
1548 3449 : BgpProto::OpenMessage::Capability::MpExtension, val.second, 4);
1549 3452 : opt_param->capabilities.push_back(cap);
1550 : }
1551 :
1552 1670 : if (server_->enable_4byte_as()) {
1553 42 : uint32_t asn = ntohl(local_as_);
1554 : BgpProto::OpenMessage::Capability *cap =
1555 : new BgpProto::OpenMessage::Capability(
1556 : BgpProto::OpenMessage::Capability::AS4Support,
1557 42 : (const uint8_t *)(&asn), 4);
1558 42 : opt_param->capabilities.push_back(cap);
1559 : }
1560 1670 : peer_close_->AddGRCapabilities(opt_param);
1561 1670 : peer_close_->AddLLGRCapabilities(opt_param);
1562 :
1563 1670 : if (opt_param->capabilities.size()) {
1564 1670 : openmsg.opt_params.push_back(opt_param);
1565 : } else {
1566 0 : delete opt_param;
1567 : }
1568 : uint8_t data[256];
1569 1670 : int result = BgpProto::Encode(&openmsg, data, sizeof(data));
1570 1670 : assert(result > BgpProto::kMinMessageSize);
1571 1670 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
1572 : BGP_PEER_DIR_OUT, "Open " << openmsg.ToString());
1573 1670 : session->Send(data, result, NULL);
1574 1670 : inc_tx_open();
1575 1670 : }
1576 :
1577 1548 : void BgpPeer::SendKeepalive(bool from_timer) {
1578 1548 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
1579 :
1580 : // Bail if there's no session for the peer anymore.
1581 1549 : if (!session_)
1582 0 : return;
1583 :
1584 1549 : BgpProto::Keepalive msg;
1585 : uint8_t data[BgpProto::kMinMessageSize];
1586 1549 : int result = BgpProto::Encode(&msg, data, sizeof(data));
1587 1544 : assert(result == BgpProto::kMinMessageSize);
1588 1544 : SandeshLevel::type log_level = from_timer ? Sandesh::LoggingUtLevel() :
1589 1545 : SandeshLevel::SYS_INFO;
1590 1545 : BGP_LOG_PEER(Message, this, log_level, BGP_LOG_FLAG_SYSLOG,
1591 : BGP_PEER_DIR_OUT, "Keepalive");
1592 1545 : send_ready_ = session_->Send(data, result, NULL);
1593 1550 : inc_tx_keepalive();
1594 1550 : }
1595 :
1596 13846 : static bool SkipUpdateSend() {
1597 : static bool init_;
1598 : static bool skip_;
1599 :
1600 13846 : if (init_) return skip_;
1601 :
1602 3 : skip_ = getenv("BGP_SKIP_UPDATE_SEND") != NULL;
1603 3 : init_ = true;
1604 :
1605 3 : return skip_;
1606 : }
1607 :
1608 1746 : BgpPeer::OriginOverride::OriginOverride(
1609 1746 : const BgpNeighborConfig::OriginOverrideConfig &config)
1610 1746 : : origin_override(config.origin_override),
1611 1746 : origin(BgpAttr::OriginFromString(config.origin)) {
1612 1746 : }
1613 :
1614 1062 : bool BgpPeer::OriginOverride::operator!=(const OriginOverride &rhs) const {
1615 1062 : if (origin_override != rhs.origin_override) {
1616 0 : return true;
1617 : }
1618 :
1619 : // compare origin only if override is set
1620 1062 : if (origin_override && origin != rhs.origin) {
1621 0 : return true;
1622 : }
1623 1062 : return false;
1624 : }
1625 :
1626 : //
1627 : // Accumulate the message in the update buffer.
1628 : // Flush the existing buffer if the message can't fit.
1629 : // Note that FlushUpdateUnlocked clears the buffer.
1630 : //
1631 17165 : bool BgpPeer::SendUpdate(const uint8_t *msg, size_t msgsize,
1632 : const string *msg_str) {
1633 17165 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
1634 17166 : bool send_ready = true;
1635 17166 : if (buffer_.size() + msgsize > buffer_capacity_) {
1636 0 : send_ready = FlushUpdateUnlocked();
1637 0 : assert(buffer_.empty());
1638 : }
1639 17166 : buffer_.insert(buffer_.end(), msg, msg + msgsize);
1640 17166 : inc_tx_update();
1641 17166 : return send_ready;
1642 17166 : }
1643 :
1644 15935 : bool BgpPeer::FlushUpdateUnlocked() {
1645 : // Bail if the update buffer is empty.
1646 15935 : if (buffer_.empty())
1647 471 : return true;
1648 :
1649 : // Bail if there's no session for the peer anymore.
1650 15464 : if (!session_) {
1651 1618 : buffer_.clear();
1652 1618 : return true;
1653 : }
1654 :
1655 13846 : if (!SkipUpdateSend()) {
1656 13846 : send_ready_ = session_->Send(buffer_.data(), buffer_.size(), NULL);
1657 13847 : buffer_.clear();
1658 13847 : if (send_ready_) {
1659 13847 : StartKeepaliveTimerUnlocked();
1660 : } else {
1661 0 : StopKeepaliveTimerUnlocked();
1662 : }
1663 : } else {
1664 0 : send_ready_ = true;
1665 : }
1666 :
1667 13847 : if (!send_ready_) {
1668 0 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
1669 : BGP_PEER_DIR_NA, "Send blocked");
1670 : }
1671 13847 : return send_ready_;
1672 : }
1673 :
1674 15927 : bool BgpPeer::FlushUpdate() {
1675 15927 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
1676 31871 : return FlushUpdateUnlocked();
1677 15936 : }
1678 :
1679 758 : bool BgpPeer::notification() const {
1680 758 : return peer_close_->gr_params().notification();
1681 : }
1682 :
1683 : // Check if GR Helper mode sould be attempted.
1684 2112 : bool BgpPeer::AttemptGRHelperMode(int code, int subcode) const {
1685 2112 : if (!code)
1686 402 : return true;
1687 :
1688 1710 : if (code == BgpProto::Notification::Cease &&
1689 1663 : (subcode == BgpProto::Notification::HardReset ||
1690 : subcode == BgpProto::Notification::PeerDeconfigured)) {
1691 951 : return false;
1692 : }
1693 :
1694 : // If Peer supports Notification (N) bit, then attempt GR-Helper for all
1695 : // other notifications, not otherwise.
1696 759 : return notification();
1697 : }
1698 :
1699 862 : void BgpPeer::SendNotification(BgpSession *session,
1700 : int code, int subcode, const string &data) {
1701 862 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
1702 863 : session->SendNotification(code, subcode, data);
1703 865 : state_machine_->set_last_notification_out(code, subcode, data);
1704 865 : inc_tx_notification();
1705 865 : }
1706 :
1707 1115 : bool BgpPeer::SetCapabilities(const BgpProto::OpenMessage *msg) {
1708 1115 : peer_bgp_id_ = htonl(msg->identifier);
1709 1115 : capabilities_.clear();
1710 1115 : vector<BgpProto::OpenMessage::OptParam *>::const_iterator it;
1711 2230 : for (it = msg->opt_params.begin(); it < msg->opt_params.end(); ++it) {
1712 1115 : capabilities_.insert(capabilities_.end(), (*it)->capabilities.begin(),
1713 1115 : (*it)->capabilities.end());
1714 1115 : (*it)->capabilities.clear();
1715 : }
1716 :
1717 1115 : as4_supported_ = false;
1718 1115 : if (server_->enable_4byte_as()) {
1719 24 : vector<BgpProto::OpenMessage::Capability *>::iterator c_it;
1720 48 : for (c_it = capabilities_.begin(); c_it < capabilities_.end(); ++c_it) {
1721 48 : if ((*c_it)->code ==BgpProto::OpenMessage::Capability::AS4Support) {
1722 24 : as4_supported_ = true;
1723 24 : break;
1724 : }
1725 : }
1726 : }
1727 2230 : BgpPeerInfoData peer_info;
1728 1115 : peer_info.set_name(ToUVEKey());
1729 1115 : peer_info.set_peer_id(peer_bgp_id_);
1730 :
1731 1114 : vector<string> families;
1732 1114 : vector<BgpProto::OpenMessage::Capability *>::iterator cap_it;
1733 4088 : for (cap_it = capabilities_.begin(); cap_it < capabilities_.end();
1734 2974 : ++cap_it) {
1735 2973 : if ((*cap_it)->code != BgpProto::OpenMessage::Capability::MpExtension)
1736 1251 : continue;
1737 1722 : uint8_t *data = (*cap_it)->capability.data();
1738 1722 : uint16_t afi = get_value(data, 2);
1739 1722 : uint8_t safi = get_value(data + 3, 1);
1740 1722 : Address::Family family = BgpAf::AfiSafiToFamily(afi, safi);
1741 1722 : if (family == Address::UNSPEC) {
1742 0 : families.push_back(BgpAf::ToString(afi, safi));
1743 : } else {
1744 1722 : families.push_back(Address::FamilyToString(family));
1745 : }
1746 : }
1747 1115 : peer_info.set_families(families);
1748 :
1749 1114 : negotiated_families_.clear();
1750 12228 : for (int idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
1751 11115 : if (!family_attributes_list_[idx])
1752 9431 : continue;
1753 1720 : Address::Family family = static_cast<Address::Family>(idx);
1754 : uint16_t afi;
1755 : uint8_t safi;
1756 1720 : tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
1757 1722 : if (!MpNlriAllowed(afi, safi))
1758 36 : continue;
1759 1686 : negotiated_families_.push_back(Address::FamilyToString(family));
1760 : }
1761 1113 : sort(negotiated_families_.begin(), negotiated_families_.end());
1762 1111 : peer_info.set_negotiated_families(negotiated_families_);
1763 :
1764 : // Process GR/LLGR capabilities and close non-gracefully if any ongoing GR
1765 : // needs be aborted.
1766 1114 : if (!peer_close_->SetGRCapabilities(&peer_info)) {
1767 0 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
1768 : BGP_PEER_DIR_IN, "Close non-gracefully");
1769 0 : Close(false);
1770 0 : return false;
1771 : }
1772 1108 : return true;
1773 1108 : }
1774 :
1775 : // Reset capabilities stored inside peer structure.
1776 : //
1777 : // When open message is processed, we directly take the capabilities off the
1778 : // open message and store inside the peer structure.
1779 : //
1780 2092 : void BgpPeer::ResetCapabilities() {
1781 2092 : STLDeleteValues(&capabilities_);
1782 4184 : BgpPeerInfoData peer_info;
1783 2092 : peer_info.set_name(ToUVEKey());
1784 2092 : vector<string> families = vector<string>();
1785 2092 : peer_info.set_families(families);
1786 2092 : vector<string> negotiated_families = vector<string>();
1787 2092 : peer_info.set_negotiated_families(negotiated_families);
1788 2092 : peer_info.set_graceful_restart_families(vector<string>());
1789 2092 : BGPPeerInfoSend(peer_info);
1790 2092 : }
1791 :
1792 55631 : bool BgpPeer::MpNlriAllowed(uint16_t afi, uint8_t safi) {
1793 55631 : vector<BgpProto::OpenMessage::Capability *>::iterator it;
1794 145333 : for (it = capabilities_.begin(); it < capabilities_.end(); ++it) {
1795 145230 : if ((*it)->code != BgpProto::OpenMessage::Capability::MpExtension)
1796 108 : continue;
1797 145122 : uint8_t *data = (*it)->capability.data();
1798 145119 : uint16_t af_value = get_value(data, 2);
1799 145121 : uint8_t safi_value = get_value(data + 3, 1);
1800 145118 : if (afi == af_value && safi == safi_value) {
1801 55524 : return true;
1802 : }
1803 : }
1804 108 : return false;
1805 : }
1806 :
1807 22692 : bool BgpPeer::Is4ByteAsSupported() const {
1808 22692 : return as4_supported_;
1809 : }
1810 :
1811 : template <typename TableT, typename PrefixT>
1812 15508 : void BgpPeer::ProcessNlri(Address::Family family, DBRequest::DBOperation oper,
1813 : const BgpMpNlri *nlri, BgpAttrPtr attr, uint32_t flags) {
1814 15508 : TableT *table = static_cast<TableT *>(rtinstance_->GetTable(family));
1815 15508 : assert(table);
1816 :
1817 34744 : for (vector<BgpProtoPrefix *>::const_iterator it = nlri->nlri.begin();
1818 34744 : it != nlri->nlri.end(); ++it) {
1819 19236 : PrefixT prefix;
1820 19236 : BgpAttrPtr new_attr(attr);
1821 19236 : uint32_t label = 0;
1822 19236 : uint32_t l3_label = 0;
1823 35014 : int result = PrefixT::FromProtoPrefix(server_, **it,
1824 15778 : (oper == DBRequest::DB_ENTRY_ADD_CHANGE ? attr.get() : NULL),
1825 : family, &prefix, &new_attr, &label, &l3_label);
1826 19236 : if (result) {
1827 0 : BGP_LOG_PEER_WARNING(Message, this,
1828 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN,
1829 : "MP NLRI parse error for " <<
1830 : Address::FamilyToString(family) << " route");
1831 0 : continue;
1832 0 : }
1833 :
1834 19236 : DBRequest req;
1835 19236 : req.oper = oper;
1836 19236 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
1837 15778 : req.data.reset(new typename TableT::RequestData(
1838 : new_attr, flags, label, l3_label, 0));
1839 : }
1840 19236 : req.key.reset(new typename TableT::RequestKey(prefix, this));
1841 19236 : table->Enqueue(&req);
1842 : }
1843 15508 : }
1844 :
1845 : template <typename PrefixT>
1846 0 : void BgpPeer::ProcessNlriBgpaas(Address::Family family, DBRequest::DBOperation oper,
1847 : const BgpMpNlri *nlri, BgpAttrPtr attr, uint32_t flags) {
1848 :
1849 0 : for (vector<BgpProtoPrefix *>::const_iterator it = nlri->nlri.begin();
1850 0 : it != nlri->nlri.end(); ++it) {
1851 0 : PrefixT prefix;
1852 0 : BgpAttrPtr new_attr(attr);
1853 0 : uint32_t label = 0;
1854 0 : uint32_t l3_label = 0;
1855 0 : int result = PrefixT::FromProtoPrefix(server_, **it,
1856 0 : (oper == DBRequest::DB_ENTRY_ADD_CHANGE ? attr.get() : NULL),
1857 : family, &prefix, &new_attr, &label, &l3_label);
1858 0 : if (result) {
1859 0 : BGP_LOG_PEER_WARNING(Message, this,
1860 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN,
1861 : "MP NLRI parse error for " <<
1862 : Address::FamilyToString(family) << " route");
1863 0 : continue;
1864 0 : }
1865 :
1866 0 : ProcessBgpaas(oper, prefix.addr(), prefix.prefixlen(), new_attr, flags);
1867 : }
1868 0 : }
1869 :
1870 0 : void BgpPeer::ProcessBgpaas(DBRequest::DBOperation oper,
1871 : IpAddress addr, uint8_t addr_len, BgpAttrPtr attr, uint32_t flags) {
1872 :
1873 0 : if (rtinstance_->routing_instance_vxlan() == "") {
1874 0 : return;
1875 : }
1876 0 : RoutingInstanceMgr *mgr = server()->routing_instance_mgr();
1877 0 : if (mgr == nullptr) {
1878 0 : return;
1879 : }
1880 : RoutingInstance *vxlan_ri =
1881 0 : mgr->GetRoutingInstance(rtinstance_->routing_instance_vxlan());
1882 0 : if (vxlan_ri == nullptr) {
1883 0 : return;
1884 : }
1885 0 : EvpnTable *table = static_cast<EvpnTable *>(vxlan_ri->GetTable(Address::EVPN));
1886 0 : EvpnPrefix prefix_evpn(RouteDistinguisher::kZeroRd, addr, addr_len);
1887 :
1888 0 : DBRequest req;
1889 0 : req.oper = oper;
1890 0 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
1891 0 : req.data.reset(new EvpnTable::RequestData(attr, flags, 0, 0, 0));
1892 : }
1893 : else {
1894 0 : req.data.reset(NULL);
1895 : }
1896 0 : req.key.reset(new EvpnTable::RequestKey(prefix_evpn, this));
1897 0 : table->Enqueue(&req);
1898 0 : }
1899 :
1900 13156 : uint32_t BgpPeer::GetPathFlags(Address::Family family,
1901 : const BgpAttr *attr) const {
1902 13156 : uint32_t flags = resolve_paths_ ? BgpPath::ResolveNexthop : 0;
1903 :
1904 : // Check for OriginatorId loop in case we are an RR client.
1905 13186 : if (peer_type_ == BgpProto::IBGP &&
1906 30 : attr->originator_id().to_ulong() == ntohl(local_bgp_id_)) {
1907 0 : flags |= BgpPath::OriginatorIdLooped;
1908 : }
1909 :
1910 : // Check for ClusterList loop in case we are an RR.
1911 13156 : if (server_->cluster_id() && attr->cluster_list() &&
1912 0 : attr->cluster_list()->cluster_list().ClusterListLoop(
1913 0 : server_->cluster_id())) {
1914 0 : flags |= BgpPath::ClusterListLooped;
1915 : }
1916 :
1917 13156 : if (!attr->as_path() && !attr->aspath_4byte())
1918 0 : return flags;
1919 :
1920 : // Check whether neighbor has appended its AS to the AS_PATH.
1921 39408 : if ((PeerType() == BgpProto::EBGP) &&
1922 39378 : ((attr->as_path() && !attr->as_path()->path().AsLeftMostMatch(
1923 26252 : peer_as())) || (attr->aspath_4byte() &&
1924 0 : !attr->aspath_4byte()->path().AsLeftMostMatch(peer_as())))) {
1925 0 : flags |= BgpPath::NoNeighborAs;
1926 : }
1927 :
1928 : // Check for AS_PATH loop.
1929 13156 : uint8_t max_loop_count = family_attributes_list_[family]->loop_count;
1930 13156 : if (attr->IsAsPathLoop(local_as_, max_loop_count))
1931 0 : flags |= BgpPath::AsPathLooped;
1932 :
1933 13156 : return flags;
1934 : }
1935 :
1936 17169 : uint32_t BgpPeer::GetLocalPrefFromMed(uint32_t med) const {
1937 17169 : if (peer_type_ != BgpProto::EBGP)
1938 1085 : return 0;
1939 16084 : if (!peer_is_control_node_)
1940 16084 : return 0;
1941 0 : if (med == 0)
1942 0 : return 0;
1943 0 : if (med == 100)
1944 0 : return 200;
1945 0 : if (med == 200)
1946 0 : return 100;
1947 0 : return numeric_limits<uint32_t>::max() - med;
1948 : }
1949 :
1950 17169 : void BgpPeer::ProcessUpdate(const BgpProto::Update *msg, size_t msgsize) {
1951 17169 : BgpAttrPtr attr = server_->attr_db()->Locate(msg->path_attributes);
1952 :
1953 17169 : uint32_t local_pref = GetLocalPrefFromMed(attr->med());
1954 17169 : if (local_pref) {
1955 0 : attr = server_->attr_db()->ReplaceLocalPreferenceAndLocate(attr.get(),
1956 0 : local_pref);
1957 : }
1958 :
1959 : // Check if peer is marked to override the route origin attribute
1960 17169 : if (origin_override_.origin_override) {
1961 0 : attr = server_->attr_db()->ReplaceOriginAndLocate(attr.get(),
1962 0 : origin_override_.origin);
1963 : }
1964 :
1965 34338 : if ((router_type_ == "bgpaas-client") ||
1966 17169 : (router_type_ == "bgpaas-server")) {
1967 0 : attr = server_->attr_db()->ReplaceSubProtocolAndLocate(attr.get(),
1968 0 : MatchProtocolToString(MatchProtocol::BGPaaS));
1969 : }
1970 :
1971 17169 : uint32_t reach_count = 0, unreach_count = 0;
1972 17169 : RoutingInstance *instance = GetRoutingInstance();
1973 17169 : if (msg->nlri.size() || msg->withdrawn_routes.size()) {
1974 : InetTable *table =
1975 0 : static_cast<InetTable *>(instance->GetTable(Address::INET));
1976 0 : if (!table) {
1977 0 : BGP_LOG_WARNING_STR(BgpConfig, BGP_LOG_FLAG_ALL,
1978 : "Cannot find inet table");
1979 0 : return;
1980 : }
1981 :
1982 0 : unreach_count += msg->withdrawn_routes.size();
1983 0 : for (vector<BgpProtoPrefix *>::const_iterator it =
1984 0 : msg->withdrawn_routes.begin(); it != msg->withdrawn_routes.end();
1985 0 : ++it) {
1986 0 : Ip4Prefix prefix;
1987 0 : int result = Ip4Prefix::FromProtoPrefix((**it), &prefix);
1988 0 : if (result) {
1989 0 : BGP_LOG_PEER_WARNING(Message, this,
1990 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN,
1991 : "Withdrawn route parse error for inet route");
1992 0 : continue;
1993 0 : }
1994 :
1995 0 : if ((router_type_ == "bgpaas-client") ||
1996 0 : (router_type_ == "bgpaas-server")) {
1997 0 : ProcessBgpaas(DBRequest::DB_ENTRY_DELETE, prefix.addr(),
1998 0 : prefix.prefixlen(), attr, 0);
1999 : }
2000 :
2001 0 : DBRequest req;
2002 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
2003 0 : req.data.reset(NULL);
2004 0 : req.key.reset(new InetTable::RequestKey(prefix, this));
2005 0 : table->Enqueue(&req);
2006 0 : }
2007 :
2008 0 : uint32_t flags = GetPathFlags(Address::INET, attr.get());
2009 0 : reach_count += msg->nlri.size();
2010 0 : for (vector<BgpProtoPrefix *>::const_iterator it = msg->nlri.begin();
2011 0 : it != msg->nlri.end(); ++it) {
2012 0 : Ip4Prefix prefix;
2013 0 : int result = Ip4Prefix::FromProtoPrefix((**it), &prefix);
2014 0 : if (result) {
2015 0 : BGP_LOG_PEER_WARNING(Message, this,
2016 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN,
2017 : "NLRI parse error for inet route");
2018 0 : continue;
2019 0 : }
2020 :
2021 0 : DBRequest req;
2022 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
2023 0 : req.data.reset(new InetTable::RequestData(attr, flags, 0, 0, 0));
2024 0 : req.key.reset(new InetTable::RequestKey(prefix, this));
2025 0 : table->Enqueue(&req);
2026 :
2027 0 : if ((router_type_ == "bgpaas-client") ||
2028 0 : (router_type_ == "bgpaas-server")) {
2029 0 : ProcessBgpaas(DBRequest::DB_ENTRY_ADD_CHANGE, prefix.addr(),
2030 0 : prefix.prefixlen(), attr, flags);
2031 : }
2032 0 : }
2033 : }
2034 :
2035 17169 : for (vector<BgpAttribute *>::const_iterator ait =
2036 17169 : msg->path_attributes.begin();
2037 77557 : ait != msg->path_attributes.end(); ++ait) {
2038 : DBRequest::DBOperation oper;
2039 62049 : if ((*ait)->code == BgpAttribute::MPReachNlri) {
2040 13156 : oper = DBRequest::DB_ENTRY_ADD_CHANGE;
2041 48893 : } else if ((*ait)->code == BgpAttribute::MPUnreachNlri) {
2042 4013 : oper = DBRequest::DB_ENTRY_DELETE;
2043 : } else {
2044 44880 : continue;
2045 : }
2046 :
2047 17169 : BgpMpNlri *nlri = static_cast<BgpMpNlri *>(*ait);
2048 17169 : assert(nlri);
2049 17169 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
2050 13156 : reach_count += nlri->nlri.size();
2051 : } else {
2052 4013 : unreach_count += nlri->nlri.size();
2053 : }
2054 :
2055 17169 : Address::Family family = BgpAf::AfiSafiToFamily(nlri->afi, nlri->safi);
2056 17169 : if (!IsFamilyNegotiated(family)) {
2057 0 : BGP_LOG_PEER_NOTICE(Message, this,
2058 : BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN,
2059 : "AFI "<< nlri->afi << " SAFI " << (int) nlri->safi <<
2060 : " not allowed");
2061 0 : continue;
2062 0 : }
2063 :
2064 : // Handle EndOfRib marker.
2065 17169 : if (oper == DBRequest::DB_ENTRY_DELETE && nlri->nlri.empty()) {
2066 1660 : inc_rx_end_of_rib();
2067 1660 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO,
2068 : BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_IN,
2069 : "EndOfRib marker family " <<
2070 : Address::FamilyToString(family) <<
2071 : " size " << msgsize);
2072 1660 : ReceiveEndOfRIB(family, msgsize);
2073 1661 : return;
2074 : }
2075 :
2076 15508 : uint32_t flags = 0;
2077 15508 : if ((*ait)->code == BgpAttribute::MPReachNlri) {
2078 13156 : flags = GetPathFlags(family, attr.get());
2079 13156 : attr = GetMpNlriNexthop(nlri, attr);
2080 : }
2081 :
2082 15508 : switch (family) {
2083 28 : case Address::INET:
2084 : case Address::INETMPLS:
2085 28 : ProcessNlri<InetTable, Ip4Prefix>(
2086 : family, oper, nlri, attr, flags);
2087 56 : if ((router_type_ == "bgpaas-client") ||
2088 28 : (router_type_ == "bgpaas-server")) {
2089 0 : ProcessNlriBgpaas<Ip4Prefix>(
2090 : family, oper, nlri, attr, flags);
2091 : }
2092 28 : break;
2093 6302 : case Address::INETVPN:
2094 6302 : ProcessNlri<InetVpnTable, InetVpnPrefix>(
2095 : family, oper, nlri, attr, flags);
2096 6302 : break;
2097 0 : case Address::INET6:
2098 0 : ProcessNlri<Inet6Table, Inet6Prefix>(
2099 : family, oper, nlri, attr, flags);
2100 0 : if ((router_type_ == "bgpaas-client") ||
2101 0 : (router_type_ == "bgpaas-server")) {
2102 0 : ProcessNlriBgpaas<Inet6Prefix>(
2103 : family, oper, nlri, attr, flags);
2104 : }
2105 0 : break;
2106 5452 : case Address::INET6VPN:
2107 5452 : ProcessNlri<Inet6VpnTable, Inet6VpnPrefix>(
2108 : family, oper, nlri, attr, flags);
2109 5452 : break;
2110 2180 : case Address::EVPN:
2111 2180 : ProcessNlri<EvpnTable, EvpnPrefix>(
2112 : family, oper, nlri, attr, flags);
2113 2180 : break;
2114 0 : case Address::ERMVPN:
2115 0 : ProcessNlri<ErmVpnTable, ErmVpnPrefix>(
2116 : family, oper, nlri, attr, flags);
2117 0 : break;
2118 10 : case Address::MVPN:
2119 10 : ProcessNlri<MvpnTable, MvpnPrefix>(
2120 : family, oper, nlri, attr, flags);
2121 10 : break;
2122 1536 : case Address::RTARGET:
2123 1536 : ProcessNlri<RTargetTable, RTargetPrefix>(
2124 : family, oper, nlri, attr, flags);
2125 1536 : break;
2126 0 : default:
2127 0 : break;
2128 : }
2129 : }
2130 :
2131 15508 : inc_rx_route_reach(reach_count);
2132 15508 : inc_rx_route_unreach(unreach_count);
2133 15508 : if (Sandesh::LoggingLevel() >= Sandesh::LoggingUtLevel()) {
2134 15508 : BGP_LOG_PEER(Message, this, Sandesh::LoggingUtLevel(),
2135 : BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_IN,
2136 : "Update size " << msgsize <<
2137 : " reach " << reach_count << " unreach " << unreach_count);
2138 : }
2139 17169 : }
2140 63794 : const std::vector<std::string> BgpPeer::GetDefaultTunnelEncap(
2141 : const Address::Family family) const {
2142 63794 : if (family_attributes_list_[family] == NULL)
2143 46584 : return std::vector<std::string>();
2144 17208 : return family_attributes_list_[family]->default_tunnel_encap_list;
2145 : }
2146 :
2147 63795 : void BgpPeer::ProcessPathTunnelEncapsulation(const BgpPath *path, BgpAttr *attr,
2148 : ExtCommunityDB *extcomm_db,
2149 : const BgpTable *table) const {
2150 63795 : if (!GetDefaultTunnelEncap(table->family()).empty()) {
2151 0 : ExtCommunityPtr ext_community = attr->ext_community();
2152 0 : bool tunnel_encap_found = false;
2153 0 : if (ext_community) {
2154 0 : for (ExtCommunity::ExtCommunityList::const_iterator iter =
2155 0 : attr->ext_community()->communities().begin();
2156 0 : iter != attr->ext_community()->communities().end();
2157 0 : ++iter) {
2158 0 : if (ExtCommunity::is_tunnel_encap(*iter)) {
2159 0 : tunnel_encap_found = true;
2160 0 : break;
2161 : }
2162 : }
2163 : }
2164 : // Set default tunnel encap since it is not in the path
2165 0 : if (!ext_community || !tunnel_encap_found) {
2166 0 : ExtCommunity::ExtCommunityList encap_list;
2167 0 : BOOST_FOREACH(const string &encap_string,
2168 : GetDefaultTunnelEncap(table->family())) {
2169 0 : TunnelEncap tunnel_encap(encap_string);
2170 0 : encap_list.push_back(tunnel_encap.GetExtCommunity());
2171 0 : }
2172 : ext_community =
2173 0 : extcomm_db->ReplaceTunnelEncapsulationAndLocate(
2174 0 : ext_community ? ext_community.get() : NULL, encap_list);
2175 0 : attr->set_ext_community(ext_community);
2176 0 : }
2177 0 : }
2178 63769 : }
2179 :
2180 :
2181 34428 : void BgpPeer::UpdatePrimaryPathCount(int count, Address::Family family) const {
2182 34428 : primary_path_count_ += count;
2183 34430 : if (family == Address::UNSPEC)
2184 0 : return;
2185 34430 : family_primary_path_count_[family] += count;
2186 34432 : uint32_t limit = 0;
2187 34432 : if (family_attributes_list_[family])
2188 34430 : limit = family_attributes_list_[family]->prefix_limit;
2189 34429 : if (limit && family_primary_path_count_[family] > limit)
2190 0 : TriggerPrefixLimitCheck();
2191 : }
2192 :
2193 0 : void BgpPeer::StartPrefixLimitIdleTimer(uint32_t plim_idle_time_msecs) {
2194 0 : prefix_limit_idle_timer_->Start(plim_idle_time_msecs,
2195 : boost::bind(&BgpPeer::PrefixLimitIdleTimerExpired, this),
2196 : boost::bind(&BgpPeer::PrefixLimitIdleTimerErrorHandler, this, _1, _2));
2197 0 : }
2198 :
2199 378 : void BgpPeer::StopPrefixLimitIdleTimer() {
2200 378 : prefix_limit_idle_timer_->Cancel();
2201 378 : }
2202 :
2203 2021 : bool BgpPeer::PrefixLimitIdleTimerRunning() const {
2204 2021 : return prefix_limit_idle_timer_->running();
2205 : }
2206 :
2207 0 : bool BgpPeer::PrefixLimitIdleTimerExpired() {
2208 0 : return false;
2209 : }
2210 :
2211 0 : void BgpPeer::PrefixLimitIdleTimerErrorHandler(string error_name,
2212 : string error_message) {
2213 0 : BGP_LOG_PEER_CRITICAL(Timer, this, BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2214 : "Timer error: " << error_name << " " << error_message);
2215 0 : }
2216 :
2217 0 : void BgpPeer::EndOfRibTimerErrorHandler(string error_name,
2218 : string error_message) {
2219 0 : BGP_LOG_PEER_CRITICAL(Timer, this, BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2220 : "Timer error: " << error_name << " " << error_message);
2221 0 : }
2222 :
2223 1114 : void BgpPeer::RegisterToVpnTables() {
2224 1114 : CHECK_CONCURRENCY("bgp::StateMachine", "bgp::RTFilter", "bgp::Config");
2225 :
2226 1113 : if (vpn_tables_registered_)
2227 0 : return;
2228 1113 : vpn_tables_registered_ = true;
2229 :
2230 1113 : RoutingInstance *instance = GetRoutingInstance();
2231 : vector<Address::Family> vpn_family_list = list_of
2232 1113 : (Address::INETVPN)(Address::INET6VPN)(Address::ERMVPN)(Address::EVPN)
2233 1114 : (Address::MVPN);
2234 12240 : BOOST_FOREACH(Address::Family vpn_family, vpn_family_list) {
2235 5563 : if (!IsFamilyNegotiated(vpn_family))
2236 4880 : continue;
2237 684 : BgpTable *table = instance->GetTable(vpn_family);
2238 904 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_TRACE,
2239 : table, "Register peer with the table");
2240 684 : Register(table, BuildRibExportPolicy(vpn_family));
2241 : }
2242 1113 : }
2243 :
2244 2125 : void BgpPeer::StartEndOfRibReceiveTimer(Address::Family family) {
2245 2125 : uint32_t timeout = GetEndOfRibReceiveTime(family);
2246 :
2247 2125 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO,
2248 : BGP_LOG_FLAG_SYSLOG, BGP_PEER_DIR_OUT,
2249 : "EndOfRib Receive Timer scheduled for family " <<
2250 : Address::FamilyToString(family) <<
2251 : " to fire after " << timeout << " second(s)");
2252 2126 : eor_receive_timer_[family]->Start(timeout * 1000,
2253 : boost::bind(&BgpPeer::EndOfRibReceiveTimerExpired, this, family),
2254 : boost::bind(&BgpPeer::EndOfRibTimerErrorHandler, this, _1, _2));
2255 2126 : }
2256 :
2257 0 : void BgpPeer::KeepaliveTimerErrorHandler(string error_name,
2258 : string error_message) {
2259 0 : BGP_LOG_PEER_CRITICAL(Timer, this, BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
2260 : "Timer error: " << error_name << " " << error_message);
2261 0 : }
2262 :
2263 0 : bool BgpPeer::EndOfRibReceiveTimerExpired(Address::Family family) {
2264 0 : if (family == Address::RTARGET)
2265 0 : RegisterToVpnTables();
2266 :
2267 : // Fake reception of EoRs to exit from GR states and sweep all stale routes.
2268 0 : close_manager_->ProcessEORMarkerReceived(family);
2269 0 : return false;
2270 : }
2271 :
2272 436 : bool BgpPeer::KeepaliveTimerExpired() {
2273 436 : if (!IsReady())
2274 0 : return false;
2275 :
2276 436 : SendKeepalive(true);
2277 :
2278 : //
2279 : // Start the timer again, by returning true
2280 : //
2281 435 : return true;
2282 : }
2283 :
2284 14962 : void BgpPeer::StartKeepaliveTimerUnlocked() {
2285 14962 : int keepalive_time_msecs = state_machine_->keepalive_time_msecs();
2286 14962 : if (keepalive_time_msecs <= 0)
2287 0 : return;
2288 :
2289 14962 : keepalive_timer_->Start(keepalive_time_msecs,
2290 : boost::bind(&BgpPeer::KeepaliveTimerExpired, this),
2291 : boost::bind(&BgpPeer::KeepaliveTimerErrorHandler, this, _1, _2));
2292 : }
2293 :
2294 1115 : void BgpPeer::StartKeepaliveTimer() {
2295 1115 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
2296 1115 : if (session_ && send_ready_)
2297 1115 : StartKeepaliveTimerUnlocked();
2298 1115 : }
2299 :
2300 0 : void BgpPeer::StopKeepaliveTimerUnlocked() {
2301 0 : keepalive_timer_->Cancel();
2302 0 : }
2303 :
2304 0 : bool BgpPeer::KeepaliveTimerRunning() {
2305 0 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
2306 0 : return keepalive_timer_->running();
2307 0 : }
2308 :
2309 0 : void BgpPeer::SetSendReady() {
2310 0 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
2311 0 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
2312 : BGP_PEER_DIR_NA, "Send ready");
2313 0 : send_ready_ = true;
2314 0 : if (session_ != NULL)
2315 0 : StartKeepaliveTimerUnlocked();
2316 0 : }
2317 :
2318 1115 : void BgpPeer::set_session(BgpSession *session) {
2319 1115 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
2320 1115 : assert(session_ == NULL);
2321 1115 : session_ = session;
2322 1115 : }
2323 :
2324 2800 : void BgpPeer::clear_session() {
2325 2800 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
2326 2800 : if (session_) {
2327 1115 : session_->clear_peer();
2328 1115 : session_->set_observer(NULL);
2329 1115 : session_->Close();
2330 : }
2331 2800 : session_ = NULL;
2332 2800 : }
2333 :
2334 7606 : BgpSession *BgpPeer::session() {
2335 7606 : return session_;
2336 : }
2337 :
2338 1957 : string BgpPeer::BytesToHexString(const u_int8_t *msg, size_t size) {
2339 1957 : ostringstream out;
2340 : char buf[4];
2341 :
2342 166296 : for (size_t i = 0; i < size; i ++) {
2343 164339 : if (!(i % 32)) out << "\n";
2344 164339 : if (!(i % 4)) out << " 0x";
2345 164339 : snprintf(buf, sizeof(buf), "%02X", msg[i]);
2346 164339 : out << buf;
2347 : }
2348 :
2349 1957 : out << "\n";
2350 :
2351 3914 : return out.str();
2352 1957 : }
2353 :
2354 21018 : bool BgpPeer::ReceiveMsg(BgpSession *session, const u_int8_t *msg,
2355 : size_t size) {
2356 21018 : ParseErrorContext ec;
2357 42037 : BgpProto::BgpMessage *minfo = BgpProto::Decode(msg, size, &ec,
2358 21018 : Is4ByteAsSupported());
2359 :
2360 21018 : if (minfo == NULL) {
2361 0 : BGP_TRACE_PEER_PACKET(this, msg, size, SandeshLevel::SYS_WARN);
2362 0 : BGP_LOG_PEER_WARNING(Message, this, BGP_LOG_FLAG_ALL,
2363 : BGP_PEER_DIR_IN,
2364 : "Error while parsing message at " << ec.type_name);
2365 0 : state_machine_->OnMessageError(session, &ec);
2366 0 : return false;
2367 : }
2368 :
2369 : // Tracing periodic keepalive packets is not necessary.
2370 21018 : if (minfo->type != BgpProto::KEEPALIVE)
2371 19469 : BGP_TRACE_PEER_PACKET(this, msg, size, SandeshLevel::SYS_WARN); //Sandesh::LoggingUtLevel()
2372 :
2373 21018 : state_machine_->OnMessage(session, minfo, size);
2374 21019 : return true;
2375 21019 : }
2376 :
2377 : //
2378 : // Extract nexthop address from BgpMpNlri if appropriate and return updated
2379 : // BgpAttrPtr. The original attribute is returned for cases where there's no
2380 : // nexthop attribute in the BgpMpNlri.
2381 : //
2382 13156 : BgpAttrPtr BgpPeer::GetMpNlriNexthop(BgpMpNlri *nlri, BgpAttrPtr attr) {
2383 13156 : bool update_nh = false;
2384 13156 : IpAddress addr;
2385 :
2386 13156 : if (nlri->afi == BgpAf::IPv4) {
2387 6844 : if (nlri->safi == BgpAf::Mpls || nlri->safi == BgpAf::Unicast ||
2388 6820 : nlri->safi == BgpAf::RTarget || nlri->safi == BgpAf::MVpn) {
2389 1532 : Ip4Address::bytes_type bt = { { 0 } };
2390 3064 : copy(nlri->nexthop.begin(),
2391 1532 : nlri->nexthop.begin() + sizeof(bt), bt.begin());
2392 1532 : addr = Ip4Address(bt);
2393 1532 : update_nh = true;
2394 6844 : } else if (nlri->safi == BgpAf::Vpn) {
2395 5312 : Ip4Address::bytes_type bt = { { 0 } };
2396 5312 : size_t rdsize = RouteDistinguisher::kSize;
2397 10624 : copy(nlri->nexthop.begin() + rdsize,
2398 5312 : nlri->nexthop.begin() + rdsize + sizeof(bt), bt.begin());
2399 5312 : addr = Ip4Address(bt);
2400 5312 : update_nh = true;
2401 : }
2402 6312 : } else if (nlri->afi == BgpAf::L2Vpn) {
2403 1788 : if (nlri->safi == BgpAf::EVpn) {
2404 1788 : Ip4Address::bytes_type bt = { { 0 } };
2405 3576 : copy(nlri->nexthop.begin(),
2406 1788 : nlri->nexthop.begin() + sizeof(bt), bt.begin());
2407 1788 : addr = Ip4Address(bt);
2408 1788 : update_nh = true;
2409 : }
2410 4524 : } else if (nlri->afi == BgpAf::IPv6) {
2411 4524 : if (nlri->safi == BgpAf::Unicast) {
2412 : // There could be either 1 or 2 v6 addresses in the nexthop field.
2413 : // The first one is supposed to be global and the optional second
2414 : // one, if present, is link local. We will be liberal and find the
2415 : // global address, whether it's first or second. Further, if the
2416 : // address is a v4-mapped v6 address, we use the corresponding v4
2417 : // address as the nexthop.
2418 0 : for (int idx = 0; idx < 2; ++idx) {
2419 0 : Ip6Address::bytes_type bt = { { 0 } };
2420 0 : if ((idx + 1) * sizeof(bt) > nlri->nexthop.size())
2421 0 : break;
2422 0 : copy(nlri->nexthop.begin() + idx * sizeof(bt),
2423 0 : nlri->nexthop.begin() + (idx + 1) * sizeof(bt), bt.begin());
2424 0 : Ip6Address v6_addr(bt);
2425 0 : if (v6_addr.is_v4_mapped()) {
2426 0 : addr = Address::V4FromV4MappedV6(v6_addr);
2427 0 : update_nh = true;
2428 0 : break;
2429 : }
2430 0 : if (!v6_addr.is_link_local()) {
2431 0 : addr = v6_addr;
2432 0 : update_nh = true;
2433 0 : break;
2434 : }
2435 : }
2436 4524 : } else if (nlri->safi == BgpAf::Vpn) {
2437 4524 : Ip6Address::bytes_type bt = { { 0 } };
2438 4524 : size_t rdsize = RouteDistinguisher::kSize;
2439 9048 : copy(nlri->nexthop.begin() + rdsize,
2440 4524 : nlri->nexthop.begin() + rdsize + sizeof(bt), bt.begin());
2441 4524 : Ip6Address v6_addr(bt);
2442 4524 : if (v6_addr.is_v4_mapped()) {
2443 4524 : addr = Address::V4FromV4MappedV6(v6_addr);
2444 4524 : update_nh = true;
2445 : }
2446 : }
2447 : }
2448 :
2449 : // Always update the nexthop in BgpAttr with MpReachNlri->nexthop.
2450 : // NOP in cases <afi,safi> doesn't carry nexthop attribute.
2451 13156 : if (update_nh) {
2452 13156 : attr = server_->attr_db()->ReplaceNexthopAndLocate(attr.get(), addr);
2453 : }
2454 26312 : return attr;
2455 : }
2456 :
2457 684 : void BgpPeer::ManagedDelete() {
2458 684 : if (deleter_->IsDeleted())
2459 0 : return;
2460 684 : BGP_LOG_PEER(Config, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2461 : BGP_PEER_DIR_NA, "Received request for deletion");
2462 684 : if (IsRouterTypeBGPaaS()) {
2463 0 : server()->increment_deleting_bgpaas_count();
2464 : } else {
2465 684 : server()->increment_deleting_count();
2466 : }
2467 684 : deleter_->Delete();
2468 : }
2469 :
2470 2415 : void BgpPeer::RetryDelete() {
2471 2415 : if (!deleter_->IsDeleted())
2472 1049 : return;
2473 1366 : deleter_->RetryDelete();
2474 : }
2475 :
2476 21729 : int BgpPeer::GetTaskInstance() const {
2477 21729 : return index_ % TaskScheduler::GetInstance()->HardwareThreadCount();
2478 : }
2479 :
2480 1957 : void BgpPeer::SetDataCollectionKey(BgpPeerInfo *peer_info) const {
2481 1957 : if (rtinstance_) {
2482 1957 : peer_info->set_domain(rtinstance_->name());
2483 : } else {
2484 0 : peer_info->set_domain(BgpConfigManager::kMasterInstance);
2485 : }
2486 :
2487 1957 : peer_info->set_ip_address(peer_key_.endpoint.address().to_string());
2488 1957 : }
2489 :
2490 0 : static void FillProtoStats(const IPeerDebugStats::ProtoStats &stats,
2491 : PeerProtoStats *proto_stats) {
2492 0 : proto_stats->set_open(stats.open);
2493 0 : proto_stats->set_keepalive(stats.keepalive);
2494 0 : proto_stats->set_close(stats.close);
2495 0 : proto_stats->set_update(stats.update);
2496 0 : proto_stats->set_notification(stats.notification);
2497 0 : proto_stats->set_total(stats.open + stats.keepalive + stats.close +
2498 0 : stats.update + stats.notification);
2499 0 : }
2500 :
2501 0 : static void FillRouteUpdateStats(const IPeerDebugStats::UpdateStats &stats,
2502 : PeerUpdateStats *rt_stats) {
2503 0 : rt_stats->set_reach(stats.reach);
2504 0 : rt_stats->set_unreach(stats.unreach);
2505 0 : rt_stats->set_end_of_rib(stats.end_of_rib);
2506 0 : rt_stats->set_total(stats.reach + stats.unreach + stats.end_of_rib);
2507 0 : }
2508 :
2509 0 : static void FillSocketStats(const IPeerDebugStats::SocketStats &socket_stats,
2510 : PeerSocketStats *peer_socket_stats) {
2511 0 : peer_socket_stats->set_calls(socket_stats.calls);
2512 0 : peer_socket_stats->set_bytes(socket_stats.bytes);
2513 0 : if (socket_stats.calls) {
2514 0 : peer_socket_stats->set_average_bytes(
2515 0 : socket_stats.bytes/socket_stats.calls);
2516 : }
2517 0 : peer_socket_stats->set_blocked_count(socket_stats.blocked_count);
2518 0 : ostringstream os;
2519 0 : os << boost::posix_time::microseconds(long(socket_stats.blocked_duration_usecs));
2520 0 : peer_socket_stats->set_blocked_duration(os.str());
2521 0 : if (socket_stats.blocked_count) {
2522 0 : os.str("");
2523 0 : os << boost::posix_time::microseconds(
2524 0 : socket_stats.blocked_duration_usecs/socket_stats.blocked_count);
2525 0 : peer_socket_stats->set_average_blocked_duration(os.str());
2526 : }
2527 0 : }
2528 :
2529 0 : void BgpPeer::FillCloseInfo(BgpNeighborResp *resp) const {
2530 0 : close_manager_->FillCloseInfo(resp);
2531 0 : }
2532 :
2533 0 : void BgpPeer::FillBgpNeighborDebugState(BgpNeighborResp *bnr,
2534 : const IPeerDebugStats *peer_stats) {
2535 0 : bnr->set_last_state(peer_stats->last_state());
2536 0 : bnr->set_last_event(peer_stats->last_event());
2537 0 : bnr->set_last_error(peer_stats->last_error());
2538 0 : bnr->set_last_state_at(peer_stats->last_state_change_at());
2539 0 : bnr->set_flap_count(peer_stats->num_flaps());
2540 0 : bnr->set_flap_time(peer_stats->last_flap());
2541 :
2542 0 : IPeerDebugStats::ProtoStats stats;
2543 0 : PeerProtoStats proto_stats;
2544 0 : peer_stats->GetRxProtoStats(&stats);
2545 0 : FillProtoStats(stats, &proto_stats);
2546 0 : bnr->set_rx_proto_stats(proto_stats);
2547 :
2548 0 : peer_stats->GetTxProtoStats(&stats);
2549 0 : FillProtoStats(stats, &proto_stats);
2550 0 : bnr->set_tx_proto_stats(proto_stats);
2551 :
2552 0 : IPeerDebugStats::UpdateStats update_stats;
2553 0 : PeerUpdateStats rt_stats;
2554 0 : peer_stats->GetRxRouteUpdateStats(&update_stats);
2555 0 : FillRouteUpdateStats(update_stats, &rt_stats);
2556 0 : bnr->set_rx_update_stats(rt_stats);
2557 :
2558 0 : peer_stats->GetTxRouteUpdateStats(&update_stats);
2559 0 : FillRouteUpdateStats(update_stats, &rt_stats);
2560 0 : bnr->set_tx_update_stats(rt_stats);
2561 :
2562 0 : IPeerDebugStats::SocketStats socket_stats;
2563 0 : PeerSocketStats peer_socket_stats;
2564 :
2565 0 : peer_stats->GetRxSocketStats(&socket_stats);
2566 0 : FillSocketStats(socket_stats, &peer_socket_stats);
2567 0 : bnr->set_rx_socket_stats(peer_socket_stats);
2568 :
2569 0 : peer_stats->GetTxSocketStats(&socket_stats);
2570 0 : FillSocketStats(socket_stats, &peer_socket_stats);
2571 0 : bnr->set_tx_socket_stats(peer_socket_stats);
2572 0 : }
2573 :
2574 0 : void BgpPeer::FillBgpNeighborFamilyAttributes(BgpNeighborResp *nbr) const {
2575 0 : vector<ShowBgpNeighborFamily> show_family_attributes_list;
2576 0 : for (int idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
2577 0 : if (!family_attributes_list_[idx])
2578 0 : continue;
2579 0 : ShowBgpNeighborFamily show_family_attributes;
2580 0 : show_family_attributes.set_family(
2581 0 : Address::FamilyToString(static_cast<Address::Family>(idx)));
2582 0 : show_family_attributes.set_loop_count(
2583 0 : family_attributes_list_[idx]->loop_count);
2584 0 : show_family_attributes.set_prefix_limit(
2585 0 : family_attributes_list_[idx]->prefix_limit);
2586 0 : show_family_attributes.set_idle_timeout(
2587 0 : family_attributes_list_[idx]->idle_timeout);
2588 0 : if (!family_attributes_list_[idx]->gateway_address.is_unspecified()) {
2589 0 : show_family_attributes.set_gateway_address(
2590 0 : family_attributes_list_[idx]->gateway_address.to_string());
2591 : }
2592 0 : show_family_attributes_list.push_back(show_family_attributes);
2593 0 : }
2594 0 : nbr->set_family_attributes_list(show_family_attributes_list);
2595 0 : }
2596 :
2597 0 : void BgpPeer::FillNeighborInfo(const BgpSandeshContext *bsc,
2598 : BgpNeighborResp *bnr, bool summary) const {
2599 0 : bnr->set_instance_name(rtinstance_->name());
2600 0 : bnr->set_peer(peer_basename_);
2601 0 : bnr->set_deleted(IsDeleted());
2602 0 : bnr->set_closed_at(UTCUsecToString(deleter_->delete_time_stamp_usecs()));
2603 0 : bnr->set_admin_down(admin_down_);
2604 0 : bnr->set_passive(passive_);
2605 0 : bnr->set_as_override(as_override_);
2606 0 : bnr->set_origin_override(origin_override_.origin_override);
2607 0 : if (origin_override_.origin_override) {
2608 0 : bnr->set_route_origin(BgpAttr::OriginToString(origin_override_.origin));
2609 : } else {
2610 0 : bnr->set_route_origin("-");
2611 : }
2612 0 : bnr->set_private_as_action(private_as_action_);
2613 0 : bnr->set_peer_address(peer_address_string());
2614 0 : bnr->set_peer_id(bgp_identifier_string());
2615 0 : bnr->set_peer_asn(peer_as());
2616 0 : bnr->set_peer_port(peer_port());
2617 0 : bnr->set_transport_address(transport_address_string());
2618 0 : bnr->set_encoding("BGP");
2619 0 : bnr->set_peer_type(PeerType() == BgpProto::IBGP ? "internal" : "external");
2620 0 : bnr->set_router_type(router_type_);
2621 0 : bnr->set_state(state_machine_->StateName());
2622 0 : bnr->set_local_address(server_->ToString());
2623 0 : bnr->set_local_id(Ip4Address(ntohl(local_bgp_id_)).to_string());
2624 0 : bnr->set_local_asn(local_as());
2625 0 : bnr->set_cluster_id(Ip4Address(cluster_id_).to_string());
2626 0 : bnr->set_negotiated_hold_time(state_machine_->hold_time());
2627 0 : bnr->set_primary_path_count(GetPrimaryPathCount());
2628 0 : bnr->set_task_instance(GetTaskInstance());
2629 0 : bnr->set_send_ready(send_ready_);
2630 0 : bnr->set_flap_count(peer_stats_->num_flaps());
2631 0 : bnr->set_as4_supported(Is4ByteAsSupported());
2632 0 : bnr->set_flap_time(peer_stats_->last_flap());
2633 0 : bnr->set_auth_type(
2634 0 : AuthenticationData::KeyTypeToString(inuse_authkey_type_));
2635 0 : if (bsc->test_mode()) {
2636 0 : bnr->set_auth_keys(auth_data_.KeysToStringDetail());
2637 : }
2638 :
2639 0 : if (summary)
2640 0 : return;
2641 :
2642 0 : bnr->set_configured_address_families(configured_families_);
2643 0 : bnr->set_negotiated_address_families(negotiated_families_);
2644 :
2645 0 : peer_close_->FillNeighborInfo(bnr);
2646 :
2647 0 : bnr->set_configured_hold_time(state_machine_->GetConfiguredHoldTime());
2648 0 : FillBgpNeighborFamilyAttributes(bnr);
2649 0 : FillBgpNeighborDebugState(bnr, peer_stats_.get());
2650 0 : BgpMembershipManager *mgr = server_->membership_mgr();
2651 0 : mgr->FillPeerMembershipInfo(this, bnr);
2652 0 : bnr->set_routing_instances(vector<BgpNeighborRoutingInstance>());
2653 0 : FillCloseInfo(bnr);
2654 : }
2655 :
2656 1288 : void BgpPeer::inc_rx_open() {
2657 1288 : peer_stats_->proto_stats_[0].open++;
2658 1289 : }
2659 :
2660 1670 : void BgpPeer::inc_tx_open() {
2661 1670 : peer_stats_->proto_stats_[1].open++;
2662 1670 : }
2663 :
2664 1549 : void BgpPeer::inc_rx_keepalive() {
2665 1549 : peer_stats_->proto_stats_[0].keepalive++;
2666 1549 : }
2667 :
2668 766 : uint64_t BgpPeer::get_rx_keepalive() const {
2669 766 : return peer_stats_->proto_stats_[0].keepalive;
2670 : }
2671 :
2672 1550 : void BgpPeer::inc_tx_keepalive() {
2673 1550 : peer_stats_->proto_stats_[1].keepalive++;
2674 1550 : }
2675 :
2676 49 : uint64_t BgpPeer::get_tx_keepalive() const {
2677 49 : return peer_stats_->proto_stats_[1].keepalive;
2678 : }
2679 :
2680 17175 : void BgpPeer::inc_rx_update() {
2681 17175 : peer_stats_->proto_stats_[0].update++;
2682 17175 : }
2683 :
2684 0 : uint64_t BgpPeer::get_rx_update() const {
2685 0 : return peer_stats_->proto_stats_[0].update;
2686 : }
2687 :
2688 18838 : void BgpPeer::inc_tx_update() {
2689 18838 : peer_stats_->proto_stats_[1].update++;
2690 18838 : }
2691 :
2692 0 : uint64_t BgpPeer::get_tx_update() const {
2693 0 : return peer_stats_->proto_stats_[1].update;
2694 : }
2695 :
2696 1006 : void BgpPeer::inc_rx_notification() {
2697 1006 : peer_stats_->proto_stats_[0].notification++;
2698 1006 : }
2699 :
2700 432 : uint64_t BgpPeer::get_rx_notification() const {
2701 432 : return peer_stats_->proto_stats_[0].notification;
2702 : }
2703 :
2704 865 : void BgpPeer::inc_tx_notification() {
2705 865 : peer_stats_->proto_stats_[1].notification++;
2706 865 : }
2707 :
2708 1660 : void BgpPeer::inc_rx_end_of_rib() {
2709 1660 : peer_stats_->update_stats_[0].end_of_rib++;
2710 1660 : }
2711 :
2712 0 : uint64_t BgpPeer::get_rx_end_of_rib() const {
2713 0 : return peer_stats_->update_stats_[0].end_of_rib;
2714 : }
2715 :
2716 1672 : void BgpPeer::inc_tx_end_of_rib() {
2717 1672 : peer_stats_->update_stats_[1].end_of_rib++;
2718 1672 : }
2719 :
2720 0 : uint64_t BgpPeer::get_tx_end_of_rib() const {
2721 0 : return peer_stats_->update_stats_[1].end_of_rib;
2722 : }
2723 :
2724 15508 : void BgpPeer::inc_rx_route_reach(uint64_t count) {
2725 15508 : peer_stats_->update_stats_[0].reach += count;
2726 15508 : }
2727 :
2728 0 : uint64_t BgpPeer::get_rx_route_reach() const {
2729 0 : return peer_stats_->update_stats_[0].reach;
2730 : }
2731 :
2732 0 : uint64_t BgpPeer::get_tx_route_reach() const {
2733 0 : return peer_stats_->update_stats_[1].reach;
2734 : }
2735 :
2736 15508 : void BgpPeer::inc_rx_route_unreach(uint64_t count) {
2737 15508 : peer_stats_->update_stats_[0].unreach += count;
2738 15508 : }
2739 :
2740 0 : uint64_t BgpPeer::get_rx_route_unreach() const {
2741 0 : return peer_stats_->update_stats_[0].unreach;
2742 : }
2743 :
2744 0 : uint64_t BgpPeer::get_tx_route_unreach() const {
2745 0 : return peer_stats_->update_stats_[1].unreach;
2746 : }
2747 :
2748 0 : uint64_t BgpPeer::get_rx_route_total() const {
2749 0 : return peer_stats_->update_stats_[0].reach +
2750 0 : peer_stats_->update_stats_[0].unreach +
2751 0 : peer_stats_->update_stats_[0].end_of_rib;
2752 : }
2753 :
2754 0 : uint64_t BgpPeer::get_tx_route_total() const {
2755 0 : return peer_stats_->update_stats_[1].reach +
2756 0 : peer_stats_->update_stats_[1].unreach +
2757 0 : peer_stats_->update_stats_[1].end_of_rib;
2758 : }
2759 :
2760 37 : void BgpPeer::inc_connect_error() {
2761 37 : peer_stats_->error_stats_.connect_error++;
2762 37 : }
2763 :
2764 78 : void BgpPeer::inc_connect_timer_expired() {
2765 78 : peer_stats_->error_stats_.connect_timer++;
2766 78 : }
2767 :
2768 0 : void BgpPeer::inc_hold_timer_expired() {
2769 0 : peer_stats_->error_stats_.hold_timer++;
2770 0 : }
2771 :
2772 30 : void BgpPeer::inc_open_error() {
2773 30 : peer_stats_->error_stats_.open_error++;
2774 30 : }
2775 :
2776 0 : void BgpPeer::inc_update_error() {
2777 0 : peer_stats_->error_stats_.update_error++;
2778 0 : }
2779 :
2780 138 : uint64_t BgpPeer::get_connect_error() const {
2781 138 : return peer_stats_->error_stats_.connect_error;
2782 : }
2783 :
2784 122 : uint64_t BgpPeer::get_connect_timer_expired() const {
2785 122 : return peer_stats_->error_stats_.connect_timer;
2786 : }
2787 :
2788 6 : uint64_t BgpPeer::get_hold_timer_expired() const {
2789 6 : return peer_stats_->error_stats_.hold_timer;
2790 : }
2791 :
2792 152 : uint64_t BgpPeer::get_open_error() const {
2793 152 : return peer_stats_->error_stats_.open_error;
2794 : }
2795 :
2796 0 : uint64_t BgpPeer::get_update_error() const {
2797 0 : return peer_stats_->error_stats_.update_error;
2798 : }
2799 :
2800 0 : uint64_t BgpPeer::get_socket_reads() const {
2801 0 : IPeerDebugStats::SocketStats stats;
2802 0 : peer_stats_->GetRxSocketStats(&stats);
2803 0 : return stats.calls;
2804 : }
2805 :
2806 0 : uint64_t BgpPeer::get_socket_writes() const {
2807 0 : IPeerDebugStats::SocketStats stats;
2808 0 : peer_stats_->GetTxSocketStats(&stats);
2809 0 : return stats.calls;
2810 : }
2811 :
2812 0 : string BgpPeer::last_flap_at() const {
2813 0 : if (last_flap_) {
2814 0 : return integerToString(UTCUsecToPTime(last_flap_));
2815 : } else {
2816 0 : return "";
2817 : }
2818 : }
2819 :
2820 1114 : void BgpPeer::increment_flap_count() {
2821 1114 : flap_count_++;
2822 1114 : total_flap_count_++;
2823 1114 : last_flap_ = UTCTimestampUsec();
2824 :
2825 2228 : BgpPeerInfoData peer_info;
2826 1114 : peer_info.set_name(ToUVEKey());
2827 1114 : PeerFlapInfo flap_info;
2828 1114 : flap_info.set_flap_count(flap_count_);
2829 1114 : flap_info.set_flap_time(last_flap_);
2830 1113 : peer_info.set_flap_info(flap_info);
2831 1113 : BGPPeerInfoSend(peer_info);
2832 :
2833 2224 : PeerFlapData peer_flap_data;
2834 1112 : peer_flap_data.set_name(ToUVEKey());
2835 1111 : peer_flap_data.set_flap_info(flap_info);
2836 1111 : assert(!peer_flap_data.get_name().empty());
2837 1111 : BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
2838 1111 : }
2839 :
2840 106 : void BgpPeer::reset_flap_count() {
2841 106 : flap_count_ = 0;
2842 106 : last_flap_ = 0;
2843 :
2844 212 : BgpPeerInfoData peer_info;
2845 106 : peer_info.set_name(ToUVEKey());
2846 106 : PeerFlapInfo flap_info;
2847 106 : peer_info.set_flap_info(flap_info);
2848 106 : BGPPeerInfoSend(peer_info);
2849 :
2850 212 : PeerFlapData peer_flap_data;
2851 106 : peer_flap_data.set_name(ToUVEKey());
2852 106 : peer_flap_data.set_flap_info(flap_info);
2853 106 : assert(!peer_flap_data.get_name().empty());
2854 106 : BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
2855 106 : }
2856 :
2857 : // Ignore if the peer is IBGP and a BGPaaS client since we do not support that
2858 : // combination. i.e, allow any EBGP session or any non BGPaaS-client session.
2859 737 : bool BgpPeer::ProcessSession() const {
2860 737 : return PeerType() != BgpProto::IBGP || router_type() != "bgpaas-client";
2861 : }
2862 :
2863 : // Update control DSCP
2864 0 : void BgpPeer::DSCPUpdateCallback(uint8_t dscp_value) {
2865 0 : if ((session_ != NULL) && (dscp_value != 0xFF)) {
2866 0 : session_->SetDscpSocketOption(dscp_value);
2867 : }
2868 0 : }
|