LCOV - code coverage report
Current view: top level - bgp - bgp_update_sender.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 12 12 100.0 %
Date: 2026-11-09 02:10:49 Functions: 6 6 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_UPDATE_SENDER_H_
       7             : #define SRC_BGP_BGP_UPDATE_SENDER_H_
       8             : 
       9             : #include <boost/ptr_container/ptr_list.hpp>
      10             : 
      11             : #include <vector>
      12             : 
      13             : #include "base/bitset.h"
      14             : #include "base/index_map.h"
      15             : #include "base/queue_task.h"
      16             : 
      17             : class BgpServer;
      18             : class BgpUpdateSender;
      19             : class IPeerUpdate;
      20             : class RibOut;
      21             : class RibPeerSet;
      22             : 
      23             : //
      24             : // This class maintains state to generate updates for a DB partition for all
      25             : // RibOuts and IPeerUpdates in a BgpServer.  All BgpSenderPartitions work in
      26             : // parallel and maintain their own view of whether an IPeerUpdate is blocked,
      27             : // in sync etc.
      28             : //
      29             : // A BgpSenderPartition maintains two indexed maps for internal bookkeeping.
      30             : //
      31             : // o PeerStateMap allocates an index per IPeerUpdate to allow direct access to
      32             : //   the corresponding PeerState using the index.  The PeerState nested class
      33             : //   is described elsewhere.
      34             : // o RibStateMap allocates a bit index per RibOut and allows direct access to
      35             : //   the corresponding RibState using the index. The RibState nested class is
      36             : //   described elsewhere.
      37             : //
      38             : // BgpSenderPartition contains a WorkQueue of WorkBase entries to represent
      39             : // pending work. A WorkBase can either be a WorkRibOut, which corresponds to
      40             : // to a tail dequeue for a (RibOut, QueueId) or a WorkPeer which corresponds
      41             : // to a peer dequeue.
      42             : //
      43             : // A mutex is used to control access to the WorkQueue between producers that
      44             : // need to enqueue WorkBase entries and the Worker which dequeues the entries
      45             : // and processes them. The producers are the BgpExport class which creates a
      46             : // WorkRibOut entry after adding a RouteUpdate to an empty UpdateQueue, and
      47             : // IPeerUpdate class which creates a WorkPeer entry when it becomes unblocked.
      48             : //
      49             : class BgpSenderPartition {
      50             : public:
      51             :     BgpSenderPartition(BgpUpdateSender *sender, int index);
      52             :     ~BgpSenderPartition();
      53             : 
      54             :     void Add(RibOut *ribout, IPeerUpdate *peer);
      55             :     void Remove(RibOut *ribout, IPeerUpdate *peer);
      56             : 
      57             :     void RibOutActive(RibOut *ribout, int queue_id);
      58             : 
      59             :     void PeerSendReady(IPeerUpdate *peer);
      60             :     bool PeerIsSendReady(IPeerUpdate *peer) const;
      61             :     bool PeerIsRegistered(IPeerUpdate *peer) const;
      62             :     bool PeerInSync(IPeerUpdate *peer) const;
      63             : 
      64             :     bool CheckInvariants() const;
      65             : 
      66             :     int task_id() const;
      67      218668 :     int index() const { return index_; }
      68             : 
      69             :     // For unit testing.
      70             :     void set_disabled(bool disabled);
      71             : 
      72             : private:
      73             :     friend class BgpUpdateSenderTest;
      74             :     friend class RibOutUpdatesTest;
      75             : 
      76             :     struct WorkBase {
      77             :         enum Type {
      78             :             WPeer,
      79             :             WRibOut
      80             :         };
      81      612483 :         explicit WorkBase(Type type)
      82      612483 :             : type(type), valid(true) {
      83      612483 :         }
      84             :         Type type;
      85             :         bool valid;
      86             :     };
      87             : 
      88             :     struct WorkRibOut : public WorkBase {
      89      612041 :         WorkRibOut(RibOut *ribout, int queue_id)
      90      612041 :             : WorkBase(WRibOut), ribout(ribout), queue_id(queue_id) {
      91      612100 :         }
      92             :         RibOut *ribout;
      93             :         int queue_id;
      94             :     };
      95             : 
      96             :     struct WorkPeer : public WorkBase {
      97         390 :         explicit WorkPeer(IPeerUpdate *peer)
      98         390 :             : WorkBase(WPeer), peer(peer) {
      99         390 :         }
     100             :         IPeerUpdate *peer;
     101             :     };
     102             : 
     103             :     class PeerState;
     104             :     struct PeerRibState;
     105             :     class RibState;
     106             :     class Worker;
     107             : 
     108             :     typedef boost::ptr_list<WorkBase> WorkQueue;
     109             :     typedef IndexMap<IPeerUpdate *, PeerState> PeerStateMap;
     110             :     typedef IndexMap<RibOut *, RibState> RibStateMap;
     111             : 
     112             :     void MaybeStartWorker();
     113             :     std::unique_ptr<WorkBase> WorkDequeue();
     114             :     void WorkEnqueue(WorkBase *wentry);
     115             :     void WorkPeerEnqueue(IPeerUpdate *peer);
     116             :     void WorkPeerInvalidate(IPeerUpdate *peer);
     117             :     void WorkRibOutEnqueue(RibOut *ribout, int queue_id);
     118             :     void WorkRibOutInvalidate(RibOut *ribout);
     119             : 
     120             :     void UpdateRibOut(RibOut *ribout, int queue_id);
     121             :     void UpdatePeer(IPeerUpdate *peer);
     122             : 
     123             :     bool UpdatePeerQueue(IPeerUpdate *peer, PeerState *ps, int queue_id);
     124             : 
     125             :     void BuildSyncBitSet(const RibOut *ribout, RibState *rs, RibPeerSet *msync);
     126             : 
     127             :     void SetQueueActive(const RibOut *ribout, RibState *rs, int queue_id,
     128             :                         const RibPeerSet &munsync);
     129             :     void SetQueueActive(RibOut *ribout, int queue_id, IPeerUpdate *peer);
     130             :     bool IsQueueActive(RibOut *ribout, int queue_id, IPeerUpdate *peer);
     131             :     void SetSendBlocked(RibOut *ribout, int queue_id,
     132             :                         const RibPeerSet &blocked);
     133             :     void SetSendBlocked(const RibOut *ribout, RibState *rs, int queue_id,
     134             :                         const RibPeerSet &blocked);
     135             :     void SetQueueSync(PeerState *ps, int queue_id);
     136             : 
     137             :     BgpUpdateSender *sender_;
     138             :     int index_;
     139             :     bool running_;
     140             :     bool disabled_;
     141             :     WorkQueue work_queue_;
     142             :     Worker *worker_task_;
     143             :     PeerStateMap peer_state_imap_;
     144             :     RibStateMap rib_state_imap_;
     145             : 
     146             :     DISALLOW_COPY_AND_ASSIGN(BgpSenderPartition);
     147             : };
     148             : 
     149             : //
     150             : // This is a wrapper that hides the existence of multiple BgpSenderPartitions
     151             : // from client classes.  It relays APIs to appropriate/all BgpSenderPartition
     152             : // instance(s).
     153             : //
     154             : // The send ready WorkQueue is needed to process send ready notifications for
     155             : // IPeerUpdates in the context of bgp::SendReadyTask. This ensures that there
     156             : // are no concurrency issues in case the IPeerUpdate gets unblocked while we
     157             : // are still processing the previous WorkBase which caused it to get blocked
     158             : // in the first place.
     159             : //
     160             : class BgpUpdateSender {
     161             : public:
     162             :     explicit BgpUpdateSender(BgpServer *server);
     163             :     ~BgpUpdateSender();
     164             : 
     165             :     void Join(RibOut *ribout, IPeerUpdate *peer);
     166             :     void Leave(RibOut *ribout, IPeerUpdate *peer);
     167             : 
     168             :     void RibOutActive(int index, RibOut *ribout, int queue_id);
     169             :     void PeerSendReady(IPeerUpdate *peer);
     170             :     bool PeerIsRegistered(IPeerUpdate *peer) const;
     171             :     bool PeerInSync(IPeerUpdate *peer) const;
     172             : 
     173      218525 :     int task_id() const { return task_id_; }
     174             :     bool CheckInvariants() const;
     175             : 
     176             :     // For unit testing.
     177             :     void DisableProcessing();
     178             :     void EnableProcessing();
     179             : 
     180             : private:
     181             :     friend class BgpTestPeer;
     182             :     friend class BgpUpdateSenderTest;
     183             :     friend class RibOutUpdatesTest;
     184             : 
     185             :     bool SendReadyCallback(IPeerUpdate *peer);
     186          99 :     BgpSenderPartition *partition(int index) { return partitions_[index]; }
     187             : 
     188             :     BgpServer *server_;
     189             :     int task_id_;
     190             :     std::vector<BgpSenderPartition *> partitions_;
     191             :     WorkQueue<IPeerUpdate *> send_ready_queue_;
     192             : 
     193             :     DISALLOW_COPY_AND_ASSIGN(BgpUpdateSender);
     194             : };
     195             : 
     196             : #endif  // SRC_BGP_BGP_UPDATE_SENDER_H_

Generated by: LCOV version 1.14