LCOV - code coverage report
Current view: top level - bgp - bgp_xmpp_channel.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 1732 1918 90.3 %
Date: 2026-06-18 01:51:13 Functions: 155 164 94.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/bgp_xmpp_channel.h"
       6             : 
       7             : #include <boost/assign/list_of.hpp>
       8             : #include <boost/foreach.hpp>
       9             : 
      10             : #include <limits>
      11             : #include <sstream>
      12             : #include <vector>
      13             : #include <atomic>
      14             : 
      15             : #include "base/regex.h"
      16             : #include "base/task_annotations.h"
      17             : #include "bgp/bgp_config.h"
      18             : #include "bgp/bgp_factory.h"
      19             : #include "bgp/bgp_log.h"
      20             : #include "bgp/bgp_membership.h"
      21             : #include "bgp/bgp_server.h"
      22             : #include "bgp/bgp_update_sender.h"
      23             : #include "bgp/bgp_xmpp_peer_close.h"
      24             : #include "bgp/inet/inet_table.h"
      25             : #include "bgp/inet6/inet6_table.h"
      26             : #include "bgp/extended-community/etree.h"
      27             : #include "bgp/extended-community/load_balance.h"
      28             : #include "bgp/extended-community/mac_mobility.h"
      29             : #include "bgp/extended-community/local_sequence_number.h"
      30             : #include "bgp/extended-community/router_mac.h"
      31             : #include "bgp/extended-community/tag.h"
      32             : #include "bgp/large-community/tag.h"
      33             : #include "bgp/ermvpn/ermvpn_table.h"
      34             : #include "bgp/evpn/evpn_route.h"
      35             : #include "bgp/evpn/evpn_table.h"
      36             : #include "bgp/mvpn/mvpn_table.h"
      37             : #include "bgp/peer_close_manager.h"
      38             : #include "bgp/peer_stats.h"
      39             : #include "bgp/security_group/security_group.h"
      40             : #include "bgp/tunnel_encap/tunnel_encap.h"
      41             : #include "bgp/bgp_xmpp_rtarget_manager.h"
      42             : #include "control-node/sandesh/control_node_types.h"
      43             : #include "net/community_type.h"
      44             : #include "schema/xmpp_multicast_types.h"
      45             : #include "schema/xmpp_enet_types.h"
      46             : #include "schema/xmpp_mvpn_types.h"
      47             : #include "xml/xml_pugi.h"
      48             : #include "xmpp/xmpp_connection.h"
      49             : #include "xmpp/xmpp_init.h"
      50             : #include "xmpp/xmpp_server.h"
      51             : #include "xmpp/sandesh/xmpp_peer_info_types.h"
      52             : 
      53             : using autogen::EnetItemType;
      54             : using autogen::EnetNextHopListType;
      55             : using autogen::EnetSecurityGroupListType;
      56             : using autogen::EnetTunnelEncapsulationListType;
      57             : 
      58             : using autogen::McastItemType;
      59             : using autogen::McastNextHopsType;
      60             : using autogen::McastTunnelEncapsulationListType;
      61             : 
      62             : using autogen::MvpnItemType;
      63             : using autogen::MvpnNextHopType;
      64             : using autogen::MvpnTunnelEncapsulationListType;
      65             : 
      66             : using autogen::ItemType;
      67             : using autogen::NextHopListType;
      68             : using autogen::SecurityGroupListType;
      69             : using autogen::CommunityTagListType;
      70             : using autogen::TunnelEncapsulationListType;
      71             : using autogen::TagListType;
      72             : 
      73             : using boost::assign::list_of;
      74             : using boost::smatch;
      75             : using boost::system::error_code;
      76             : using contrail::regex;
      77             : using contrail::regex_match;
      78             : using contrail::regex_search;
      79             : using pugi::xml_node;
      80             : using std::unique_ptr;
      81             : using std::make_pair;
      82             : using std::numeric_limits;
      83             : using std::ostringstream;
      84             : using std::pair;
      85             : using std::set;
      86             : using std::string;
      87             : using std::vector;
      88             : 
      89             : //
      90             : // Calculate med from local preference.
      91             : // Should move agent definitions to a common location and use those here
      92             : // instead of hard coded values.
      93             : //
      94       12373 : static uint32_t GetMedFromLocalPref(uint32_t local_pref) {
      95       12373 :     if (local_pref == 0)
      96        2384 :         return 0;
      97        9989 :     if (local_pref == 100)
      98        6868 :         return 200;
      99        3121 :     if (local_pref == 200)
     100          34 :         return 100;
     101        3087 :     return numeric_limits<uint32_t>::max() - local_pref;
     102             : }
     103             : 
     104           2 : void BgpXmppChannel::ErrorStats::incr_inet6_rx_bad_xml_token_count() {
     105           2 :     ++inet6_rx_bad_xml_token_count;
     106           2 : }
     107             : 
     108           2 : void BgpXmppChannel::ErrorStats::incr_inet6_rx_bad_prefix_count() {
     109           2 :     ++inet6_rx_bad_prefix_count;
     110           2 : }
     111             : 
     112           3 : void BgpXmppChannel::ErrorStats::incr_inet6_rx_bad_nexthop_count() {
     113           3 :     ++inet6_rx_bad_nexthop_count;
     114           3 : }
     115             : 
     116           3 : void BgpXmppChannel::ErrorStats::incr_inet6_rx_bad_afi_safi_count() {
     117           3 :     ++inet6_rx_bad_afi_safi_count;
     118           3 : }
     119             : 
     120          63 : uint64_t BgpXmppChannel::ErrorStats::get_inet6_rx_bad_xml_token_count() const {
     121          63 :     return inet6_rx_bad_xml_token_count;
     122             : }
     123             : 
     124          64 : uint64_t BgpXmppChannel::ErrorStats::get_inet6_rx_bad_prefix_count() const {
     125          64 :     return inet6_rx_bad_prefix_count;
     126             : }
     127             : 
     128          63 : uint64_t BgpXmppChannel::ErrorStats::get_inet6_rx_bad_nexthop_count() const {
     129          63 :     return inet6_rx_bad_nexthop_count;
     130             : }
     131             : 
     132          65 : uint64_t BgpXmppChannel::ErrorStats::get_inet6_rx_bad_afi_safi_count() const {
     133          65 :     return inet6_rx_bad_afi_safi_count;
     134             : }
     135             : 
     136             : class BgpXmppChannel::PeerStats : public IPeerDebugStats {
     137             : public:
     138       10044 :     explicit PeerStats(BgpXmppChannel *peer)
     139       10044 :         : parent_(peer) {
     140       10044 :     }
     141             : 
     142             :     // Used when peer flaps.
     143             :     // Don't need to do anything since the BgpXmppChannel itself gets deleted.
     144           0 :     virtual void Clear() {
     145           0 :     }
     146             : 
     147             :     // Printable name
     148           0 :     virtual string ToString() const {
     149           0 :         return parent_->ToString();
     150             :     }
     151             : 
     152             :     // Previous State of the peer
     153         487 :     virtual string last_state() const {
     154         487 :         return (parent_->channel_->LastStateName());
     155             :     }
     156             :     // Last state change occurred at
     157         487 :     virtual string last_state_change_at() const {
     158         487 :         return (parent_->channel_->LastStateChangeAt());
     159             :     }
     160             : 
     161             :     // Last error on this peer
     162         487 :     virtual string last_error() const {
     163         487 :         return "";
     164             :     }
     165             : 
     166             :     // Last Event on this peer
     167         487 :     virtual string last_event() const {
     168         487 :         return (parent_->channel_->LastEvent());
     169             :     }
     170             : 
     171             :     // When was the Last
     172        1461 :     virtual string last_flap() const {
     173        1461 :         return (parent_->channel_->LastFlap());
     174             :     }
     175             : 
     176             :     // Total number of flaps
     177        1461 :     virtual uint64_t num_flaps() const {
     178        1461 :         return (parent_->channel_->FlapCount());
     179             :     }
     180             : 
     181         547 :     virtual void GetRxProtoStats(ProtoStats *stats) const {
     182         547 :         stats->open = parent_->channel_->rx_open();
     183         547 :         stats->close = parent_->channel_->rx_close();
     184         547 :         stats->keepalive = parent_->channel_->rx_keepalive();
     185         547 :         stats->update = parent_->channel_->rx_update();
     186         547 :     }
     187             : 
     188         547 :     virtual void GetTxProtoStats(ProtoStats *stats) const {
     189         547 :         stats->open = parent_->channel_->tx_open();
     190         547 :         stats->close = parent_->channel_->tx_close();
     191         547 :         stats->keepalive = parent_->channel_->tx_keepalive();
     192         547 :         stats->update = parent_->channel_->tx_update();
     193         547 :     }
     194             : 
     195         607 :     virtual void GetRxRouteUpdateStats(UpdateStats *stats)  const {
     196         607 :         stats->reach = parent_->stats_[RX].reach.load();
     197         607 :         stats->unreach = parent_->stats_[RX].unreach.load();
     198         607 :         stats->end_of_rib = parent_->stats_[RX].end_of_rib.load();
     199         607 :         stats->total = stats->reach + stats->unreach + stats->end_of_rib;
     200         607 :     }
     201             : 
     202         607 :     virtual void GetTxRouteUpdateStats(UpdateStats *stats)  const {
     203         607 :         stats->reach = parent_->stats_[TX].reach.load();
     204         607 :         stats->unreach = parent_->stats_[TX].unreach.load();
     205         607 :         stats->end_of_rib = parent_->stats_[TX].end_of_rib.load();
     206         607 :         stats->total = stats->reach + stats->unreach + stats->end_of_rib;
     207         607 :     }
     208             : 
     209         487 :     virtual void GetRxSocketStats(IPeerDebugStats::SocketStats *stats) const {
     210         487 :         const XmppSession *session = parent_->GetSession();
     211         487 :         if (session) {
     212         475 :             const io::SocketStats &socket_stats = session->GetSocketStats();
     213         475 :             stats->calls = socket_stats.read_calls;
     214         475 :             stats->bytes = socket_stats.read_bytes;
     215             :         }
     216         487 :     }
     217             : 
     218         487 :     virtual void GetTxSocketStats(IPeerDebugStats::SocketStats *stats) const {
     219         487 :         const XmppSession *session = parent_->GetSession();
     220         487 :         if (session) {
     221         475 :             const io::SocketStats &socket_stats = session->GetSocketStats();
     222         475 :             stats->calls = socket_stats.write_calls;
     223         475 :             stats->bytes = socket_stats.write_bytes;
     224         475 :             stats->blocked_count = socket_stats.write_blocked;
     225         475 :             stats->blocked_duration_usecs =
     226         475 :                 socket_stats.write_blocked_duration_usecs;
     227             :         }
     228         487 :     }
     229             : 
     230          60 :     virtual void GetRxErrorStats(RxErrorStats *stats) const {
     231          60 :         const BgpXmppChannel::ErrorStats &err_stats = parent_->error_stats();
     232          60 :         stats->inet6_bad_xml_token_count =
     233          60 :             err_stats.get_inet6_rx_bad_xml_token_count();
     234          60 :         stats->inet6_bad_prefix_count =
     235          60 :             err_stats.get_inet6_rx_bad_prefix_count();
     236          60 :         stats->inet6_bad_nexthop_count =
     237          60 :             err_stats.get_inet6_rx_bad_nexthop_count();
     238          60 :         stats->inet6_bad_afi_safi_count =
     239          60 :             err_stats.get_inet6_rx_bad_afi_safi_count();
     240          60 :     }
     241             : 
     242          60 :     virtual void GetRxRouteStats(RxRouteStats *stats) const {
     243          60 :         stats->total_path_count = parent_->Peer()->GetTotalPathCount();
     244          60 :         stats->primary_path_count = parent_->Peer()->GetPrimaryPathCount();
     245          60 :     }
     246             : 
     247     1577766 :     virtual void UpdateTxUnreachRoute(uint64_t count) {
     248     1577766 :         parent_->stats_[TX].unreach += count;
     249     1577787 :     }
     250             : 
     251     1577538 :     virtual void UpdateTxReachRoute(uint64_t count) {
     252     1577538 :         parent_->stats_[TX].reach += count;
     253     1577782 :     }
     254             : 
     255             : private:
     256             :     BgpXmppChannel *parent_;
     257             : };
     258             : 
     259             : class BgpXmppChannel::XmppPeer : public IPeer {
     260             : public:
     261       10044 :     XmppPeer(BgpServer *server, BgpXmppChannel *channel)
     262       20088 :         : server_(server),
     263       10044 :           parent_(channel),
     264       10044 :           is_closed_(false),
     265       10044 :           send_ready_(true),
     266       10044 :           closed_at_(0) {
     267       10044 :         total_path_count_ = 0;
     268       10044 :         primary_path_count_ = 0;
     269       10044 :     }
     270             : 
     271       20088 :     virtual ~XmppPeer() {
     272       10044 :         assert(GetTotalPathCount() == 0);
     273             : 
     274       20088 :         XmppPeerInfoData peer_info;
     275       10044 :         peer_info.set_name(ToUVEKey());
     276       10044 :         peer_info.set_deleted(true);
     277       10044 :         parent_->XMPPPeerInfoSend(peer_info);
     278             : 
     279       20088 :         PeerStatsData peer_stats_data;
     280       10044 :         peer_stats_data.set_name(ToUVEKey());
     281       10044 :         peer_stats_data.set_deleted(true);
     282       10044 :         assert(!peer_stats_data.get_name().empty());
     283       10044 :         BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectXmppPeerInfo");
     284       20088 :     }
     285             : 
     286       19593 :     virtual bool MembershipPathCallback(DBTablePartBase *tpart, BgpRoute *rt,
     287             :                                         BgpPath *path) {
     288       19593 :         if (parent_->close_manager_->IsMembershipInUse())
     289       19519 :             return parent_->close_manager_->MembershipPathCallback(tpart, rt,
     290       19523 :                                                                    path);
     291             : 
     292          73 :         BgpTable *table = static_cast<BgpTable *>(tpart->parent());
     293          73 :         return table->DeletePath(tpart, rt, path);
     294             :     }
     295             : 
     296             :     virtual bool SendUpdate(const uint8_t *msg, size_t msgsize,
     297             :                             const std::string *msg_str);
     298       56935 :     virtual bool SendUpdate(const uint8_t *msg, size_t msgsize) {
     299       56935 :         return SendUpdate(msg, msgsize, NULL);
     300             :     }
     301     1670920 :     virtual const string &ToString() const {
     302     1670920 :         return parent_->ToString();
     303             :     }
     304             : 
     305        6285 :     virtual bool CanUseMembershipManager() const {
     306        6285 :         return parent_->GetMembershipRequestQueueSize() == 0;
     307             :     }
     308             : 
     309       59320 :     virtual bool IsRegistrationRequired() const { return true; }
     310             : 
     311      632647 :     virtual const string &ToUVEKey() const {
     312      632647 :         return parent_->ToUVEKey();
     313             :     }
     314             : 
     315      752974 :     virtual BgpServer *server() { return server_; }
     316     3894529 :     virtual BgpServer *server() const { return server_; }
     317           0 :     virtual IPeerClose *peer_close() {
     318           0 :         return parent_->peer_close_.get();
     319             :     }
     320       65897 :     virtual IPeerClose *peer_close() const {
     321       65897 :         return parent_->peer_close_.get();
     322             :     }
     323             : 
     324       65897 :     void UpdateCloseRouteStats(Address::Family family, const BgpPath *old_path,
     325             :                                uint32_t path_flags) const {
     326       65897 :         peer_close()->UpdateRouteStats(family, old_path, path_flags);
     327       65897 :     }
     328             : 
     329     1577707 :     virtual IPeerDebugStats *peer_stats() {
     330     1577707 :         return parent_->peer_stats_.get();
     331             :     }
     332        2555 :     virtual const IPeerDebugStats *peer_stats() const {
     333        2555 :         return parent_->peer_stats_.get();
     334             :     }
     335             : 
     336      191028 :     virtual bool IsReady() const {
     337      191028 :         return (parent_->channel_->GetPeerState() == xmps::READY);
     338             :     }
     339           0 :     virtual const string GetStateName() const {
     340           0 :         switch (parent_->channel_->GetPeerState()) {
     341           0 :             case xmps::UNKNOWN: return "UNKNOWN";
     342           0 :             case xmps::READY: return "READY";
     343           0 :             case xmps::NOT_READY: return "NOT_READY";
     344           0 :             case xmps::TIMEDOUT: return "TIMEDOUT";
     345             :         }
     346           0 :         return "UNKNOWN";
     347             :     }
     348     1759578 :     virtual bool IsXmppPeer() const {
     349     1759578 :         return true;
     350             :     }
     351             :     virtual void Close(bool graceful);
     352             : 
     353       74487 :     const bool IsDeleted() const { return is_closed_; }
     354       16613 :     void SetPeerClosed(bool closed) {
     355       16613 :         is_closed_ = closed;
     356       16613 :         if (is_closed_)
     357       16389 :             closed_at_ = UTCTimestampUsec();
     358       16614 :     }
     359         974 :     uint64_t closed_at() const { return closed_at_; }
     360             : 
     361      493282 :     virtual BgpProto::BgpPeerType PeerType() const {
     362      493282 :         return BgpProto::XMPP;
     363             :     }
     364             : 
     365      228793 :     virtual uint32_t bgp_identifier() const {
     366      228793 :         const TcpSession::Endpoint &remote = parent_->endpoint();
     367      228793 :         if (remote.address().is_v4()) {
     368      228793 :             return remote.address().to_v4().to_ulong();
     369             :         }
     370           0 :         return 0;
     371             :     }
     372             : 
     373      251624 :     virtual void UpdateTotalPathCount(int count) const {
     374      251624 :         total_path_count_ += count;
     375      251633 :     }
     376       10104 :     virtual int GetTotalPathCount() const {
     377       10104 :         return total_path_count_;
     378             :     }
     379           0 :     virtual bool IsAs4Supported() const { return true; }
     380      129222 :     virtual void UpdatePrimaryPathCount(int count,
     381             :         Address::Family family) const {
     382      129222 :         primary_path_count_ += count;
     383      129223 :     }
     384        1034 :     virtual int GetPrimaryPathCount() const {
     385        1034 :          return primary_path_count_;
     386             :     }
     387      125417 :     virtual void ProcessPathTunnelEncapsulation(const BgpPath *path,
     388             :         BgpAttr *attr, ExtCommunityDB *extcomm_db, const BgpTable *table)
     389             :         const {
     390      125417 :     }
     391           0 :     virtual const std::vector<std::string> GetDefaultTunnelEncap(
     392             :         Address::Family family) const {
     393           0 :         return std::vector<std::string>();
     394             :     }
     395           0 :     virtual bool IsInGRTimerWaitState() const {
     396           0 :         return parent_->close_manager_->IsInGRTimerWaitState();
     397             :     }
     398             : 
     399      141173 :     void MembershipRequestCallback(BgpTable *table) {
     400      141173 :         parent_->MembershipRequestCallback(table);
     401      141173 :     }
     402             : 
     403     1805815 :     virtual bool send_ready() const { return send_ready_; }
     404       26244 :     bool IsRouterTypeBGPaaS() const { return false; }
     405             : 
     406             : private:
     407           1 :     void WriteReadyCb(const boost::system::error_code &ec) {
     408           1 :         if (!server_) return;
     409           1 :         BgpUpdateSender *sender = server_->update_sender();
     410           2 :         BGP_LOG_PEER(Event, this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     411             :                      BGP_PEER_DIR_NA, "Send ready");
     412           1 :         sender->PeerSendReady(this);
     413           1 :         send_ready_ = true;
     414             : 
     415             :         // Restart EndOfRib Send timer if necessary.
     416           1 :         parent_->ResetEndOfRibSendState();
     417             :     }
     418             : 
     419             :     BgpServer *server_;
     420             :     BgpXmppChannel *parent_;
     421             :     mutable std::atomic<int> total_path_count_;
     422             :     mutable std::atomic<int> primary_path_count_;
     423             :     bool is_closed_;
     424             :     bool send_ready_;
     425             :     uint64_t closed_at_;
     426             : };
     427             : 
     428             : // Skip sending updates if the destinatin matches against the pattern.
     429             : // XXX Used in test environments only
     430     1631223 : bool BgpXmppChannel::SkipUpdateSend() {
     431     1631223 :     static char *skip_env_ = getenv("XMPP_SKIP_UPDATE_SEND");
     432     1631233 :     if (!skip_env_)
     433     1631233 :         return false;
     434             : 
     435             :     // Use XMPP_SKIP_UPDATE_SEND as a regex pattern to match against destination
     436             :     // Cache the result to avoid redundant regex evaluation
     437           0 :     if (!skip_update_send_cached_) {
     438           0 :         smatch matches;
     439           0 :         skip_update_send_ = regex_search(ToString(), matches, regex(skip_env_));
     440           0 :         skip_update_send_cached_ = true;
     441           0 :     }
     442           0 :     return skip_update_send_;
     443             : }
     444             : 
     445     1634456 : bool BgpXmppChannel::XmppPeer::SendUpdate(const uint8_t *msg, size_t msgsize,
     446             :     const string *msg_str) {
     447     1634456 :     XmppChannel *channel = parent_->channel_;
     448     1634456 :     if (channel->GetPeerState() == xmps::READY) {
     449     1630989 :         parent_->stats_[TX].rt_updates++;
     450     1631254 :         if (parent_->SkipUpdateSend())
     451           0 :             return true;
     452     1631230 :         send_ready_ = channel->Send(msg, msgsize, msg_str, xmps::BGP,
     453             :                 boost::bind(&BgpXmppChannel::XmppPeer::WriteReadyCb, this, _1));
     454     1631178 :         if (!send_ready_) {
     455         126 :             BGP_LOG_PEER(Event, this, SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL,
     456             :                          BGP_PEER_DIR_NA, "Send blocked");
     457             : 
     458             :             // If EndOfRib Send timer is running, cancel it and reschedule it
     459             :             // after socket gets unblocked.
     460          93 :             if (parent_->eor_send_timer_ && parent_->eor_send_timer_->running())
     461          62 :                 parent_->eor_send_timer_->Cancel();
     462             :         }
     463     1631128 :         return send_ready_;
     464             :     } else {
     465        3455 :         return false;
     466             :     }
     467             : }
     468             : 
     469       10170 : void BgpXmppChannel::XmppPeer::Close(bool graceful) {
     470       10170 :     send_ready_ = true;
     471       10170 :     parent_->set_peer_closed(true);
     472       10171 :     if (server_ == NULL)
     473        3815 :         return;
     474             : 
     475             :     XmppConnection *connection =
     476        6356 :         const_cast<XmppConnection *>(parent_->channel_->connection());
     477             : 
     478        6355 :     if (connection && !connection->IsActiveChannel()) {
     479             : 
     480             :         // Clear EOR state.
     481        6346 :         parent_->ClearEndOfRibState();
     482             : 
     483        6346 :         parent_->peer_close_->Close(graceful);
     484             :     }
     485             : }
     486             : 
     487       10044 : BgpXmppChannel::BgpXmppChannel(XmppChannel *channel,
     488             :                                BgpServer *bgp_server,
     489       10044 :                                BgpXmppChannelManager *manager)
     490       10044 :     : channel_(channel),
     491       10044 :       peer_id_(xmps::BGP),
     492       10044 :       rtarget_manager_(new BgpXmppRTargetManager(this)),
     493       10044 :       bgp_server_(bgp_server),
     494       10044 :       peer_(new XmppPeer(bgp_server, this)),
     495       10044 :       peer_close_(new BgpXmppPeerClose(this)),
     496       10044 :       peer_stats_(new PeerStats(this)),
     497       10044 :       bgp_policy_(BgpProto::XMPP, RibExportPolicy::XMPP, -1, 0),
     498       10044 :       manager_(manager),
     499       10044 :       delete_in_progress_(false),
     500       10044 :       deleted_(false),
     501       10044 :       defer_peer_close_(false),
     502       10044 :       skip_update_send_(false),
     503       10044 :       skip_update_send_cached_(false),
     504       10044 :       eor_sent_(false),
     505       10044 :       eor_receive_timer_(NULL),
     506       10044 :       eor_send_timer_(NULL),
     507       10044 :       eor_receive_timer_start_time_(0),
     508       10044 :       eor_send_timer_start_time_(0),
     509       20088 :       membership_response_worker_(
     510             :             TaskScheduler::GetInstance()->GetTaskId("xmpp::StateMachine"),
     511       10044 :             channel->GetTaskInstance(),
     512             :             boost::bind(&BgpXmppChannel::MembershipResponseHandler, this, _1)),
     513       60264 :       lb_mgr_(new LabelBlockManager()) {
     514       10044 :     close_manager_.reset(
     515       10044 :         BgpStaticObjectFactory::Create<PeerCloseManager>(static_cast<IPeerClose*>(peer_close_.get())));
     516       10044 :     if (bgp_server) {
     517        6229 :         eor_receive_timer_ =
     518        6229 :             TimerManager::CreateTimer(*bgp_server->ioservice(),
     519             :                 "EndOfRib receive timer",
     520             :                 TaskScheduler::GetInstance()->GetTaskId("xmpp::StateMachine"),
     521        6229 :                 channel->GetTaskInstance());
     522        6229 :         eor_send_timer_ =
     523        6229 :             TimerManager::CreateTimer(*bgp_server->ioservice(),
     524             :                 "EndOfRib send timer",
     525             :                 TaskScheduler::GetInstance()->GetTaskId("xmpp::StateMachine"),
     526        6229 :                 channel->GetTaskInstance());
     527             :     }
     528       10044 :     channel_->RegisterReferer(peer_id_);
     529       10044 :     channel_->RegisterReceive(peer_id_,
     530             :          boost::bind(&BgpXmppChannel::ReceiveUpdate, this, _1));
     531       12451 :     BGP_LOG_PEER(Event, peer_.get(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
     532             :         BGP_PEER_DIR_NA, "Created");
     533       10044 : }
     534             : 
     535       15591 : BgpXmppChannel::~BgpXmppChannel() {
     536       10044 :     if (channel_->connection() && !channel_->connection()->IsActiveChannel()) {
     537        6180 :         CHECK_CONCURRENCY("bgp::Config");
     538             :     }
     539             : 
     540       10044 :     if (manager_)
     541        6190 :         manager_->RemoveChannel(channel_);
     542       10044 :     if (manager_ && delete_in_progress_)
     543        6180 :         manager_->decrement_deleting_count();
     544       10044 :     STLDeleteElements(&defer_q_);
     545       10044 :     assert(peer_deleted());
     546       10044 :     assert(!close_manager_->IsMembershipInUse());
     547       10044 :     assert(table_membership_request_map_.empty());
     548       10044 :     TimerManager::DeleteTimer(eor_receive_timer_);
     549       10044 :     TimerManager::DeleteTimer(eor_send_timer_);
     550       12451 :     BGP_LOG_PEER(Event, peer_.get(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
     551             :         BGP_PEER_DIR_NA, "Deleted");
     552       10044 :     channel_->UnRegisterWriteReady(peer_id_);
     553       10044 :     channel_->UnRegisterReferer(peer_id_);
     554       10044 :     channel_->UnRegisterReceive(peer_id_);
     555       15591 : }
     556             : 
     557       10044 : void BgpXmppChannel::XMPPPeerInfoSend(const XmppPeerInfoData &peer_info) const {
     558       10044 :     assert(!peer_info.get_name().empty());
     559       10044 :     BGP_UVE_SEND(XMPPPeerInfo, peer_info);
     560       10044 : }
     561             : 
     562        5662 : const XmppSession *BgpXmppChannel::GetSession() const {
     563        5662 :     if (channel_ && channel_->connection()) {
     564        5662 :         return channel_->connection()->session();
     565             :     }
     566           0 :     return NULL;
     567             : }
     568             : 
     569     1673911 : const string &BgpXmppChannel::ToString() const {
     570     1673911 :     return channel_->ToString();
     571             : }
     572             : 
     573      632650 : const string &BgpXmppChannel::ToUVEKey() const {
     574      632650 :     if (channel_->connection()) {
     575      632286 :         return channel_->connection()->ToUVEKey();
     576             :     } else {
     577         368 :         return channel_->ToString();
     578             :     }
     579             : }
     580             : 
     581         974 : string BgpXmppChannel::StateName() const {
     582         974 :     return channel_->StateName();
     583             : }
     584             : 
     585             : 
     586        6285 : size_t BgpXmppChannel::GetMembershipRequestQueueSize() const {
     587        6285 :     return table_membership_request_map_.size();
     588             : }
     589             : 
     590        2793 : void BgpXmppChannel::RoutingInstanceCallback(string vrf_name, int op) {
     591        2793 :     if (delete_in_progress_)
     592          76 :         return;
     593        2717 :     if (vrf_name == BgpConfigManager::kMasterInstance)
     594         131 :         return;
     595        2586 :     if (op == RoutingInstanceMgr::INSTANCE_DELETE)
     596         424 :         return;
     597             : 
     598        2162 :     RoutingInstanceMgr *instance_mgr = bgp_server_->routing_instance_mgr();
     599        2162 :     assert(instance_mgr);
     600        2162 :     RoutingInstance *rt_instance = instance_mgr->GetRoutingInstance(vrf_name);
     601        2162 :     assert(rt_instance);
     602             : 
     603        2162 :     if (op == RoutingInstanceMgr::INSTANCE_ADD) {
     604             :         const InstanceMembershipRequestState *imr_state =
     605          63 :             GetInstanceMembershipState(vrf_name);
     606          63 :         if (!imr_state)
     607          32 :             return;
     608          31 :         ProcessDeferredSubscribeRequest(rt_instance, *imr_state);
     609          31 :         DeleteInstanceMembershipState(vrf_name);
     610             :     } else {
     611        2099 :         SubscriptionState *sub_state = GetSubscriptionState(rt_instance);
     612        2099 :         if (!sub_state)
     613         775 :             return;
     614        1324 :         rtarget_manager_->RoutingInstanceCallback(
     615             :             rt_instance, &sub_state->targets);
     616             :     }
     617             : }
     618             : 
     619     1533261 : IPeer *BgpXmppChannel::Peer() {
     620     1533261 :     return peer_.get();
     621             : }
     622             : 
     623        5111 : const IPeer *BgpXmppChannel::Peer() const {
     624        5111 :     return peer_.get();
     625             : }
     626             : 
     627      228783 : TcpSession::Endpoint BgpXmppChannel::endpoint() const {
     628      228783 :     return channel_->connection()->endpoint();
     629             : }
     630             : 
     631       30062 : bool BgpXmppChannel::XmppDecodeAddress(int af, const string &address,
     632             :                                        IpAddress *addrp, bool zero_ok) {
     633       30062 :     if (af != BgpAf::IPv4 && af != BgpAf::IPv6 && af != BgpAf::L2Vpn)
     634           0 :         return false;
     635             : 
     636       30062 :     error_code error;
     637       30062 :     *addrp = IpAddress::from_string(address, error);
     638       30062 :     if (error)
     639          17 :         return false;
     640             : 
     641       30045 :     return (zero_ok ? true : !addrp->is_unspecified());
     642             : }
     643             : 
     644             : //
     645             : // Return true if there's a pending request, false otherwise.
     646             : //
     647       40095 : bool BgpXmppChannel::GetMembershipInfo(BgpTable *table,
     648             :     int *instance_id, uint64_t *subscription_gen_id, RequestType *req_type) {
     649       40095 :     *instance_id = -1;
     650       40095 :     *subscription_gen_id = 0;
     651             :     TableMembershipRequestState *tmr_state =
     652       40095 :         GetTableMembershipState(table->name());
     653       40095 :     if (tmr_state) {
     654        1205 :         *req_type = tmr_state->pending_req;
     655        1205 :         *instance_id = tmr_state->instance_id;
     656        1205 :         return true;
     657             :     } else {
     658       38890 :         *req_type = NONE;
     659       38890 :         BgpMembershipManager *mgr = bgp_server_->membership_mgr();
     660       38890 :         mgr->GetRegistrationInfo(peer_.get(), table,
     661             :                                  instance_id, subscription_gen_id);
     662       38890 :         return false;
     663             :     }
     664             : }
     665             : 
     666             : //
     667             : // Add entry to the pending table request map.
     668             : //
     669       72822 : void BgpXmppChannel::AddTableMembershipState(const string &table_name,
     670             :     TableMembershipRequestState tmr_state) {
     671       72822 :     table_membership_request_map_.insert(make_pair(table_name, tmr_state));
     672       72823 : }
     673             : 
     674             : //
     675             : // Delete entry from the pending table request map.
     676             : // Return true if the entry was found and deleted.
     677             : //
     678       72822 : bool BgpXmppChannel::DeleteTableMembershipState(const string &table_name) {
     679       72822 :     return (table_membership_request_map_.erase(table_name) > 0);
     680             : }
     681             : 
     682             : //
     683             : // Find entry in the pending table request map.
     684             : //
     685             : BgpXmppChannel::TableMembershipRequestState *
     686      185962 : BgpXmppChannel::GetTableMembershipState(
     687             :     const string &table_name) {
     688             :     TableMembershipRequestMap::iterator loc =
     689      185962 :         table_membership_request_map_.find(table_name);
     690      185958 :     return (loc == table_membership_request_map_.end() ? NULL : &loc->second);
     691             : }
     692             : 
     693             : //
     694             : // Find entry in the pending table request map.
     695             : // Const version.
     696             : //
     697             : const BgpXmppChannel::TableMembershipRequestState *
     698        9500 : BgpXmppChannel::GetTableMembershipState(
     699             :     const string &table_name) const {
     700             :     TableMembershipRequestMap::const_iterator loc =
     701        9500 :         table_membership_request_map_.find(table_name);
     702        9500 :     return (loc == table_membership_request_map_.end() ? NULL : &loc->second);
     703             : }
     704             : 
     705             : //
     706             : // Add entry to the pending instance request map.
     707             : //
     708         142 : void BgpXmppChannel::AddInstanceMembershipState(const string &instance,
     709             :     InstanceMembershipRequestState imr_state) {
     710         142 :     instance_membership_request_map_.insert(make_pair(instance, imr_state));
     711         142 : }
     712             : 
     713             : //
     714             : // Delete entry from the pending instance request map.
     715             : // Return true if the entry was found and deleted.
     716             : //
     717         192 : bool BgpXmppChannel::DeleteInstanceMembershipState(const string &instance) {
     718         192 :     return (instance_membership_request_map_.erase(instance) > 0);
     719             : }
     720             : 
     721             : //
     722             : // Find the entry in the pending instance request map.
     723             : //
     724             : const BgpXmppChannel::InstanceMembershipRequestState *
     725        5626 : BgpXmppChannel::GetInstanceMembershipState(const string &instance) const {
     726             :     InstanceMembershipRequestMap::const_iterator loc =
     727        5626 :         instance_membership_request_map_.find(instance);
     728        5626 :     return loc != instance_membership_request_map_.end() ? &loc->second : NULL;
     729             : }
     730             : 
     731             : //
     732             : // Verify that there's a subscribe or pending subscribe for the table
     733             : // corresponding to the vrf and family.
     734             : // If there's a subscribe, populate the table and instance_id.
     735             : // If there's a pending subscribe, populate the instance_id.
     736             : // The subscribe_pending parameter is set appropriately.
     737             : //
     738             : // Return true if there's a subscribe or pending subscribe, false otherwise.
     739             : //
     740       41650 : bool BgpXmppChannel::VerifyMembership(const string &vrf_name,
     741             :     Address::Family family, BgpTable **table,
     742             :     int *instance_id, uint64_t *subscription_gen_id, bool *subscribe_pending,
     743             :     bool add_change) {
     744       41650 :     *table = NULL;
     745       41650 :     *subscribe_pending = false;
     746             : 
     747       41650 :     RoutingInstanceMgr *instance_mgr = bgp_server_->routing_instance_mgr();
     748       41650 :     RoutingInstance *rt_instance = instance_mgr->GetRoutingInstance(vrf_name);
     749       41651 :     if (rt_instance)
     750       41597 :         *table = rt_instance->GetTable(family);
     751       41651 :     if (rt_instance != NULL && !rt_instance->deleted()) {
     752             :         RequestType req_type;
     753       40095 :         if (GetMembershipInfo(*table, instance_id,
     754             :                               subscription_gen_id, &req_type)) {
     755             :             // Bail if there's a pending unsubscribe.
     756        1205 :             if (req_type != SUBSCRIBE) {
     757           8 :                 BGP_LOG_PEER_INSTANCE_CRITICAL(Peer(), vrf_name,
     758             :                     BGP_PEER_DIR_IN, BGP_LOG_FLAG_ALL,
     759             :                     "Received route after unsubscribe");
     760          23 :                 return false;
     761             :             }
     762        1201 :             *subscribe_pending = true;
     763             :         } else {
     764             :             // Bail if we are not subscribed to the table.
     765       38890 :             if (*instance_id < 0) {
     766          31 :                 BGP_LOG_PEER_INSTANCE_CRITICAL(Peer(), vrf_name,
     767             :                     BGP_PEER_DIR_IN, BGP_LOG_FLAG_ALL,
     768             :                     "Received route without subscribe");
     769          19 :                 return false;
     770             :             }
     771             :         }
     772             :     } else {
     773             :         // Bail if there's no pending subscribe for the instance.
     774             :         // Note that route retract can be received while the instance is
     775             :         // marked for deletion.
     776             :         const InstanceMembershipRequestState *imr_state =
     777        1556 :             GetInstanceMembershipState(vrf_name);
     778        1556 :         if (imr_state) {
     779          53 :             *instance_id = imr_state->instance_id;
     780          53 :             *subscribe_pending = true;
     781        1503 :         } else if (add_change || !rt_instance) {
     782          16 :             BGP_LOG_PEER_INSTANCE_CRITICAL(Peer(), vrf_name, BGP_PEER_DIR_IN,
     783             :                BGP_LOG_FLAG_ALL, "Received route without pending subscribe");
     784           8 :             return false;
     785             :         }
     786             :     }
     787             : 
     788       41620 :     return true;
     789             : }
     790             : 
     791        1169 : bool BgpXmppChannel::ProcessMcastItem(string vrf_name,
     792             :     const pugi::xml_node &node, bool add_change) {
     793        1169 :     McastItemType item;
     794        1169 :     item.Clear();
     795             : 
     796        1169 :     if (!item.XmlParse(node)) {
     797           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
     798             :             BGP_LOG_FLAG_ALL, "Invalid multicast route message received");
     799           1 :         return false;
     800             :     }
     801             : 
     802        1168 :     if (item.entry.nlri.af != BgpAf::IPv4) {
     803           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
     804             :             "Unsupported address family " << item.entry.nlri.af <<
     805             :             " for multicast route");
     806           1 :         return false;
     807             :     }
     808             : 
     809        1167 :     if (item.entry.nlri.safi != BgpAf::Mcast) {
     810           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
     811             :             BGP_LOG_FLAG_ALL, "Unsupported subsequent address family " <<
     812             :             item.entry.nlri.safi << " for multicast route");
     813           1 :         return false;
     814             :     }
     815             : 
     816        1166 :     error_code error;
     817        1166 :     IpAddress grp_address = IpAddress::from_string("0.0.0.0", error);
     818        1166 :     if (!item.entry.nlri.group.empty()) {
     819        1166 :         if (!XmppDecodeAddress(item.entry.nlri.af,
     820             :             item.entry.nlri.group, &grp_address, false)) {
     821           7 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
     822             :                 "Bad group address " << item.entry.nlri.group);
     823           4 :             return false;
     824             :         }
     825             :     }
     826             : 
     827        1162 :     IpAddress src_address = IpAddress::from_string("0.0.0.0", error);
     828        1162 :     if (!item.entry.nlri.source.empty()) {
     829        1162 :         if (!XmppDecodeAddress(item.entry.nlri.af,
     830             :             item.entry.nlri.source, &src_address, true)) {
     831           5 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
     832             :                 "Bad source address " << item.entry.nlri.source);
     833           3 :             return false;
     834             :         }
     835             :     }
     836             : 
     837             :     bool subscribe_pending;
     838             :     int instance_id;
     839             :     uint64_t subscription_gen_id;
     840             :     BgpTable *table;
     841        1159 :     if (!VerifyMembership(vrf_name, Address::ERMVPN, &table, &instance_id,
     842             :         &subscription_gen_id, &subscribe_pending, add_change)) {
     843           6 :         channel_->Close();
     844           6 :         return false;
     845             :     }
     846             : 
     847             :     // Build the key to the Multicast DBTable
     848             :     uint16_t cluster_seed =
     849        1153 :         bgp_server_->global_config()->rd_cluster_seed();
     850        1153 :     RouteDistinguisher mc_rd;
     851        1153 :     if (cluster_seed) {
     852           0 :         mc_rd = RouteDistinguisher(cluster_seed, peer_->bgp_identifier(),
     853           0 :                                    instance_id);
     854             :     } else {
     855        1153 :         mc_rd = RouteDistinguisher(peer_->bgp_identifier(), instance_id);
     856             :     }
     857             : 
     858             :     ErmVpnPrefix mc_prefix(ErmVpnPrefix::NativeRoute, mc_rd,
     859        1153 :         grp_address.to_v4(), src_address.to_v4());
     860             : 
     861             :     // Build and enqueue a DB request for route-addition
     862        1153 :     DBRequest req;
     863        1153 :     req.key.reset(new ErmVpnTable::RequestKey(mc_prefix, peer_.get()));
     864             : 
     865        1152 :     uint32_t flags = 0;
     866        1152 :     ExtCommunitySpec ext;
     867        1151 :     string label_range("none");
     868             : 
     869        1151 :     if (add_change) {
     870         728 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     871         728 :         vector<uint32_t> labels;
     872         728 :         const McastNextHopsType &inh_list = item.entry.next_hops;
     873             : 
     874         728 :         if (inh_list.next_hop.empty()) {
     875           2 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
     876             :                 BGP_LOG_FLAG_ALL, "Missing next-hop for multicast route " <<
     877             :                 mc_prefix.ToString());
     878           1 :             return false;
     879             :         }
     880             : 
     881             :         // Agents should send only one next-hop in the item
     882         727 :         if (inh_list.next_hop.size() != 1) {
     883           2 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
     884             :                 "More than one nexthop received for multicast route " <<
     885             :                 mc_prefix.ToString());
     886           1 :             return false;
     887             :         }
     888             : 
     889         726 :         McastNextHopsType::const_iterator nit = inh_list.begin();
     890             : 
     891             :         // Label Allocation item.entry.label by parsing the range
     892         726 :         label_range = nit->label;
     893        1453 :         if (!stringToIntegerList(label_range, "-", labels) ||
     894         727 :             labels.size() != 2) {
     895           4 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
     896             :                 "Bad label range " << label_range <<
     897             :                 " for multicast route " << mc_prefix.ToString());
     898           3 :             return false;
     899             :         }
     900             : 
     901         724 :         if (!labels[0] || !labels[1] || labels[1] < labels[0]) {
     902           6 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
     903             :                 BGP_LOG_FLAG_ALL, "Bad label range " << label_range <<
     904             :                 " for multicast route " << mc_prefix.ToString());
     905           3 :             return false;
     906             :         }
     907             : 
     908         721 :         BgpAttrSpec attrs;
     909         721 :         LabelBlockPtr lbptr = lb_mgr_->LocateBlock(labels[0], labels[1]);
     910             : 
     911         721 :         BgpAttrLabelBlock attr_label(lbptr);
     912         721 :         attrs.push_back(&attr_label);
     913             : 
     914             :         // Next-hop ip address
     915         720 :         IpAddress nh_address;
     916         720 :         if (!XmppDecodeAddress(nit->af, nit->address, &nh_address)) {
     917           5 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
     918             :                 BGP_LOG_FLAG_ALL, "Bad nexthop address " << nit->address <<
     919             :                 " for multicast route " << mc_prefix.ToString());
     920           3 :             return false;
     921             :         }
     922         717 :         BgpAttrNextHop nexthop(nh_address.to_v4().to_ulong());
     923         717 :         attrs.push_back(&nexthop);
     924             : 
     925             :         // Process tunnel encapsulation list.
     926         718 :         bool no_tunnel_encap = true;
     927         718 :         bool no_valid_tunnel_encap = true;
     928         718 :         for (McastTunnelEncapsulationListType::const_iterator eit =
     929         718 :              nit->tunnel_encapsulation_list.begin();
     930         753 :              eit != nit->tunnel_encapsulation_list.end(); ++eit) {
     931          35 :             no_tunnel_encap = false;
     932          35 :             TunnelEncap tun_encap(*eit);
     933          35 :             if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
     934           0 :                 continue;
     935          35 :             no_valid_tunnel_encap = false;
     936          35 :             ext.communities.push_back(tun_encap.GetExtCommunityValue());
     937             :         }
     938             : 
     939             :         // Mark the path as infeasible if all tunnel encaps published
     940             :         // by agent are invalid.
     941         718 :         if (!no_tunnel_encap && no_valid_tunnel_encap) {
     942           0 :             flags = BgpPath::NoTunnelEncap;
     943             :         }
     944             : 
     945         718 :         if (!ext.communities.empty())
     946          23 :             attrs.push_back(&ext);
     947             : 
     948         718 :         BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
     949         718 :         req.data.reset(new ErmVpnTable::RequestData(
     950         718 :             attr, flags, 0, 0, subscription_gen_id));
     951         718 :         stats_[RX].reach++;
     952         738 :     } else {
     953         423 :         req.oper = DBRequest::DB_ENTRY_DELETE;
     954         423 :         stats_[RX].unreach++;
     955             :     }
     956             : 
     957             :     // Defer all requests till subscribe is processed.
     958        1142 :     if (subscribe_pending) {
     959          42 :         DBRequest *request_entry = new DBRequest();
     960          42 :         request_entry->Swap(&req);
     961             :         string table_name =
     962          42 :             RoutingInstance::GetTableName(vrf_name, Address::ERMVPN);
     963          42 :         defer_q_.insert(make_pair(
     964          84 :             make_pair(vrf_name, table_name), request_entry));
     965          42 :         return true;
     966          42 :     }
     967             : 
     968        1100 :     assert(table);
     969        1318 :     BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
     970             :         SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
     971             :         "Multicast group " << item.entry.nlri.group <<
     972             :         " source " << item.entry.nlri.source <<
     973             :         " and label range " << label_range <<
     974             :         " enqueued for " << (add_change ? "add/change" : "delete"));
     975        1100 :     table->Enqueue(&req);
     976        1100 :     return true;
     977        1169 : }
     978             : 
     979          88 : void BgpXmppChannel::CreateType5MvpnRouteRequest(IpAddress grp_address,
     980             :         IpAddress src_address, bool add_change, uint64_t subscription_gen_id,
     981             :         int instance_id, DBRequest& req, const MvpnNextHopType &nexthop) {
     982          88 :     RouteDistinguisher mc_rd =  RouteDistinguisher::kZeroRd;
     983             :     MvpnPrefix mc_prefix(MvpnPrefix::SourceActiveADRoute, mc_rd,
     984          88 :             grp_address.to_v4(), src_address.to_v4());
     985          88 :     uint32_t flags = 0;
     986             : 
     987             :     // Build and enqueue a DB request for route-addition
     988          88 :     req.key.reset(new MvpnTable::RequestKey(mc_prefix, peer_.get()));
     989             : 
     990          88 :     if (add_change) {
     991          76 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     992             : 
     993          76 :         BgpAttrSpec attrs;
     994             :         // Next-hop ip address
     995          76 :         IpAddress nh_address;
     996          76 :         if (!XmppDecodeAddress(nexthop.af, nexthop.address, &nh_address)) {
     997           0 :             return;
     998             :         }
     999             : 
    1000             :         BgpAttrSourceRd source_rd(
    1001          76 :                 RouteDistinguisher(nh_address.to_v4().to_ulong(), instance_id));
    1002          76 :         attrs.push_back(&source_rd);
    1003          76 :         BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
    1004          76 :         req.data.reset(new MvpnTable::RequestData(
    1005          76 :             attr, flags, 0, 0, subscription_gen_id));
    1006          76 :         stats_[RX].reach++;
    1007          76 :     } else {
    1008          12 :         req.oper = DBRequest::DB_ENTRY_DELETE;
    1009          12 :         stats_[RX].unreach++;
    1010             :     }
    1011          88 : }
    1012             : 
    1013         158 : void BgpXmppChannel::CreateType7MvpnRouteRequest(IpAddress grp_address,
    1014             :         IpAddress src_address, bool add_change, uint64_t subscription_gen_id,
    1015             :         DBRequest& req) {
    1016         158 :     RouteDistinguisher mc_rd =  RouteDistinguisher::kZeroRd;
    1017             :     MvpnPrefix mc_prefix(MvpnPrefix::SourceTreeJoinRoute, mc_rd, 0,
    1018         158 :             grp_address.to_v4(), src_address.to_v4());
    1019         158 :     uint32_t flags = BgpPath::ResolveNexthop;
    1020             : 
    1021             :     // Build and enqueue a DB request for route-addition
    1022         158 :     req.key.reset(new MvpnTable::RequestKey(mc_prefix, peer_.get()));
    1023             : 
    1024         158 :     if (add_change) {
    1025         126 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1026             : 
    1027         126 :         BgpAttrSpec attrs;
    1028             : 
    1029             :         // Next-hop ip address
    1030         126 :         BgpAttrNextHop nexthop(src_address);
    1031         126 :         attrs.push_back(&nexthop);
    1032             : 
    1033         126 :         BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
    1034         126 :         req.data.reset(new MvpnTable::RequestData(
    1035         126 :             attr, flags, 0, 0, subscription_gen_id));
    1036         126 :         stats_[RX].reach++;
    1037         126 :     } else {
    1038          32 :         req.oper = DBRequest::DB_ENTRY_DELETE;
    1039          32 :         stats_[RX].unreach++;
    1040             :     }
    1041         158 : }
    1042             : 
    1043         248 : bool BgpXmppChannel::ProcessMvpnItem(string vrf_name,
    1044             :     const pugi::xml_node &node, bool add_change) {
    1045         248 :     MvpnItemType item;
    1046         248 :     item.Clear();
    1047             : 
    1048         248 :     if (!item.XmlParse(node)) {
    1049           0 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1050             :             BGP_LOG_FLAG_ALL, "Invalid multicast route message received");
    1051           0 :         return false;
    1052             :     }
    1053             : 
    1054         248 :     if (item.entry.nlri.af != BgpAf::IPv4) {
    1055           0 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1056             :             "Unsupported address family " << item.entry.nlri.af <<
    1057             :             " for multicast route");
    1058           0 :         return false;
    1059             :     }
    1060             : 
    1061         248 :     if (item.entry.nlri.safi != BgpAf::MVpn) {
    1062           0 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1063             :             BGP_LOG_FLAG_ALL, "Unsupported subsequent address family " <<
    1064             :             item.entry.nlri.safi << " for multicast route");
    1065           0 :         return false;
    1066             :     }
    1067             : 
    1068         248 :     if (item.entry.nlri.group.empty()) {
    1069           0 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1070             :             "Mandatory group address not specified");
    1071           0 :         return false;
    1072             :     }
    1073             : 
    1074         248 :     error_code error;
    1075         248 :     IpAddress grp_address = IpAddress::from_string("0.0.0.0", error);
    1076         248 :     if (!XmppDecodeAddress(item.entry.nlri.af,
    1077             :         item.entry.nlri.group, &grp_address, false)) {
    1078           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1079             :             "Bad group address " << item.entry.nlri.group);
    1080           1 :         return false;
    1081             :     }
    1082             : 
    1083         247 :     if (item.entry.nlri.source.empty()) {
    1084           0 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1085             :             "Mandatory source address not specified");
    1086           0 :         return false;
    1087             :     }
    1088             : 
    1089         247 :     IpAddress src_address = IpAddress::from_string("0.0.0.0", error);
    1090         247 :     if (!XmppDecodeAddress(item.entry.nlri.af,
    1091             :         item.entry.nlri.source, &src_address, true)) {
    1092           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1093             :             "Bad source address " << item.entry.nlri.source);
    1094           1 :         return false;
    1095             :     }
    1096             : 
    1097             :     bool subscribe_pending;
    1098             :     int instance_id;
    1099             :     uint64_t subscription_gen_id;
    1100             :     BgpTable *table;
    1101         246 :     if (!VerifyMembership(vrf_name, Address::MVPN, &table, &instance_id,
    1102             :         &subscription_gen_id, &subscribe_pending, add_change)) {
    1103           0 :         channel_->Close();
    1104           0 :         return false;
    1105             :     }
    1106             : 
    1107         246 :     int rt_type = item.entry.nlri.route_type;
    1108         246 :     DBRequest req;
    1109             :     // Build the key to the Multicast DBTable
    1110         246 :     if (rt_type == MvpnPrefix::SourceTreeJoinRoute) {
    1111         158 :         CreateType7MvpnRouteRequest(grp_address, src_address, add_change,
    1112             :                 subscription_gen_id, req);
    1113          88 :     } else if (rt_type == MvpnPrefix::SourceActiveADRoute) {
    1114          88 :         CreateType5MvpnRouteRequest(grp_address, src_address, add_change,
    1115             :                 subscription_gen_id, instance_id, req, item.entry.next_hop);
    1116             :     } else {
    1117           0 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1118             :             "Unsupported route type " << item.entry.nlri.route_type);
    1119           0 :         return false;
    1120             :     }
    1121             : 
    1122             :     // Need to locate path resolver if not done already
    1123         246 :     assert(table);
    1124         246 :     table->LocatePathResolver();
    1125             : 
    1126             :     // Defer all requests till subscribe is processed.
    1127         246 :     if (subscribe_pending) {
    1128           8 :         DBRequest *request_entry = new DBRequest();
    1129           8 :         request_entry->Swap(&req);
    1130             :         string table_name =
    1131           8 :             RoutingInstance::GetTableName(vrf_name, Address::MVPN);
    1132           8 :         defer_q_.insert(make_pair(
    1133          16 :             make_pair(vrf_name, table_name), request_entry));
    1134           8 :         return true;
    1135           8 :     }
    1136             : 
    1137         476 :     BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
    1138             :         SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
    1139             :         "Multicast group " << item.entry.nlri.group <<
    1140             :         " source " << item.entry.nlri.source <<
    1141             :         " enqueued for " << (add_change ? "add/change" : "delete"));
    1142         238 :     table->Enqueue(&req);
    1143         238 :     return true;
    1144         248 : }
    1145             : 
    1146       25621 : bool BgpXmppChannel::ProcessItem(string vrf_name,
    1147             :     const pugi::xml_node &node, bool add_change, int primary_instance_id) {
    1148       25621 :     ItemType item;
    1149       25621 :     item.Clear();
    1150             : 
    1151       25621 :     if (!item.XmlParse(node)) {
    1152           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1153             :             "Invalid inet route message received");
    1154           1 :         return false;
    1155             :     }
    1156             : 
    1157       25620 :     if (item.entry.nlri.af != BgpAf::IPv4) {
    1158           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1159             :             "Unsupported address family " << item.entry.nlri.af <<
    1160             :             " for inet route " << item.entry.nlri.address);
    1161           1 :         return false;
    1162             :     }
    1163             : 
    1164       25619 :     if ((item.entry.nlri.safi != BgpAf::Unicast) &&
    1165          12 :           (item.entry.nlri.safi != BgpAf::Mpls)) {
    1166           0 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1167             :             "Unsupported subsequent address family " << item.entry.nlri.safi <<
    1168             :             " for inet route " << item.entry.nlri.address);
    1169           0 :         return false;
    1170             :     }
    1171       25619 :     error_code error;
    1172             :     Ip4Prefix inet_prefix =
    1173       25619 :         Ip4Prefix::FromString(item.entry.nlri.address, &error);
    1174       25619 :     if (error) {
    1175           4 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1176             :             "Bad inet route " << item.entry.nlri.address);
    1177           2 :         return false;
    1178             :     }
    1179             : 
    1180       25617 :     if (add_change && item.entry.next_hops.next_hop.empty()) {
    1181           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1182             :             "Missing next-hops for inet route " << inet_prefix.ToString());
    1183           1 :         return false;
    1184             :     }
    1185             : 
    1186             :     // Rules for routes in master instance:
    1187             :     // - Label must be 0 unless it is INETMPLS
    1188             :     // - Tunnel encapsulation is not required
    1189             :     // - Do not add SourceRd and ExtCommunitySpec
    1190       25616 :     bool master = (vrf_name == BgpConfigManager::kMasterInstance);
    1191             :     bool subscribe_pending;
    1192             :     int instance_id;
    1193             :     uint64_t subscription_gen_id;
    1194             :     BgpTable *table;
    1195       51232 :     Address::Family family = BgpAf::AfiSafiToFamily(item.entry.nlri.af,
    1196       25616 :                                                     item.entry.nlri.safi);
    1197       25616 :     if (!VerifyMembership(vrf_name, family, &table, &instance_id,
    1198             :         &subscription_gen_id, &subscribe_pending, add_change)) {
    1199           6 :         channel_->Close();
    1200           6 :         return false;
    1201             :     }
    1202             : 
    1203       25609 :     DBRequest req;
    1204       25609 :     req.key.reset(new InetTable::RequestKey(inet_prefix, peer_.get()));
    1205             : 
    1206       25609 :     IpAddress nh_address(Ip4Address(0));
    1207       25609 :     uint32_t label = 0;
    1208       25609 :     uint32_t flags = 0;
    1209       25609 :     ExtCommunitySpec ext;
    1210       25609 :     LargeCommunitySpec largecomm;
    1211       25609 :     CommunitySpec comm;
    1212             : 
    1213       25608 :     if (add_change) {
    1214       15218 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1215       15218 :         BgpAttrSpec attrs;
    1216             : 
    1217       15218 :         const NextHopListType &inh_list = item.entry.next_hops;
    1218             : 
    1219             :         // Agents should send only one next-hop in the item.
    1220       15218 :         if (inh_list.next_hop.size() != 1) {
    1221           0 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1222             :                 BGP_LOG_FLAG_ALL,
    1223             :                 "More than one nexthop received for inet route " <<
    1224             :                 inet_prefix.ToString());
    1225           0 :             return false;
    1226             :         }
    1227             : 
    1228       15218 :         NextHopListType::const_iterator nit = inh_list.begin();
    1229             : 
    1230       15218 :         IpAddress nhop_address(Ip4Address(0));
    1231       15218 :         if (!XmppDecodeAddress(nit->af, nit->address, &nhop_address)) {
    1232           6 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1233             :                 BGP_LOG_FLAG_ALL,
    1234             :                 "Bad nexthop address " << nit->address <<
    1235             :                 " for inet route " << inet_prefix.ToString());
    1236           3 :             return false;
    1237             :         }
    1238             : 
    1239       17902 :         if (nit->label > EvpnPrefix::kMaxVniSigned ||
    1240        2686 :             ((master && nit->label) &&
    1241             :              !(family == Address::INETMPLS))) {
    1242           5 :              BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1243             :                 BGP_LOG_FLAG_ALL,
    1244             :                 "Bad label " << nit->label <<
    1245             :                 " for inet route " << inet_prefix.ToString());
    1246           5 :             return false;
    1247             :         }
    1248       27747 :         if ((!master || (master && (family == Address::INETMPLS))) &&
    1249       12536 :             !nit->label) {
    1250           4 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1251             :                BGP_LOG_FLAG_ALL,
    1252             :                "Bad label " << nit->label <<
    1253             :                " for inet route in master instance(mpls)/non master instance" <<
    1254             :                inet_prefix.ToString());
    1255           2 :            return false;
    1256             :         }
    1257             : 
    1258       15209 :         nh_address = nhop_address;
    1259       15209 :         label = nit->label;
    1260             : 
    1261             :         // Process tunnel encapsulation list.
    1262       15209 :         bool no_tunnel_encap = true;
    1263       15209 :         bool no_valid_tunnel_encap = true;
    1264       15209 :         for (TunnelEncapsulationListType::const_iterator eit =
    1265       15209 :             nit->tunnel_encapsulation_list.begin();
    1266       28613 :             eit != nit->tunnel_encapsulation_list.end(); ++eit) {
    1267       13404 :             no_tunnel_encap = false;
    1268       13404 :             TunnelEncap tun_encap(*eit);
    1269       13403 :             if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
    1270           0 :                 continue;
    1271       13403 :             no_valid_tunnel_encap = false;
    1272       13403 :             ext.communities.push_back(tun_encap.GetExtCommunityValue());
    1273             :         }
    1274             : 
    1275             :         // Mark the path as infeasible if all tunnel encaps published
    1276             :         // by agent are invalid.
    1277       15209 :         if (!no_tunnel_encap && no_valid_tunnel_encap && !master) {
    1278           0 :             flags = BgpPath::NoTunnelEncap;
    1279             :         }
    1280             : 
    1281             :         // Process router-mac as ext-community.
    1282       15209 :         if (!nit->mac.empty()) {
    1283             :             MacAddress mac_addr =
    1284           0 :                         MacAddress::FromString(nit->mac, &error);
    1285           0 :             if (error) {
    1286           0 :                 BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1287             :                     BGP_LOG_FLAG_ALL,
    1288             :                     "Bad next-hop mac address " << nit->mac);
    1289           0 :                 return false;
    1290             :             }
    1291           0 :             if (!mac_addr.IsZero()) {
    1292           0 :                 RouterMac router_mac(mac_addr);
    1293           0 :                 ext.communities.push_back(router_mac.GetExtCommunityValue());
    1294             :             }
    1295             :         }
    1296             : 
    1297             :         // Process tags list.
    1298       15209 :         uint64_t tag_val = 0;
    1299       15209 :         for (TagListType::const_iterator tit = nit->tag_list.begin();
    1300       15219 :             tit != nit->tag_list.end(); ++tit) {
    1301          10 :             tag_val = nit->is_new_tags_list ? *tit :
    1302           0 :                 ((0xFFFF0000 & *tit) << 16) | (0x0000FFFF & *tit);
    1303          10 :             TagLC tag_lc(bgp_server_->autonomous_system(), tag_val);
    1304          40 :             for (const auto &value_data : tag_lc.GetLargeCommunityValue()) {
    1305          30 :                 largecomm.communities.push_back(value_data);
    1306          10 :             }
    1307             :         }
    1308             : 
    1309             :         // Process local sequence_number
    1310       15209 :         if (nit->local_sequence_number) {
    1311           0 :             LocalSequenceNumber lsn (nit->local_sequence_number);
    1312           0 :             ext.communities.push_back(lsn.GetExtCommunityValue());
    1313             :         }
    1314             : 
    1315       15209 :         BgpAttrLocalPref local_pref(item.entry.local_preference);
    1316       15209 :         if (local_pref.local_pref != 0)
    1317       12824 :             attrs.push_back(&local_pref);
    1318             : 
    1319             :         // If there's no explicit med, calculate it automatically from the
    1320             :         // local pref.
    1321       15210 :         uint32_t med_value = item.entry.med;
    1322       15210 :         if (!med_value)
    1323        7770 :             med_value = GetMedFromLocalPref(local_pref.local_pref);
    1324       15210 :         BgpAttrMultiExitDisc med(med_value);
    1325       15210 :         if (med.med != 0)
    1326       12826 :             attrs.push_back(&med);
    1327             : 
    1328             :         // Process community tags.
    1329       15210 :         const CommunityTagListType &ict_list = item.entry.community_tag_list;
    1330       15210 :         for (CommunityTagListType::const_iterator cit = ict_list.begin();
    1331       15222 :             cit != ict_list.end(); ++cit) {
    1332          12 :             error_code error;
    1333             :             uint32_t rt_community =
    1334          12 :                 CommunityType::CommunityFromString(*cit, &error);
    1335          12 :             if (error)
    1336           0 :                 continue;
    1337          12 :             comm.communities.push_back(rt_community);
    1338             :         }
    1339             : 
    1340       15210 :         uint32_t addr = nh_address.to_v4().to_ulong();
    1341       15210 :         BgpAttrNextHop nexthop(addr);
    1342       15210 :         attrs.push_back(&nexthop);
    1343             :         uint16_t cluster_seed =
    1344       15210 :             bgp_server_->global_config()->rd_cluster_seed();
    1345       15210 :         BgpAttrSourceRd source_rd;
    1346       15210 :         if (!master || primary_instance_id) {
    1347       12541 :             if (master)
    1348          10 :                 instance_id = primary_instance_id;
    1349       12541 :             if (cluster_seed) {
    1350           6 :                 source_rd = BgpAttrSourceRd(
    1351           9 :                     RouteDistinguisher(cluster_seed, addr, instance_id));
    1352             :             } else {
    1353       25076 :                 source_rd = BgpAttrSourceRd(
    1354       37614 :                     RouteDistinguisher(addr, instance_id));
    1355             :             }
    1356       12541 :             attrs.push_back(&source_rd);
    1357             :         }
    1358             : 
    1359             :         // Process security group list.
    1360       15210 :         uint16_t sg_index = 0;
    1361       15210 :         const SecurityGroupListType &isg_list = item.entry.security_group_list;
    1362       15210 :         for (SecurityGroupListType::const_iterator sit = isg_list.begin();
    1363       30938 :             sit != isg_list.end(); ++sit) {
    1364       15728 :             if (bgp_server_->autonomous_system() <= AS2_MAX) {
    1365       15728 :                 SecurityGroup sg(bgp_server_->autonomous_system(), *sit);
    1366       15728 :                 ext.communities.push_back(sg.GetExtCommunityValue());
    1367             :             } else {
    1368           0 :                 SecurityGroup sg(sg_index, *sit);
    1369           0 :                 SecurityGroup4ByteAs sg4(bgp_server_->autonomous_system(),
    1370           0 :                                          sg_index++);
    1371           0 :                 ext.communities.push_back(sg4.GetExtCommunityValue());
    1372           0 :                 ext.communities.push_back(sg.GetExtCommunityValue());
    1373             :             }
    1374             :         }
    1375             : 
    1376       15210 :         if (item.entry.mobility.seqno) {
    1377         512 :             MacMobility mm(item.entry.mobility.seqno,
    1378         512 :                            item.entry.mobility.sticky);
    1379         512 :             ext.communities.push_back(mm.GetExtCommunityValue());
    1380       14698 :         } else if (item.entry.sequence_number) {
    1381           0 :             MacMobility mm(item.entry.sequence_number);
    1382           0 :             ext.communities.push_back(mm.GetExtCommunityValue());
    1383             :         }
    1384             : 
    1385             :         // Process load-balance extended community.
    1386       15210 :         LoadBalance load_balance(item.entry.load_balance);
    1387       15210 :         if (!load_balance.IsDefault())
    1388           2 :             ext.communities.push_back(load_balance.GetExtCommunityValue());
    1389             : 
    1390       15210 :         if (!comm.communities.empty())
    1391           7 :             attrs.push_back(&comm);
    1392       15210 :         if (!master && !ext.communities.empty())
    1393       12531 :             attrs.push_back(&ext);
    1394       15209 :         if (!master && !largecomm.communities.empty())
    1395           3 :             attrs.push_back(&largecomm);
    1396             : 
    1397             :         // Process sub-protocol(route types)
    1398       15209 :         BgpAttrSubProtocol sbp(item.entry.sub_protocol);
    1399       15209 :         attrs.push_back(&sbp);
    1400             : 
    1401       15209 :         BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
    1402       15209 :         req.data.reset(new BgpTable::RequestData(
    1403       15209 :             attr, flags, label, 0, subscription_gen_id));
    1404       15219 :     } else {
    1405       10390 :         req.oper = DBRequest::DB_ENTRY_DELETE;
    1406             :     }
    1407             : 
    1408             :     // Defer all requests till subscribe is processed.
    1409       25599 :     if (subscribe_pending) {
    1410         444 :         DBRequest *request_entry = new DBRequest();
    1411         444 :         request_entry->Swap(&req);
    1412             :         string table_name =
    1413         444 :             RoutingInstance::GetTableName(vrf_name, family);
    1414         444 :         defer_q_.insert(make_pair(
    1415         888 :             make_pair(vrf_name, table_name), request_entry));
    1416         444 :        return true;
    1417         444 :     }
    1418             : 
    1419       25155 :     assert(table);
    1420       33967 :     BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
    1421             :         SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
    1422             :         "Inet route " << item.entry.nlri.address <<
    1423             :         " with next-hop " << nh_address << " and label " << label <<
    1424             :         " enqueued for " << (add_change ? "add/change" : "delete") <<
    1425             :         " to table " << table->name());
    1426       25156 :     table->Enqueue(&req);
    1427             : 
    1428       25156 :     if (add_change) {
    1429       14783 :         stats_[RX].reach++;
    1430             :     } else {
    1431       10373 :         stats_[RX].unreach++;
    1432             :     }
    1433             : 
    1434       25156 :     return true;
    1435       25621 : }
    1436             : 
    1437        9101 : bool BgpXmppChannel::ProcessInet6Item(string vrf_name,
    1438             :     const pugi::xml_node &node, bool add_change) {
    1439        9101 :     ItemType item;
    1440        9101 :     item.Clear();
    1441             : 
    1442        9101 :     if (!item.XmlParse(node)) {
    1443           2 :         error_stats().incr_inet6_rx_bad_xml_token_count();
    1444           3 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1445             :             "Invalid inet6 route message received");
    1446           2 :         return false;
    1447             :     }
    1448             : 
    1449        9099 :     if (item.entry.nlri.af != BgpAf::IPv6) {
    1450           2 :         error_stats().incr_inet6_rx_bad_afi_safi_count();
    1451           3 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1452             :             "Unsupported address family " << item.entry.nlri.af <<
    1453             :             " for inet6 route " << item.entry.nlri.address);
    1454           2 :         return false;
    1455             :     }
    1456             : 
    1457        9097 :     if (item.entry.nlri.safi != BgpAf::Unicast) {
    1458           1 :         error_stats().incr_inet6_rx_bad_afi_safi_count();
    1459           1 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1460             :             "Unsupported subsequent address family " << item.entry.nlri.safi <<
    1461             :             " for inet6 route " << item.entry.nlri.address);
    1462           1 :         return false;
    1463             :     }
    1464             : 
    1465        9096 :     error_code error;
    1466             :     Inet6Prefix inet6_prefix =
    1467        9096 :         Inet6Prefix::FromString(item.entry.nlri.address, &error);
    1468        9096 :     if (error) {
    1469           2 :         error_stats().incr_inet6_rx_bad_prefix_count();
    1470           3 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1471             :             "Bad inet6 route " << item.entry.nlri.address);
    1472           2 :         return false;
    1473             :     }
    1474             : 
    1475        9094 :     if (add_change && item.entry.next_hops.next_hop.empty()) {
    1476           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1477             :             "Missing next-hops for inet6 route " << inet6_prefix.ToString());
    1478           1 :         return false;
    1479             :     }
    1480             : 
    1481             :     // Rules for routes in master instance:
    1482             :     // - Label must be 0
    1483             :     // - Tunnel encapsulation is not required
    1484             :     // - Do not add SourceRd and ExtCommunitySpec
    1485        9093 :     bool master = (vrf_name == BgpConfigManager::kMasterInstance);
    1486             : 
    1487             :     // vector<Address::Family> family_list = list_of(Address::INET6)(Address::EVPN);
    1488        9093 :     vector<Address::Family> family_list = list_of(Address::INET6);
    1489       27261 :     BOOST_FOREACH(Address::Family family, family_list) {
    1490             :         bool subscribe_pending;
    1491             :         int instance_id;
    1492             :         uint64_t subscription_gen_id;
    1493             :         BgpTable *table;
    1494        9093 :         if (!VerifyMembership(vrf_name, family, &table, &instance_id,
    1495             :             &subscription_gen_id, &subscribe_pending, add_change)) {
    1496           6 :             channel_->Close();
    1497           9 :             return false;
    1498             :         }
    1499             : 
    1500        9087 :         DBRequest req;
    1501        9087 :         if (family == Address::INET6) {
    1502        9087 :             req.key.reset(new Inet6Table::RequestKey(inet6_prefix, peer_.get()));
    1503             :         } else {
    1504             :             EvpnPrefix evpn_prefix(RouteDistinguisher::kZeroRd,
    1505           0 :                 inet6_prefix.addr(), inet6_prefix.prefixlen());
    1506           0 :             req.key.reset(new EvpnTable::RequestKey(evpn_prefix, peer_.get()));
    1507             :         }
    1508             : 
    1509        9087 :         IpAddress nh_address(Ip4Address(0));
    1510        9087 :         uint32_t label = 0;
    1511        9087 :         uint32_t flags = 0;
    1512        9087 :         ExtCommunitySpec ext;
    1513        9087 :         LargeCommunitySpec largecomm;
    1514        9087 :         CommunitySpec comm;
    1515             : 
    1516        9087 :         if (add_change) {
    1517        6775 :             req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1518        6775 :             BgpAttrSpec attrs;
    1519             : 
    1520        6775 :             const NextHopListType &inh_list = item.entry.next_hops;
    1521             : 
    1522             :             // Agents should send only one next-hop in the item.
    1523        6775 :             if (inh_list.next_hop.size() != 1) {
    1524           0 :                 BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1525             :                     BGP_LOG_FLAG_ALL,
    1526             :                     "More than one nexthop received for inet6 route " <<
    1527             :                     inet6_prefix.ToString());
    1528           0 :                 return false;
    1529             :             }
    1530             : 
    1531        6775 :             NextHopListType::const_iterator nit = inh_list.begin();
    1532             : 
    1533        6775 :             IpAddress nhop_address(Ip4Address(0));
    1534        6775 :             if (!XmppDecodeAddress(nit->af, nit->address, &nhop_address)) {
    1535           3 :                 error_stats().incr_inet6_rx_bad_nexthop_count();
    1536           5 :                 BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1537             :                     BGP_LOG_FLAG_ALL,
    1538             :                     "Bad nexthop address " << nit->address <<
    1539             :                     " for inet6 route " << inet6_prefix.ToString());
    1540           3 :                 return false;
    1541             :             }
    1542             : 
    1543        6772 :             if (family == Address::EVPN) {
    1544           0 :                 if (nit->vni > EvpnPrefix::kMaxVniSigned) {
    1545           0 :                     BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1546             :                         BGP_LOG_FLAG_ALL,
    1547             :                         "Bad label " << nit->vni <<
    1548             :                         " for inet6 route " << inet6_prefix.ToString());
    1549           0 :                     return false;
    1550             :                 }
    1551           0 :                 if (!nit->vni)
    1552           0 :                     continue;
    1553           0 :                 if (nit->mac.empty())
    1554           0 :                     continue;
    1555             : 
    1556             :                 MacAddress mac_addr =
    1557           0 :                     MacAddress::FromString(nit->mac, &error);
    1558           0 :                 if (error) {
    1559           0 :                     BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1560             :                         BGP_LOG_FLAG_ALL,
    1561             :                         "Bad next-hop mac address " << nit->mac);
    1562           0 :                     return false;
    1563             :                 }
    1564           0 :                 RouterMac router_mac(mac_addr);
    1565           0 :                 ext.communities.push_back(router_mac.GetExtCommunityValue());
    1566             :             } else {
    1567        6772 :                 if (nit->label > EvpnPrefix::kMaxVniSigned || (master && nit->label)) {
    1568           0 :                     BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1569             :                         BGP_LOG_FLAG_ALL,
    1570             :                         "Bad label " << nit->label <<
    1571             :                         " for inet6 route " << inet6_prefix.ToString());
    1572           0 :                     return false;
    1573             :                 }
    1574        6772 :                 if (!master && !nit->label)
    1575           0 :                     continue;
    1576             :             }
    1577             : 
    1578        6772 :             nh_address = nhop_address;
    1579        6772 :             if (family == Address::INET6) {
    1580        6772 :                 label = nit->label;
    1581             :             } else {
    1582           0 :                 label = nit->vni;
    1583             :             }
    1584             : 
    1585             :             // Process tunnel encapsulation list.
    1586        6772 :             bool no_tunnel_encap = true;
    1587        6772 :             bool no_valid_tunnel_encap = true;
    1588        6772 :             for (TunnelEncapsulationListType::const_iterator eit =
    1589        6772 :                 nit->tunnel_encapsulation_list.begin();
    1590       16611 :                 eit != nit->tunnel_encapsulation_list.end(); ++eit) {
    1591        9839 :                 no_tunnel_encap = false;
    1592        9839 :                 TunnelEncap tun_encap(*eit);
    1593        9839 :                 if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
    1594           0 :                     continue;
    1595        9839 :                 no_valid_tunnel_encap = false;
    1596        9839 :                 ext.communities.push_back(tun_encap.GetExtCommunityValue());
    1597             :             }
    1598             : 
    1599             :             // Mark the path as infeasible if all tunnel encaps published
    1600             :             // by agent are invalid.
    1601        6772 :             if (!no_tunnel_encap && no_valid_tunnel_encap && !master) {
    1602           0 :                 flags = BgpPath::NoTunnelEncap;
    1603             :             }
    1604             : 
    1605             :             // Process router-mac as ext-community.
    1606        6772 :             if (!nit->mac.empty()) {
    1607             :                 MacAddress mac_addr =
    1608           0 :                         MacAddress::FromString(nit->mac, &error);
    1609           0 :                 if (error) {
    1610           0 :                     BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1611             :                         BGP_LOG_FLAG_ALL,
    1612             :                         "Bad next-hop mac address " << nit->mac);
    1613           0 :                     return false;
    1614             :                 }
    1615           0 :                 if (!mac_addr.IsZero()) {
    1616           0 :                     RouterMac router_mac(mac_addr);
    1617           0 :                     ext.communities.push_back(router_mac.GetExtCommunityValue());
    1618             :                 }
    1619             :             }
    1620             : 
    1621             :             // Process tags list.
    1622        6772 :             uint64_t tag_val = 0;
    1623        6772 :             for (TagListType::const_iterator tit = nit->tag_list.begin();
    1624        6774 :                 tit != nit->tag_list.end(); ++tit) {
    1625           2 :                 tag_val = nit->is_new_tags_list ? *tit :
    1626           2 :                     ((0xFFFF0000 & *tit) << 16) | (0x0000FFFF & *tit);
    1627           2 :                 TagLC tag_lc(bgp_server_->autonomous_system(), tag_val);
    1628           2 :                 for (const auto &value_data :
    1629          10 :                     tag_lc.GetLargeCommunityValue()) {
    1630           6 :                     largecomm.communities.push_back(value_data);
    1631           2 :                 }
    1632             :             }
    1633             : 
    1634             :             // Process local sequence_number
    1635        6772 :             if (nit->local_sequence_number) {
    1636           0 :                 LocalSequenceNumber lsn (nit->local_sequence_number);
    1637           0 :                 ext.communities.push_back(lsn.GetExtCommunityValue());
    1638             :             }
    1639             : 
    1640        6772 :             BgpAttrLocalPref local_pref(item.entry.local_preference);
    1641        6772 :             if (local_pref.local_pref != 0)
    1642        6772 :                 attrs.push_back(&local_pref);
    1643             : 
    1644             :             // If there's no explicit med, calculate it automatically from the
    1645             :             // local pref.
    1646        6772 :             uint32_t med_value = item.entry.med;
    1647        6772 :             if (!med_value)
    1648         231 :                 med_value = GetMedFromLocalPref(local_pref.local_pref);
    1649        6772 :             BgpAttrMultiExitDisc med(med_value);
    1650        6772 :             if (med.med != 0)
    1651        6772 :                 attrs.push_back(&med);
    1652             : 
    1653             :             // Process community tags.
    1654        6772 :             const CommunityTagListType &ict_list =
    1655             :                 item.entry.community_tag_list;
    1656        6772 :             for (CommunityTagListType::const_iterator cit = ict_list.begin();
    1657        6780 :                 cit != ict_list.end(); ++cit) {
    1658           8 :                 error_code error;
    1659             :                 uint32_t rt_community =
    1660           8 :                     CommunityType::CommunityFromString(*cit, &error);
    1661           8 :                 if (error)
    1662           0 :                     continue;
    1663           8 :                 comm.communities.push_back(rt_community);
    1664             :             }
    1665             : 
    1666        6772 :             BgpAttrNextHop nexthop(nh_address);
    1667        6772 :             attrs.push_back(&nexthop);
    1668             : 
    1669        6772 :             BgpAttrSourceRd source_rd;
    1670        6772 :             if (!master) {
    1671        4107 :                 uint32_t addr = nh_address.to_v4().to_ulong();
    1672             :                 uint16_t cluster_seed =
    1673        4107 :                   bgp_server_->global_config()->rd_cluster_seed();
    1674        4107 :                 if (cluster_seed) {
    1675           6 :                     source_rd = BgpAttrSourceRd(
    1676           9 :                         RouteDistinguisher(cluster_seed, addr, instance_id));
    1677             :                 } else {
    1678        8208 :                     source_rd = BgpAttrSourceRd(
    1679       12312 :                         RouteDistinguisher(addr, instance_id));
    1680             :                 }
    1681        4107 :                 attrs.push_back(&source_rd);
    1682             :             }
    1683             : 
    1684             :             // Process security group list.
    1685        6772 :             const SecurityGroupListType &isg_list =
    1686             :                 item.entry.security_group_list;
    1687        6772 :             uint16_t sg_index = 0;
    1688        6772 :             for (SecurityGroupListType::const_iterator sit = isg_list.begin();
    1689       13554 :                 sit != isg_list.end(); ++sit) {
    1690        6782 :                 if (bgp_server_->autonomous_system() <= AS2_MAX) {
    1691        6782 :                     SecurityGroup sg(bgp_server_->autonomous_system(), *sit);
    1692        6782 :                     ext.communities.push_back(sg.GetExtCommunityValue());
    1693             :                 } else {
    1694           0 :                     SecurityGroup sg(sg_index, *sit);
    1695           0 :                     SecurityGroup4ByteAs sg4(bgp_server_->autonomous_system(),
    1696           0 :                                              sg_index++);
    1697           0 :                     ext.communities.push_back(sg4.GetExtCommunityValue());
    1698           0 :                     ext.communities.push_back(sg.GetExtCommunityValue());
    1699             :                 }
    1700             :             }
    1701             : 
    1702        6772 :             if (item.entry.mobility.seqno) {
    1703          18 :                 MacMobility mm(item.entry.mobility.seqno,
    1704          18 :                     item.entry.mobility.sticky);
    1705          18 :                 ext.communities.push_back(mm.GetExtCommunityValue());
    1706        6754 :             } else if (item.entry.sequence_number) {
    1707           0 :                 MacMobility mm(item.entry.sequence_number);
    1708           0 :                 ext.communities.push_back(mm.GetExtCommunityValue());
    1709             :             }
    1710             : 
    1711             :             // Process load-balance extended community.
    1712        6772 :             LoadBalance load_balance(item.entry.load_balance);
    1713        6772 :             if (!load_balance.IsDefault())
    1714           0 :                 ext.communities.push_back(load_balance.GetExtCommunityValue());
    1715             : 
    1716             :             // Process sub-protocol(route types)
    1717        6772 :             BgpAttrSubProtocol sbp(item.entry.sub_protocol);
    1718        6772 :             attrs.push_back(&sbp);
    1719             : 
    1720        6772 :             if (!comm.communities.empty())
    1721           5 :                 attrs.push_back(&comm);
    1722        6772 :             if (!master && !ext.communities.empty())
    1723        4107 :                 attrs.push_back(&ext);
    1724        6772 :             if (!master && !largecomm.communities.empty())
    1725           1 :                 attrs.push_back(&largecomm);
    1726             : 
    1727        6772 :             BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
    1728        6772 :             req.data.reset(new BgpTable::RequestData(
    1729        6772 :                 attr, flags, label, 0, subscription_gen_id));
    1730        6775 :         } else {
    1731        2312 :             req.oper = DBRequest::DB_ENTRY_DELETE;
    1732             :         }
    1733             : 
    1734             :         // Defer all requests till subscribe is processed.
    1735        9084 :         if (subscribe_pending) {
    1736         338 :             DBRequest *request_entry = new DBRequest();
    1737         338 :             request_entry->Swap(&req);
    1738             :             string table_name =
    1739         338 :                 RoutingInstance::GetTableName(vrf_name, family);
    1740         338 :             defer_q_.insert(make_pair(
    1741         676 :                 make_pair(vrf_name, table_name), request_entry));
    1742         338 :             continue;
    1743         338 :         }
    1744             : 
    1745        8746 :         assert(table);
    1746       16683 :         BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
    1747             :             SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
    1748             :             "Inet6 route " << item.entry.nlri.address <<
    1749             :             " with next-hop " << nh_address << " and label " << label <<
    1750             :             " enqueued for " << (add_change ? "add/change" : "delete") <<
    1751             :             " to table " << table->name());
    1752        8746 :         table->Enqueue(&req);
    1753       10110 :     }
    1754             : 
    1755        9084 :     if (add_change) {
    1756        6772 :         stats_[RX].reach++;
    1757             :     } else {
    1758        2312 :         stats_[RX].unreach++;
    1759             :     }
    1760             : 
    1761        9084 :     return true;
    1762        9101 : }
    1763             : 
    1764        5546 : bool BgpXmppChannel::ProcessEnetItem(string vrf_name,
    1765             :     const pugi::xml_node &node, bool add_change) {
    1766        5546 :     EnetItemType item;
    1767        5546 :     item.Clear();
    1768             : 
    1769        5546 :     if (!item.XmlParse(node)) {
    1770           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1771             :             "Invalid enet route message received");
    1772           1 :         return false;
    1773             :     }
    1774             : 
    1775        5545 :     if (item.entry.nlri.af != BgpAf::L2Vpn) {
    1776           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1777             :             "Unsupported address family " << item.entry.nlri.af <<
    1778             :             " for enet route " << item.entry.nlri.address);
    1779           1 :         return false;
    1780             :     }
    1781             : 
    1782        5544 :     if (item.entry.nlri.safi != BgpAf::Enet) {
    1783           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1784             :             "Unsupported subsequent address family " << item.entry.nlri.safi <<
    1785             :             " for enet route " << item.entry.nlri.mac);
    1786           1 :         return false;
    1787             :     }
    1788             : 
    1789        5543 :     bool type6 = false;
    1790        5543 :     error_code error;
    1791        5543 :     IpAddress group= IpAddress::from_string("0.0.0.0", error);
    1792        5543 :     if (!item.entry.nlri.group.empty()) {
    1793          36 :         type6 = true;
    1794          36 :         if (!XmppDecodeAddress(item.entry.nlri.af,
    1795             :                     item.entry.nlri.group, &group, false)) {
    1796           0 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1797             :                 "Bad group address " << item.entry.nlri.group);
    1798             :         }
    1799             :     }
    1800             : 
    1801        5543 :     IpAddress source = IpAddress::from_string("0.0.0.0", error);
    1802        5543 :     if (!item.entry.nlri.source.empty() && !XmppDecodeAddress(
    1803             :                 item.entry.nlri.af, item.entry.nlri.source, &source, true)) {
    1804           0 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1805             :             "Bad source address " << item.entry.nlri.source);
    1806             :     }
    1807             : 
    1808             :     //error_code error;
    1809        5543 :     MacAddress mac_addr = MacAddress::FromString(item.entry.nlri.mac, &error);
    1810             : 
    1811        5542 :     if (error) {
    1812           2 :         BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1813             :             "Bad mac address " << item.entry.nlri.mac);
    1814           1 :         return false;
    1815             :     }
    1816             : 
    1817        5541 :     bool type2 = type6 ? false : !mac_addr.IsZero();
    1818        5542 :     Ip4Prefix inet_prefix;
    1819        5541 :     Inet6Prefix inet6_prefix;
    1820        5541 :     IpAddress ip_addr;
    1821        5541 :     int prefix_len = 0;
    1822        5541 :     if (!item.entry.nlri.address.empty()) {
    1823        1359 :         size_t pos = item.entry.nlri.address.find('/');
    1824        1359 :         if (pos == string::npos) {
    1825           2 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name, BGP_LOG_FLAG_ALL,
    1826             :                 "Missing / in address " << item.entry.nlri.address);
    1827           1 :             return false;
    1828             :         }
    1829             : 
    1830        1358 :         bool ipv6 = item.entry.nlri.address.find(':') != string::npos;
    1831        1358 :         if (!ipv6) {
    1832             :             inet_prefix =
    1833        1315 :                 Ip4Prefix::FromString(item.entry.nlri.address, &error);
    1834        1315 :             if (error) {
    1835           2 :                 BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1836             :                     BGP_LOG_FLAG_ALL,
    1837             :                     "Cannot parse inet prefix string " <<
    1838             :                         item.entry.nlri.address);
    1839           1 :                 return false;
    1840             :             }
    1841             : 
    1842        1319 :             if (type2 && inet_prefix.prefixlen() != 32 &&
    1843           4 :                 item.entry.nlri.address != "0.0.0.0/0") {
    1844           2 :                 BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1845             :                     BGP_LOG_FLAG_ALL,
    1846             :                     "Bad inet address " << item.entry.nlri.address);
    1847           1 :                 return false;
    1848             :             }
    1849             : 
    1850        1313 :             ip_addr = inet_prefix.ip4_addr();
    1851        1312 :             prefix_len = inet_prefix.prefixlen();
    1852             :         } else {
    1853             :             inet6_prefix =
    1854          43 :                 Inet6Prefix::FromString(item.entry.nlri.address, &error);
    1855             : 
    1856          43 :             if (error) {
    1857           2 :                 BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1858             :                     BGP_LOG_FLAG_ALL,
    1859             :                     "Cannot parse inet6 prefix string " <<
    1860             :                         item.entry.nlri.address);
    1861           1 :                 return false;
    1862             :             }
    1863             : 
    1864          42 :             if (type2 && inet6_prefix.prefixlen() != 128 &&
    1865           0 :                 item.entry.nlri.address != "::/0") {
    1866           0 :                 BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1867             :                     BGP_LOG_FLAG_ALL,
    1868             :                     "Bad inet6 address " << item.entry.nlri.address);
    1869           0 :                 return false;
    1870             :             }
    1871          42 :             ip_addr = inet6_prefix.ip6_addr();
    1872          42 :             prefix_len = inet6_prefix.prefixlen();
    1873             :         }
    1874             :     }
    1875             : 
    1876             :     bool subscribe_pending;
    1877             :     int instance_id;
    1878             :     uint64_t subscription_gen_id;
    1879             :     BgpTable *table;
    1880        5536 :     if (!VerifyMembership(vrf_name, Address::EVPN, &table, &instance_id,
    1881             :         &subscription_gen_id, &subscribe_pending, add_change)) {
    1882          13 :         channel_->Close();
    1883          13 :         return false;
    1884             :     }
    1885             : 
    1886        5525 :     RouteDistinguisher rd;
    1887        5525 :     if (mac_addr.IsBroadcast()) {
    1888         710 :         rd = RouteDistinguisher(peer_->bgp_identifier(), instance_id);
    1889        4815 :     } else if (type6) {
    1890          72 :         rd = RouteDistinguisher(bgp_server_->bgp_identifier(),
    1891          72 :                                 table->routing_instance()->index());
    1892             :     } else {
    1893        4779 :         rd = RouteDistinguisher::kZeroRd;
    1894             :     }
    1895             : 
    1896        5525 :     uint32_t ethernet_tag = item.entry.nlri.ethernet_tag;
    1897             :     EvpnPrefix evpn_prefix = type6 ?
    1898             :         EvpnPrefix(rd, ethernet_tag, source, group,
    1899          36 :                    Ip4Address(bgp_server_->bgp_identifier())) :
    1900             :         type2 ? EvpnPrefix(rd, ethernet_tag, mac_addr, ip_addr) :
    1901        5561 :         EvpnPrefix(rd, ip_addr, prefix_len);
    1902             : 
    1903        5525 :     DBRequest req;
    1904        5525 :     ExtCommunitySpec ext;
    1905        5525 :     LargeCommunitySpec largecomm;
    1906        5524 :     req.key.reset(new EvpnTable::RequestKey(evpn_prefix, peer_.get()));
    1907             : 
    1908        5523 :     IpAddress nh_address(Ip4Address(0));
    1909        5523 :     uint32_t label = 0;
    1910        5523 :     uint32_t l3_label = 0;
    1911        5523 :     uint32_t flags = 0;
    1912             : 
    1913        5523 :     if (add_change) {
    1914        4375 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1915        4375 :         BgpAttrSpec attrs;
    1916        4375 :         const EnetNextHopListType &inh_list = item.entry.next_hops;
    1917             : 
    1918        4375 :         if (inh_list.next_hop.empty()) {
    1919           2 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1920             :                 BGP_LOG_FLAG_ALL, "Missing next-hops for enet route " <<
    1921             :                                   evpn_prefix.ToXmppIdString());
    1922           1 :             return false;
    1923             :         }
    1924             : 
    1925             :         // Agents should send only one next-hop in the item.
    1926        4374 :         if (inh_list.next_hop.size() != 1) {
    1927           0 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1928             :                 BGP_LOG_FLAG_ALL,
    1929             :                 "More than one nexthop received for enet route " <<
    1930             :                 evpn_prefix.ToXmppIdString());
    1931           0 :             return false;
    1932             :         }
    1933             : 
    1934        4374 :         EnetNextHopListType::const_iterator nit = inh_list.begin();
    1935             : 
    1936        4374 :         IpAddress nhop_address(Ip4Address(0));
    1937             : 
    1938        4374 :         if (!XmppDecodeAddress(nit->af, nit->address, &nhop_address)) {
    1939           4 :             BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1940             :                 BGP_LOG_FLAG_ALL, "Bad nexthop address " << nit->address <<
    1941             :                 " for enet route " << evpn_prefix.ToXmppIdString());
    1942           2 :             return false;
    1943             :         }
    1944             : 
    1945        4372 :         nh_address = nhop_address;
    1946        4372 :         label = nit->label;
    1947        4372 :         l3_label = nit->l3_label;
    1948        4372 :         if (!nit->mac.empty()) {
    1949             :             MacAddress rmac_addr =
    1950          10 :                 MacAddress::FromString(nit->mac, &error);
    1951          10 :             if (error) {
    1952           0 :                 BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    1953             :                     BGP_LOG_FLAG_ALL,
    1954             :                     "Bad next-hop mac address " << nit->mac <<
    1955             :                     " for enet route " << evpn_prefix.ToXmppIdString());
    1956           0 :                 return false;
    1957             :             }
    1958          10 :             RouterMac router_mac(rmac_addr);
    1959          10 :             ext.communities.push_back(router_mac.GetExtCommunityValue());
    1960             :         }
    1961             : 
    1962             :         // Process tunnel encapsulation list.
    1963        4372 :         bool no_tunnel_encap = true;
    1964        4372 :         bool no_valid_tunnel_encap = true;
    1965        4372 :         for (EnetTunnelEncapsulationListType::const_iterator eit =
    1966        4372 :             nit->tunnel_encapsulation_list.begin();
    1967        8744 :             eit != nit->tunnel_encapsulation_list.end(); ++eit) {
    1968        4372 :             no_tunnel_encap = false;
    1969        4372 :             TunnelEncap tun_encap(*eit);
    1970        4372 :             if (tun_encap.tunnel_encap() == TunnelEncapType::UNSPEC)
    1971           0 :                 continue;
    1972        4372 :             no_valid_tunnel_encap = false;
    1973        4372 :             ext.communities.push_back(tun_encap.GetExtCommunityValue());
    1974        4372 :             if (tun_encap.tunnel_encap() == TunnelEncapType::GRE) {
    1975        4326 :                 TunnelEncap alt_tun_encap(TunnelEncapType::MPLS_O_GRE);
    1976        4326 :                 ext.communities.push_back(alt_tun_encap.GetExtCommunityValue());
    1977             :             }
    1978             :         }
    1979             : 
    1980             :         // Mark the path as infeasible if all tunnel encaps published
    1981             :         // by agent are invalid.
    1982        4372 :         if (!no_tunnel_encap && no_valid_tunnel_encap) {
    1983           0 :             flags = BgpPath::NoTunnelEncap;
    1984             :         }
    1985             : 
    1986             :         // Process tags list.
    1987        4372 :         uint64_t tag_val = 0;
    1988        4372 :         for (TagListType::const_iterator tit = nit->tag_list.begin();
    1989        4376 :             tit != nit->tag_list.end(); ++tit) {
    1990           4 :             tag_val = nit->is_new_tags_list ? *tit :
    1991           4 :                 ((0x0000FFFF0000 & *tit) << 16) |
    1992           4 :                 (0x00000000FFFF & *tit);
    1993           4 :             TagLC tag_lc(bgp_server_->autonomous_system(), tag_val);
    1994          16 :             for (const auto &value_data : tag_lc.GetLargeCommunityValue()) {
    1995          12 :                 largecomm.communities.push_back(value_data);
    1996           4 :             }
    1997             :         }
    1998             : 
    1999             :         // Process local sequence_number
    2000        4372 :         if (nit->local_sequence_number) {
    2001           0 :             LocalSequenceNumber lsn (nit->local_sequence_number);
    2002           0 :             ext.communities.push_back(lsn.GetExtCommunityValue());
    2003             :         }
    2004             : 
    2005        4372 :         BgpAttrLocalPref local_pref(item.entry.local_preference);
    2006        4372 :         if (local_pref.local_pref != 0) {
    2007        4372 :             attrs.push_back(&local_pref);
    2008             :         }
    2009             : 
    2010             :         // If there's no explicit med, calculate it automatically from the
    2011             :         // local pref.
    2012        4372 :         uint32_t med_value = item.entry.med;
    2013        4372 :         if (!med_value)
    2014        4372 :             med_value = GetMedFromLocalPref(local_pref.local_pref);
    2015        4372 :         BgpAttrMultiExitDisc med(med_value);
    2016        4372 :         if (med.med != 0)
    2017        4372 :             attrs.push_back(&med);
    2018             : 
    2019        4372 :         BgpAttrNextHop nexthop(nh_address.to_v4().to_ulong());
    2020        4371 :         if (type6) {
    2021          36 :             flags |= BgpPath::CheckGlobalErmVpnRoute;
    2022          72 :             if (item.entry.replicator_address.empty() &&
    2023          36 :                     item.entry.edge_replication_not_supported) {
    2024             :                 // Only for test to inject remote smet routes
    2025           0 :                 flags &= ~BgpPath::CheckGlobalErmVpnRoute;
    2026           0 :                 attrs.push_back(&nexthop);
    2027             :             }
    2028             :         } else {
    2029        4335 :             attrs.push_back(&nexthop);
    2030             :         }
    2031             : 
    2032        4372 :         uint16_t cluster_seed = bgp_server_->global_config()->rd_cluster_seed();
    2033        4372 :         BgpAttrSourceRd source_rd;
    2034        4371 :         if (cluster_seed) {
    2035           0 :             source_rd = BgpAttrSourceRd(RouteDistinguisher(cluster_seed,
    2036           0 :                 nh_address.to_v4().to_ulong(), instance_id));
    2037             :         } else {
    2038        8743 :             source_rd = BgpAttrSourceRd(RouteDistinguisher(
    2039       13115 :                 nh_address.to_v4().to_ulong(), instance_id));
    2040             :         }
    2041        4372 :         attrs.push_back(&source_rd);
    2042             : 
    2043             :         // Process security group list.
    2044        4372 :         const EnetSecurityGroupListType &isg_list =
    2045             :             item.entry.security_group_list;
    2046        4372 :         uint16_t sg_index = 0;
    2047        4372 :         for (EnetSecurityGroupListType::const_iterator sit = isg_list.begin();
    2048        8748 :             sit != isg_list.end(); ++sit) {
    2049        4376 :             if (bgp_server_->autonomous_system() <= AS2_MAX) {
    2050        4376 :                 SecurityGroup sg(bgp_server_->autonomous_system(), *sit);
    2051        4376 :                 ext.communities.push_back(sg.GetExtCommunityValue());
    2052             :             } else {
    2053           0 :                 SecurityGroup sg(sg_index, *sit);
    2054           0 :                 SecurityGroup4ByteAs sg4(bgp_server_->autonomous_system(),
    2055           0 :                                              sg_index++);
    2056           0 :                 ext.communities.push_back(sg4.GetExtCommunityValue());
    2057           0 :                 ext.communities.push_back(sg.GetExtCommunityValue());
    2058             :             }
    2059             :         }
    2060             : 
    2061        4372 :         if (item.entry.mobility.seqno) {
    2062           6 :             MacMobility mm(item.entry.mobility.seqno,
    2063           6 :                 item.entry.mobility.sticky);
    2064           6 :             ext.communities.push_back(mm.GetExtCommunityValue());
    2065        4366 :         } else if (item.entry.sequence_number) {
    2066           2 :             MacMobility mm(item.entry.sequence_number);
    2067           2 :             ext.communities.push_back(mm.GetExtCommunityValue());
    2068             :         }
    2069             : 
    2070        4372 :         ETree etree(item.entry.etree_leaf);
    2071        4372 :         ext.communities.push_back(etree.GetExtCommunityValue());
    2072             : 
    2073        4372 :         if (!ext.communities.empty())
    2074        4372 :             attrs.push_back(&ext);
    2075        4371 :         if (!largecomm.communities.empty())
    2076           2 :             attrs.push_back(&largecomm);
    2077             : 
    2078        4371 :         PmsiTunnelSpec pmsi_spec;
    2079        4371 :         if (mac_addr.IsBroadcast()) {
    2080         355 :             if (!item.entry.replicator_address.empty()) {
    2081           4 :                 IpAddress replicator_address;
    2082           4 :                 if (!XmppDecodeAddress(BgpAf::IPv4,
    2083             :                     item.entry.replicator_address, &replicator_address)) {
    2084           4 :                     BGP_LOG_PEER_INSTANCE_WARNING(Peer(), vrf_name,
    2085             :                         BGP_LOG_FLAG_ALL,
    2086             :                         "Bad replicator address " <<
    2087             :                         item.entry.replicator_address <<
    2088             :                         " for enet route " << evpn_prefix.ToXmppIdString());
    2089           2 :                     return false;
    2090             :                 }
    2091           2 :                 pmsi_spec.tunnel_type =
    2092             :                     PmsiTunnelSpec::AssistedReplicationContrail;
    2093           2 :                 pmsi_spec.tunnel_flags = PmsiTunnelSpec::ARLeaf;
    2094           2 :                 pmsi_spec.SetIdentifier(replicator_address.to_v4());
    2095             :             } else {
    2096         351 :                 pmsi_spec.tunnel_type = PmsiTunnelSpec::IngressReplication;
    2097         351 :                 if (item.entry.assisted_replication_supported) {
    2098           0 :                     pmsi_spec.tunnel_flags |= PmsiTunnelSpec::ARReplicator;
    2099           0 :                     pmsi_spec.tunnel_flags |= PmsiTunnelSpec::LeafInfoRequired;
    2100             :                 }
    2101         351 :                 if (!item.entry.edge_replication_not_supported) {
    2102         175 :                     pmsi_spec.tunnel_flags |=
    2103             :                         PmsiTunnelSpec::EdgeReplicationSupported;
    2104             :                 }
    2105         351 :                 pmsi_spec.SetIdentifier(nh_address.to_v4());
    2106             :             }
    2107         354 :             ExtCommunity ext_comm(bgp_server_->extcomm_db(), ext);
    2108         354 :             pmsi_spec.SetLabel(label, &ext_comm);
    2109         353 :             attrs.push_back(&pmsi_spec);
    2110         353 :         }
    2111             : 
    2112        4370 :         BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attrs);
    2113             : 
    2114        4370 :         req.data.reset(new EvpnTable::RequestData(
    2115        4370 :             attr, flags, label, l3_label, subscription_gen_id));
    2116        4370 :         stats_[RX].reach++;
    2117        4385 :     } else {
    2118        1148 :         req.oper = DBRequest::DB_ENTRY_DELETE;
    2119        1148 :         stats_[RX].unreach++;
    2120             :     }
    2121             : 
    2122             :     // Defer all requests till subscribe is processed.
    2123        5519 :     if (subscribe_pending) {
    2124         403 :         DBRequest *request_entry = new DBRequest();
    2125         403 :         request_entry->Swap(&req);
    2126             :         string table_name =
    2127         403 :             RoutingInstance::GetTableName(vrf_name, Address::EVPN);
    2128         403 :         defer_q_.insert(make_pair(
    2129         806 :             make_pair(vrf_name, table_name), request_entry));
    2130         403 :         return true;
    2131         403 :     }
    2132             : 
    2133        5116 :     assert(table);
    2134        9560 :     BGP_LOG_PEER_INSTANCE(Peer(), vrf_name,
    2135             :         SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
    2136             :         "Enet route " << evpn_prefix.ToXmppIdString() <<
    2137             :         " with next-hop " << nh_address <<
    2138             :         " label " << label << " l3-label " << l3_label <<
    2139             :         " enqueued for " << (add_change ? "add/change" : "delete"));
    2140        5116 :     table->Enqueue(&req);
    2141        5117 :     return true;
    2142        5546 : }
    2143             : 
    2144        1010 : void BgpXmppChannel::DequeueRequest(const string &table_name,
    2145             :                                     DBRequest *request) {
    2146        1010 :     unique_ptr<DBRequest> ptr(request);
    2147             : 
    2148             :     BgpTable *table = static_cast<BgpTable *>
    2149        1010 :         (bgp_server_->database()->FindTable(table_name));
    2150        1010 :     if (table == NULL || table->IsDeleted()) {
    2151           5 :         return;
    2152             :     }
    2153             : 
    2154        1005 :     BgpMembershipManager *mgr = bgp_server_->membership_mgr();
    2155        1005 :     if (mgr) {
    2156        1005 :         int instance_id = -1;
    2157        1005 :         uint64_t subscription_gen_id = 0;
    2158        1005 :         bool is_registered = mgr->GetRegistrationInfo(peer_.get(), table,
    2159             :                                             &instance_id, &subscription_gen_id);
    2160        1005 :         if (!is_registered) {
    2161           0 :             BGP_LOG_PEER_WARNING(Membership, Peer(),
    2162             :                 BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2163             :                 "Not subscribed to table " << table->name());
    2164           0 :             return;
    2165             :         }
    2166        1005 :         if (ptr->oper == DBRequest::DB_ENTRY_ADD_CHANGE) {
    2167        1003 :             ((BgpTable::RequestData *)ptr->data.get())
    2168        1003 :                 ->set_subscription_gen_id(subscription_gen_id);
    2169             :         }
    2170             :     }
    2171             : 
    2172        1005 :     table->Enqueue(ptr.get());
    2173        1010 : }
    2174             : 
    2175          86 : bool BgpXmppChannel::ResumeClose() {
    2176          86 :     peer_->Close(true);
    2177          87 :     return true;
    2178             : }
    2179             : 
    2180       68864 : void BgpXmppChannel::RegisterTable(int line, BgpTable *table,
    2181             :     const TableMembershipRequestState *tmr_state) {
    2182             :     // Defer if Membership manager is in use (by close manager).
    2183       68864 :     if (close_manager_->IsMembershipInUse()) {
    2184         276 :         BGP_LOG_PEER_TABLE(Peer(), SandeshLevel::SYS_DEBUG,
    2185             :                            BGP_LOG_FLAG_ALL, table, "RegisterTable deferred "
    2186             :                            "from :" << line);
    2187          92 :         return;
    2188             :     }
    2189             : 
    2190       68772 :     BgpMembershipManager *mgr = bgp_server_->membership_mgr();
    2191       85071 :     BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
    2192             :                  BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2193             :                  "Subscribe to table " << table->name() <<
    2194             :                  (tmr_state->no_ribout ? " (no ribout)" : "") <<
    2195             :                  " with id " << tmr_state->instance_id);
    2196       68772 :     if (tmr_state->no_ribout) {
    2197          56 :         mgr->RegisterRibIn(peer_.get(), table);
    2198          56 :         mgr->SetRegistrationInfo(peer_.get(), table, tmr_state->instance_id,
    2199          56 :             manager_->get_subscription_gen_id());
    2200          56 :         channel_stats_.table_subscribe++;
    2201          56 :         MembershipRequestCallback(table);
    2202             :     } else {
    2203       68716 :         mgr->Register(peer_.get(), table, bgp_policy_, tmr_state->instance_id);
    2204       68716 :         channel_stats_.table_subscribe++;
    2205             :     }
    2206             : 
    2207             :     // If EndOfRib Send timer is running, cancel it and reschedule it after all
    2208             :     // outstanding membership registrations are complete.
    2209       68772 :     if (eor_send_timer_->running())
    2210       13595 :         eor_send_timer_->Cancel();
    2211             : }
    2212             : 
    2213        4468 : void BgpXmppChannel::UnregisterTable(int line, BgpTable *table) {
    2214             :     // Defer if Membership manager is in use (by close manager).
    2215        4468 :     if (close_manager_->IsMembershipInUse()) {
    2216         948 :         BGP_LOG_PEER_TABLE(Peer(), SandeshLevel::SYS_DEBUG,
    2217             :                            BGP_LOG_FLAG_ALL, table, "UnregisterTable deferred "
    2218             :                            "from :" << line);
    2219         316 :         return;
    2220             :     }
    2221             : 
    2222        4152 :     BgpMembershipManager *mgr = bgp_server_->membership_mgr();
    2223        5729 :     BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
    2224             :                  BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2225             :                  "Unsubscribe to table " << table->name());
    2226        4152 :     mgr->Unregister(peer_.get(), table);
    2227        4152 :     channel_stats_.table_unsubscribe++;
    2228             : }
    2229             : 
    2230             : #define RegisterTable(table, tmr_state) \
    2231             :     RegisterTable(__LINE__, table, tmr_state)
    2232             : #define UnregisterTable(table) UnregisterTable(__LINE__, table)
    2233             : 
    2234             : // Process all pending membership requests of various tables.
    2235         264 : void BgpXmppChannel::ProcessPendingSubscriptions() {
    2236         264 :     assert(!close_manager_->IsMembershipInUse());
    2237        1080 :     BOOST_FOREACH(TableMembershipRequestMap::value_type &entry,
    2238             :                   table_membership_request_map_) {
    2239             :         BgpTable *table = static_cast<BgpTable *>(
    2240         408 :             bgp_server_->database()->FindTable(entry.first));
    2241         408 :         const TableMembershipRequestState &tmr_state = entry.second;
    2242         408 :         if (tmr_state.current_req == SUBSCRIBE) {
    2243          92 :             RegisterTable(table, &tmr_state);
    2244             :         } else {
    2245         316 :             assert(tmr_state.current_req == UNSUBSCRIBE);
    2246         316 :             UnregisterTable(table);
    2247             :         }
    2248             :     }
    2249         264 : }
    2250             : 
    2251       10813 : size_t BgpXmppChannel::table_membership_requests() const {
    2252       10813 :     return table_membership_request_map_.size();
    2253             : }
    2254             : 
    2255      141039 : bool BgpXmppChannel::MembershipResponseHandler(string table_name) {
    2256      141039 :     if (close_manager_->IsMembershipInUse()) {
    2257       68108 :         close_manager_->MembershipRequestCallback();
    2258       68312 :         return true;
    2259             :     }
    2260             : 
    2261             :     TableMembershipRequestState *tmr_state =
    2262       72917 :         GetTableMembershipState(table_name);
    2263       72915 :     if (!tmr_state) {
    2264           0 :         BGP_LOG_PEER_INSTANCE_CRITICAL(Peer(), table_name,
    2265             :                      BGP_PEER_DIR_IN, BGP_LOG_FLAG_ALL,
    2266             :                      "Table not in subscribe/unsubscribe request queue");
    2267           0 :         assert(false);
    2268             :     }
    2269             : 
    2270       72915 :     if (tmr_state->current_req == SUBSCRIBE) {
    2271       85062 :         BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
    2272             :                      BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2273             :                      "Subscribe to table " << table_name << " completed");
    2274       68766 :         channel_stats_.table_subscribe_complete++;
    2275             :     } else {
    2276        5729 :         BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
    2277             :                      BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2278             :                      "Unsubscribe to table " << table_name << " completed");
    2279        4152 :         channel_stats_.table_unsubscribe_complete++;
    2280             :     }
    2281             : 
    2282       72924 :     if (defer_peer_close_) {
    2283         641 :         DeleteTableMembershipState(table_name);
    2284         640 :         if (table_membership_requests())
    2285         554 :             return true;
    2286          86 :         defer_peer_close_ = false;
    2287          86 :         ResumeClose();
    2288             :     } else {
    2289       72283 :         ProcessMembershipResponse(table_name, tmr_state);
    2290             :     }
    2291             : 
    2292       72366 :     assert(channel_stats_.table_subscribe_complete <=
    2293             :                channel_stats_.table_subscribe);
    2294       72366 :     assert(channel_stats_.table_unsubscribe_complete <=
    2295             :                channel_stats_.table_unsubscribe);
    2296             : 
    2297             :     // Restart EndOfRib send if necessary.
    2298       72366 :     ResetEndOfRibSendState();
    2299             : 
    2300             :     // If Close manager is waiting to use membership, try now.
    2301       72366 :     if (close_manager_->IsMembershipInWait())
    2302          36 :         close_manager_->MembershipRequest();
    2303             : 
    2304       72366 :     return true;
    2305             : }
    2306             : 
    2307       72280 : bool BgpXmppChannel::ProcessMembershipResponse(string table_name,
    2308             :     TableMembershipRequestState *tmr_state) {
    2309             :     BgpTable *table = static_cast<BgpTable *>
    2310       72280 :         (bgp_server_->database()->FindTable(table_name));
    2311       72278 :     if (!table) {
    2312         137 :         DeleteTableMembershipState(table_name);
    2313         137 :         return true;
    2314             :     }
    2315       72141 :     BgpMembershipManager *mgr = bgp_server_->membership_mgr();
    2316             : 
    2317       72141 :     if ((tmr_state->current_req == UNSUBSCRIBE) &&
    2318        3908 :         (tmr_state->pending_req == SUBSCRIBE)) {
    2319             :         // Process pending subscribe now that unsubscribe has completed.
    2320          29 :         tmr_state->current_req = SUBSCRIBE;
    2321          29 :         RegisterTable(table, tmr_state);
    2322          29 :         return true;
    2323       72112 :     } else if ((tmr_state->current_req == SUBSCRIBE) &&
    2324       68233 :                (tmr_state->pending_req == UNSUBSCRIBE)) {
    2325             :         // Process pending unsubscribe now that subscribe has completed.
    2326          49 :         tmr_state->current_req = UNSUBSCRIBE;
    2327          49 :         UnregisterTable(table);
    2328          49 :         return true;
    2329      212315 :     } else if ((tmr_state->current_req == SUBSCRIBE) &&
    2330      140252 :         (tmr_state->pending_req == SUBSCRIBE) &&
    2331       68184 :         (mgr->IsRibOutRegistered(peer_.get(), table) == tmr_state->no_ribout)) {
    2332             :         // Trigger an unsubscribe so that we can subsequently subscribe with
    2333             :         // the updated value of no_ribout.
    2334          23 :         tmr_state->current_req = UNSUBSCRIBE;
    2335          23 :         UnregisterTable(table);
    2336          23 :         return true;
    2337             :     }
    2338             : 
    2339       72045 :     string vrf_name = table->routing_instance()->name();
    2340       72043 :     VrfTableName vrf_n_table = make_pair(vrf_name, table->name());
    2341             : 
    2342       72041 :     if (tmr_state->pending_req == UNSUBSCRIBE) {
    2343        3879 :         if (!GetInstanceMembershipState(vrf_name))
    2344        3878 :             assert(defer_q_.count(vrf_n_table) == 0);
    2345        3879 :         DeleteTableMembershipState(table_name);
    2346        3879 :         return true;
    2347       68162 :     } else if (tmr_state->pending_req == SUBSCRIBE) {
    2348       68166 :         mgr->SetRegistrationInfo(peer_.get(), table, tmr_state->instance_id,
    2349       68162 :             manager_->get_subscription_gen_id());
    2350       68165 :         DeleteTableMembershipState(table_name);
    2351             :     }
    2352             : 
    2353       68161 :     for (DeferQ::iterator it = defer_q_.find(vrf_n_table);
    2354       69170 :          it != defer_q_.end() && it->first.second == table->name(); ++it) {
    2355        1010 :         DequeueRequest(table->name(), it->second);
    2356             :     }
    2357             : 
    2358             :     // Erase all elements for the table
    2359       68161 :     defer_q_.erase(vrf_n_table);
    2360             : 
    2361       68161 :     return true;
    2362       72040 : }
    2363             : 
    2364      141229 : void BgpXmppChannel::MembershipRequestCallback(BgpTable *table) {
    2365      141229 :     membership_response_worker_.Enqueue(table->name());
    2366      141229 : }
    2367             : 
    2368         487 : void BgpXmppChannel::FillCloseInfo(BgpNeighborResp *resp) const {
    2369         487 :     close_manager_->FillCloseInfo(resp);
    2370         487 : }
    2371             : 
    2372         487 : void BgpXmppChannel::FillInstanceMembershipInfo(BgpNeighborResp *resp) const {
    2373         487 :     vector<BgpNeighborRoutingInstance> instance_list;
    2374        4287 :     BOOST_FOREACH(const SubscribedRoutingInstanceList::value_type &entry,
    2375             :         routing_instances_) {
    2376        1900 :         BgpNeighborRoutingInstance instance;
    2377        1900 :         instance.set_name(entry.first->name());
    2378        1900 :         if (entry.second.IsLlgrStale()) {
    2379           0 :             instance.set_state("subscribed-llgr-stale");
    2380        1900 :         } else if (entry.second.IsGrStale()) {
    2381           0 :             instance.set_state("subscribed-gr-stale");
    2382             :         } else {
    2383        1900 :             instance.set_state("subscribed");
    2384             :         }
    2385        1900 :         instance.set_index(entry.second.index);
    2386        1900 :         rtarget_manager_->FillInfo(&instance, entry.second.targets);
    2387        1900 :         instance_list.push_back(instance);
    2388        1900 :     }
    2389         487 :     BOOST_FOREACH(const InstanceMembershipRequestMap::value_type &entry,
    2390             :         instance_membership_request_map_) {
    2391           0 :         const InstanceMembershipRequestState &imr_state = entry.second;
    2392           0 :         BgpNeighborRoutingInstance instance;
    2393           0 :         instance.set_name(entry.first);
    2394           0 :         instance.set_state("pending");
    2395           0 :         instance.set_index(imr_state.instance_id);
    2396           0 :         instance_list.push_back(instance);
    2397           0 :     }
    2398         487 :     resp->set_routing_instances(instance_list);
    2399         487 : }
    2400             : 
    2401         487 : void BgpXmppChannel::FillTableMembershipInfo(BgpNeighborResp *resp) const {
    2402         487 :     vector<BgpNeighborRoutingTable> old_table_list = resp->get_routing_tables();
    2403         487 :     set<string> old_table_set;
    2404         487 :     vector<BgpNeighborRoutingTable> new_table_list;
    2405             : 
    2406       19487 :     BOOST_FOREACH(const BgpNeighborRoutingTable &table, old_table_list) {
    2407        9500 :         old_table_set.insert(table.get_name());
    2408        9500 :         if (!GetTableMembershipState(table.get_name()))
    2409        9500 :             new_table_list.push_back(table);
    2410             :     }
    2411             : 
    2412         487 :     BOOST_FOREACH(const TableMembershipRequestMap::value_type &entry,
    2413             :         table_membership_request_map_) {
    2414           0 :         BgpNeighborRoutingTable table;
    2415           0 :         table.set_name(entry.first);
    2416           0 :         if (old_table_set.find(entry.first) != old_table_set.end())
    2417           0 :             table.set_current_state("subscribed");
    2418           0 :         const TableMembershipRequestState &tmr_state = entry.second;
    2419           0 :         if (tmr_state.current_req == SUBSCRIBE) {
    2420           0 :             table.set_current_request("subscribe");
    2421             :         } else {
    2422           0 :             table.set_current_request("unsubscribe");
    2423             :         }
    2424           0 :         if (tmr_state.pending_req == SUBSCRIBE) {
    2425           0 :             table.set_pending_request("subscribe");
    2426             :         } else {
    2427           0 :             table.set_pending_request("unsubscribe");
    2428             :         }
    2429           0 :         new_table_list.push_back(table);
    2430           0 :     }
    2431         487 :     resp->set_routing_tables(new_table_list);
    2432         487 : }
    2433             : 
    2434             : //
    2435             : // Erase all defer_q_ elements with the given (vrf, table).
    2436             : //
    2437          20 : void BgpXmppChannel::FlushDeferQ(string vrf_name, string table_name) {
    2438          20 :     for (DeferQ::iterator it =
    2439          20 :         defer_q_.find(make_pair(vrf_name, table_name)), itnext;
    2440          59 :         (it != defer_q_.end() && it->first.second == table_name);
    2441          39 :         it = itnext) {
    2442          39 :         itnext = it;
    2443          39 :         itnext++;
    2444          39 :         delete it->second;
    2445          39 :         defer_q_.erase(it);
    2446             :     }
    2447          20 : }
    2448             : 
    2449             : //
    2450             : // Erase all defer_q_ elements for all tables for the given vrf.
    2451             : //
    2452          10 : void BgpXmppChannel::FlushDeferQ(string vrf_name) {
    2453          10 :     for (DeferQ::iterator it =
    2454          10 :         defer_q_.lower_bound(make_pair(vrf_name, string())), itnext;
    2455          25 :         (it != defer_q_.end() && it->first.first == vrf_name);
    2456          15 :         it = itnext) {
    2457          15 :         itnext = it;
    2458          15 :         itnext++;
    2459          15 :         delete it->second;
    2460          15 :         defer_q_.erase(it);
    2461             :     }
    2462          10 : }
    2463             : 
    2464             : // Mark all current subscriptions as 'stale'. This is called when peer close
    2465             : // process is initiated by BgpXmppChannel via PeerCloseManager.
    2466         195 : void BgpXmppChannel::StaleCurrentSubscriptions() {
    2467         195 :     CHECK_CONCURRENCY(peer_close_->GetTaskName());
    2468        1675 :     BOOST_FOREACH(SubscribedRoutingInstanceList::value_type &entry,
    2469             :                   routing_instances_) {
    2470         740 :         entry.second.SetGrStale();
    2471         740 :         rtarget_manager_->UpdateRouteTargetRouteFlag(entry.first,
    2472         740 :                 entry.second.targets, BgpPath::Stale);
    2473             :     }
    2474         195 : }
    2475             : 
    2476             : // Mark all current subscriptions as 'llgr_stale'.
    2477          29 : void BgpXmppChannel::LlgrStaleCurrentSubscriptions() {
    2478          29 :     CHECK_CONCURRENCY(peer_close_->GetTaskName());
    2479         271 :     BOOST_FOREACH(SubscribedRoutingInstanceList::value_type &entry,
    2480             :                   routing_instances_) {
    2481         121 :         assert(entry.second.IsGrStale());
    2482         121 :         entry.second.SetLlgrStale();
    2483         121 :         rtarget_manager_->UpdateRouteTargetRouteFlag(entry.first,
    2484         121 :                 entry.second.targets, BgpPath::Stale | BgpPath::LlgrStale);
    2485             :     }
    2486          29 : }
    2487             : 
    2488             : // Sweep all current subscriptions which are still marked as 'stale'.
    2489          40 : void BgpXmppChannel::SweepCurrentSubscriptions() {
    2490          40 :     CHECK_CONCURRENCY(peer_close_->GetTaskName());
    2491          40 :     for (SubscribedRoutingInstanceList::iterator i = routing_instances_.begin();
    2492         216 :             i != routing_instances_.end();) {
    2493         176 :         if (i->second.IsGrStale()) {
    2494          68 :             string name = i->first->name();
    2495             : 
    2496             :             // Increment the iterator first as we expect the entry to be
    2497             :             // soon removed.
    2498          68 :             i++;
    2499         136 :             BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
    2500             :                          BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2501             :                          "Instance subscription " << name <<
    2502             :                          " is still stale and hence unsubscribed");
    2503          68 :             ProcessSubscriptionRequest(name, NULL, false);
    2504          68 :         } else {
    2505         108 :             i++;
    2506             :         }
    2507             :     }
    2508          40 : }
    2509             : 
    2510             : // Clear staled subscription state as new subscription has been received.
    2511         252 : void BgpXmppChannel::ClearStaledSubscription(RoutingInstance *rt_instance,
    2512             :         SubscriptionState *sub_state) {
    2513         252 :     if (!sub_state->IsGrStale())
    2514           0 :         return;
    2515             : 
    2516         504 :     BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
    2517             :                  BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2518             :                  "Instance subscription " << rt_instance->name() <<
    2519             :                  " stale flag is cleared");
    2520         252 :     sub_state->ClearStale();
    2521         252 :     rtarget_manager_->Stale(sub_state->targets);
    2522             : }
    2523             : 
    2524       14231 : void BgpXmppChannel::AddSubscriptionState(RoutingInstance *rt_instance,
    2525             :         int index) {
    2526       14231 :     SubscriptionState state(rt_instance->GetImportList(), index);
    2527             :     pair<SubscribedRoutingInstanceList::iterator, bool> ret =
    2528       14231 :         routing_instances_.insert(pair<RoutingInstance *, SubscriptionState> (
    2529             :                                       rt_instance, state));
    2530             : 
    2531             :     // During GR, we expect duplicate subscription requests. Clear stale
    2532             :     // state, as agent did re-subscribe after restart.
    2533       14231 :     if (!ret.second) {
    2534         252 :         ClearStaledSubscription(rt_instance, &ret.first->second);
    2535             :     } else {
    2536       13979 :         rtarget_manager_->PublishRTargetRoute(rt_instance, true);
    2537             :     }
    2538       14231 : }
    2539             : 
    2540         898 : void BgpXmppChannel::DeleteSubscriptionState(RoutingInstance *rt_instance) {
    2541         898 :     routing_instances_.erase(rt_instance);
    2542         898 : }
    2543             : 
    2544       17236 : BgpXmppChannel::SubscriptionState *BgpXmppChannel::GetSubscriptionState(
    2545             :     RoutingInstance *rt_instance) {
    2546             :     SubscribedRoutingInstanceList::iterator loc =
    2547       17236 :         routing_instances_.find(rt_instance);
    2548       17236 :     return (loc != routing_instances_.end() ? &loc->second : NULL);
    2549             : }
    2550             : 
    2551           0 : const BgpXmppChannel::SubscriptionState *BgpXmppChannel::GetSubscriptionState(
    2552             :     RoutingInstance *rt_instance) const {
    2553             :     SubscribedRoutingInstanceList::const_iterator loc =
    2554           0 :         routing_instances_.find(rt_instance);
    2555           0 :     return (loc != routing_instances_.end() ? &loc->second : NULL);
    2556             : }
    2557             : 
    2558          31 : void BgpXmppChannel::ProcessDeferredSubscribeRequest(RoutingInstance *instance,
    2559             :     const InstanceMembershipRequestState &imr_state) {
    2560          31 :     int instance_id = imr_state.instance_id;
    2561          31 :     bool no_ribout = imr_state.no_ribout;
    2562          31 :     AddSubscriptionState(instance, instance_id);
    2563          31 :     RoutingInstance::RouteTableList const rt_list = instance->GetTables();
    2564          31 :     for (RoutingInstance::RouteTableList::const_iterator it = rt_list.begin();
    2565         186 :          it != rt_list.end(); ++it) {
    2566         155 :         BgpTable *table = it->second;
    2567         155 :         if (table->IsVpnTable() || table->family() == Address::RTARGET)
    2568           0 :             continue;
    2569             : 
    2570             :         TableMembershipRequestState tmr_state(
    2571         155 :             SUBSCRIBE, instance_id, no_ribout);
    2572         155 :         AddTableMembershipState(table->name(), tmr_state);
    2573         155 :         RegisterTable(table, &tmr_state);
    2574             :     }
    2575          31 : }
    2576             : 
    2577       15284 : void BgpXmppChannel::ProcessSubscriptionRequest(
    2578             :         string vrf_name, const XmppStanza::XmppMessageIq *iq,
    2579             :         bool add_change) {
    2580       15284 :     int instance_id = -1;
    2581       15284 :     bool no_ribout = false;
    2582             : 
    2583       15284 :     if (add_change) {
    2584       14354 :         XmlPugi *pugi = reinterpret_cast<XmlPugi *>(iq->dom.get());
    2585       14354 :         xml_node options = pugi->FindNode("options");
    2586       28710 :         for (xml_node node = options.first_child(); node;
    2587       14356 :              node = node.next_sibling()) {
    2588       14356 :             if (strcmp(node.name(), "instance-id") == 0) {
    2589       14342 :                 instance_id = node.text().as_int();
    2590             :             }
    2591       14356 :             if (strcmp(node.name(), "no-ribout") == 0) {
    2592          14 :                 no_ribout = node.text().as_bool();
    2593             :             }
    2594             :         }
    2595             :     }
    2596             : 
    2597       15284 :     RoutingInstanceMgr *instance_mgr = bgp_server_->routing_instance_mgr();
    2598       15284 :     assert(instance_mgr);
    2599       15284 :     RoutingInstance *rt_instance = instance_mgr->GetRoutingInstance(vrf_name);
    2600       15284 :     if (rt_instance == NULL) {
    2601         173 :         BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_INFO,
    2602             :                      BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2603             :                      "Routing instance " << vrf_name <<
    2604             :                      " not found when processing " <<
    2605             :                      (add_change ? "subscribe" : "unsubscribe"));
    2606         145 :         if (add_change) {
    2607         135 :             if (GetInstanceMembershipState(vrf_name)) {
    2608           2 :                 BGP_LOG_PEER_WARNING(Membership, Peer(),
    2609             :                              BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2610             :                              "Duplicate subscribe for routing instance " <<
    2611             :                              vrf_name << ", triggering close");
    2612           1 :                 channel_->Close();
    2613             :             } else {
    2614         134 :                 AddInstanceMembershipState(vrf_name,
    2615             :                     InstanceMembershipRequestState(instance_id, no_ribout));
    2616         134 :                 channel_stats_.instance_subscribe++;
    2617             :             }
    2618             :         } else {
    2619          10 :             if (DeleteInstanceMembershipState(vrf_name)) {
    2620           9 :                 FlushDeferQ(vrf_name);
    2621           9 :                 channel_stats_.instance_unsubscribe++;
    2622             :             } else {
    2623           2 :                 BGP_LOG_PEER_WARNING(Membership, Peer(),
    2624             :                              BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2625             :                              "Spurious unsubscribe for routing instance " <<
    2626             :                              vrf_name << ", triggering close");
    2627           1 :                 channel_->Close();
    2628             :             }
    2629             :         }
    2630         186 :         return;
    2631       15139 :     } else if (rt_instance->deleted()) {
    2632         322 :         BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
    2633             :                      BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2634             :                      "Routing instance " << vrf_name <<
    2635             :                      " is being deleted when processing " <<
    2636             :                      (add_change ? "subscribe" : "unsubscribe"));
    2637         161 :         if (add_change) {
    2638          10 :             if (GetInstanceMembershipState(vrf_name)) {
    2639           2 :                 BGP_LOG_PEER_WARNING(Membership, Peer(),
    2640             :                              BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2641             :                              "Duplicate subscribe for routing instance " <<
    2642             :                              vrf_name << ", triggering close");
    2643           1 :                 channel_->Close();
    2644           9 :             } else if (GetSubscriptionState(rt_instance)) {
    2645           2 :                 BGP_LOG_PEER_WARNING(Membership, Peer(),
    2646             :                              BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2647             :                              "Duplicate subscribe for routing instance " <<
    2648             :                              vrf_name << ", triggering close");
    2649           1 :                 channel_->Close();
    2650             :             } else {
    2651           8 :                 AddInstanceMembershipState(vrf_name,
    2652             :                     InstanceMembershipRequestState(instance_id, no_ribout));
    2653           8 :                 channel_stats_.instance_subscribe++;
    2654             :             }
    2655          10 :             return;
    2656             :         } else {
    2657             :             // If instance is being deleted and agent is trying to unsubscribe
    2658             :             // we need to process the unsubscribe if vrf is not in the request
    2659             :             // map.  This would be the normal case where we wait for agent to
    2660             :             // unsubscribe in order to remove routes added by it.
    2661         151 :             if (DeleteInstanceMembershipState(vrf_name)) {
    2662           1 :                 FlushDeferQ(vrf_name);
    2663           1 :                 channel_stats_.instance_unsubscribe++;
    2664           1 :                 return;
    2665         150 :             } else if (!GetSubscriptionState(rt_instance)) {
    2666           4 :                 BGP_LOG_PEER_WARNING(Membership, Peer(),
    2667             :                              BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2668             :                              "Spurious unsubscribe for routing instance " <<
    2669             :                              vrf_name << ", triggering close");
    2670           2 :                 channel_->Close();
    2671           2 :                 return;
    2672             :             }
    2673         148 :             channel_stats_.instance_unsubscribe++;
    2674             :         }
    2675             :     } else {
    2676       14978 :         if (add_change) {
    2677             :             const SubscriptionState *sub_state =
    2678       14209 :                 GetSubscriptionState(rt_instance);
    2679       14209 :             if (sub_state) {
    2680         261 :                 if (!close_manager_->IsCloseInProgress()) {
    2681           2 :                     BGP_LOG_PEER_WARNING(Membership, Peer(),
    2682             :                                  BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2683             :                                  "Duplicate subscribe for routing instance " <<
    2684             :                                  vrf_name << ", triggering close");
    2685           1 :                     channel_->Close();
    2686           1 :                     return;
    2687             :                 }
    2688         260 :                 if (!sub_state->IsGrStale()) {
    2689          16 :                     BGP_LOG_PEER_WARNING(Membership, Peer(),
    2690             :                                  BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2691             :                                  "Duplicate subscribe for routing instance " <<
    2692             :                                  vrf_name << " under GR, triggering close");
    2693           8 :                     channel_->Close();
    2694           8 :                     return;
    2695             :                 }
    2696             :             }
    2697       14200 :             channel_stats_.instance_subscribe++;
    2698             :         } else {
    2699         769 :             if (!GetSubscriptionState(rt_instance)) {
    2700          26 :                 BGP_LOG_PEER_WARNING(Membership, Peer(),
    2701             :                              BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2702             :                              "Spurious unsubscribe for routing instance " <<
    2703             :                              vrf_name << ", triggering close");
    2704          19 :                 channel_->Close();
    2705          19 :                 return;
    2706             :             }
    2707         750 :             channel_stats_.instance_unsubscribe++;
    2708             :         }
    2709             :     }
    2710             : 
    2711       15098 :     if (add_change) {
    2712       14200 :         AddSubscriptionState(rt_instance, instance_id);
    2713             :     } else  {
    2714         898 :         rtarget_manager_->PublishRTargetRoute(rt_instance, false);
    2715         898 :         DeleteSubscriptionState(rt_instance);
    2716             :     }
    2717             : 
    2718       15098 :     RoutingInstance::RouteTableList const rt_list = rt_instance->GetTables();
    2719       15098 :     for (RoutingInstance::RouteTableList::const_iterator it = rt_list.begin();
    2720       95668 :          it != rt_list.end(); ++it) {
    2721       80570 :         BgpTable *table = it->second;
    2722       80570 :         if (table->IsVpnTable() || table->family() == Address::RTARGET)
    2723        7620 :             continue;
    2724             : 
    2725       72950 :         if (add_change) {
    2726             :             TableMembershipRequestState *tmr_state =
    2727       68688 :                 GetTableMembershipState(table->name());
    2728       68686 :             if (!tmr_state) {
    2729             :                 TableMembershipRequestState tmp_tmr_state(
    2730       68586 :                     SUBSCRIBE, instance_id, no_ribout);
    2731       68586 :                 AddTableMembershipState(table->name(), tmp_tmr_state);
    2732       68588 :                 RegisterTable(table, &tmp_tmr_state);
    2733             :             } else {
    2734         100 :                 tmr_state->instance_id = instance_id;
    2735         100 :                 tmr_state->pending_req = SUBSCRIBE;
    2736         100 :                 tmr_state->no_ribout = no_ribout;
    2737             :             }
    2738             :         } else {
    2739        4262 :             if (defer_q_.count(make_pair(vrf_name, table->name()))) {
    2740          40 :                 BGP_LOG_PEER(Membership, Peer(), SandeshLevel::SYS_DEBUG,
    2741             :                              BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2742             :                              "Flush deferred route requests for table " <<
    2743             :                              table->name() << " on unsubscribe");
    2744          20 :                 FlushDeferQ(vrf_name, table->name());
    2745             :             }
    2746             : 
    2747             :             // Erase all elements for the table.
    2748             : 
    2749             :             TableMembershipRequestState *tmr_state =
    2750        4262 :                 GetTableMembershipState(table->name());
    2751        4262 :             if (!tmr_state) {
    2752        4080 :                 AddTableMembershipState(table->name(),
    2753             :                     TableMembershipRequestState(
    2754             :                         UNSUBSCRIBE, instance_id, no_ribout));
    2755        4080 :                 UnregisterTable(table);
    2756             :             } else {
    2757         182 :                 tmr_state->instance_id = -1;
    2758         182 :                 tmr_state->pending_req = UNSUBSCRIBE;
    2759         182 :                 tmr_state->no_ribout = false;
    2760             :             }
    2761             :         }
    2762             :     }
    2763       15098 : }
    2764             : 
    2765        6346 : void BgpXmppChannel::ClearEndOfRibState() {
    2766        6346 :     eor_receive_timer_->Cancel();
    2767        6345 :     eor_send_timer_->Cancel();
    2768        6346 :     eor_sent_ = false;
    2769        6346 : }
    2770             : 
    2771         475 : void BgpXmppChannel::ReceiveEndOfRIB(Address::Family family) {
    2772         475 :     eor_receive_timer_->Cancel();
    2773         475 :     close_manager_->ProcessEORMarkerReceived(family);
    2774         475 : }
    2775             : 
    2776           0 : void BgpXmppChannel::EndOfRibTimerErrorHandler(string error_name,
    2777             :                                                string error_message) {
    2778           0 :     BGP_LOG_PEER_CRITICAL(Timer, Peer(), BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA,
    2779             :                  "Timer error: " << error_name << " " << error_message);
    2780           0 : }
    2781             : 
    2782         435 : bool BgpXmppChannel::EndOfRibReceiveTimerExpired() {
    2783         435 :     if (!peer_->IsReady())
    2784           0 :         return false;
    2785             : 
    2786         435 :     uint32_t timeout = manager() && manager()->xmpp_server() ?
    2787         435 :         manager()->xmpp_server()->GetEndOfRibReceiveTime() :
    2788         435 :         BgpGlobalSystemConfig::kEndOfRibTime;
    2789             : 
    2790             :     // If max timeout has not reached yet, check if we can exit GR sooner by
    2791             :     // looking at the activity in the channel.
    2792         435 :     if (UTCTimestamp() - eor_receive_timer_start_time_ < timeout) {
    2793             : 
    2794             :         // If there is some send or receive activity in the channel in last few
    2795             :         // seconds, delay EoR receive event.
    2796           0 :         if (channel_->LastReceived(kEndOfRibSendRetryTime * 6) ||
    2797           0 :                 channel_->LastSent(kEndOfRibSendRetryTime * 6)) {
    2798           0 :             eor_receive_timer_->Reschedule(kEndOfRibSendRetryTime * 1000);
    2799           0 :             BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO,
    2800             :                          BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN,
    2801             :                          "EndOfRib Receive timer rescheduled to fire after " <<
    2802             :                          kEndOfRibSendRetryTime << " second(s)");
    2803           0 :             return true;
    2804             :         }
    2805             :     }
    2806             : 
    2807         518 :     BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    2808             :                  BGP_PEER_DIR_IN, "EndOfRib Receive timer expired");
    2809         435 :     ReceiveEndOfRIB(Address::UNSPEC);
    2810         435 :     return false;
    2811             : }
    2812             : 
    2813        9453 : time_t BgpXmppChannel::GetEndOfRibSendTime() const {
    2814        9453 :     return manager() && manager()->xmpp_server() ?
    2815        9452 :         manager()->xmpp_server()->GetEndOfRibSendTime() :
    2816        9453 :         BgpGlobalSystemConfig::kEndOfRibTime;
    2817             : }
    2818             : 
    2819        9456 : bool BgpXmppChannel::EndOfRibSendTimerExpired() {
    2820        9456 :     if (!peer_->IsReady())
    2821           0 :         return false;
    2822             : 
    2823             :     // If max timeout has not reached yet, check if we can exit GR sooner by
    2824             :     // looking at the activity in the channel.
    2825        9456 :     if (UTCTimestamp() - eor_send_timer_start_time_ < GetEndOfRibSendTime()) {
    2826             : 
    2827             :         // If there is some send or receive activity in the channel in last few
    2828             :         // seconds, delay EoR send event.
    2829        9452 :         if (channel_->LastReceived(kEndOfRibSendRetryTime * 6) ||
    2830        9776 :                 channel_->LastSent(kEndOfRibSendRetryTime * 6) ||
    2831         324 :                 manager()->bgp_server()->IsServerStartingUp()) {
    2832        9264 :             eor_send_timer_->Reschedule(kEndOfRibSendRetryTime * 1000);
    2833       10762 :             BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO,
    2834             :                          BGP_LOG_FLAG_ALL, BGP_PEER_DIR_OUT,
    2835             :                          "EndOfRib Send timer rescheduled to fire after " <<
    2836             :                          kEndOfRibSendRetryTime << " second(s)");
    2837        9265 :             return true;
    2838             :         }
    2839             :     }
    2840             : 
    2841         190 :     SendEndOfRIB();
    2842         190 :     return false;
    2843             : }
    2844             : 
    2845        6292 : void BgpXmppChannel::StartEndOfRibReceiveTimer() {
    2846        6292 :     uint32_t timeout = manager() && manager()->xmpp_server() ?
    2847        6284 :                            manager()->xmpp_server()->GetEndOfRibReceiveTime() :
    2848        6292 :                            BgpGlobalSystemConfig::kEndOfRibTime;
    2849        6292 :     eor_receive_timer_start_time_ = UTCTimestamp();
    2850        6292 :     eor_receive_timer_->Cancel();
    2851             : 
    2852        7232 :     BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    2853             :         BGP_PEER_DIR_IN, "EndOfRib Receive timer scheduled to fire after " <<
    2854             :         timeout << " second(s)");
    2855        6292 :     eor_receive_timer_->Start(timeout * 1000,
    2856             :         boost::bind(&BgpXmppChannel::EndOfRibReceiveTimerExpired, this),
    2857             :         boost::bind(&BgpXmppChannel::EndOfRibTimerErrorHandler, this, _1, _2));
    2858        6292 : }
    2859             : 
    2860       78659 : void BgpXmppChannel::ResetEndOfRibSendState() {
    2861       78659 :     if (eor_sent_)
    2862         693 :         return;
    2863             : 
    2864             :     // If socket is blocked, then wait for it to get unblocked first.
    2865       77966 :     if (!peer_->send_ready())
    2866          14 :         return;
    2867             : 
    2868             :     // If there is any outstanding subscribe pending, wait for its completion.
    2869       77950 :     if (channel_stats_.table_subscribe_complete !=
    2870       77952 :             channel_stats_.table_subscribe)
    2871       54130 :         return;
    2872             : 
    2873       23820 :     eor_send_timer_start_time_ = UTCTimestamp();
    2874       23820 :     eor_send_timer_->Cancel();
    2875             : 
    2876       29318 :     BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    2877             :         BGP_PEER_DIR_OUT, "EndOfRib Send timer scheduled to fire after " <<
    2878             :         kEndOfRibSendRetryTime << " second(s)");
    2879       23821 :     eor_send_timer_->Start(kEndOfRibSendRetryTime * 1000,
    2880             :         boost::bind(&BgpXmppChannel::EndOfRibSendTimerExpired, this),
    2881             :         boost::bind(&BgpXmppChannel::EndOfRibTimerErrorHandler, this, _1, _2));
    2882             : }
    2883             : 
    2884             : /*
    2885             :  * Empty items list constitute eor marker.
    2886             :  */
    2887         190 : void BgpXmppChannel::SendEndOfRIB() {
    2888         190 :     eor_send_timer_->Cancel();
    2889         190 :     eor_sent_ = true;
    2890             : 
    2891         190 :     string msg;
    2892         190 :     msg += "\n<message from=\"";
    2893         190 :     msg += XmppInit::kControlNodeJID;
    2894         190 :     msg += "\" to=\"";
    2895         190 :     msg += peer_->ToString();
    2896         190 :     msg += "/";
    2897         190 :     msg += XmppInit::kBgpPeer;
    2898         190 :     msg += "\">";
    2899         190 :     msg += "\n\t<event xmlns=\"http://jabber.org/protocol/pubsub\">";
    2900         380 :     msg = (msg + "\n<items node=\"") + XmppInit::kEndOfRibMarker +
    2901         190 :           "\"></items>";
    2902         190 :     msg += "\n\t</event>\n</message>\n";
    2903             : 
    2904         190 :     if (channel_->connection())
    2905         188 :         channel_->connection()->Send((const uint8_t *) msg.data(), msg.size());
    2906             : 
    2907         190 :     stats_[TX].end_of_rib++;
    2908         206 :     BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO, BGP_LOG_FLAG_ALL,
    2909             :                  BGP_PEER_DIR_OUT, "EndOfRib marker sent");
    2910         190 : }
    2911             : 
    2912             : // Process any associated primary instance-id.
    2913       25624 : int BgpXmppChannel::GetPrimaryInstanceID(const string &s,
    2914             :                                          bool expect_prefix_len) const {
    2915       25624 :     if (s.empty())
    2916           0 :         return 0;
    2917       25624 :     char *str = const_cast<char *>(s.c_str());
    2918             :     char *saveptr, *token;
    2919       25624 :     token = strtok_r(str, "/", &saveptr); // Get afi
    2920       25624 :     if (!token || !saveptr)
    2921           0 :         return 0;
    2922       25624 :     token = strtok_r(NULL, "/", &saveptr); // Get safi
    2923       25624 :     if (!token || !saveptr)
    2924           0 :         return 0;
    2925       25624 :     token = strtok_r(NULL, "/", &saveptr); // vrf name
    2926       25624 :     if (!token || !saveptr)
    2927           0 :         return 0;
    2928       25624 :     token = strtok_r(NULL, "/", &saveptr); // address
    2929       25624 :     if (!token || !saveptr)
    2930           2 :         return 0;
    2931       25622 :     if (expect_prefix_len) {
    2932       25618 :         token = strtok_r(NULL, "/", &saveptr); // prefix-length
    2933       25618 :         if (!token || !saveptr)
    2934           1 :             return 0;
    2935             :     }
    2936       25621 :     token = strtok_r(NULL, "/", &saveptr); // primary instance-id
    2937       25621 :     if (!token)
    2938       25605 :         return 0;
    2939          16 :     return strtoul(token, NULL, 0);
    2940             : }
    2941             : 
    2942       56894 : void BgpXmppChannel::ReceiveUpdate(const XmppStanza::XmppMessage *msg) {
    2943       56894 :     CHECK_CONCURRENCY("xmpp::StateMachine");
    2944             : 
    2945             :     // Bail if the connection is being deleted. It's not safe to assert
    2946             :     // because the Delete method can be called from the main thread.
    2947       56893 :     if (channel_->connection() && channel_->connection()->IsDeleted())
    2948           0 :         return;
    2949             : 
    2950             :     // Make sure that peer is not set for closure already.
    2951       56895 :     assert(!defer_peer_close_);
    2952       56895 :     assert(!peer_deleted());
    2953             : 
    2954       56894 :     if (msg->type == XmppStanza::IQ_STANZA) {
    2955       56894 :         const XmppStanza::XmppMessageIq *iq =
    2956             :                    static_cast<const XmppStanza::XmppMessageIq *>(msg);
    2957       56894 :         if (iq->iq_type.compare("set") == 0) {
    2958       56895 :             if (iq->action.compare("subscribe") == 0) {
    2959       14354 :                 ProcessSubscriptionRequest(iq->node, iq, true);
    2960       42541 :             } else if (iq->action.compare("unsubscribe") == 0) {
    2961         862 :                 ProcessSubscriptionRequest(iq->node, iq, false);
    2962       41679 :             } else if (iq->action.compare("publish") == 0) {
    2963       41673 :                 XmlBase *impl = msg->dom.get();
    2964       41673 :                 stats_[RX].rt_updates++;
    2965       41674 :                 XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl);
    2966       41674 :                 xml_node item = pugi->FindNode("item");
    2967             : 
    2968             :                 // Empty items-list can be considered as EOR Marker for all afis
    2969       41673 :                 if (item == 0) {
    2970          56 :                     BGP_LOG_PEER(Message, Peer(), SandeshLevel::SYS_INFO,
    2971             :                                  BGP_LOG_FLAG_ALL, BGP_PEER_DIR_IN,
    2972             :                                  "EndOfRib marker received");
    2973          28 :                     stats_[RX].end_of_rib++;
    2974          28 :                     ReceiveEndOfRIB(Address::UNSPEC);
    2975          28 :                     return;
    2976             :                 }
    2977       83290 :                 for (; item; item = item.next_sibling()) {
    2978       41645 :                     if (strcmp(item.name(), "item") != 0) continue;
    2979             : 
    2980       41645 :                     string id(iq->as_node.c_str());
    2981       41645 :                     char *str = const_cast<char *>(id.c_str());
    2982             :                     char *saveptr;
    2983       41645 :                     char *af = strtok_r(str, "/", &saveptr);
    2984       41646 :                     char *safi = strtok_r(NULL, "/", &saveptr);
    2985             : 
    2986       41646 :                     if (atoi(af) == BgpAf::IPv4 &&
    2987       27018 :                         ((atoi(safi) == BgpAf::Unicast) ||
    2988        1415 :                          (atoi(safi) == BgpAf::Mpls))) {
    2989       25615 :                         ProcessItem(iq->node, item, iq->is_as_node,
    2990       25615 :                             GetPrimaryInstanceID(iq->as_node, true));
    2991       16031 :                     } else if (atoi(af) == BgpAf::IPv6 &&
    2992        9095 :                                atoi(safi) == BgpAf::Unicast) {
    2993        9095 :                         ProcessInet6Item(iq->node, item, iq->is_as_node);
    2994        6936 :                     } else if (atoi(af) == BgpAf::IPv4 &&
    2995        1403 :                         atoi(safi) == BgpAf::Mcast) {
    2996        1155 :                         ProcessMcastItem(iq->node, item, iq->is_as_node);
    2997        5781 :                     } else if (atoi(af) == BgpAf::IPv4 &&
    2998         248 :                         atoi(safi) == BgpAf::MVpn) {
    2999         248 :                         ProcessMvpnItem(iq->node, item, iq->is_as_node);
    3000        5533 :                     } else if (atoi(af) == BgpAf::L2Vpn &&
    3001        5533 :                                atoi(safi) == BgpAf::Enet) {
    3002        5533 :                         ProcessEnetItem(iq->node, item, iq->is_as_node);
    3003             :                     }
    3004       41645 :                 }
    3005             :             }
    3006             :         }
    3007             :     }
    3008             : }
    3009             : 
    3010        6180 : bool BgpXmppChannelManager::DeleteChannel(BgpXmppChannel *channel) {
    3011        6180 :     if (!channel->deleted()) {
    3012        6180 :         channel->set_deleted(true);
    3013        6180 :         delete channel;
    3014             :     }
    3015        6180 :     return true;
    3016             : }
    3017             : 
    3018             : // BgpXmppChannelManager routines.
    3019        2084 : BgpXmppChannelManager::BgpXmppChannelManager(XmppServer *xmpp_server,
    3020        2084 :                                              BgpServer *server)
    3021        2084 :     : xmpp_server_(xmpp_server),
    3022        2084 :       bgp_server_(server),
    3023        2084 :       queue_(TaskScheduler::GetInstance()->GetTaskId("bgp::Config"), 0,
    3024             :           boost::bind(&BgpXmppChannelManager::DeleteChannel, this, _1)),
    3025        2084 :       id_(-1),
    3026        2084 :       asn_listener_id_(-1),
    3027        2084 :       identifier_listener_id_(-1),
    3028        4168 :       dscp_listener_id_(-1) {
    3029             :     // Initialize the gen id counter
    3030        2084 :     subscription_gen_id_ = 1;
    3031        2084 :     deleting_count_ = 0;
    3032             : 
    3033        2084 :     if (xmpp_server)
    3034        2078 :         xmpp_server->CreateConfigUpdater(server->config_manager());
    3035        2084 :     queue_.SetEntryCallback(
    3036             :             boost::bind(&BgpXmppChannelManager::IsReadyForDeletion, this));
    3037        2084 :     if (xmpp_server) {
    3038        2078 :         xmpp_server->RegisterConnectionEvent(xmps::BGP,
    3039             :                boost::bind(&BgpXmppChannelManager::XmppHandleChannelEvent,
    3040             :                            this, _1, _2));
    3041             :     }
    3042        2084 :     admin_down_listener_id_ =
    3043        2084 :         server->RegisterAdminDownCallback(boost::bind(
    3044             :             &BgpXmppChannelManager::AdminDownCallback, this));
    3045        2084 :     asn_listener_id_ =
    3046        2084 :         server->RegisterASNUpdateCallback(boost::bind(
    3047             :             &BgpXmppChannelManager::ASNUpdateCallback, this, _1, _2));
    3048        2084 :     identifier_listener_id_ =
    3049        2084 :         server->RegisterIdentifierUpdateCallback(boost::bind(
    3050             :             &BgpXmppChannelManager::IdentifierUpdateCallback, this, _1));
    3051        2084 :     dscp_listener_id_ =
    3052        2084 :         server->RegisterDSCPUpdateCallback(boost::bind(
    3053             :             &BgpXmppChannelManager::DSCPUpdateCallback, this, _1));
    3054             : 
    3055        2084 :     id_ = server->routing_instance_mgr()->RegisterInstanceOpCallback(
    3056             :         boost::bind(&BgpXmppChannelManager::RoutingInstanceCallback,
    3057             :                     this, _1, _2));
    3058        2084 : }
    3059             : 
    3060        3540 : BgpXmppChannelManager::~BgpXmppChannelManager() {
    3061        2084 :     assert(channel_map_.empty());
    3062        2084 :     assert(channel_name_map_.empty());
    3063        2084 :     assert(deleting_count_ == 0);
    3064        2084 :     if (xmpp_server_) {
    3065        2078 :         xmpp_server_->UnRegisterConnectionEvent(xmps::BGP);
    3066             :     }
    3067             : 
    3068        2084 :     queue_.Shutdown();
    3069        2084 :     bgp_server_->UnregisterAdminDownCallback(admin_down_listener_id_);
    3070        2084 :     bgp_server_->UnregisterASNUpdateCallback(asn_listener_id_);
    3071        2084 :     bgp_server_->routing_instance_mgr()->UnregisterInstanceOpCallback(id_);
    3072        2084 :     bgp_server_->UnregisterDSCPUpdateCallback(dscp_listener_id_);
    3073        3540 : }
    3074             : 
    3075       22180 : bool BgpXmppChannelManager::IsReadyForDeletion() {
    3076       22180 :     return bgp_server_->IsReadyForDeletion();
    3077             : }
    3078             : 
    3079           4 : void BgpXmppChannelManager::SetQueueDisable(bool disabled) {
    3080           4 :     queue_.set_disable(disabled);
    3081           4 : }
    3082             : 
    3083           2 : size_t BgpXmppChannelManager::GetQueueSize() const {
    3084           2 :     return queue_.Length();
    3085             : }
    3086             : 
    3087          16 : void BgpXmppChannelManager::AdminDownCallback() {
    3088          16 :     xmpp_server_->ClearAllConnections();
    3089          16 : }
    3090             : 
    3091           7 : void BgpXmppChannelManager::DSCPUpdateCallback(uint8_t dscp_value) {
    3092           7 :     xmpp_server_->SetDscpValue(dscp_value);
    3093           7 : }
    3094             : 
    3095        2419 : void BgpXmppChannelManager::ASNUpdateCallback(as_t old_asn,
    3096             :     as_t old_local_asn) {
    3097        2419 :     CHECK_CONCURRENCY("bgp::Config");
    3098        4537 :     BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
    3099        1059 :         i.second->rtarget_manager()->ASNUpdateCallback(old_asn, old_local_asn);
    3100             :     }
    3101        2419 :     if (bgp_server_->autonomous_system() != old_asn) {
    3102        2390 :         xmpp_server_->ClearAllConnections();
    3103             :     }
    3104        2419 : }
    3105             : 
    3106        2408 : void BgpXmppChannelManager::IdentifierUpdateCallback(
    3107             :         Ip4Address old_identifier) {
    3108        2408 :     CHECK_CONCURRENCY("bgp::Config");
    3109        2408 :     xmpp_server_->ClearAllConnections();
    3110        2408 : }
    3111             : 
    3112       24816 : void BgpXmppChannelManager::RoutingInstanceCallback(string vrf_name, int op) {
    3113       24816 :     CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");
    3114       30402 :     BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
    3115        2793 :         i.second->RoutingInstanceCallback(vrf_name, op);
    3116             :     }
    3117       24816 : }
    3118             : 
    3119         304 : void BgpXmppChannelManager::VisitChannels(BgpXmppChannelManager::VisitorFn fn) {
    3120         304 :     std::scoped_lock lock(mutex_);
    3121         334 :     BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
    3122          15 :         fn(i.second);
    3123             :     }
    3124         304 : }
    3125             : 
    3126         189 : void BgpXmppChannelManager::VisitChannels(BgpXmppChannelManager::VisitorFn fn)
    3127             :         const {
    3128         189 :     std::scoped_lock lock(mutex_);
    3129         309 :     BOOST_FOREACH(const XmppChannelMap::value_type &i, channel_map_) {
    3130          60 :         fn(i.second);
    3131             :     }
    3132         189 : }
    3133             : 
    3134          21 : BgpXmppChannel *BgpXmppChannelManager::FindChannel(string client) {
    3135          21 :     BOOST_FOREACH(XmppChannelMap::value_type &i, channel_map_) {
    3136          20 :         if (i.second->ToString() == client) {
    3137          20 :             return i.second;
    3138             :         }
    3139             :     }
    3140           1 :     return NULL;
    3141             : }
    3142             : 
    3143          28 : BgpXmppChannel *BgpXmppChannelManager::FindChannel(
    3144             :         const XmppChannel *ch) {
    3145          28 :     XmppChannelMap::iterator it = channel_map_.find(ch);
    3146          28 :     if (it == channel_map_.end())
    3147           0 :         return NULL;
    3148          28 :     return it->second;
    3149             : }
    3150             : 
    3151        6198 : void BgpXmppChannelManager::RemoveChannel(XmppChannel *channel) {
    3152        6198 :     if (channel->connection() && !channel->connection()->IsActiveChannel()) {
    3153        6180 :         CHECK_CONCURRENCY("bgp::Config");
    3154             :     }
    3155        6198 :     channel_map_.erase(channel);
    3156        6198 :     channel_name_map_.erase(channel->ToString());
    3157        6198 : }
    3158             : 
    3159        4003 : BgpXmppChannel *BgpXmppChannelManager::CreateChannel(XmppChannel *channel) {
    3160        4003 :     CHECK_CONCURRENCY("xmpp::StateMachine");
    3161        4003 :     BgpXmppChannel *ch = new BgpXmppChannel(channel, bgp_server_, this);
    3162             : 
    3163        4003 :     return ch;
    3164             : }
    3165             : 
    3166       12866 : void BgpXmppChannelManager::XmppHandleChannelEvent(XmppChannel *channel,
    3167             :                                                    xmps::PeerState state) {
    3168       12866 :     std::scoped_lock lock(mutex_);
    3169             : 
    3170       12871 :     XmppChannelMap::iterator it = channel_map_.find(channel);
    3171       12871 :     BgpXmppChannel *bgp_xmpp_channel = NULL;
    3172       12871 :     if (state == xmps::READY) {
    3173        6292 :         if (it == channel_map_.end()) {
    3174        6188 :             bgp_xmpp_channel = CreateChannel(channel);
    3175        6188 :             channel_map_.insert(make_pair(channel, bgp_xmpp_channel));
    3176        6188 :             channel_name_map_.insert(
    3177       12376 :                 make_pair(channel->ToString(), bgp_xmpp_channel));
    3178        7024 :             BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
    3179             :                          Sandesh::LoggingUtLevel(), BGP_LOG_FLAG_SYSLOG,
    3180             :                          BGP_PEER_DIR_IN,
    3181             :                          "Received XmppChannel up event");
    3182        6188 :             if (!bgp_server_->HasSelfConfiguration()) {
    3183         304 :                 BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
    3184             :                              SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG,
    3185             :                              BGP_PEER_DIR_IN,
    3186             :                              "No BGP configuration for self - closing channel");
    3187         296 :                 if (!getenv("CONTRAIL_CAT_FRAMEWORK"))
    3188         296 :                     channel->Close();
    3189             :             }
    3190        6188 :             if (bgp_server_->admin_down()) {
    3191         192 :                 BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
    3192             :                              SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG,
    3193             :                              BGP_PEER_DIR_IN,
    3194             :                              "BGP is administratively down - closing channel");
    3195         192 :                 channel->Close();
    3196             :             }
    3197             :         } else {
    3198         104 :             bgp_xmpp_channel = (*it).second;
    3199         104 :             if (bgp_xmpp_channel->peer_deleted())
    3200           0 :                 return;
    3201             : 
    3202             :             // Gracefully close the channel if GR closure is in progress.
    3203             :             // This can happen if GR timers fire just after session comes
    3204             :             // back up.
    3205         208 :             if (bgp_xmpp_channel->close_manager()->IsCloseInProgress() &&
    3206         104 :                 !bgp_xmpp_channel->close_manager()->IsInGRTimerWaitState()) {
    3207           0 :                 BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
    3208             :                              SandeshLevel::SYS_INFO, BGP_LOG_FLAG_SYSLOG,
    3209             :                              BGP_PEER_DIR_IN,
    3210             :                              "Graceful Closure in progress - Closing channel");
    3211           0 :                 channel->Close();
    3212             :             }
    3213         104 :             channel->RegisterReceive(xmps::BGP,
    3214             :                 boost::bind(&BgpXmppChannel::ReceiveUpdate, bgp_xmpp_channel,
    3215             :                             _1));
    3216             :         }
    3217             : 
    3218        6292 :         bgp_xmpp_channel->eor_sent_ = false;
    3219        6292 :         bgp_xmpp_channel->StartEndOfRibReceiveTimer();
    3220        6292 :         bgp_xmpp_channel->ResetEndOfRibSendState();
    3221        6579 :     } else if (state == xmps::NOT_READY) {
    3222        6579 :         if (it != channel_map_.end()) {
    3223        6354 :             bgp_xmpp_channel = (*it).second;
    3224        7356 :             BGP_LOG_PEER(Message, bgp_xmpp_channel->Peer(),
    3225             :                          Sandesh::LoggingUtLevel(), BGP_LOG_FLAG_SYSLOG,
    3226             :                          BGP_PEER_DIR_IN,
    3227             :                          "Received XmppChannel down event");
    3228             : 
    3229             :             // Trigger closure of this channel
    3230        6354 :             bgp_xmpp_channel->Close();
    3231             :         } else {
    3232         225 :             ostringstream os;
    3233         450 :             os << "Peer not found for " << channel->ToString() <<
    3234         225 :                   " on channel down event";
    3235         225 :             BGP_LOG_NOTICE(BgpMessage, BGP_LOG_FLAG_ALL, os.str());
    3236         225 :         }
    3237             :     }
    3238       12871 : }
    3239             : 
    3240          60 : void BgpXmppChannelManager::FillPeerInfo(const BgpXmppChannel *channel) const {
    3241          60 :     PeerStatsInfo stats;
    3242          60 :     PeerStats::FillPeerDebugStats(channel->Peer()->peer_stats(), &stats);
    3243             : 
    3244         120 :     XmppPeerInfoData peer_info;
    3245          60 :     peer_info.set_name(channel->Peer()->ToUVEKey());
    3246          60 :     peer_info.set_peer_stats_info(stats);
    3247          60 :     assert(!peer_info.get_name().empty());
    3248          60 :     BGP_UVE_SEND(XMPPPeerInfo, peer_info);
    3249             : 
    3250         120 :     PeerStatsData peer_stats_data;
    3251          60 :     peer_stats_data.set_name(channel->Peer()->ToUVEKey());
    3252          60 :     peer_stats_data.set_encoding("XMPP");
    3253          60 :     PeerStats::FillPeerUpdateStats(channel->Peer()->peer_stats(),
    3254             :                                    &peer_stats_data);
    3255          60 :     assert(!peer_stats_data.get_name().empty());
    3256          60 :     BGP_UVE_SEND2(PeerStatsUve, peer_stats_data, "ObjectXmppPeerInfo");
    3257          60 : }
    3258             : 
    3259         189 : bool BgpXmppChannelManager::CollectStats(BgpRouterState *state, bool first)
    3260             :          const {
    3261         189 :     CHECK_CONCURRENCY("bgp::ShowCommand");
    3262             : 
    3263         189 :     VisitChannels(boost::bind(&BgpXmppChannelManager::FillPeerInfo, this, _1));
    3264         189 :     bool change = false;
    3265         189 :     uint32_t num_xmpp = count();
    3266         189 :     if (first || num_xmpp != state->get_num_xmpp_peer()) {
    3267          15 :         state->set_num_xmpp_peer(num_xmpp);
    3268          15 :         change = true;
    3269             :     }
    3270             : 
    3271         189 :     uint32_t num_up_xmpp = NumUpPeer();
    3272         189 :     if (first || num_up_xmpp != state->get_num_up_xmpp_peer()) {
    3273          15 :         state->set_num_up_xmpp_peer(num_up_xmpp);
    3274          15 :         change = true;
    3275             :     }
    3276             : 
    3277         189 :     uint32_t num_deleting_xmpp = deleting_count();
    3278         189 :     if (first || num_deleting_xmpp != state->get_num_deleting_xmpp_peer()) {
    3279           1 :         state->set_num_deleting_xmpp_peer(num_deleting_xmpp);
    3280           1 :         change = true;
    3281             :     }
    3282             : 
    3283         189 :     return change;
    3284             : }
    3285             : 
    3286       10169 : void BgpXmppChannel::Close() {
    3287       10169 :     instance_membership_request_map_.clear();
    3288       10169 :     STLDeleteElements(&defer_q_);
    3289             : 
    3290       10168 :     if (table_membership_requests()) {
    3291         152 :         BGP_LOG_PEER(Event, peer_.get(), SandeshLevel::SYS_INFO,
    3292             :             BGP_LOG_FLAG_ALL, BGP_PEER_DIR_NA, "Close procedure deferred");
    3293          87 :         defer_peer_close_ = true;
    3294          87 :         return;
    3295             :     }
    3296       10082 :     peer_->Close(true);
    3297             : }
    3298             : 
    3299             : //
    3300             : // Return connection's remote tcp endpoint if available
    3301             : //
    3302        2740 : TcpSession::Endpoint BgpXmppChannel::remote_endpoint() const {
    3303        2740 :     const XmppSession *session = GetSession();
    3304        2740 :     if (session) {
    3305        2668 :         return session->remote_endpoint();
    3306             :     }
    3307          72 :     return TcpSession::Endpoint();
    3308             : }
    3309             : 
    3310             : //
    3311             : // Return connection's local tcp endpoint if available
    3312             : //
    3313         974 : TcpSession::Endpoint BgpXmppChannel::local_endpoint() const {
    3314         974 :     const XmppSession *session = GetSession();
    3315         974 :     if (session) {
    3316         950 :         return session->local_endpoint();
    3317             :     }
    3318          24 :     return TcpSession::Endpoint();
    3319             : }
    3320             : 
    3321             : //
    3322             : // Return connection's remote tcp endpoint string.
    3323             : //
    3324         974 : string BgpXmppChannel::transport_address_string() const {
    3325         974 :     TcpSession::Endpoint endpoint = remote_endpoint();
    3326         974 :     ostringstream oss;
    3327         974 :     oss << endpoint;
    3328        1948 :     return oss.str();
    3329         974 : }
    3330             : 
    3331             : //
    3332             : // Mark the XmppPeer as deleted.
    3333             : //
    3334       16613 : void BgpXmppChannel::set_peer_closed(bool flag) {
    3335       16613 :     peer_->SetPeerClosed(flag);
    3336       16614 : }
    3337             : 
    3338             : //
    3339             : // Return true if the XmppPeer is deleted.
    3340             : //
    3341       74487 : bool BgpXmppChannel::peer_deleted() const {
    3342       74487 :     return peer_->IsDeleted();
    3343             : }
    3344             : 
    3345             : //
    3346             : // Return time stamp of when the XmppPeer delete was initiated.
    3347             : //
    3348         974 : uint64_t BgpXmppChannel::peer_closed_at() const {
    3349         974 :     return peer_->closed_at();
    3350             : }
    3351             : 
    3352        7333 : bool BgpXmppChannel::IsSubscriptionGrStale(RoutingInstance *instance) const {
    3353             :     SubscribedRoutingInstanceList::const_iterator it =
    3354        7333 :         routing_instances_.find(instance);
    3355        7333 :     assert(it != routing_instances_.end());
    3356       14666 :     return it->second.IsGrStale();
    3357             : }
    3358             : 
    3359        7333 : bool BgpXmppChannel::IsSubscriptionLlgrStale(RoutingInstance *instance) const {
    3360             :     SubscribedRoutingInstanceList::const_iterator it =
    3361        7333 :         routing_instances_.find(instance);
    3362        7333 :     assert(it != routing_instances_.end());
    3363       14666 :     return it->second.IsLlgrStale();
    3364             : }
    3365             : 
    3366       15936 : bool BgpXmppChannel::IsSubscriptionEmpty() const {
    3367       15936 :     return routing_instances_.empty();
    3368             : }
    3369             : 
    3370       14877 : const RoutingInstance::RouteTargetList &BgpXmppChannel::GetSubscribedRTargets(
    3371             :         RoutingInstance *instance) const {
    3372             :     SubscribedRoutingInstanceList::const_iterator it =
    3373       14877 :         routing_instances_.find(instance);
    3374       14877 :     assert(it != routing_instances_.end());
    3375       14877 :     return it->second.targets;
    3376             : }

Generated by: LCOV version 1.14