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