LCOV - code coverage report
Current view: top level - bgp/routing-instance - rtarget_group_mgr.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 13 13 100.0 %
Date: 2026-06-22 02:21:21 Functions: 10 10 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_ROUTING_INSTANCE_RTARGET_GROUP_MGR_H_
       6             : #define SRC_BGP_ROUTING_INSTANCE_RTARGET_GROUP_MGR_H_
       7             : 
       8             : #include <boost/ptr_container/ptr_map.hpp>
       9             : #include <boost/shared_ptr.hpp>
      10             : #include <sandesh/sandesh_types.h>
      11             : #include <sandesh/sandesh.h>
      12             : #include <sandesh/sandesh_trace.h>
      13             : 
      14             : #include <map>
      15             : #include <set>
      16             : #include <string>
      17             : #include <vector>
      18             : #include <mutex>
      19             : 
      20             : #include "base/queue_task.h"
      21             : #include "base/lifetime.h"
      22             : #include "bgp/community.h"
      23             : #include "bgp/routing-instance/rtarget_group.h"
      24             : #include "bgp/rtarget/rtarget_address.h"
      25             : #include "db/db_table_partition.h"
      26             : 
      27             : class BgpRoute;
      28             : class BgpServer;
      29             : class BgpTable;
      30             : class RibOut;
      31             : class RibPeerSet;
      32             : class RTargetRoute;
      33             : class RTargetGroupMgr;
      34             : class TaskTrigger;
      35             : 
      36             : //
      37             : // This keeps track of the RTargetGroupMgr's listener state for a BgpTable.
      38             : // The BgpTable could be a VPN table or bgp.rtarget.0.
      39             : //
      40             : class RtGroupMgrTableState {
      41             : public:
      42             :     RtGroupMgrTableState(BgpTable *table, DBTableBase::ListenerId id);
      43             :     ~RtGroupMgrTableState();
      44             : 
      45             :     void ManagedDelete();
      46             : 
      47      791211 :     DBTableBase::ListenerId GetListenerId() const {
      48      791211 :         return id_;
      49             :     }
      50             : 
      51             : private:
      52             :     DBTableBase::ListenerId id_;
      53             :     LifetimeRef<RtGroupMgrTableState> table_delete_ref_;
      54             : 
      55             :     DISALLOW_COPY_AND_ASSIGN(RtGroupMgrTableState);
      56             : };
      57             : 
      58             : //
      59             : // The RTargetGroupMgr sets VPNRouteState on dependent VPN BgpRoutes.  This
      60             : // VPNRouteState is simply a list of the current RouteTargets that we have
      61             : // seen and processed for the BgpRoute. When the RouteTargets for a BgpRoute
      62             : // get updated, the VPNRouteState is used to update the appropriate RtGroups
      63             : // list of dependent VPN routes.
      64             : //
      65             : class VpnRouteState : public DBState {
      66             : public:
      67             :     typedef std::set<RouteTarget> RTargetList;
      68             : 
      69             :     void AddRouteTarget(RTargetGroupMgr *mgr, int part_id, BgpRoute *rt,
      70             :         RTargetList::const_iterator it);
      71             :     void DeleteRouteTarget(RTargetGroupMgr *mgr, int part_id, BgpRoute *rt,
      72             :         RTargetList::const_iterator it);
      73             : 
      74             : private:
      75             :     friend class RTargetGroupMgr;
      76             : 
      77      592124 :     const RTargetList *GetList() const { return &list_; }
      78      592280 :     RTargetList *GetMutableList() { return &list_; }
      79             : 
      80             :     RTargetList list_;
      81             : };
      82             : 
      83             : //
      84             : // The RTargetGroupMgr sets RTargetState on RTargetRoutes. This RTargetState
      85             : // is the current InterestedPeerList that we have seen and processed for the
      86             : // RTargetRoute.  When a BgpPath is added or deleted for a RTargetRoute the
      87             : // RTargetState is used to update the appropriate RtGroups InterestedPeerList.
      88             : //
      89             : class RTargetState : public DBState {
      90             : public:
      91             :     void AddInterestedPeer(RTargetGroupMgr *mgr, RtGroup *rtgroup,
      92             :         RTargetRoute *rt, RtGroup::InterestedPeerList::const_iterator it);
      93             :     void DeleteInterestedPeer(RTargetGroupMgr *mgr, RtGroup *rtgroup,
      94             :         RTargetRoute *rt, RtGroup::InterestedPeerList::iterator it);
      95             : 
      96             : private:
      97             :     friend class RTargetGroupMgr;
      98             : 
      99      102940 :     const RtGroup::InterestedPeerList *GetList() const { return &list_; }
     100      102940 :     RtGroup::InterestedPeerList *GetMutableList() { return &list_; }
     101             : 
     102             :     RtGroup::InterestedPeerList list_;
     103             : };
     104             : 
     105             : struct RtGroupMgrReq {
     106             :     enum RequestType {
     107             :         SHOW_RTGROUP,
     108             :         SHOW_RTGROUP_PEER,
     109             :         SHOW_RTGROUP_SUMMARY,
     110             :     };
     111             : 
     112             :     RtGroupMgrReq(RequestType type, SandeshResponse *resp,
     113             :         const std::string &param = std::string())
     114             :         : type_(type), snh_resp_(resp), param_(param) {
     115             :     }
     116             : 
     117             :     RequestType type_;
     118             :     SandeshResponse *snh_resp_;
     119             :     std::string param_;
     120             : 
     121             : private:
     122             :     DISALLOW_COPY_AND_ASSIGN(RtGroupMgrReq);
     123             : };
     124             : 
     125             : //
     126             : // This class implements the core logic required to construct and update the
     127             : // policy for RouteTarget based constrained distribution of BGP VPN routes.
     128             : // This policy is applied when exporting BgpRoutes from VPN tables such as
     129             : // bgp.l3vpn.0 and bgp.evpn.0.
     130             : //
     131             : // The RtGroupMap keeps track of all RtGroups using a map of RouteTarget to
     132             : // RtGroup pointers. A RtGroup is created the first time it's needed. There
     133             : // are 3 possible triggers:
     134             : //
     135             : // 1. RoutePathReplicator needs to associate BgpTables with the RouteTarget.
     136             : // 2. A VPN BgpRoute with the RouteTarget as one of it's targets is received.
     137             : // 3. A RTargetRoute for the RouteTarget is received.
     138             : //
     139             : // The users of RtGroups invoke RemoveRtGroup when they no longer need it. If
     140             : // the RtGroup is eligible to be deleted i.e. it has no state associated with
     141             : // it, it gets added to the RtGroupRemoveList.  The list is processed in the
     142             : // context of the bgp::RTFilter task.  The RtGroup is deleted if it's still
     143             : // eligible for deletion i.e. it hasn't been resurrected after being enqueued.
     144             : // Processing RtGroup deletion in this manner avoids race conditions wherein
     145             : // one db::DBTable task deletes an RtGroup while another db::DBTable task has
     146             : // a pointer to it.
     147             : //
     148             : // A mutex is used to protect the RtGroupMap since LocateRtGroup/GetRtGroup
     149             : // is called from multiple db::DBTable tasks concurrently. The same mutex is
     150             : // also used to protect the RtGroupRemoveList as multiple db::DBTable tasks
     151             : // can try to add RtGroups to the list concurrently.
     152             : //
     153             : // The RTargetGroupMgr needs to register as a listener for all VPN tables and
     154             : // for bgp.rtarget.0. It keeps track of it's listener ids for the tables using
     155             : // the RtGroupMgrTableStateList.  Note that it does not need to register for
     156             : // any VRF tables, only for the VPN tables in the master routing instance and
     157             : // bgp.rtarget.0 (which also belongs to the master instance).
     158             : //
     159             : // The RTargetGroupMgr registers as a listener for all VPN tables so that it
     160             : // can maintain the list of the dependent VPN routes for a given RouteTarget.
     161             : // The actual dependency is maintained in the associated RtGroup object based
     162             : // on APIs invoked from the RTargetGroupMgr.
     163             : //
     164             : // The RTargetGroupMgr sets VPNRouteState on dependent VPN BgpRoutes.  This
     165             : // VPNRouteState is simply a list of the current RouteTargets that we have
     166             : // seen and processed for the BgpRoute. When the RouteTargets for a BgpRoute
     167             : // get updated, the VPNRouteState is used to update the appropriate RtGroups
     168             : // list of dependent VPN routes.
     169             : //
     170             : // The VPNRouteState and the list of dependent VPN BgpRoutes are updated from
     171             : // the context of the db::DBTable task i.e. when processing notification for a
     172             : // VPN BgpRoute.
     173             : //
     174             : // The RTargetGroupMgr also registers as a listener for bgp.rtarget.0 so that
     175             : // it can maintain the list of interested peers for a given RouteTarget.  The
     176             : // actual dependency is maintained in the associated RtGroup object based on
     177             : // APIs invoked from the RTargetGroupMgr.
     178             : //
     179             : // The RTargetGroupMgr sets RTargetState on RTargetRoutes. This RTargetState
     180             : // is the current InterestedPeerList that we have seen and processed for the
     181             : // RTargetRoute.  When a BgpPath is added or deleted for a RTargetRoute the
     182             : // RTargetState is used to update the appropriate RtGroups InterestedPeerList.
     183             : //
     184             : // The RTargetState and the InterestedPeerList are not updated directly from
     185             : // the context of the db::DBTable task.  Instead, the RTargetRoute is added
     186             : // to the RTargetRouteTriggerList. The RTargetRouteTriggerList keeps track of
     187             : // RTargetRoutes that need to be processed and is evaluated from context of
     188             : // bgp::RTFilter task. This lets us absorb multiple changes to a RTargetRoute
     189             : // in one shot.  Since the bgp::RTFilter task is mutually exclusive with the
     190             : // db::DBTable task, this also prevents any concurrency issues wherein the
     191             : // BgpExport::Export method for the VPN tables accesses the InterestedPeerList
     192             : // for an RtGroups while it's being modified on account of changes to the
     193             : // RTargetRoute.
     194             : //
     195             : // When a RTargetRoute in the RTargetRouteTriggerList is processed, we figure
     196             : // out if InterestedPeerList has changed.  If so, the RouteTarget in question
     197             : // is added to all the RouteTargetTriggerLists, one per DBTable partition. The
     198             : // RouteTargetTriggerList keeps track of RouteTargets whose dependent BgpRoutes
     199             : // need to be re-evaluated.  It gets processed in the context of db::DBTable
     200             : // task. All RouteTargetTriggerLists can be processed concurrently since they
     201             : // work on different partitions.  As db::DBTable tasks are mutually exclusive
     202             : // with the bgp::RTFilter task, it is guaranteed that a RouteTargetTriggerList
     203             : // does not get modified while it's being processed.
     204             : //
     205             : class RTargetGroupMgr {
     206             : public:
     207             :     typedef boost::ptr_map<const RouteTarget, RtGroup> RtGroupMap;
     208             :     typedef RtGroupMap::const_iterator const_iterator;
     209             : 
     210             :     explicit RTargetGroupMgr(BgpServer *server);
     211             :     virtual ~RTargetGroupMgr();
     212             : 
     213       41135 :     bool empty() const { return rtgroup_map_.empty(); }
     214             :     const_iterator begin() const { return rtgroup_map_.begin(); }
     215        4598 :     const_iterator end() const { return rtgroup_map_.end(); }
     216         502 :     const_iterator lower_bound(const RouteTarget &rt) const {
     217         502 :         return rtgroup_map_.lower_bound(rt);
     218             :     }
     219             : 
     220             :     // RtGroup
     221             :     RtGroup *GetRtGroup(const RouteTarget &rt);
     222             :     RtGroup *GetRtGroup(const ExtCommunity::ExtCommunityValue &comm);
     223             :     RtGroup *LocateRtGroup(const RouteTarget &rt);
     224             :     void NotifyRtGroupUnlocked(const RouteTarget &rt);
     225             :     void NotifyRtGroup(const RouteTarget &rt);
     226             :     void RemoveRtGroup(const RouteTarget &rt);
     227             : 
     228             :     virtual void GetRibOutInterestedPeers(RibOut *ribout,
     229             :              const ExtCommunity *ext_community,
     230             :              const RibPeerSet &peerset, RibPeerSet *new_peerset);
     231             :     void Enqueue(RtGroupMgrReq *req);
     232             :     void Initialize();
     233             :     void ManagedDelete();
     234     1545173 :     bool IsRTargetRoutesProcessed() const {
     235     1545173 :         return rtarget_route_list_.empty();
     236             :     }
     237             : 
     238             : private:
     239             :     friend class BgpXmppRTargetTest;
     240             :     friend class ReplicationTest;
     241             : 
     242             :     typedef std::map<BgpTable *,
     243             :             RtGroupMgrTableState *> RtGroupMgrTableStateList;
     244             :     typedef std::set<RTargetRoute *> RTargetRouteTriggerList;
     245             :     typedef std::set<RouteTarget> RouteTargetTriggerList;
     246             :     typedef std::set<RtGroup *> RtGroupRemoveList;
     247             : 
     248             :     void RTargetDepSync(DBTablePartBase *root, BgpRoute *rt,
     249             :                         DBTableBase::ListenerId id, VpnRouteState *dbstate,
     250             :                         const VpnRouteState::RTargetList *future);
     251             :     void RTargetPeerSync(BgpTable *table, RTargetRoute *rt,
     252             :                          DBTableBase::ListenerId id, RTargetState *dbstate,
     253             :                          const RtGroup::InterestedPeerList *future);
     254             :     void BuildRTargetDistributionGraph(BgpTable *table, RTargetRoute *rt,
     255             :                                        DBTableBase::ListenerId id);
     256       58391 :     BgpServer *server() { return server_; }
     257             : 
     258             :     bool ProcessRTargetRouteList();
     259             :     void DisableRTargetRouteProcessing();
     260             :     void EnableRTargetRouteProcessing();
     261             :     bool IsRTargetRouteOnList(RTargetRoute *rt) const;
     262             : 
     263             :     bool ProcessRouteTargetList(int part_id);
     264             :     void AddRouteTargetToLists(const RouteTarget &rtarget);
     265             :     void DisableRouteTargetProcessing();
     266             :     void EnableRouteTargetProcessing();
     267             :     bool IsRouteTargetOnList(const RouteTarget &rtarget) const;
     268             : 
     269             :     bool ProcessRtGroupList();
     270             :     void DisableRtGroupProcessing();
     271             :     void EnableRtGroupProcessing();
     272             :     bool IsRtGroupOnList(RtGroup *rtgroup) const;
     273             : 
     274             :     DBTableBase::ListenerId GetListenerId(BgpTable *table);
     275             :     void UnregisterTables();
     276             :     bool VpnRouteNotify(DBTablePartBase *root, DBEntryBase *entry);
     277             :     bool RTargetRouteNotify(DBTablePartBase *root, DBEntryBase *entry);
     278             :     bool RequestHandler(RtGroupMgrReq *req);
     279             : 
     280             :     BgpServer *server_;
     281             :     std::mutex mutex_;
     282             :     RtGroupMap rtgroup_map_;
     283             :     RtGroupMgrTableStateList table_state_;
     284             :     boost::scoped_ptr<TaskTrigger> rtarget_route_trigger_;
     285             :     boost::scoped_ptr<TaskTrigger> remove_rtgroup_trigger_;
     286             :     std::vector<boost::shared_ptr<TaskTrigger> > rtarget_dep_triggers_;
     287             :     RTargetRouteTriggerList rtarget_route_list_;
     288             :     std::vector<RouteTargetTriggerList> rtarget_trigger_lists_;
     289             :     RtGroupRemoveList rtgroup_remove_list_;
     290             :     LifetimeRef<RTargetGroupMgr> master_instance_delete_ref_;
     291             : 
     292             :     DISALLOW_COPY_AND_ASSIGN(RTargetGroupMgr);
     293             : };
     294             : 
     295             : #endif  // SRC_BGP_ROUTING_INSTANCE_RTARGET_GROUP_MGR_H_

Generated by: LCOV version 1.14