OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 #include <tbb/atomic.h>
14 #include <tbb/mutex.h>
15 
16 #include <map>
17 #include <set>
18 #include <string>
19 #include <vector>
20 
21 #include "base/queue_task.h"
22 #include "base/lifetime.h"
23 #include "bgp/community.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 //
42 public:
45 
46  void ManagedDelete();
47 
49  return id_;
50  }
51 
52 private:
55 
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  const RTargetList *GetList() const { return &list_; }
80 
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  const RtGroup::InterestedPeerList *GetList() const { return &list_; }
102 
104 };
105 
107  enum RequestType {
111  };
112 
114  const std::string &param = std::string())
115  : type_(type), snh_resp_(resp), param_(param) {
116  }
117 
120  std::string param_;
121 
122 private:
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 //
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  bool empty() const { return rtgroup_map_.empty(); }
215  const_iterator begin() const { return rtgroup_map_.begin(); }
216  const_iterator end() const { return rtgroup_map_.end(); }
218  return rtgroup_map_.lower_bound(rt);
219  }
220 
221  // RtGroup
222  RtGroup *GetRtGroup(const RouteTarget &rt);
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();
236  return rtarget_route_list_.empty();
237  }
238 
239 private:
240  friend class BgpXmppRTargetTest;
241  friend class ReplicationTest;
242 
243  typedef std::map<BgpTable *,
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,
251  const VpnRouteState::RTargetList *future);
252  void RTargetPeerSync(BgpTable *table, RTargetRoute *rt,
254  const RtGroup::InterestedPeerList *future);
257  BgpServer *server() { return server_; }
258 
262  bool IsRTargetRouteOnList(RTargetRoute *rt) const;
263 
264  bool ProcessRouteTargetList(int part_id);
265  void AddRouteTargetToLists(const RouteTarget &rtarget);
268  bool IsRouteTargetOnList(const RouteTarget &rtarget) const;
269 
270  bool ProcessRtGroupList();
273  bool IsRtGroupOnList(RtGroup *rtgroup) const;
274 
276  void UnregisterTables();
277  bool VpnRouteNotify(DBTablePartBase *root, DBEntryBase *entry);
278  bool RTargetRouteNotify(DBTablePartBase *root, DBEntryBase *entry);
279  bool RequestHandler(RtGroupMgrReq *req);
280 
282  tbb::mutex mutex_;
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_;
289  std::vector<RouteTargetTriggerList> rtarget_trigger_lists_;
292 
294 };
295 
296 #endif // SRC_BGP_ROUTING_INSTANCE_RTARGET_GROUP_MGR_H_
RtGroupMgrTableStateList table_state_
std::map< const BgpPeer *, RTargetRouteList > InterestedPeerList
Definition: rtarget_group.h:68
bool IsRouteTargetOnList(const RouteTarget &rtarget) const
boost::array< uint8_t, 8 > ExtCommunityValue
Definition: community.h:152
void DisableRTargetRouteProcessing()
RtGroupMgrReq(RequestType type, SandeshResponse *resp, const std::string &param=std::string())
RTargetList list_
const RtGroup::InterestedPeerList * GetList() const
DBTableBase::ListenerId id_
void NotifyRtGroup(const RouteTarget &rt)
void AddInterestedPeer(RTargetGroupMgr *mgr, RtGroup *rtgroup, RTargetRoute *rt, RtGroup::InterestedPeerList::const_iterator it)
RtGroupMap::const_iterator const_iterator
LifetimeRef< RtGroupMgrTableState > table_delete_ref_
virtual ~RTargetGroupMgr()
void RTargetPeerSync(BgpTable *table, RTargetRoute *rt, DBTableBase::ListenerId id, RTargetState *dbstate, const RtGroup::InterestedPeerList *future)
BgpServer * server()
std::set< RtGroup * > RtGroupRemoveList
void Enqueue(RtGroupMgrReq *req)
bool ProcessRouteTargetList(int part_id)
const_iterator begin() const
std::map< BgpTable *, RtGroupMgrTableState * > RtGroupMgrTableStateList
int ListenerId
Definition: db_table.h:62
std::vector< RouteTargetTriggerList > rtarget_trigger_lists_
RTargetRouteTriggerList rtarget_route_list_
void AddRouteTargetToLists(const RouteTarget &rtarget)
RtGroupRemoveList rtgroup_remove_list_
const RTargetList * GetList() const
void DisableRouteTargetProcessing()
SandeshResponse * snh_resp_
LifetimeRef< RTargetGroupMgr > master_instance_delete_ref_
DBTableBase::ListenerId GetListenerId() const
uint8_t type
Definition: load_balance.h:109
RtGroup * LocateRtGroup(const RouteTarget &rt)
void RemoveRtGroup(const RouteTarget &rt)
void EnableRouteTargetProcessing()
void NotifyRtGroupUnlocked(const RouteTarget &rt)
RtGroupMgrTableState(BgpTable *table, DBTableBase::ListenerId id)
boost::scoped_ptr< TaskTrigger > remove_rtgroup_trigger_
const_iterator lower_bound(const RouteTarget &rt) const
boost::scoped_ptr< TaskTrigger > rtarget_route_trigger_
bool IsRTargetRouteOnList(RTargetRoute *rt) const
RTargetGroupMgr(BgpServer *server)
RequestType type_
bool RequestHandler(RtGroupMgrReq *req)
friend class ReplicationTest
void DeleteRouteTarget(RTargetGroupMgr *mgr, int part_id, BgpRoute *rt, RTargetList::const_iterator it)
RTargetList * GetMutableList()
bool IsRTargetRoutesProcessed() const
bool RTargetRouteNotify(DBTablePartBase *root, DBEntryBase *entry)
RtGroup * GetRtGroup(const RouteTarget &rt)
RtGroupMap rtgroup_map_
std::set< RTargetRoute * > RTargetRouteTriggerList
void BuildRTargetDistributionGraph(BgpTable *table, RTargetRoute *rt, DBTableBase::ListenerId id)
DISALLOW_COPY_AND_ASSIGN(RtGroupMgrTableState)
RtGroup::InterestedPeerList list_
boost::ptr_map< const RouteTarget, RtGroup > RtGroupMap
void DeleteInterestedPeer(RTargetGroupMgr *mgr, RtGroup *rtgroup, RTargetRoute *rt, RtGroup::InterestedPeerList::iterator it)
bool empty() const
RtGroup::InterestedPeerList * GetMutableList()
DBTableBase::ListenerId GetListenerId(BgpTable *table)
void EnableRTargetRouteProcessing()
std::vector< boost::shared_ptr< TaskTrigger > > rtarget_dep_triggers_
DISALLOW_COPY_AND_ASSIGN(RtGroupMgrReq)
void AddRouteTarget(RTargetGroupMgr *mgr, int part_id, BgpRoute *rt, RTargetList::const_iterator it)
const_iterator end() const
DISALLOW_COPY_AND_ASSIGN(RTargetGroupMgr)
bool IsRtGroupOnList(RtGroup *rtgroup) const
void RTargetDepSync(DBTablePartBase *root, BgpRoute *rt, DBTableBase::ListenerId id, VpnRouteState *dbstate, const VpnRouteState::RTargetList *future)
bool VpnRouteNotify(DBTablePartBase *root, DBEntryBase *entry)
std::set< RouteTarget > RouteTargetTriggerList
virtual void GetRibOutInterestedPeers(RibOut *ribout, const ExtCommunity *ext_community, const RibPeerSet &peerset, RibPeerSet *new_peerset)
std::set< RouteTarget > RTargetList
std::string param_
friend class BgpXmppRTargetTest