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-08 02:02:55 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       10358 :     explicit PeerStats(BgpPeer *peer)
      57       51790 :         : peer_(peer) {
      58       10358 :     }
      59             : 
      60             :     // Used when peer flaps.
      61             :     // Reset all counters.
      62             :     // Socket counters are implicitly cleared because we use a new socket.
      63        5247 :     virtual void Clear() {
      64        5247 :         error_stats_ = ErrorStats();
      65        5247 :         proto_stats_[0] = ProtoStats();
      66        5246 :         proto_stats_[1] = ProtoStats();
      67        5247 :         update_stats_[0] = UpdateStats();
      68        5246 :         update_stats_[1] = UpdateStats();
      69        5247 :     }
      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         206 :     virtual void GetRxProtoStats(ProtoStats *stats) const {
     102         206 :         *stats = proto_stats_[0];
     103         206 :     }
     104             : 
     105         206 :     virtual void GetTxProtoStats(ProtoStats *stats) const {
     106         206 :         *stats = proto_stats_[1];
     107         206 :     }
     108             : 
     109         356 :     virtual void GetRxRouteUpdateStats(UpdateStats *stats)  const {
     110         356 :         *stats = update_stats_[0];
     111         356 :     }
     112             : 
     113         356 :     virtual void GetTxRouteUpdateStats(UpdateStats *stats)  const {
     114         356 :         *stats = update_stats_[1];
     115         356 :     }
     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      158974 :     virtual void UpdateTxUnreachRoute(uint64_t count) {
     137      158974 :         update_stats_[1].unreach += count;
     138      158974 :     }
     139             : 
     140      158959 :     virtual void UpdateTxReachRoute(uint64_t count) {
     141      158959 :         update_stats_[1].reach += count;
     142      158959 :     }
     143             : 
     144             :     // Do nothing for bgp peers.
     145         150 :     virtual void GetRxErrorStats(RxErrorStats *stats) const {
     146         150 :     }
     147             : 
     148         150 :     virtual void GetRxRouteStats(RxRouteStats *stats) const {
     149         150 :         stats->total_path_count = peer_->GetTotalPathCount();
     150         150 :         stats->primary_path_count = peer_->GetPrimaryPathCount();
     151         150 :     }
     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       10358 :     explicit DeleteActor(BgpPeer *peer)
     165       10358 :         : LifetimeActor(peer->server_->lifetime_manager()),
     166       10358 :           peer_(peer) {
     167       10358 :     }
     168             : 
     169       23712 :     virtual bool MayDelete() const {
     170       23712 :         CHECK_CONCURRENCY("bgp::Config");
     171       23712 :         if (!peer_->close_manager_->IsQueueEmpty())
     172        5872 :             return false;
     173       17840 :         if (peer_->IsCloseInProgress())
     174           0 :             return false;
     175       17840 :         if (!peer_->state_machine_->IsQueueEmpty())
     176        8273 :             return false;
     177        9567 :         if (peer_->prefix_limit_trigger_.IsSet())
     178           0 :             return false;
     179        9567 :         return true;
     180             :     }
     181             : 
     182        9567 :     virtual void Shutdown() {
     183        9567 :         CHECK_CONCURRENCY("bgp::Config");
     184        9567 :         peer_->Clear(BgpProto::Notification::PeerDeconfigured);
     185        9567 :     }
     186             : 
     187        9567 :     virtual void Destroy() {
     188        9567 :         CHECK_CONCURRENCY("bgp::Config");
     189        9567 :         peer_->PostCloseRelease();
     190        9567 :         if (peer_->IsRouterTypeBGPaaS()) {
     191         112 :             peer_->server()->decrement_deleting_bgpaas_count();
     192             :         } else {
     193        9455 :             peer_->server()->decrement_deleting_count();
     194             :         }
     195        9567 :         if (peer_->dscp_listener_id_ >= 0) {
     196        9567 :             peer_->server()->UnregisterDSCPUpdateCallback(
     197        9567 :                                         peer_->dscp_listener_id_);
     198        9567 :             peer_->dscp_listener_id_ = -1;
     199             :         }
     200        9567 :         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        9567 :         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        9567 :         assert(!peer_->membership_req_pending());
     211        9567 :         assert(!peer_->close_manager_->IsMembershipInUse());
     212        9567 :         peer_->rtinstance_->peer_manager()->DestroyIPeer(peer_);
     213        9567 :     }
     214             : 
     215             : private:
     216             :     BgpPeer *peer_;
     217             : };
     218             : 
     219             : //
     220             : // Constructor for BgpPeerFamilyAttributes.
     221             : //
     222       32616 : BgpPeerFamilyAttributes::BgpPeerFamilyAttributes(
     223             :     const BgpNeighborConfig *config,
     224       32616 :     const BgpFamilyAttributesConfig &family_config) {
     225       32616 :     if (family_config.loop_count) {
     226          16 :         loop_count = family_config.loop_count;
     227             :     } else {
     228       32600 :         loop_count = config->loop_count();
     229             :     }
     230       32616 :     prefix_limit = family_config.prefix_limit;
     231       32616 :     idle_timeout = family_config.idle_timeout;
     232       32616 :     default_tunnel_encap_list = family_config.default_tunnel_encap_list;
     233             : 
     234       32616 :     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       32616 : }
     242             : 
     243       12818 : RibExportPolicy BgpPeer::BuildRibExportPolicy(Address::Family family) const {
     244       12818 :     RibExportPolicy policy;
     245             :     BgpPeerFamilyAttributes *family_attributes =
     246       12816 :         family_attributes_list_[family];
     247       12815 :     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       12804 :         policy = RibExportPolicy(peer_type_, RibExportPolicy::BGP, peer_as_,
     253       12808 :             as_override_, peer_close_->IsCloseLongLivedGraceful(),
     254       12808 :             as4_supported_, family_attributes->gateway_address,
     255       12808 :             -1, cluster_id_, family_attributes->default_tunnel_encap_list,
     256       25612 :             local_as_);
     257             :     }
     258             : 
     259       12810 :     if (private_as_action_ == "remove") {
     260           2 :         policy.SetRemovePrivatePolicy(false, false, true);
     261       12809 :     } else if (private_as_action_ == "remove-all") {
     262           2 :         policy.SetRemovePrivatePolicy(true, false, true);
     263       12806 :     } else if (private_as_action_ == "replace-all") {
     264           1 :         policy.SetRemovePrivatePolicy(true, true, true);
     265             :     }
     266             : 
     267       12810 :     return policy;
     268           0 : }
     269             : 
     270       12706 : void BgpPeer::ReceiveEndOfRIB(Address::Family family, size_t msgsize) {
     271       12706 :     close_manager_->ProcessEORMarkerReceived(family);
     272       12708 :     eor_receive_timer_[family]->Cancel();
     273             : 
     274             :     // If EoR for RTarget is received, start registration for other families.
     275       12708 :     if (family == Address::RTARGET)
     276        2624 :         RegisterToVpnTables();
     277       12706 : }
     278             : 
     279       12885 : void BgpPeer::SendEndOfRIBActual(Address::Family family) {
     280       12885 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
     281             : 
     282             :     // Bail if there's no session for the peer anymore.
     283       12885 :     if (!session_)
     284          58 :         return;
     285             : 
     286       12827 :     BgpProto::Update update;
     287             :     uint16_t afi;
     288             :     uint8_t safi;
     289       12827 :     tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
     290       12827 :     BgpMpNlri *nlri = new BgpMpNlri(BgpAttribute::MPUnreachNlri, afi, safi);
     291       12827 :     update.path_attributes.push_back(nlri);
     292             :     uint8_t data[256];
     293       25654 :     int msgsize = BgpProto::Encode(&update, data, sizeof(data), NULL,
     294       12827 :                                    Is4ByteAsSupported());
     295       12827 :     assert(msgsize > BgpProto::kMinMessageSize);
     296       12827 :     session_->Send(data, msgsize, NULL);
     297       12827 :     inc_tx_end_of_rib();
     298       12827 :     inc_tx_update();
     299       12827 :     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       12885 : }
     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       19796 : uint32_t BgpPeer::GetEndOfRibReceiveTime(Address::Family family) const {
     315       19796 :     return family == Address::RTARGET ?
     316       19796 :         kRouteTargetEndOfRibTimeSecs : server_->GetEndOfRibReceiveTime();
     317             : }
     318             : 
     319        9123 : bool BgpPeer::IsServerStartingUp() const {
     320        9123 :     return server_->IsServerStartingUp();
     321             : }
     322             : 
     323         100 : bool BgpPeer::IsCloseGraceful() const {
     324         100 :     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       42049 : void BgpPeer::BGPPeerInfoSend(const BgpPeerInfoData &peer_info) const {
     417       42049 :     assert(!peer_info.get_name().empty());
     418       42048 :     BGP_UVE_SEND(BGPPeerInfo, peer_info);
     419       42050 : }
     420             : 
     421       13061 : bool BgpPeer::CanUseMembershipManager() const {
     422       13061 :     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       27840 : void BgpPeer::MembershipRequestCallback(BgpTable *table) {
     431       27840 :     if (close_manager_->IsMembershipInUse()) {
     432       14960 :         close_manager_->MembershipRequestCallback();
     433       14960 :         return;
     434             :     }
     435             : 
     436       12880 :     assert(membership_req_pending_ > 0);
     437       12880 :     membership_req_pending_--;
     438             : 
     439             :     // Resume if CloseManager is waiting to use membership manager.
     440       20372 :     if (!membership_req_pending_ &&
     441        7492 :         close_manager_->IsMembershipInWait()) {
     442          23 :         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       12880 :     if (defer_close_) {
     448         107 :         if (!membership_req_pending_) {
     449          49 :             defer_close_ = false;
     450          49 :             trigger_.Set();
     451             :         }
     452         107 :         return;
     453             :     }
     454             : 
     455       12773 :     SendEndOfRIB(table->family());
     456             : }
     457             : 
     458       80811 : bool BgpPeer::MembershipPathCallback(DBTablePartBase *tpart, BgpRoute *route,
     459             :                                      BgpPath *path) {
     460       80811 :     return close_manager_->MembershipPathCallback(tpart, route, path);
     461             : }
     462             : 
     463          48 : bool BgpPeer::ResumeClose() {
     464          48 :     peer_close_->Close(graceful_close_);
     465          49 :     graceful_close_ = true;
     466          49 :     return true;
     467             : }
     468             : 
     469       10358 : BgpPeer::BgpPeer(BgpServer *server, RoutingInstance *instance,
     470       10358 :                  const BgpNeighborConfig *config)
     471       10358 :         : server_(server),
     472       10358 :           rtinstance_(instance),
     473       10358 :           peer_key_(config),
     474       10358 :           peer_port_(config->source_port()),
     475       10358 :           peer_name_(config->name()),
     476       10358 :           router_type_(config->router_type()),
     477       10358 :           config_(config),
     478       10358 :           index_(server->RegisterPeer(this)),
     479       10358 :           trigger_(boost::bind(&BgpPeer::ResumeClose, this),
     480             :                    TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     481             :                    GetTaskInstance()),
     482       10358 :           prefix_limit_idle_timer_(
     483       10358 :               TimerManager::CreateTimer(*server->ioservice(),
     484             :               "BGP prefix limit idle timer",
     485             :               TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     486             :               GetTaskInstance())),
     487       10358 :           prefix_limit_trigger_(boost::bind(&BgpPeer::CheckPrefixLimits, this),
     488             :                    TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     489             :                    GetTaskInstance()),
     490       10358 :           buffer_capacity_(GetBufferCapacity()),
     491       10358 :           session_(NULL),
     492       10358 :           keepalive_timer_(TimerManager::CreateTimer(*server->ioservice(),
     493             :                      "BGP keepalive timer",
     494             :                    TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     495             :                    GetTaskInstance())),
     496       10358 :           eor_send_timer_start_time_(0),
     497       10358 :           send_ready_(true),
     498       10358 :           admin_down_(config->admin_down()),
     499       10358 :           passive_(config->passive()),
     500       10358 :           resolve_paths_(config->router_type() == "bgpaas-client"),
     501       10358 :           as_override_(config->as_override()),
     502       10358 :           cluster_id_(config->cluster_id()),
     503       10358 :           origin_override_(config->origin_override()),
     504       10358 :           defer_close_(false),
     505       10358 :           graceful_close_(true),
     506       10358 :           as4_supported_(false),
     507       10358 :           vpn_tables_registered_(false),
     508       10358 :           hold_time_(config->hold_time()),
     509       10358 :           local_as_(config->local_as()),
     510       10358 :           peer_as_(config->peer_as()),
     511       10358 :           local_bgp_id_(config->local_identifier()),
     512       10358 :           peer_bgp_id_(0),
     513       10358 :           peer_type_((config->peer_as() == config->local_as()) ?
     514             :                          BgpProto::IBGP : BgpProto::EBGP),
     515       10358 :           state_machine_(BgpStaticObjectFactory::Create<StateMachine>(this)),
     516       10358 :           peer_close_(BgpStaticObjectFactory::Create<BgpPeerClose>(this)),
     517       10358 :           peer_stats_(new PeerStats(this)),
     518       10358 :           deleter_(new DeleteActor(this)),
     519       10358 :           instance_delete_ref_(this, instance ? instance->deleter() : NULL),
     520       10358 :           flap_count_(0),
     521       10358 :           total_flap_count_(0),
     522       10358 :           last_flap_(0),
     523       10358 :           dscp_listener_id_(-1),
     524       10358 :           inuse_authkey_type_(AuthenticationData::NIL),
     525       10358 :           asn_listener_id_(-1),
     526      207160 :           instance_op_(-1) {
     527       10358 :     buffer_.reserve(buffer_capacity_);
     528       10358 :     close_manager_.reset(
     529       10358 :         BgpStaticObjectFactory::Create<PeerCloseManager>(static_cast<IPeerClose*>(peer_close_.get())));
     530       10358 :     ostringstream oss1;
     531       10358 :     oss1 << peer_key_.endpoint.address();
     532       10358 :     if (peer_key_.endpoint.port() != BgpConfigManager::kDefaultPort)
     533        4005 :         oss1 << ":" << dec << peer_key_.endpoint.port();
     534       10358 :     to_str_ = oss1.str();
     535             : 
     536       10358 :     ostringstream oss2;
     537       10358 :     if (rtinstance_)
     538        9567 :         oss2 << rtinstance_->name() << ":";
     539       10358 :     oss2 << server_->localname() << ":";
     540       10358 :     oss2 << peer_name();
     541       10358 :     uve_key_str_ = oss2.str();
     542             : 
     543       20714 :     if (router_type_ == "control-node" ||
     544       10356 :         router_type_ == "external-control-node") {
     545          26 :         peer_is_control_node_ = true;
     546             :     } else {
     547       10332 :         peer_is_control_node_ = false;
     548             :     }
     549             : 
     550       10358 :     dscp_listener_id_ = server_->RegisterDSCPUpdateCallback(boost::bind(
     551             :         &BgpPeer::DSCPUpdateCallback, this, _1));
     552       10358 :     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       10358 :     membership_req_pending_ = 0;
     560       10358 :     BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
     561             :         BGP_PEER_DIR_NA, "Created");
     562             : 
     563       10358 :     if (rtinstance_ && peer_name_.find(rtinstance_->name()) == 0) {
     564        9408 :         peer_basename_ = peer_name_.substr(rtinstance_->name().size() + 1);
     565             :     } else {
     566         950 :         peer_basename_ = peer_name_;
     567             :     }
     568             : 
     569       10358 :     for (Address::Family family = Address::UNSPEC;
     570      113938 :             family < Address::NUM_FAMILIES;
     571      103580 :             family = static_cast<Address::Family>(family + 1)) {
     572      103580 :         family_primary_path_count_[family] = 0;
     573      207160 :         eor_send_timer_[family] =
     574      310740 :             TimerManager::CreateTimer(*server->ioservice(),
     575      207160 :                 "BGP EoR Send timer for " + Address::FamilyToString(family),
     576             :                 TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     577             :                 GetTaskInstance());
     578      207160 :         eor_receive_timer_[family] =
     579      310740 :             TimerManager::CreateTimer(*server->ioservice(),
     580      207160 :                 "BGP EoR Receive timer for " + Address::FamilyToString(family),
     581             :                 TaskScheduler::GetInstance()->GetTaskId("bgp::StateMachine"),
     582             :                 GetTaskInstance());
     583             :     }
     584             : 
     585       10358 :     total_path_count_ = 0;
     586       10358 :     primary_path_count_ = 0;
     587             : 
     588             :     // Check rtinstance_ to accommodate unit tests.
     589       10358 :     if (resolve_paths_ && rtinstance_) {
     590         112 :         rtinstance_->GetTable(Address::INET)->LocatePathResolver();
     591         112 :         rtinstance_->GetTable(Address::INET6)->LocatePathResolver();
     592             :     }
     593             : 
     594       10358 :     ProcessEndpointConfig(config);
     595       10358 :     ProcessAuthKeyChainConfig(config);
     596       10358 :     ProcessFamilyAttributesConfig(config);
     597             : 
     598       20716 :     BgpPeerInfoData peer_info;
     599       10358 :     peer_info.set_name(ToUVEKey());
     600       10358 :     peer_info.set_admin_down(admin_down_);
     601       10358 :     peer_info.set_passive(passive_);
     602       10358 :     peer_info.set_as_override(as_override_);
     603       10358 :     peer_info.set_origin_override(origin_override_.origin_override);
     604       10358 :     if (origin_override_.origin_override) {
     605           3 :         peer_info.set_route_origin(
     606           6 :             BgpAttr::OriginToString(origin_override_.origin));
     607             :     } else {
     608       10355 :         peer_info.set_route_origin("-");
     609             :     }
     610       10358 :     peer_info.set_router_type(router_type_);
     611       10358 :     peer_info.set_cluster_id(Ip4Address(cluster_id_).to_string());
     612       20716 :     peer_info.set_peer_type(
     613       10358 :         PeerType() == BgpProto::IBGP ? "internal" : "external");
     614       10358 :     peer_info.set_local_asn(local_as_);
     615       10358 :     peer_info.set_peer_asn(peer_as_);
     616       10358 :     peer_info.set_peer_port(peer_port_);
     617       10358 :     peer_info.set_hold_time(hold_time_);
     618       10358 :     peer_info.set_local_id(local_bgp_id_);
     619       10358 :     peer_info.set_configured_families(configured_families_);
     620       10358 :     peer_info.set_peer_address(peer_key_.endpoint.address().to_string());
     621       10358 :     BGPPeerInfoSend(peer_info);
     622       10358 : }
     623             : 
     624       15738 : BgpPeer::~BgpPeer() {
     625       10358 :     assert(!close_manager()->IsCloseInProgress());
     626       10358 :     assert(!IsCloseInProgress());
     627       10358 :     assert(GetTotalPathCount() == 0);
     628       10358 :     STLDeleteValues(&family_attributes_list_);
     629       10358 :     ClearListenSocketAuthKey();
     630       20716 :     BgpPeerInfoData peer_info;
     631       10358 :     peer_info.set_name(ToUVEKey());
     632       10358 :     peer_info.set_deleted(true);
     633       10358 :     BGPPeerInfoSend(peer_info);
     634             : 
     635       20716 :     PeerStatsData peer_stats_data;
     636       10358 :     peer_stats_data.set_name(ToUVEKey());
     637       10358 :     peer_stats_data.set_deleted(true);
     638       10358 :     assert(!peer_stats_data.get_name().empty());
     639       10358 :     BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectBgpPeer");
     640             : 
     641       20716 :     PeerFlapData peer_flap_data;
     642       10358 :     peer_flap_data.set_name(ToUVEKey());
     643       10358 :     peer_flap_data.set_deleted(true);
     644       10358 :     assert(!peer_flap_data.get_name().empty());
     645       10358 :     BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
     646             : 
     647       10358 :     BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
     648             :         BGP_PEER_DIR_NA, "Deleted");
     649       15738 : }
     650             : 
     651        9567 : void BgpPeer::Initialize() {
     652        9567 :     if (!admin_down_)
     653        9537 :         state_machine_->Initialize();
     654        9567 : }
     655             : 
     656       10358 : size_t BgpPeer::GetBufferCapacity() const {
     657             :     // For testing only - configure through environment variable.
     658       10358 :     char *buffer_capacity_str = getenv("BGP_PEER_BUFFER_SIZE");
     659       10358 :     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       10353 :     if (IsRouterTypeBGPaaS()) {
     670         113 :         return kMinBufferCapacity;
     671             :     } else {
     672       10240 :         return kMaxBufferCapacity;
     673             :     }
     674             : }
     675             : 
     676       36991 : bool BgpPeer::CheckSplitHorizon(uint32_t server_cluster_id,
     677             :         uint32_t ribout_cid) const {
     678       36991 :     if (PeerType() == BgpProto::IBGP) {
     679             :         // check if router is a route reflector
     680       36826 :         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         167 :     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       12399 : void BgpPeer::DeleteRTargets(as_t as) {
     755       12399 :     if (!IsRouterTypeBGPaaS())
     756       12161 :         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       10498 : void BgpPeer::NotifyEstablished(bool established) {
     798       10498 :     if (established) {
     799        5248 :         if (IsRouterTypeBGPaaS()) {
     800         196 :             server_->IncrementUpBgpaasPeerCount();
     801         196 :             AddRTargets(server_->local_autonomous_system());
     802             :         } else {
     803        5052 :             server_->IncrementUpPeerCount();
     804             :         }
     805             :     } else {
     806        5250 :         if (IsRouterTypeBGPaaS()) {
     807         196 :             server_->DecrementUpBgpaasPeerCount();
     808             :         } else {
     809        5053 :             server_->DecrementUpPeerCount();
     810             :         }
     811             :     }
     812       10500 : }
     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       20423 : bool BgpPeer::ProcessAuthKeyChainConfig(const BgpNeighborConfig *config) {
     831       20423 :     const AuthenticationData &input_auth_data = config->auth_data();
     832             : 
     833       20423 :     if (auth_data_ == input_auth_data) {
     834       20215 :         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       10375 : void BgpPeer::ClearListenSocketAuthKey() {
     888       10375 :     if (inuse_authkey_type_ == AuthenticationData::MD5) {
     889         162 :         server_->session_manager()->SetListenSocketMd5Option(PeerAddress(), "");
     890             :     }
     891       10375 : }
     892             : 
     893       10876 : void BgpPeer::SetSessionSocketAuthKey(TcpSession *session) {
     894       10876 :     if ((inuse_authkey_type_ == AuthenticationData::MD5) && PeerAddress()) {
     895        1248 :         assert(!inuse_auth_key_.value.empty());
     896        1248 :         LogInstallAuthKeys("Session", "add", inuse_auth_key_,
     897             :                            inuse_authkey_type_);
     898        1248 :         session->SetMd5SocketOption(PeerAddress(), inuse_auth_key_.value);
     899             :     }
     900       10876 : }
     901             : 
     902        4169 : void BgpPeer::SetSessionSocketOptionDscp(TcpSession *session) {
     903        4169 :     uint8_t dscp_value = server_->global_qos()->control_dscp();
     904             : 
     905        4169 :     if (!session->socket()) {
     906         139 :         return;
     907             :     }
     908        4030 :    if (dscp_value != 0xFF) {
     909        4030 :         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        1456 : void BgpPeer::LogInstallAuthKeys(const string &socket_name,
     918             :         const string &oper, const AuthenticationKey &auth_key,
     919             :         KeyType key_type) {
     920        2912 :     string logstr = socket_name + " socket kernel " + oper + " of key id "
     921        5824 :                           + integerToString(auth_key.id) + ", type "
     922        2912 :                           + AuthenticationData::KeyTypeToString(key_type)
     923        4368 :                           + ", peer " + peer_name_;
     924        1456 :     BGP_LOG_PEER(Config, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
     925             :                  BGP_PEER_DIR_NA, logstr);
     926        1456 : }
     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       10016 : bool BgpPeer::CheckPrefixLimits() {
     934       10016 :     RetryDelete();
     935       10017 :     if (!IsReady())
     936        9606 :         return true;
     937        4134 :     for (size_t idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
     938             :         BgpPeerFamilyAttributes *family_attributes =
     939        3769 :             family_attributes_list_[idx];
     940        3769 :         if (!family_attributes || family_attributes->prefix_limit == 0)
     941        3721 :             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          48 :         break;
     947             :     }
     948         413 :     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       20423 : bool BgpPeer::ProcessFamilyAttributesConfig(const BgpNeighborConfig *config) {
     958       20423 :     FamilyAttributesList family_attributes_list(Address::NUM_FAMILIES);
     959       85655 :     BOOST_FOREACH(const BgpFamilyAttributesConfig family_config,
     960             :         config->family_attributes_list()) {
     961             :         Address::Family family =
     962       32616 :             Address::FamilyFromString(family_config.family);
     963       32616 :         assert(family != Address::UNSPEC);
     964             :         BgpPeerFamilyAttributes *family_attributes =
     965       32616 :             new BgpPeerFamilyAttributes(config, family_config);
     966       32616 :         family_attributes_list[family] = family_attributes;
     967       32616 :     }
     968             : 
     969       20423 :     int ret = STLSortedCompare(
     970             :         family_attributes_list.begin(), family_attributes_list.end(),
     971             :         family_attributes_list_.begin(), family_attributes_list_.end(),
     972             :         BgpPeerFamilyAttributesCompare());
     973       20423 :     STLDeleteValues(&family_attributes_list_);
     974       20423 :     family_attributes_list_ = family_attributes_list;
     975       20423 :     configured_families_ = config->GetAddressFamilies();
     976       20423 :     return (ret != 0);
     977       20423 : }
     978             : 
     979       20423 : void BgpPeer::ProcessEndpointConfig(const BgpNeighborConfig *config) {
     980       20423 :     if (config->router_type() == "bgpaas-client") {
     981         204 :         endpoint_ = TcpSession::Endpoint(Ip4Address(), config->source_port());
     982             :     } else {
     983       20219 :         endpoint_ = TcpSession::Endpoint();
     984             :     }
     985       20423 : }
     986             : 
     987       10020 : void BgpPeer::TriggerPrefixLimitCheck() const {
     988       10020 :     prefix_limit_trigger_.Set();
     989       10020 : }
     990             : 
     991       10065 : void BgpPeer::ConfigUpdate(const BgpNeighborConfig *config) {
     992       10065 :     if (IsDeleted())
     993           0 :         return;
     994             : 
     995       10065 :     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       10065 :     if (!config_)
    1000           0 :         return;
    1001             : 
    1002       10065 :     bool clear_session = false;
    1003       10065 :     bool admin_down_changed = false;
    1004       20130 :     BgpPeerInfoData peer_info;
    1005       10065 :     peer_info.set_name(ToUVEKey());
    1006             : 
    1007       10065 :     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       10065 :     if (passive_ != config->passive()) {
    1014          24 :         passive_ = config->passive();
    1015          24 :         peer_info.set_passive(passive_);
    1016          24 :         clear_session = true;
    1017             :     }
    1018             : 
    1019       10065 :     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       10065 :     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       10065 :     OriginOverride origin_override(config->origin_override());
    1032       10065 :     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       10065 :     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       20130 :     if (router_type_ == "control-node" ||
    1050       10065 :         router_type_ == "external-control-node") {
    1051          26 :         peer_is_control_node_ = true;
    1052             :     } else {
    1053       10039 :         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       10065 :     BgpPeerKey key(config);
    1061       10065 :     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       10065 :     if (ProcessAuthKeyChainConfig(config)) {
    1068          61 :         clear_session = true;
    1069             :     }
    1070             : 
    1071       10065 :     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       10065 :     ProcessEndpointConfig(config);
    1077             : 
    1078       10065 :     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       10065 :     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       10065 :     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       10065 :     boost::system::error_code ec;
    1115       10065 :     uint32_t local_bgp_id = config->local_identifier();
    1116       10065 :     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       10065 :     BgpProto::BgpPeerType old_type = PeerType();
    1123       10065 :     peer_type_ = (peer_as_ == local_as_) ? BgpProto::IBGP : BgpProto::EBGP;
    1124       10065 :     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       10065 :     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       10065 :     if (ProcessFamilyAttributesConfig(config)) {
    1138          87 :         peer_info.set_configured_families(configured_families_);
    1139          87 :         clear_session = true;
    1140             :     } else {
    1141        9978 :         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       10065 :     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       10065 :     if (admin_down_changed || clear_session) {
    1156         764 :         StopPrefixLimitIdleTimer();
    1157         764 :         BGPPeerInfoSend(peer_info);
    1158             :     }
    1159       10065 : }
    1160             : 
    1161        6711 : void BgpPeer::ClearConfig() {
    1162        6711 :     CHECK_CONCURRENCY("bgp::Config");
    1163        6711 :     config_ = NULL;
    1164        6711 : }
    1165             : 
    1166        6269 : LifetimeActor *BgpPeer::deleter() {
    1167        6269 :     return deleter_.get();
    1168             : }
    1169             : 
    1170             : //
    1171             : // Check if the given address family has been negotiated with the peer.
    1172             : //
    1173      539275 : bool BgpPeer::IsFamilyNegotiated(Address::Family family) {
    1174             :     // Bail if the family is not configured locally.
    1175      539275 :     if (!LookupFamily(family))
    1176       48530 :         return false;
    1177             : 
    1178             :     // Check if the peer advertised it in his Open message.
    1179             :     uint16_t afi;
    1180             :     uint8_t safi;
    1181      490792 :     tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
    1182      490798 :     return MpNlriAllowed(afi, safi);
    1183             : }
    1184             : 
    1185             : // Release resources for a peer that is going to be deleted.
    1186        9574 : void BgpPeer::PostCloseRelease() {
    1187        9574 :     if (index_ != -1) {
    1188        9574 :         server_->UnregisterPeer(this);
    1189        9574 :         index_ = -1;
    1190             :     }
    1191        9574 :     TimerManager::DeleteTimer(keepalive_timer_);
    1192        9574 :     TimerManager::DeleteTimer(prefix_limit_idle_timer_);
    1193             : 
    1194        9574 :     for (Address::Family family = Address::UNSPEC;
    1195      105314 :             family < Address::NUM_FAMILIES;
    1196       95740 :             family = static_cast<Address::Family>(family + 1)) {
    1197       95740 :         TimerManager::DeleteTimer(eor_send_timer_[family]);
    1198       95740 :         TimerManager::DeleteTimer(eor_receive_timer_[family]);
    1199             :     }
    1200        9574 : }
    1201             : 
    1202             : // IsReady
    1203             : //
    1204             : // Check whether this peer is up and ready
    1205             : //
    1206      716169 : bool BgpPeer::IsReady() const {
    1207      716169 :     return state_machine_->get_state() == StateMachine::ESTABLISHED;
    1208             : }
    1209             : 
    1210      733266 : bool BgpPeer::IsXmppPeer() const {
    1211      733266 :     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       12520 : uint32_t BgpPeer::bgp_identifier() const {
    1223       12520 :     return ntohl(peer_bgp_id_);
    1224             : }
    1225             : 
    1226        5298 : string BgpPeer::bgp_identifier_string() const {
    1227       10599 :     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       14780 : void BgpPeer::CustomClose() {
    1251       14780 :     ResetCapabilities();
    1252       14779 :     keepalive_timer_->Cancel();
    1253             : 
    1254       14779 :     for (Address::Family family = Address::UNSPEC;
    1255      162576 :             family < Address::NUM_FAMILIES;
    1256      147797 :             family = static_cast<Address::Family>(family + 1)) {
    1257      147796 :         eor_send_timer_[family]->Cancel();
    1258      147796 :         eor_receive_timer_[family]->Cancel();
    1259             :     }
    1260             : 
    1261       14780 :     if (close_manager_->IsInDeleteState())
    1262       12361 :         DeleteRTargets(server_->local_autonomous_system());
    1263       14780 : }
    1264             : 
    1265             : //
    1266             : // Close this peer by closing all of it's RIBs.
    1267             : //
    1268       15608 : void BgpPeer::Close(bool graceful) {
    1269       15608 :     send_ready_ = true;
    1270       15608 :     if (membership_req_pending_ && !close_manager_->IsMembershipInUse()) {
    1271          49 :         BGP_LOG_PEER(Event, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    1272             :             BGP_PEER_DIR_NA, "Close procedure deferred");
    1273          49 :         defer_close_ = true;
    1274             : 
    1275             :         // Note down non-graceful closures. Once a close is non-graceful,
    1276             :         // it shall remain as non-graceful.
    1277          49 :         graceful_close_ &= graceful;
    1278          49 :         return;
    1279             :     }
    1280             : 
    1281       15556 :     peer_close_->Close(graceful);
    1282             : }
    1283             : 
    1284         192 : IPeerClose *BgpPeer::peer_close() {
    1285         192 :     return peer_close_.get();
    1286             : }
    1287             : 
    1288      150600 : IPeerClose *BgpPeer::peer_close() const {
    1289      150600 :     return peer_close_.get();
    1290             : }
    1291             : 
    1292      150599 : void BgpPeer::UpdateCloseRouteStats(Address::Family family,
    1293             :         const BgpPath *old_path, uint32_t path_flags) const {
    1294      150599 :     peer_close()->UpdateRouteStats(family, old_path, path_flags);
    1295      150600 : }
    1296             : 
    1297      164216 : IPeerDebugStats *BgpPeer::peer_stats() {
    1298      164216 :     return peer_stats_.get();
    1299             : }
    1300             : 
    1301         300 : const IPeerDebugStats *BgpPeer::peer_stats() const {
    1302         300 :     return peer_stats_.get();
    1303             : }
    1304             : 
    1305       10519 : void BgpPeer::Clear(int subcode) {
    1306       10519 :     CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine");
    1307       10519 :     state_machine_->Shutdown(subcode);
    1308       10519 : }
    1309             : 
    1310             : //
    1311             : // Check whether this peer has been marked for deletion from configuration
    1312             : //
    1313       56916 : bool BgpPeer::IsDeleted() const {
    1314       56916 :     return deleter_->IsDeleted();
    1315             : }
    1316             : 
    1317        1859 : bool BgpPeer::IsInGRTimerWaitState() const {
    1318        1859 :     return close_manager_->IsInGRTimerWaitState();
    1319             : }
    1320             : 
    1321       38041 : bool BgpPeer::IsCloseInProgress() const {
    1322       38041 :     CHECK_CONCURRENCY("bgp::Config", "bgp::StateMachine");
    1323             : 
    1324             :     // trigger is set only after defer_close is reset
    1325       38041 :     assert(!(defer_close_ && trigger_.IsSet()));
    1326       77472 :     return defer_close_ || trigger_.IsSet() ||
    1327       38020 :             (close_manager_->IsCloseInProgress() &&
    1328       39452 :              !IsInGRTimerWaitState());
    1329             : }
    1330             : 
    1331       19020 : StateMachine::State BgpPeer::GetState() const {
    1332       19020 :     return state_machine_->get_state();
    1333             : }
    1334             : 
    1335           0 : const string BgpPeer::GetStateName() const {
    1336           0 :     return state_machine_->StateName();
    1337             : }
    1338             : 
    1339        6902 : BgpSession *BgpPeer::CreateSession() {
    1340        6902 :     if (PrefixLimitIdleTimerRunning())
    1341         116 :         return NULL;
    1342             : 
    1343        6785 :     TcpSession *session = server_->session_manager()->CreateSession();
    1344        6777 :     if (session == NULL)
    1345          76 :         return NULL;
    1346             : 
    1347             :     // Set valid keys, if any, in the socket.
    1348        6701 :     SetSessionSocketAuthKey(session);
    1349             : 
    1350        6707 :     BgpSession *bgp_session = static_cast<BgpSession *>(session);
    1351        6707 :     BindLocalEndpoint(bgp_session);
    1352        6710 :     bgp_session->set_peer(this);
    1353        6710 :     return bgp_session;
    1354             : }
    1355             : 
    1356         889 : void BgpPeer::SetAdminState(bool down, int subcode) {
    1357         889 :     CHECK_CONCURRENCY("bgp::Config");
    1358         889 :     if (admin_down_ == down)
    1359           8 :         return;
    1360         881 :     admin_down_ = down;
    1361         881 :     state_machine_->SetAdminState(down, subcode);
    1362         881 :     if (admin_down_) {
    1363         476 :         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        4169 : bool BgpPeer::AcceptSession(BgpSession *session) {
    1369        4169 :     session->set_peer(this);
    1370             : 
    1371             :     // Set valid keys, if any, in the socket.
    1372        4169 :     SetSessionSocketAuthKey(session);
    1373             : 
    1374             :     // Set control dscp, if any
    1375        4169 :     SetSessionSocketOptionDscp(session);
    1376             : 
    1377        4169 :     return state_machine_->PassiveOpen(session);
    1378             : }
    1379             : 
    1380       12862 : 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       12862 :     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       12862 :     if (close_manager_->IsMembershipInWait())
    1393           0 :         assert(membership_req_pending_ > 0);
    1394       12862 :     BgpMembershipManager *membership_mgr = server_->membership_mgr();
    1395       12862 :     membership_req_pending_++;
    1396       12879 :     membership_mgr->Register(this, table, policy);
    1397             : 
    1398             :     // Start EndOfRib receive timer.
    1399       12880 :     StartEndOfRibReceiveTimer(table->family());
    1400       12880 : }
    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        6916 :     BgpMembershipManager *membership_mgr = server_->membership_mgr();
    1412        6916 :     membership_mgr->RegisterRibIn(this, table);
    1413             : 
    1414             :     // Start EndOfRib receive timer.
    1415        6917 :     StartEndOfRibReceiveTimer(table->family());
    1416        6917 : }
    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        5250 : void BgpPeer::RegisterAllTables() {
    1432        5250 :     RoutingInstance *instance = GetRoutingInstance();
    1433             : 
    1434        5250 :     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        5250 :         (Address::INET)(Address::INETMPLS)(Address::INET6);
    1439       36714 :     BOOST_FOREACH(Address::Family family, family_list) {
    1440       15732 :         if (!IsFamilyNegotiated(family))
    1441       13650 :             continue;
    1442        2086 :         BgpTable *table = instance->GetTable(family);
    1443        3182 :         BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
    1444             :                            table, "Register peer with the table");
    1445        2084 :         Register(table, BuildRibExportPolicy(family));
    1446             :     }
    1447             : 
    1448             : 
    1449       10296 :     if (((router_type_ == "bgpaas-client") ||
    1450       10493 :         (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        5247 :     vpn_tables_registered_ = false;
    1466        5247 :     if (!IsFamilyNegotiated(Address::RTARGET)) {
    1467        2622 :         RegisterToVpnTables();
    1468        2622 :         return;
    1469             :     }
    1470             : 
    1471        2627 :     Address::Family family = Address::RTARGET;
    1472        2627 :     BgpTable *table = instance->GetTable(family);
    1473        3247 :     BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
    1474             :         table, "Register peer with the table");
    1475        2621 :     Register(table, BuildRibExportPolicy(family));
    1476             : 
    1477             :     vector<Address::Family> vpn_family_list = list_of
    1478        2628 :         (Address::INETVPN)(Address::INET6VPN)(Address::ERMVPN)(Address::EVPN)
    1479        2628 :         (Address::MVPN);
    1480       28906 :     BOOST_FOREACH(Address::Family vpn_family, vpn_family_list) {
    1481       13138 :         if (!IsFamilyNegotiated(vpn_family))
    1482        6320 :             continue;
    1483        6819 :         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        5250 : }
    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        9124 : void BgpPeer::SendOpen(TcpSession *session) {
    1502        9124 :     BgpProto::OpenMessage openmsg;
    1503        9126 :     openmsg.as_num = local_as_ > 0xffff ? AS_TRANS : local_as_;
    1504        9126 :     openmsg.holdtime = state_machine_->GetConfiguredHoldTime();
    1505        9125 :     openmsg.identifier = ntohl(local_bgp_id_);
    1506             :     BgpProto::OpenMessage::OptParam *opt_param =
    1507        9125 :         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       10116 :     };
    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        9181 :         (supported_families_[8], cap_mp[8]);
    1540             : 
    1541             :     // Add capabilities for configured address families.
    1542      173290 :     BOOST_FOREACH(const FamilyToCapabilityMap::value_type &val,
    1543             :         family_to_cap_map) {
    1544       82073 :         if (!LookupFamily(val.first))
    1545       55880 :             continue;
    1546             :         BgpProto::OpenMessage::Capability *cap =
    1547             :             new BgpProto::OpenMessage::Capability(
    1548       26195 :                 BgpProto::OpenMessage::Capability::MpExtension, val.second, 4);
    1549       26211 :         opt_param->capabilities.push_back(cap);
    1550             :     }
    1551             : 
    1552        9123 :     if (server_->enable_4byte_as()) {
    1553          74 :         uint32_t asn = ntohl(local_as_);
    1554             :         BgpProto::OpenMessage::Capability *cap =
    1555             :                 new BgpProto::OpenMessage::Capability(
    1556             :                     BgpProto::OpenMessage::Capability::AS4Support,
    1557          74 :                     (const uint8_t *)(&asn), 4);
    1558          74 :         opt_param->capabilities.push_back(cap);
    1559             :     }
    1560        9124 :     peer_close_->AddGRCapabilities(opt_param);
    1561        9118 :     peer_close_->AddLLGRCapabilities(opt_param);
    1562             : 
    1563        9119 :     if (opt_param->capabilities.size()) {
    1564        9119 :         openmsg.opt_params.push_back(opt_param);
    1565             :     } else {
    1566           0 :         delete opt_param;
    1567             :     }
    1568             :     uint8_t data[256];
    1569        9118 :     int result = BgpProto::Encode(&openmsg, data, sizeof(data));
    1570        9125 :     assert(result > BgpProto::kMinMessageSize);
    1571        9125 :     BGP_LOG_PEER(Message, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    1572             :                  BGP_PEER_DIR_OUT, "Open "  << openmsg.ToString());
    1573        9125 :     session->Send(data, result, NULL);
    1574        9127 :     inc_tx_open();
    1575        9128 : }
    1576             : 
    1577        6809 : void BgpPeer::SendKeepalive(bool from_timer) {
    1578        6809 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    1579             : 
    1580             :     // Bail if there's no session for the peer anymore.
    1581        6810 :     if (!session_)
    1582           0 :         return;
    1583             : 
    1584        6810 :     BgpProto::Keepalive msg;
    1585             :     uint8_t data[BgpProto::kMinMessageSize];
    1586        6810 :     int result = BgpProto::Encode(&msg, data, sizeof(data));
    1587        6806 :     assert(result == BgpProto::kMinMessageSize);
    1588        6806 :     SandeshLevel::type log_level = from_timer ? Sandesh::LoggingUtLevel() :
    1589        6806 :                                                 SandeshLevel::SYS_INFO;
    1590        6806 :     BGP_LOG_PEER(Message, this, log_level, BGP_LOG_FLAG_SYSLOG,
    1591             :                  BGP_PEER_DIR_OUT, "Keepalive");
    1592        6806 :     send_ready_ = session_->Send(data, result, NULL);
    1593        6807 :     inc_tx_keepalive();
    1594        6806 : }
    1595             : 
    1596      128825 : static bool SkipUpdateSend() {
    1597             :     static bool init_;
    1598             :     static bool skip_;
    1599             : 
    1600      128825 :     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       20423 : BgpPeer::OriginOverride::OriginOverride(
    1609       20423 :                 const BgpNeighborConfig::OriginOverrideConfig &config)
    1610       20423 :         : origin_override(config.origin_override),
    1611       20423 :         origin(BgpAttr::OriginFromString(config.origin)) {
    1612       20423 : }
    1613             : 
    1614       10065 : bool BgpPeer::OriginOverride::operator!=(const OriginOverride &rhs) const {
    1615       10065 :     if (origin_override != rhs.origin_override) {
    1616           2 :         return true;
    1617             :     }
    1618             : 
    1619             :     // compare origin only if override is set
    1620       10063 :     if (origin_override && origin != rhs.origin) {
    1621           0 :         return true;
    1622             :     }
    1623       10063 :     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      158977 : bool BgpPeer::SendUpdate(const uint8_t *msg, size_t msgsize,
    1632             :     const string *msg_str) {
    1633      158977 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    1634      158990 :     bool send_ready = true;
    1635      158990 :     if (buffer_.size() + msgsize > buffer_capacity_) {
    1636           5 :         send_ready = FlushUpdateUnlocked();
    1637           5 :         assert(buffer_.empty());
    1638             :     }
    1639      158990 :     buffer_.insert(buffer_.end(), msg, msg + msgsize);
    1640      158987 :     inc_tx_update();
    1641      158987 :     return send_ready;
    1642      158986 : }
    1643             : 
    1644      146495 : bool BgpPeer::FlushUpdateUnlocked() {
    1645             :     // Bail if the update buffer is empty.
    1646      146495 :     if (buffer_.empty())
    1647        4611 :         return true;
    1648             : 
    1649             :     // Bail if there's no session for the peer anymore.
    1650      141884 :     if (!session_) {
    1651       13058 :         buffer_.clear();
    1652       13057 :         return true;
    1653             :     }
    1654             : 
    1655      128826 :     if (!SkipUpdateSend()) {
    1656      128825 :         send_ready_ = session_->Send(buffer_.data(), buffer_.size(), NULL);
    1657      128826 :         buffer_.clear();
    1658      128825 :         if (send_ready_) {
    1659      128808 :             StartKeepaliveTimerUnlocked();
    1660             :         } else {
    1661          17 :             StopKeepaliveTimerUnlocked();
    1662             :         }
    1663             :     } else {
    1664           0 :         send_ready_ = true;
    1665             :     }
    1666             : 
    1667      128823 :     if (!send_ready_) {
    1668          17 :         BGP_LOG_PEER(Event, this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
    1669             :                      BGP_PEER_DIR_NA, "Send blocked");
    1670             :     }
    1671      128823 :     return send_ready_;
    1672             : }
    1673             : 
    1674      146449 : bool BgpPeer::FlushUpdate() {
    1675      146449 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    1676      292976 :     return FlushUpdateUnlocked();
    1677      146487 : }
    1678             : 
    1679        2366 : bool BgpPeer::notification() const {
    1680        2366 :     return peer_close_->gr_params().notification();
    1681             : }
    1682             : 
    1683             : // Check if GR Helper mode sould be attempted.
    1684       15765 : bool BgpPeer::AttemptGRHelperMode(int code, int subcode) const {
    1685       15765 :     if (!code)
    1686        2387 :         return true;
    1687             : 
    1688       13378 :     if (code == BgpProto::Notification::Cease &&
    1689       12991 :             (subcode == BgpProto::Notification::HardReset ||
    1690             :              subcode == BgpProto::Notification::PeerDeconfigured)) {
    1691       10860 :         return false;
    1692             :     }
    1693             : 
    1694             :     // If Peer supports Notification (N) bit, then attempt GR-Helper for all
    1695             :     // other notifications, not otherwise.
    1696        2518 :     return notification();
    1697             : }
    1698             : 
    1699        4943 : void BgpPeer::SendNotification(BgpSession *session,
    1700             :         int code, int subcode, const string &data) {
    1701        4943 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    1702        4943 :     session->SendNotification(code, subcode, data);
    1703        4942 :     state_machine_->set_last_notification_out(code, subcode, data);
    1704        4942 :     inc_tx_notification();
    1705        4943 : }
    1706             : 
    1707        5331 : bool BgpPeer::SetCapabilities(const BgpProto::OpenMessage *msg) {
    1708        5331 :     peer_bgp_id_ = htonl(msg->identifier);
    1709        5331 :     capabilities_.clear();
    1710        5331 :     vector<BgpProto::OpenMessage::OptParam *>::const_iterator it;
    1711       10659 :     for (it = msg->opt_params.begin(); it < msg->opt_params.end(); ++it) {
    1712        5330 :         capabilities_.insert(capabilities_.end(), (*it)->capabilities.begin(),
    1713        5330 :                              (*it)->capabilities.end());
    1714        5328 :         (*it)->capabilities.clear();
    1715             :     }
    1716             : 
    1717        5328 :     as4_supported_ = false;
    1718        5328 :     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       10659 :     BgpPeerInfoData peer_info;
    1728        5331 :     peer_info.set_name(ToUVEKey());
    1729        5331 :     peer_info.set_peer_id(peer_bgp_id_);
    1730             : 
    1731        5331 :     vector<string> families;
    1732        5331 :     vector<BgpProto::OpenMessage::Capability *>::iterator cap_it;
    1733       25187 :     for (cap_it = capabilities_.begin(); cap_it < capabilities_.end();
    1734       19857 :          ++cap_it) {
    1735       19862 :         if ((*cap_it)->code != BgpProto::OpenMessage::Capability::MpExtension)
    1736        6816 :             continue;
    1737       13046 :         uint8_t *data = (*cap_it)->capability.data();
    1738       13047 :         uint16_t afi = get_value(data, 2);
    1739       13048 :         uint8_t safi = get_value(data + 3, 1);
    1740       13048 :         Address::Family family = BgpAf::AfiSafiToFamily(afi, safi);
    1741       13048 :         if (family == Address::UNSPEC) {
    1742           0 :             families.push_back(BgpAf::ToString(afi, safi));
    1743             :         } else {
    1744       13048 :             families.push_back(Address::FamilyToString(family));
    1745             :         }
    1746             :     }
    1747        5326 :     peer_info.set_families(families);
    1748             : 
    1749        5327 :     negotiated_families_.clear();
    1750       58593 :     for (int idx = Address::UNSPEC; idx < Address::NUM_FAMILIES; ++idx) {
    1751       53262 :         if (!family_attributes_list_[idx])
    1752       40250 :             continue;
    1753       13152 :         Address::Family family = static_cast<Address::Family>(idx);
    1754             :         uint16_t afi;
    1755             :         uint8_t safi;
    1756       13152 :         tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
    1757       13153 :         if (!MpNlriAllowed(afi, safi))
    1758         142 :             continue;
    1759       13017 :         negotiated_families_.push_back(Address::FamilyToString(family));
    1760             :     }
    1761        5331 :     sort(negotiated_families_.begin(), negotiated_families_.end());
    1762        5324 :     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        5324 :     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        5325 :     return true;
    1773        5325 : }
    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       14917 : void BgpPeer::ResetCapabilities() {
    1781       14917 :     STLDeleteValues(&capabilities_);
    1782       29834 :     BgpPeerInfoData peer_info;
    1783       14917 :     peer_info.set_name(ToUVEKey());
    1784       14917 :     vector<string> families = vector<string>();
    1785       14917 :     peer_info.set_families(families);
    1786       14917 :     vector<string> negotiated_families = vector<string>();
    1787       14917 :     peer_info.set_negotiated_families(negotiated_families);
    1788       14915 :     peer_info.set_graceful_restart_families(vector<string>());
    1789       14915 :     BGPPeerInfoSend(peer_info);
    1790       14916 : }
    1791             : 
    1792      503938 : bool BgpPeer::MpNlriAllowed(uint16_t afi, uint8_t safi) {
    1793      503938 :     vector<BgpProto::OpenMessage::Capability *>::iterator it;
    1794     1322878 :     for (it = capabilities_.begin(); it < capabilities_.end(); ++it) {
    1795     1322567 :         if ((*it)->code != BgpProto::OpenMessage::Capability::MpExtension)
    1796         479 :             continue;
    1797     1322103 :         uint8_t *data = (*it)->capability.data();
    1798     1322077 :         uint16_t af_value = get_value(data, 2);
    1799     1322076 :         uint8_t safi_value = get_value(data + 3, 1);
    1800     1322063 :         if (afi == af_value && safi == safi_value) {
    1801      503602 :             return true;
    1802             :         }
    1803             :     }
    1804         289 :     return false;
    1805             : }
    1806             : 
    1807      188156 : bool BgpPeer::Is4ByteAsSupported() const {
    1808      188156 :     return as4_supported_;
    1809             : }
    1810             : 
    1811             : template <typename TableT, typename PrefixT>
    1812      145097 : void BgpPeer::ProcessNlri(Address::Family family, DBRequest::DBOperation oper,
    1813             :     const BgpMpNlri *nlri, BgpAttrPtr attr, uint32_t flags) {
    1814      145097 :     TableT *table = static_cast<TableT *>(rtinstance_->GetTable(family));
    1815      145087 :     assert(table);
    1816             : 
    1817      343900 :     for (vector<BgpProtoPrefix *>::const_iterator it = nlri->nlri.begin();
    1818      343899 :          it != nlri->nlri.end(); ++it) {
    1819      198797 :         PrefixT prefix;
    1820      198798 :         BgpAttrPtr new_attr(attr);
    1821      198812 :         uint32_t label = 0;
    1822      198812 :         uint32_t l3_label = 0;
    1823      338849 :         int result = PrefixT::FromProtoPrefix(server_, **it,
    1824      140039 :             (oper == DBRequest::DB_ENTRY_ADD_CHANGE ? attr.get() : NULL),
    1825             :             family, &prefix, &new_attr, &label, &l3_label);
    1826      198793 :         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      198793 :         DBRequest req;
    1835      198792 :         req.oper = oper;
    1836      198792 :         if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
    1837      140018 :             req.data.reset(new typename TableT::RequestData(
    1838             :                 new_attr, flags, label, l3_label, 0));
    1839             :         }
    1840      198797 :         req.key.reset(new typename TableT::RequestKey(prefix, this));
    1841      198791 :         table->Enqueue(&req);
    1842             :     }
    1843      145098 : }
    1844             : 
    1845             : template <typename PrefixT>
    1846        1342 : void BgpPeer::ProcessNlriBgpaas(Address::Family family, DBRequest::DBOperation oper,
    1847             :     const BgpMpNlri *nlri, BgpAttrPtr attr, uint32_t flags) {
    1848             : 
    1849        2684 :     for (vector<BgpProtoPrefix *>::const_iterator it = nlri->nlri.begin();
    1850        2684 :          it != nlri->nlri.end(); ++it) {
    1851        1342 :         PrefixT prefix;
    1852        1342 :         BgpAttrPtr new_attr(attr);
    1853        1342 :         uint32_t label = 0;
    1854        1342 :         uint32_t l3_label = 0;
    1855        2174 :         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        1342 :         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        1342 :         ProcessBgpaas(oper, prefix.addr(), prefix.prefixlen(), new_attr, flags);
    1867             :     }
    1868        1342 : }
    1869             : 
    1870        1342 : void BgpPeer::ProcessBgpaas(DBRequest::DBOperation oper,
    1871             :     IpAddress addr, uint8_t addr_len, BgpAttrPtr attr, uint32_t flags) {
    1872             : 
    1873        1342 :     if (rtinstance_->routing_instance_vxlan() == "") {
    1874         668 :         return;
    1875             :     }
    1876         674 :     RoutingInstanceMgr *mgr = server()->routing_instance_mgr();
    1877         674 :     if (mgr == nullptr) {
    1878           0 :         return;
    1879             :     }
    1880             :     RoutingInstance *vxlan_ri =
    1881         674 :         mgr->GetRoutingInstance(rtinstance_->routing_instance_vxlan());
    1882         674 :     if (vxlan_ri == nullptr) {
    1883           0 :         return;
    1884             :     }
    1885         674 :     EvpnTable *table = static_cast<EvpnTable *>(vxlan_ri->GetTable(Address::EVPN));
    1886         674 :     EvpnPrefix prefix_evpn(RouteDistinguisher::kZeroRd, addr, addr_len);
    1887             : 
    1888         674 :     DBRequest req;
    1889         674 :     req.oper = oper;
    1890         674 :     if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
    1891         416 :         req.data.reset(new EvpnTable::RequestData(attr, flags, 0, 0, 0));
    1892             :     }
    1893             :     else {
    1894         258 :         req.data.reset(NULL);
    1895             :     }
    1896         674 :     req.key.reset(new EvpnTable::RequestKey(prefix_evpn, this));
    1897         674 :     table->Enqueue(&req);
    1898         674 : }
    1899             : 
    1900      111091 : uint32_t BgpPeer::GetPathFlags(Address::Family family,
    1901             :     const BgpAttr *attr) const {
    1902      111091 :     uint32_t flags = resolve_paths_ ? BgpPath::ResolveNexthop : 0;
    1903             : 
    1904             :     // Check for OriginatorId loop in case we are an RR client.
    1905      134766 :     if (peer_type_ == BgpProto::IBGP &&
    1906       23677 :         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      111091 :     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      111088 :     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      285910 :     if ((PeerType() == BgpProto::EBGP) &&
    1922      262180 :           ((attr->as_path() && !attr->as_path()->path().AsLeftMostMatch(
    1923      174793 :           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      111081 :     uint8_t max_loop_count = family_attributes_list_[family]->loop_count;
    1930      111081 :     if (attr->IsAsPathLoop(local_as_, max_loop_count))
    1931           6 :         flags |= BgpPath::AsPathLooped;
    1932             : 
    1933      111077 :     return flags;
    1934             : }
    1935             : 
    1936      157804 : uint32_t BgpPeer::GetLocalPrefFromMed(uint32_t med) const {
    1937      157804 :     if (peer_type_ != BgpProto::EBGP)
    1938       39831 :         return 0;
    1939      117973 :     if (!peer_is_control_node_)
    1940      117823 :         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      157803 : void BgpPeer::ProcessUpdate(const BgpProto::Update *msg, size_t msgsize) {
    1951      157803 :     BgpAttrPtr attr = server_->attr_db()->Locate(msg->path_attributes);
    1952             : 
    1953      157804 :     uint32_t local_pref = GetLocalPrefFromMed(attr->med());
    1954      157804 :     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      157804 :     if (origin_override_.origin_override) {
    1961           8 :         attr = server_->attr_db()->ReplaceOriginAndLocate(attr.get(),
    1962           4 :                                                        origin_override_.origin);
    1963             :     }
    1964             : 
    1965      313871 :     if ((router_type_ == "bgpaas-client") ||
    1966      156066 :         (router_type_ == "bgpaas-server")) {
    1967        5202 :         attr = server_->attr_db()->ReplaceSubProtocolAndLocate(attr.get(),
    1968        5202 :                              MatchProtocolToString(MatchProtocol::BGPaaS));
    1969             :     }
    1970             : 
    1971      157801 :     uint32_t reach_count = 0, unreach_count = 0;
    1972      157801 :     RoutingInstance *instance = GetRoutingInstance();
    1973      157799 :     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      157797 :     for (vector<BgpAttribute *>::const_iterator ait =
    2036      157798 :             msg->path_attributes.begin();
    2037      701602 :             ait != msg->path_attributes.end(); ++ait) {
    2038             :         DBRequest::DBOperation oper;
    2039      556492 :         if ((*ait)->code == BgpAttribute::MPReachNlri) {
    2040      111076 :             oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    2041      445416 :         } else if ((*ait)->code == BgpAttribute::MPUnreachNlri) {
    2042       46715 :             oper = DBRequest::DB_ENTRY_DELETE;
    2043             :         } else {
    2044      398704 :             continue;
    2045             :         }
    2046             : 
    2047      157791 :         BgpMpNlri *nlri = static_cast<BgpMpNlri *>(*ait);
    2048      157790 :         assert(nlri);
    2049      157790 :         if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
    2050      111075 :             reach_count += nlri->nlri.size();
    2051             :         } else {
    2052       46715 :             unreach_count += nlri->nlri.size();
    2053             :         }
    2054             : 
    2055      157790 :         Address::Family family = BgpAf::AfiSafiToFamily(nlri->afi, nlri->safi);
    2056      157791 :         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      157803 :         if (oper == DBRequest::DB_ENTRY_DELETE && nlri->nlri.empty()) {
    2066       12704 :             inc_rx_end_of_rib();
    2067       12703 :             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       12703 :             ReceiveEndOfRIB(family, msgsize);
    2073       12703 :             return;
    2074             :         }
    2075             : 
    2076      145098 :         uint32_t flags = 0;
    2077      145098 :         if ((*ait)->code == BgpAttribute::MPReachNlri) {
    2078      111085 :             flags = GetPathFlags(family, attr.get());
    2079      111076 :             attr = GetMpNlriNexthop(nlri, attr);
    2080             :         }
    2081             : 
    2082      145089 :         switch (family) {
    2083        4721 :         case Address::INET:
    2084             :         case Address::INETMPLS:
    2085        4721 :             ProcessNlri<InetTable, Ip4Prefix>(
    2086             :                 family, oper, nlri, attr, flags);
    2087        8824 :             if ((router_type_ == "bgpaas-client") ||
    2088        4103 :                 (router_type_ == "bgpaas-server")) {
    2089         618 :                 ProcessNlriBgpaas<Ip4Prefix>(
    2090             :                     family, oper, nlri, attr, flags);
    2091             :             }
    2092        4721 :             break;
    2093       55890 :         case Address::INETVPN:
    2094       55890 :             ProcessNlri<InetVpnTable, InetVpnPrefix>(
    2095             :                 family, oper, nlri, attr, flags);
    2096       55890 :             break;
    2097        3603 :         case Address::INET6:
    2098        3603 :             ProcessNlri<Inet6Table, Inet6Prefix>(
    2099             :                 family, oper, nlri, attr, flags);
    2100        6482 :             if ((router_type_ == "bgpaas-client") ||
    2101        2879 :                 (router_type_ == "bgpaas-server")) {
    2102         724 :                 ProcessNlriBgpaas<Inet6Prefix>(
    2103             :                     family, oper, nlri, attr, flags);
    2104             :             }
    2105        3603 :             break;
    2106       40165 :         case Address::INET6VPN:
    2107       40165 :             ProcessNlri<Inet6VpnTable, Inet6VpnPrefix>(
    2108             :                 family, oper, nlri, attr, flags);
    2109       40165 :             break;
    2110       16863 :         case Address::EVPN:
    2111       16863 :             ProcessNlri<EvpnTable, EvpnPrefix>(
    2112             :                 family, oper, nlri, attr, flags);
    2113       16863 :             break;
    2114        4238 :         case Address::ERMVPN:
    2115        4238 :             ProcessNlri<ErmVpnTable, ErmVpnPrefix>(
    2116             :                 family, oper, nlri, attr, flags);
    2117        4238 :             break;
    2118        1124 :         case Address::MVPN:
    2119        1124 :             ProcessNlri<MvpnTable, MvpnPrefix>(
    2120             :                 family, oper, nlri, attr, flags);
    2121        1124 :             break;
    2122       18485 :         case Address::RTARGET:
    2123       18485 :             ProcessNlri<RTargetTable, RTargetPrefix>(
    2124             :                 family, oper, nlri, attr, flags);
    2125       18496 :             break;
    2126           0 :         default:
    2127           0 :             break;
    2128             :         }
    2129             :     }
    2130             : 
    2131      145100 :     inc_rx_route_reach(reach_count);
    2132      145100 :     inc_rx_route_unreach(unreach_count);
    2133      145098 :     if (Sandesh::LoggingLevel() >= Sandesh::LoggingUtLevel()) {
    2134      145099 :         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      157803 : }
    2140      463349 : const std::vector<std::string> BgpPeer::GetDefaultTunnelEncap(
    2141             :     const Address::Family family) const {
    2142      463349 :     if (family_attributes_list_[family] == NULL)
    2143      299138 :         return std::vector<std::string>();
    2144      164222 :     return family_attributes_list_[family]->default_tunnel_encap_list;
    2145             : }
    2146             : 
    2147      463349 : void BgpPeer::ProcessPathTunnelEncapsulation(const BgpPath *path, BgpAttr *attr,
    2148             :                                              ExtCommunityDB *extcomm_db,
    2149             :                                              const BgpTable *table) const {
    2150      463349 :     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      463278 : }
    2179             : 
    2180             : 
    2181      300344 : void BgpPeer::UpdatePrimaryPathCount(int count, Address::Family family) const {
    2182      300344 :     primary_path_count_ += count;
    2183      300363 :     if (family == Address::UNSPEC)
    2184           8 :         return;
    2185      300355 :     family_primary_path_count_[family] += count;
    2186      300353 :     uint32_t limit = 0;
    2187      300353 :     if (family_attributes_list_[family])
    2188      298259 :         limit = family_attributes_list_[family]->prefix_limit;
    2189      300343 :     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       11284 : bool BgpPeer::PrefixLimitIdleTimerRunning() const {
    2204       11284 :     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        5245 : void BgpPeer::RegisterToVpnTables() {
    2224        5245 :     CHECK_CONCURRENCY("bgp::StateMachine", "bgp::RTFilter", "bgp::Config");
    2225             : 
    2226        5246 :     if (vpn_tables_registered_)
    2227          24 :         return;
    2228        5222 :     vpn_tables_registered_ = true;
    2229             : 
    2230        5222 :     RoutingInstance *instance = GetRoutingInstance();
    2231             :     vector<Address::Family> vpn_family_list = list_of
    2232        5222 :         (Address::INETVPN)(Address::INET6VPN)(Address::ERMVPN)(Address::EVPN)
    2233        5221 :         (Address::MVPN);
    2234       57424 :     BOOST_FOREACH(Address::Family vpn_family, vpn_family_list) {
    2235       26100 :         if (!IsFamilyNegotiated(vpn_family))
    2236       17995 :             continue;
    2237        8106 :         BgpTable *table = instance->GetTable(vpn_family);
    2238       10133 :         BGP_LOG_PEER_TABLE(this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_TRACE,
    2239             :             table, "Register peer with the table");
    2240        8107 :         Register(table, BuildRibExportPolicy(vpn_family));
    2241             :     }
    2242        5220 : }
    2243             : 
    2244       19796 : void BgpPeer::StartEndOfRibReceiveTimer(Address::Family family) {
    2245       19796 :     uint32_t timeout = GetEndOfRibReceiveTime(family);
    2246             : 
    2247       19795 :     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       19797 :     eor_receive_timer_[family]->Start(timeout * 1000,
    2253             :         boost::bind(&BgpPeer::EndOfRibReceiveTimerExpired, this, family),
    2254             :         boost::bind(&BgpPeer::EndOfRibTimerErrorHandler, this, _1, _2));
    2255       19797 : }
    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        1490 : bool BgpPeer::KeepaliveTimerExpired() {
    2273        1490 :     if (!IsReady())
    2274           0 :         return false;
    2275             : 
    2276        1490 :     SendKeepalive(true);
    2277             : 
    2278             :     //
    2279             :     // Start the timer again, by returning true
    2280             :     //
    2281        1490 :     return true;
    2282             : }
    2283             : 
    2284      134118 : void BgpPeer::StartKeepaliveTimerUnlocked() {
    2285      134118 :     int keepalive_time_msecs = state_machine_->keepalive_time_msecs();
    2286      134117 :     if (keepalive_time_msecs <= 0)
    2287           0 :         return;
    2288             : 
    2289      134117 :     keepalive_timer_->Start(keepalive_time_msecs,
    2290             :         boost::bind(&BgpPeer::KeepaliveTimerExpired, this),
    2291             :         boost::bind(&BgpPeer::KeepaliveTimerErrorHandler, this, _1, _2));
    2292             : }
    2293             : 
    2294        5316 : void BgpPeer::StartKeepaliveTimer() {
    2295        5316 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    2296        5320 :     if (session_ && send_ready_)
    2297        5319 :         StartKeepaliveTimerUnlocked();
    2298        5320 : }
    2299             : 
    2300          17 : void BgpPeer::StopKeepaliveTimerUnlocked() {
    2301          17 :     keepalive_timer_->Cancel();
    2302          17 : }
    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        6111 : void BgpPeer::set_session(BgpSession *session) {
    2319        6111 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    2320        6111 :     assert(session_ == NULL);
    2321        6111 :     session_ = session;
    2322        6111 : }
    2323             : 
    2324       26766 : void BgpPeer::clear_session() {
    2325       26766 :     tbb::spin_mutex::scoped_lock lock(spin_mutex_);
    2326       26766 :     if (session_) {
    2327        6111 :         session_->clear_peer();
    2328        6111 :         session_->set_observer(NULL);
    2329        6111 :         session_->Close();
    2330             :     }
    2331       26765 :     session_ = NULL;
    2332       26765 : }
    2333             : 
    2334       57911 : BgpSession *BgpPeer::session() {
    2335       57911 :     return session_;
    2336             : }
    2337             : 
    2338       31437 : string BgpPeer::BytesToHexString(const u_int8_t *msg, size_t size) {
    2339       31437 :     ostringstream out;
    2340             :     char buf[4];
    2341             : 
    2342     2399620 :     for (size_t i = 0; i < size; i ++) {
    2343     2368183 :         if (!(i % 32)) out << "\n";
    2344     2368184 :         if (!(i %  4)) out << " 0x";
    2345     2368181 :         snprintf(buf, sizeof(buf), "%02X", msg[i]);
    2346     2368181 :         out << buf;
    2347             :     }
    2348             : 
    2349       31437 :     out << "\n";
    2350             : 
    2351       62874 :     return out.str();
    2352       31437 : }
    2353             : 
    2354      175217 : bool BgpPeer::ReceiveMsg(BgpSession *session, const u_int8_t *msg,
    2355             :                          size_t size) {
    2356      175217 :     ParseErrorContext ec;
    2357      350418 :     BgpProto::BgpMessage *minfo = BgpProto::Decode(msg, size, &ec,
    2358      175218 :                                                    Is4ByteAsSupported());
    2359             : 
    2360      175201 :     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      175201 :     if (minfo->type != BgpProto::KEEPALIVE)
    2371      168493 :         BGP_TRACE_PEER_PACKET(this, msg, size, SandeshLevel::SYS_WARN); //Sandesh::LoggingUtLevel()
    2372             : 
    2373      175205 :     state_machine_->OnMessage(session, minfo, size);
    2374      175223 :     return true;
    2375      175223 : }
    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      111086 : BgpAttrPtr BgpPeer::GetMpNlriNexthop(BgpMpNlri *nlri, BgpAttrPtr attr) {
    2383      111086 :     bool update_nh = false;
    2384      111086 :     IpAddress addr;
    2385             : 
    2386      111085 :     if (nlri->afi == BgpAf::IPv4) {
    2387       66021 :         if (nlri->safi == BgpAf::Mpls || nlri->safi == BgpAf::Unicast ||
    2388       62853 :             nlri->safi == BgpAf::RTarget || nlri->safi == BgpAf::MVpn) {
    2389       19731 :             Ip4Address::bytes_type bt = { { 0 } };
    2390       39460 :             copy(nlri->nexthop.begin(),
    2391       19731 :                 nlri->nexthop.begin() + sizeof(bt), bt.begin());
    2392       19723 :             addr = Ip4Address(bt);
    2393       19723 :             update_nh = true;
    2394       66013 :         } else if (nlri->safi == BgpAf::Vpn) {
    2395       42966 :             Ip4Address::bytes_type bt = { { 0 } };
    2396       42966 :             size_t rdsize = RouteDistinguisher::kSize;
    2397       85932 :             copy(nlri->nexthop.begin() + rdsize,
    2398       42966 :                 nlri->nexthop.begin() + rdsize + sizeof(bt), bt.begin());
    2399       42966 :             addr = Ip4Address(bt);
    2400       42966 :             update_nh = true;
    2401             :         }
    2402       45064 :     } else if (nlri->afi == BgpAf::L2Vpn) {
    2403       12504 :         if (nlri->safi == BgpAf::EVpn) {
    2404       12504 :             Ip4Address::bytes_type bt = { { 0 } };
    2405       25008 :             copy(nlri->nexthop.begin(),
    2406       12504 :                 nlri->nexthop.begin() + sizeof(bt), bt.begin());
    2407       12504 :             addr = Ip4Address(bt);
    2408       12504 :             update_nh = true;
    2409             :         }
    2410       32560 :     } else if (nlri->afi == BgpAf::IPv6) {
    2411       32560 :         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        2518 :             for (int idx = 0; idx < 2; ++idx) {
    2419        2518 :                 Ip6Address::bytes_type bt = { { 0 } };
    2420        2518 :                 if ((idx + 1) * sizeof(bt) > nlri->nexthop.size())
    2421        2518 :                     break;
    2422        5036 :                 copy(nlri->nexthop.begin() + idx * sizeof(bt),
    2423        2518 :                     nlri->nexthop.begin() + (idx + 1) * sizeof(bt), bt.begin());
    2424        2518 :                 Ip6Address v6_addr(bt);
    2425        2518 :                 if (v6_addr.is_v4_mapped()) {
    2426        1315 :                     addr = Address::V4FromV4MappedV6(v6_addr);
    2427        1315 :                     update_nh = true;
    2428        1315 :                     break;
    2429             :                 }
    2430        1203 :                 if (!v6_addr.is_link_local()) {
    2431        1203 :                     addr = v6_addr;
    2432        1203 :                     update_nh = true;
    2433        1203 :                     break;
    2434             :                 }
    2435             :             }
    2436       30042 :         } else if (nlri->safi == BgpAf::Vpn) {
    2437       30042 :             Ip6Address::bytes_type bt = { { 0 } };
    2438       30042 :             size_t rdsize = RouteDistinguisher::kSize;
    2439       60084 :             copy(nlri->nexthop.begin() + rdsize,
    2440       30042 :                 nlri->nexthop.begin() + rdsize + sizeof(bt), bt.begin());
    2441       30042 :             Ip6Address v6_addr(bt);
    2442       30042 :             if (v6_addr.is_v4_mapped()) {
    2443       30042 :                 addr = Address::V4FromV4MappedV6(v6_addr);
    2444       30042 :                 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      111077 :     if (update_nh) {
    2452      107753 :         attr = server_->attr_db()->ReplaceNexthopAndLocate(attr.get(), addr);
    2453             :     }
    2454      222170 :     return attr;
    2455             : }
    2456             : 
    2457        9605 : void BgpPeer::ManagedDelete() {
    2458        9605 :     if (deleter_->IsDeleted())
    2459          38 :         return;
    2460        9567 :     BGP_LOG_PEER(Config, this, SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    2461             :                  BGP_PEER_DIR_NA, "Received request for deletion");
    2462        9567 :     if (IsRouterTypeBGPaaS()) {
    2463         112 :         server()->increment_deleting_bgpaas_count();
    2464             :     } else {
    2465        9455 :         server()->increment_deleting_count();
    2466             :     }
    2467        9567 :     deleter_->Delete();
    2468             : }
    2469             : 
    2470       29148 : void BgpPeer::RetryDelete() {
    2471       29148 :     if (!deleter_->IsDeleted())
    2472       10017 :         return;
    2473       19133 :     deleter_->RetryDelete();
    2474             : }
    2475             : 
    2476      311375 : int BgpPeer::GetTaskInstance() const {
    2477      311375 :     return index_ % TaskScheduler::GetInstance()->HardwareThreadCount();
    2478             : }
    2479             : 
    2480       31437 : void BgpPeer::SetDataCollectionKey(BgpPeerInfo *peer_info) const {
    2481       31437 :     if (rtinstance_) {
    2482       31437 :         peer_info->set_domain(rtinstance_->name());
    2483             :     } else {
    2484           0 :         peer_info->set_domain(BgpConfigManager::kMasterInstance);
    2485             :     }
    2486             : 
    2487       31437 :     peer_info->set_ip_address(peer_key_.endpoint.address().to_string());
    2488       31437 : }
    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        6147 : void BgpPeer::inc_rx_open() {
    2657        6147 :     peer_stats_->proto_stats_[0].open++;
    2658        6147 : }
    2659             : 
    2660        9125 : void BgpPeer::inc_tx_open() {
    2661        9125 :     peer_stats_->proto_stats_[1].open++;
    2662        9128 : }
    2663             : 
    2664        6750 : void BgpPeer::inc_rx_keepalive() {
    2665        6750 :     peer_stats_->proto_stats_[0].keepalive++;
    2666        6749 : }
    2667             : 
    2668        4144 : uint64_t BgpPeer::get_rx_keepalive() const {
    2669        4144 :     return peer_stats_->proto_stats_[0].keepalive;
    2670             : }
    2671             : 
    2672        6805 : void BgpPeer::inc_tx_keepalive() {
    2673        6805 :     peer_stats_->proto_stats_[1].keepalive++;
    2674        6806 : }
    2675             : 
    2676         171 : uint64_t BgpPeer::get_tx_keepalive() const {
    2677         171 :     return peer_stats_->proto_stats_[1].keepalive;
    2678             : }
    2679             : 
    2680      157872 : void BgpPeer::inc_rx_update() {
    2681      157872 :     peer_stats_->proto_stats_[0].update++;
    2682      157871 : }
    2683             : 
    2684           8 : uint64_t BgpPeer::get_rx_update() const {
    2685           8 :     return peer_stats_->proto_stats_[0].update;
    2686             : }
    2687             : 
    2688      171814 : void BgpPeer::inc_tx_update() {
    2689      171814 :     peer_stats_->proto_stats_[1].update++;
    2690      171814 : }
    2691             : 
    2692          37 : uint64_t BgpPeer::get_tx_update() const {
    2693          37 :     return peer_stats_->proto_stats_[1].update;
    2694             : }
    2695             : 
    2696        4632 : void BgpPeer::inc_rx_notification() {
    2697        4632 :     peer_stats_->proto_stats_[0].notification++;
    2698        4632 : }
    2699             : 
    2700         443 : uint64_t BgpPeer::get_rx_notification() const {
    2701         443 :     return peer_stats_->proto_stats_[0].notification;
    2702             : }
    2703             : 
    2704        4942 : void BgpPeer::inc_tx_notification() {
    2705        4942 :     peer_stats_->proto_stats_[1].notification++;
    2706        4942 : }
    2707             : 
    2708       12703 : void BgpPeer::inc_rx_end_of_rib() {
    2709       12703 :     peer_stats_->update_stats_[0].end_of_rib++;
    2710       12703 : }
    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       12827 : void BgpPeer::inc_tx_end_of_rib() {
    2717       12827 :     peer_stats_->update_stats_[1].end_of_rib++;
    2718       12827 : }
    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      145100 : void BgpPeer::inc_rx_route_reach(uint64_t count) {
    2725      145100 :     peer_stats_->update_stats_[0].reach += count;
    2726      145100 : }
    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      145100 : void BgpPeer::inc_rx_route_unreach(uint64_t count) {
    2737      145100 :     peer_stats_->update_stats_[0].unreach += count;
    2738      145098 : }
    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         122 : void BgpPeer::inc_connect_error() {
    2761         122 :     peer_stats_->error_stats_.connect_error++;
    2762         122 : }
    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          78 : void BgpPeer::inc_open_error() {
    2773          78 :     peer_stats_->error_stats_.open_error++;
    2774          78 : }
    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         169 : uint64_t BgpPeer::get_open_error() const {
    2793         169 :     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        5249 : void BgpPeer::increment_flap_count() {
    2821        5249 :     flap_count_++;
    2822        5249 :     total_flap_count_++;
    2823        5249 :     last_flap_ = UTCTimestampUsec();
    2824             : 
    2825       10498 :     BgpPeerInfoData peer_info;
    2826        5249 :     peer_info.set_name(ToUVEKey());
    2827        5250 :     PeerFlapInfo flap_info;
    2828        5250 :     flap_info.set_flap_count(flap_count_);
    2829        5248 :     flap_info.set_flap_time(last_flap_);
    2830        5249 :     peer_info.set_flap_info(flap_info);
    2831        5248 :     BGPPeerInfoSend(peer_info);
    2832             : 
    2833       10494 :     PeerFlapData peer_flap_data;
    2834        5246 :     peer_flap_data.set_name(ToUVEKey());
    2835        5246 :     peer_flap_data.set_flap_info(flap_info);
    2836        5246 :     assert(!peer_flap_data.get_name().empty());
    2837        5246 :     BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
    2838        5247 : }
    2839             : 
    2840         405 : void BgpPeer::reset_flap_count() {
    2841         405 :     flap_count_ = 0;
    2842         405 :     last_flap_ = 0;
    2843             : 
    2844         810 :     BgpPeerInfoData peer_info;
    2845         405 :     peer_info.set_name(ToUVEKey());
    2846         405 :     PeerFlapInfo flap_info;
    2847         405 :     peer_info.set_flap_info(flap_info);
    2848         405 :     BGPPeerInfoSend(peer_info);
    2849             : 
    2850         810 :     PeerFlapData peer_flap_data;
    2851         405 :     peer_flap_data.set_name(ToUVEKey());
    2852         405 :     peer_flap_data.set_flap_info(flap_info);
    2853         405 :     assert(!peer_flap_data.get_name().empty());
    2854         405 :     BGP_UVE_SEND2(PeerFlap, peer_flap_data, "ObjectBgpPeer");
    2855         405 : }
    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        3436 : bool BgpPeer::ProcessSession() const {
    2860        3436 :     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           3 :         session_->SetDscpSocketOption(dscp_value);
    2867             :     }
    2868           6 : }

Generated by: LCOV version 1.14