OpenSDN source code
rtarget_group_mgr.h
Go to the documentation of this file.
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"
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 //
41 public:
44 
45  void ManagedDelete();
46 
48  return id_;
49  }
50 
51 private:
54 
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  const RTargetList *GetList() const { return &list_; }
79 
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  const RtGroup::InterestedPeerList *GetList() const { return &list_; }
101 
103 };
104 
106  enum RequestType {
110  };
111 
113  const std::string &param = std::string())
114  : type_(type), snh_resp_(resp), param_(param) {
115  }
116 
119  std::string param_;
120 
121 private:
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 //
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  bool empty() const { return rtgroup_map_.empty(); }
214  const_iterator begin() const { return rtgroup_map_.begin(); }
215  const_iterator end() const { return rtgroup_map_.end(); }
217  return rtgroup_map_.lower_bound(rt);
218  }
219 
220  // RtGroup
221  RtGroup *GetRtGroup(const RouteTarget &rt);
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();
235  return rtarget_route_list_.empty();
236  }
237 
238 private:
239  friend class BgpXmppRTargetTest;
240  friend class ReplicationTest;
241 
242  typedef std::map<BgpTable *,
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,
250  const VpnRouteState::RTargetList *future);
251  void RTargetPeerSync(BgpTable *table, RTargetRoute *rt,
253  const RtGroup::InterestedPeerList *future);
256  BgpServer *server() { return server_; }
257 
261  bool IsRTargetRouteOnList(RTargetRoute *rt) const;
262 
263  bool ProcessRouteTargetList(int part_id);
264  void AddRouteTargetToLists(const RouteTarget &rtarget);
267  bool IsRouteTargetOnList(const RouteTarget &rtarget) const;
268 
269  bool ProcessRtGroupList();
272  bool IsRtGroupOnList(RtGroup *rtgroup) const;
273 
275  void UnregisterTables();
276  bool VpnRouteNotify(DBTablePartBase *root, DBEntryBase *entry);
277  bool RTargetRouteNotify(DBTablePartBase *root, DBEntryBase *entry);
279 
281  std::mutex mutex_;
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_;
288  std::vector<RouteTargetTriggerList> rtarget_trigger_lists_;
291 
293 };
294 
295 #endif // SRC_BGP_ROUTING_INSTANCE_RTARGET_GROUP_MGR_H_
int ListenerId
Definition: db_table.h:62
boost::array< uint8_t, 8 > ExtCommunityValue
Definition: community.h:154
friend class BgpXmppRTargetTest
bool IsRTargetRouteOnList(RTargetRoute *rt) const
bool IsRTargetRoutesProcessed() const
void EnableRTargetRouteProcessing()
bool IsRtGroupOnList(RtGroup *rtgroup) const
const_iterator end() const
void RemoveRtGroup(const RouteTarget &rt)
bool IsRouteTargetOnList(const RouteTarget &rtarget) const
virtual ~RTargetGroupMgr()
std::set< RTargetRoute * > RTargetRouteTriggerList
friend class ReplicationTest
void Enqueue(RtGroupMgrReq *req)
void AddRouteTargetToLists(const RouteTarget &rtarget)
boost::scoped_ptr< TaskTrigger > rtarget_route_trigger_
RtGroupMap rtgroup_map_
std::set< RouteTarget > RouteTargetTriggerList
std::vector< boost::shared_ptr< TaskTrigger > > rtarget_dep_triggers_
RTargetGroupMgr(BgpServer *server)
bool empty() const
virtual void GetRibOutInterestedPeers(RibOut *ribout, const ExtCommunity *ext_community, const RibPeerSet &peerset, RibPeerSet *new_peerset)
RtGroup * LocateRtGroup(const RouteTarget &rt)
DBTableBase::ListenerId GetListenerId(BgpTable *table)
void RTargetDepSync(DBTablePartBase *root, BgpRoute *rt, DBTableBase::ListenerId id, VpnRouteState *dbstate, const VpnRouteState::RTargetList *future)
std::set< RtGroup * > RtGroupRemoveList
bool ProcessRouteTargetList(int part_id)
void DisableRouteTargetProcessing()
void DisableRTargetRouteProcessing()
bool RTargetRouteNotify(DBTablePartBase *root, DBEntryBase *entry)
std::map< BgpTable *, RtGroupMgrTableState * > RtGroupMgrTableStateList
RtGroupMgrTableStateList table_state_
void NotifyRtGroup(const RouteTarget &rt)
RtGroupMap::const_iterator const_iterator
void NotifyRtGroupUnlocked(const RouteTarget &rt)
void BuildRTargetDistributionGraph(BgpTable *table, RTargetRoute *rt, DBTableBase::ListenerId id)
boost::scoped_ptr< TaskTrigger > remove_rtgroup_trigger_
RtGroupRemoveList rtgroup_remove_list_
BgpServer * server()
bool VpnRouteNotify(DBTablePartBase *root, DBEntryBase *entry)
std::vector< RouteTargetTriggerList > rtarget_trigger_lists_
bool RequestHandler(RtGroupMgrReq *req)
RTargetRouteTriggerList rtarget_route_list_
LifetimeRef< RTargetGroupMgr > master_instance_delete_ref_
const_iterator begin() const
void EnableRouteTargetProcessing()
void RTargetPeerSync(BgpTable *table, RTargetRoute *rt, DBTableBase::ListenerId id, RTargetState *dbstate, const RtGroup::InterestedPeerList *future)
RtGroup * GetRtGroup(const RouteTarget &rt)
boost::ptr_map< const RouteTarget, RtGroup > RtGroupMap
const_iterator lower_bound(const RouteTarget &rt) const
DISALLOW_COPY_AND_ASSIGN(RTargetGroupMgr)
RtGroup::InterestedPeerList list_
void AddInterestedPeer(RTargetGroupMgr *mgr, RtGroup *rtgroup, RTargetRoute *rt, RtGroup::InterestedPeerList::const_iterator it)
const RtGroup::InterestedPeerList * GetList() const
void DeleteInterestedPeer(RTargetGroupMgr *mgr, RtGroup *rtgroup, RTargetRoute *rt, RtGroup::InterestedPeerList::iterator it)
RtGroup::InterestedPeerList * GetMutableList()
RtGroupMgrTableState(BgpTable *table, DBTableBase::ListenerId id)
LifetimeRef< RtGroupMgrTableState > table_delete_ref_
DBTableBase::ListenerId GetListenerId() const
DISALLOW_COPY_AND_ASSIGN(RtGroupMgrTableState)
DBTableBase::ListenerId id_
std::map< const BgpPeer *, RTargetRouteList > InterestedPeerList
Definition: rtarget_group.h:68
std::set< RouteTarget > RTargetList
RTargetList * GetMutableList()
void DeleteRouteTarget(RTargetGroupMgr *mgr, int part_id, BgpRoute *rt, RTargetList::const_iterator it)
RTargetList list_
void AddRouteTarget(RTargetGroupMgr *mgr, int part_id, BgpRoute *rt, RTargetList::const_iterator it)
const RTargetList * GetList() const
uint8_t type
Definition: load_balance.h:2
std::string param_
DISALLOW_COPY_AND_ASSIGN(RtGroupMgrReq)
SandeshResponse * snh_resp_
RtGroupMgrReq(RequestType type, SandeshResponse *resp, const std::string &param=std::string())
RequestType type_