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

Generated by: LCOV version 1.14