LCOV - code coverage report
Current view: top level - bgp - bgp_peer.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 864 1777 48.6 %
Date: 2026-09-21 02:11:39 Functions: 102 210 48.6 %
Legend: Lines: hit not hit

          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          80 :     explicit PeerStats(BgpPeer *peer)
      57         400 :         : peer_(peer) {
      58          80 :     }
      59             : 
      60             :     // Used when peer flaps.
      61             :     // Reset all counters.
      62             :     // Socket counters are implicitly cleared because we use a new socket.
      63          32 :     virtual void Clear() {
      64          32 :         error_stats_ = ErrorStats();
      65          32 :         proto_stats_[0] = ProtoStats();
      66          32 :         proto_stats_[1] = ProtoStats();
      67          32 :         update_stats_[0] = UpdateStats();
      68          32 :         update_stats_[1] = UpdateStats();
      69          32 :     }
      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         284 :     virtual void UpdateTxUnreachRoute(uint64_t count) {
     137         284 :         update_stats_[1].unreach += count;
     138         284 :     }
     139             : 
     140         284 :     virtual void UpdateTxReachRoute(uint64_t count) {
     141         284 :         update_stats_[1].reach += count;
     142         284 :     }
     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          80 :     explicit DeleteActor(BgpPeer *peer)
     165          80 :         : LifetimeActor(peer->server_->lifetime_manager()),
     166          80 :           peer_(peer) {
     167          80 :     }
     168             : 
     169         176 :     virtual bool MayDelete() const {
     170         176 :         CHECK_CONCURRENCY("bgp::Config");
     171         176 :         if (!peer_->close_manager_->IsQueueEmpty())
     172          16 :             return false;
     173         160 :         if (peer_->IsCloseInProgress())
     174           0 :             return false;
     175         160 :         if (!peer_->state_machine_->IsQueueEmpty())
     176          80 :             return false;
     177          80 :         if (peer_->prefix_limit_trigger_.IsSet())
     178           0 :             return false;
     179          80 :         return true;
     180             :     }
     181             : 
     182          80 :     virtual void Shutdown() {
     183          80 :         CHECK_CONCURRENCY("bgp::Config");
     184          80 :         peer_->Clear(BgpProto::Notification::PeerDeconfigured);
     185          80 :     }
     186             : 
     187          80 :     virtual void Destroy() {
     188          80 :         CHECK_CONCURRENCY("bgp::Config");
     189          80 :         peer_->PostCloseRelease();
     190          80 :         if (peer_->IsRouterTypeBGPaaS()) {
     191           0 :             peer_->server()->decrement_deleting_bgpaas_count();
     192             :         } else {
     193          80 :             peer_->server()->decrement_deleting_count();
     194             :         }
     195          80 :         if (peer_->dscp_listener_id_ >= 0) {
     196          80 :             peer_->server()->UnregisterDSCPUpdateCallback(
     197          80 :                                         peer_->dscp_listener_id_);
     198          80 :             peer_->dscp_listener_id_ = -1;
     199             :         }
     200          80 :         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          80 :         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          80 :         assert(!peer_->membership_req_pending());
     211          80 :         assert(!peer_->close_manager_->IsMembershipInUse());
     212          80 :         peer_->rtinstance_->peer_manager()->DestroyIPeer(peer_);
     213          80 :     }
     214             : 
     215             : private:
     216             :     BgpPeer *peer_;
     217             : };
     218             : 
     219             : //
     220             : // Constructor for BgpPeerFamilyAttributes.
     221             : //
     222         192 : BgpPeerFamilyAttributes::BgpPeerFamilyAttributes(
     223             :     const BgpNeighborConfig *config,
     224         192 :     const BgpFamilyAttributesConfig &family_config) {
     225         192 :     if (family_config.loop_count) {
     226           0 :         loop_count = family_config.loop_count;
     227             :     } else {
     228         192 :         loop_count = config->loop_count();
     229             :     }
     230         192 :     prefix_limit = family_config.prefix_limit;
     231         192 :     idle_timeout = family_config.idle_timeout;
     232         192 :     default_tunnel_encap_list = family_config.default_tunnel_encap_list;
     233             : 
     234         192 :     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         192 : }
     242             : 
     243          96 : RibExportPolicy BgpPeer::BuildRibExportPolicy(Address::Family family) const {
     244          96 :     RibExportPolicy policy;
     245             :     BgpPeerFamilyAttributes *family_attributes =
     246          96 :         family_attributes_list_[family];
     247          96 :     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          96 :         policy = RibExportPolicy(peer_type_, RibExportPolicy::BGP, peer_as_,
     253          96 :             as_override_, peer_close_->IsCloseLongLivedGraceful(),
     254          96 :             as4_supported_, family_attributes->gateway_address,
     255          96 :             -1, cluster_id_, family_attributes->default_tunnel_encap_list,
     256         192 :             local_as_);
     257             :     }
     258             : 
     259          96 :     if (private_as_action_ == "remove") {
     260           0 :         policy.SetRemovePrivatePolicy(false, false, true);
     261          96 :     } else if (private_as_action_ == "remove-all") {
     262           0 :         policy.SetRemovePrivatePolicy(true, false, true);
     263          96 :     } else if (private_as_action_ == "replace-all") {
     264           0 :         policy.SetRemovePrivatePolicy(true, true, true);
     265             :     }
     266             : 
     267          96 :     return policy;
     268           0 : }
     269             : 
     270          96 : void BgpPeer::ReceiveEndOfRIB(Address::Family family, size_t msgsize) {
     271          96 :     close_manager_->ProcessEORMarkerReceived(family);
     272          96 :     eor_receive_timer_[family]->Cancel();
     273             : 
     274             :     // If EoR for RTarget is received, start registration for other families.
     275          96 :     if (family == Address::RTARGET)
     276           0 :         RegisterToVpnTables();
     277          96 : }
     278             : 
     279         144 : void BgpPeer::SendEndOfRIBActual(Address::Family family) {
     280         144 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
     281             : 
     282             :     // Bail if there's no session for the peer anymore.
     283         144 :     if (!session_)
     284          48 :         return;
     285             : 
     286          96 :     BgpProto::Update update;
     287             :     uint16_t afi;
     288             :     uint8_t safi;
     289          96 :     tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
     290          96 :     BgpMpNlri *nlri = new BgpMpNlri(BgpAttribute::MPUnreachNlri, afi, safi);
     291          96 :     update.path_attributes.push_back(nlri);
     292             :     uint8_t data[256];
     293         192 :     int msgsize = BgpProto::Encode(&update, data, sizeof(data), NULL,
     294          96 :                                    Is4ByteAsSupported());
     295          96 :     assert(msgsize > BgpProto::kMinMessageSize);
     296          96 :     session_->Send(data, msgsize, NULL);
     297          96 :     inc_tx_end_of_rib();
     298          96 :     inc_tx_update();
     299          96 :     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         144 : }
     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         144 : uint32_t BgpPeer::GetEndOfRibReceiveTime(Address::Family family) const {
     315         144 :     return family == Address::RTARGET ?
     316         144 :         kRouteTargetEndOfRibTimeSecs : server_->GetEndOfRibReceiveTime();
     317             : }
     318             : 
     319          48 : bool BgpPeer::IsServerStartingUp() const {
     320          48 :     return server_->IsServerStartingUp();
     321             : }
     322             : 
     323           0 : bool BgpPeer::IsCloseGraceful() const {
     324           0 :     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         288 : void BgpPeer::BGPPeerInfoSend(const BgpPeerInfoData &peer_info) const {
     417         288 :     assert(!peer_info.get_name().empty());
     418         288 :     BGP_UVE_SEND(BGPPeerInfo, peer_info);
     419         288 : }
     420             : 
     421          96 : bool BgpPeer::CanUseMembershipManager() const {
     422          96 :     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         288 : void BgpPeer::MembershipRequestCallback(BgpTable *table) {
     431         288 :     if (close_manager_->IsMembershipInUse()) {
     432         144 :         close_manager_->MembershipRequestCallback();
     433         144 :         return;
     434             :     }
     435             : 
     436         144 :     assert(membership_req_pending_ > 0);
     437         144 :     membership_req_pending_--;
     438             : 
     439             :     // Resume if CloseManager is waiting to use membership manager.
     440         224 :     if (!membership_req_pending_ &&
     441          80 :         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         144 :     if (defer_close_) {
     448           0 :         if (!membership_req_pending_) {
     449           0 :             defer_close_ = false;
     450           0 :             trigger_.Set();
     451             :         }
     452           0 :         return;
     453             :     }
     454             : 
     455         144 :     SendEndOfRIB(table->family());
     456             : }
     457             : 
     458          83 : bool BgpPeer::MembershipPathCallback(DBTablePartBase *tpart, BgpRoute *route,
     459             :                                      BgpPath *path) {
     460          83 :     return close_manager_->MembershipPathCallback(tpart, route, path);
     461             : }
     462             : 
     463           0 : bool BgpPeer::ResumeClose() {
     464           0 :     peer_close_->Close(graceful_close_);
     465           0 :     graceful_close_ = true;
     466           0 :     return true;
     467             : }
     468             : 
     469          80 : BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,
     470          80 :                  const BgpNeighborConfig *config)
     471          80 :         : server_(server),
     472          80 :           rtinstance_(instance),
     473          80 :           peer_key_(config),
     474          80 :           peer_port_(config->source_port()),
     475          80 :           peer_name_(config->name()),
     476          80 :           router_type_(config->router_type()),
     477          80 :           config_(config),
     478          80 :           index_(server->RegisterPeer(this)),
     479          80 :           trigger_(boost::bind(&BgpPeer::ResumeClose, this),
     480             :                    TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     481             :                    GetTaskInstance()),
     482          80 :           prefix_limit_idle_timer_(
     483          80 :               TimerManager::CreateTimer(*server->ioservice(),
     484             :               "BGP prefix limit idle timer",
     485             :               TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     486             :               GetTaskInstance())),
     487          80 :           prefix_limit_trigger_(boost::bind(&BgpPeer::CheckPrefixLimits, this),
     488             :                    TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     489             :                    GetTaskInstance()),
     490          80 :           buffer_capacity_(GetBufferCapacity()),
     491          80 :           session_(NULL),
     492          80 :           keepalive_timer_(TimerManager::CreateTimer(*server->ioservice(),
     493             :                      "BGP keepalive timer",
     494             :                    TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     495             :                    GetTaskInstance())),
     496          80 :           eor_send_timer_start_time_(0),
     497          80 :           send_ready_(true),
     498          80 :           admin_down_(config->admin_down()),
     499          80 :           passive_(config->passive()),
     500          80 :           resolve_paths_(config->router_type() == "bgpaas-client"),
     501          80 :           as_override_(config->as_override()),
     502          80 :           cluster_id_(config->cluster_id()),
     503          80 :           origin_override_(config->origin_override()),
     504          80 :           defer_close_(false),
     505          80 :           graceful_close_(true),
     506          80 :           as4_supported_(false),
     507          80 :           vpn_tables_registered_(false),
     508          80 :           hold_time_(config->hold_time()),
     509          80 :           local_as_(config->local_as()),
     510          80 :           peer_as_(config->peer_as()),
     511          80 :           local_bgp_id_(config->local_identifier()),
     512          80 :           peer_bgp_id_(0),
     513          80 :           peer_type_((config->peer_as() == config->local_as()) ?
     514             :                          BgpProto::IBGP : BgpProto::EBGP),
     515          80 :           state_machine_(BgpStaticObjectFactory::Create<StateMachine>(this)),
     516          80 :           peer_close_(BgpStaticObjectFactory::Create<BgpPeerClose>(this)),
     517          80 :           peer_stats_(new PeerStats(this)),
     518          80 :           deleter_(new DeleteActor(this)),
     519          80 :           instance_delete_ref_(this, instance ? instance->deleter() : NULL),
     520          80 :           flap_count_(0),
     521          80 :           total_flap_count_(0),
     522          80 :           last_flap_(0),
     523          80 :           dscp_listener_id_(-1),
     524          80 :           inuse_authkey_type_(AuthenticationData::NIL),
     525          80 :           asn_listener_id_(-1),
     526        1600 :           instance_op_(-1) {
     527          80 :     buffer_.reserve(buffer_capacity_);
     528          80 :     close_manager_.reset(
     529          80 :         BgpStaticObjectFactory::Create<PeerCloseManager>(static_cast<IPeerClose*>(peer_close_.get())));
     530          80 :     ostringstream oss1;
     531          80 :     oss1 << peer_key_.endpoint.address();
     532          80 :     if (peer_key_.endpoint.port() != BgpConfigManager::kDefaultPort)
     533          64 :         oss1 << ":" << dec << peer_key_.endpoint.port();
     534          80 :     to_str_ = oss1.str();
     535             : 
     536          80 :     ostringstream oss2;
     537          80 :     if (rtinstance_)
     538          80 :         oss2 << rtinstance_->name() << ":";
     539          80 :     oss2 << server_->localname() << ":";
     540          80 :     oss2 << peer_name();
     541          80 :     uve_key_str_ = oss2.str();
     542             : 
     543         160 :     if (router_type_ == "control-node" ||
     544          80 :         router_type_ == "external-control-node") {
     545           0 :         peer_is_control_node_ = true;
     546             :     } else {
     547          80 :         peer_is_control_node_ = false;
     548             :     }
     549             : 
     550          80 :     dscp_listener_id_ = server_->RegisterDSCPUpdateCallback(boost::bind(
     551             :         &BgpPeer::DSCPUpdateCallback, this, _1));
     552          80 :     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          80 :     membership_req_pending_ = 0;
     560          80 :     BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
     561             :         BGP_PEER_DIR_NA, "Created");
     562             : 
     563          80 :     if (rtinstance_ && peer_name_.find(rtinstance_->name()) == 0) {
     564          32 :         peer_basename_ = peer_name_.substr(rtinstance_->name().size() + 1);
     565             :     } else {
     566          48 :         peer_basename_ = peer_name_;
     567             :     }
     568             : 
     569          80 :     for (Address::Family family = Address::UNSPEC;
     570         880 :             family < Address::NUM_FAMILIES;
     571         800 :             family = static_cast<Address::Family>(family + 1)) {
     572         800 :         family_primary_path_count_[family] = 0;
     573        1600 :         eor_send_timer_[family] =
     574        2400 :             TimerManager::CreateTimer(*server->ioservice(),
     575        1600 :                 "BGP EoR Send timer for " + Address::FamilyToString(family),
     576             :                 TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     577             :                 GetTaskInstance());
     578        1600 :         eor_receive_timer_[family] =
     579        2400 :             TimerManager::CreateTimer(*server->ioservice(),
     580        1600 :                 "BGP EoR Receive timer for " + Address::FamilyToString(family),
     581             :                 TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     582             :                 GetTaskInstance());
     583             :     }
     584             : 
     585          80 :     total_path_count_ = 0;
     586          80 :     primary_path_count_ = 0;
     587             : 
     588             :     // Check rtinstance_ to accommodate unit tests.
     589          80 :     if (resolve_paths_ && rtinstance_) {
     590           0 :         rtinstance_->GetTable(Address::INET)->LocatePathResolver();
     591           0 :         rtinstance_->GetTable(Address::INET6)->LocatePathResolver();
     592             :     }
     593             : 
     594          80 :     ProcessEndpointConfig(config);
     595          80 :     ProcessAuthKeyChainConfig(config);
     596          80 :     ProcessFamilyAttributesConfig(config);
     597             : 
     598         160 :     BgpPeerInfoData peer_info;
     599          80 :     peer_info.set_name(ToUVEKey());
     600          80 :     peer_info.set_admin_down(admin_down_);
     601          80 :     peer_info.set_passive(passive_);
     602          80 :     peer_info.set_as_override(as_override_);
     603          80 :     peer_info.set_origin_override(origin_override_.origin_override);
     604          80 :     if (origin_override_.origin_override) {
     605           0 :         peer_info.set_route_origin(
     606           0 :             BgpAttr::OriginToString(origin_override_.origin));
     607             :     } else {
     608          80 :         peer_info.set_route_origin("-");
     609             :     }
     610          80 :     peer_info.set_router_type(router_type_);
     611          80 :     peer_info.set_cluster_id(Ip4Address(cluster_id_).to_string());
     612         160 :     peer_info.set_peer_type(
     613          80 :         PeerType() == BgpProto::IBGP ? "internal" : "external");
     614          80 :     peer_info.set_local_asn(local_as_);
     615          80 :     peer_info.set_peer_asn(peer_as_);
     616          80 :     peer_info.set_peer_port(peer_port_);
     617          80 :     peer_info.set_hold_time(hold_time_);
     618          80 :     peer_info.set_local_id(local_bgp_id_);
     619          80 :     peer_info.set_configured_families(configured_families_);
     620          80 :     peer_info.set_peer_address(peer_key_.endpoint.address().to_string());
     621          80 :     BGPPeerInfoSend(peer_info);
     622          80 : }
     623             : 
     624          80 : BgpPeer::~BgpPeer() {
     625          80 :     assert(!close_manager()->IsCloseInProgress());
     626          80 :     assert(!IsCloseInProgress());
     627          80 :     assert(GetTotalPathCount() == 0);
     628          80 :     STLDeleteValues(&family_attributes_list_);
     629          80 :     ClearListenSocketAuthKey();
     630         160 :     BgpPeerInfoData peer_info;
     631          80 :     peer_info.set_name(ToUVEKey());
     632          80 :     peer_info.set_deleted(true);
     633          80 :     BGPPeerInfoSend(peer_info);
     634             : 
     635         160 :     PeerStatsData peer_stats_data;
     636          80 :     peer_stats_data.set_name(ToUVEKey());
     637          80 :     peer_stats_data.set_deleted(true);
     638          80 :     assert(!peer_stats_data.get_name().empty());
     639          80 :     BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectBgpPeer");
     640             : 
     641         160 :     PeerFlapData peer_flap_data;
     642          80 :     peer_flap_data.set_name(ToUVEKey());
     643          80 :     peer_flap_data.set_deleted(true);
     644          80 :     assert(!peer_flap_data.get_name().empty());
     645          80 :     BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
     646             : 
     647          80 :     BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
     648             :         BGP_PEER_DIR_NA, "Deleted");
     649          80 : }
     650             : 
     651          80 : void BgpPeer::Initialize() {
     652          80 :     if (!admin_down_)
     653          80 :         state_machine_->Initialize();
     654          80 : }
     655             : 
     656          80 : size_t BgpPeer::GetBufferCapacity() const {
     657             :     // For testing only - configure through environment variable.
     658          80 :     char *buffer_capacity_str = getenv("BGP_PEER_BUFFER_SIZE");
     659          80 :     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          80 :     if (IsRouterTypeBGPaaS()) {
     670           0 :         return kMinBufferCapacity;
     671             :     } else {
     672          80 :         return kMaxBufferCapacity;
     673             :     }
     674             : }
     675             : 
     676         193 : bool BgpPeer::CheckSplitHorizon(uint32_t server_cluster_id,
     677             :         uint32_t ribout_cid) const {
     678         193 :     if (PeerType() == BgpProto::IBGP) {
     679             :         // check if router is a route reflector
     680         105 :         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           0 :         if (server_cluster_id != cluster_id_) {
     684             :             // If received from non-client, reflect to all the clients only
     685           0 :             if (ribout_cid && ribout_cid != server_cluster_id) {
     686           0 :                 return true;
     687             :             }
     688             :         }
     689             :     }
     690          88 :     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          96 : void BgpPeer::DeleteRTargets(as_t as) {
     755          96 :     if (!IsRouterTypeBGPaaS())
     756          96 :         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          64 : void BgpPeer::NotifyEstablished(bool established) {
     798          64 :     if (established) {
     799          32 :         if (IsRouterTypeBGPaaS()) {
     800           0 :             server_->IncrementUpBgpaasPeerCount();
     801           0 :             AddRTargets(server_->local_autonomous_system());
     802             :         } else {
     803          32 :             server_->IncrementUpPeerCount();
     804             :         }
     805             :     } else {
     806          32 :         if (IsRouterTypeBGPaaS()) {
     807           0 :             server_->DecrementUpBgpaasPeerCount();
     808             :         } else {
     809          32 :             server_->DecrementUpPeerCount();
     810             :         }
     811             :     }
     812          64 : }
     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         112 : bool BgpPeer::ProcessAuthKeyChainConfig(const BgpNeighborConfig *config) {
     831         112 :     const AuthenticationData &input_auth_data = config->auth_data();
     832             : 
     833         112 :     if (auth_data_ == input_auth_data) {
     834         112 :         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          80 : void BgpPeer::ClearListenSocketAuthKey() {
     888          80 :     if (inuse_authkey_type_ == AuthenticationData::MD5) {
     889           0 :         server_->session_manager()->SetListenSocketMd5Option(PeerAddress(), "");
     890             :     }
     891          80 : }
     892             : 
     893          64 : void BgpPeer::SetSessionSocketAuthKey(TcpSession *session) {
     894          64 :     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          64 : }
     901             : 
     902          32 : void BgpPeer::SetSessionSocketOptionDscp(TcpSession *session) {
     903          32 :     uint8_t dscp_value = server_->global_qos()->control_dscp();
     904             : 
     905          32 :     if (!session->socket()) {
     906           0 :         return;
     907             :     }
     908          32 :    if (dscp_value != 0xFF) {
     909          32 :         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          32 : bool BgpPeer::CheckPrefixLimits() {
     934          32 :     RetryDelete();
     935          32 :     if (!IsReady())
     936          32 :         return true;
     937           0 :     for (size_t idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
     938             :         BgpPeerFamilyAttributes *family_attributes =
     939           0 :             family_attributes_list_[idx];
     940           0 :         if (!family_attributes || family_attributes->prefix_limit == 0)
     941           0 :             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           0 :     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         112 : bool BgpPeer::ProcessFamilyAttributesConfig(const BgpNeighborConfig *config) {
     958         112 :     FamilyAttributesList family_attributes_list(Address::NUM_FAMILIES);
     959         496 :     BOOST_FOREACH(const BgpFamilyAttributesConfig family_config,
     960             :         config->family_attributes_list()) {
     961             :         Address::Family family =
     962         192 :             Address::FamilyFromString(family_config.family);
     963         192 :         assert(family != Address::UNSPEC);
     964             :         BgpPeerFamilyAttributes *family_attributes =
     965         192 :             new BgpPeerFamilyAttributes(config, family_config);
     966         192 :         family_attributes_list[family] = family_attributes;
     967         192 :     }
     968             : 
     969         112 :     int ret = STLSortedCompare(
     970             :         family_attributes_list.begin(), family_attributes_list.end(),
     971             :         family_attributes_list_.begin(), family_attributes_list_.end(),
     972             :         BgpPeerFamilyAttributesCompare());
     973         112 :     STLDeleteValues(&family_attributes_list_);
     974         112 :     family_attributes_list_ = family_attributes_list;
     975         112 :     configured_families_ = config->GetAddressFamilies();
     976         112 :     return (ret != 0);
     977         112 : }
     978             : 
     979         112 : void BgpPeer::ProcessEndpointConfig(const BgpNeighborConfig *config) {
     980         112 :     if (config->router_type() == "bgpaas-client") {
     981           0 :         endpoint_ = TcpSession::Endpoint(Ip4Address(), config->source_port());
     982             :     } else {
     983         112 :         endpoint_ = TcpSession::Endpoint();
     984             :     }
     985         112 : }
     986             : 
     987          32 : void BgpPeer::TriggerPrefixLimitCheck() const {
     988          32 :     prefix_limit_trigger_.Set();
     989          32 : }
     990             : 
     991          32 : void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
     992          32 :     if (IsDeleted())
     993           0 :         return;
     994             : 
     995          32 :     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          32 :     if (!config_)
    1000           0 :         return;
    1001             : 
    1002          32 :     bool clear_session = false;
    1003          32 :     bool admin_down_changed = false;
    1004          64 :     BgpPeerInfoData peer_info;
    1005          32 :     peer_info.set_name(ToUVEKey());
    1006             : 
    1007          32 :     if (admin_down_ != config->admin_down()) {
    1008           0 :         SetAdminState(config->admin_down());
    1009           0 :         peer_info.set_admin_down(admin_down_);
    1010           0 :         admin_down_changed = true;
    1011             :     }
    1012             : 
    1013          32 :     if (passive_ != config->passive()) {
    1014           0 :         passive_ = config->passive();
    1015           0 :         peer_info.set_passive(passive_);
    1016           0 :         clear_session = true;
    1017             :     }
    1018             : 
    1019          32 :     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          32 :     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          32 :     OriginOverride origin_override(config->origin_override());
    1032          32 :     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          32 :     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          64 :     if (router_type_ == "control-node" ||
    1050          32 :         router_type_ == "external-control-node") {
    1051           0 :         peer_is_control_node_ = true;
    1052             :     } else {
    1053          32 :         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          32 :     BgpPeerKey key(config);
    1061          32 :     if (peer_key_ != key) {
    1062           0 :         ClearListenSocketAuthKey();
    1063           0 :         peer_key_ = key;
    1064           0 :         peer_info.set_peer_address(peer_key_.endpoint.address().to_string());
    1065           0 :         clear_session = true;
    1066             :     }
    1067          32 :     if (ProcessAuthKeyChainConfig(config)) {
    1068           0 :         clear_session = true;
    1069             :     }
    1070             : 
    1071          32 :     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          32 :     ProcessEndpointConfig(config);
    1077             : 
    1078          32 :     if (local_as_ != config->local_as()) {
    1079           0 :         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           0 :         local_as_ = config->local_as();
    1086           0 :         peer_info.set_local_asn(local_as_);
    1087           0 :         clear_session = true;
    1088             :     }
    1089             : 
    1090          32 :     if (hold_time_ != config->hold_time()) {
    1091           0 :         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           0 :         hold_time_ = config->hold_time();
    1098           0 :         peer_info.set_hold_time(hold_time_);
    1099           0 :         clear_session = true;
    1100             :     }
    1101             : 
    1102          32 :     if (peer_as_ != config->peer_as()) {
    1103           0 :         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           0 :         peer_as_ = config->peer_as();
    1110           0 :         peer_info.set_peer_asn(peer_as_);
    1111           0 :         clear_session = true;
    1112             :     }
    1113             : 
    1114          32 :     boost::system::error_code ec;
    1115          32 :     uint32_t local_bgp_id = config->local_identifier();
    1116          32 :     if (local_bgp_id_ != local_bgp_id) {
    1117           0 :         local_bgp_id_ = local_bgp_id;
    1118           0 :         peer_info.set_local_id(local_bgp_id_);
    1119           0 :         clear_session = true;
    1120             :     }
    1121             : 
    1122          32 :     BgpProto::BgpPeerType old_type = PeerType();
    1123          32 :     peer_type_ = (peer_as_ == local_as_) ? BgpProto::IBGP : BgpProto::EBGP;
    1124          32 :     if (old_type != PeerType()) {
    1125           0 :         peer_info.set_peer_type(
    1126           0 :             PeerType() == BgpProto::IBGP ? "internal" : "external");
    1127           0 :         clear_session = true;
    1128             :     }
    1129             : 
    1130             :     // Check if there is any change in private-as-action configuration.
    1131          32 :     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          32 :     if (ProcessFamilyAttributesConfig(config)) {
    1138           0 :         peer_info.set_configured_families(configured_families_);
    1139           0 :         clear_session = true;
    1140             :     } else {
    1141          32 :         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          32 :     if (!admin_down_changed && !admin_down_ && clear_session) {
    1148           0 :         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           0 :         Clear(BgpProto::Notification::OtherConfigChange);
    1152             :     }
    1153             : 
    1154             :     // Send the UVE as appropriate.
    1155          32 :     if (admin_down_changed || clear_session) {
    1156           0 :         StopPrefixLimitIdleTimer();
    1157           0 :         BGPPeerInfoSend(peer_info);
    1158             :     }
    1159          32 : }
    1160             : 
    1161           0 : void BgpPeer::ClearConfig() {
    1162           0 :     CHECK_CONCURRENCY("bgp::Config");
    1163           0 :     config_ = NULL;
    1164           0 : }
    1165             : 
    1166          32 : LifetimeActor *BgpPeer::deleter() {
    1167          32 :     return deleter_.get();
    1168             : }
    1169             : 
    1170             : //
    1171             : // Check if the given address family has been negotiated with the peer.
    1172             : //
    1173         880 : bool BgpPeer::IsFamilyNegotiated(Address::Family family) {
    1174             :     // Bail if the family is not configured locally.
    1175         880 :     if (!LookupFamily(family))
    1176         487 :         return false;
    1177             : 
    1178             :     // Check if the peer advertised it in his Open message.
    1179             :     uint16_t afi;
    1180             :     uint8_t safi;
    1181         393 :     tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
    1182         393 :     return MpNlriAllowed(afi, safi);
    1183             : }
    1184             : 
    1185             : // Release resources for a peer that is going to be deleted.
    1186          80 : void BgpPeer::PostCloseRelease() {
    1187          80 :     if (index_ != -1) {
    1188          80 :         server_->UnregisterPeer(this);
    1189          80 :         index_ = -1;
    1190             :     }
    1191          80 :     TimerManager::DeleteTimer(keepalive_timer_);
    1192          80 :     TimerManager::DeleteTimer(prefix_limit_idle_timer_);
    1193             : 
    1194          80 :     for (Address::Family family = Address::UNSPEC;
    1195         880 :             family < Address::NUM_FAMILIES;
    1196         800 :             family = static_cast<Address::Family>(family + 1)) {
    1197         800 :         TimerManager::DeleteTimer(eor_send_timer_[family]);
    1198         800 :         TimerManager::DeleteTimer(eor_receive_timer_[family]);
    1199             :     }
    1200          80 : }
    1201             : 
    1202             : // IsReady
    1203             : //
    1204             : // Check whether this peer is up and ready
    1205             : //
    1206         472 : bool BgpPeer::IsReady() const {
    1207         472 :     return state_machine_->get_state() == StateMachine::ESTABLISHED;
    1208             : }
    1209             : 
    1210         684 : bool BgpPeer::IsXmppPeer() const {
    1211         684 :     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          80 : uint32_t BgpPeer::bgp_identifier() const {
    1223          80 :     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          96 : void BgpPeer::CustomClose() {
    1251          96 :     ResetCapabilities();
    1252          96 :     keepalive_timer_->Cancel();
    1253             : 
    1254          96 :     for (Address::Family family = Address::UNSPEC;
    1255        1056 :             family < Address::NUM_FAMILIES;
    1256         960 :             family = static_cast<Address::Family>(family + 1)) {
    1257         960 :         eor_send_timer_[family]->Cancel();
    1258         960 :         eor_receive_timer_[family]->Cancel();
    1259             :     }
    1260             : 
    1261          96 :     if (close_manager_->IsInDeleteState())
    1262          96 :         DeleteRTargets(server_->local_autonomous_system());
    1263          96 : }
    1264             : 
    1265             : //
    1266             : // Close this peer by closing all of it's RIBs.
    1267             : //
    1268          94 : void BgpPeer::Close(bool graceful) {
    1269          94 :     send_ready_ = true;
    1270          94 :     if (membership_req_pending_ && !close_manager_->IsMembershipInUse()) {
    1271           0 :         BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    1272             :             BGP_PEER_DIR_NA, "Close procedure deferred");
    1273           0 :         defer_close_ = true;
    1274             : 
    1275             :         // Note down non-graceful closures. Once a close is non-graceful,
    1276             :         // it shall remain as non-graceful.
    1277           0 :         graceful_close_ &= graceful;
    1278           0 :         return;
    1279             :     }
    1280             : 
    1281          94 :     peer_close_->Close(graceful);
    1282             : }
    1283             : 
    1284           0 : IPeerClose *BgpPeer::peer_close() {
    1285           0 :     return peer_close_.get();
    1286             : }
    1287             : 
    1288         184 : IPeerClose *BgpPeer::peer_close() const {
    1289         184 :     return peer_close_.get();
    1290             : }
    1291             : 
    1292         184 : void BgpPeer::UpdateCloseRouteStats(Address::Family family,
    1293             :         const BgpPath *old_path, uint32_t path_flags) const {
    1294         184 :     peer_close()->UpdateRouteStats(family, old_path, path_flags);
    1295         184 : }
    1296             : 
    1297         316 : IPeerDebugStats *BgpPeer::peer_stats() {
    1298         316 :     return peer_stats_.get();
    1299             : }
    1300             : 
    1301           0 : const IPeerDebugStats *BgpPeer::peer_stats() const {
    1302           0 :     return peer_stats_.get();
    1303             : }
    1304             : 
    1305          80 : void BgpPeer::Clear(int subcode) {
    1306          80 :     CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine");
    1307          80 :     state_machine_->Shutdown(subcode);
    1308          80 : }
    1309             : 
    1310             : //
    1311             : // Check whether this peer has been marked for deletion from configuration
    1312             : //
    1313         320 : bool BgpPeer::IsDeleted() const {
    1314         320 :     return deleter_->IsDeleted();
    1315             : }
    1316             : 
    1317           0 : bool BgpPeer::IsInGRTimerWaitState() const {
    1318           0 :     return close_manager_->IsInGRTimerWaitState();
    1319             : }
    1320             : 
    1321         304 : bool BgpPeer::IsCloseInProgress() const {
    1322         304 :     CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine");
    1323             : 
    1324             :     // trigger is set only after defer_close is reset
    1325         304 :     assert(!(defer_close_ && trigger_.IsSet()));
    1326         608 :     return defer_close_ || trigger_.IsSet() ||
    1327         304 :             (close_manager_->IsCloseInProgress() &&
    1328         304 :              !IsInGRTimerWaitState());
    1329             : }
    1330             : 
    1331         199 : StateMachine::State BgpPeer::GetState() const {
    1332         199 :     return state_machine_->get_state();
    1333             : }
    1334             : 
    1335           0 : const string BgpPeer::GetStateName() const {
    1336           0 :     return state_machine_->StateName();
    1337             : }
    1338             : 
    1339          32 : BgpSession *BgpPeer::CreateSession() {
    1340          32 :     if (PrefixLimitIdleTimerRunning())
    1341           0 :         return NULL;
    1342             : 
    1343          32 :     TcpSession *session = server_->session_manager()->CreateSession();
    1344          32 :     if (session == NULL)
    1345           0 :         return NULL;
    1346             : 
    1347             :     // Set valid keys, if any, in the socket.
    1348          32 :     SetSessionSocketAuthKey(session);
    1349             : 
    1350          32 :     BgpSession *bgp_session = static_cast<BgpSession *>(session);
    1351          32 :     BindLocalEndpoint(bgp_session);
    1352          32 :     bgp_session->set_peer(this);
    1353          32 :     return bgp_session;
    1354             : }
    1355             : 
    1356           0 : void BgpPeer::SetAdminState(bool down, int subcode) {
    1357           0 :     CHECK_CONCURRENCY("bgp::Config");
    1358           0 :     if (admin_down_ == down)
    1359           0 :         return;
    1360           0 :     admin_down_ = down;
    1361           0 :     state_machine_->SetAdminState(down, subcode);
    1362           0 :     if (admin_down_) {
    1363           0 :         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          32 : bool BgpPeer::AcceptSession(BgpSession *session) {
    1369          32 :     session->set_peer(this);
    1370             : 
    1371             :     // Set valid keys, if any, in the socket.
    1372          32 :     SetSessionSocketAuthKey(session);
    1373             : 
    1374             :     // Set control dscp, if any
    1375          32 :     SetSessionSocketOptionDscp(session);
    1376             : 
    1377          32 :     return state_machine_->PassiveOpen(session);
    1378             : }
    1379             : 
    1380         144 : 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         144 :     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         144 :     if (close_manager_->IsMembershipInWait())
    1393           0 :         assert(membership_req_pending_ > 0);
    1394         144 :     BgpMembershipManager *membership_mgr = server_->membership_mgr();
    1395         144 :     membership_req_pending_++;
    1396         144 :     membership_mgr->Register(this, table, policy);
    1397             : 
    1398             :     // Start EndOfRib receive timer.
    1399         144 :     StartEndOfRibReceiveTimer(table->family());
    1400         144 : }
    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          32 : void BgpPeer::RegisterAllTables() {
    1432          32 :     RoutingInstance *instance = GetRoutingInstance();
    1433             : 
    1434          32 :     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          32 :         (Address::INET)(Address::INETMPLS)(Address::INET6);
    1439         224 :     BOOST_FOREACH(Address::Family family, family_list) {
    1440          96 :         if (!IsFamilyNegotiated(family))
    1441          96 :             continue;
    1442           0 :         BgpTable *table = instance->GetTable(family);
    1443           0 :         BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
    1444             :                            table, "Register peer with the table");
    1445           0 :         Register(table, BuildRibExportPolicy(family));
    1446             :     }
    1447             : 
    1448             : 
    1449          64 :     if (((router_type_ == "bgpaas-client") ||
    1450          64 :         (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          32 :     vpn_tables_registered_ = false;
    1466          32 :     if (!IsFamilyNegotiated(Address::RTARGET)) {
    1467          32 :         RegisterToVpnTables();
    1468          32 :         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          32 : }
    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          48 : void BgpPeer::SendOpen(TcpSession *session) {
    1502          48 :     BgpProto::OpenMessage openmsg;
    1503          48 :     openmsg.as_num = local_as_ > 0xffff ? AS_TRANS : local_as_;
    1504          48 :     openmsg.holdtime = state_machine_->GetConfiguredHoldTime();
    1505          48 :     openmsg.identifier = ntohl(local_bgp_id_);
    1506             :     BgpProto::OpenMessage::OptParam *opt_param =
    1507          48 :         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          66 :     };
    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          49 :         (supported_families_[8], cap_mp[8]);
    1540             : 
    1541             :     // Add capabilities for configured address families.
    1542         912 :     BOOST_FOREACH(const FamilyToCapabilityMap::value_type &val,
    1543             :         family_to_cap_map) {
    1544         432 :         if (!LookupFamily(val.first))
    1545         288 :             continue;
    1546             :         BgpProto::OpenMessage::Capability *cap =
    1547             :             new BgpProto::OpenMessage::Capability(
    1548         144 :                 BgpProto::OpenMessage::Capability::MpExtension, val.second, 4);
    1549         144 :         opt_param->capabilities.push_back(cap);
    1550             :     }
    1551             : 
    1552          48 :     if (server_->enable_4byte_as()) {
    1553          24 :         uint32_t asn = ntohl(local_as_);
    1554             :         BgpProto::OpenMessage::Capability *cap =
    1555             :                 new BgpProto::OpenMessage::Capability(
    1556             :                     BgpProto::OpenMessage::Capability::AS4Support,
    1557          24 :                     (const uint8_t *)(&asn), 4);
    1558          24 :         opt_param->capabilities.push_back(cap);
    1559             :     }
    1560          48 :     peer_close_->AddGRCapabilities(opt_param);
    1561          48 :     peer_close_->AddLLGRCapabilities(opt_param);
    1562             : 
    1563          48 :     if (opt_param->capabilities.size()) {
    1564          48 :         openmsg.opt_params.push_back(opt_param);
    1565             :     } else {
    1566           0 :         delete opt_param;
    1567             :     }
    1568             :     uint8_t data[256];
    1569          48 :     int result = BgpProto::Encode(&openmsg, data, sizeof(data));
    1570          48 :     assert(result > BgpProto::kMinMessageSize);
    1571          48 :     BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    1572             :                  BGP_PEER_DIR_OUT, "Open "  << openmsg.ToString());
    1573          48 :     session->Send(data, result, NULL);
    1574          48 :     inc_tx_open();
    1575          48 : }
    1576             : 
    1577          32 : void BgpPeer::SendKeepalive(bool from_timer) {
    1578          32 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    1579             : 
    1580             :     // Bail if there's no session for the peer anymore.
    1581          32 :     if (!session_)
    1582           0 :         return;
    1583             : 
    1584          32 :     BgpProto::Keepalive msg;
    1585             :     uint8_t data[BgpProto::kMinMessageSize];
    1586          32 :     int result = BgpProto::Encode(&msg, data, sizeof(data));
    1587          32 :     assert(result == BgpProto::kMinMessageSize);
    1588          32 :     SandeshLevel::type log_level = from_timer ? Sandesh::LoggingUtLevel() :
    1589          32 :                                                 SandeshLevel::SYS_INFO;
    1590          32 :     BGP_LOG_PEER(Message, this, log_level, BGP_LOG_FLAG_SYSLOG,
    1591             :                  BGP_PEER_DIR_OUT, "Keepalive");
    1592          32 :     send_ready_ = session_->Send(data, result, NULL);
    1593          32 :     inc_tx_keepalive();
    1594          32 : }
    1595             : 
    1596         201 : static bool SkipUpdateSend() {
    1597             :     static bool init_;
    1598             :     static bool skip_;
    1599             : 
    1600         201 :     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         112 : BgpPeer::OriginOverride::OriginOverride(
    1609         112 :                 const BgpNeighborConfig::OriginOverrideConfig &config)
    1610         112 :         : origin_override(config.origin_override),
    1611         112 :         origin(BgpAttr::OriginFromString(config.origin)) {
    1612         112 : }
    1613             : 
    1614          32 : bool BgpPeer::OriginOverride::operator!=(const OriginOverride &rhs) const {
    1615          32 :     if (origin_override != rhs.origin_override) {
    1616           0 :         return true;
    1617             :     }
    1618             : 
    1619             :     // compare origin only if override is set
    1620          32 :     if (origin_override && origin != rhs.origin) {
    1621           0 :         return true;
    1622             :     }
    1623          32 :     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         284 : bool BgpPeer::SendUpdate(const uint8_t *msg, size_t msgsize,
    1632             :     const string *msg_str) {
    1633         284 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    1634         284 :     bool send_ready = true;
    1635         284 :     if (buffer_.size() + msgsize > buffer_capacity_) {
    1636           0 :         send_ready = FlushUpdateUnlocked();
    1637           0 :         assert(buffer_.empty());
    1638             :     }
    1639         284 :     buffer_.insert(buffer_.end(), msg, msg + msgsize);
    1640         284 :     inc_tx_update();
    1641         284 :     return send_ready;
    1642         284 : }
    1643             : 
    1644         284 : bool BgpPeer::FlushUpdateUnlocked() {
    1645             :     // Bail if the update buffer is empty.
    1646         284 :     if (buffer_.empty())
    1647           0 :         return true;
    1648             : 
    1649             :     // Bail if there's no session for the peer anymore.
    1650         284 :     if (!session_) {
    1651          83 :         buffer_.clear();
    1652          83 :         return true;
    1653             :     }
    1654             : 
    1655         201 :     if (!SkipUpdateSend()) {
    1656         201 :         send_ready_ = session_->Send(buffer_.data(), buffer_.size(), NULL);
    1657         201 :         buffer_.clear();
    1658         201 :         if (send_ready_) {
    1659         201 :             StartKeepaliveTimerUnlocked();
    1660             :         } else {
    1661           0 :             StopKeepaliveTimerUnlocked();
    1662             :         }
    1663             :     } else {
    1664           0 :         send_ready_ = true;
    1665             :     }
    1666             : 
    1667         201 :     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         201 :     return send_ready_;
    1672             : }
    1673             : 
    1674         284 : bool BgpPeer::FlushUpdate() {
    1675         284 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    1676         568 :     return FlushUpdateUnlocked();
    1677         284 : }
    1678             : 
    1679           0 : bool BgpPeer::notification() const {
    1680           0 :     return peer_close_->gr_params().notification();
    1681             : }
    1682             : 
    1683             : // Check if GR Helper mode sould be attempted.
    1684          94 : bool BgpPeer::AttemptGRHelperMode(int code, int subcode) const {
    1685          94 :     if (!code)
    1686           0 :         return true;
    1687             : 
    1688          94 :     if (code == BgpProto::Notification::Cease &&
    1689          95 :             (subcode == BgpProto::Notification::HardReset ||
    1690             :              subcode == BgpProto::Notification::PeerDeconfigured)) {
    1691          94 :         return false;
    1692             :     }
    1693             : 
    1694             :     // If Peer supports Notification (N) bit, then attempt GR-Helper for all
    1695             :     // other notifications, not otherwise.
    1696           0 :     return notification();
    1697             : }
    1698             : 
    1699          48 : void BgpPeer::SendNotification(BgpSession *session,
    1700             :         int code, int subcode, const string &data) {
    1701          48 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    1702          48 :     session->SendNotification(code, subcode, data);
    1703          48 :     state_machine_->set_last_notification_out(code, subcode, data);
    1704          48 :     inc_tx_notification();
    1705          48 : }
    1706             : 
    1707          32 : bool BgpPeer::SetCapabilities(const BgpProto::OpenMessage *msg) {
    1708          32 :     peer_bgp_id_ = htonl(msg->identifier);
    1709          32 :     capabilities_.clear();
    1710          32 :     vector<BgpProto::OpenMessage::OptParam *>::const_iterator it;
    1711          64 :     for (it = msg->opt_params.begin(); it < msg->opt_params.end(); ++it) {
    1712          32 :         capabilities_.insert(capabilities_.end(), (*it)->capabilities.begin(),
    1713          32 :                              (*it)->capabilities.end());
    1714          32 :         (*it)->capabilities.clear();
    1715             :     }
    1716             : 
    1717          32 :     as4_supported_ = false;
    1718          32 :     if (server_->enable_4byte_as()) {
    1719          16 :         vector<BgpProto::OpenMessage::Capability *>::iterator c_it;
    1720          64 :         for (c_it = capabilities_.begin(); c_it < capabilities_.end(); ++c_it) {
    1721          64 :             if ((*c_it)->code ==BgpProto::OpenMessage::Capability::AS4Support) {
    1722          16 :                 as4_supported_ = true;
    1723          16 :                 break;
    1724             :             }
    1725             :         }
    1726             :     }
    1727          64 :     BgpPeerInfoData peer_info;
    1728          32 :     peer_info.set_name(ToUVEKey());
    1729          32 :     peer_info.set_peer_id(peer_bgp_id_);
    1730             : 
    1731          32 :     vector<string> families;
    1732          32 :     vector<BgpProto::OpenMessage::Capability *>::iterator cap_it;
    1733         176 :     for (cap_it = capabilities_.begin(); cap_it < capabilities_.end();
    1734         144 :          ++cap_it) {
    1735         144 :         if ((*cap_it)->code != BgpProto::OpenMessage::Capability::MpExtension)
    1736          48 :             continue;
    1737          96 :         uint8_t *data = (*cap_it)->capability.data();
    1738          96 :         uint16_t afi = get_value(data, 2);
    1739          96 :         uint8_t safi = get_value(data + 3, 1);
    1740          96 :         Address::Family family = BgpAf::AfiSafiToFamily(afi, safi);
    1741          96 :         if (family == Address::UNSPEC) {
    1742           0 :             families.push_back(BgpAf::ToString(afi, safi));
    1743             :         } else {
    1744          96 :             families.push_back(Address::FamilyToString(family));
    1745             :         }
    1746             :     }
    1747          32 :     peer_info.set_families(families);
    1748             : 
    1749          32 :     negotiated_families_.clear();
    1750         352 :     for (int idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
    1751         320 :         if (!family_attributes_list_[idx])
    1752         224 :             continue;
    1753          96 :         Address::Family family = static_cast<Address::Family>(idx);
    1754             :         uint16_t afi;
    1755             :         uint8_t safi;
    1756          96 :         tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
    1757          96 :         if (!MpNlriAllowed(afi, safi))
    1758           0 :             continue;
    1759          96 :         negotiated_families_.push_back(Address::FamilyToString(family));
    1760             :     }
    1761          32 :     sort(negotiated_families_.begin(), negotiated_families_.end());
    1762          32 :     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          32 :     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          32 :     return true;
    1773          32 : }
    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          96 : void BgpPeer::ResetCapabilities() {
    1781          96 :     STLDeleteValues(&capabilities_);
    1782         192 :     BgpPeerInfoData peer_info;
    1783          96 :     peer_info.set_name(ToUVEKey());
    1784          96 :     vector<string> families = vector<string>();
    1785          96 :     peer_info.set_families(families);
    1786          96 :     vector<string> negotiated_families = vector<string>();
    1787          96 :     peer_info.set_negotiated_families(negotiated_families);
    1788          96 :     peer_info.set_graceful_restart_families(vector<string>());
    1789          96 :     BGPPeerInfoSend(peer_info);
    1790          96 : }
    1791             : 
    1792         489 : bool BgpPeer::MpNlriAllowed(uint16_t afi, uint8_t safi) {
    1793         489 :     vector<BgpProto::OpenMessage::Capability *>::iterator it;
    1794        1051 :     for (it = capabilities_.begin(); it < capabilities_.end(); ++it) {
    1795        1051 :         if ((*it)->code != BgpProto::OpenMessage::Capability::MpExtension)
    1796           0 :             continue;
    1797        1051 :         uint8_t *data = (*it)->capability.data();
    1798        1051 :         uint16_t af_value = get_value(data, 2);
    1799        1051 :         uint8_t safi_value = get_value(data + 3, 1);
    1800        1051 :         if (afi == af_value && safi == safi_value) {
    1801         489 :             return true;
    1802             :         }
    1803             :     }
    1804           0 :     return false;
    1805             : }
    1806             : 
    1807         492 : bool BgpPeer::Is4ByteAsSupported() const {
    1808         492 :     return as4_supported_;
    1809             : }
    1810             : 
    1811             : template <typename TableT, typename PrefixT>
    1812         201 : void BgpPeer::ProcessNlri(Address::Family family, DBRequest::DBOperation oper,
    1813             :     const BgpMpNlri *nlri, BgpAttrPtr attr, uint32_t flags) {
    1814         201 :     TableT *table = static_cast<TableT *>(rtinstance_->GetTable(family));
    1815         201 :     assert(table);
    1816             : 
    1817         402 :     for (vector<BgpProtoPrefix *>::const_iterator it = nlri->nlri.begin();
    1818         402 :          it != nlri->nlri.end(); ++it) {
    1819         201 :         PrefixT prefix;
    1820         201 :         BgpAttrPtr new_attr(attr);
    1821         201 :         uint32_t label = 0;
    1822         201 :         uint32_t l3_label = 0;
    1823         333 :         int result = PrefixT::FromProtoPrefix(server_, **it,
    1824         132 :             (oper == DBRequest::DB_ENTRY_ADD_CHANGE ? attr.get() : NULL),
    1825             :             family, &prefix, &new_attr, &label, &l3_label);
    1826         201 :         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         201 :         DBRequest req;
    1835         201 :         req.oper = oper;
    1836         201 :         if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
    1837         132 :             req.data.reset(new typename TableT::RequestData(
    1838             :                 new_attr, flags, label, l3_label, 0));
    1839             :         }
    1840         201 :         req.key.reset(new typename TableT::RequestKey(prefix, this));
    1841         201 :         table->Enqueue(&req);
    1842             :     }
    1843         201 : }
    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         132 : uint32_t BgpPeer::GetPathFlags(Address::Family family,
    1901             :     const BgpAttr *attr) const {
    1902         132 :     uint32_t flags = resolve_paths_ ? BgpPath::ResolveNexthop : 0;
    1903             : 
    1904             :     // Check for OriginatorId loop in case we are an RR client.
    1905         202 :     if (peer_type_ == BgpProto::IBGP &&
    1906          70 :         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         132 :     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         132 :     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         256 :     if ((PeerType() == BgpProto::EBGP) &&
    1922         124 :           ((attr->as_path() && !attr->as_path()->path().AsLeftMostMatch(
    1923          93 :           peer_as())) || (attr->aspath_4byte() &&
    1924          31 :           !attr->aspath_4byte()->path().AsLeftMostMatch(peer_as())))) {
    1925           0 :         flags |= BgpPath::NoNeighborAs;
    1926             :     }
    1927             : 
    1928             :     // Check for AS_PATH loop.
    1929         132 :     uint8_t max_loop_count = family_attributes_list_[family]->loop_count;
    1930         132 :     if (attr->IsAsPathLoop(local_as_, max_loop_count))
    1931           4 :         flags |= BgpPath::AsPathLooped;
    1932             : 
    1933         132 :     return flags;
    1934             : }
    1935             : 
    1936         297 : uint32_t BgpPeer::GetLocalPrefFromMed(uint32_t med) const {
    1937         297 :     if (peer_type_ != BgpProto::EBGP)
    1938         156 :         return 0;
    1939         141 :     if (!peer_is_control_node_)
    1940         141 :         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         297 : void BgpPeer::ProcessUpdate(const BgpProto::Update *msg, size_t msgsize) {
    1951         297 :     BgpAttrPtr attr = server_->attr_db()->Locate(msg->path_attributes);
    1952             : 
    1953         297 :     uint32_t local_pref = GetLocalPrefFromMed(attr->med());
    1954         297 :     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         297 :     if (origin_override_.origin_override) {
    1961           0 :         attr = server_->attr_db()->ReplaceOriginAndLocate(attr.get(),
    1962           0 :                                                        origin_override_.origin);
    1963             :     }
    1964             : 
    1965         594 :     if ((router_type_ == "bgpaas-client") ||
    1966         297 :         (router_type_ == "bgpaas-server")) {
    1967           0 :         attr = server_->attr_db()->ReplaceSubProtocolAndLocate(attr.get(),
    1968           0 :                              MatchProtocolToString(MatchProtocol::BGPaaS));
    1969             :     }
    1970             : 
    1971         297 :     uint32_t reach_count = 0, unreach_count = 0;
    1972         297 :     RoutingInstance *instance = GetRoutingInstance();
    1973         297 :     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         297 :     for (vector<BgpAttribute *>::const_iterator ait =
    2036         297 :             msg->path_attributes.begin();
    2037         968 :             ait != msg->path_attributes.end(); ++ait) {
    2038             :         DBRequest::DBOperation oper;
    2039         767 :         if ((*ait)->code == BgpAttribute::MPReachNlri) {
    2040         132 :             oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    2041         635 :         } else if ((*ait)->code == BgpAttribute::MPUnreachNlri) {
    2042         165 :             oper = DBRequest::DB_ENTRY_DELETE;
    2043             :         } else {
    2044         470 :             continue;
    2045             :         }
    2046             : 
    2047         297 :         BgpMpNlri *nlri = static_cast<BgpMpNlri *>(*ait);
    2048         297 :         assert(nlri);
    2049         297 :         if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
    2050         132 :             reach_count += nlri->nlri.size();
    2051             :         } else {
    2052         165 :             unreach_count += nlri->nlri.size();
    2053             :         }
    2054             : 
    2055         297 :         Address::Family family = BgpAf::AfiSafiToFamily(nlri->afi, nlri->safi);
    2056         297 :         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         297 :         if (oper == DBRequest::DB_ENTRY_DELETE && nlri->nlri.empty()) {
    2066          96 :             inc_rx_end_of_rib();
    2067          96 :             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          96 :             ReceiveEndOfRIB(family, msgsize);
    2073          96 :             return;
    2074             :         }
    2075             : 
    2076         201 :         uint32_t flags = 0;
    2077         201 :         if ((*ait)->code == BgpAttribute::MPReachNlri) {
    2078         132 :             flags = GetPathFlags(family, attr.get());
    2079         132 :             attr = GetMpNlriNexthop(nlri, attr);
    2080             :         }
    2081             : 
    2082         201 :         switch (family) {
    2083           0 :         case Address::INET:
    2084             :         case Address::INETMPLS:
    2085           0 :             ProcessNlri<InetTable, Ip4Prefix>(
    2086             :                 family, oper, nlri, attr, flags);
    2087           0 :             if ((router_type_ == "bgpaas-client") ||
    2088           0 :                 (router_type_ == "bgpaas-server")) {
    2089           0 :                 ProcessNlriBgpaas<Ip4Prefix>(
    2090             :                     family, oper, nlri, attr, flags);
    2091             :             }
    2092           0 :             break;
    2093          64 :         case Address::INETVPN:
    2094          64 :             ProcessNlri<InetVpnTable, InetVpnPrefix>(
    2095             :                 family, oper, nlri, attr, flags);
    2096          64 :             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         137 :         case Address::MVPN:
    2119         137 :             ProcessNlri<MvpnTable, MvpnPrefix>(
    2120             :                 family, oper, nlri, attr, flags);
    2121         137 :             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         201 :     inc_rx_route_reach(reach_count);
    2132         201 :     inc_rx_route_unreach(unreach_count);
    2133         201 :     if (Sandesh::LoggingLevel() >= Sandesh::LoggingUtLevel()) {
    2134         201 :         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         297 : }
    2140         372 : const std::vector<std::string> BgpPeer::GetDefaultTunnelEncap(
    2141             :     const Address::Family family) const {
    2142         372 :     if (family_attributes_list_[family] == NULL)
    2143         144 :         return std::vector<std::string>();
    2144         228 :     return family_attributes_list_[family]->default_tunnel_encap_list;
    2145             : }
    2146             : 
    2147         372 : void BgpPeer::ProcessPathTunnelEncapsulation(const BgpPath *path, BgpAttr *attr,
    2148             :                                              ExtCommunityDB *extcomm_db,
    2149             :                                              const BgpTable *table) const {
    2150         372 :     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         372 : }
    2179             : 
    2180             : 
    2181         368 : void BgpPeer::UpdatePrimaryPathCount(int count, Address::Family family) const {
    2182         368 :     primary_path_count_ += count;
    2183         368 :     if (family == Address::UNSPEC)
    2184           0 :         return;
    2185         368 :     family_primary_path_count_[family] += count;
    2186         368 :     uint32_t limit = 0;
    2187         368 :     if (family_attributes_list_[family])
    2188         264 :         limit = family_attributes_list_[family]->prefix_limit;
    2189         368 :     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           0 : void BgpPeer::StopPrefixLimitIdleTimer() {
    2200           0 :     prefix_limit_idle_timer_->Cancel();
    2201           0 : }
    2202             : 
    2203          64 : bool BgpPeer::PrefixLimitIdleTimerRunning() const {
    2204          64 :     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          32 : void BgpPeer::RegisterToVpnTables() {
    2224          32 :     CHECK_CONCURRENCY("bgp::StateMachine", "bgp::RTFilter", "bgp::Config");
    2225             : 
    2226          32 :     if (vpn_tables_registered_)
    2227           0 :         return;
    2228          32 :     vpn_tables_registered_ = true;
    2229             : 
    2230          32 :     RoutingInstance *instance = GetRoutingInstance();
    2231             :     vector<Address::Family> vpn_family_list = list_of
    2232          32 :         (Address::INETVPN)(Address::INET6VPN)(Address::ERMVPN)(Address::EVPN)
    2233          32 :         (Address::MVPN);
    2234         352 :     BOOST_FOREACH(Address::Family vpn_family, vpn_family_list) {
    2235         160 :         if (!IsFamilyNegotiated(vpn_family))
    2236          64 :             continue;
    2237          96 :         BgpTable *table = instance->GetTable(vpn_family);
    2238          96 :         BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_TRACE,
    2239             :             table, "Register peer with the table");
    2240          96 :         Register(table, BuildRibExportPolicy(vpn_family));
    2241             :     }
    2242          32 : }
    2243             : 
    2244         144 : void BgpPeer::StartEndOfRibReceiveTimer(Address::Family family) {
    2245         144 :     uint32_t timeout = GetEndOfRibReceiveTime(family);
    2246             : 
    2247         144 :     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         144 :     eor_receive_timer_[family]->Start(timeout * 1000,
    2253             :         boost::bind(&BgpPeer::EndOfRibReceiveTimerExpired, this, family),
    2254             :         boost::bind(&BgpPeer::EndOfRibTimerErrorHandler, this, _1, _2));
    2255         144 : }
    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           0 : bool BgpPeer::KeepaliveTimerExpired() {
    2273           0 :     if (!IsReady())
    2274           0 :         return false;
    2275             : 
    2276           0 :     SendKeepalive(true);
    2277             : 
    2278             :     //
    2279             :     // Start the timer again, by returning true
    2280             :     //
    2281           0 :     return true;
    2282             : }
    2283             : 
    2284         233 : void BgpPeer::StartKeepaliveTimerUnlocked() {
    2285         233 :     int keepalive_time_msecs = state_machine_->keepalive_time_msecs();
    2286         233 :     if (keepalive_time_msecs <= 0)
    2287           0 :         return;
    2288             : 
    2289         233 :     keepalive_timer_->Start(keepalive_time_msecs,
    2290             :         boost::bind(&BgpPeer::KeepaliveTimerExpired, this),
    2291             :         boost::bind(&BgpPeer::KeepaliveTimerErrorHandler, this, _1, _2));
    2292             : }
    2293             : 
    2294          32 : void BgpPeer::StartKeepaliveTimer() {
    2295          32 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    2296          32 :     if (session_ && send_ready_)
    2297          32 :         StartKeepaliveTimerUnlocked();
    2298          32 : }
    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          32 : void BgpPeer::set_session(BgpSession *session) {
    2319          32 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    2320          32 :     assert(session_ == NULL);
    2321          32 :     session_ = session;
    2322          32 : }
    2323             : 
    2324         174 : void BgpPeer::clear_session() {
    2325         174 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    2326         176 :     if (session_) {
    2327          32 :         session_->clear_peer();
    2328          32 :         session_->set_observer(NULL);
    2329          32 :         session_->Close();
    2330             :     }
    2331         176 :     session_ = NULL;
    2332         176 : }
    2333             : 
    2334         333 : BgpSession *BgpPeer::session() {
    2335         333 :     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         396 : bool BgpPeer::ReceiveMsg(BgpSession *session, const u_int8_t *msg,
    2355             :                          size_t size) {
    2356         396 :     ParseErrorContext ec;
    2357         792 :     BgpProto::BgpMessage *minfo = BgpProto::Decode(msg, size, &ec,
    2358         396 :                                                    Is4ByteAsSupported());
    2359             : 
    2360         396 :     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         396 :     if (minfo->type != BgpProto::KEEPALIVE)
    2371         364 :         BGP_TRACE_PEER_PACKET(this, msg, size, SandeshLevel::SYS_WARN); //Sandesh::LoggingUtLevel()
    2372             : 
    2373         396 :     state_machine_->OnMessage(session, minfo, size);
    2374         396 :     return true;
    2375         396 : }
    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         132 : BgpAttrPtr BgpPeer::GetMpNlriNexthop(BgpMpNlri *nlri, BgpAttrPtr attr) {
    2383         132 :     bool update_nh = false;
    2384         132 :     IpAddress addr;
    2385             : 
    2386         132 :     if (nlri->afi == BgpAf::IPv4) {
    2387         132 :         if (nlri->safi == BgpAf::Mpls || nlri->safi == BgpAf::Unicast ||
    2388         132 :             nlri->safi == BgpAf::RTarget || nlri->safi == BgpAf::MVpn) {
    2389          96 :             Ip4Address::bytes_type bt = { { 0 } };
    2390         192 :             copy(nlri->nexthop.begin(),
    2391          96 :                 nlri->nexthop.begin() + sizeof(bt), bt.begin());
    2392          96 :             addr = Ip4Address(bt);
    2393          96 :             update_nh = true;
    2394         132 :         } else if (nlri->safi == BgpAf::Vpn) {
    2395          36 :             Ip4Address::bytes_type bt = { { 0 } };
    2396          36 :             size_t rdsize = RouteDistinguisher::kSize;
    2397          72 :             copy(nlri->nexthop.begin() + rdsize,
    2398          36 :                 nlri->nexthop.begin() + rdsize + sizeof(bt), bt.begin());
    2399          36 :             addr = Ip4Address(bt);
    2400          36 :             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         132 :     if (update_nh) {
    2452         132 :         attr = server_->attr_db()->ReplaceNexthopAndLocate(attr.get(), addr);
    2453             :     }
    2454         264 :     return attr;
    2455             : }
    2456             : 
    2457          80 : void BgpPeer::ManagedDelete() {
    2458          80 :     if (deleter_->IsDeleted())
    2459           0 :         return;
    2460          80 :     BGP_LOG_PEER(Config, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    2461             :                  BGP_PEER_DIR_NA, "Received request for deletion");
    2462          80 :     if (IsRouterTypeBGPaaS()) {
    2463           0 :         server()->increment_deleting_bgpaas_count();
    2464             :     } else {
    2465          80 :         server()->increment_deleting_count();
    2466             :     }
    2467          80 :     deleter_->Delete();
    2468             : }
    2469             : 
    2470         190 : void BgpPeer::RetryDelete() {
    2471         190 :     if (!deleter_->IsDeleted())
    2472          32 :         return;
    2473         157 :     deleter_->RetryDelete();
    2474             : }
    2475             : 
    2476        2384 : int BgpPeer::GetTaskInstance() const {
    2477        2384 :     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          48 : void BgpPeer::inc_rx_open() {
    2657          48 :     peer_stats_->proto_stats_[0].open++;
    2658          48 : }
    2659             : 
    2660          48 : void BgpPeer::inc_tx_open() {
    2661          48 :     peer_stats_->proto_stats_[1].open++;
    2662          48 : }
    2663             : 
    2664          32 : void BgpPeer::inc_rx_keepalive() {
    2665          32 :     peer_stats_->proto_stats_[0].keepalive++;
    2666          32 : }
    2667             : 
    2668           0 : uint64_t BgpPeer::get_rx_keepalive() const {
    2669           0 :     return peer_stats_->proto_stats_[0].keepalive;
    2670             : }
    2671             : 
    2672          32 : void BgpPeer::inc_tx_keepalive() {
    2673          32 :     peer_stats_->proto_stats_[1].keepalive++;
    2674          32 : }
    2675             : 
    2676           0 : uint64_t BgpPeer::get_tx_keepalive() const {
    2677           0 :     return peer_stats_->proto_stats_[1].keepalive;
    2678             : }
    2679             : 
    2680         297 : void BgpPeer::inc_rx_update() {
    2681         297 :     peer_stats_->proto_stats_[0].update++;
    2682         297 : }
    2683             : 
    2684           0 : uint64_t BgpPeer::get_rx_update() const {
    2685           0 :     return peer_stats_->proto_stats_[0].update;
    2686             : }
    2687             : 
    2688         380 : void BgpPeer::inc_tx_update() {
    2689         380 :     peer_stats_->proto_stats_[1].update++;
    2690         380 : }
    2691             : 
    2692           0 : uint64_t BgpPeer::get_tx_update() const {
    2693           0 :     return peer_stats_->proto_stats_[1].update;
    2694             : }
    2695             : 
    2696          19 : void BgpPeer::inc_rx_notification() {
    2697          19 :     peer_stats_->proto_stats_[0].notification++;
    2698          19 : }
    2699             : 
    2700           0 : uint64_t BgpPeer::get_rx_notification() const {
    2701           0 :     return peer_stats_->proto_stats_[0].notification;
    2702             : }
    2703             : 
    2704          48 : void BgpPeer::inc_tx_notification() {
    2705          48 :     peer_stats_->proto_stats_[1].notification++;
    2706          48 : }
    2707             : 
    2708          96 : void BgpPeer::inc_rx_end_of_rib() {
    2709          96 :     peer_stats_->update_stats_[0].end_of_rib++;
    2710          96 : }
    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          96 : void BgpPeer::inc_tx_end_of_rib() {
    2717          96 :     peer_stats_->update_stats_[1].end_of_rib++;
    2718          96 : }
    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         201 : void BgpPeer::inc_rx_route_reach(uint64_t count) {
    2725         201 :     peer_stats_->update_stats_[0].reach += count;
    2726         201 : }
    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         201 : void BgpPeer::inc_rx_route_unreach(uint64_t count) {
    2737         201 :     peer_stats_->update_stats_[0].unreach += count;
    2738         201 : }
    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           0 : void BgpPeer::inc_connect_error() {
    2761           0 :     peer_stats_->error_stats_.connect_error++;
    2762           0 : }
    2763             : 
    2764           0 : void BgpPeer::inc_connect_timer_expired() {
    2765           0 :     peer_stats_->error_stats_.connect_timer++;
    2766           0 : }
    2767             : 
    2768           0 : void BgpPeer::inc_hold_timer_expired() {
    2769           0 :     peer_stats_->error_stats_.hold_timer++;
    2770           0 : }
    2771             : 
    2772           0 : void BgpPeer::inc_open_error() {
    2773           0 :     peer_stats_->error_stats_.open_error++;
    2774           0 : }
    2775             : 
    2776           0 : void BgpPeer::inc_update_error() {
    2777           0 :     peer_stats_->error_stats_.update_error++;
    2778           0 : }
    2779             : 
    2780           0 : uint64_t BgpPeer::get_connect_error() const {
    2781           0 :     return peer_stats_->error_stats_.connect_error;
    2782             : }
    2783             : 
    2784           0 : uint64_t BgpPeer::get_connect_timer_expired() const {
    2785           0 :     return peer_stats_->error_stats_.connect_timer;
    2786             : }
    2787             : 
    2788           0 : uint64_t BgpPeer::get_hold_timer_expired() const {
    2789           0 :     return peer_stats_->error_stats_.hold_timer;
    2790             : }
    2791             : 
    2792           0 : uint64_t BgpPeer::get_open_error() const {
    2793           0 :     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          32 : void BgpPeer::increment_flap_count() {
    2821          32 :     flap_count_++;
    2822          32 :     total_flap_count_++;
    2823          32 :     last_flap_ = UTCTimestampUsec();
    2824             : 
    2825          64 :     BgpPeerInfoData peer_info;
    2826          32 :     peer_info.set_name(ToUVEKey());
    2827          32 :     PeerFlapInfo flap_info;
    2828          32 :     flap_info.set_flap_count(flap_count_);
    2829          32 :     flap_info.set_flap_time(last_flap_);
    2830          32 :     peer_info.set_flap_info(flap_info);
    2831          32 :     BGPPeerInfoSend(peer_info);
    2832             : 
    2833          64 :     PeerFlapData peer_flap_data;
    2834          32 :     peer_flap_data.set_name(ToUVEKey());
    2835          32 :     peer_flap_data.set_flap_info(flap_info);
    2836          32 :     assert(!peer_flap_data.get_name().empty());
    2837          32 :     BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
    2838          32 : }
    2839             : 
    2840           0 : void BgpPeer::reset_flap_count() {
    2841           0 :     flap_count_ = 0;
    2842           0 :     last_flap_ = 0;
    2843             : 
    2844           0 :     BgpPeerInfoData peer_info;
    2845           0 :     peer_info.set_name(ToUVEKey());
    2846           0 :     PeerFlapInfo flap_info;
    2847           0 :     peer_info.set_flap_info(flap_info);
    2848           0 :     BGPPeerInfoSend(peer_info);
    2849             : 
    2850           0 :     PeerFlapData peer_flap_data;
    2851           0 :     peer_flap_data.set_name(ToUVEKey());
    2852           0 :     peer_flap_data.set_flap_info(flap_info);
    2853           0 :     assert(!peer_flap_data.get_name().empty());
    2854           0 :     BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
    2855           0 : }
    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          32 : bool BgpPeer::ProcessSession() const {
    2860          32 :     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 : }

Generated by: LCOV version 1.14