LCOV - code coverage report
Current view: top level - bgp - bgp_mvpn.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 25 25 100.0 %
Date: 2026-11-09 02:10:49 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #ifndef SRC_BGP_BGP_MVPN_H_
       7             : #define SRC_BGP_BGP_MVPN_H_
       8             : 
       9             : #include <map>
      10             : #include <set>
      11             : #include <sstream>
      12             : #include <string>
      13             : #include <vector>
      14             : #include <atomic>
      15             : #include <shared_mutex>
      16             : #include <boost/scoped_ptr.hpp>
      17             : 
      18             : #include "base/lifetime.h"
      19             : #include "base/address.h"
      20             : #include "bgp/bgp_attr.h"
      21             : #include "bgp/bgp_table.h"
      22             : #include "db/db_entry.h"
      23             : 
      24             : class BgpPath;
      25             : class BgpRoute;
      26             : class BgpServer;
      27             : class BgpTable;
      28             : class ErmVpnRoute;
      29             : class ErmVpnTable;
      30             : struct MvpnDBState;
      31             : class MvpnManager;
      32             : class MvpnManagerPartition;
      33             : class MvpnPrefix;
      34             : class MvpnProjectManager;
      35             : class MvpnProjectManagerPartition;
      36             : class MvpnRoute;
      37             : class MvpnState;
      38             : class MvpnTable;
      39             : class PathResolver;
      40             : class RoutingInstance;
      41             : class UpdateInfo;
      42             : 
      43             : typedef boost::intrusive_ptr<MvpnState> MvpnStatePtr;
      44             : 
      45             : // This struct represents a MVPN Neighbor discovered using BGP or using auto
      46             : // exported routes from one routing-instance into another.
      47             : //
      48             : // Each received Type1 Intra AS Auto-Discovery ad Type2 Inter AS Auto Discovery
      49             : // routes from MVPN BGP Peers is maintained as MVPN neighbors inside a map in
      50             : // each MvpnManager object. RouteDistinguisher is used as the key to this map.
      51             : //
      52             : // Typically neighbor information is used in mvpn when the Type I and Type II
      53             : // routes also carry PMSI tunnel information to send multicast traffic to all
      54             : // intended receivers. In Phase I, PMSI information is not sent encoded inside
      55             : // Type I/Type II AD routes. Also, in phase I, PMSI information if received in
      56             : // Type I/Type II routes from remote neighbors is not processed.
      57             : struct MvpnNeighbor {
      58             : public:
      59             :     MvpnNeighbor();
      60             :     MvpnNeighbor(const RouteDistinguisher &rd, const IpAddress &originator);
      61             :     std::string ToString() const;
      62             :     const RouteDistinguisher &rd() const;
      63             :     const IpAddress &originator() const;
      64             :     uint32_t source_as() const;
      65             :     bool operator==(const MvpnNeighbor &rhs) const;
      66             : 
      67             : private:
      68             :     friend class MvpnManagerPartition;
      69             : 
      70             :     RouteDistinguisher rd_;
      71             :     IpAddress originator_;
      72             :     uint32_t source_as_;
      73             : };
      74             : 
      75             : // This class manages Mvpn routes with in a partition of an MvpnTable.
      76             : //
      77             : // It holds a back pointer to the parent MvpnManager class along with the
      78             : // partition id this object belongs to.
      79             : //
      80             : // Upon route change notification, based on the route-type for which a route
      81             : // notification has been received, different set of actions are undertaken in
      82             : // this class. This class only handles routes in which customer 'Group' info is
      83             : // encoded, such as Type3 S-PMSI routes.
      84             : //
      85             : // Notification for a Type7 SourceTreeJoinRoute route add/change/delete
      86             : //     When this route is successfully imported into a vrf, new Type3 S-PMSI
      87             : //     route is originated/updated into that vrf.mvpn.0 if there is at least
      88             : //     one associated Join route from the agent with flags marked as "Sender"
      89             : //     or "SenderAndReciver".
      90             : //
      91             : // Notification for a Type3 S-PMSI route add/change/delete
      92             : //     When sender indicates that it has a sender for a particular <S,G> entry,
      93             : //     (With Leaf-Information required in the PMSI tunnel attribute), then this
      94             : //     class originates/updates a new Type4 LeafAD route into vrf.mvpn.0 table.
      95             : //     LeafAD route however is originated only if a usuable GlobalErmVpnRoute
      96             : //     is avaiable for stitching. On the other hand, if such a route was already
      97             : //     originated before and now is no longer feasible, it is deleted instead.
      98             : //
      99             : // Notification for a Type4 Leaf AD route add/change/delete
     100             : //     When leaf-ad routes are imported into a vrf and notified, the routes are
     101             : //     stored inside a map using route as the key and best path attributes as
     102             : //     values in the associated MvpnState. If the route is deleted, then it is
     103             : //     deleted from the map as well. If a usable Type5 source active route is
     104             : //     present in the vrf, then it is notified so that sender agent can be
     105             : //     updated with the right set of path attributes (PMSI) in order to be able
     106             : //     to replicate multicast traffic in the data plane.
     107             : class MvpnManagerPartition {
     108             : public:
     109             :     MvpnManagerPartition(MvpnManager *manager, int part_id);
     110             :     virtual ~MvpnManagerPartition();
     111             :     MvpnProjectManagerPartition *GetProjectManagerPartition();
     112             :     const MvpnProjectManagerPartition *GetProjectManagerPartition() const;
     113             : 
     114             : private:
     115             :     friend class MvpnManager;
     116             : 
     117             :     MvpnTable *table();
     118             :     int listener_id() const;
     119             : 
     120             :     void ProcessType3SPMSIRoute(MvpnRoute *spmsi_rt);
     121             :     void ProcessType4LeafADRoute(MvpnRoute *leaf_ad);
     122             :     void ProcessType5SourceActiveRoute(MvpnRoute *join_rt);
     123             :     void ProcessType7SourceTreeJoinRoute(MvpnRoute *join_rt);
     124             : 
     125             :     MvpnStatePtr GetState(MvpnRoute *route);
     126             :     MvpnStatePtr GetState(MvpnRoute *route) const;
     127             :     MvpnStatePtr LocateState(MvpnRoute *route);
     128             :     void NotifyForestNode(const Ip4Address &source, const Ip4Address &group);
     129             :     bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label,
     130             :             Ip4Address *address, std::vector<std::string> *encap) const;
     131             : 
     132             :     MvpnManager *manager_;
     133             :     int part_id_;
     134             : 
     135             :     DISALLOW_COPY_AND_ASSIGN(MvpnManagerPartition);
     136             : };
     137             : 
     138             : // This class manages MVPN routes for a given vrf.mvpn.0 table.
     139             : //
     140             : // In each *.mvpn.0 table, an instance of this class is created when ever the
     141             : // mvpn table itself is created (which happens when its parent routing-instance
     142             : // gets created.
     143             : //
     144             : // This class allocated one instance of MvpnManagerPartition for each DB
     145             : // partition. While all <S,G> specific operations are essentially manages inside
     146             : // MvpnManagerPartition object (in order to get necessary protection from
     147             : // concurrency across different db partitions), all other operations which are
     148             : // <S,G> agnostic are mainly handled in this class.
     149             : //
     150             : // Specifically, all MVPN BGP neighbors are maintained in std::map NeighborMap.
     151             : // Neighbors are created or updated when Type1/Type2 paths are received and are
     152             : // deleted when those routes are deleted. All access to this map is protected
     153             : // by a mutex because even though the map itself may be created, updated, or
     154             : // deleted always serially from with in the same db task, map will get accessed
     155             : // (read) concurrently from task running of different DB partitions.
     156             : //
     157             : // This class also provides DeleteActor and maintains a LifetimeRef to parent
     158             : // MvpnTable object in order to ensure orderly cleanup during table deletion.
     159             : class MvpnManager {
     160             : public:
     161             :     typedef std::vector<MvpnManagerPartition *> PartitionList;
     162             :     typedef PartitionList::const_iterator const_iterator;
     163             :     typedef std::map<RouteDistinguisher, MvpnNeighbor> NeighborMap;
     164             : 
     165             :     MvpnManager(MvpnTable *table, ErmVpnTable *ermvpn_table);
     166             :     virtual ~MvpnManager();
     167             :     bool FindNeighbor(const RouteDistinguisher &rd, MvpnNeighbor *nbr) const;
     168             :     MvpnProjectManager *GetProjectManager();
     169             :     void ManagedDelete();
     170             :     BgpRoute *RouteReplicate(BgpServer *server, BgpTable *src_table,
     171             :         BgpRoute *source_rt, const BgpPath *src_path, ExtCommunityPtr comm);
     172             :     void ResolvePath(RoutingInstance *rtinstance, BgpRoute *rt, BgpPath *path);
     173             :     MvpnTable *table();
     174             :     const MvpnTable *table() const;
     175             :     int listener_id() const;
     176             :     virtual void Terminate();
     177             :     virtual void Initialize();
     178             :     size_t neighbors_count() const;
     179             :     const NeighborMap &neighbors() const;
     180             :     void ReOriginateType1Route(const Ip4Address &old_identifier);
     181             :     void OriginateType1Route();
     182             :     bool MayDelete() const;
     183             :     const LifetimeActor *deleter() const;
     184             :     bool deleted() const;
     185             :     LifetimeActor *deleter();
     186             :     virtual void UpdateSecondaryTablesForReplication(MvpnRoute *rt,
     187             :             BgpTable::TableSet *secondary_tables) const;
     188           2 :     std::shared_mutex &neighbors_mutex() { return neighbors_mutex_; }
     189             : 
     190             : private:
     191             :     friend class MvpnManagerPartition;
     192             :     class DeleteActor;
     193             : 
     194             :     void AllocPartitions();
     195             :     void FreePartitions();
     196             :     void ProcessType1ADRoute(MvpnRoute *route);
     197             :     void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry);
     198             :     bool FindResolvedNeighbor(const BgpPath *path,
     199             :                               MvpnNeighbor *neighbor) const;
     200             :     void SetDBState(MvpnRoute *route, MvpnDBState *mvpn_dbstate);
     201             :     void ClearDBState(MvpnRoute *route);
     202             : 
     203             :     MvpnTable *table_;
     204             :     ErmVpnTable *ermvpn_table_;
     205             :     int listener_id_;
     206             :     int identifier_listener_id_;
     207             :     std::atomic<int> db_states_count_;
     208             :     PartitionList partitions_;
     209             : 
     210             :     NeighborMap neighbors_;
     211             :     mutable std::shared_mutex neighbors_mutex_;
     212             : 
     213             :     boost::scoped_ptr<DeleteActor> deleter_;
     214             :     LifetimeRef<MvpnManager> table_delete_ref_;
     215             :     LifetimeRef<MvpnManager> ermvpn_table_delete_ref_;
     216             : 
     217             :     DISALLOW_COPY_AND_ASSIGN(MvpnManager);
     218             : };
     219             : 
     220             : // This class holds Mvpn state for a particular <S,G> at any given time.
     221             : //
     222             : // In MVPN state machinery, different types of routes are sent and received at
     223             : // different phases of processing. This class holds all relevant information
     224             : // associated with an <S,G>.
     225             : //
     226             : // This is a refcounted class which is referred by DB States of different
     227             : // routes. When the refcount reaches 0, (last referring db state is deleted),
     228             : // this object is deleted from the container map and then destroyed.
     229             : //
     230             : // global_ermvpn_tree_rt_
     231             : //     This is a reference to GlobalErmVpnRoute associated with the ErmVpnTree
     232             : //     used in the data plane for this <S,G>. This route is created/updated
     233             : //     when ErmVpn notifies changes to ermvpn routes.
     234             : //
     235             : // spmsi_rt_
     236             : //     This is the 'only' Type3 SPMSI sender route originated for this S,G.
     237             : //     When an agent indicates that it has an active sender for a particular
     238             : //     <S,G> via Join route, then this route is originated (if there is atleast
     239             : //     one active receiver)
     240             : //
     241             : // spmsi_routes_received_
     242             : //     This is a set of all Type3 spmsi routes received for this <S-G>. It is
     243             : //     possible that when these routes are received, then there is no ermvpn
     244             : //     tree route to use for forwarding in the data plane. In such a case, later
     245             : //     when global_ermvpn_tree_rt_ does get updated, all leaf ad routes in this
     246             : //     set are notified and re-evaluated.
     247             : //
     248             : // leafad_routes_attr_received_
     249             : //     This is a map of all type 4 leaf ad routes originated (in response to
     250             : //     received/imported type-3 spmsi routes. For each route, associated path
     251             : //     attributes of the best path are stored as value inside the map. Whenever
     252             : //     this map changes or when a new type-5 source active route is received,
     253             : //     the correspnding sender agent is notified with the olist that contains
     254             : //     the PMSI attributes as received in leafad routes path attributes.
     255             : //
     256             : // states_
     257             : //     This is the parent map that holds 'this' MvpnState pointer as the value
     258             : //     for the associated SG key. When the refcount reaches zero, it indicates
     259             : //     that there is no reference to this state from of the DB States associated
     260             : //     with any Mvpn route. Hence at that time, this state is removed this map
     261             : //     states_ and destroyed. This map actually sits inside the associated
     262             : //     MvpnProjectManagerParitition object.
     263             : class MvpnState {
     264             : public:
     265             :     typedef std::set<MvpnRoute *> RoutesSet;
     266             :     typedef std::map<MvpnRoute *, BgpAttrPtr> RoutesMap;
     267             : 
     268             :     // Simple structure to hold <S,G>. Source as "0.0.0.0" can be used to encode
     269             :     // <*,G> as well.
     270             :     struct SG {
     271             :         SG(const Ip4Address &source, const Ip4Address &group);
     272             :         SG(const IpAddress &source, const IpAddress &group);
     273             :         explicit SG(const ErmVpnRoute *route);
     274             :         explicit SG(const MvpnRoute *route);
     275             :         bool operator<(const SG &other) const;
     276             : 
     277             :         IpAddress source;
     278             :         IpAddress group;
     279             :     };
     280             : 
     281             :     typedef std::map<SG, MvpnState *> StatesMap;
     282             :     MvpnState(const SG &sg, StatesMap *states, MvpnProjectManager *pm);
     283             : 
     284             :     virtual ~MvpnState();
     285             :     const SG &sg() const;
     286             :     ErmVpnRoute *global_ermvpn_tree_rt();
     287             :     const ErmVpnRoute *global_ermvpn_tree_rt() const;
     288             :     MvpnRoute *spmsi_rt();
     289             :     const MvpnRoute *spmsi_rt() const;
     290             :     void set_global_ermvpn_tree_rt(ErmVpnRoute *global_ermvpn_tree_rt);
     291             :     void set_spmsi_rt(MvpnRoute *spmsi_rt);
     292             :     RoutesSet &spmsi_routes_received();
     293             :     RoutesMap &leafad_routes_attr_received();
     294             :     const RoutesSet &spmsi_routes_received() const;
     295             :     const RoutesMap &leafad_routes_attr_received() const;
     296           1 :     const StatesMap *states() const { return states_; }
     297       32264 :     StatesMap *states() { return states_; }
     298             :     MvpnRoute *source_active_rt();
     299             :     const MvpnRoute *source_active_rt() const;
     300             :     void set_source_active_rt(MvpnRoute *source_active_rt);
     301       12476 :     MvpnProjectManager *project_manager() { return project_manager_; }
     302           1 :     const MvpnProjectManager *project_manager() const {
     303           1 :         return project_manager_;
     304             :     }
     305           1 :     int refcount() const { return refcount_; }
     306             : 
     307             : private:
     308             :     friend class MvpnDBState;
     309             :     friend class MvpnManagerPartition;
     310             :     friend class MvpnProjectManagerPartition;
     311             :     friend void intrusive_ptr_add_ref(MvpnState *mvpn_state);
     312             :     friend void intrusive_ptr_release(MvpnState *mvpn_state);
     313             : 
     314             :     const ErmVpnTable *table() const;
     315             : 
     316             :     SG sg_;
     317             :     ErmVpnRoute *global_ermvpn_tree_rt_;
     318             :     MvpnRoute *spmsi_rt_;
     319             :     MvpnRoute *source_active_rt_;
     320             :     RoutesSet spmsi_routes_received_;
     321             :     RoutesMap leafad_routes_attr_received_;
     322             :     StatesMap *states_;
     323             :     MvpnProjectManager *project_manager_;
     324             :     std::atomic<int> refcount_;
     325             : 
     326             :     DISALLOW_COPY_AND_ASSIGN(MvpnState);
     327             : };
     328             : 
     329             : // This class holds a reference to MvpnState along with associated route
     330             : // pointer. This is stored as DBState inside the table along with the
     331             : // associated route.
     332             : //
     333             : // Note: Routes are never deleted until the DB state is deleted. MvpnState which
     334             : // is refcounted is also deleted only when there is no MvpnDBState that refers
     335             : // to it.
     336             : struct MvpnDBState : public DBState {
     337             :     explicit MvpnDBState(MvpnStatePtr state);
     338             :     ~MvpnDBState();
     339             :     MvpnStatePtr state();
     340             :     MvpnRoute *route();
     341             :     void set_state(MvpnStatePtr state);
     342             :     void set_route(MvpnRoute *route);
     343             : 
     344             : private:
     345             :     MvpnStatePtr state_;
     346             :     MvpnRoute *route_;
     347             : 
     348             :     DISALLOW_COPY_AND_ASSIGN(MvpnDBState);
     349             : };
     350             : 
     351             : // This class glues mvpn and ermvpn modules, inside a particular DB partition.
     352             : //
     353             : // Each MVPN is associated with a parent MvpnProjectManager virtual-network via
     354             : // configuration. This parent MvpnProjectManager's ermvpn tree is the one used
     355             : // for all multicast packets replication in the data plane for the given MVPN.
     356             : //
     357             : // Inside each RoutingInstance object, name of this parent manager virtual
     358             : // network is stored in mvpn_project_manager_network_ string. When ever this
     359             : // information is set/modified/cleared in the routing instance, all associated
     360             : // Type3 S-PMSI MPVN received routes should be notified for re-evaluation.
     361             : //
     362             : // MvpnState::StatesMap states_
     363             : //     A Map of <<S,G>, MvpnState> is maintained to hold MvpnState for all
     364             : //     <S,G>s that fall into a specific DB partition.
     365             : //
     366             : // This provides APIs to create/update/delete MvpnState as required. MvpnState
     367             : // is refcounted. When the refcount reaches 1, it is deleted from the StatesMap
     368             : // and destroyed.
     369             : class MvpnProjectManagerPartition {
     370             : public:
     371             :     typedef MvpnState::SG SG;
     372             : 
     373             :     MvpnProjectManagerPartition(MvpnProjectManager*manager, int part_id);
     374             :     virtual ~MvpnProjectManagerPartition();
     375             :     MvpnStatePtr GetState(const SG &sg);
     376             :     MvpnStatePtr GetState(const SG &sg) const;
     377             :     MvpnStatePtr LocateState(const SG &sg);
     378             :     MvpnStatePtr CreateState(const SG &sg);
     379       27936 :     const MvpnState::StatesMap &states() const { return states_; }
     380         191 :     MvpnState::StatesMap &states() { return states_; }
     381             : 
     382             : private:
     383             :     friend class MvpnProjectManager;
     384             :     friend class MvpnManagerPartition;
     385             : 
     386             :     ErmVpnRoute *GetGlobalTreeRootRoute(ErmVpnRoute *rt) const;
     387             :     ErmVpnTable *table();
     388             :     const ErmVpnTable *table() const;
     389             :     void RouteListener(DBEntryBase *db_entry);
     390             :     int listener_id() const;
     391             :     void NotifyForestNode(const Ip4Address &source, const Ip4Address &group);
     392             :     bool GetForestNodePMSI(ErmVpnRoute *rt, uint32_t *label,
     393             :             Ip4Address *address, std::vector<std::string> *encap) const;
     394             :     bool IsUsableGlobalTreeRootRoute(ErmVpnRoute *ermvpn_route) const;
     395             : 
     396             :     // Back pointer to the parent MvpnProjectManager
     397             :     MvpnProjectManager *manager_;
     398             : 
     399             :     // Partition id of the manged DB partition.
     400             :     int part_id_;
     401             :     MvpnState::StatesMap states_;;
     402             : 
     403             :     DISALLOW_COPY_AND_ASSIGN(MvpnProjectManagerPartition);
     404             : };
     405             : 
     406             : // This class glues mvpn and ermvpn modules
     407             : //
     408             : // It maintains a list of MvpnProjectManagerPartition objects, one for each DB
     409             : // partition.
     410             : //
     411             : // It listens to changes to ErmVpn table and for any applicable change to
     412             : // GlobalErmVpnRoute, it notifies all applicable received SPMSI routes so that
     413             : // those routes can be replicated/deleted based on the current state of the
     414             : // GlobalErmVpnRoute associated with a given <S,G>.
     415             : //
     416             : // This class also provides DeleteActor and maintains a LifetimeRef to parent
     417             : // MvpnTable object in order to ensure orderly cleanup during table deletion.
     418             : class MvpnProjectManager {
     419             : public:
     420             :     class DeleteActor;
     421             :     typedef std::vector<MvpnProjectManagerPartition *> PartitionList;
     422             :     typedef PartitionList::const_iterator const_iterator;
     423             : 
     424             :     explicit MvpnProjectManager(ErmVpnTable *table);
     425             :     virtual ~MvpnProjectManager();
     426             :     MvpnProjectManagerPartition *GetPartition(int part_id);
     427             :     const MvpnProjectManagerPartition *GetPartition(int part_id) const;
     428             :     void ManagedDelete();
     429             :     virtual void Terminate();
     430             :     ErmVpnTable *table();
     431             :     const ErmVpnTable *table() const;
     432             :     int listener_id() const;
     433             :     const LifetimeActor *deleter() const;
     434             :     LifetimeActor *deleter();
     435             :     bool deleted() const;
     436             :     virtual void Initialize();
     437             :     MvpnStatePtr GetState(MvpnRoute *route) const;
     438             :     MvpnStatePtr GetState(MvpnRoute *route);
     439             :     MvpnStatePtr GetState(ErmVpnRoute *route) const;
     440             :     UpdateInfo *GetUpdateInfo(MvpnRoute *route);
     441         190 :     const PartitionList &partitions() const { return partitions_; }
     442             :     bool MayDelete() const;
     443             :     void GetMvpnSourceAddress(ErmVpnRoute *ermvpn_route,
     444             :                               Ip4Address *address) const;
     445             : 
     446             : private:
     447             :     void AllocPartitions();
     448             :     void FreePartitions();
     449             :     void RouteListener(DBTablePartBase *tpart, DBEntryBase *db_entry);
     450             :     UpdateInfo *GetType7UpdateInfo(MvpnRoute *route);
     451             : 
     452             :     // Parent ErmVpn table.
     453             :     ErmVpnTable *table_;
     454             :     int listener_id_;
     455             :     PartitionList partitions_;
     456             : 
     457             :     boost::scoped_ptr<DeleteActor> deleter_;
     458             :     LifetimeRef<MvpnProjectManager> table_delete_ref_;
     459             : 
     460             :     DISALLOW_COPY_AND_ASSIGN(MvpnProjectManager);
     461             : };
     462             : 
     463             : // Increment refcont atomically.
     464       95995 : inline void intrusive_ptr_add_ref(MvpnState *mvpn_state) {
     465       95995 :     mvpn_state->refcount_.fetch_add(1);
     466       95995 : }
     467             : 
     468             : // Decrement refcount of an mvpn_state. If the refcount falls to 1, it implies
     469             : // that there is no more reference to this particular state from any other data
     470             : // structure. Hence, it can be deleted from the container map and destroyed as
     471             : // well.
     472       95995 : inline void intrusive_ptr_release(MvpnState *mvpn_state) {
     473       95995 :     int prev = mvpn_state->refcount_.fetch_sub(1);
     474       95995 :     if (prev > 1)
     475       87929 :         return;
     476        8066 :     if (mvpn_state->states()) {
     477             :         MvpnState::StatesMap::iterator iter =
     478        8066 :             mvpn_state->states()->find(mvpn_state->sg());
     479        8066 :         if (iter != mvpn_state->states()->end()) {
     480        8066 :             assert(iter->second == mvpn_state);
     481        8066 :             mvpn_state->states()->erase(iter);
     482             : 
     483             :             // Attempt project manager deletion as it could be held up due to
     484             :             // this map being non-empty so far..
     485        8066 :             if (mvpn_state->project_manager()->deleter()->IsDeleted())
     486        4410 :                 mvpn_state->project_manager()->deleter()->RetryDelete();
     487             :         }
     488             :     }
     489        8066 :     delete mvpn_state;
     490             : }
     491             : 
     492             : #define MVPN_RT_LOG(rt, ...) \
     493             :     RTINSTANCE_LOG(MvpnRoute, this->table()->routing_instance(), \
     494             :                    SandeshLevel::UT_DEBUG, \
     495             :                    RTINSTANCE_LOG_FLAG_ALL, \
     496             :                    (rt)->GetPrefix().source().to_string(), \
     497             :                    (rt)->GetPrefix().group().to_string(), \
     498             :                    (rt)->GetType(), (rt)->ToString(), ##__VA_ARGS__)
     499             : 
     500             : #define MVPN_ERMVPN_RT_LOG(rt, ...) \
     501             :     RTINSTANCE_LOG(MvpnErmVpnRoute, this->table()->routing_instance(), \
     502             :                    SandeshLevel::UT_DEBUG, \
     503             :                    RTINSTANCE_LOG_FLAG_ALL, \
     504             :                    (rt)->GetPrefix().source().to_string(), \
     505             :                    (rt)->GetPrefix().group().to_string(), \
     506             :                    (rt)->GetType(), (rt)->ToString(), ##__VA_ARGS__)
     507             : 
     508             : #define MVPN_LOG(type, ...) \
     509             :     RTINSTANCE_LOG(type, this->table()->routing_instance(), \
     510             :         SandeshLevel::SYS_DEBUG, RTINSTANCE_LOG_FLAG_ALL, ##__VA_ARGS__)
     511             : 
     512             : #define MVPN_TRACE(type, ...) \
     513             :     RTINSTANCE_LOG(type, this->table()->routing_instance(), \
     514             :         SandeshLevel::UT_DEBUG, RTINSTANCE_LOG_FLAG_ALL, ##__VA_ARGS__)
     515             : 
     516             : #endif  // SRC_BGP_BGP_MVPN_H_

Generated by: LCOV version 1.14