LCOV - code coverage report
Current view: top level - bgp - bgp_update_queue.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 17 20 85.0 %
Date: 2026-11-09 02:10:49 Functions: 2 2 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_QUEUE_H_
       7             : #define SRC_BGP_BGP_UPDATE_QUEUE_H_
       8             : 
       9             : #include <list>
      10             : #include <set>
      11             : #include <vector>
      12             : 
      13             : #include "bgp/bgp_update.h"
      14             : 
      15             : //
      16             : // Comparator used to order UpdateInfos in the UpdateQueue set container.
      17             : // Looks at the BgpAttr, Timestamp and the associated RouteUpdate but not
      18             : // the Label, in order to achieve optimal packing of BGP updates. Ignore
      19             : // the BgpAttr in case of XMPP since each item is self contained - there's
      20             : // no notion of common attributes for all items in an update message.
      21             : //
      22             : // Compare the UpdateInfo pointers themselves as the final tie-breaker to
      23             : // handle the case where there are 2 UpdateInfos with the same BgpAttr in
      24             : // the same RouteUpdate. This can happen if the label (or the set for ecmp
      25             : // nexthops in case of an XMPP ribout) for a route changes between the Join
      26             : // operations for 2 different sets of IPeerUpdates.
      27             : //
      28             : struct UpdateByAttrCmp {
      29     2166206 :     bool operator()(const UpdateInfo &lhs, const UpdateInfo &rhs) const {
      30     2166206 :         if (lhs.roattr.is_xmpp()) {
      31      713396 :             if (lhs.roattr.IsReachable() < rhs.roattr.IsReachable()) {
      32           0 :                 return true;
      33             :             }
      34      713368 :             if (lhs.roattr.IsReachable() > rhs.roattr.IsReachable()) {
      35       13616 :                 return false;
      36             :             }
      37             :         } else {
      38     1452798 :             if (lhs.roattr.attr() < rhs.roattr.attr()) {
      39       41710 :                 return true;
      40             :             }
      41     1410925 :             if (lhs.roattr.attr() > rhs.roattr.attr()) {
      42       56016 :                 return false;
      43             :             }
      44             :         }
      45     2054435 :         if (lhs.update->tstamp() < rhs.update->tstamp())  {
      46      367301 :             return true;
      47             :         }
      48     1687431 :         if (lhs.update->tstamp() > rhs.update->tstamp()) {
      49     1687311 :             return false;
      50             :         }
      51          40 :         if (lhs.update < rhs.update)  {
      52           0 :             return true;
      53             :         }
      54          40 :         if (lhs.update > rhs.update) {
      55           0 :             return false;
      56             :         }
      57          40 :         return (&lhs < &rhs);
      58             :     }
      59             : };
      60             : 
      61             : //
      62             : // This class implements an update queue for a RibOut.  A RibUpdateMonitor
      63             : // contains a vector of pointers to UpdateQueue. The UpdateQueue instances
      64             : // are created and the corresponding pointers added to the vector from the
      65             : // RibOutUpdates constructor.  The following relationships are relevant:
      66             : //
      67             : //     RibOut -> RibOutUpdates (1:N)
      68             : //     RibOutUpdates -> RibUpdateMonitor (1:1)
      69             : //     RibUpdateMonitor -> UpdateQueue (1:N)
      70             : //
      71             : // Each UpdateQueue has an id which indicates whether it's a BULK queue or
      72             : // an UPDATE queue.  A BULK queue is used for route refresh and also when
      73             : // a new peer comes up.
      74             : //
      75             : // An UpdateQueue contains an intrusive doubly linked list of UpdateEntry
      76             : // base elements, which could be either be UpdateMarker or RouteUpdate.
      77             : // This list is maintained in temporal order i.e. it's a FIFO.
      78             : //
      79             : // An UpdateQueue also has a intrusive set of UpdateInfo elements.  These
      80             : // are ordered by attribute, timestamp and the corresponding prefix. This
      81             : // container is used when building updates since it allows us to traverse
      82             : // prefixes grouped by attributes. The relationship between a RouteUpdate
      83             : // and UpdateInfo is described elsewhere.
      84             : //
      85             : // An UpdateQueue also maintains a mapping from a peer's bit position to
      86             : // it's UpdateMarker. Note that it's possible for multiple peers to point
      87             : // to the same marker.
      88             : //
      89             : // A special UpdateMarker called the tail marker is used as an easy way to
      90             : // keep track of whether the list is empty.  The tail marker is always the
      91             : // last marker in the list.  Another way to think about this is that all
      92             : // the RouteUpdates after the tail marker have not been seen by any peer.
      93             : // This property is maintained by making sure that when the update marker
      94             : // for a peer (or set of peers) reaches the tail marker, it's merged into
      95             : // the tail marker.
      96             : //
      97             : class UpdateQueue {
      98             : public:
      99             :     // Typedefs for the intrusive list.
     100             :     typedef boost::intrusive::member_hook<
     101             :         UpdateEntry,
     102             :         boost::intrusive::list_member_hook<>,
     103             :         &UpdateEntry::list_node
     104             :     > UpdateEntryNode;
     105             : 
     106             :     typedef boost::intrusive::list<UpdateEntry, UpdateEntryNode> UpdatesByOrder;
     107             : 
     108             :     // Typedefs for the intrusive set.
     109             :     typedef boost::intrusive::member_hook<UpdateInfo,
     110             :         boost::intrusive::set_member_hook<>,
     111             :         &UpdateInfo::update_node
     112             :     > UpdateSetNode;
     113             : 
     114             :     typedef boost::intrusive::set<UpdateInfo, UpdateSetNode,
     115             :         boost::intrusive::compare<UpdateByAttrCmp>
     116             :     > UpdatesByAttr;
     117             : 
     118             :     typedef std::vector<UpdateMarker *> MarkerList;
     119             : 
     120             :     UpdateQueue(const RibOut *ribout, int queue_id);
     121             :     ~UpdateQueue();
     122             : 
     123             :     bool Enqueue(RouteUpdate *rt_update);
     124             :     void Dequeue(RouteUpdate *rt_update);
     125             : 
     126             :     RouteUpdate *NextUpdate(UpdateEntry *upentry);
     127             :     UpdateEntry *NextEntry(UpdateEntry *upentry);
     128             : 
     129             :     void AttrDequeue(UpdateInfo *current_uinfo);
     130             :     UpdateInfo *AttrNext(UpdateInfo *current_uinfo);
     131             : 
     132             :     void AddMarker(UpdateMarker *marker, RouteUpdate *rt_update);
     133             :     void MoveMarker(UpdateMarker *marker, RouteUpdate *rt_update);
     134             :     void MarkerSplit(UpdateMarker *marker, const RibPeerSet &msplit);
     135             :     void MarkerMerge(UpdateMarker *dst_marker, UpdateMarker *src_marker,
     136             :                      const RibPeerSet &bitset);
     137             :     UpdateMarker *GetMarker(int bit);
     138             : 
     139             :     bool Join(int bit);
     140             :     void Leave(int bit);
     141             : 
     142             :     bool CheckInvariants() const;
     143             : 
     144     1217396 :     UpdateMarker *tail_marker() { return &tail_marker_; }
     145             : 
     146             :     bool empty() const;
     147             :     size_t size() const;
     148             :     size_t marker_count() const;
     149             : 
     150             : private:
     151             :     friend class BgpExportTest;
     152             :     friend class RibOutUpdatesTest;
     153             : 
     154             :     int queue_id_;
     155             :     bool encoding_is_xmpp_;
     156             :     uint64_t tstamp_;
     157             :     size_t marker_count_;
     158             :     UpdatesByOrder queue_;
     159             :     UpdatesByAttr attr_set_;
     160             :     MarkerList markers_;
     161             :     UpdateMarker tail_marker_;
     162             : 
     163             :     DISALLOW_COPY_AND_ASSIGN(UpdateQueue);
     164             : };
     165             : 
     166             : #endif  // SRC_BGP_BGP_UPDATE_QUEUE_H_

Generated by: LCOV version 1.14