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