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