LCOV - code coverage report
Current view: top level - bgp - bgp_xmpp_channel.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 84 84 100.0 %
Date: 2026-11-09 02:10:49 Functions: 44 44 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #ifndef SRC_BGP_BGP_XMPP_CHANNEL_H_
       7             : #define SRC_BGP_BGP_XMPP_CHANNEL_H_
       8             : 
       9             : #include <map>
      10             : #include <set>
      11             : #include <string>
      12             : #include <utility>
      13             : #include <mutex>
      14             : #include <atomic>
      15             : 
      16             : #include <boost/function.hpp>
      17             : #include <boost/system/error_code.hpp>
      18             : #include <boost/scoped_ptr.hpp>
      19             : 
      20             : #include "base/queue_task.h"
      21             : #include "bgp/bgp_rib_policy.h"
      22             : #include "bgp/routing-instance/routing_instance.h"
      23             : #include "io/tcp_session.h"
      24             : #include "net/rd.h"
      25             : #include "schema/xmpp_mvpn_types.h"
      26             : #include "xmpp/xmpp_channel.h"
      27             : 
      28             : namespace pugi {
      29             : class xml_node;
      30             : }
      31             : 
      32             : class BgpGlobalSystemConfig;
      33             : class BgpRouterState;
      34             : class BgpServer;
      35             : class BgpXmppRTargetManager;
      36             : struct DBRequest;
      37             : class IPeer;
      38             : class PeerCloseManager;
      39             : class XmppServer;
      40             : class BgpXmppChannelMock;
      41             : class BgpXmppChannelManager;
      42             : class BgpXmppChannelManagerMock;
      43             : class BgpXmppPeerClose;
      44             : class Timer;
      45             : class XmppConfigUpdater;
      46             : class XmppPeerInfoData;
      47             : class XmppSession;
      48             : 
      49             : class BgpXmppChannel {
      50             : public:
      51             :     static const int kEndOfRibSendRetryTime = 1; // Seconds
      52             :     enum StatsIndex {
      53             :         RX,
      54             :         TX,
      55             :     };
      56             :     struct Stats {
      57       20084 :         Stats() {
      58       20084 :             rt_updates = 0;
      59       20084 :             reach = 0;
      60       20084 :             unreach = 0;
      61       20083 :             end_of_rib = 0;
      62       20084 :         }
      63             :         std::atomic<uint64_t> rt_updates;
      64             :         std::atomic<uint64_t> reach;
      65             :         std::atomic<uint64_t> unreach;
      66             :         std::atomic<uint64_t> end_of_rib;
      67             :     };
      68             :     struct ChannelStats {
      69       10042 :         ChannelStats() {
      70       10042 :             instance_subscribe = 0;
      71       10042 :             instance_unsubscribe = 0;
      72       10042 :             table_subscribe = 0;
      73       10041 :             table_subscribe_complete = 0;
      74       10042 :             table_unsubscribe = 0;
      75       10042 :             table_unsubscribe_complete = 0;
      76       10042 :         }
      77             :         std::atomic<uint64_t> instance_subscribe;
      78             :         std::atomic<uint64_t> instance_unsubscribe;
      79             :         std::atomic<uint64_t> table_subscribe;
      80             :         std::atomic<uint64_t> table_subscribe_complete;
      81             :         std::atomic<uint64_t> table_unsubscribe;
      82             :         std::atomic<uint64_t> table_unsubscribe_complete;
      83             :     };
      84             : 
      85             :     struct ErrorStats {
      86       10042 :         ErrorStats() {
      87       10042 :             inet6_rx_bad_xml_token_count = 0;
      88       10042 :             inet6_rx_bad_prefix_count = 0;
      89       10042 :             inet6_rx_bad_nexthop_count = 0;
      90       10042 :             inet6_rx_bad_afi_safi_count = 0;
      91       10042 :         }
      92             :         void incr_inet6_rx_bad_xml_token_count();
      93             :         void incr_inet6_rx_bad_prefix_count();
      94             :         void incr_inet6_rx_bad_nexthop_count();
      95             :         void incr_inet6_rx_bad_afi_safi_count();
      96             :         uint64_t get_inet6_rx_bad_xml_token_count() const;
      97             :         uint64_t get_inet6_rx_bad_prefix_count() const;
      98             :         uint64_t get_inet6_rx_bad_nexthop_count() const;
      99             :         uint64_t get_inet6_rx_bad_afi_safi_count() const;
     100             : 
     101             :         std::atomic<uint64_t> inet6_rx_bad_xml_token_count;
     102             :         std::atomic<uint64_t> inet6_rx_bad_prefix_count;
     103             :         std::atomic<uint64_t> inet6_rx_bad_nexthop_count;
     104             :         std::atomic<uint64_t> inet6_rx_bad_afi_safi_count;
     105             :     };
     106             : 
     107             :     explicit BgpXmppChannel(XmppChannel *channel, BgpServer *bgp_server = NULL,
     108             :                             BgpXmppChannelManager *manager = NULL);
     109             :     virtual ~BgpXmppChannel();
     110             : 
     111             :     void Close();
     112             :     IPeer *Peer();
     113             :     const IPeer *Peer() const;
     114             :     virtual TcpSession::Endpoint endpoint() const;
     115             : 
     116             :     const std::string &ToString() const;
     117             :     const std::string &ToUVEKey() const;
     118             :     std::string StateName() const;
     119             :     TcpSession::Endpoint remote_endpoint() const;
     120             :     TcpSession::Endpoint local_endpoint() const;
     121             :     std::string transport_address_string() const;
     122             : 
     123             :     void set_peer_closed(bool flag);
     124             :     bool peer_deleted() const;
     125             :     uint64_t peer_closed_at() const;
     126             :     bool table_membership_request_map_empty() const;
     127             :     size_t GetMembershipRequestQueueSize() const;
     128             : 
     129             :     const XmppSession *GetSession() const;
     130             :     const Stats &rx_stats() const { return stats_[RX]; }
     131             :     const Stats &tx_stats() const { return stats_[TX]; }
     132          88 :     ErrorStats &error_stats() { return error_stats_; }
     133             :     const ErrorStats &error_stats() const { return error_stats_; }
     134        9993 :     void set_deleted(bool deleted) { deleted_ = deleted; }
     135        6178 :     bool deleted() { return deleted_; }
     136             :     void RoutingInstanceCallback(std::string vrf_name, int op);
     137             :     void ASNUpdateCallback(as_t old_asn, as_t old_local_asn);
     138             :     void FillInstanceMembershipInfo(BgpNeighborResp *resp) const;
     139             :     void FillTableMembershipInfo(BgpNeighborResp *resp) const;
     140             :     void FillCloseInfo(BgpNeighborResp *resp) const;
     141             :     void StaleCurrentSubscriptions();
     142             :     void LlgrStaleCurrentSubscriptions();
     143             :     void SweepCurrentSubscriptions();
     144             :     void XMPPPeerInfoSend(const XmppPeerInfoData &peer_info) const;
     145         974 :     const XmppChannel *channel() const { return channel_; }
     146       25348 :     XmppChannel *channel() { return channel_; }
     147             :     void StartEndOfRibReceiveTimer();
     148             :     void ResetEndOfRibSendState();
     149             :     bool EndOfRibSendTimerExpired();
     150             :     bool MembershipResponseHandler(std::string table_name);
     151          18 :     Timer *eor_send_timer() const { return eor_send_timer_; }
     152           9 :     bool eor_sent() const { return eor_sent_; }
     153             :     size_t table_membership_requests() const;
     154             :     void ClearEndOfRibState();
     155       72567 :     PeerCloseManager *close_manager() { return close_manager_.get(); }
     156             : 
     157           7 :     uint64_t get_rx_route_reach() const { return stats_[RX].reach; }
     158           7 :     uint64_t get_rx_route_unreach() const { return stats_[RX].unreach; }
     159             :     uint64_t get_rx_update() const { return stats_[RX].rt_updates; }
     160             : 
     161           7 :     uint64_t get_tx_route_reach() const { return stats_[TX].reach; }
     162           7 :     uint64_t get_tx_route_unreach() const { return stats_[TX].unreach; }
     163           7 :     uint64_t get_tx_update() const { return stats_[TX].rt_updates; }
     164             :     bool SkipUpdateSend();
     165       42219 :     bool delete_in_progress() const { return delete_in_progress_; }
     166        6178 :     void set_delete_in_progress(bool flag) { delete_in_progress_ = flag; }
     167             : 
     168        7237 :     BgpXmppRTargetManager *rtarget_manager() {
     169        7237 :         return rtarget_manager_.get();
     170             :     }
     171             :     bool IsSubscriptionGrStale(RoutingInstance *instance) const;
     172             :     bool IsSubscriptionLlgrStale(RoutingInstance *instance) const;
     173             :     bool IsSubscriptionEmpty() const;
     174             :     const RoutingInstance::RouteTargetList &GetSubscribedRTargets(
     175             :             RoutingInstance *instance) const;
     176        6178 :     void ClearSubscriptions() { routing_instances_.clear(); }
     177      273987 :     BgpServer *bgp_server() { return bgp_server_; }
     178       28796 :     const BgpXmppChannelManager *manager() const { return manager_; }
     179       38278 :     BgpXmppChannelManager *manager() { return manager_; }
     180             :     XmppChannel *xmpp_channel() const { return channel_; }
     181             :     void ReceiveEndOfRIB(Address::Family family);
     182             :     void ProcessPendingSubscriptions();
     183             :     int GetPrimaryInstanceID(const std::string &s,
     184             :                              bool expect_prefix_len) const;
     185             : 
     186             : protected:
     187             :     struct InstanceMembershipRequestState {
     188         182 :         InstanceMembershipRequestState(int instance_id = -1,
     189             :             bool no_ribout = false)
     190         182 :             : instance_id(instance_id), no_ribout(no_ribout) {
     191         182 :         };
     192             : 
     193             :         int instance_id;
     194             :         bool no_ribout;
     195             :     };
     196             : 
     197             : 
     198             :     XmppChannel *channel_;
     199             : 
     200             : private:
     201             :     friend class BgpXmppChannelMock;
     202             :     friend class BgpXmppChannelManager;
     203             :     friend class BgpXmppParseTest;
     204             :     friend class BgpXmppUnitTest;
     205             :     class XmppPeer;
     206             :     class PeerClose;
     207             :     class PeerStats;
     208             : 
     209             :     //
     210             :     // State the instance id received in Membership subscription request
     211             :     // Also remember we received unregister request
     212             :     //
     213             :     enum RequestType {
     214             :         NONE,
     215             :         SUBSCRIBE,
     216             :         UNSUBSCRIBE,
     217             :     };
     218             :     struct TableMembershipRequestState {
     219       72819 :         TableMembershipRequestState(RequestType current, int id,
     220             :             bool no_ribout = false)
     221       72819 :             : current_req(current),
     222       72819 :               instance_id(id),
     223       72819 :               pending_req(current),
     224       72819 :               no_ribout(no_ribout) {
     225       72819 :         }
     226             :         RequestType current_req;
     227             :         int instance_id;
     228             :         RequestType pending_req;
     229             :         bool no_ribout;
     230             :     };
     231             : 
     232             :     // Map of routing instances to which this BgpXmppChannel is subscribed.
     233             :     struct SubscriptionState {
     234             :         enum State {
     235             :             NONE = 0,
     236             :             GR_STALE = 1 << 0,
     237             :             LLGR_STALE = 1 << 1
     238             :         };
     239             : 
     240             :         SubscriptionState() : index(-1), state(NONE) { }
     241       14231 :         SubscriptionState(const RoutingInstance::RouteTargetList &targets,
     242             :                           int index)
     243       14231 :                 : targets(targets), index(index), state(NONE) { }
     244             : 
     245       10497 :         bool IsGrStale() const { return((state & GR_STALE) != 0); }
     246         740 :         void SetGrStale() { state |= GR_STALE; }
     247             : 
     248         121 :         void SetLlgrStale() { state |= LLGR_STALE; }
     249        9690 :         bool IsLlgrStale() const { return((state & LLGR_STALE) != 0); }
     250             : 
     251         251 :         void ClearStale() { state &= ~(GR_STALE | LLGR_STALE); }
     252             : 
     253             :         RoutingInstance::RouteTargetList targets;
     254             :         int index;
     255             :         uint32_t state;
     256             :     };
     257             : 
     258             :     typedef std::map<RoutingInstance *, SubscriptionState>
     259             :         SubscribedRoutingInstanceList;
     260             : 
     261             :     // Map of table name to subscription request state.
     262             :     typedef std::map<std::string,
     263             :         TableMembershipRequestState> TableMembershipRequestMap;
     264             : 
     265             :     // Map of routing-instance name to subscription request state. This map
     266             :     // maintains list of requests that are received for subscription before
     267             :     // routing instance is created or recreated (in case the instance is in
     268             :     // the process of being deleted).
     269             :     typedef std::map<std::string,
     270             :         InstanceMembershipRequestState> InstanceMembershipRequestMap;
     271             : 
     272             :     // The code assumes that multimap preserves insertion order for duplicate
     273             :     // values of same key.
     274             :     typedef std::pair<const std::string, const std::string> VrfTableName;
     275             :     typedef std::multimap<VrfTableName, DBRequest *> DeferQ;
     276             : 
     277             :     virtual void ReceiveUpdate(const XmppStanza::XmppMessage *msg);
     278             : 
     279             :     virtual bool GetMembershipInfo(BgpTable *table,
     280             :         int *instance_id, uint64_t *subscribed_at, RequestType *req_type);
     281             :     bool VerifyMembership(const std::string &vrf_name, Address::Family family,
     282             :         BgpTable **table, int *instance_id, uint64_t *subscribed_at,
     283             :         bool *subscribe_pending, bool add_change);
     284             : 
     285             :     void AddTableMembershipState(const std::string &table_name,
     286             :         TableMembershipRequestState tmr_state);
     287             :     bool DeleteTableMembershipState(const std::string &table_name);
     288             :     TableMembershipRequestState *GetTableMembershipState(
     289             :         const std::string &table_name);
     290             :     const TableMembershipRequestState *GetTableMembershipState(
     291             :         const std::string &table_name) const;
     292             : 
     293             :     void AddInstanceMembershipState(const std::string &instance,
     294             :         InstanceMembershipRequestState imr_state);
     295             :     bool DeleteInstanceMembershipState(const std::string &instance);
     296             :     virtual const InstanceMembershipRequestState *GetInstanceMembershipState(
     297             :         const std::string &instance) const;
     298             : 
     299             :     bool ProcessItem(std::string vrf_name, const pugi::xml_node &node,
     300             :                      bool add_change, int primary_instance_id = 0);
     301             :     bool ProcessInet6Item(std::string vrf_name, const pugi::xml_node &node,
     302             :                           bool add_change);
     303             :     bool ProcessMcastItem(std::string vrf_name,
     304             :                           const pugi::xml_node &item, bool add_change);
     305             :     bool ProcessMvpnItem(std::string vrf_name,
     306             :                          const pugi::xml_node &item, bool add_change);
     307             :     void CreateType7MvpnRouteRequest(IpAddress grp_address,
     308             :         IpAddress src_address, bool add_change, uint64_t subscription_gen_id,
     309             :         DBRequest &req);
     310             :     void CreateType5MvpnRouteRequest(IpAddress grp_address,
     311             :         IpAddress src_address, bool add_change, uint64_t subscription_gen_id,
     312             :         int instance_id, DBRequest &req, const autogen::MvpnNextHopType &nh);
     313             :     bool ProcessEnetItem(std::string vrf_name,
     314             :                          const pugi::xml_node &item, bool add_change);
     315             :     void ProcessSubscriptionRequest(std::string rt_instance,
     316             :                                     const XmppStanza::XmppMessageIq *iq,
     317             :                                     bool add_change);
     318             :     void AddSubscriptionState(RoutingInstance *rt_instance, int index);
     319             :     void DeleteSubscriptionState(RoutingInstance *rt_instance);
     320             :     SubscriptionState *GetSubscriptionState(RoutingInstance *rt_instance);
     321             :     const SubscriptionState *GetSubscriptionState(
     322             :         RoutingInstance *rt_instance) const;
     323             : 
     324             :     void RegisterTable(int line, BgpTable *table,
     325             :         const TableMembershipRequestState *tmr_state);
     326             :     void UnregisterTable(int line, BgpTable *table);
     327             :     void MembershipRequestCallback(BgpTable *table);
     328             :     void DequeueRequest(const std::string &table_name, DBRequest *request);
     329             :     bool XmppDecodeAddress(int af, const std::string &address,
     330             :                            IpAddress *addrp, bool zero_ok = false);
     331             :     bool ResumeClose();
     332             :     void FlushDeferQ(std::string vrf_name);
     333             :     void FlushDeferQ(std::string vrf_name, std::string table_name);
     334             :     void ProcessDeferredSubscribeRequest(RoutingInstance *rt_instance,
     335             :         const InstanceMembershipRequestState &imr_state);
     336             :     void ClearStaledSubscription(RoutingInstance *rt_instance,
     337             :                                  SubscriptionState *sub_state);
     338             :     bool ProcessMembershipResponse(std::string table_name,
     339             :                                    TableMembershipRequestState *tmr_state);
     340             :     bool EndOfRibReceiveTimerExpired();
     341             :     void EndOfRibTimerErrorHandler(std::string error_name,
     342             :                                    std::string error_message);
     343             :     void SendEndOfRIB();
     344             :     virtual time_t GetEndOfRibSendTime() const;
     345             : 
     346             :     xmps::PeerId peer_id_;
     347             :     boost::scoped_ptr<BgpXmppRTargetManager> rtarget_manager_;
     348             :     BgpServer *bgp_server_;
     349             :     boost::scoped_ptr<XmppPeer> peer_;
     350             :     boost::scoped_ptr<BgpXmppPeerClose> peer_close_;
     351             :     boost::scoped_ptr<PeerCloseManager> close_manager_;
     352             :     boost::scoped_ptr<PeerStats> peer_stats_;
     353             :     RibExportPolicy bgp_policy_;
     354             : 
     355             :     // DB Requests pending membership request response.
     356             :     DeferQ defer_q_;
     357             : 
     358             :     TableMembershipRequestMap table_membership_request_map_;
     359             :     InstanceMembershipRequestMap instance_membership_request_map_;
     360             :     BgpXmppChannelManager *manager_;
     361             :     bool delete_in_progress_;
     362             :     bool deleted_;
     363             :     bool defer_peer_close_;
     364             :     bool skip_update_send_;
     365             :     bool skip_update_send_cached_;
     366             :     bool eor_sent_;
     367             :     Timer *eor_receive_timer_;
     368             :     Timer *eor_send_timer_;
     369             :     time_t eor_receive_timer_start_time_;
     370             :     time_t eor_send_timer_start_time_;
     371             :     WorkQueue<std::string> membership_response_worker_;
     372             :     SubscribedRoutingInstanceList routing_instances_;
     373             : 
     374             :     // statistics
     375             :     Stats stats_[2];
     376             :     ChannelStats channel_stats_;
     377             :     ErrorStats error_stats_;
     378             : 
     379             :     // Label block manager for multicast labels.
     380             :     LabelBlockManagerPtr lb_mgr_;
     381             : 
     382             :     DISALLOW_COPY_AND_ASSIGN(BgpXmppChannel);
     383             : };
     384             : 
     385             : class BgpXmppChannelManager {
     386             : public:
     387             :     typedef std::map<const XmppChannel *, BgpXmppChannel *> XmppChannelMap;
     388             :     typedef std::map<std::string, BgpXmppChannel *> XmppChannelNameMap;
     389             :     typedef XmppChannelNameMap::const_iterator const_name_iterator;
     390             :     typedef boost::function<void(BgpXmppChannel *)> VisitorFn;
     391             : 
     392             :     BgpXmppChannelManager(XmppServer *, BgpServer *);
     393             :     virtual ~BgpXmppChannelManager();
     394             : 
     395             :     const_name_iterator name_cbegin() const {
     396             :         return channel_name_map_.begin();
     397             :     }
     398        2506 :     const_name_iterator name_cend() const {
     399        2506 :         return channel_name_map_.end();
     400             :     }
     401         386 :     const_name_iterator name_clower_bound(const std::string &name) const {
     402         386 :         return channel_name_map_.lower_bound(name);
     403             :     }
     404             : 
     405             :     void VisitChannels(BgpXmppChannelManager::VisitorFn);
     406             :     void VisitChannels(BgpXmppChannelManager::VisitorFn) const;
     407             :     BgpXmppChannel *FindChannel(const XmppChannel *channel);
     408             :     BgpXmppChannel *FindChannel(std::string client);
     409             :     void RemoveChannel(XmppChannel *channel);
     410             :     virtual void XmppHandleChannelEvent(XmppChannel *channel,
     411             :                                         xmps::PeerState state);
     412             : 
     413         260 :     const XmppChannelMap &channel_map() const { return channel_map_; }
     414        6178 :     void Enqueue(BgpXmppChannel *bx_channel) {
     415        6178 :         queue_.Enqueue(bx_channel);
     416        6178 :     }
     417             :     bool IsReadyForDeletion();
     418             :     void SetQueueDisable(bool disabled);
     419             :     size_t GetQueueSize() const;
     420             :     void AdminDownCallback();
     421             :     void ASNUpdateCallback(as_t old_asn, as_t old_local_asn);
     422             :     void IdentifierUpdateCallback(Ip4Address old_identifier);
     423             :     void RoutingInstanceCallback(std::string vrf_name, int op);
     424             :     void DSCPUpdateCallback(uint8_t value);
     425             : 
     426         177 :     uint32_t count() const {
     427         177 :         std::scoped_lock lock(mutex_);
     428         354 :         return channel_map_.size();
     429         177 :     }
     430         641 :     uint32_t NumUpPeer() const {
     431         641 :         std::scoped_lock lock(mutex_);
     432        1282 :         return channel_map_.size();
     433         641 :     }
     434             : 
     435         177 :     int32_t deleting_count() const { return deleting_count_; }
     436        6178 :     void increment_deleting_count() { deleting_count_++; }
     437        6178 :     void decrement_deleting_count() {
     438        6178 :         assert(deleting_count_);
     439        6178 :         deleting_count_--;
     440        6178 :     }
     441             : 
     442         343 :     BgpServer *bgp_server() { return bgp_server_; }
     443       18826 :     XmppServer *xmpp_server() { return xmpp_server_; }
     444       19195 :     const XmppServer *xmpp_server() const { return xmpp_server_; }
     445       68251 :     uint64_t get_subscription_gen_id() {
     446      136502 :         return subscription_gen_id_.fetch_add(1);
     447             :     }
     448             :     bool CollectStats(BgpRouterState *state, bool first) const;
     449             : 
     450             : protected:
     451             :     virtual BgpXmppChannel *CreateChannel(XmppChannel *channel);
     452             :     virtual bool DeleteChannel(BgpXmppChannel *channel);
     453             : 
     454             : private:
     455             :     friend class BgpXmppChannelManagerMock;
     456             :     friend class BgpXmppUnitTest;
     457             : 
     458             :     void FillPeerInfo(const BgpXmppChannel *channel) const;
     459             : 
     460             :     XmppServer *xmpp_server_;
     461             :     BgpServer *bgp_server_;
     462             :     WorkQueue<BgpXmppChannel *> queue_;
     463             :     mutable std::mutex mutex_;
     464             :     XmppChannelMap channel_map_;
     465             :     XmppChannelNameMap channel_name_map_;
     466             :     int id_;
     467             :     int admin_down_listener_id_;
     468             :     int asn_listener_id_;
     469             :     int identifier_listener_id_;
     470             :     int dscp_listener_id_;
     471             :     std::atomic<int32_t> deleting_count_;
     472             :     // Generation number for subscription tracking
     473             :     std::atomic<uint64_t> subscription_gen_id_;
     474             : 
     475             :     DISALLOW_COPY_AND_ASSIGN(BgpXmppChannelManager);
     476             : };
     477             : 
     478             : #endif  // SRC_BGP_BGP_XMPP_CHANNEL_H_

Generated by: LCOV version 1.14