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

Generated by: LCOV version 1.14