Line data Source code
1 : /*
2 : * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #ifndef __AGENT_PKT_FLOW_MGMT_TREE_H__
7 : #define __AGENT_PKT_FLOW_MGMT_TREE_H__
8 :
9 : #include <cstdlib>
10 : #include <map>
11 : #include <mutex>
12 : #include <pkt/flow_mgmt/flow_mgmt_key.h>
13 :
14 : class FlowMgmtKeyNode;
15 : class FlowMgmtEntry;
16 :
17 : class BgpAsAServiceFlowMgmtRequest;
18 :
19 : typedef std::map<FlowMgmtKey *, FlowMgmtKeyNode *, FlowMgmtKeyCmp> FlowMgmtKeyTree;
20 :
21 : class FlowMgmtTree {
22 : public:
23 : typedef std::map<FlowMgmtKey *, FlowMgmtEntry *, FlowMgmtKeyCmp> Tree;
24 20 : FlowMgmtTree(FlowMgmtManager *mgr) : mgr_(mgr) { }
25 20 : virtual ~FlowMgmtTree() {
26 20 : assert(tree_.size() == 0);
27 20 : }
28 :
29 : // Add a flow into dependency tree for an object
30 : // Creates an entry if not already present in the tree
31 : virtual bool Add(FlowMgmtKey *key, FlowEntry *flow,
32 : FlowMgmtKeyNode *node);
33 : // Delete a flow from dependency tree for an object
34 : // Entry is deleted after all flows dependent on the entry are deleted
35 : // and DBEntry delete message is got from FlowTable
36 : virtual bool Delete(FlowMgmtKey *key, FlowEntry *flow,
37 : FlowMgmtKeyNode *node);
38 : virtual void InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry);
39 : virtual void RemoveEntry(Tree::iterator it);
40 :
41 : // Handle DBEntry add
42 : virtual bool OperEntryAdd(const FlowMgmtRequest *req, FlowMgmtKey *key);
43 : // Handle DBEntry change
44 : virtual bool OperEntryChange(const FlowMgmtRequest *req, FlowMgmtKey *key);
45 : // Handle DBEntry delete
46 : virtual bool OperEntryDelete(const FlowMgmtRequest *req, FlowMgmtKey *key);
47 :
48 : // Try delete a DBEntry
49 : virtual bool RetryDelete(FlowMgmtKey *key);
50 :
51 : // Get all Keys relavent for the tree and store them into FlowMgmtKeyTree
52 : virtual void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) = 0;
53 : // Allocate a FlowMgmtEntry for the tree
54 : virtual FlowMgmtEntry *Allocate(const FlowMgmtKey *key) = 0;
55 :
56 : // Called just before entry is deleted. Used to implement cleanup operations
57 : virtual void FreeNotify(FlowMgmtKey *key, uint32_t gen_id);
58 :
59 : FlowMgmtEntry *Locate(FlowMgmtKey *key);
60 : FlowMgmtEntry *Find(FlowMgmtKey *key);
61 : FlowMgmtKey *LowerBound(FlowMgmtKey *key);
62 0 : Tree &tree() { return tree_; }
63 296 : FlowMgmtManager *mgr() const { return mgr_; }
64 : static bool AddFlowMgmtKey(FlowMgmtKeyTree *tree, FlowMgmtKey *key);
65 :
66 : protected:
67 : bool TryDelete(FlowMgmtKey *key, FlowMgmtEntry *entry);
68 : Tree tree_;
69 : FlowMgmtManager *mgr_;
70 :
71 : private:
72 : DISALLOW_COPY_AND_ASSIGN(FlowMgmtTree);
73 : };
74 :
75 : ////////////////////////////////////////////////////////////////////////////
76 : // Object specific information below
77 : ////////////////////////////////////////////////////////////////////////////
78 : class AclFlowMgmtTree : public FlowMgmtTree {
79 : public:
80 2 : AclFlowMgmtTree(FlowMgmtManager *mgr) : FlowMgmtTree(mgr) { }
81 2 : virtual ~AclFlowMgmtTree() { }
82 :
83 : bool Add(FlowMgmtKey *key, FlowEntry *flow, FlowMgmtKey *old_key,
84 : FlowMgmtKeyNode *node);
85 : bool Delete(FlowMgmtKey *key, FlowEntry *flow,
86 : FlowMgmtKeyNode *node);
87 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree,
88 : const MatchAclParamsList *acl_list);
89 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree);
90 : FlowMgmtEntry *Allocate(const FlowMgmtKey *key);
91 :
92 : private:
93 : DISALLOW_COPY_AND_ASSIGN(AclFlowMgmtTree);
94 : };
95 :
96 : class VnFlowMgmtTree : public FlowMgmtTree {
97 : public:
98 2 : VnFlowMgmtTree(FlowMgmtManager *mgr) : FlowMgmtTree(mgr) {}
99 2 : virtual ~VnFlowMgmtTree() {}
100 :
101 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree);
102 : FlowMgmtEntry *Allocate(const FlowMgmtKey *key);
103 :
104 : void VnFlowCounters(const VnEntry *vn,
105 : uint32_t *ingress_flow_count,
106 : uint32_t *egress_flow_count);
107 : void RemoveEntry(Tree::iterator it);
108 : void InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry);
109 :
110 : private:
111 : // We need to support query of counters in VN from other threads.
112 : // So, implement synchronization on access to VN Flow Tree
113 : std::mutex mutex_;
114 : DISALLOW_COPY_AND_ASSIGN(VnFlowMgmtTree);
115 : };
116 :
117 : class InterfaceFlowMgmtTree : public FlowMgmtTree {
118 : public:
119 2 : InterfaceFlowMgmtTree(FlowMgmtManager *mgr) : FlowMgmtTree(mgr) {}
120 2 : virtual ~InterfaceFlowMgmtTree() {}
121 :
122 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree);
123 : FlowMgmtEntry *Allocate(const FlowMgmtKey *key);
124 : void InterfaceFlowCount(const Interface *itf, uint64_t *created,
125 : uint64_t *aged, uint32_t *active_flows);
126 : void InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry);
127 : void RemoveEntry(Tree::iterator it);
128 :
129 : private:
130 : // We need to support query of counters in Interface from other threads.
131 : // So, implement synchronization on access to Interface Flow Tree
132 : std::mutex mutex_;
133 : DISALLOW_COPY_AND_ASSIGN(InterfaceFlowMgmtTree);
134 : };
135 :
136 : class NhFlowMgmtTree : public FlowMgmtTree {
137 : public:
138 2 : NhFlowMgmtTree(FlowMgmtManager *mgr) : FlowMgmtTree(mgr) {}
139 2 : virtual ~NhFlowMgmtTree() {}
140 :
141 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree);
142 : FlowMgmtEntry *Allocate(const FlowMgmtKey *key);
143 :
144 : private:
145 : DISALLOW_COPY_AND_ASSIGN(NhFlowMgmtTree);
146 : };
147 :
148 : class RouteFlowMgmtTree : public FlowMgmtTree {
149 : public:
150 6 : RouteFlowMgmtTree(FlowMgmtManager *mgr) : FlowMgmtTree(mgr) { }
151 6 : virtual ~RouteFlowMgmtTree() { }
152 : virtual bool HasVrfFlows(uint32_t vrf_id, Agent::RouteTableType type) = 0;
153 :
154 : virtual bool Delete(FlowMgmtKey *key, FlowEntry *flow, FlowMgmtKeyNode *node);
155 : virtual bool OperEntryDelete(const FlowMgmtRequest *req, FlowMgmtKey *key);
156 : virtual bool OperEntryAdd(const FlowMgmtRequest *req, FlowMgmtKey *key);
157 :
158 : private:
159 : void SetDBEntry(const FlowMgmtRequest *req, FlowMgmtKey *key);
160 : DISALLOW_COPY_AND_ASSIGN(RouteFlowMgmtTree);
161 : };
162 :
163 : class InetRouteFlowMgmtTree : public RouteFlowMgmtTree {
164 : public:
165 : typedef Patricia::Tree<InetRouteFlowMgmtKey, &InetRouteFlowMgmtKey::node_,
166 : InetRouteFlowMgmtKey::KeyCmp> LpmTree;
167 :
168 4 : InetRouteFlowMgmtTree(FlowMgmtManager *mgr) : RouteFlowMgmtTree(mgr) { }
169 4 : virtual ~InetRouteFlowMgmtTree() { }
170 :
171 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree, uint32_t vrf,
172 : const IpAddress &ip, uint8_t plen);
173 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree,
174 : const IpAddress &ip, const FlowRouteRefMap *rt_list);
175 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree);
176 :
177 : virtual bool OperEntryAdd(const FlowMgmtRequest *req, FlowMgmtKey *key);
178 : virtual bool OperEntryDelete(const FlowMgmtRequest *req, FlowMgmtKey *key);
179 : FlowMgmtEntry *Allocate(const FlowMgmtKey *key);
180 : bool HasVrfFlows(uint32_t vrf_id, Agent::RouteTableType type);
181 :
182 1887 : InetRouteFlowMgmtKey *LPM(const InetRouteFlowMgmtKey *key) {
183 1887 : if (key->plen_ == 0)
184 0 : return NULL;
185 1887 : return lpm_tree_.LPMFind(key);
186 : }
187 :
188 1911 : void AddToLPMTree(InetRouteFlowMgmtKey *key) {
189 : InetRouteFlowMgmtKey *rt_key =
190 1911 : static_cast<InetRouteFlowMgmtKey *>(key->Clone());
191 1911 : if (lpm_tree_.Insert(rt_key) == false)
192 975 : delete rt_key;
193 1911 : }
194 :
195 936 : void DelFromLPMTree(InetRouteFlowMgmtKey *key) {
196 936 : InetRouteFlowMgmtKey *rt_key = lpm_tree_.Find(key);
197 936 : if (rt_key != NULL) {
198 936 : lpm_tree_.Remove(rt_key);
199 936 : delete rt_key;
200 : }
201 936 : }
202 : bool RecomputeCoveringRoute(InetRouteFlowMgmtKey *covering_route,
203 : InetRouteFlowMgmtKey *key);
204 : bool RouteNHChangeEvent(const FlowMgmtRequest *req, FlowMgmtKey *key);
205 :
206 : private:
207 : LpmTree lpm_tree_;
208 : DISALLOW_COPY_AND_ASSIGN(InetRouteFlowMgmtTree);
209 : };
210 :
211 : class BridgeRouteFlowMgmtTree : public RouteFlowMgmtTree {
212 : public:
213 2 : BridgeRouteFlowMgmtTree(FlowMgmtManager *mgr) : RouteFlowMgmtTree(mgr) { }
214 2 : virtual ~BridgeRouteFlowMgmtTree() { }
215 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree);
216 : FlowMgmtEntry *Allocate(const FlowMgmtKey *key);
217 : bool HasVrfFlows(uint32_t vrf_id, Agent::RouteTableType type);
218 :
219 : private:
220 : DISALLOW_COPY_AND_ASSIGN(BridgeRouteFlowMgmtTree);
221 : };
222 :
223 : ////////////////////////////////////////////////////////////////////////////
224 : // Flow Management tree for VRF. VRF tree does not follow the normal pattern
225 : // for other DBEntries.
226 : //
227 : // VRF flow management implements following functions,
228 : // 1. Generate event to delete VRF when all flows for a VRF are deleted
229 : // 2. Implement lifetime reference to Route Table for INET/Bridge DBTables
230 : // The route-table must be present till all flows relavent for the flow are
231 : // present.
232 : // FlowLifetimeRef implements Lifetime actor on the route-table till all
233 : // flows for the route-table are deleted
234 : //
235 : // When a flow-add is got, we dont really check for presence of VRF or not.
236 : // When adding a flow, FlowTable must ensure that VRF is valid at that time
237 : //
238 : // FlowTable module on the other hand, ensures that flow is not added on a
239 : // non-existing or a deleted VRF
240 : //
241 : // The routes used in flow-entry refer to VRF by vrf-id (ex. RouteFlowRefMap).
242 : // Hence, we dont have VRF pointer in all cases. Instead, we store vrf-id as
243 : // key
244 : ////////////////////////////////////////////////////////////////////////////
245 : class VrfFlowMgmtTree : public FlowMgmtTree {
246 : public:
247 : // Build local mapping of vrf-id to VrfEntry mapping.
248 : // The mapping is already maintained in VrfTable. But, we cannot query it
249 : // since we run in parallel to DB Task context
250 : typedef std::map<uint32_t, const VrfEntry *> VrfIdMap;
251 2 : VrfFlowMgmtTree(FlowMgmtManager *mgr) : FlowMgmtTree(mgr) { }
252 2 : virtual ~VrfFlowMgmtTree() { }
253 :
254 : virtual FlowMgmtEntry *Allocate(const FlowMgmtKey *key);
255 : virtual bool OperEntryAdd(const FlowMgmtRequest *req, FlowMgmtKey *key);
256 : virtual bool OperEntryDelete(const FlowMgmtRequest *req, FlowMgmtKey *key);
257 : void DeleteDefaultRoute(const VrfEntry *vrf);
258 : virtual void FreeNotify(FlowMgmtKey *key, uint32_t gen_id);
259 : void RetryDelete(uint32_t vrf_id);
260 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree);
261 :
262 : private:
263 : VrfIdMap id_map_;
264 : DISALLOW_COPY_AND_ASSIGN(VrfFlowMgmtTree);
265 : };
266 :
267 : class BgpAsAServiceFlowMgmtTree : public FlowMgmtTree {
268 : public:
269 : static const int kInvalidCnIndex = -1;
270 4 : BgpAsAServiceFlowMgmtTree(FlowMgmtManager *mgr, int index) :
271 4 : FlowMgmtTree(mgr), index_(index) {}
272 8 : virtual ~BgpAsAServiceFlowMgmtTree() {}
273 :
274 : void ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree);
275 : FlowMgmtEntry *Allocate(const FlowMgmtKey *key);
276 : bool BgpAsAServiceHealthCheckUpdate(Agent *agent,
277 : BgpAsAServiceFlowMgmtKey &key,
278 : BgpAsAServiceFlowMgmtRequest *req);
279 : bool BgpAsAServiceDelete(BgpAsAServiceFlowMgmtKey &key,
280 : const FlowMgmtRequest *req);
281 : void DeleteAll();
282 : //Gets CN index from flow.
283 : static int GetCNIndex(const FlowEntry *flow);
284 : // Called just before entry is deleted. Used to implement cleanup operations
285 : virtual void FreeNotify(FlowMgmtKey *key, uint32_t gen_id);
286 :
287 : private:
288 : int index_;
289 : DISALLOW_COPY_AND_ASSIGN(BgpAsAServiceFlowMgmtTree);
290 : };
291 :
292 : #endif // __AGENT_PKT_FLOW_MGMT_TREE_H__
|