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 1590 : FlowMgmtEntry *FlowMgmtTree::Find(FlowMgmtKey *key) {
12 1590 : Tree::iterator it = tree_.find(key);
13 1590 : if (it == tree_.end())
14 364 : return NULL;
15 :
16 1226 : return it->second;
17 : }
18 :
19 985 : FlowMgmtEntry *FlowMgmtTree::Locate(FlowMgmtKey *key) {
20 985 : FlowMgmtEntry *entry = Find(key);
21 985 : if (entry == NULL) {
22 346 : entry = Allocate(key);
23 346 : InsertEntry(key->Clone(), entry);
24 : }
25 :
26 985 : return entry;
27 : }
28 :
29 346 : void FlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry) {
30 346 : tree_[key] = entry;
31 346 : }
32 :
33 36 : FlowMgmtKey *FlowMgmtTree::LowerBound(FlowMgmtKey *key) {
34 36 : Tree::iterator it = tree_.lower_bound(key);
35 36 : if (it == tree_.end())
36 36 : return NULL;
37 :
38 0 : return it->first;
39 : }
40 :
41 578 : bool FlowMgmtTree::TryDelete(FlowMgmtKey *key, FlowMgmtEntry *entry) {
42 578 : if (entry->CanDelete() == false)
43 232 : return false;
44 :
45 : // Send message only if we have seen DELETE message from FlowTable
46 346 : if (entry->oper_state() == FlowMgmtEntry::OPER_DEL_SEEN) {
47 344 : FreeNotify(key, entry->gen_id());
48 : }
49 :
50 346 : Tree::iterator it = tree_.find(key);
51 346 : assert(it != tree_.end());
52 346 : FlowMgmtKey *first = it->first;
53 346 : RemoveEntry(it);
54 346 : delete entry;
55 346 : delete first;
56 :
57 346 : return true;
58 : }
59 :
60 346 : void FlowMgmtTree::RemoveEntry(Tree::iterator it) {
61 346 : tree_.erase(it);
62 346 : }
63 :
64 : /////////////////////////////////////////////////////////////////////////////
65 : // Generic Event handler on tree for add/delete of a flow
66 : /////////////////////////////////////////////////////////////////////////////
67 648 : bool FlowMgmtTree::AddFlowMgmtKey(FlowMgmtKeyTree *tree, FlowMgmtKey *key) {
68 648 : FlowMgmtKeyNode *node = new FlowMgmtKeyNode();
69 648 : std::pair<FlowMgmtKeyTree::iterator, bool> ret;
70 648 : ret = tree->insert(make_pair(key, node));
71 648 : if (ret.second == false) {
72 163 : delete key;
73 163 : delete node;
74 : }
75 648 : 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 453 : bool FlowMgmtTree::Add(FlowMgmtKey *key, FlowEntry *flow,
81 : FlowMgmtKeyNode *node) {
82 453 : FlowMgmtEntry *entry = Locate(key);
83 453 : if (entry == NULL) {
84 0 : return false;
85 : }
86 :
87 453 : return entry->Add(flow, node);
88 : }
89 :
90 206 : bool FlowMgmtTree::Delete(FlowMgmtKey *key, FlowEntry *flow,
91 : FlowMgmtKeyNode *node) {
92 206 : Tree::iterator it = tree_.find(key);
93 206 : if (it == tree_.end()) {
94 0 : return false;
95 : }
96 :
97 206 : FlowMgmtEntry *entry = it->second;
98 206 : bool ret = entry->Delete(flow, node);
99 :
100 206 : TryDelete(it->first, entry);
101 206 : 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 344 : void FlowMgmtTree::FreeNotify(FlowMgmtKey *key, uint32_t gen_id) {
110 344 : assert(key->db_entry() != NULL);
111 344 : FlowEvent::Event event = key->FreeDBEntryEvent();
112 344 : if (event == FlowEvent::INVALID)
113 0 : return;
114 344 : mgr_->FreeDBEntryEvent(event, key, gen_id);
115 : }
116 :
117 : // An object is added/updated. Enqueue REVALUATE for flows dependent on it
118 500 : bool FlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req, FlowMgmtKey *key) {
119 500 : FlowMgmtEntry *entry = Locate(key);
120 500 : entry->OperEntryAdd(mgr_, req, key);
121 500 : return true;
122 : }
123 :
124 11 : bool FlowMgmtTree::OperEntryChange(const FlowMgmtRequest *req,
125 : FlowMgmtKey *key) {
126 11 : FlowMgmtEntry *entry = Find(key);
127 11 : if (entry) {
128 11 : entry->OperEntryChange(mgr_, req, key);
129 : }
130 11 : return true;
131 : }
132 :
133 : // Send DELETE Entry message to FlowTable module
134 350 : bool FlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
135 : FlowMgmtKey *key) {
136 350 : FlowMgmtEntry *entry = Find(key);
137 350 : if (entry == NULL) {
138 0 : FreeNotify(key, req->gen_id());
139 0 : return true;
140 : }
141 :
142 350 : entry->OperEntryDelete(mgr_, req, key);
143 350 : return TryDelete(key, entry);
144 : }
145 :
146 15 : bool FlowMgmtTree::RetryDelete(FlowMgmtKey *key) {
147 15 : FlowMgmtEntry *entry = Find(key);
148 15 : if (entry == NULL) {
149 0 : return true;
150 : }
151 :
152 15 : 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 4 : void BgpAsAServiceFlowMgmtTree::DeleteAll() {
205 4 : Tree::iterator it = tree_.begin();
206 4 : 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 4 : }
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 1300 : void AclFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree,
237 : const MatchAclParamsList *acl_list) {
238 1300 : std::list<MatchAclParams>::const_iterator it;
239 1332 : for (it = acl_list->begin(); it != acl_list->end(); it++) {
240 32 : AclFlowMgmtKey *key = new AclFlowMgmtKey(it->acl.get(),
241 32 : &it->ace_id_list);
242 32 : AddFlowMgmtKey(tree, key);
243 : }
244 1300 : }
245 :
246 100 : void AclFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
247 100 : ExtractKeys(flow, tree, &flow->match_p().m_acl_l);
248 100 : ExtractKeys(flow, tree, &flow->match_p().m_out_acl_l);
249 100 : ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_acl_l);
250 100 : ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_out_acl_l);
251 100 : ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_reverse_acl_l);
252 100 : ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_reverse_out_acl_l);
253 100 : ExtractKeys(flow, tree, &flow->match_p().m_mirror_acl_l);
254 100 : ExtractKeys(flow, tree, &flow->match_p().m_out_mirror_acl_l);
255 100 : ExtractKeys(flow, tree, &flow->match_p().m_vrf_assign_acl_l);
256 100 : ExtractKeys(flow, tree, &flow->match_p().aps_policy.m_acl_l);
257 100 : ExtractKeys(flow, tree, &flow->match_p().aps_policy.m_out_acl_l);
258 100 : ExtractKeys(flow, tree, &flow->match_p().fwaas_policy.m_acl_l);
259 100 : ExtractKeys(flow, tree, &flow->match_p().fwaas_policy.m_out_acl_l);
260 100 : }
261 :
262 4 : FlowMgmtEntry *AclFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
263 4 : return new AclFlowMgmtEntry();
264 : }
265 :
266 32 : bool AclFlowMgmtTree::Add(FlowMgmtKey *key, FlowEntry *flow,
267 : FlowMgmtKey *old_key, FlowMgmtKeyNode *node) {
268 32 : AclFlowMgmtEntry *entry = static_cast<AclFlowMgmtEntry *>(Locate(key));
269 32 : if (entry == NULL) {
270 0 : return false;
271 : }
272 :
273 32 : AclFlowMgmtKey *acl_key = static_cast<AclFlowMgmtKey *>(key);
274 32 : const AclEntryIDList *old_ace_id_list = NULL;
275 32 : if (old_key) {
276 25 : AclFlowMgmtKey *old_acl_key = static_cast<AclFlowMgmtKey *>(old_key);
277 25 : old_ace_id_list = old_acl_key->ace_id_list();
278 : }
279 32 : 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 100 : void VnFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
301 100 : if (flow->vn_entry() == NULL)
302 0 : return;
303 100 : VnFlowMgmtKey *key = new VnFlowMgmtKey(flow->vn_entry());
304 100 : AddFlowMgmtKey(tree, key);
305 : }
306 :
307 6 : FlowMgmtEntry *VnFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
308 6 : return new VnFlowMgmtEntry();
309 : }
310 :
311 6 : void VnFlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry) {
312 6 : std::scoped_lock mutex(mutex_);
313 6 : FlowMgmtTree::InsertEntry(key, entry);
314 6 : }
315 :
316 6 : void VnFlowMgmtTree::RemoveEntry(Tree::iterator it) {
317 6 : std::scoped_lock mutex(mutex_);
318 6 : FlowMgmtTree::RemoveEntry(it);
319 6 : }
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 100 : void InterfaceFlowMgmtTree::ExtractKeys(FlowEntry *flow,
362 : FlowMgmtKeyTree *tree) {
363 100 : if (flow->intf_entry() == NULL)
364 0 : return;
365 : InterfaceFlowMgmtKey *key =
366 100 : new InterfaceFlowMgmtKey(flow->intf_entry());
367 100 : 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 100 : void NhFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
378 100 : if (flow->rpf_nh() == NULL)
379 10 : return;
380 90 : NhFlowMgmtKey *key = new NhFlowMgmtKey(flow->rpf_nh());
381 90 : AddFlowMgmtKey(tree, key);
382 : }
383 :
384 160 : FlowMgmtEntry *NhFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
385 160 : return new NhFlowMgmtEntry();
386 : }
387 :
388 : /////////////////////////////////////////////////////////////////////////////
389 : // Route Flow Management
390 : /////////////////////////////////////////////////////////////////////////////
391 72 : bool RouteFlowMgmtTree::Delete(FlowMgmtKey *key, FlowEntry *flow,
392 : FlowMgmtKeyNode *node) {
393 72 : bool ret = FlowMgmtTree::Delete(key, flow, node);
394 72 : RouteFlowMgmtKey *route_key = static_cast<RouteFlowMgmtKey *>(key);
395 72 : mgr_->RetryVrfDelete(route_key->vrf_id());
396 72 : return ret;
397 : }
398 :
399 406 : void RouteFlowMgmtTree::SetDBEntry(const FlowMgmtRequest *req,
400 : FlowMgmtKey *key) {
401 406 : Tree::iterator it = tree_.find(key);
402 406 : if (it == tree_.end()) {
403 0 : return;
404 : }
405 :
406 406 : if (req->db_entry() == NULL) {
407 0 : return;
408 : }
409 :
410 406 : if (it->first->db_entry()) {
411 275 : assert(it->first->db_entry() == req->db_entry());
412 275 : return;
413 : }
414 131 : it->first->set_db_entry(req->db_entry());
415 131 : return;
416 : }
417 :
418 131 : 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 131 : SetDBEntry(req, key);
423 131 : bool ret = FlowMgmtTree::OperEntryDelete(req, key);
424 131 : RouteFlowMgmtKey *route_key = static_cast<RouteFlowMgmtKey *>(key);
425 131 : mgr_->RetryVrfDelete(route_key->vrf_id());
426 131 : return ret;
427 : }
428 :
429 275 : bool RouteFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
430 : FlowMgmtKey *key) {
431 275 : bool ret = FlowMgmtTree::OperEntryAdd(req, key);
432 275 : if (req->db_entry() == NULL)
433 0 : return ret;
434 :
435 : // Set the DBEntry in the flow-mgmt-entry
436 275 : SetDBEntry(req, key);
437 275 : return ret;
438 : }
439 :
440 : /////////////////////////////////////////////////////////////////////////////
441 : // Inet Route Flow Management
442 : /////////////////////////////////////////////////////////////////////////////
443 220 : 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 220 : VrfEntry *vrfp = mgr_->agent()->vrf_table()->FindVrfFromId(vrf);
448 220 : if (vrfp == NULL) {
449 0 : return;
450 : }
451 :
452 220 : 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 220 : if (flow->l3_flow() || (plen != 255)) {
459 202 : if (ip.is_v4()) {
460 202 : Ip4Address ip4 = Address::GetIp4SubnetAddress(ip.to_v4(), plen);
461 202 : 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 220 : if (key) {
469 202 : 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 200 : void InetRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow,
483 : FlowMgmtKeyTree *tree) {
484 :
485 200 : if (flow->l3_flow() == false) {
486 : // For l2-flows Track INET route for RPF only
487 156 : if (flow->data().rpf_vrf != VrfEntry::kInvalidIndex) {
488 140 : ExtractKeys(flow, tree, flow->data().rpf_vrf,
489 140 : flow->key().src_addr, flow->data().rpf_plen);
490 : }
491 156 : 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 81 : FlowMgmtEntry *InetRouteFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
529 81 : return new InetRouteFlowMgmtEntry();
530 : }
531 :
532 24 : bool InetRouteFlowMgmtTree::HasVrfFlows(uint32_t vrf,
533 : Agent::RouteTableType type) {
534 24 : InetRouteFlowMgmtKey *next_key = NULL;
535 :
536 24 : if (type == Agent::INET4_UNICAST) {
537 12 : InetRouteFlowMgmtKey key(vrf, Ip4Address(0), 0);
538 12 : next_key = static_cast<InetRouteFlowMgmtKey *>(LowerBound(&key));
539 24 : } else if (type == Agent::INET6_UNICAST) {
540 12 : InetRouteFlowMgmtKey key(vrf, Ip6Address(), 0);
541 12 : next_key = static_cast<InetRouteFlowMgmtKey *>(LowerBound(&key));
542 12 : } else {
543 0 : return false;
544 : }
545 :
546 24 : if (next_key == NULL)
547 24 : return false;
548 :
549 0 : if (next_key->vrf_id() != vrf)
550 0 : return false;
551 :
552 0 : return true;
553 : }
554 :
555 164 : bool InetRouteFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
556 : FlowMgmtKey *key) {
557 164 : 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 164 : InetRouteFlowMgmtKey *rt_key = static_cast<InetRouteFlowMgmtKey *>(key);
564 164 : AddToLPMTree(rt_key);
565 164 : if (rt_key->plen_ > 0) {
566 150 : InetRouteFlowMgmtKey lpm_key(rt_key->vrf_id_, rt_key->ip_,
567 150 : rt_key->plen_ - 1);
568 150 : InetRouteFlowMgmtKey *covering_route = LPM(&lpm_key);
569 150 : if (covering_route != NULL) {
570 67 : ret = RecomputeCoveringRoute(covering_route, rt_key);
571 : }
572 150 : rt_key->plen_ += 1;
573 150 : }
574 :
575 164 : return ret;
576 : }
577 :
578 67 : bool InetRouteFlowMgmtTree::RecomputeCoveringRoute
579 : (InetRouteFlowMgmtKey *covering_route, InetRouteFlowMgmtKey *key) {
580 67 : InetRouteFlowMgmtEntry *entry = dynamic_cast<InetRouteFlowMgmtEntry *>
581 67 : (Find(covering_route));
582 67 : if (entry == NULL) {
583 0 : return true;
584 : }
585 :
586 67 : return entry->RecomputeCoveringRouteEntry(mgr_, covering_route, key);
587 : }
588 :
589 79 : bool InetRouteFlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
590 : FlowMgmtKey *key) {
591 79 : InetRouteFlowMgmtKey *rt_key = static_cast<InetRouteFlowMgmtKey *>(key);
592 79 : DelFromLPMTree(rt_key);
593 79 : return RouteFlowMgmtTree::OperEntryDelete(req, key);
594 : }
595 :
596 0 : bool InetRouteFlowMgmtTree::RouteNHChangeEvent(const FlowMgmtRequest *req,
597 : FlowMgmtKey *key) {
598 : InetRouteFlowMgmtEntry *entry = static_cast<InetRouteFlowMgmtEntry*>
599 0 : (Find(key));
600 0 : if (entry == NULL) {
601 0 : return true;
602 : }
603 :
604 0 : return entry->HandleNhChange(mgr_, req, key);
605 : }
606 :
607 : /////////////////////////////////////////////////////////////////////////////
608 : // Bridge Route Flow Management
609 : /////////////////////////////////////////////////////////////////////////////
610 100 : void BridgeRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow,
611 : FlowMgmtKeyTree *tree) {
612 100 : if (flow->l3_flow() == true)
613 22 : return;
614 :
615 78 : VrfTable *table = mgr_->agent()->vrf_table();
616 78 : uint32_t vrf = flow->data().flow_source_vrf;
617 78 : if (vrf != VrfEntry::kInvalidIndex && table->FindVrfFromId(vrf) != NULL) {
618 : BridgeRouteFlowMgmtKey *key =
619 62 : new BridgeRouteFlowMgmtKey(vrf, flow->data().smac);
620 62 : AddFlowMgmtKey(tree, key);
621 : }
622 :
623 78 : vrf = flow->data().flow_dest_vrf;
624 78 : if (vrf != VrfEntry::kInvalidIndex && table->FindVrfFromId(vrf) != NULL) {
625 : BridgeRouteFlowMgmtKey *key =
626 62 : new BridgeRouteFlowMgmtKey(vrf, flow->data().smac);
627 62 : AddFlowMgmtKey(tree, key);
628 : }
629 : }
630 :
631 52 : FlowMgmtEntry *BridgeRouteFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
632 52 : return new BridgeRouteFlowMgmtEntry();
633 : }
634 :
635 12 : bool BridgeRouteFlowMgmtTree::HasVrfFlows(uint32_t vrf,
636 : Agent::RouteTableType type) {
637 12 : BridgeRouteFlowMgmtKey key(vrf, MacAddress::ZeroMac());
638 : BridgeRouteFlowMgmtKey *next_key = static_cast<BridgeRouteFlowMgmtKey *>
639 12 : (LowerBound(&key));
640 12 : if (next_key == NULL)
641 12 : return false;
642 :
643 0 : if (next_key->vrf_id() != vrf)
644 0 : return false;
645 :
646 0 : return true;
647 12 : }
648 :
649 : /////////////////////////////////////////////////////////////////////////////
650 : // Vrf Flow Management
651 : /////////////////////////////////////////////////////////////////////////////
652 0 : void VrfFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
653 0 : }
654 :
655 12 : FlowMgmtEntry *VrfFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
656 12 : const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
657 12 : return new VrfFlowMgmtEntry(this, vrf);
658 : }
659 :
660 12 : bool VrfFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
661 : FlowMgmtKey *key) {
662 12 : bool ret = FlowMgmtTree::OperEntryAdd(req, key);
663 :
664 12 : const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
665 12 : VrfIdMap::iterator it = id_map_.find(vrf->vrf_id());
666 12 : if (it != id_map_.end())
667 0 : return ret;
668 :
669 12 : id_map_.insert(make_pair(vrf->vrf_id(), vrf));
670 12 : return ret;
671 : }
672 :
673 12 : void VrfFlowMgmtTree::FreeNotify(FlowMgmtKey *key, uint32_t gen_id) {
674 12 : FlowMgmtTree::FreeNotify(key, gen_id);
675 :
676 12 : const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
677 12 : VrfIdMap::iterator it = id_map_.find(vrf->vrf_id());
678 12 : if (it != id_map_.end()) {
679 12 : id_map_.erase(it);
680 : }
681 12 : }
682 :
683 239 : void VrfFlowMgmtTree::RetryDelete(uint32_t vrf_id) {
684 239 : VrfIdMap::iterator it = id_map_.find(vrf_id);
685 239 : if (it == id_map_.end())
686 3 : return;
687 :
688 236 : VrfFlowMgmtKey key(it->second);
689 236 : const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(key.db_entry());
690 236 : if (vrf && vrf->AllRouteTablesEmpty()) {
691 15 : FlowMgmtTree::RetryDelete(&key);
692 : }
693 236 : }
694 :
695 18 : 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 18 : InetRouteFlowMgmtKey key(vrf->vrf_id(), Ip4Address(0), 0);
708 18 : FlowMgmtEntry *route_entry = mgr_->ip4_route_flow_mgmt_tree()->Find(&key);
709 18 : 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 18 : 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 18 : }
720 :
721 18 : bool VrfFlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
722 : FlowMgmtKey *key) {
723 18 : const VrfEntry* vrf = static_cast<const VrfEntry *>(req->db_entry());
724 18 : DeleteDefaultRoute(vrf);
725 :
726 18 : return FlowMgmtTree::OperEntryDelete(req, key);
727 : }
|