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

Generated by: LCOV version 1.14