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

Generated by: LCOV version 1.14