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