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

Generated by: LCOV version 1.14