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 10358 : explicit PeerStats(BgpPeer *peer)
57 51790 : : peer_(peer) {
58 10358 : }
59 :
60 : // Used when peer flaps.
61 : // Reset all counters.
62 : // Socket counters are implicitly cleared because we use a new socket.
63 5247 : virtual void Clear() {
64 5247 : error_stats_ = ErrorStats();
65 5247 : proto_stats_[0] = ProtoStats();
66 5246 : proto_stats_[1] = ProtoStats();
67 5247 : update_stats_[0] = UpdateStats();
68 5246 : update_stats_[1] = UpdateStats();
69 5247 : }
70 :
71 : // Printable name
72 0 : virtual string ToString() const {
73 0 : return peer_->ToString();
74 : }
75 : // Previous State of the peer
76 56 : virtual string last_state() const {
77 56 : return peer_->state_machine()->LastStateName();
78 : }
79 56 : virtual string last_state_change_at() const {
80 56 : return peer_->state_machine()->last_state_change_at();
81 : }
82 : // Last error on this peer
83 56 : virtual string last_error() const {
84 56 : return peer_->state_machine()->last_notification_in_error();
85 : }
86 : // Last Event on this peer
87 56 : virtual string last_event() const {
88 56 : return peer_->state_machine()->last_event();
89 : }
90 :
91 : // When was the Last
92 168 : virtual string last_flap() const {
93 168 : return peer_->last_flap_at();
94 : }
95 :
96 : // Total number of flaps
97 168 : virtual uint64_t num_flaps() const {
98 168 : return peer_->flap_count();
99 : }
100 :
101 206 : virtual void GetRxProtoStats(ProtoStats *stats) const {
102 206 : *stats = proto_stats_[0];
103 206 : }
104 :
105 206 : virtual void GetTxProtoStats(ProtoStats *stats) const {
106 206 : *stats = proto_stats_[1];
107 206 : }
108 :
109 356 : virtual void GetRxRouteUpdateStats(UpdateStats *stats) const {
110 356 : *stats = update_stats_[0];
111 356 : }
112 :
113 356 : virtual void GetTxRouteUpdateStats(UpdateStats *stats) const {
114 356 : *stats = update_stats_[1];
115 356 : }
116 :
117 56 : virtual void GetRxSocketStats(IPeerDebugStats::SocketStats *stats) const {
118 56 : if (peer_->session()) {
119 54 : const io::SocketStats &socket_stats = peer_->session()->GetSocketStats();
120 54 : stats->calls = socket_stats.read_calls;
121 54 : stats->bytes = socket_stats.read_bytes;
122 : }
123 56 : }
124 :
125 56 : virtual void GetTxSocketStats(IPeerDebugStats::SocketStats *stats) const {
126 56 : if (peer_->session()) {
127 54 : const io::SocketStats &socket_stats = peer_->session()->GetSocketStats();
128 54 : stats->calls = socket_stats.write_calls;
129 54 : stats->bytes = socket_stats.write_bytes;
130 54 : stats->blocked_count = socket_stats.write_blocked;
131 54 : stats->blocked_duration_usecs =
132 54 : socket_stats.write_blocked_duration_usecs;
133 : }
134 56 : }
135 :
136 158974 : virtual void UpdateTxUnreachRoute(uint64_t count) {
137 158974 : update_stats_[1].unreach += count;
138 158974 : }
139 :
140 158959 : virtual void UpdateTxReachRoute(uint64_t count) {
141 158959 : update_stats_[1].reach += count;
142 158959 : }
143 :
144 : // Do nothing for bgp peers.
145 150 : virtual void GetRxErrorStats(RxErrorStats *stats) const {
146 150 : }
147 :
148 150 : virtual void GetRxRouteStats(RxRouteStats *stats) const {
149 150 : stats->total_path_count = peer_->GetTotalPathCount();
150 150 : stats->primary_path_count = peer_->GetPrimaryPathCount();
151 150 : }
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 10358 : explicit DeleteActor(BgpPeer *peer)
165 10358 : : LifetimeActor(peer->server_->lifetime_manager()),
166 10358 : peer_(peer) {
167 10358 : }
168 :
169 23712 : virtual bool MayDelete() const {
170 23712 : CHECK_CONCURRENCY("bgp::Config");
171 23712 : if (!peer_->close_manager_->IsQueueEmpty())
172 5872 : return false;
173 17840 : if (peer_->IsCloseInProgress())
174 0 : return false;
175 17840 : if (!peer_->state_machine_->IsQueueEmpty())
176 8273 : return false;
177 9567 : if (peer_->prefix_limit_trigger_.IsSet())
178 0 : return false;
179 9567 : return true;
180 : }
181 :
182 9567 : virtual void Shutdown() {
183 9567 : CHECK_CONCURRENCY("bgp::Config");
184 9567 : peer_->Clear(BgpProto::Notification::PeerDeconfigured);
185 9567 : }
186 :
187 9567 : virtual void Destroy() {
188 9567 : CHECK_CONCURRENCY("bgp::Config");
189 9567 : peer_->PostCloseRelease();
190 9567 : if (peer_->IsRouterTypeBGPaaS()) {
191 112 : peer_->server()->decrement_deleting_bgpaas_count();
192 : } else {
193 9455 : peer_->server()->decrement_deleting_count();
194 : }
195 9567 : if (peer_->dscp_listener_id_ >= 0) {
196 9567 : peer_->server()->UnregisterDSCPUpdateCallback(
197 9567 : peer_->dscp_listener_id_);
198 9567 : peer_->dscp_listener_id_ = -1;
199 : }
200 9567 : if (peer_->instance_op_ >= 0) {
201 112 : peer_->server()->routing_instance_mgr()->
202 112 : UnregisterInstanceOpCallback(peer_->instance_op_);
203 112 : peer_->instance_op_ = -1;
204 : }
205 9567 : if (peer_->asn_listener_id_ >= 0) {
206 112 : peer_->server()->UnregisterASNUpdateCallback(
207 112 : peer_->asn_listener_id_);
208 112 : peer_->asn_listener_id_ = -1;
209 : }
210 9567 : assert(!peer_->membership_req_pending());
211 9567 : assert(!peer_->close_manager_->IsMembershipInUse());
212 9567 : peer_->rtinstance_->peer_manager()->DestroyIPeer(peer_);
213 9567 : }
214 :
215 : private:
216 : BgpPeer *peer_;
217 : };
218 :
219 : //
220 : // Constructor for BgpPeerFamilyAttributes.
221 : //
222 32616 : BgpPeerFamilyAttributes::BgpPeerFamilyAttributes(
223 : const BgpNeighborConfig *config,
224 32616 : const BgpFamilyAttributesConfig &family_config) {
225 32616 : if (family_config.loop_count) {
226 16 : loop_count = family_config.loop_count;
227 : } else {
228 32600 : loop_count = config->loop_count();
229 : }
230 32616 : prefix_limit = family_config.prefix_limit;
231 32616 : idle_timeout = family_config.idle_timeout;
232 32616 : default_tunnel_encap_list = family_config.default_tunnel_encap_list;
233 :
234 32616 : if (config->router_type() == "bgpaas-client") {
235 400 : if (family_config.family == "inet") {
236 202 : gateway_address = config->gateway_address(Address::INET);
237 198 : } else if (family_config.family == "inet6") {
238 198 : gateway_address = config->gateway_address(Address::INET6);
239 : }
240 : }
241 32616 : }
242 :
243 12818 : RibExportPolicy BgpPeer::BuildRibExportPolicy(Address::Family family) const {
244 12818 : RibExportPolicy policy;
245 : BgpPeerFamilyAttributes *family_attributes =
246 12816 : family_attributes_list_[family];
247 12815 : if (!family_attributes) {
248 7 : policy = RibExportPolicy(peer_type_, RibExportPolicy::BGP, peer_as_,
249 7 : as_override_, peer_close_->IsCloseLongLivedGraceful(),
250 14 : as4_supported_, -1, cluster_id_, local_as_);
251 : } else {
252 12804 : policy = RibExportPolicy(peer_type_, RibExportPolicy::BGP, peer_as_,
253 12808 : as_override_, peer_close_->IsCloseLongLivedGraceful(),
254 12808 : as4_supported_, family_attributes->gateway_address,
255 12808 : -1, cluster_id_, family_attributes->default_tunnel_encap_list,
256 25612 : local_as_);
257 : }
258 :
259 12810 : if (private_as_action_ == "remove") {
260 2 : policy.SetRemovePrivatePolicy(false, false, true);
261 12809 : } else if (private_as_action_ == "remove-all") {
262 2 : policy.SetRemovePrivatePolicy(true, false, true);
263 12806 : } else if (private_as_action_ == "replace-all") {
264 1 : policy.SetRemovePrivatePolicy(true, true, true);
265 : }
266 :
267 12810 : return policy;
268 0 : }
269 :
270 12706 : void BgpPeer::ReceiveEndOfRIB(Address::Family family, size_t msgsize) {
271 12706 : close_manager_->ProcessEORMarkerReceived(family);
272 12708 : eor_receive_timer_[family]->Cancel();
273 :
274 : // If EoR for RTarget is received, start registration for other families.
275 12708 : if (family == Address::RTARGET)
276 2624 : RegisterToVpnTables();
277 12706 : }
278 :
279 12885 : void BgpPeer::SendEndOfRIBActual(Address::Family family) {
280 12885 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
281 :
282 : // Bail if there's no session for the peer anymore.
283 12885 : if (!session_)
284 58 : return;
285 :
286 12827 : BgpProto::Update update;
287 : uint16_t afi;
288 : uint8_t safi;
289 12827 : tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
290 12827 : BgpMpNlri *nlri = new BgpMpNlri(BgpAttribute::MPUnreachNlri, afi, safi);
291 12827 : update.path_attributes.push_back(nlri);
292 : uint8_t data[256];
293 25654 : int msgsize = BgpProto::Encode(&update, data, sizeof(data), NULL,
294 12827 : Is4ByteAsSupported());
295 12827 : assert(msgsize > BgpProto::kMinMessageSize);
296 12827 : session_->Send(data, msgsize, NULL);
297 12827 : inc_tx_end_of_rib();
298 12827 : inc_tx_update();
299 12827 : 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 12885 : }
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 19796 : uint32_t BgpPeer::GetEndOfRibReceiveTime(Address::Family family) const {
315 19796 : return family == Address::RTARGET ?
316 19796 : kRouteTargetEndOfRibTimeSecs : server_->GetEndOfRibReceiveTime();
317 : }
318 :
319 9123 : bool BgpPeer::IsServerStartingUp() const {
320 9123 : return server_->IsServerStartingUp();
321 : }
322 :
323 100 : bool BgpPeer::IsCloseGraceful() const {
324 100 : return peer_close_->IsCloseGraceful();
325 : }
326 :
327 0 : time_t BgpPeer::GetRTargetTableLastUpdatedTimeStamp() const {
328 0 : return server_->GetRTargetTableLastUpdatedTimeStamp();
329 : }
330 :
331 768 : bool BgpPeer::EndOfRibSendTimerExpired(Address::Family family) {
332 768 : if (!IsReady())
333 384 : return false;
334 :
335 : // Send EoR if wait time has exceeded the configured maximum.
336 384 : if (GetEorSendTimerElapsedTime() >= server_->GetEndOfRibSendTime()) {
337 128 : SendEndOfRIBActual(family);
338 128 : return false;
339 : }
340 :
341 : // Defer if output queue has not been fully drained yet.
342 256 : uint32_t output_depth = GetOutputQueueDepth(family);
343 256 : if (output_depth) {
344 128 : eor_send_timer_[family]->Reschedule(kEndOfRibSendRetryTime * 1000);
345 128 : 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 128 : return true;
352 : }
353 :
354 : // Send EoR if we are not still under [re-]starting phase.
355 128 : if (!IsServerStartingUp()) {
356 64 : SendEndOfRIBActual(family);
357 64 : return false;
358 : }
359 :
360 : // Defer if configuration processing is not complete yet.
361 64 : if (!ConfigClientManager::end_of_rib_computed()) {
362 32 : eor_send_timer_[family]->Reschedule(kEndOfRibSendRetryTime * 1000);
363 32 : 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 32 : 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 32 : if (family != Address::RTARGET) {
376 16 : eor_send_timer_[family]->Reschedule(kEndOfRibSendRetryTime * 1000);
377 16 : 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 16 : return true;
384 : }
385 :
386 : // Defer EoR if any new route-target was added to the table recently (6s).
387 16 : if (UTCTimestamp() - GetRTargetTableLastUpdatedTimeStamp() <
388 16 : 0.02 * server_->GetEndOfRibSendTime()) {
389 4 : eor_send_timer_[family]->Reschedule(kEndOfRibSendRetryTime * 1000);
390 4 : 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 4 : return true;
397 : }
398 :
399 : // Send eor as [re-]starting phase is complete for this family.
400 12 : SendEndOfRIBActual(family);
401 12 : return false;
402 : }
403 :
404 28 : void BgpPeer::SendEndOfRIB(Address::Family family) {
405 28 : eor_send_timer_start_time_ = UTCTimestamp();
406 28 : 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 28 : eor_send_timer_[family]->Start(kEndOfRibSendRetryTime * 1000,
412 : boost::bind(&BgpPeer::EndOfRibSendTimerExpired, this, family),
413 : boost::bind(&BgpPeer::EndOfRibTimerErrorHandler, this, _1, _2));
414 28 : }
415 :
416 42049 : void BgpPeer::BGPPeerInfoSend(const BgpPeerInfoData &peer_info) const {
417 42049 : assert(!peer_info.get_name().empty());
418 42048 : BGP_UVE_SEND(BGPPeerInfo, peer_info);
419 42050 : }
420 :
421 13061 : bool BgpPeer::CanUseMembershipManager() const {
422 13061 : 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 27840 : void BgpPeer::MembershipRequestCallback(BgpTable *table) {
431 27840 : if (close_manager_->IsMembershipInUse()) {
432 14960 : close_manager_->MembershipRequestCallback();
433 14960 : return;
434 : }
435 :
436 12880 : assert(membership_req_pending_ > 0);
437 12880 : membership_req_pending_--;
438 :
439 : // Resume if CloseManager is waiting to use membership manager.
440 20372 : if (!membership_req_pending_ &&
441 7492 : close_manager_->IsMembershipInWait()) {
442 23 : 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 12880 : if (defer_close_) {
448 107 : if (!membership_req_pending_) {
449 49 : defer_close_ = false;
450 49 : trigger_.Set();
451 : }
452 107 : return;
453 : }
454 :
455 12773 : SendEndOfRIB(table->family());
456 : }
457 :
458 80811 : bool BgpPeer::MembershipPathCallback(DBTablePartBase *tpart, BgpRoute *route,
459 : BgpPath *path) {
460 80811 : return close_manager_->MembershipPathCallback(tpart, route, path);
461 : }
462 :
463 48 : bool BgpPeer::ResumeClose() {
464 48 : peer_close_->Close(graceful_close_);
465 49 : graceful_close_ = true;
466 49 : return true;
467 : }
468 :
469 10358 : BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,
470 10358 : const BgpNeighborConfig *config)
471 10358 : : server_(server),
472 10358 : rtinstance_(instance),
473 10358 : peer_key_(config),
474 10358 : peer_port_(config->source_port()),
475 10358 : peer_name_(config->name()),
476 10358 : router_type_(config->router_type()),
477 10358 : config_(config),
478 10358 : index_(server->RegisterPeer(this)),
479 10358 : trigger_(boost::bind(&BgpPeer::ResumeClose, this),
480 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
481 : GetTaskInstance()),
482 10358 : prefix_limit_idle_timer_(
483 10358 : TimerManager::CreateTimer(*server->ioservice(),
484 : "BGP prefix limit idle timer",
485 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
486 : GetTaskInstance())),
487 10358 : prefix_limit_trigger_(boost::bind(&BgpPeer::CheckPrefixLimits, this),
488 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
489 : GetTaskInstance()),
490 10358 : buffer_capacity_(GetBufferCapacity()),
491 10358 : session_(NULL),
492 10358 : keepalive_timer_(TimerManager::CreateTimer(*server->ioservice(),
493 : "BGP keepalive timer",
494 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
495 : GetTaskInstance())),
496 10358 : eor_send_timer_start_time_(0),
497 10358 : send_ready_(true),
498 10358 : admin_down_(config->admin_down()),
499 10358 : passive_(config->passive()),
500 10358 : resolve_paths_(config->router_type() == "bgpaas-client"),
501 10358 : as_override_(config->as_override()),
502 10358 : cluster_id_(config->cluster_id()),
503 10358 : origin_override_(config->origin_override()),
504 10358 : defer_close_(false),
505 10358 : graceful_close_(true),
506 10358 : as4_supported_(false),
507 10358 : vpn_tables_registered_(false),
508 10358 : hold_time_(config->hold_time()),
509 10358 : local_as_(config->local_as()),
510 10358 : peer_as_(config->peer_as()),
511 10358 : local_bgp_id_(config->local_identifier()),
512 10358 : peer_bgp_id_(0),
513 10358 : peer_type_((config->peer_as() == config->local_as()) ?
514 : BgpProto::IBGP : BgpProto::EBGP),
515 10358 : state_machine_(BgpStaticObjectFactory::Create<StateMachine>(this)),
516 10358 : peer_close_(BgpStaticObjectFactory::Create<BgpPeerClose>(this)),
517 10358 : peer_stats_(new PeerStats(this)),
518 10358 : deleter_(new DeleteActor(this)),
519 10358 : instance_delete_ref_(this, instance ? instance->deleter() : NULL),
520 10358 : flap_count_(0),
521 10358 : total_flap_count_(0),
522 10358 : last_flap_(0),
523 10358 : dscp_listener_id_(-1),
524 10358 : inuse_authkey_type_(AuthenticationData::NIL),
525 10358 : asn_listener_id_(-1),
526 207160 : instance_op_(-1) {
527 10358 : buffer_.reserve(buffer_capacity_);
528 10358 : close_manager_.reset(
529 10358 : BgpStaticObjectFactory::Create<PeerCloseManager>(static_cast<IPeerClose*>(peer_close_.get())));
530 10358 : ostringstream oss1;
531 10358 : oss1 << peer_key_.endpoint.address();
532 10358 : if (peer_key_.endpoint.port() != BgpConfigManager::kDefaultPort)
533 4005 : oss1 << ":" << dec << peer_key_.endpoint.port();
534 10358 : to_str_ = oss1.str();
535 :
536 10358 : ostringstream oss2;
537 10358 : if (rtinstance_)
538 9567 : oss2 << rtinstance_->name() << ":";
539 10358 : oss2 << server_->localname() << ":";
540 10358 : oss2 << peer_name();
541 10358 : uve_key_str_ = oss2.str();
542 :
543 20714 : if (router_type_ == "control-node" ||
544 10356 : router_type_ == "external-control-node") {
545 26 : peer_is_control_node_ = true;
546 : } else {
547 10332 : peer_is_control_node_ = false;
548 : }
549 :
550 10358 : dscp_listener_id_ = server_->RegisterDSCPUpdateCallback(boost::bind(
551 : &BgpPeer::DSCPUpdateCallback, this, _1));
552 10358 : if (IsRouterTypeBGPaaS()) {
553 114 : asn_listener_id_ = server->RegisterASNUpdateCallback(boost::bind(
554 : &BgpPeer::ASNUpdateCallback, this, _1, _2));
555 114 : instance_op_=server->routing_instance_mgr()->RegisterInstanceOpCallback(
556 : boost::bind(&BgpPeer::RoutingInstanceCallback, this, _1, _2));
557 : }
558 :
559 10358 : membership_req_pending_ = 0;
560 10358 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
561 : BGP_PEER_DIR_NA, "Created");
562 :
563 10358 : if (rtinstance_ && peer_name_.find(rtinstance_->name()) == 0) {
564 9408 : peer_basename_ = peer_name_.substr(rtinstance_->name().size() + 1);
565 : } else {
566 950 : peer_basename_ = peer_name_;
567 : }
568 :
569 10358 : for (Address::Family family = Address::UNSPEC;
570 113938 : family < Address::NUM_FAMILIES;
571 103580 : family = static_cast<Address::Family>(family + 1)) {
572 103580 : family_primary_path_count_[family] = 0;
573 207160 : eor_send_timer_[family] =
574 310740 : TimerManager::CreateTimer(*server->ioservice(),
575 207160 : "BGP EoR Send timer for " + Address::FamilyToString(family),
576 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
577 : GetTaskInstance());
578 207160 : eor_receive_timer_[family] =
579 310740 : TimerManager::CreateTimer(*server->ioservice(),
580 207160 : "BGP EoR Receive timer for " + Address::FamilyToString(family),
581 : TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
582 : GetTaskInstance());
583 : }
584 :
585 10358 : total_path_count_ = 0;
586 10358 : primary_path_count_ = 0;
587 :
588 : // Check rtinstance_ to accommodate unit tests.
589 10358 : if (resolve_paths_ && rtinstance_) {
590 112 : rtinstance_->GetTable(Address::INET)->LocatePathResolver();
591 112 : rtinstance_->GetTable(Address::INET6)->LocatePathResolver();
592 : }
593 :
594 10358 : ProcessEndpointConfig(config);
595 10358 : ProcessAuthKeyChainConfig(config);
596 10358 : ProcessFamilyAttributesConfig(config);
597 :
598 20716 : BgpPeerInfoData peer_info;
599 10358 : peer_info.set_name(ToUVEKey());
600 10358 : peer_info.set_admin_down(admin_down_);
601 10358 : peer_info.set_passive(passive_);
602 10358 : peer_info.set_as_override(as_override_);
603 10358 : peer_info.set_origin_override(origin_override_.origin_override);
604 10358 : if (origin_override_.origin_override) {
605 3 : peer_info.set_route_origin(
606 6 : BgpAttr::OriginToString(origin_override_.origin));
607 : } else {
608 10355 : peer_info.set_route_origin("-");
609 : }
610 10358 : peer_info.set_router_type(router_type_);
611 10358 : peer_info.set_cluster_id(Ip4Address(cluster_id_).to_string());
612 20716 : peer_info.set_peer_type(
613 10358 : PeerType() == BgpProto::IBGP ? "internal" : "external");
614 10358 : peer_info.set_local_asn(local_as_);
615 10358 : peer_info.set_peer_asn(peer_as_);
616 10358 : peer_info.set_peer_port(peer_port_);
617 10358 : peer_info.set_hold_time(hold_time_);
618 10358 : peer_info.set_local_id(local_bgp_id_);
619 10358 : peer_info.set_configured_families(configured_families_);
620 10358 : peer_info.set_peer_address(peer_key_.endpoint.address().to_string());
621 10358 : BGPPeerInfoSend(peer_info);
622 10358 : }
623 :
624 15738 : BgpPeer::~BgpPeer() {
625 10358 : assert(!close_manager()->IsCloseInProgress());
626 10358 : assert(!IsCloseInProgress());
627 10358 : assert(GetTotalPathCount() == 0);
628 10358 : STLDeleteValues(&family_attributes_list_);
629 10358 : ClearListenSocketAuthKey();
630 20716 : BgpPeerInfoData peer_info;
631 10358 : peer_info.set_name(ToUVEKey());
632 10358 : peer_info.set_deleted(true);
633 10358 : BGPPeerInfoSend(peer_info);
634 :
635 20716 : PeerStatsData peer_stats_data;
636 10358 : peer_stats_data.set_name(ToUVEKey());
637 10358 : peer_stats_data.set_deleted(true);
638 10358 : assert(!peer_stats_data.get_name().empty());
639 10358 : BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectBgpPeer");
640 :
641 20716 : PeerFlapData peer_flap_data;
642 10358 : peer_flap_data.set_name(ToUVEKey());
643 10358 : peer_flap_data.set_deleted(true);
644 10358 : assert(!peer_flap_data.get_name().empty());
645 10358 : BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
646 :
647 10358 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
648 : BGP_PEER_DIR_NA, "Deleted");
649 15738 : }
650 :
651 9567 : void BgpPeer::Initialize() {
652 9567 : if (!admin_down_)
653 9537 : state_machine_->Initialize();
654 9567 : }
655 :
656 10358 : size_t BgpPeer::GetBufferCapacity() const {
657 : // For testing only - configure through environment variable.
658 10358 : char *buffer_capacity_str = getenv("BGP_PEER_BUFFER_SIZE");
659 10358 : if (buffer_capacity_str) {
660 5 : size_t env_buffer_capacity = strtoul(buffer_capacity_str, NULL, 0);
661 5 : if (env_buffer_capacity < kMinBufferCapacity)
662 2 : env_buffer_capacity = kMinBufferCapacity;
663 5 : if (env_buffer_capacity > kMaxBufferCapacity)
664 1 : env_buffer_capacity = kMaxBufferCapacity;
665 5 : return env_buffer_capacity;
666 : }
667 :
668 : // Return internal default based on peer router-type.
669 10353 : if (IsRouterTypeBGPaaS()) {
670 113 : return kMinBufferCapacity;
671 : } else {
672 10240 : return kMaxBufferCapacity;
673 : }
674 : }
675 :
676 36991 : bool BgpPeer::CheckSplitHorizon(uint32_t server_cluster_id,
677 : uint32_t ribout_cid) const {
678 36991 : if (PeerType() == BgpProto::IBGP) {
679 : // check if router is a route reflector
680 36826 : 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 167 : return false;
691 : }
692 :
693 434 : BgpTable *BgpPeer::GetRTargetTable() {
694 434 : RoutingInstanceMgr *instance_mgr = server_->routing_instance_mgr();
695 434 : if (!instance_mgr)
696 0 : return NULL;
697 434 : RoutingInstance *master = instance_mgr->GetDefaultRoutingInstance();
698 434 : if (!master)
699 0 : return NULL;
700 434 : return master->GetTable(Address::RTARGET);
701 : }
702 :
703 196 : BgpAttrPtr BgpPeer::GetRouteTargetRouteAttr() const {
704 196 : BgpAttrSpec attrs;
705 196 : BgpAttrNextHop nexthop(server_->bgp_identifier());
706 196 : attrs.push_back(&nexthop);
707 196 : BgpAttrOrigin origin(BgpAttrOrigin::IGP);
708 196 : attrs.push_back(&origin);
709 392 : return server_->attr_db()->Locate(attrs);
710 196 : }
711 :
712 : // Add one route-target route to bgp.rtarget.0 table.
713 588 : void BgpPeer::BGPaaSAddRTarget(as_t as, BgpTable *table, BgpAttrPtr attr,
714 : RouteTargetList::const_iterator it) {
715 588 : const RouteTarget rtarget = *it;
716 588 : DBRequest req;
717 588 : RTargetPrefix rt_prefix(as, rtarget);
718 588 : req.key.reset(new RTargetTable::RequestKey(rt_prefix, this));
719 588 : req.data.reset(new RTargetTable::RequestData(attr, 0, 0, 0, 0));
720 588 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
721 588 : table->Enqueue(&req);
722 588 : }
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 196 : void BgpPeer::AddRTargets(as_t as) {
727 196 : if (!IsRouterTypeBGPaaS())
728 0 : return;
729 196 : assert(IsReady());
730 196 : BgpTable *table = GetRTargetTable();
731 196 : assert(table);
732 196 : BgpAttrPtr attr = GetRouteTargetRouteAttr();
733 196 : rtargets_ = rtinstance_->GetImportList();
734 196 : for (RouteTargetList::const_iterator it = rtargets_.begin();
735 784 : it != rtargets_.end(); it++) {
736 588 : BGPaaSAddRTarget(as, table, attr, it);
737 : }
738 196 : }
739 :
740 : // Delete one route-target route from bgp.rtarget.0 table.
741 204 : void BgpPeer::BGPaaSDeleteRTarget(as_t as, BgpTable *table,
742 : RouteTargetList::const_iterator it) {
743 204 : const RouteTarget rtarget = *it;
744 204 : DBRequest req;
745 204 : RTargetPrefix rt_prefix(as, rtarget);
746 204 : req.key.reset(new RTargetTable::RequestKey(rt_prefix, this));
747 204 : req.oper = DBRequest::DB_ENTRY_DELETE;
748 204 : table->Enqueue(&req);
749 204 : }
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 12399 : void BgpPeer::DeleteRTargets(as_t as) {
755 12399 : if (!IsRouterTypeBGPaaS())
756 12161 : return;
757 238 : BgpTable *table = GetRTargetTable();
758 238 : if (!table)
759 36 : return;
760 202 : for (RouteTargetList::const_iterator it = rtargets_.begin();
761 406 : it != rtargets_.end(); it++) {
762 204 : BGPaaSDeleteRTarget(as, table, it);
763 : }
764 202 : rtargets_.clear();
765 : }
766 :
767 38 : void BgpPeer::ASNUpdateCallback(as_t old_asn, as_t old_local_asn) {
768 38 : CHECK_CONCURRENCY("bgp::Config");
769 38 : DeleteRTargets(old_local_asn);
770 38 : if (!IsReady())
771 38 : 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 306 : void BgpPeer::RoutingInstanceCallback(const std::string &vrf_name, int op) {
779 306 : assert(IsRouterTypeBGPaaS());
780 306 : if (op != RoutingInstanceMgr::INSTANCE_UPDATE || !IsReady())
781 306 : return;
782 2 : if (vrf_name != rtinstance_->name())
783 2 : 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 10498 : void BgpPeer::NotifyEstablished(bool established) {
798 10498 : if (established) {
799 5248 : if (IsRouterTypeBGPaaS()) {
800 196 : server_->IncrementUpBgpaasPeerCount();
801 196 : AddRTargets(server_->local_autonomous_system());
802 : } else {
803 5052 : server_->IncrementUpPeerCount();
804 : }
805 : } else {
806 5250 : if (IsRouterTypeBGPaaS()) {
807 196 : server_->DecrementUpBgpaasPeerCount();
808 : } else {
809 5053 : server_->DecrementUpPeerCount();
810 : }
811 : }
812 10500 : }
813 :
814 170 : void BgpPeer::BindLocalEndpoint(BgpSession *session) {
815 170 : }
816 :
817 : // Just return the first entry for now.
818 208 : bool BgpPeer::GetBestAuthKey(AuthenticationKey *auth_key,
819 : KeyType *key_type) const {
820 208 : if (auth_data_.Empty()) {
821 6 : return false;
822 : }
823 202 : assert(auth_key);
824 202 : AuthenticationData::const_iterator iter = auth_data_.begin();
825 202 : *auth_key = *iter;
826 202 : *key_type = auth_data_.key_type();
827 202 : return true;
828 : }
829 :
830 20423 : bool BgpPeer::ProcessAuthKeyChainConfig(const BgpNeighborConfig *config) {
831 20423 : const AuthenticationData &input_auth_data = config->auth_data();
832 :
833 20423 : if (auth_data_ == input_auth_data) {
834 20215 : return false;
835 : }
836 :
837 208 : auth_data_ = input_auth_data;
838 208 : return InstallAuthKeys();
839 : }
840 :
841 208 : bool BgpPeer::InstallAuthKeys() {
842 208 : if (!PeerAddress()) {
843 0 : return false;
844 : }
845 :
846 208 : AuthenticationKey auth_key;
847 : KeyType key_type;
848 208 : bool valid = GetBestAuthKey(&auth_key, &key_type);
849 208 : if (valid) {
850 202 : if (key_type == AuthenticationData::MD5) {
851 202 : LogInstallAuthKeys("Listen", "add", auth_key, key_type);
852 202 : SetListenSocketAuthKey(auth_key, key_type);
853 202 : 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 6 : if (inuse_authkey_type_ == AuthenticationData::MD5) {
859 6 : LogInstallAuthKeys("Listen", "delete", inuse_auth_key_,
860 : inuse_authkey_type_);
861 6 : ClearListenSocketAuthKey();
862 : // Resetting the key information must be done last.
863 6 : ResetInuseAuthKeyInfo();
864 : }
865 : }
866 208 : return true;
867 208 : }
868 :
869 202 : void BgpPeer::SetInuseAuthKeyInfo(const AuthenticationKey &key, KeyType type) {
870 202 : inuse_auth_key_ = key;
871 202 : inuse_authkey_type_ = type;
872 202 : }
873 :
874 6 : void BgpPeer::ResetInuseAuthKeyInfo() {
875 6 : inuse_auth_key_.Reset();
876 6 : inuse_authkey_type_ = AuthenticationData::NIL;
877 6 : }
878 :
879 202 : void BgpPeer::SetListenSocketAuthKey(const AuthenticationKey &auth_key,
880 : KeyType key_type) {
881 202 : if (key_type == AuthenticationData::MD5) {
882 202 : server_->session_manager()->
883 202 : SetListenSocketMd5Option(PeerAddress(), auth_key.value);
884 : }
885 202 : }
886 :
887 10375 : void BgpPeer::ClearListenSocketAuthKey() {
888 10375 : if (inuse_authkey_type_ == AuthenticationData::MD5) {
889 162 : server_->session_manager()->SetListenSocketMd5Option(PeerAddress(), "");
890 : }
891 10375 : }
892 :
893 10876 : void BgpPeer::SetSessionSocketAuthKey(TcpSession *session) {
894 10876 : if ((inuse_authkey_type_ == AuthenticationData::MD5) && PeerAddress()) {
895 1248 : assert(!inuse_auth_key_.value.empty());
896 1248 : LogInstallAuthKeys("Session", "add", inuse_auth_key_,
897 : inuse_authkey_type_);
898 1248 : session->SetMd5SocketOption(PeerAddress(), inuse_auth_key_.value);
899 : }
900 10876 : }
901 :
902 4169 : void BgpPeer::SetSessionSocketOptionDscp(TcpSession *session) {
903 4169 : uint8_t dscp_value = server_->global_qos()->control_dscp();
904 :
905 4169 : if (!session->socket()) {
906 139 : return;
907 : }
908 4030 : if (dscp_value != 0xFF) {
909 4030 : session->SetDscpSocketOption(server_->global_qos()->control_dscp());
910 : }
911 : }
912 :
913 194 : string BgpPeer::GetInuseAuthKeyValue() const {
914 194 : return inuse_auth_key_.value;
915 : }
916 :
917 1456 : void BgpPeer::LogInstallAuthKeys(const string &socket_name,
918 : const string &oper, const AuthenticationKey &auth_key,
919 : KeyType key_type) {
920 2912 : string logstr = socket_name + " socket kernel " + oper + " of key id "
921 5824 : + integerToString(auth_key.id) + ", type "
922 2912 : + AuthenticationData::KeyTypeToString(key_type)
923 4368 : + ", peer " + peer_name_;
924 1456 : BGP_LOG_PEER(Config, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
925 : BGP_PEER_DIR_NA, logstr);
926 1456 : }
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 10016 : bool BgpPeer::CheckPrefixLimits() {
934 10016 : RetryDelete();
935 10017 : if (!IsReady())
936 9606 : return true;
937 4134 : for (size_t idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
938 : BgpPeerFamilyAttributes *family_attributes =
939 3769 : family_attributes_list_[idx];
940 3769 : if (!family_attributes || family_attributes->prefix_limit == 0)
941 3721 : continue;
942 48 : if (family_primary_path_count_[idx] <= family_attributes->prefix_limit)
943 0 : continue;
944 48 : Clear(BgpProto::Notification::MaxPrefixes);
945 48 : StartPrefixLimitIdleTimer(family_attributes->idle_timeout * 1000);
946 48 : break;
947 : }
948 413 : 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 20423 : bool BgpPeer::ProcessFamilyAttributesConfig(const BgpNeighborConfig *config) {
958 20423 : FamilyAttributesList family_attributes_list(Address::NUM_FAMILIES);
959 85655 : BOOST_FOREACH(const BgpFamilyAttributesConfig family_config,
960 : config->family_attributes_list()) {
961 : Address::Family family =
962 32616 : Address::FamilyFromString(family_config.family);
963 32616 : assert(family != Address::UNSPEC);
964 : BgpPeerFamilyAttributes *family_attributes =
965 32616 : new BgpPeerFamilyAttributes(config, family_config);
966 32616 : family_attributes_list[family] = family_attributes;
967 32616 : }
968 :
969 20423 : int ret = STLSortedCompare(
970 : family_attributes_list.begin(), family_attributes_list.end(),
971 : family_attributes_list_.begin(), family_attributes_list_.end(),
972 : BgpPeerFamilyAttributesCompare());
973 20423 : STLDeleteValues(&family_attributes_list_);
974 20423 : family_attributes_list_ = family_attributes_list;
975 20423 : configured_families_ = config->GetAddressFamilies();
976 20423 : return (ret != 0);
977 20423 : }
978 :
979 20423 : void BgpPeer::ProcessEndpointConfig(const BgpNeighborConfig *config) {
980 20423 : if (config->router_type() == "bgpaas-client") {
981 204 : endpoint_ = TcpSession::Endpoint(Ip4Address(), config->source_port());
982 : } else {
983 20219 : endpoint_ = TcpSession::Endpoint();
984 : }
985 20423 : }
986 :
987 10020 : void BgpPeer::TriggerPrefixLimitCheck() const {
988 10020 : prefix_limit_trigger_.Set();
989 10020 : }
990 :
991 10065 : void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
992 10065 : if (IsDeleted())
993 0 : return;
994 :
995 10065 : 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 10065 : if (!config_)
1000 0 : return;
1001 :
1002 10065 : bool clear_session = false;
1003 10065 : bool admin_down_changed = false;
1004 20130 : BgpPeerInfoData peer_info;
1005 10065 : peer_info.set_name(ToUVEKey());
1006 :
1007 10065 : 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 10065 : if (passive_ != config->passive()) {
1014 24 : passive_ = config->passive();
1015 24 : peer_info.set_passive(passive_);
1016 24 : clear_session = true;
1017 : }
1018 :
1019 10065 : if (as_override_ != config->as_override()) {
1020 2 : as_override_ = config->as_override();
1021 2 : peer_info.set_as_override(as_override_);
1022 2 : clear_session = true;
1023 : }
1024 :
1025 10065 : 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 10065 : OriginOverride origin_override(config->origin_override());
1032 10065 : if (origin_override_ != origin_override) {
1033 2 : origin_override_ = origin_override;
1034 2 : peer_info.set_origin_override(origin_override_.origin_override);
1035 2 : if (origin_override_.origin_override) {
1036 1 : peer_info.set_route_origin(config->origin_override().origin);
1037 : } else {
1038 1 : peer_info.set_route_origin("-");
1039 : }
1040 2 : clear_session = true;
1041 : }
1042 :
1043 10065 : 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 20130 : if (router_type_ == "control-node" ||
1050 10065 : router_type_ == "external-control-node") {
1051 26 : peer_is_control_node_ = true;
1052 : } else {
1053 10039 : 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 10065 : BgpPeerKey key(config);
1061 10065 : if (peer_key_ != key) {
1062 11 : ClearListenSocketAuthKey();
1063 11 : peer_key_ = key;
1064 11 : peer_info.set_peer_address(peer_key_.endpoint.address().to_string());
1065 11 : clear_session = true;
1066 : }
1067 10065 : if (ProcessAuthKeyChainConfig(config)) {
1068 61 : clear_session = true;
1069 : }
1070 :
1071 10065 : if (peer_port_ != config->source_port()) {
1072 8 : peer_port_ = config->source_port();
1073 8 : peer_info.set_peer_port(peer_port_);
1074 8 : clear_session = true;
1075 : }
1076 10065 : ProcessEndpointConfig(config);
1077 :
1078 10065 : if (local_as_ != config->local_as()) {
1079 221 : 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 221 : local_as_ = config->local_as();
1086 221 : peer_info.set_local_asn(local_as_);
1087 221 : clear_session = true;
1088 : }
1089 :
1090 10065 : 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 10065 : if (peer_as_ != config->peer_as()) {
1103 194 : 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 194 : peer_as_ = config->peer_as();
1110 194 : peer_info.set_peer_asn(peer_as_);
1111 194 : clear_session = true;
1112 : }
1113 :
1114 10065 : boost::system::error_code ec;
1115 10065 : uint32_t local_bgp_id = config->local_identifier();
1116 10065 : if (local_bgp_id_ != local_bgp_id) {
1117 75 : local_bgp_id_ = local_bgp_id;
1118 75 : peer_info.set_local_id(local_bgp_id_);
1119 75 : clear_session = true;
1120 : }
1121 :
1122 10065 : BgpProto::BgpPeerType old_type = PeerType();
1123 10065 : peer_type_ = (peer_as_ == local_as_) ? BgpProto::IBGP : BgpProto::EBGP;
1124 10065 : if (old_type != PeerType()) {
1125 98 : peer_info.set_peer_type(
1126 49 : PeerType() == BgpProto::IBGP ? "internal" : "external");
1127 49 : clear_session = true;
1128 : }
1129 :
1130 : // Check if there is any change in private-as-action configuration.
1131 10065 : if (private_as_action_ != config->private_as_action()) {
1132 12 : private_as_action_ = config->private_as_action();
1133 12 : clear_session = true;
1134 : }
1135 :
1136 : // Check if there is any change in the configured address families.
1137 10065 : if (ProcessFamilyAttributesConfig(config)) {
1138 87 : peer_info.set_configured_families(configured_families_);
1139 87 : clear_session = true;
1140 : } else {
1141 9978 : 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 10065 : if (!admin_down_changed && !admin_down_ && clear_session) {
1148 644 : 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 644 : Clear(BgpProto::Notification::OtherConfigChange);
1152 : }
1153 :
1154 : // Send the UVE as appropriate.
1155 10065 : if (admin_down_changed || clear_session) {
1156 764 : StopPrefixLimitIdleTimer();
1157 764 : BGPPeerInfoSend(peer_info);
1158 : }
1159 10065 : }
1160 :
1161 6711 : void BgpPeer::ClearConfig() {
1162 6711 : CHECK_CONCURRENCY("bgp::Config");
1163 6711 : config_ = NULL;
1164 6711 : }
1165 :
1166 6269 : LifetimeActor *BgpPeer::deleter() {
1167 6269 : return deleter_.get();
1168 : }
1169 :
1170 : //
1171 : // Check if the given address family has been negotiated with the peer.
1172 : //
1173 539275 : bool BgpPeer::IsFamilyNegotiated(Address::Family family) {
1174 : // Bail if the family is not configured locally.
1175 539275 : if (!LookupFamily(family))
1176 48530 : return false;
1177 :
1178 : // Check if the peer advertised it in his Open message.
1179 : uint16_t afi;
1180 : uint8_t safi;
1181 490792 : tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
1182 490798 : return MpNlriAllowed(afi, safi);
1183 : }
1184 :
1185 : // Release resources for a peer that is going to be deleted.
1186 9574 : void BgpPeer::PostCloseRelease() {
1187 9574 : if (index_ != -1) {
1188 9574 : server_->UnregisterPeer(this);
1189 9574 : index_ = -1;
1190 : }
1191 9574 : TimerManager::DeleteTimer(keepalive_timer_);
1192 9574 : TimerManager::DeleteTimer(prefix_limit_idle_timer_);
1193 :
1194 9574 : for (Address::Family family = Address::UNSPEC;
1195 105314 : family < Address::NUM_FAMILIES;
1196 95740 : family = static_cast<Address::Family>(family + 1)) {
1197 95740 : TimerManager::DeleteTimer(eor_send_timer_[family]);
1198 95740 : TimerManager::DeleteTimer(eor_receive_timer_[family]);
1199 : }
1200 9574 : }
1201 :
1202 : // IsReady
1203 : //
1204 : // Check whether this peer is up and ready
1205 : //
1206 716169 : bool BgpPeer::IsReady() const {
1207 716169 : return state_machine_->get_state() == StateMachine::ESTABLISHED;
1208 : }
1209 :
1210 733266 : bool BgpPeer::IsXmppPeer() const {
1211 733266 : return false;
1212 : }
1213 :
1214 0 : uint32_t BgpPeer::local_bgp_identifier() const {
1215 0 : return ntohl(local_bgp_id_);
1216 : }
1217 :
1218 16 : string BgpPeer::local_bgp_identifier_string() const {
1219 32 : return Ip4Address(ntohl(local_bgp_id_)).to_string();
1220 : }
1221 :
1222 12520 : uint32_t BgpPeer::bgp_identifier() const {
1223 12520 : return ntohl(peer_bgp_id_);
1224 : }
1225 :
1226 5298 : string BgpPeer::bgp_identifier_string() const {
1227 10599 : return Ip4Address(ntohl(peer_bgp_id_)).to_string();
1228 : }
1229 :
1230 112 : string BgpPeer::transport_address_string() const {
1231 112 : TcpSession::Endpoint endpoint;
1232 112 : ostringstream oss;
1233 112 : if (session_)
1234 108 : endpoint = session_->remote_endpoint();
1235 112 : oss << endpoint;
1236 224 : return oss.str();
1237 112 : }
1238 :
1239 8 : string BgpPeer::gateway_address_string(Address::Family family) const {
1240 8 : if (!family_attributes_list_[family])
1241 0 : return string();
1242 8 : 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 14780 : void BgpPeer::CustomClose() {
1251 14780 : ResetCapabilities();
1252 14779 : keepalive_timer_->Cancel();
1253 :
1254 14779 : for (Address::Family family = Address::UNSPEC;
1255 162576 : family < Address::NUM_FAMILIES;
1256 147797 : family = static_cast<Address::Family>(family + 1)) {
1257 147796 : eor_send_timer_[family]->Cancel();
1258 147796 : eor_receive_timer_[family]->Cancel();
1259 : }
1260 :
1261 14780 : if (close_manager_->IsInDeleteState())
1262 12361 : DeleteRTargets(server_->local_autonomous_system());
1263 14780 : }
1264 :
1265 : //
1266 : // Close this peer by closing all of it's RIBs.
1267 : //
1268 15608 : void BgpPeer::Close(bool graceful) {
1269 15608 : send_ready_ = true;
1270 15608 : if (membership_req_pending_ && !close_manager_->IsMembershipInUse()) {
1271 49 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
1272 : BGP_PEER_DIR_NA, "Close procedure deferred");
1273 49 : defer_close_ = true;
1274 :
1275 : // Note down non-graceful closures. Once a close is non-graceful,
1276 : // it shall remain as non-graceful.
1277 49 : graceful_close_ &= graceful;
1278 49 : return;
1279 : }
1280 :
1281 15556 : peer_close_->Close(graceful);
1282 : }
1283 :
1284 192 : IPeerClose *BgpPeer::peer_close() {
1285 192 : return peer_close_.get();
1286 : }
1287 :
1288 150600 : IPeerClose *BgpPeer::peer_close() const {
1289 150600 : return peer_close_.get();
1290 : }
1291 :
1292 150599 : void BgpPeer::UpdateCloseRouteStats(Address::Family family,
1293 : const BgpPath *old_path, uint32_t path_flags) const {
1294 150599 : peer_close()->UpdateRouteStats(family, old_path, path_flags);
1295 150600 : }
1296 :
1297 164216 : IPeerDebugStats *BgpPeer::peer_stats() {
1298 164216 : return peer_stats_.get();
1299 : }
1300 :
1301 300 : const IPeerDebugStats *BgpPeer::peer_stats() const {
1302 300 : return peer_stats_.get();
1303 : }
1304 :
1305 10519 : void BgpPeer::Clear(int subcode) {
1306 10519 : CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine");
1307 10519 : state_machine_->Shutdown(subcode);
1308 10519 : }
1309 :
1310 : //
1311 : // Check whether this peer has been marked for deletion from configuration
1312 : //
1313 56916 : bool BgpPeer::IsDeleted() const {
1314 56916 : return deleter_->IsDeleted();
1315 : }
1316 :
1317 1859 : bool BgpPeer::IsInGRTimerWaitState() const {
1318 1859 : return close_manager_->IsInGRTimerWaitState();
1319 : }
1320 :
1321 38041 : bool BgpPeer::IsCloseInProgress() const {
1322 38041 : CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine");
1323 :
1324 : // trigger is set only after defer_close is reset
1325 38041 : assert(!(defer_close_ && trigger_.IsSet()));
1326 77472 : return defer_close_ || trigger_.IsSet() ||
1327 38020 : (close_manager_->IsCloseInProgress() &&
1328 39452 : !IsInGRTimerWaitState());
1329 : }
1330 :
1331 19020 : StateMachine::State BgpPeer::GetState() const {
1332 19020 : return state_machine_->get_state();
1333 : }
1334 :
1335 0 : const string BgpPeer::GetStateName() const {
1336 0 : return state_machine_->StateName();
1337 : }
1338 :
1339 6902 : BgpSession *BgpPeer::CreateSession() {
1340 6902 : if (PrefixLimitIdleTimerRunning())
1341 116 : return NULL;
1342 :
1343 6785 : TcpSession *session = server_->session_manager()->CreateSession();
1344 6777 : if (session == NULL)
1345 76 : return NULL;
1346 :
1347 : // Set valid keys, if any, in the socket.
1348 6701 : SetSessionSocketAuthKey(session);
1349 :
1350 6707 : BgpSession *bgp_session = static_cast<BgpSession *>(session);
1351 6707 : BindLocalEndpoint(bgp_session);
1352 6710 : bgp_session->set_peer(this);
1353 6710 : return bgp_session;
1354 : }
1355 :
1356 889 : void BgpPeer::SetAdminState(bool down, int subcode) {
1357 889 : CHECK_CONCURRENCY("bgp::Config");
1358 889 : if (admin_down_ == down)
1359 8 : return;
1360 881 : admin_down_ = down;
1361 881 : state_machine_->SetAdminState(down, subcode);
1362 881 : if (admin_down_) {
1363 476 : 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 4169 : bool BgpPeer::AcceptSession(BgpSession *session) {
1369 4169 : session->set_peer(this);
1370 :
1371 : // Set valid keys, if any, in the socket.
1372 4169 : SetSessionSocketAuthKey(session);
1373 :
1374 : // Set control dscp, if any
1375 4169 : SetSessionSocketOptionDscp(session);
1376 :
1377 4169 : return state_machine_->PassiveOpen(session);
1378 : }
1379 :
1380 12862 : 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 12862 : 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 12862 : if (close_manager_->IsMembershipInWait())
1393 0 : assert(membership_req_pending_ > 0);
1394 12862 : BgpMembershipManager *membership_mgr = server_->membership_mgr();
1395 12862 : membership_req_pending_++;
1396 12879 : membership_mgr->Register(this, table, policy);
1397 :
1398 : // Start EndOfRib receive timer.
1399 12880 : StartEndOfRibReceiveTimer(table->family());
1400 12880 : }
1401 :
1402 6916 : void BgpPeer::Register(BgpTable *table) {
1403 6916 : 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 6916 : if (close_manager_->IsMembershipInWait())
1410 0 : assert(membership_req_pending_ > 0);
1411 6916 : BgpMembershipManager *membership_mgr = server_->membership_mgr();
1412 6916 : membership_mgr->RegisterRibIn(this, table);
1413 :
1414 : // Start EndOfRib receive timer.
1415 6917 : StartEndOfRibReceiveTimer(table->family());
1416 6917 : }
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 5250 : void BgpPeer::RegisterAllTables() {
1432 5250 : RoutingInstance *instance = GetRoutingInstance();
1433 :
1434 5250 : 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 5250 : (Address::INET)(Address::INETMPLS)(Address::INET6);
1439 36714 : BOOST_FOREACH(Address::Family family, family_list) {
1440 15732 : if (!IsFamilyNegotiated(family))
1441 13650 : continue;
1442 2086 : BgpTable *table = instance->GetTable(family);
1443 3182 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
1444 : table, "Register peer with the table");
1445 2084 : Register(table, BuildRibExportPolicy(family));
1446 : }
1447 :
1448 :
1449 10296 : if (((router_type_ == "bgpaas-client") ||
1450 10493 : (router_type_ == "bgpaas-server")) &&
1451 196 : (instance->routing_instance_vxlan() != "")) {
1452 97 : RoutingInstanceMgr *mgr = server()->routing_instance_mgr();
1453 97 : if (mgr != nullptr) {
1454 : RoutingInstance *vxlan_ri =
1455 97 : mgr->GetRoutingInstance(instance->routing_instance_vxlan());
1456 97 : if (vxlan_ri != nullptr) {
1457 97 : BgpTable *table = vxlan_ri->GetTable(Address::EVPN);
1458 194 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_TRACE,
1459 : table, "Register ribin for peer with the table");
1460 97 : Register(table);
1461 : }
1462 : }
1463 : }
1464 :
1465 5247 : vpn_tables_registered_ = false;
1466 5247 : if (!IsFamilyNegotiated(Address::RTARGET)) {
1467 2622 : RegisterToVpnTables();
1468 2622 : return;
1469 : }
1470 :
1471 2627 : Address::Family family = Address::RTARGET;
1472 2627 : BgpTable *table = instance->GetTable(family);
1473 3247 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
1474 : table, "Register peer with the table");
1475 2621 : Register(table, BuildRibExportPolicy(family));
1476 :
1477 : vector<Address::Family> vpn_family_list = list_of
1478 2628 : (Address::INETVPN)(Address::INET6VPN)(Address::ERMVPN)(Address::EVPN)
1479 2628 : (Address::MVPN);
1480 28906 : BOOST_FOREACH(Address::Family vpn_family, vpn_family_list) {
1481 13138 : if (!IsFamilyNegotiated(vpn_family))
1482 6320 : continue;
1483 6819 : BgpTable *table = instance->GetTable(vpn_family);
1484 8752 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_TRACE,
1485 : table, "Register ribin for peer with the table");
1486 6819 : Register(table);
1487 : }
1488 5250 : }
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 9124 : void BgpPeer::SendOpen(TcpSession *session) {
1502 9124 : BgpProto::OpenMessage openmsg;
1503 9126 : openmsg.as_num = local_as_ > 0xffff ? AS_TRANS : local_as_;
1504 9126 : openmsg.holdtime = state_machine_->GetConfiguredHoldTime();
1505 9125 : openmsg.identifier = ntohl(local_bgp_id_);
1506 : BgpProto::OpenMessage::OptParam *opt_param =
1507 9125 : new BgpProto::OpenMessage::OptParam;
1508 :
1509 : static const uint8_t cap_mp[][4] = {
1510 55 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[0]), 0,
1511 55 : BgpAf::FamilyToSafi(supported_families_[0]) },
1512 55 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[1]), 0,
1513 55 : BgpAf::FamilyToSafi(supported_families_[1]) },
1514 55 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[2]), 0,
1515 55 : BgpAf::FamilyToSafi(supported_families_[2]) },
1516 55 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[3]), 0,
1517 55 : BgpAf::FamilyToSafi(supported_families_[3]) },
1518 55 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[4]), 0,
1519 55 : BgpAf::FamilyToSafi(supported_families_[4]) },
1520 55 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[5]), 0,
1521 55 : BgpAf::FamilyToSafi(supported_families_[5]) },
1522 55 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[6]), 0,
1523 55 : BgpAf::FamilyToSafi(supported_families_[6]) },
1524 55 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[7]), 0,
1525 55 : BgpAf::FamilyToSafi(supported_families_[7]) },
1526 55 : { 0, (uint8_t) BgpAf::FamilyToAfi(supported_families_[8]), 0,
1527 55 : BgpAf::FamilyToSafi(supported_families_[8]) },
1528 10116 : };
1529 :
1530 : static const FamilyToCapabilityMap family_to_cap_map = map_list_of
1531 110 : (supported_families_[0], cap_mp[0])
1532 55 : (supported_families_[1], cap_mp[1])
1533 55 : (supported_families_[2], cap_mp[2])
1534 55 : (supported_families_[3], cap_mp[3])
1535 55 : (supported_families_[4], cap_mp[4])
1536 55 : (supported_families_[5], cap_mp[5])
1537 55 : (supported_families_[6], cap_mp[6])
1538 55 : (supported_families_[7], cap_mp[7])
1539 9181 : (supported_families_[8], cap_mp[8]);
1540 :
1541 : // Add capabilities for configured address families.
1542 173290 : BOOST_FOREACH(const FamilyToCapabilityMap::value_type &val,
1543 : family_to_cap_map) {
1544 82073 : if (!LookupFamily(val.first))
1545 55880 : continue;
1546 : BgpProto::OpenMessage::Capability *cap =
1547 : new BgpProto::OpenMessage::Capability(
1548 26195 : BgpProto::OpenMessage::Capability::MpExtension, val.second, 4);
1549 26211 : opt_param->capabilities.push_back(cap);
1550 : }
1551 :
1552 9123 : if (server_->enable_4byte_as()) {
1553 74 : uint32_t asn = ntohl(local_as_);
1554 : BgpProto::OpenMessage::Capability *cap =
1555 : new BgpProto::OpenMessage::Capability(
1556 : BgpProto::OpenMessage::Capability::AS4Support,
1557 74 : (const uint8_t *)(&asn), 4);
1558 74 : opt_param->capabilities.push_back(cap);
1559 : }
1560 9124 : peer_close_->AddGRCapabilities(opt_param);
1561 9118 : peer_close_->AddLLGRCapabilities(opt_param);
1562 :
1563 9119 : if (opt_param->capabilities.size()) {
1564 9119 : openmsg.opt_params.push_back(opt_param);
1565 : } else {
1566 0 : delete opt_param;
1567 : }
1568 : uint8_t data[256];
1569 9118 : int result = BgpProto::Encode(&openmsg, data, sizeof(data));
1570 9125 : assert(result > BgpProto::kMinMessageSize);
1571 9125 : BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
1572 : BGP_PEER_DIR_OUT, "Open " << openmsg.ToString());
1573 9125 : session->Send(data, result, NULL);
1574 9127 : inc_tx_open();
1575 9128 : }
1576 :
1577 6809 : void BgpPeer::SendKeepalive(bool from_timer) {
1578 6809 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
1579 :
1580 : // Bail if there's no session for the peer anymore.
1581 6810 : if (!session_)
1582 0 : return;
1583 :
1584 6810 : BgpProto::Keepalive msg;
1585 : uint8_t data[BgpProto::kMinMessageSize];
1586 6810 : int result = BgpProto::Encode(&msg, data, sizeof(data));
1587 6806 : assert(result == BgpProto::kMinMessageSize);
1588 6806 : SandeshLevel::type log_level = from_timer ? Sandesh::LoggingUtLevel() :
1589 6806 : SandeshLevel::SYS_INFO;
1590 6806 : BGP_LOG_PEER(Message, this, log_level, BGP_LOG_FLAG_SYSLOG,
1591 : BGP_PEER_DIR_OUT, "Keepalive");
1592 6806 : send_ready_ = session_->Send(data, result, NULL);
1593 6807 : inc_tx_keepalive();
1594 6806 : }
1595 :
1596 128825 : static bool SkipUpdateSend() {
1597 : static bool init_;
1598 : static bool skip_;
1599 :
1600 128825 : if (init_) return skip_;
1601 :
1602 51 : skip_ = getenv("BGP_SKIP_UPDATE_SEND") != NULL;
1603 51 : init_ = true;
1604 :
1605 51 : return skip_;
1606 : }
1607 :
1608 20423 : BgpPeer::OriginOverride::OriginOverride(
1609 20423 : const BgpNeighborConfig::OriginOverrideConfig &config)
1610 20423 : : origin_override(config.origin_override),
1611 20423 : origin(BgpAttr::OriginFromString(config.origin)) {
1612 20423 : }
1613 :
1614 10065 : bool BgpPeer::OriginOverride::operator!=(const OriginOverride &rhs) const {
1615 10065 : if (origin_override != rhs.origin_override) {
1616 2 : return true;
1617 : }
1618 :
1619 : // compare origin only if override is set
1620 10063 : if (origin_override && origin != rhs.origin) {
1621 0 : return true;
1622 : }
1623 10063 : 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 158977 : bool BgpPeer::SendUpdate(const uint8_t *msg, size_t msgsize,
1632 : const string *msg_str) {
1633 158977 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
1634 158990 : bool send_ready = true;
1635 158990 : if (buffer_.size() + msgsize > buffer_capacity_) {
1636 5 : send_ready = FlushUpdateUnlocked();
1637 5 : assert(buffer_.empty());
1638 : }
1639 158990 : buffer_.insert(buffer_.end(), msg, msg + msgsize);
1640 158987 : inc_tx_update();
1641 158987 : return send_ready;
1642 158986 : }
1643 :
1644 146495 : bool BgpPeer::FlushUpdateUnlocked() {
1645 : // Bail if the update buffer is empty.
1646 146495 : if (buffer_.empty())
1647 4611 : return true;
1648 :
1649 : // Bail if there's no session for the peer anymore.
1650 141884 : if (!session_) {
1651 13058 : buffer_.clear();
1652 13057 : return true;
1653 : }
1654 :
1655 128826 : if (!SkipUpdateSend()) {
1656 128825 : send_ready_ = session_->Send(buffer_.data(), buffer_.size(), NULL);
1657 128826 : buffer_.clear();
1658 128825 : if (send_ready_) {
1659 128808 : StartKeepaliveTimerUnlocked();
1660 : } else {
1661 17 : StopKeepaliveTimerUnlocked();
1662 : }
1663 : } else {
1664 0 : send_ready_ = true;
1665 : }
1666 :
1667 128823 : if (!send_ready_) {
1668 17 : BGP_LOG_PEER(Event, this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
1669 : BGP_PEER_DIR_NA, "Send blocked");
1670 : }
1671 128823 : return send_ready_;
1672 : }
1673 :
1674 146449 : bool BgpPeer::FlushUpdate() {
1675 146449 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
1676 292976 : return FlushUpdateUnlocked();
1677 146487 : }
1678 :
1679 2366 : bool BgpPeer::notification() const {
1680 2366 : return peer_close_->gr_params().notification();
1681 : }
1682 :
1683 : // Check if GR Helper mode sould be attempted.
1684 15765 : bool BgpPeer::AttemptGRHelperMode(int code, int subcode) const {
1685 15765 : if (!code)
1686 2387 : return true;
1687 :
1688 13378 : if (code == BgpProto::Notification::Cease &&
1689 12991 : (subcode == BgpProto::Notification::HardReset ||
1690 : subcode == BgpProto::Notification::PeerDeconfigured)) {
1691 10860 : return false;
1692 : }
1693 :
1694 : // If Peer supports Notification (N) bit, then attempt GR-Helper for all
1695 : // other notifications, not otherwise.
1696 2518 : return notification();
1697 : }
1698 :
1699 4943 : void BgpPeer::SendNotification(BgpSession *session,
1700 : int code, int subcode, const string &data) {
1701 4943 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
1702 4943 : session->SendNotification(code, subcode, data);
1703 4942 : state_machine_->set_last_notification_out(code, subcode, data);
1704 4942 : inc_tx_notification();
1705 4943 : }
1706 :
1707 5331 : bool BgpPeer::SetCapabilities(const BgpProto::OpenMessage *msg) {
1708 5331 : peer_bgp_id_ = htonl(msg->identifier);
1709 5331 : capabilities_.clear();
1710 5331 : vector<BgpProto::OpenMessage::OptParam *>::const_iterator it;
1711 10659 : for (it = msg->opt_params.begin(); it < msg->opt_params.end(); ++it) {
1712 5330 : capabilities_.insert(capabilities_.end(), (*it)->capabilities.begin(),
1713 5330 : (*it)->capabilities.end());
1714 5328 : (*it)->capabilities.clear();
1715 : }
1716 :
1717 5328 : as4_supported_ = false;
1718 5328 : if (server_->enable_4byte_as()) {
1719 45 : vector<BgpProto::OpenMessage::Capability *>::iterator c_it;
1720 152 : for (c_it = capabilities_.begin(); c_it < capabilities_.end(); ++c_it) {
1721 147 : if ((*c_it)->code ==BgpProto::OpenMessage::Capability::AS4Support) {
1722 40 : as4_supported_ = true;
1723 40 : break;
1724 : }
1725 : }
1726 : }
1727 10659 : BgpPeerInfoData peer_info;
1728 5331 : peer_info.set_name(ToUVEKey());
1729 5331 : peer_info.set_peer_id(peer_bgp_id_);
1730 :
1731 5331 : vector<string> families;
1732 5331 : vector<BgpProto::OpenMessage::Capability *>::iterator cap_it;
1733 25187 : for (cap_it = capabilities_.begin(); cap_it < capabilities_.end();
1734 19857 : ++cap_it) {
1735 19862 : if ((*cap_it)->code != BgpProto::OpenMessage::Capability::MpExtension)
1736 6816 : continue;
1737 13046 : uint8_t *data = (*cap_it)->capability.data();
1738 13047 : uint16_t afi = get_value(data, 2);
1739 13048 : uint8_t safi = get_value(data + 3, 1);
1740 13048 : Address::Family family = BgpAf::AfiSafiToFamily(afi, safi);
1741 13048 : if (family == Address::UNSPEC) {
1742 0 : families.push_back(BgpAf::ToString(afi, safi));
1743 : } else {
1744 13048 : families.push_back(Address::FamilyToString(family));
1745 : }
1746 : }
1747 5326 : peer_info.set_families(families);
1748 :
1749 5327 : negotiated_families_.clear();
1750 58593 : for (int idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
1751 53262 : if (!family_attributes_list_[idx])
1752 40250 : continue;
1753 13152 : Address::Family family = static_cast<Address::Family>(idx);
1754 : uint16_t afi;
1755 : uint8_t safi;
1756 13152 : tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
1757 13153 : if (!MpNlriAllowed(afi, safi))
1758 142 : continue;
1759 13017 : negotiated_families_.push_back(Address::FamilyToString(family));
1760 : }
1761 5331 : sort(negotiated_families_.begin(), negotiated_families_.end());
1762 5324 : 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 5324 : 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 5325 : return true;
1773 5325 : }
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 14917 : void BgpPeer::ResetCapabilities() {
1781 14917 : STLDeleteValues(&capabilities_);
1782 29834 : BgpPeerInfoData peer_info;
1783 14917 : peer_info.set_name(ToUVEKey());
1784 14917 : vector<string> families = vector<string>();
1785 14917 : peer_info.set_families(families);
1786 14917 : vector<string> negotiated_families = vector<string>();
1787 14917 : peer_info.set_negotiated_families(negotiated_families);
1788 14915 : peer_info.set_graceful_restart_families(vector<string>());
1789 14915 : BGPPeerInfoSend(peer_info);
1790 14916 : }
1791 :
1792 503938 : bool BgpPeer::MpNlriAllowed(uint16_t afi, uint8_t safi) {
1793 503938 : vector<BgpProto::OpenMessage::Capability *>::iterator it;
1794 1322878 : for (it = capabilities_.begin(); it < capabilities_.end(); ++it) {
1795 1322567 : if ((*it)->code != BgpProto::OpenMessage::Capability::MpExtension)
1796 479 : continue;
1797 1322103 : uint8_t *data = (*it)->capability.data();
1798 1322077 : uint16_t af_value = get_value(data, 2);
1799 1322076 : uint8_t safi_value = get_value(data + 3, 1);
1800 1322063 : if (afi == af_value && safi == safi_value) {
1801 503602 : return true;
1802 : }
1803 : }
1804 289 : return false;
1805 : }
1806 :
1807 188156 : bool BgpPeer::Is4ByteAsSupported() const {
1808 188156 : return as4_supported_;
1809 : }
1810 :
1811 : template <typename TableT, typename PrefixT>
1812 145097 : void BgpPeer::ProcessNlri(Address::Family family, DBRequest::DBOperation oper,
1813 : const BgpMpNlri *nlri, BgpAttrPtr attr, uint32_t flags) {
1814 145097 : TableT *table = static_cast<TableT *>(rtinstance_->GetTable(family));
1815 145087 : assert(table);
1816 :
1817 343900 : for (vector<BgpProtoPrefix *>::const_iterator it = nlri->nlri.begin();
1818 343899 : it != nlri->nlri.end(); ++it) {
1819 198797 : PrefixT prefix;
1820 198798 : BgpAttrPtr new_attr(attr);
1821 198812 : uint32_t label = 0;
1822 198812 : uint32_t l3_label = 0;
1823 338849 : int result = PrefixT::FromProtoPrefix(server_, **it,
1824 140039 : (oper == DBRequest::DB_ENTRY_ADD_CHANGE ? attr.get() : NULL),
1825 : family, &prefix, &new_attr, &label, &l3_label);
1826 198793 : 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 198793 : DBRequest req;
1835 198792 : req.oper = oper;
1836 198792 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
1837 140018 : req.data.reset(new typename TableT::RequestData(
1838 : new_attr, flags, label, l3_label, 0));
1839 : }
1840 198797 : req.key.reset(new typename TableT::RequestKey(prefix, this));
1841 198791 : table->Enqueue(&req);
1842 : }
1843 145098 : }
1844 :
1845 : template <typename PrefixT>
1846 1342 : void BgpPeer::ProcessNlriBgpaas(Address::Family family, DBRequest::DBOperation oper,
1847 : const BgpMpNlri *nlri, BgpAttrPtr attr, uint32_t flags) {
1848 :
1849 2684 : for (vector<BgpProtoPrefix *>::const_iterator it = nlri->nlri.begin();
1850 2684 : it != nlri->nlri.end(); ++it) {
1851 1342 : PrefixT prefix;
1852 1342 : BgpAttrPtr new_attr(attr);
1853 1342 : uint32_t label = 0;
1854 1342 : uint32_t l3_label = 0;
1855 2174 : int result = PrefixT::FromProtoPrefix(server_, **it,
1856 832 : (oper == DBRequest::DB_ENTRY_ADD_CHANGE ? attr.get() : NULL),
1857 : family, &prefix, &new_attr, &label, &l3_label);
1858 1342 : 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 1342 : ProcessBgpaas(oper, prefix.addr(), prefix.prefixlen(), new_attr, flags);
1867 : }
1868 1342 : }
1869 :
1870 1342 : void BgpPeer::ProcessBgpaas(DBRequest::DBOperation oper,
1871 : IpAddress addr, uint8_t addr_len, BgpAttrPtr attr, uint32_t flags) {
1872 :
1873 1342 : if (rtinstance_->routing_instance_vxlan() == "") {
1874 668 : return;
1875 : }
1876 674 : RoutingInstanceMgr *mgr = server()->routing_instance_mgr();
1877 674 : if (mgr == nullptr) {
1878 0 : return;
1879 : }
1880 : RoutingInstance *vxlan_ri =
1881 674 : mgr->GetRoutingInstance(rtinstance_->routing_instance_vxlan());
1882 674 : if (vxlan_ri == nullptr) {
1883 0 : return;
1884 : }
1885 674 : EvpnTable *table = static_cast<EvpnTable *>(vxlan_ri->GetTable(Address::EVPN));
1886 674 : EvpnPrefix prefix_evpn(RouteDistinguisher::kZeroRd, addr, addr_len);
1887 :
1888 674 : DBRequest req;
1889 674 : req.oper = oper;
1890 674 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
1891 416 : req.data.reset(new EvpnTable::RequestData(attr, flags, 0, 0, 0));
1892 : }
1893 : else {
1894 258 : req.data.reset(NULL);
1895 : }
1896 674 : req.key.reset(new EvpnTable::RequestKey(prefix_evpn, this));
1897 674 : table->Enqueue(&req);
1898 674 : }
1899 :
1900 111091 : uint32_t BgpPeer::GetPathFlags(Address::Family family,
1901 : const BgpAttr *attr) const {
1902 111091 : uint32_t flags = resolve_paths_ ? BgpPath::ResolveNexthop : 0;
1903 :
1904 : // Check for OriginatorId loop in case we are an RR client.
1905 134766 : if (peer_type_ == BgpProto::IBGP &&
1906 23677 : attr->originator_id().to_ulong() == ntohl(local_bgp_id_)) {
1907 1 : flags |= BgpPath::OriginatorIdLooped;
1908 : }
1909 :
1910 : // Check for ClusterList loop in case we are an RR.
1911 111091 : if (server_->cluster_id() && attr->cluster_list() &&
1912 4 : attr->cluster_list()->cluster_list().ClusterListLoop(
1913 2 : server_->cluster_id())) {
1914 1 : flags |= BgpPath::ClusterListLooped;
1915 : }
1916 :
1917 111088 : if (!attr->as_path() && !attr->aspath_4byte())
1918 5 : return flags;
1919 :
1920 : // Check whether neighbor has appended its AS to the AS_PATH.
1921 285910 : if ((PeerType() == BgpProto::EBGP) &&
1922 262180 : ((attr->as_path() && !attr->as_path()->path().AsLeftMostMatch(
1923 174793 : peer_as())) || (attr->aspath_4byte() &&
1924 31 : !attr->aspath_4byte()->path().AsLeftMostMatch(peer_as())))) {
1925 4 : flags |= BgpPath::NoNeighborAs;
1926 : }
1927 :
1928 : // Check for AS_PATH loop.
1929 111081 : uint8_t max_loop_count = family_attributes_list_[family]->loop_count;
1930 111081 : if (attr->IsAsPathLoop(local_as_, max_loop_count))
1931 6 : flags |= BgpPath::AsPathLooped;
1932 :
1933 111077 : return flags;
1934 : }
1935 :
1936 157804 : uint32_t BgpPeer::GetLocalPrefFromMed(uint32_t med) const {
1937 157804 : if (peer_type_ != BgpProto::EBGP)
1938 39831 : return 0;
1939 117973 : if (!peer_is_control_node_)
1940 117823 : return 0;
1941 150 : if (med == 0)
1942 132 : return 0;
1943 18 : if (med == 100)
1944 2 : return 200;
1945 16 : if (med == 200)
1946 13 : return 100;
1947 3 : return numeric_limits<uint32_t>::max() - med;
1948 : }
1949 :
1950 157803 : void BgpPeer::ProcessUpdate(const BgpProto::Update *msg, size_t msgsize) {
1951 157803 : BgpAttrPtr attr = server_->attr_db()->Locate(msg->path_attributes);
1952 :
1953 157804 : uint32_t local_pref = GetLocalPrefFromMed(attr->med());
1954 157804 : if (local_pref) {
1955 36 : attr = server_->attr_db()->ReplaceLocalPreferenceAndLocate(attr.get(),
1956 18 : local_pref);
1957 : }
1958 :
1959 : // Check if peer is marked to override the route origin attribute
1960 157804 : if (origin_override_.origin_override) {
1961 8 : attr = server_->attr_db()->ReplaceOriginAndLocate(attr.get(),
1962 4 : origin_override_.origin);
1963 : }
1964 :
1965 313871 : if ((router_type_ == "bgpaas-client") ||
1966 156066 : (router_type_ == "bgpaas-server")) {
1967 5202 : attr = server_->attr_db()->ReplaceSubProtocolAndLocate(attr.get(),
1968 5202 : MatchProtocolToString(MatchProtocol::BGPaaS));
1969 : }
1970 :
1971 157801 : uint32_t reach_count = 0, unreach_count = 0;
1972 157801 : RoutingInstance *instance = GetRoutingInstance();
1973 157799 : if (msg->nlri.size() || msg->withdrawn_routes.size()) {
1974 : InetTable *table =
1975 6 : static_cast<InetTable *>(instance->GetTable(Address::INET));
1976 6 : if (!table) {
1977 0 : BGP_LOG_WARNING_STR(BgpConfig, BGP_LOG_FLAG_ALL,
1978 : "Cannot find inet table");
1979 0 : return;
1980 : }
1981 :
1982 6 : unreach_count += msg->withdrawn_routes.size();
1983 6 : for (vector<BgpProtoPrefix *>::const_iterator it =
1984 24 : msg->withdrawn_routes.begin(); it != msg->withdrawn_routes.end();
1985 12 : ++it) {
1986 12 : Ip4Prefix prefix;
1987 12 : int result = Ip4Prefix::FromProtoPrefix((**it), &prefix);
1988 12 : 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 24 : if ((router_type_ == "bgpaas-client") ||
1996 12 : (router_type_ == "bgpaas-server")) {
1997 0 : ProcessBgpaas(DBRequest::DB_ENTRY_DELETE, prefix.addr(),
1998 0 : prefix.prefixlen(), attr, 0);
1999 : }
2000 :
2001 12 : DBRequest req;
2002 12 : req.oper = DBRequest::DB_ENTRY_DELETE;
2003 12 : req.data.reset(NULL);
2004 12 : req.key.reset(new InetTable::RequestKey(prefix, this));
2005 12 : table->Enqueue(&req);
2006 12 : }
2007 :
2008 6 : uint32_t flags = GetPathFlags(Address::INET, attr.get());
2009 6 : reach_count += msg->nlri.size();
2010 6 : for (vector<BgpProtoPrefix *>::const_iterator it = msg->nlri.begin();
2011 12 : it != msg->nlri.end(); ++it) {
2012 6 : Ip4Prefix prefix;
2013 6 : int result = Ip4Prefix::FromProtoPrefix((**it), &prefix);
2014 6 : 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 6 : DBRequest req;
2022 6 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
2023 6 : req.data.reset(new InetTable::RequestData(attr, flags, 0, 0, 0));
2024 6 : req.key.reset(new InetTable::RequestKey(prefix, this));
2025 6 : table->Enqueue(&req);
2026 :
2027 12 : if ((router_type_ == "bgpaas-client") ||
2028 6 : (router_type_ == "bgpaas-server")) {
2029 0 : ProcessBgpaas(DBRequest::DB_ENTRY_ADD_CHANGE, prefix.addr(),
2030 0 : prefix.prefixlen(), attr, flags);
2031 : }
2032 6 : }
2033 : }
2034 :
2035 157797 : for (vector<BgpAttribute *>::const_iterator ait =
2036 157798 : msg->path_attributes.begin();
2037 701602 : ait != msg->path_attributes.end(); ++ait) {
2038 : DBRequest::DBOperation oper;
2039 556492 : if ((*ait)->code == BgpAttribute::MPReachNlri) {
2040 111076 : oper = DBRequest::DB_ENTRY_ADD_CHANGE;
2041 445416 : } else if ((*ait)->code == BgpAttribute::MPUnreachNlri) {
2042 46715 : oper = DBRequest::DB_ENTRY_DELETE;
2043 : } else {
2044 398704 : continue;
2045 : }
2046 :
2047 157791 : BgpMpNlri *nlri = static_cast<BgpMpNlri *>(*ait);
2048 157790 : assert(nlri);
2049 157790 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
2050 111075 : reach_count += nlri->nlri.size();
2051 : } else {
2052 46715 : unreach_count += nlri->nlri.size();
2053 : }
2054 :
2055 157790 : Address::Family family = BgpAf::AfiSafiToFamily(nlri->afi, nlri->safi);
2056 157791 : if (!IsFamilyNegotiated(family)) {
2057 1 : 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 1 : continue;
2062 1 : }
2063 :
2064 : // Handle EndOfRib marker.
2065 157803 : if (oper == DBRequest::DB_ENTRY_DELETE && nlri->nlri.empty()) {
2066 12704 : inc_rx_end_of_rib();
2067 12703 : 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 12703 : ReceiveEndOfRIB(family, msgsize);
2073 12703 : return;
2074 : }
2075 :
2076 145098 : uint32_t flags = 0;
2077 145098 : if ((*ait)->code == BgpAttribute::MPReachNlri) {
2078 111085 : flags = GetPathFlags(family, attr.get());
2079 111076 : attr = GetMpNlriNexthop(nlri, attr);
2080 : }
2081 :
2082 145089 : switch (family) {
2083 4721 : case Address::INET:
2084 : case Address::INETMPLS:
2085 4721 : ProcessNlri<InetTable, Ip4Prefix>(
2086 : family, oper, nlri, attr, flags);
2087 8824 : if ((router_type_ == "bgpaas-client") ||
2088 4103 : (router_type_ == "bgpaas-server")) {
2089 618 : ProcessNlriBgpaas<Ip4Prefix>(
2090 : family, oper, nlri, attr, flags);
2091 : }
2092 4721 : break;
2093 55890 : case Address::INETVPN:
2094 55890 : ProcessNlri<InetVpnTable, InetVpnPrefix>(
2095 : family, oper, nlri, attr, flags);
2096 55890 : break;
2097 3603 : case Address::INET6:
2098 3603 : ProcessNlri<Inet6Table, Inet6Prefix>(
2099 : family, oper, nlri, attr, flags);
2100 6482 : if ((router_type_ == "bgpaas-client") ||
2101 2879 : (router_type_ == "bgpaas-server")) {
2102 724 : ProcessNlriBgpaas<Inet6Prefix>(
2103 : family, oper, nlri, attr, flags);
2104 : }
2105 3603 : break;
2106 40165 : case Address::INET6VPN:
2107 40165 : ProcessNlri<Inet6VpnTable, Inet6VpnPrefix>(
2108 : family, oper, nlri, attr, flags);
2109 40165 : break;
2110 16863 : case Address::EVPN:
2111 16863 : ProcessNlri<EvpnTable, EvpnPrefix>(
2112 : family, oper, nlri, attr, flags);
2113 16863 : break;
2114 4238 : case Address::ERMVPN:
2115 4238 : ProcessNlri<ErmVpnTable, ErmVpnPrefix>(
2116 : family, oper, nlri, attr, flags);
2117 4238 : break;
2118 1124 : case Address::MVPN:
2119 1124 : ProcessNlri<MvpnTable, MvpnPrefix>(
2120 : family, oper, nlri, attr, flags);
2121 1124 : break;
2122 18485 : case Address::RTARGET:
2123 18485 : ProcessNlri<RTargetTable, RTargetPrefix>(
2124 : family, oper, nlri, attr, flags);
2125 18496 : break;
2126 0 : default:
2127 0 : break;
2128 : }
2129 : }
2130 :
2131 145100 : inc_rx_route_reach(reach_count);
2132 145100 : inc_rx_route_unreach(unreach_count);
2133 145098 : if (Sandesh::LoggingLevel() >= Sandesh::LoggingUtLevel()) {
2134 145099 : 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 157803 : }
2140 463349 : const std::vector<std::string> BgpPeer::GetDefaultTunnelEncap(
2141 : const Address::Family family) const {
2142 463349 : if (family_attributes_list_[family] == NULL)
2143 299138 : return std::vector<std::string>();
2144 164222 : return family_attributes_list_[family]->default_tunnel_encap_list;
2145 : }
2146 :
2147 463349 : void BgpPeer::ProcessPathTunnelEncapsulation(const BgpPath *path, BgpAttr *attr,
2148 : ExtCommunityDB *extcomm_db,
2149 : const BgpTable *table) const {
2150 463349 : if (!GetDefaultTunnelEncap(table->family()).empty()) {
2151 6 : ExtCommunityPtr ext_community = attr->ext_community();
2152 6 : bool tunnel_encap_found = false;
2153 6 : if (ext_community) {
2154 6 : for (ExtCommunity::ExtCommunityList::const_iterator iter =
2155 6 : attr->ext_community()->communities().begin();
2156 20 : iter != attr->ext_community()->communities().end();
2157 14 : ++iter) {
2158 16 : if (ExtCommunity::is_tunnel_encap(*iter)) {
2159 2 : tunnel_encap_found = true;
2160 2 : break;
2161 : }
2162 : }
2163 : }
2164 : // Set default tunnel encap since it is not in the path
2165 6 : if (!ext_community || !tunnel_encap_found) {
2166 4 : ExtCommunity::ExtCommunityList encap_list;
2167 16 : BOOST_FOREACH(const string &encap_string,
2168 : GetDefaultTunnelEncap(table->family())) {
2169 6 : TunnelEncap tunnel_encap(encap_string);
2170 6 : encap_list.push_back(tunnel_encap.GetExtCommunity());
2171 4 : }
2172 : ext_community =
2173 12 : extcomm_db->ReplaceTunnelEncapsulationAndLocate(
2174 12 : ext_community ? ext_community.get() : NULL, encap_list);
2175 4 : attr->set_ext_community(ext_community);
2176 4 : }
2177 6 : }
2178 463278 : }
2179 :
2180 :
2181 300344 : void BgpPeer::UpdatePrimaryPathCount(int count, Address::Family family) const {
2182 300344 : primary_path_count_ += count;
2183 300363 : if (family == Address::UNSPEC)
2184 8 : return;
2185 300355 : family_primary_path_count_[family] += count;
2186 300353 : uint32_t limit = 0;
2187 300353 : if (family_attributes_list_[family])
2188 298259 : limit = family_attributes_list_[family]->prefix_limit;
2189 300343 : if (limit && family_primary_path_count_[family] > limit)
2190 48 : TriggerPrefixLimitCheck();
2191 : }
2192 :
2193 48 : void BgpPeer::StartPrefixLimitIdleTimer(uint32_t plim_idle_time_msecs) {
2194 48 : prefix_limit_idle_timer_->Start(plim_idle_time_msecs,
2195 : boost::bind(&BgpPeer::PrefixLimitIdleTimerExpired, this),
2196 : boost::bind(&BgpPeer::PrefixLimitIdleTimerErrorHandler, this, _1, _2));
2197 48 : }
2198 :
2199 764 : void BgpPeer::StopPrefixLimitIdleTimer() {
2200 764 : prefix_limit_idle_timer_->Cancel();
2201 764 : }
2202 :
2203 11284 : bool BgpPeer::PrefixLimitIdleTimerRunning() const {
2204 11284 : return prefix_limit_idle_timer_->running();
2205 : }
2206 :
2207 40 : bool BgpPeer::PrefixLimitIdleTimerExpired() {
2208 40 : 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 5245 : void BgpPeer::RegisterToVpnTables() {
2224 5245 : CHECK_CONCURRENCY("bgp::StateMachine", "bgp::RTFilter", "bgp::Config");
2225 :
2226 5246 : if (vpn_tables_registered_)
2227 24 : return;
2228 5222 : vpn_tables_registered_ = true;
2229 :
2230 5222 : RoutingInstance *instance = GetRoutingInstance();
2231 : vector<Address::Family> vpn_family_list = list_of
2232 5222 : (Address::INETVPN)(Address::INET6VPN)(Address::ERMVPN)(Address::EVPN)
2233 5221 : (Address::MVPN);
2234 57424 : BOOST_FOREACH(Address::Family vpn_family, vpn_family_list) {
2235 26100 : if (!IsFamilyNegotiated(vpn_family))
2236 17995 : continue;
2237 8106 : BgpTable *table = instance->GetTable(vpn_family);
2238 10133 : BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_TRACE,
2239 : table, "Register peer with the table");
2240 8107 : Register(table, BuildRibExportPolicy(vpn_family));
2241 : }
2242 5220 : }
2243 :
2244 19796 : void BgpPeer::StartEndOfRibReceiveTimer(Address::Family family) {
2245 19796 : uint32_t timeout = GetEndOfRibReceiveTime(family);
2246 :
2247 19795 : 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 19797 : eor_receive_timer_[family]->Start(timeout * 1000,
2253 : boost::bind(&BgpPeer::EndOfRibReceiveTimerExpired, this, family),
2254 : boost::bind(&BgpPeer::EndOfRibTimerErrorHandler, this, _1, _2));
2255 19797 : }
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 64 : bool BgpPeer::EndOfRibReceiveTimerExpired(Address::Family family) {
2264 64 : if (family == Address::RTARGET)
2265 0 : RegisterToVpnTables();
2266 :
2267 : // Fake reception of EoRs to exit from GR states and sweep all stale routes.
2268 64 : close_manager_->ProcessEORMarkerReceived(family);
2269 64 : return false;
2270 : }
2271 :
2272 1490 : bool BgpPeer::KeepaliveTimerExpired() {
2273 1490 : if (!IsReady())
2274 0 : return false;
2275 :
2276 1490 : SendKeepalive(true);
2277 :
2278 : //
2279 : // Start the timer again, by returning true
2280 : //
2281 1490 : return true;
2282 : }
2283 :
2284 134118 : void BgpPeer::StartKeepaliveTimerUnlocked() {
2285 134118 : int keepalive_time_msecs = state_machine_->keepalive_time_msecs();
2286 134117 : if (keepalive_time_msecs <= 0)
2287 0 : return;
2288 :
2289 134117 : keepalive_timer_->Start(keepalive_time_msecs,
2290 : boost::bind(&BgpPeer::KeepaliveTimerExpired, this),
2291 : boost::bind(&BgpPeer::KeepaliveTimerErrorHandler, this, _1, _2));
2292 : }
2293 :
2294 5316 : void BgpPeer::StartKeepaliveTimer() {
2295 5316 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
2296 5320 : if (session_ && send_ready_)
2297 5319 : StartKeepaliveTimerUnlocked();
2298 5320 : }
2299 :
2300 17 : void BgpPeer::StopKeepaliveTimerUnlocked() {
2301 17 : keepalive_timer_->Cancel();
2302 17 : }
2303 :
2304 1066 : bool BgpPeer::KeepaliveTimerRunning() {
2305 1066 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
2306 2132 : return keepalive_timer_->running();
2307 1066 : }
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 6111 : void BgpPeer::set_session(BgpSession *session) {
2319 6111 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
2320 6111 : assert(session_ == NULL);
2321 6111 : session_ = session;
2322 6111 : }
2323 :
2324 26766 : void BgpPeer::clear_session() {
2325 26766 : tbb::spin_mutex::scoped_lock lock(spin_mutex_);
2326 26766 : if (session_) {
2327 6111 : session_->clear_peer();
2328 6111 : session_->set_observer(NULL);
2329 6111 : session_->Close();
2330 : }
2331 26765 : session_ = NULL;
2332 26765 : }
2333 :
2334 57911 : BgpSession *BgpPeer::session() {
2335 57911 : return session_;
2336 : }
2337 :
2338 31437 : string BgpPeer::BytesToHexString(const u_int8_t *msg, size_t size) {
2339 31437 : ostringstream out;
2340 : char buf[4];
2341 :
2342 2399620 : for (size_t i = 0; i < size; i ++) {
2343 2368183 : if (!(i % 32)) out << "\n";
2344 2368184 : if (!(i % 4)) out << " 0x";
2345 2368181 : snprintf(buf, sizeof(buf), "%02X", msg[i]);
2346 2368181 : out << buf;
2347 : }
2348 :
2349 31437 : out << "\n";
2350 :
2351 62874 : return out.str();
2352 31437 : }
2353 :
2354 175217 : bool BgpPeer::ReceiveMsg(BgpSession *session, const u_int8_t *msg,
2355 : size_t size) {
2356 175217 : ParseErrorContext ec;
2357 350418 : BgpProto::BgpMessage *minfo = BgpProto::Decode(msg, size, &ec,
2358 175218 : Is4ByteAsSupported());
2359 :
2360 175201 : 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 175201 : if (minfo->type != BgpProto::KEEPALIVE)
2371 168493 : BGP_TRACE_PEER_PACKET(this, msg, size, SandeshLevel::SYS_WARN); //Sandesh::LoggingUtLevel()
2372 :
2373 175205 : state_machine_->OnMessage(session, minfo, size);
2374 175223 : return true;
2375 175223 : }
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 111086 : BgpAttrPtr BgpPeer::GetMpNlriNexthop(BgpMpNlri *nlri, BgpAttrPtr attr) {
2383 111086 : bool update_nh = false;
2384 111086 : IpAddress addr;
2385 :
2386 111085 : if (nlri->afi == BgpAf::IPv4) {
2387 66021 : if (nlri->safi == BgpAf::Mpls || nlri->safi == BgpAf::Unicast ||
2388 62853 : nlri->safi == BgpAf::RTarget || nlri->safi == BgpAf::MVpn) {
2389 19731 : Ip4Address::bytes_type bt = { { 0 } };
2390 39460 : copy(nlri->nexthop.begin(),
2391 19731 : nlri->nexthop.begin() + sizeof(bt), bt.begin());
2392 19723 : addr = Ip4Address(bt);
2393 19723 : update_nh = true;
2394 66013 : } else if (nlri->safi == BgpAf::Vpn) {
2395 42966 : Ip4Address::bytes_type bt = { { 0 } };
2396 42966 : size_t rdsize = RouteDistinguisher::kSize;
2397 85932 : copy(nlri->nexthop.begin() + rdsize,
2398 42966 : nlri->nexthop.begin() + rdsize + sizeof(bt), bt.begin());
2399 42966 : addr = Ip4Address(bt);
2400 42966 : update_nh = true;
2401 : }
2402 45064 : } else if (nlri->afi == BgpAf::L2Vpn) {
2403 12504 : if (nlri->safi == BgpAf::EVpn) {
2404 12504 : Ip4Address::bytes_type bt = { { 0 } };
2405 25008 : copy(nlri->nexthop.begin(),
2406 12504 : nlri->nexthop.begin() + sizeof(bt), bt.begin());
2407 12504 : addr = Ip4Address(bt);
2408 12504 : update_nh = true;
2409 : }
2410 32560 : } else if (nlri->afi == BgpAf::IPv6) {
2411 32560 : 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 2518 : for (int idx = 0; idx < 2; ++idx) {
2419 2518 : Ip6Address::bytes_type bt = { { 0 } };
2420 2518 : if ((idx + 1) * sizeof(bt) > nlri->nexthop.size())
2421 2518 : break;
2422 5036 : copy(nlri->nexthop.begin() + idx * sizeof(bt),
2423 2518 : nlri->nexthop.begin() + (idx + 1) * sizeof(bt), bt.begin());
2424 2518 : Ip6Address v6_addr(bt);
2425 2518 : if (v6_addr.is_v4_mapped()) {
2426 1315 : addr = Address::V4FromV4MappedV6(v6_addr);
2427 1315 : update_nh = true;
2428 1315 : break;
2429 : }
2430 1203 : if (!v6_addr.is_link_local()) {
2431 1203 : addr = v6_addr;
2432 1203 : update_nh = true;
2433 1203 : break;
2434 : }
2435 : }
2436 30042 : } else if (nlri->safi == BgpAf::Vpn) {
2437 30042 : Ip6Address::bytes_type bt = { { 0 } };
2438 30042 : size_t rdsize = RouteDistinguisher::kSize;
2439 60084 : copy(nlri->nexthop.begin() + rdsize,
2440 30042 : nlri->nexthop.begin() + rdsize + sizeof(bt), bt.begin());
2441 30042 : Ip6Address v6_addr(bt);
2442 30042 : if (v6_addr.is_v4_mapped()) {
2443 30042 : addr = Address::V4FromV4MappedV6(v6_addr);
2444 30042 : 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 111077 : if (update_nh) {
2452 107753 : attr = server_->attr_db()->ReplaceNexthopAndLocate(attr.get(), addr);
2453 : }
2454 222170 : return attr;
2455 : }
2456 :
2457 9605 : void BgpPeer::ManagedDelete() {
2458 9605 : if (deleter_->IsDeleted())
2459 38 : return;
2460 9567 : BGP_LOG_PEER(Config, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
2461 : BGP_PEER_DIR_NA, "Received request for deletion");
2462 9567 : if (IsRouterTypeBGPaaS()) {
2463 112 : server()->increment_deleting_bgpaas_count();
2464 : } else {
2465 9455 : server()->increment_deleting_count();
2466 : }
2467 9567 : deleter_->Delete();
2468 : }
2469 :
2470 29148 : void BgpPeer::RetryDelete() {
2471 29148 : if (!deleter_->IsDeleted())
2472 10017 : return;
2473 19133 : deleter_->RetryDelete();
2474 : }
2475 :
2476 311375 : int BgpPeer::GetTaskInstance() const {
2477 311375 : return index_ % TaskScheduler::GetInstance()->HardwareThreadCount();
2478 : }
2479 :
2480 31437 : void BgpPeer::SetDataCollectionKey(BgpPeerInfo *peer_info) const {
2481 31437 : if (rtinstance_) {
2482 31437 : peer_info->set_domain(rtinstance_->name());
2483 : } else {
2484 0 : peer_info->set_domain(BgpConfigManager::kMasterInstance);
2485 : }
2486 :
2487 31437 : peer_info->set_ip_address(peer_key_.endpoint.address().to_string());
2488 31437 : }
2489 :
2490 1086 : static void FillProtoStats(const IPeerDebugStats::ProtoStats &stats,
2491 : PeerProtoStats *proto_stats) {
2492 1086 : proto_stats->set_open(stats.open);
2493 1086 : proto_stats->set_keepalive(stats.keepalive);
2494 1086 : proto_stats->set_close(stats.close);
2495 1086 : proto_stats->set_update(stats.update);
2496 1086 : proto_stats->set_notification(stats.notification);
2497 1086 : proto_stats->set_total(stats.open + stats.keepalive + stats.close +
2498 1086 : stats.update + stats.notification);
2499 1086 : }
2500 :
2501 1086 : static void FillRouteUpdateStats(const IPeerDebugStats::UpdateStats &stats,
2502 : PeerUpdateStats *rt_stats) {
2503 1086 : rt_stats->set_reach(stats.reach);
2504 1086 : rt_stats->set_unreach(stats.unreach);
2505 1086 : rt_stats->set_end_of_rib(stats.end_of_rib);
2506 1086 : rt_stats->set_total(stats.reach + stats.unreach + stats.end_of_rib);
2507 1086 : }
2508 :
2509 1086 : static void FillSocketStats(const IPeerDebugStats::SocketStats &socket_stats,
2510 : PeerSocketStats *peer_socket_stats) {
2511 1086 : peer_socket_stats->set_calls(socket_stats.calls);
2512 1086 : peer_socket_stats->set_bytes(socket_stats.bytes);
2513 1086 : if (socket_stats.calls) {
2514 1058 : peer_socket_stats->set_average_bytes(
2515 1058 : socket_stats.bytes/socket_stats.calls);
2516 : }
2517 1086 : peer_socket_stats->set_blocked_count(socket_stats.blocked_count);
2518 1086 : ostringstream os;
2519 1086 : os << boost::posix_time::microseconds(long(socket_stats.blocked_duration_usecs));
2520 1086 : peer_socket_stats->set_blocked_duration(os.str());
2521 1086 : 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 1086 : }
2528 :
2529 56 : void BgpPeer::FillCloseInfo(BgpNeighborResp *resp) const {
2530 56 : close_manager_->FillCloseInfo(resp);
2531 56 : }
2532 :
2533 543 : void BgpPeer::FillBgpNeighborDebugState(BgpNeighborResp *bnr,
2534 : const IPeerDebugStats *peer_stats) {
2535 543 : bnr->set_last_state(peer_stats->last_state());
2536 543 : bnr->set_last_event(peer_stats->last_event());
2537 543 : bnr->set_last_error(peer_stats->last_error());
2538 543 : bnr->set_last_state_at(peer_stats->last_state_change_at());
2539 543 : bnr->set_flap_count(peer_stats->num_flaps());
2540 543 : bnr->set_flap_time(peer_stats->last_flap());
2541 :
2542 543 : IPeerDebugStats::ProtoStats stats;
2543 543 : PeerProtoStats proto_stats;
2544 543 : peer_stats->GetRxProtoStats(&stats);
2545 543 : FillProtoStats(stats, &proto_stats);
2546 543 : bnr->set_rx_proto_stats(proto_stats);
2547 :
2548 543 : peer_stats->GetTxProtoStats(&stats);
2549 543 : FillProtoStats(stats, &proto_stats);
2550 543 : bnr->set_tx_proto_stats(proto_stats);
2551 :
2552 543 : IPeerDebugStats::UpdateStats update_stats;
2553 543 : PeerUpdateStats rt_stats;
2554 543 : peer_stats->GetRxRouteUpdateStats(&update_stats);
2555 543 : FillRouteUpdateStats(update_stats, &rt_stats);
2556 543 : bnr->set_rx_update_stats(rt_stats);
2557 :
2558 543 : peer_stats->GetTxRouteUpdateStats(&update_stats);
2559 543 : FillRouteUpdateStats(update_stats, &rt_stats);
2560 543 : bnr->set_tx_update_stats(rt_stats);
2561 :
2562 543 : IPeerDebugStats::SocketStats socket_stats;
2563 543 : PeerSocketStats peer_socket_stats;
2564 :
2565 543 : peer_stats->GetRxSocketStats(&socket_stats);
2566 543 : FillSocketStats(socket_stats, &peer_socket_stats);
2567 543 : bnr->set_rx_socket_stats(peer_socket_stats);
2568 :
2569 543 : peer_stats->GetTxSocketStats(&socket_stats);
2570 543 : FillSocketStats(socket_stats, &peer_socket_stats);
2571 543 : bnr->set_tx_socket_stats(peer_socket_stats);
2572 543 : }
2573 :
2574 56 : void BgpPeer::FillBgpNeighborFamilyAttributes(BgpNeighborResp *nbr) const {
2575 56 : vector<ShowBgpNeighborFamily> show_family_attributes_list;
2576 616 : for (int idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
2577 560 : if (!family_attributes_list_[idx])
2578 504 : continue;
2579 56 : ShowBgpNeighborFamily show_family_attributes;
2580 56 : show_family_attributes.set_family(
2581 112 : Address::FamilyToString(static_cast<Address::Family>(idx)));
2582 56 : show_family_attributes.set_loop_count(
2583 56 : family_attributes_list_[idx]->loop_count);
2584 56 : show_family_attributes.set_prefix_limit(
2585 56 : family_attributes_list_[idx]->prefix_limit);
2586 56 : show_family_attributes.set_idle_timeout(
2587 56 : family_attributes_list_[idx]->idle_timeout);
2588 56 : 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 56 : show_family_attributes_list.push_back(show_family_attributes);
2593 56 : }
2594 56 : nbr->set_family_attributes_list(show_family_attributes_list);
2595 56 : }
2596 :
2597 112 : void BgpPeer::FillNeighborInfo(const BgpSandeshContext *bsc,
2598 : BgpNeighborResp *bnr, bool summary) const {
2599 112 : bnr->set_instance_name(rtinstance_->name());
2600 112 : bnr->set_peer(peer_basename_);
2601 112 : bnr->set_deleted(IsDeleted());
2602 112 : bnr->set_closed_at(UTCUsecToString(deleter_->delete_time_stamp_usecs()));
2603 112 : bnr->set_admin_down(admin_down_);
2604 112 : bnr->set_passive(passive_);
2605 112 : bnr->set_as_override(as_override_);
2606 112 : bnr->set_origin_override(origin_override_.origin_override);
2607 112 : if (origin_override_.origin_override) {
2608 0 : bnr->set_route_origin(BgpAttr::OriginToString(origin_override_.origin));
2609 : } else {
2610 112 : bnr->set_route_origin("-");
2611 : }
2612 112 : bnr->set_private_as_action(private_as_action_);
2613 112 : bnr->set_peer_address(peer_address_string());
2614 112 : bnr->set_peer_id(bgp_identifier_string());
2615 112 : bnr->set_peer_asn(peer_as());
2616 112 : bnr->set_peer_port(peer_port());
2617 112 : bnr->set_transport_address(transport_address_string());
2618 112 : bnr->set_encoding("BGP");
2619 112 : bnr->set_peer_type(PeerType() == BgpProto::IBGP ? "internal" : "external");
2620 112 : bnr->set_router_type(router_type_);
2621 112 : bnr->set_state(state_machine_->StateName());
2622 112 : bnr->set_local_address(server_->ToString());
2623 112 : bnr->set_local_id(Ip4Address(ntohl(local_bgp_id_)).to_string());
2624 112 : bnr->set_local_asn(local_as());
2625 112 : bnr->set_cluster_id(Ip4Address(cluster_id_).to_string());
2626 112 : bnr->set_negotiated_hold_time(state_machine_->hold_time());
2627 112 : bnr->set_primary_path_count(GetPrimaryPathCount());
2628 112 : bnr->set_task_instance(GetTaskInstance());
2629 112 : bnr->set_send_ready(send_ready_);
2630 112 : bnr->set_flap_count(peer_stats_->num_flaps());
2631 112 : bnr->set_as4_supported(Is4ByteAsSupported());
2632 112 : bnr->set_flap_time(peer_stats_->last_flap());
2633 112 : bnr->set_auth_type(
2634 224 : AuthenticationData::KeyTypeToString(inuse_authkey_type_));
2635 112 : if (bsc->test_mode()) {
2636 0 : bnr->set_auth_keys(auth_data_.KeysToStringDetail());
2637 : }
2638 :
2639 112 : if (summary)
2640 56 : return;
2641 :
2642 56 : bnr->set_configured_address_families(configured_families_);
2643 56 : bnr->set_negotiated_address_families(negotiated_families_);
2644 :
2645 56 : peer_close_->FillNeighborInfo(bnr);
2646 :
2647 56 : bnr->set_configured_hold_time(state_machine_->GetConfiguredHoldTime());
2648 56 : FillBgpNeighborFamilyAttributes(bnr);
2649 56 : FillBgpNeighborDebugState(bnr, peer_stats_.get());
2650 56 : BgpMembershipManager *mgr = server_->membership_mgr();
2651 56 : mgr->FillPeerMembershipInfo(this, bnr);
2652 56 : bnr->set_routing_instances(vector<BgpNeighborRoutingInstance>());
2653 56 : FillCloseInfo(bnr);
2654 : }
2655 :
2656 6147 : void BgpPeer::inc_rx_open() {
2657 6147 : peer_stats_->proto_stats_[0].open++;
2658 6147 : }
2659 :
2660 9125 : void BgpPeer::inc_tx_open() {
2661 9125 : peer_stats_->proto_stats_[1].open++;
2662 9128 : }
2663 :
2664 6750 : void BgpPeer::inc_rx_keepalive() {
2665 6750 : peer_stats_->proto_stats_[0].keepalive++;
2666 6749 : }
2667 :
2668 4144 : uint64_t BgpPeer::get_rx_keepalive() const {
2669 4144 : return peer_stats_->proto_stats_[0].keepalive;
2670 : }
2671 :
2672 6805 : void BgpPeer::inc_tx_keepalive() {
2673 6805 : peer_stats_->proto_stats_[1].keepalive++;
2674 6806 : }
2675 :
2676 171 : uint64_t BgpPeer::get_tx_keepalive() const {
2677 171 : return peer_stats_->proto_stats_[1].keepalive;
2678 : }
2679 :
2680 157872 : void BgpPeer::inc_rx_update() {
2681 157872 : peer_stats_->proto_stats_[0].update++;
2682 157871 : }
2683 :
2684 8 : uint64_t BgpPeer::get_rx_update() const {
2685 8 : return peer_stats_->proto_stats_[0].update;
2686 : }
2687 :
2688 171814 : void BgpPeer::inc_tx_update() {
2689 171814 : peer_stats_->proto_stats_[1].update++;
2690 171814 : }
2691 :
2692 37 : uint64_t BgpPeer::get_tx_update() const {
2693 37 : return peer_stats_->proto_stats_[1].update;
2694 : }
2695 :
2696 4632 : void BgpPeer::inc_rx_notification() {
2697 4632 : peer_stats_->proto_stats_[0].notification++;
2698 4632 : }
2699 :
2700 443 : uint64_t BgpPeer::get_rx_notification() const {
2701 443 : return peer_stats_->proto_stats_[0].notification;
2702 : }
2703 :
2704 4942 : void BgpPeer::inc_tx_notification() {
2705 4942 : peer_stats_->proto_stats_[1].notification++;
2706 4942 : }
2707 :
2708 12703 : void BgpPeer::inc_rx_end_of_rib() {
2709 12703 : peer_stats_->update_stats_[0].end_of_rib++;
2710 12703 : }
2711 :
2712 8 : uint64_t BgpPeer::get_rx_end_of_rib() const {
2713 8 : return peer_stats_->update_stats_[0].end_of_rib;
2714 : }
2715 :
2716 12827 : void BgpPeer::inc_tx_end_of_rib() {
2717 12827 : peer_stats_->update_stats_[1].end_of_rib++;
2718 12827 : }
2719 :
2720 12 : uint64_t BgpPeer::get_tx_end_of_rib() const {
2721 12 : return peer_stats_->update_stats_[1].end_of_rib;
2722 : }
2723 :
2724 145100 : void BgpPeer::inc_rx_route_reach(uint64_t count) {
2725 145100 : peer_stats_->update_stats_[0].reach += count;
2726 145100 : }
2727 :
2728 8 : uint64_t BgpPeer::get_rx_route_reach() const {
2729 8 : return peer_stats_->update_stats_[0].reach;
2730 : }
2731 :
2732 12 : uint64_t BgpPeer::get_tx_route_reach() const {
2733 12 : return peer_stats_->update_stats_[1].reach;
2734 : }
2735 :
2736 145100 : void BgpPeer::inc_rx_route_unreach(uint64_t count) {
2737 145100 : peer_stats_->update_stats_[0].unreach += count;
2738 145098 : }
2739 :
2740 8 : uint64_t BgpPeer::get_rx_route_unreach() const {
2741 8 : return peer_stats_->update_stats_[0].unreach;
2742 : }
2743 :
2744 12 : uint64_t BgpPeer::get_tx_route_unreach() const {
2745 12 : return peer_stats_->update_stats_[1].unreach;
2746 : }
2747 :
2748 8 : uint64_t BgpPeer::get_rx_route_total() const {
2749 8 : return peer_stats_->update_stats_[0].reach +
2750 8 : peer_stats_->update_stats_[0].unreach +
2751 8 : peer_stats_->update_stats_[0].end_of_rib;
2752 : }
2753 :
2754 12 : uint64_t BgpPeer::get_tx_route_total() const {
2755 12 : return peer_stats_->update_stats_[1].reach +
2756 12 : peer_stats_->update_stats_[1].unreach +
2757 12 : peer_stats_->update_stats_[1].end_of_rib;
2758 : }
2759 :
2760 122 : void BgpPeer::inc_connect_error() {
2761 122 : peer_stats_->error_stats_.connect_error++;
2762 122 : }
2763 :
2764 287 : void BgpPeer::inc_connect_timer_expired() {
2765 287 : peer_stats_->error_stats_.connect_timer++;
2766 287 : }
2767 :
2768 74 : void BgpPeer::inc_hold_timer_expired() {
2769 74 : peer_stats_->error_stats_.hold_timer++;
2770 74 : }
2771 :
2772 78 : void BgpPeer::inc_open_error() {
2773 78 : peer_stats_->error_stats_.open_error++;
2774 78 : }
2775 :
2776 0 : void BgpPeer::inc_update_error() {
2777 0 : peer_stats_->error_stats_.update_error++;
2778 0 : }
2779 :
2780 141 : uint64_t BgpPeer::get_connect_error() const {
2781 141 : return peer_stats_->error_stats_.connect_error;
2782 : }
2783 :
2784 1117 : uint64_t BgpPeer::get_connect_timer_expired() const {
2785 1117 : 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 169 : uint64_t BgpPeer::get_open_error() const {
2793 169 : 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 168 : string BgpPeer::last_flap_at() const {
2813 168 : if (last_flap_) {
2814 12 : return integerToString(UTCUsecToPTime(last_flap_));
2815 : } else {
2816 162 : return "";
2817 : }
2818 : }
2819 :
2820 5249 : void BgpPeer::increment_flap_count() {
2821 5249 : flap_count_++;
2822 5249 : total_flap_count_++;
2823 5249 : last_flap_ = UTCTimestampUsec();
2824 :
2825 10498 : BgpPeerInfoData peer_info;
2826 5249 : peer_info.set_name(ToUVEKey());
2827 5250 : PeerFlapInfo flap_info;
2828 5250 : flap_info.set_flap_count(flap_count_);
2829 5248 : flap_info.set_flap_time(last_flap_);
2830 5249 : peer_info.set_flap_info(flap_info);
2831 5248 : BGPPeerInfoSend(peer_info);
2832 :
2833 10494 : PeerFlapData peer_flap_data;
2834 5246 : peer_flap_data.set_name(ToUVEKey());
2835 5246 : peer_flap_data.set_flap_info(flap_info);
2836 5246 : assert(!peer_flap_data.get_name().empty());
2837 5246 : BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
2838 5247 : }
2839 :
2840 405 : void BgpPeer::reset_flap_count() {
2841 405 : flap_count_ = 0;
2842 405 : last_flap_ = 0;
2843 :
2844 810 : BgpPeerInfoData peer_info;
2845 405 : peer_info.set_name(ToUVEKey());
2846 405 : PeerFlapInfo flap_info;
2847 405 : peer_info.set_flap_info(flap_info);
2848 405 : BGPPeerInfoSend(peer_info);
2849 :
2850 810 : PeerFlapData peer_flap_data;
2851 405 : peer_flap_data.set_name(ToUVEKey());
2852 405 : peer_flap_data.set_flap_info(flap_info);
2853 405 : assert(!peer_flap_data.get_name().empty());
2854 405 : BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
2855 405 : }
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 3436 : bool BgpPeer::ProcessSession() const {
2860 3436 : return PeerType() != BgpProto::IBGP || router_type() != "bgpaas-client";
2861 : }
2862 :
2863 : // Update control DSCP
2864 6 : void BgpPeer::DSCPUpdateCallback(uint8_t dscp_value) {
2865 6 : if ((session_ != NULL) && (dscp_value != 0xFF)) {
2866 3 : session_->SetDscpSocketOption(dscp_value);
2867 : }
2868 6 : }
|