LCOV - code coverage report
Current view: top level - bgp - bgp_ribout.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 93 97 95.9 %
Date: 2026-06-11 01:56:02 Functions: 65 66 98.5 %
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_RIBOUT_H_
       6             : #define SRC_BGP_BGP_RIBOUT_H_
       7             : 
       8             : #include <boost/scoped_ptr.hpp>
       9             : #include <boost/intrusive/slist.hpp>
      10             : 
      11             : #include <algorithm>
      12             : #include <string>
      13             : #include <vector>
      14             : 
      15             : #include "base/bitset.h"
      16             : #include "base/index_map.h"
      17             : #include "bgp/bgp_attr.h"
      18             : #include "bgp/bgp_proto.h"
      19             : #include "bgp/bgp_rib_policy.h"
      20             : #include "db/db_entry.h"
      21             : #include "net/tunnel_encap_type.h"
      22             : 
      23             : class IPeer;
      24             : class IPeerUpdate;
      25             : class RibOutUpdates;
      26             : class ShowRibOutStatistics;
      27             : class BgpTable;
      28             : class BgpExport;
      29             : class BgpRoute;
      30             : class BgpUpdateSender;
      31             : class RouteUpdate;
      32             : class UpdateInfoSList;
      33             : 
      34             : //
      35             : // This class represents the attributes for a ribout entry, including the
      36             : // label.  It is essentially a combination of a smart pointer to BgpAttr
      37             : // and a label. The label is not included in BgpAttr in order to maximize
      38             : // sharing of the BgpAttr.
      39             : //
      40             : class RibOutAttr {
      41             : public:
      42             :     // This nested class represents an ecmp element for a ribout entry. A
      43             :     // ribout entry keeps a vector of these elements. Each element stores
      44             :     // all per nexthop properties in addition to the nexthop address and
      45             :     // label.
      46             :     //
      47             :     // The origin_vn_index keeps track of the index of the VN from which
      48             :     // the BgpPath originated.  A value of -1 means that the VN is unknown.
      49             :     class NextHop {
      50             :         public:
      51             :             NextHop(const BgpTable *table, IpAddress address,
      52             :                 const MacAddress &mac, uint32_t label, uint32_t l3_label,
      53             :                 const ExtCommunity *ext_community,
      54             :                 const LargeCommunity *large_community, bool vrf_originated);
      55             : 
      56      539572 :             const IpAddress address() const { return address_; }
      57        9103 :             const MacAddress &mac() const { return mac_; }
      58      694478 :             uint32_t label() const { return label_; }
      59       11605 :             uint32_t l3_label() const { return l3_label_; }
      60             :             const Ip4Address &source_address() const { return source_address_; }
      61     1067916 :             int origin_vn_index() const { return origin_vn_index_; }
      62      960606 :             std::vector<std::string> encap() const { return encap_; }
      63      539805 :             std::vector<uint64_t> tag_list() const { return tag_list_; }
      64             : 
      65             :             int CompareTo(const NextHop &rhs) const;
      66             :             bool operator==(const NextHop &rhs) const;
      67             :             bool operator!=(const NextHop &rhs) const;
      68             :             bool operator<(const NextHop &rhs) const;
      69             : 
      70             :         private:
      71             :             IpAddress address_;
      72             :             MacAddress mac_;
      73             :             uint32_t label_;
      74             :             uint32_t l3_label_;
      75             :             Ip4Address source_address_;
      76             :             int origin_vn_index_;
      77             :             std::vector<std::string> encap_;
      78             :             std::vector<uint64_t> tag_list_;
      79             :     };
      80             : 
      81             :     typedef std::vector<NextHop> NextHopList;
      82             : 
      83             :     RibOutAttr();
      84             :     RibOutAttr(const RibOutAttr &rhs);
      85             :     RibOutAttr(const BgpRoute *route, const BgpAttr *attr, bool is_xmpp);
      86             :     RibOutAttr(const BgpTable *table, const BgpAttr *attr, uint32_t label,
      87             :         uint32_t l3_label = 0, bool is_xmpp = false);
      88             :     RibOutAttr(const BgpTable *table, const BgpRoute *route,
      89             :         const BgpAttr *attr, uint32_t label, bool include_nh = true,
      90             :         bool is_xmpp = false);
      91             : 
      92             :     RibOutAttr &operator=(const RibOutAttr &rhs);
      93      641898 :     bool operator==(const RibOutAttr &rhs) const { return CompareTo(rhs) == 0; }
      94      451797 :     bool operator!=(const RibOutAttr &rhs) const { return CompareTo(rhs) != 0; }
      95     6189712 :     bool IsReachable() const { return attr_out_.get() != NULL; }
      96             : 
      97     2164395 :     const NextHopList &nexthop_list() const { return nexthop_list_; }
      98     7960391 :     const BgpAttr *attr() const { return attr_out_.get(); }
      99        8618 :     void set_attr(const BgpTable *table, const BgpAttrPtr &attrp) {
     100        8618 :         set_attr(table, attrp, 0, 0, false, false);
     101        8618 :     }
     102          80 :     void set_attr(const BgpTable *table, const BgpAttrPtr &attrp,
     103             :         uint32_t label) {
     104          80 :         set_attr(table, attrp, label, 0, false, false);
     105          80 :     }
     106             :     void set_attr(const BgpTable *table, const BgpAttrPtr &attrp,
     107             :         uint32_t label, uint32_t l3_label, bool vrf_originated, bool is_xmpp);
     108             :     void set_source_address(Ip4Address source_address) {
     109             :         source_address_ = source_address;
     110             :     }
     111             : 
     112           0 :     void clear() {
     113           0 :         attr_out_.reset();
     114           0 :         nexthop_list_.clear();
     115           0 :     }
     116      559189 :     uint32_t label() const {
     117      559189 :         return nexthop_list_.empty() ? label_ : nexthop_list_[0].label();
     118             :     }
     119      354410 :     uint32_t l3_label() const {
     120      354410 :         return nexthop_list_.empty() ? l3_label_ : nexthop_list_[0].l3_label();
     121             :     }
     122      245830 :     const Ip4Address &source_address() const { return source_address_; }
     123        1287 :     Ip4Address *source_address() { return &source_address_; }
     124     2357207 :     bool is_xmpp() const { return is_xmpp_; }
     125      244999 :     bool vrf_originated() const { return vrf_originated_; }
     126      735362 :     const std::string &repr() const { return repr_; }
     127       31619 :     void set_repr(const std::string &repr, size_t pos = 0) const {
     128       31619 :         repr_.clear();
     129       31619 :         repr_.append(repr, pos, std::string::npos);
     130       31623 :     }
     131             : 
     132             : private:
     133             :     int CompareTo(const RibOutAttr &rhs) const;
     134             : 
     135             :     BgpAttrPtr attr_out_;
     136             :     NextHopList nexthop_list_;
     137             :     uint32_t label_;
     138             :     uint32_t l3_label_;
     139             :     Ip4Address source_address_;
     140             :     bool is_xmpp_;
     141             :     bool vrf_originated_;
     142             :     mutable std::string repr_;
     143             : };
     144             : 
     145             : //
     146             : // This class represents a bitset of peers within a RibOut. This is distinct
     147             : // from the GroupPeerSet in order to allow it to be denser. This is possible
     148             : // because not every peer in the group may be interested in every RibOut.
     149             : //
     150             : class RibPeerSet : public BitSet {
     151             : };
     152             : 
     153             : //
     154             : // This class represents information for a particular prefix that has been
     155             : // advertised to a set of peers.
     156             : //
     157             : // An AdvertiseInfo is part of a intrusive singly linked list container in
     158             : // the RouteState.  The RibPeerSet represents the set of peers to which the
     159             : // prefix has been advertised and the RibOutAttr represents the associated
     160             : // attributes.  This representation allows us to keep track of a different
     161             : // set of attributes for each set of peers.
     162             : //
     163             : struct AdvertiseInfo {
     164        1306 :     AdvertiseInfo() { }
     165      586676 :     explicit AdvertiseInfo(const RibOutAttr *roattr) : roattr(*roattr) { }
     166             :     AdvertiseInfo(const AdvertiseInfo &rhs)
     167             :         : bitset(rhs.bitset), roattr(rhs.roattr) {
     168             :     }
     169             : 
     170             :     // Intrusive slist node for RouteState.
     171             :     boost::intrusive::slist_member_hook<> slist_node;
     172             : 
     173             :     RibPeerSet bitset;
     174             :     RibOutAttr roattr;
     175             : };
     176             : 
     177             : //
     178             : // Disposer for AdvertiseInfo.
     179             : //
     180             : struct AdvertiseInfoDisposer {
     181      587508 :     void operator()(AdvertiseInfo *ainfo) { delete ainfo; }
     182             : };
     183             : 
     184             : //
     185             : // Wrapper for intrusive slist of AdvertiseInfos. Destructor automatically
     186             : // deletes any elements still on the slist.
     187             : //
     188             : // TBD: create a class template.
     189             : //
     190             : class AdvertiseSList {
     191             : public:
     192             :     typedef boost::intrusive::member_hook<
     193             :         AdvertiseInfo,
     194             :         boost::intrusive::slist_member_hook<>,
     195             :         &AdvertiseInfo::slist_node
     196             :     > Node;
     197             :     typedef boost::intrusive::slist<
     198             :         AdvertiseInfo,
     199             :         Node,
     200             :         boost::intrusive::linear<true>
     201             :     > List;
     202             : 
     203     2659372 :     AdvertiseSList() { }
     204     2659111 :     ~AdvertiseSList() { list_.clear_and_dispose(AdvertiseInfoDisposer()); }
     205             : 
     206     5577959 :     List *operator->() { return &list_; }
     207     7407711 :     const List *operator->() const { return &list_; }
     208             :     const List &list() const { return list_; }
     209     2169089 :     void swap(AdvertiseSList &adv_slist) { list_.swap(adv_slist.list_); }
     210             : 
     211             : private:
     212             :     List list_;
     213             : };
     214             : 
     215             : //
     216             : // This class represents per prefix information that been advertised to
     217             : // the peers in a RibOut.
     218             : //
     219             : // A RouteState is derived from a DBState which means that it is part of
     220             : // the state map within a DBEntry.  This allows the RouteState to be
     221             : // associated with a DBEntry using the listener id of the RibOut as the
     222             : // index. In the steady state i.e. when there are no pending updates the
     223             : // DBEntry maps the listener id for the RibOut to a RouteState.
     224             : //
     225             : // A RouteState maintains a singly linked list of AdvertiseInfo entries
     226             : // to keep track of the attributes that have been advertised to each set
     227             : // of peers.
     228             : //
     229             : class RouteState : public DBState {
     230             : public:
     231             :     RouteState();
     232             : 
     233         187 :     void SetHistory(AdvertiseSList &history) {
     234         187 :         assert(advertised_->empty());
     235         187 :         advertised_.swap(history);
     236         187 :     }
     237     1084160 :     void SwapHistory(AdvertiseSList &history) {
     238     1084160 :         advertised_.swap(history);
     239     1084130 :     }
     240             :     void MoveHistory(RouteUpdate *rt_update);
     241             :     const AdvertiseInfo *FindHistory(const RibOutAttr &roattr) const;
     242             :     bool CompareUpdateInfo(const UpdateInfoSList &uinfo_slist) const;
     243             : 
     244      460137 :     const AdvertiseSList &Advertised() const { return advertised_; }
     245      410362 :     AdvertiseSList &Advertised() { return advertised_; }
     246             : 
     247             : private:
     248             :     AdvertiseSList advertised_;
     249             :     DISALLOW_COPY_AND_ASSIGN(RouteState);
     250             : };
     251             : 
     252             : //
     253             : // This class represents per-table state for a collection of peers with the
     254             : // same export policy.  It is effectively a combination of RibExportPolicy
     255             : // and BgpTable. A RibOut has a 1:N association with RibOutUpdates wherein
     256             : // one entry is created per DB partition.
     257             : //
     258             : // A RibOut maintains a PeerStateMap to facilitate allocation and lookup of
     259             : // a bit index per peer in the RibOut.
     260             : //
     261             : class RibOut {
     262             : public:
     263             :     class PeerIterator {
     264             :     public:
     265     1077784 :         PeerIterator(const RibOut *ribout, const RibPeerSet &peer_set)
     266     1077784 :             : ribout_(ribout), peer_set_(peer_set) {
     267     1077784 :             index_ = peer_set_.find_first();
     268     1077781 :         }
     269     3311955 :         bool HasNext() const {
     270     3311955 :             return index_ != RibPeerSet::npos;
     271             :         }
     272     2234304 :         IPeerUpdate *Next() {
     273     2234304 :             IPeerUpdate *ptr = ribout_->GetPeer(index_);
     274     2234187 :             index_ = peer_set_.find_next(index_);
     275     2233715 :             return ptr;
     276             :         }
     277     2234353 :         int index() const { return index_; }
     278             : 
     279             :     private:
     280             :         const RibOut *ribout_;
     281             :         const RibPeerSet &peer_set_;
     282             :         size_t index_;
     283             :     };
     284             : 
     285             :     RibOut(BgpTable *table, BgpUpdateSender *sender,
     286             :            const RibExportPolicy &policy);
     287             :     ~RibOut();
     288             : 
     289             :     void RegisterListener();
     290             :     void Register(IPeerUpdate *peer);
     291             :     void Unregister(IPeerUpdate *peer);
     292             :     bool IsRegistered(IPeerUpdate *peer);
     293             :     void Deactivate(IPeerUpdate *peer);
     294             :     bool IsActive(IPeerUpdate *peer) const;
     295             :     void BuildSendReadyBitSet(const RibPeerSet &peerset,
     296             :         RibPeerSet *mready) const;
     297             : 
     298             :     IPeerUpdate *GetPeer(int index) const;
     299             :     int GetPeerIndex(IPeerUpdate *peer) const;
     300             : 
     301             :     // Returns a bitmask with all the peers that are advertising this RibOut.
     302             :     const RibPeerSet &PeerSet() const;
     303             :     void GetSubsetPeerSet(RibPeerSet *peerset, const IPeerUpdate *cpeer) const;
     304             : 
     305     7025124 :     BgpTable *table() { return table_; }
     306      630401 :     const BgpTable *table() const { return table_; }
     307      617815 :     BgpUpdateSender *sender() { return sender_; }
     308             : 
     309      698087 :     const RibExportPolicy &ExportPolicy() const { return policy_; }
     310             : 
     311             :     int RouteAdvertiseCount(const BgpRoute *rt) const;
     312             :     uint32_t GetQueueSize() const;
     313             : 
     314     6679209 :     DBTableBase::ListenerId listener_id() const { return listener_id_; }
     315       33694 :     const std::string &ToString() const { return name_; }
     316             : 
     317     2949942 :     RibOutUpdates *updates(int idx) { return updates_[idx]; }
     318        9063 :     const RibOutUpdates *updates(int idx) const { return updates_[idx]; }
     319      900467 :     BgpExport *bgp_export() { return bgp_export_.get(); }
     320             : 
     321      906166 :     BgpProto::BgpPeerType peer_type() const { return policy_.type; }
     322      337331 :     as_t peer_as() const { return policy_.as_number; }
     323      200918 :     as_t local_as() const { return policy_.local_as_number; }
     324      538032 :     bool as_override() const { return policy_.as_override; }
     325        5727 :     bool llgr() const { return policy_.llgr; }
     326      311195 :     bool as4_supported() const { return policy_.as4_supported; }
     327           1 :     void set_as4_supported(bool as4) { policy_.as4_supported = as4; }
     328      204946 :     const IpAddress &nexthop() const { return policy_.nexthop; }
     329     2052933 :     bool IsEncodingXmpp() const {
     330     2052933 :         return (policy_.encoding == RibExportPolicy::XMPP);
     331             :     }
     332     1848981 :     bool IsEncodingBgp() const {
     333     1848981 :         return (policy_.encoding == RibExportPolicy::BGP);
     334             :     }
     335           4 :     std::string EncodingString() const {
     336           4 :         return IsEncodingXmpp() ? "XMPP" : "BGP";
     337             :     }
     338      245226 :     bool remove_private_enabled() const {
     339      245226 :         return policy_.remove_private.enabled;
     340             :     }
     341         114 :     bool remove_private_all() const { return policy_.remove_private.all; }
     342         114 :     bool remove_private_replace() const {
     343         114 :         return policy_.remove_private.replace;
     344             :     }
     345         114 :     bool remove_private_peer_loop_check() const {
     346         114 :         return policy_.remove_private.peer_loop_check;
     347             :     }
     348       77690 :     uint32_t cluster_id() const { return policy_.cluster_id; }
     349             : 
     350             :     void FillStatisticsInfo(std::vector<ShowRibOutStatistics> *sros_list) const;
     351             : 
     352             : private:
     353             :     struct PeerState {
     354       93130 :         explicit PeerState(IPeerUpdate *key) : peer(key), index(-1) {
     355       93130 :         }
     356       93130 :         void set_index(int idx) { index = idx; }
     357             :         IPeerUpdate *peer;
     358             :         int index;
     359             :     };
     360             :     typedef IndexMap<IPeerUpdate *, PeerState, RibPeerSet> PeerStateMap;
     361             : 
     362             :     BgpTable *table_;
     363             :     BgpUpdateSender *sender_;
     364             :     RibExportPolicy policy_;
     365             :     std::string name_;
     366             :     PeerStateMap state_map_;
     367             :     RibPeerSet active_peerset_;
     368             :     int listener_id_;
     369             :     std::vector<RibOutUpdates *> updates_;
     370             :     boost::scoped_ptr<BgpExport> bgp_export_;
     371             : 
     372             :     DISALLOW_COPY_AND_ASSIGN(RibOut);
     373             : };
     374             : 
     375             : #endif  // SRC_BGP_BGP_RIBOUT_H_

Generated by: LCOV version 1.14