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 : #include <pkt/flow_mgmt/flow_mgmt_tree.h>
7 : #include <pkt/flow_mgmt/flow_mgmt_key.h>
8 : #include <pkt/flow_mgmt/flow_mgmt_entry.h>
9 : #include <pkt/flow_mgmt/flow_mgmt_request.h>
10 : #include <pkt/flow_mgmt.h>
11 :
12 11117 : FlowMgmtEntry *FlowMgmtTree::Find(FlowMgmtKey *key) {
13 11117 : Tree::iterator it = tree_.find(key);
14 11117 : if (it == tree_.end())
15 3658 : return NULL;
16 :
17 7459 : return it->second;
18 : }
19 :
20 6166 : FlowMgmtEntry *FlowMgmtTree::Locate(FlowMgmtKey *key) {
21 6166 : FlowMgmtEntry *entry = Find(key);
22 6166 : if (entry == NULL) {
23 3515 : entry = Allocate(key);
24 3515 : InsertEntry(key->Clone(), entry);
25 : }
26 :
27 6166 : return entry;
28 : }
29 :
30 3515 : void FlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry) {
31 3515 : tree_[key] = entry;
32 3515 : }
33 :
34 222 : FlowMgmtKey *FlowMgmtTree::LowerBound(FlowMgmtKey *key) {
35 222 : Tree::iterator it = tree_.lower_bound(key);
36 222 : if (it == tree_.end())
37 105 : return NULL;
38 :
39 117 : return it->first;
40 : }
41 :
42 4372 : bool FlowMgmtTree::TryDelete(FlowMgmtKey *key, FlowMgmtEntry *entry) {
43 4372 : if (entry->CanDelete() == false)
44 857 : return false;
45 :
46 : // Send message only if we have seen DELETE message from FlowTable
47 3515 : if (entry->oper_state() == FlowMgmtEntry::OPER_DEL_SEEN) {
48 3494 : FreeNotify(key, entry->gen_id());
49 : }
50 :
51 3515 : Tree::iterator it = tree_.find(key);
52 3515 : assert(it != tree_.end());
53 3515 : FlowMgmtKey *first = it->first;
54 3515 : RemoveEntry(it);
55 3515 : delete entry;
56 3515 : delete first;
57 :
58 3515 : return true;
59 : }
60 :
61 3515 : void FlowMgmtTree::RemoveEntry(Tree::iterator it) {
62 3515 : tree_.erase(it);
63 3515 : }
64 :
65 : /////////////////////////////////////////////////////////////////////////////
66 : // Generic Event handler on tree for add/delete of a flow
67 : /////////////////////////////////////////////////////////////////////////////
68 2010 : bool FlowMgmtTree::AddFlowMgmtKey(FlowMgmtKeyTree *tree, FlowMgmtKey *key) {
69 2010 : FlowMgmtKeyNode *node = new FlowMgmtKeyNode();
70 2010 : std::pair<FlowMgmtKeyTree::iterator, bool> ret;
71 2010 : ret = tree->insert(make_pair(key, node));
72 2010 : if (ret.second == false) {
73 809 : delete key;
74 809 : delete node;
75 : }
76 2010 : return ret.second;
77 : }
78 :
79 : // Adds Flow to a FlowMgmtEntry defined by key. Does not allocate FlowMgmtEntry
80 : // if its not already present
81 1168 : bool FlowMgmtTree::Add(FlowMgmtKey *key, FlowEntry *flow,
82 : FlowMgmtKeyNode *node) {
83 1168 : FlowMgmtEntry *entry = Locate(key);
84 1168 : if (entry == NULL) {
85 0 : return false;
86 : }
87 :
88 1168 : return entry->Add(flow, node);
89 : }
90 :
91 790 : bool FlowMgmtTree::Delete(FlowMgmtKey *key, FlowEntry *flow,
92 : FlowMgmtKeyNode *node) {
93 790 : Tree::iterator it = tree_.find(key);
94 790 : if (it == tree_.end()) {
95 0 : return false;
96 : }
97 :
98 790 : FlowMgmtEntry *entry = it->second;
99 790 : bool ret = entry->Delete(flow, node);
100 :
101 790 : TryDelete(it->first, entry);
102 790 : return ret;
103 : }
104 :
105 : /////////////////////////////////////////////////////////////////////////////
106 : // Event handler for add/delete/change of an object
107 : /////////////////////////////////////////////////////////////////////////////
108 :
109 : // Send DBEntry Free message to DB Client module
110 3494 : void FlowMgmtTree::FreeNotify(FlowMgmtKey *key, uint32_t gen_id) {
111 3494 : assert(key->db_entry() != NULL);
112 3494 : FlowEvent::Event event = key->FreeDBEntryEvent();
113 3494 : if (event == FlowEvent::INVALID)
114 0 : return;
115 3494 : mgr_->FreeDBEntryEvent(event, key, gen_id);
116 : }
117 :
118 : // An object is added/updated. Enqueue REVALUATE for flows dependent on it
119 4965 : bool FlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req, FlowMgmtKey *key) {
120 4965 : FlowMgmtEntry *entry = Locate(key);
121 4965 : entry->OperEntryAdd(mgr_, req, key);
122 4965 : return true;
123 : }
124 :
125 11 : bool FlowMgmtTree::OperEntryChange(const FlowMgmtRequest *req,
126 : FlowMgmtKey *key) {
127 11 : FlowMgmtEntry *entry = Find(key);
128 11 : if (entry) {
129 11 : entry->OperEntryChange(mgr_, req, key);
130 : }
131 11 : return true;
132 : }
133 :
134 : // Send DELETE Entry message to FlowTable module
135 3564 : bool FlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
136 : FlowMgmtKey *key) {
137 3564 : FlowMgmtEntry *entry = Find(key);
138 3564 : if (entry == NULL) {
139 0 : FreeNotify(key, req->gen_id());
140 0 : return true;
141 : }
142 :
143 3564 : entry->OperEntryDelete(mgr_, req, key);
144 3564 : return TryDelete(key, entry);
145 : }
146 :
147 10 : bool FlowMgmtTree::RetryDelete(FlowMgmtKey *key) {
148 10 : FlowMgmtEntry *entry = Find(key);
149 10 : if (entry == NULL) {
150 0 : return true;
151 : }
152 :
153 10 : return TryDelete(key, entry);
154 : }
155 :
156 0 : void BgpAsAServiceFlowMgmtTree::FreeNotify(FlowMgmtKey *key, uint32_t gen_id) {
157 0 : assert(key->db_entry() == NULL);
158 0 : }
159 :
160 0 : void BgpAsAServiceFlowMgmtTree::ExtractKeys(FlowEntry *flow,
161 : FlowMgmtKeyTree *tree) {
162 0 : if (flow->is_flags_set(FlowEntry::BgpRouterService) == false)
163 0 : return;
164 : const VmInterface *vm_intf =
165 0 : dynamic_cast<const VmInterface *>(flow->intf_entry());
166 0 : if (!vm_intf || (flow->bgp_as_a_service_sport() == 0))
167 0 : return;
168 :
169 : BgpAsAServiceFlowMgmtKey *key =
170 0 : new BgpAsAServiceFlowMgmtKey(vm_intf->GetUuid(),
171 0 : flow->bgp_as_a_service_sport(),
172 0 : index_, NULL, NULL);
173 0 : AddFlowMgmtKey(tree, key);
174 : }
175 :
176 0 : FlowMgmtEntry *BgpAsAServiceFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
177 0 : return new BgpAsAServiceFlowMgmtEntry();
178 : }
179 :
180 : // Update health check on the BgpAsAService entry
181 0 : bool BgpAsAServiceFlowMgmtTree::BgpAsAServiceHealthCheckUpdate
182 : (Agent *agent, BgpAsAServiceFlowMgmtKey &key,
183 : BgpAsAServiceFlowMgmtRequest *req) {
184 0 : FlowMgmtEntry *entry = Find(&key);
185 0 : if (entry == NULL) {
186 0 : return true;
187 : }
188 :
189 0 : BgpAsAServiceFlowMgmtEntry *bgpaas_entry =
190 : static_cast<BgpAsAServiceFlowMgmtEntry *>(entry);
191 0 : return bgpaas_entry->HealthCheckUpdate(agent, mgr_, key, req);
192 : }
193 :
194 0 : bool BgpAsAServiceFlowMgmtTree::BgpAsAServiceDelete
195 : (BgpAsAServiceFlowMgmtKey &key, const FlowMgmtRequest *req) {
196 0 : FlowMgmtEntry *entry = Find(&key);
197 0 : if (entry == NULL) {
198 0 : return true;
199 : }
200 :
201 0 : entry->NonOperEntryDelete(mgr_, req, &key);
202 0 : return TryDelete(&key, entry);
203 : }
204 :
205 21 : void BgpAsAServiceFlowMgmtTree::DeleteAll() {
206 21 : Tree::iterator it = tree_.begin();
207 21 : while (it != tree_.end()) {
208 : BgpAsAServiceFlowMgmtKey *key =
209 0 : static_cast<BgpAsAServiceFlowMgmtKey *>(it->first);
210 0 : mgr_->BgpAsAServiceNotify(key->uuid(), key->source_port());
211 0 : it++;
212 : }
213 21 : }
214 :
215 0 : int BgpAsAServiceFlowMgmtTree::GetCNIndex(const FlowEntry *flow) {
216 0 : IpAddress dest_ip = IpAddress();
217 0 : if (flow->is_flags_set(FlowEntry::ReverseFlow)) {
218 0 : dest_ip = flow->key().src_addr;
219 : } else {
220 : //No reverse flow means no CN to map to so dont add flow key.
221 0 : if (flow->reverse_flow_entry() == NULL)
222 0 : return BgpAsAServiceFlowMgmtTree::kInvalidCnIndex;
223 0 : dest_ip = flow->reverse_flow_entry()->key().src_addr;
224 : }
225 0 : for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
226 0 : if (flow->flow_table()->agent()->controller_ifmap_xmpp_server(count) ==
227 0 : dest_ip.to_string()) {
228 0 : return count;
229 : }
230 : }
231 0 : return BgpAsAServiceFlowMgmtTree::kInvalidCnIndex;
232 : }
233 :
234 : /////////////////////////////////////////////////////////////////////////////
235 : // Acl Flow Management
236 : /////////////////////////////////////////////////////////////////////////////
237 2990 : void AclFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree,
238 : const MatchAclParamsList *acl_list) {
239 2990 : std::list<MatchAclParams>::const_iterator it;
240 3024 : for (it = acl_list->begin(); it != acl_list->end(); it++) {
241 34 : AclFlowMgmtKey *key = new AclFlowMgmtKey(it->acl.get(),
242 34 : &it->ace_id_list);
243 34 : AddFlowMgmtKey(tree, key);
244 : }
245 2990 : }
246 :
247 230 : void AclFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
248 230 : ExtractKeys(flow, tree, &flow->match_p().m_acl_l);
249 230 : ExtractKeys(flow, tree, &flow->match_p().m_out_acl_l);
250 230 : ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_acl_l);
251 230 : ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_out_acl_l);
252 230 : ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_reverse_acl_l);
253 230 : ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_reverse_out_acl_l);
254 230 : ExtractKeys(flow, tree, &flow->match_p().m_mirror_acl_l);
255 230 : ExtractKeys(flow, tree, &flow->match_p().m_out_mirror_acl_l);
256 230 : ExtractKeys(flow, tree, &flow->match_p().m_vrf_assign_acl_l);
257 230 : ExtractKeys(flow, tree, &flow->match_p().aps_policy.m_acl_l);
258 230 : ExtractKeys(flow, tree, &flow->match_p().aps_policy.m_out_acl_l);
259 230 : ExtractKeys(flow, tree, &flow->match_p().fwaas_policy.m_acl_l);
260 230 : ExtractKeys(flow, tree, &flow->match_p().fwaas_policy.m_out_acl_l);
261 230 : }
262 :
263 5 : FlowMgmtEntry *AclFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
264 5 : return new AclFlowMgmtEntry();
265 : }
266 :
267 33 : bool AclFlowMgmtTree::Add(FlowMgmtKey *key, FlowEntry *flow,
268 : FlowMgmtKey *old_key, FlowMgmtKeyNode *node) {
269 33 : AclFlowMgmtEntry *entry = static_cast<AclFlowMgmtEntry *>(Locate(key));
270 33 : if (entry == NULL) {
271 0 : return false;
272 : }
273 :
274 33 : AclFlowMgmtKey *acl_key = static_cast<AclFlowMgmtKey *>(key);
275 33 : const AclEntryIDList *old_ace_id_list = NULL;
276 33 : if (old_key) {
277 25 : AclFlowMgmtKey *old_acl_key = static_cast<AclFlowMgmtKey *>(old_key);
278 25 : old_ace_id_list = old_acl_key->ace_id_list();
279 : }
280 33 : return entry->Add(acl_key->ace_id_list(), flow, old_ace_id_list, node);
281 : }
282 :
283 8 : bool AclFlowMgmtTree::Delete(FlowMgmtKey *key, FlowEntry *flow,
284 : FlowMgmtKeyNode *node) {
285 8 : Tree::iterator it = tree_.find(key);
286 8 : if (it == tree_.end()) {
287 0 : return false;
288 : }
289 :
290 8 : AclFlowMgmtKey *acl_key = static_cast<AclFlowMgmtKey *>(key);
291 8 : AclFlowMgmtEntry *entry = static_cast<AclFlowMgmtEntry *>(it->second);
292 8 : bool ret = entry->Delete(acl_key->ace_id_list(), flow, node);
293 :
294 8 : TryDelete(it->first, entry);
295 8 : return ret;
296 : }
297 :
298 : /////////////////////////////////////////////////////////////////////////////
299 : // VN Flow Management
300 : /////////////////////////////////////////////////////////////////////////////
301 230 : void VnFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
302 230 : if (flow->vn_entry() == NULL)
303 4 : return;
304 226 : VnFlowMgmtKey *key = new VnFlowMgmtKey(flow->vn_entry());
305 226 : AddFlowMgmtKey(tree, key);
306 : }
307 :
308 69 : FlowMgmtEntry *VnFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
309 69 : return new VnFlowMgmtEntry();
310 : }
311 :
312 69 : void VnFlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry) {
313 69 : std::scoped_lock mutex(mutex_);
314 69 : FlowMgmtTree::InsertEntry(key, entry);
315 69 : }
316 :
317 69 : void VnFlowMgmtTree::RemoveEntry(Tree::iterator it) {
318 69 : std::scoped_lock mutex(mutex_);
319 69 : FlowMgmtTree::RemoveEntry(it);
320 69 : }
321 :
322 0 : void VnFlowMgmtTree::VnFlowCounters(const VnEntry *vn,
323 : uint32_t *ingress_flow_count,
324 : uint32_t *egress_flow_count) {
325 0 : VnFlowMgmtKey key(vn);
326 0 : std::scoped_lock mutex(mutex_);
327 0 : VnFlowMgmtEntry *entry = static_cast<VnFlowMgmtEntry *>(Find(&key));
328 0 : if (entry) {
329 0 : *ingress_flow_count += entry->ingress_flow_count();
330 0 : *egress_flow_count += entry->egress_flow_count();
331 : }
332 0 : }
333 :
334 : /////////////////////////////////////////////////////////////////////////////
335 : // Interface Flow Management
336 : /////////////////////////////////////////////////////////////////////////////
337 337 : void InterfaceFlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry){
338 337 : std::scoped_lock mutex(mutex_);
339 337 : FlowMgmtTree::InsertEntry(key, entry);
340 337 : }
341 :
342 337 : void InterfaceFlowMgmtTree::RemoveEntry(Tree::iterator it) {
343 337 : std::scoped_lock mutex(mutex_);
344 337 : FlowMgmtTree::RemoveEntry(it);
345 337 : }
346 :
347 0 : void InterfaceFlowMgmtTree::InterfaceFlowCount(const Interface *itf,
348 : uint64_t *created,
349 : uint64_t *aged,
350 : uint32_t *active_flows) {
351 0 : InterfaceFlowMgmtKey key(itf);
352 0 : std::scoped_lock mutex(mutex_);
353 : InterfaceFlowMgmtEntry *entry = static_cast<InterfaceFlowMgmtEntry *>
354 0 : (Find(&key));
355 0 : if (entry) {
356 0 : *created += entry->flow_created();
357 0 : *aged += entry->flow_aged();
358 0 : *active_flows += entry->Size();
359 : }
360 0 : }
361 :
362 230 : void InterfaceFlowMgmtTree::ExtractKeys(FlowEntry *flow,
363 : FlowMgmtKeyTree *tree) {
364 230 : if (flow->intf_entry() == NULL)
365 2 : return;
366 : InterfaceFlowMgmtKey *key =
367 228 : new InterfaceFlowMgmtKey(flow->intf_entry());
368 228 : AddFlowMgmtKey(tree, key);
369 : }
370 :
371 337 : FlowMgmtEntry *InterfaceFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
372 337 : return new InterfaceFlowMgmtEntry();
373 : }
374 :
375 : /////////////////////////////////////////////////////////////////////////////
376 : // Nh Flow Management
377 : /////////////////////////////////////////////////////////////////////////////
378 230 : void NhFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
379 230 : if (flow->rpf_nh() == NULL)
380 16 : return;
381 214 : NhFlowMgmtKey *key = new NhFlowMgmtKey(flow->rpf_nh());
382 214 : AddFlowMgmtKey(tree, key);
383 : }
384 :
385 1650 : FlowMgmtEntry *NhFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
386 1650 : return new NhFlowMgmtEntry();
387 : }
388 :
389 : /////////////////////////////////////////////////////////////////////////////
390 : // Route Flow Management
391 : /////////////////////////////////////////////////////////////////////////////
392 354 : bool RouteFlowMgmtTree::Delete(FlowMgmtKey *key, FlowEntry *flow,
393 : FlowMgmtKeyNode *node) {
394 354 : bool ret = FlowMgmtTree::Delete(key, flow, node);
395 354 : RouteFlowMgmtKey *route_key = static_cast<RouteFlowMgmtKey *>(key);
396 354 : mgr_->RetryVrfDelete(route_key->vrf_id());
397 354 : return ret;
398 : }
399 :
400 4177 : void RouteFlowMgmtTree::SetDBEntry(const FlowMgmtRequest *req,
401 : FlowMgmtKey *key) {
402 4177 : Tree::iterator it = tree_.find(key);
403 4177 : if (it == tree_.end()) {
404 0 : return;
405 : }
406 :
407 4177 : if (req->db_entry() == NULL) {
408 0 : return;
409 : }
410 :
411 4177 : if (it->first->db_entry()) {
412 2817 : assert(it->first->db_entry() == req->db_entry());
413 2817 : return;
414 : }
415 1360 : it->first->set_db_entry(req->db_entry());
416 1360 : return;
417 : }
418 :
419 1360 : bool RouteFlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
420 : FlowMgmtKey *key) {
421 : // Set the db_entry if it was not set earlier. It is needed to send the
422 : // FreeDBState message
423 1360 : SetDBEntry(req, key);
424 1360 : bool ret = FlowMgmtTree::OperEntryDelete(req, key);
425 1360 : RouteFlowMgmtKey *route_key = static_cast<RouteFlowMgmtKey *>(key);
426 1360 : mgr_->RetryVrfDelete(route_key->vrf_id());
427 1360 : return ret;
428 : }
429 :
430 2817 : bool RouteFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
431 : FlowMgmtKey *key) {
432 2817 : bool ret = FlowMgmtTree::OperEntryAdd(req, key);
433 2817 : if (req->db_entry() == NULL)
434 0 : return ret;
435 :
436 : // Set the DBEntry in the flow-mgmt-entry
437 2817 : SetDBEntry(req, key);
438 2817 : return ret;
439 : }
440 :
441 : /////////////////////////////////////////////////////////////////////////////
442 : // Inet Route Flow Management
443 : /////////////////////////////////////////////////////////////////////////////
444 1198 : void InetRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree,
445 : uint32_t vrf, const IpAddress &ip,
446 : uint8_t plen) {
447 : // We do not support renewal of VRF, so skip flow if VRF is deleted
448 1198 : VrfEntry *vrfp = mgr_->agent()->vrf_table()->FindVrfFromId(vrf);
449 1198 : if (vrfp == NULL) {
450 0 : return;
451 : }
452 :
453 1198 : InetRouteFlowMgmtKey *key = NULL;
454 : /*
455 : * For L2 flows, plen is found using LPMFind
456 : * when route is not found plen is set to -1(255)
457 : * in that case key should not be added
458 : */
459 1198 : if (flow->l3_flow() || (plen != 255)) {
460 1176 : if (ip.is_v4()) {
461 1176 : Ip4Address ip4 = Address::GetIp4SubnetAddress(ip.to_v4(), plen);
462 1176 : key = new InetRouteFlowMgmtKey(vrf, ip4, plen);
463 : } else {
464 0 : Ip6Address ip6 = Address::GetIp6SubnetAddress(ip.to_v6(), plen);
465 0 : key = new InetRouteFlowMgmtKey(vrf, ip6, plen);
466 : }
467 : }
468 :
469 1198 : if (key) {
470 1176 : AddFlowMgmtKey(tree, key);
471 : }
472 : }
473 :
474 584 : void InetRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree,
475 : const IpAddress &ip,
476 : const FlowRouteRefMap *rt_list) {
477 584 : FlowRouteRefMap::const_iterator it;
478 1096 : for (it = rt_list->begin(); it != rt_list->end(); it++) {
479 512 : ExtractKeys(flow, tree, it->first, ip, it->second);
480 : }
481 584 : }
482 :
483 460 : void InetRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow,
484 : FlowMgmtKeyTree *tree) {
485 :
486 460 : if (flow->l3_flow() == false) {
487 : // For l2-flows Track INET route for RPF only
488 168 : if (flow->data().rpf_vrf != VrfEntry::kInvalidIndex) {
489 150 : ExtractKeys(flow, tree, flow->data().rpf_vrf,
490 150 : flow->key().src_addr, flow->data().rpf_plen);
491 : }
492 168 : return;
493 : }
494 :
495 292 : if (flow->data().flow_source_vrf != VrfEntry::kInvalidIndex) {
496 268 : ExtractKeys(flow, tree, flow->data().flow_source_vrf,
497 268 : flow->key().src_addr, flow->data().source_plen);
498 : }
499 :
500 292 : if (flow->data().acl_assigned_vrf_index_ != VrfEntry::kInvalidIndex) {
501 0 : ExtractKeys(flow, tree, flow->data().acl_assigned_vrf_index_,
502 0 : flow->key().src_addr, flow->data().source_plen);
503 0 : ExtractKeys(flow, tree, flow->data().acl_assigned_vrf_index_,
504 0 : flow->key().dst_addr, flow->data().dest_plen);
505 : }
506 :
507 292 : ExtractKeys(flow, tree, flow->key().src_addr,
508 292 : &flow->data().flow_source_plen_map);
509 :
510 292 : if (flow->data().flow_dest_vrf != VrfEntry::kInvalidIndex) {
511 268 : ExtractKeys(flow, tree, flow->data().flow_dest_vrf,
512 268 : flow->key().dst_addr, flow->data().dest_plen);
513 : }
514 292 : ExtractKeys(flow, tree, flow->key().dst_addr,
515 292 : &flow->data().flow_dest_plen_map);
516 :
517 292 : if (flow->data().src_policy_vrf != VrfEntry::kInvalidIndex) {
518 0 : ExtractKeys(flow, tree, flow->data().src_policy_vrf,
519 0 : flow->key().src_addr, flow->data().src_policy_plen);
520 : }
521 :
522 292 : if (flow->data().dst_policy_vrf != VrfEntry::kInvalidIndex) {
523 0 : ExtractKeys(flow, tree, flow->data().dst_policy_vrf,
524 0 : flow->key().dst_addr, flow->data().dst_policy_plen);
525 : }
526 :
527 : }
528 :
529 956 : FlowMgmtEntry *InetRouteFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
530 956 : return new InetRouteFlowMgmtEntry();
531 : }
532 :
533 148 : bool InetRouteFlowMgmtTree::HasVrfFlows(uint32_t vrf,
534 : Agent::RouteTableType type) {
535 148 : InetRouteFlowMgmtKey *next_key = NULL;
536 :
537 148 : if (type == Agent::INET4_UNICAST) {
538 74 : InetRouteFlowMgmtKey key(vrf, Ip4Address(0), 0);
539 74 : next_key = static_cast<InetRouteFlowMgmtKey *>(LowerBound(&key));
540 148 : } else if (type == Agent::INET6_UNICAST) {
541 74 : InetRouteFlowMgmtKey key(vrf, Ip6Address(), 0);
542 74 : next_key = static_cast<InetRouteFlowMgmtKey *>(LowerBound(&key));
543 74 : } else {
544 0 : return false;
545 : }
546 :
547 148 : if (next_key == NULL)
548 70 : return false;
549 :
550 78 : if (next_key->vrf_id() != vrf)
551 78 : return false;
552 :
553 0 : return true;
554 : }
555 :
556 1911 : bool InetRouteFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
557 : FlowMgmtKey *key) {
558 1911 : bool ret = RouteFlowMgmtTree::OperEntryAdd(req, key);
559 :
560 : // A new route is added. This new route can be a longer prefix route for
561 : // flows using lower prefix-len (covering routes). So, do a LPM match to
562 : // find the covering route and trigger flow re-compute for flows on the
563 : // covering route
564 1911 : InetRouteFlowMgmtKey *rt_key = static_cast<InetRouteFlowMgmtKey *>(key);
565 1911 : AddToLPMTree(rt_key);
566 1911 : if (rt_key->plen_ > 0) {
567 1887 : InetRouteFlowMgmtKey lpm_key(rt_key->vrf_id_, rt_key->ip_,
568 1887 : rt_key->plen_ - 1);
569 1887 : InetRouteFlowMgmtKey *covering_route = LPM(&lpm_key);
570 1887 : if (covering_route != NULL) {
571 850 : ret = RecomputeCoveringRoute(covering_route, rt_key);
572 : }
573 1887 : rt_key->plen_ += 1;
574 1887 : }
575 :
576 1911 : return ret;
577 : }
578 :
579 850 : bool InetRouteFlowMgmtTree::RecomputeCoveringRoute
580 : (InetRouteFlowMgmtKey *covering_route, InetRouteFlowMgmtKey *key) {
581 850 : InetRouteFlowMgmtEntry *entry = dynamic_cast<InetRouteFlowMgmtEntry *>
582 850 : (Find(covering_route));
583 850 : if (entry == NULL) {
584 0 : return true;
585 : }
586 :
587 850 : return entry->RecomputeCoveringRouteEntry(mgr_, covering_route, key);
588 : }
589 :
590 936 : bool InetRouteFlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
591 : FlowMgmtKey *key) {
592 936 : InetRouteFlowMgmtKey *rt_key = static_cast<InetRouteFlowMgmtKey *>(key);
593 936 : DelFromLPMTree(rt_key);
594 936 : return RouteFlowMgmtTree::OperEntryDelete(req, key);
595 : }
596 :
597 4 : bool InetRouteFlowMgmtTree::RouteNHChangeEvent(const FlowMgmtRequest *req,
598 : FlowMgmtKey *key) {
599 : InetRouteFlowMgmtEntry *entry = static_cast<InetRouteFlowMgmtEntry*>
600 4 : (Find(key));
601 4 : if (entry == NULL) {
602 0 : return true;
603 : }
604 :
605 4 : return entry->HandleNhChange(mgr_, req, key);
606 : }
607 :
608 : /////////////////////////////////////////////////////////////////////////////
609 : // Bridge Route Flow Management
610 : /////////////////////////////////////////////////////////////////////////////
611 230 : void BridgeRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow,
612 : FlowMgmtKeyTree *tree) {
613 230 : if (flow->l3_flow() == true)
614 146 : return;
615 :
616 84 : VrfTable *table = mgr_->agent()->vrf_table();
617 84 : uint32_t vrf = flow->data().flow_source_vrf;
618 84 : if (vrf != VrfEntry::kInvalidIndex && table->FindVrfFromId(vrf) != NULL) {
619 : BridgeRouteFlowMgmtKey *key =
620 66 : new BridgeRouteFlowMgmtKey(vrf, flow->data().smac);
621 66 : AddFlowMgmtKey(tree, key);
622 : }
623 :
624 84 : vrf = flow->data().flow_dest_vrf;
625 84 : if (vrf != VrfEntry::kInvalidIndex && table->FindVrfFromId(vrf) != NULL) {
626 : BridgeRouteFlowMgmtKey *key =
627 66 : new BridgeRouteFlowMgmtKey(vrf, flow->data().smac);
628 66 : AddFlowMgmtKey(tree, key);
629 : }
630 : }
631 :
632 424 : FlowMgmtEntry *BridgeRouteFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
633 424 : return new BridgeRouteFlowMgmtEntry();
634 : }
635 :
636 74 : bool BridgeRouteFlowMgmtTree::HasVrfFlows(uint32_t vrf,
637 : Agent::RouteTableType type) {
638 74 : BridgeRouteFlowMgmtKey key(vrf, MacAddress::ZeroMac());
639 : BridgeRouteFlowMgmtKey *next_key = static_cast<BridgeRouteFlowMgmtKey *>
640 74 : (LowerBound(&key));
641 74 : if (next_key == NULL)
642 35 : return false;
643 :
644 39 : if (next_key->vrf_id() != vrf)
645 39 : return false;
646 :
647 0 : return true;
648 74 : }
649 :
650 : /////////////////////////////////////////////////////////////////////////////
651 : // Vrf Flow Management
652 : /////////////////////////////////////////////////////////////////////////////
653 0 : void VrfFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
654 0 : }
655 :
656 74 : FlowMgmtEntry *VrfFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
657 74 : const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
658 74 : return new VrfFlowMgmtEntry(this, vrf);
659 : }
660 :
661 74 : bool VrfFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
662 : FlowMgmtKey *key) {
663 74 : bool ret = FlowMgmtTree::OperEntryAdd(req, key);
664 :
665 74 : const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
666 74 : VrfIdMap::iterator it = id_map_.find(vrf->vrf_id());
667 74 : if (it != id_map_.end())
668 0 : return ret;
669 :
670 74 : id_map_.insert(make_pair(vrf->vrf_id(), vrf));
671 74 : return ret;
672 : }
673 :
674 74 : void VrfFlowMgmtTree::FreeNotify(FlowMgmtKey *key, uint32_t gen_id) {
675 74 : FlowMgmtTree::FreeNotify(key, gen_id);
676 :
677 74 : const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
678 74 : VrfIdMap::iterator it = id_map_.find(vrf->vrf_id());
679 74 : if (it != id_map_.end()) {
680 74 : id_map_.erase(it);
681 : }
682 74 : }
683 :
684 1936 : void VrfFlowMgmtTree::RetryDelete(uint32_t vrf_id) {
685 1936 : VrfIdMap::iterator it = id_map_.find(vrf_id);
686 1936 : if (it == id_map_.end())
687 2 : return;
688 :
689 1934 : VrfFlowMgmtKey key(it->second);
690 1934 : const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(key.db_entry());
691 1934 : if (vrf && vrf->AllRouteTablesEmpty()) {
692 10 : FlowMgmtTree::RetryDelete(&key);
693 : }
694 1934 : }
695 :
696 144 : void VrfFlowMgmtTree::DeleteDefaultRoute(const VrfEntry *vrf) {
697 : //If VMI is associated to FIP, then all non floating-ip
698 : //traffic would also be dependent FIP VRF route. This is
699 : //to ensure that if more specific route gets added preference
700 : //would be given to floating-ip
701 : //
702 : //Assume a sceanrio where traffic is not NATed, then flow would
703 : //add a dependency on default route(assume no default route is
704 : //present in FIP VRF). Now if FIP VRF is deleted there is no explicit
705 : //trigger to delete this dependencyi and hence delay in releasing VRF
706 : //reference, hence if default route DB entry is not present
707 : //impliticly delete the default route so that flow could get
708 144 : InetRouteFlowMgmtKey key(vrf->vrf_id(), Ip4Address(0), 0);
709 144 : FlowMgmtEntry *route_entry = mgr_->ip4_route_flow_mgmt_tree()->Find(&key);
710 145 : if (route_entry == NULL ||
711 1 : route_entry->oper_state() != FlowMgmtEntry::OPER_NOT_SEEN) {
712 : //If entry is not present on it has corresponding DB entry
713 : //no need for implicit delete
714 144 : return;
715 : }
716 :
717 0 : FlowMgmtRequest route_req(FlowMgmtRequest::IMPLICIT_ROUTE_DELETE);
718 0 : FlowMgmtManager::ProcessEvent(
719 0 : &route_req, &key, mgr_->ip4_route_flow_mgmt_tree());
720 144 : }
721 :
722 144 : bool VrfFlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
723 : FlowMgmtKey *key) {
724 144 : const VrfEntry* vrf = static_cast<const VrfEntry *>(req->db_entry());
725 144 : DeleteDefaultRoute(vrf);
726 :
727 144 : return FlowMgmtTree::OperEntryDelete(req, key);
728 : }
|