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

Generated by: LCOV version 1.14