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 2799 : FlowMgmtEntry *FlowMgmtTree::Find(FlowMgmtKey *key) {
12 2799 : Tree::iterator it = tree_.find(key);
13 2799 : if (it == tree_.end())
14 893 : return NULL;
15 :
16 1906 : return it->second;
17 : }
18 :
19 1607 : FlowMgmtEntry *FlowMgmtTree::Locate(FlowMgmtKey *key) {
20 1607 : FlowMgmtEntry *entry = Find(key);
21 1607 : if (entry == NULL) {
22 829 : entry = Allocate(key);
23 829 : InsertEntry(key->Clone(), entry);
24 : }
25 :
26 1607 : return entry;
27 : }
28 :
29 829 : void FlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry) {
30 829 : tree_[key] = entry;
31 829 : }
32 :
33 96 : FlowMgmtKey *FlowMgmtTree::LowerBound(FlowMgmtKey *key) {
34 96 : Tree::iterator it = tree_.lower_bound(key);
35 96 : if (it == tree_.end())
36 91 : return NULL;
37 :
38 5 : return it->first;
39 : }
40 :
41 1080 : bool FlowMgmtTree::TryDelete(FlowMgmtKey *key, FlowMgmtEntry *entry) {
42 1080 : if (entry->CanDelete() == false)
43 251 : return false;
44 :
45 : // Send message only if we have seen DELETE message from FlowTable
46 829 : if (entry->oper_state() == FlowMgmtEntry::OPER_DEL_SEEN) {
47 827 : FreeNotify(key, entry->gen_id());
48 : }
49 :
50 829 : Tree::iterator it = tree_.find(key);
51 829 : assert(it != tree_.end());
52 829 : FlowMgmtKey *first = it->first;
53 829 : RemoveEntry(it);
54 829 : delete entry;
55 829 : delete first;
56 :
57 829 : return true;
58 : }
59 :
60 829 : void FlowMgmtTree::RemoveEntry(Tree::iterator it) {
61 829 : tree_.erase(it);
62 829 : }
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 830 : void FlowMgmtTree::FreeNotify(FlowMgmtKey *key, uint32_t gen_id) {
110 830 : assert(key->db_entry() != NULL);
111 830 : FlowEvent::Event event = key->FreeDBEntryEvent();
112 830 : if (event == FlowEvent::INVALID)
113 0 : return;
114 830 : mgr_->FreeDBEntryEvent(event, key, gen_id);
115 : }
116 :
117 : // An object is added/updated. Enqueue REVALUATE for flows dependent on it
118 1122 : bool FlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req, FlowMgmtKey *key) {
119 1122 : FlowMgmtEntry *entry = Locate(key);
120 1122 : entry->OperEntryAdd(mgr_, req, key);
121 1122 : 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 856 : bool FlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
135 : FlowMgmtKey *key) {
136 856 : FlowMgmtEntry *entry = Find(key);
137 856 : if (entry == NULL) {
138 3 : FreeNotify(key, req->gen_id());
139 3 : return true;
140 : }
141 :
142 853 : entry->OperEntryDelete(mgr_, req, key);
143 853 : return TryDelete(key, entry);
144 : }
145 :
146 14 : bool FlowMgmtTree::RetryDelete(FlowMgmtKey *key) {
147 14 : FlowMgmtEntry *entry = Find(key);
148 14 : if (entry == NULL) {
149 0 : return true;
150 : }
151 :
152 14 : 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 9 : void BgpAsAServiceFlowMgmtTree::DeleteAll() {
205 9 : Tree::iterator it = tree_.begin();
206 9 : 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 9 : }
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 16 : FlowMgmtEntry *VnFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
308 16 : return new VnFlowMgmtEntry();
309 : }
310 :
311 16 : void VnFlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry) {
312 16 : std::scoped_lock mutex(mutex_);
313 16 : FlowMgmtTree::InsertEntry(key, entry);
314 16 : }
315 :
316 16 : void VnFlowMgmtTree::RemoveEntry(Tree::iterator it) {
317 16 : std::scoped_lock mutex(mutex_);
318 16 : FlowMgmtTree::RemoveEntry(it);
319 16 : }
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 81 : void InterfaceFlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry){
337 81 : std::scoped_lock mutex(mutex_);
338 81 : FlowMgmtTree::InsertEntry(key, entry);
339 81 : }
340 :
341 81 : void InterfaceFlowMgmtTree::RemoveEntry(Tree::iterator it) {
342 81 : std::scoped_lock mutex(mutex_);
343 81 : FlowMgmtTree::RemoveEntry(it);
344 81 : }
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 81 : FlowMgmtEntry *InterfaceFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
371 81 : 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 423 : FlowMgmtEntry *NhFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
385 423 : 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 825 : void RouteFlowMgmtTree::SetDBEntry(const FlowMgmtRequest *req,
400 : FlowMgmtKey *key) {
401 825 : Tree::iterator it = tree_.find(key);
402 825 : if (it == tree_.end()) {
403 0 : return;
404 : }
405 :
406 825 : if (req->db_entry() == NULL) {
407 0 : return;
408 : }
409 :
410 825 : if (it->first->db_entry()) {
411 554 : assert(it->first->db_entry() == req->db_entry());
412 554 : return;
413 : }
414 271 : it->first->set_db_entry(req->db_entry());
415 271 : return;
416 : }
417 :
418 271 : 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 271 : SetDBEntry(req, key);
423 271 : bool ret = FlowMgmtTree::OperEntryDelete(req, key);
424 271 : RouteFlowMgmtKey *route_key = static_cast<RouteFlowMgmtKey *>(key);
425 271 : mgr_->RetryVrfDelete(route_key->vrf_id());
426 271 : return ret;
427 : }
428 :
429 554 : bool RouteFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
430 : FlowMgmtKey *key) {
431 554 : bool ret = FlowMgmtTree::OperEntryAdd(req, key);
432 554 : if (req->db_entry() == NULL)
433 0 : return ret;
434 :
435 : // Set the DBEntry in the flow-mgmt-entry
436 554 : SetDBEntry(req, key);
437 554 : 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 121 : FlowMgmtEntry *InetRouteFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
529 121 : return new InetRouteFlowMgmtEntry();
530 : }
531 :
532 64 : bool InetRouteFlowMgmtTree::HasVrfFlows(uint32_t vrf,
533 : Agent::RouteTableType type) {
534 64 : InetRouteFlowMgmtKey *next_key = NULL;
535 :
536 64 : if (type == Agent::INET4_UNICAST) {
537 32 : InetRouteFlowMgmtKey key(vrf, Ip4Address(0), 0);
538 32 : next_key = static_cast<InetRouteFlowMgmtKey *>(LowerBound(&key));
539 64 : } else if (type == Agent::INET6_UNICAST) {
540 32 : InetRouteFlowMgmtKey key(vrf, Ip6Address(), 0);
541 32 : next_key = static_cast<InetRouteFlowMgmtKey *>(LowerBound(&key));
542 32 : } else {
543 0 : return false;
544 : }
545 :
546 64 : if (next_key == NULL)
547 64 : return false;
548 :
549 0 : if (next_key->vrf_id() != vrf)
550 0 : return false;
551 :
552 0 : return true;
553 : }
554 :
555 243 : bool InetRouteFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
556 : FlowMgmtKey *key) {
557 243 : 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 243 : InetRouteFlowMgmtKey *rt_key = static_cast<InetRouteFlowMgmtKey *>(key);
564 243 : AddToLPMTree(rt_key);
565 243 : if (rt_key->plen_ > 0) {
566 229 : InetRouteFlowMgmtKey lpm_key(rt_key->vrf_id_, rt_key->ip_,
567 229 : rt_key->plen_ - 1);
568 229 : InetRouteFlowMgmtKey *covering_route = LPM(&lpm_key);
569 229 : if (covering_route != NULL) {
570 106 : ret = RecomputeCoveringRoute(covering_route, rt_key);
571 : }
572 229 : rt_key->plen_ += 1;
573 229 : }
574 :
575 243 : return ret;
576 : }
577 :
578 106 : bool InetRouteFlowMgmtTree::RecomputeCoveringRoute
579 : (InetRouteFlowMgmtKey *covering_route, InetRouteFlowMgmtKey *key) {
580 106 : InetRouteFlowMgmtEntry *entry = dynamic_cast<InetRouteFlowMgmtEntry *>
581 106 : (Find(covering_route));
582 106 : if (entry == NULL) {
583 0 : return true;
584 : }
585 :
586 106 : return entry->RecomputeCoveringRouteEntry(mgr_, covering_route, key);
587 : }
588 :
589 119 : bool InetRouteFlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
590 : FlowMgmtKey *key) {
591 119 : InetRouteFlowMgmtKey *rt_key = static_cast<InetRouteFlowMgmtKey *>(key);
592 119 : DelFromLPMTree(rt_key);
593 119 : 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 152 : FlowMgmtEntry *BridgeRouteFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
632 152 : return new BridgeRouteFlowMgmtEntry();
633 : }
634 :
635 32 : bool BridgeRouteFlowMgmtTree::HasVrfFlows(uint32_t vrf,
636 : Agent::RouteTableType type) {
637 32 : BridgeRouteFlowMgmtKey key(vrf, MacAddress::ZeroMac());
638 : BridgeRouteFlowMgmtKey *next_key = static_cast<BridgeRouteFlowMgmtKey *>
639 32 : (LowerBound(&key));
640 32 : if (next_key == NULL)
641 27 : return false;
642 :
643 5 : if (next_key->vrf_id() != vrf)
644 5 : return false;
645 :
646 0 : return true;
647 32 : }
648 :
649 : /////////////////////////////////////////////////////////////////////////////
650 : // Vrf Flow Management
651 : /////////////////////////////////////////////////////////////////////////////
652 0 : void VrfFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
653 0 : }
654 :
655 32 : FlowMgmtEntry *VrfFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
656 32 : const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
657 32 : return new VrfFlowMgmtEntry(this, vrf);
658 : }
659 :
660 32 : bool VrfFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
661 : FlowMgmtKey *key) {
662 32 : bool ret = FlowMgmtTree::OperEntryAdd(req, key);
663 :
664 32 : const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
665 32 : VrfIdMap::iterator it = id_map_.find(vrf->vrf_id());
666 32 : if (it != id_map_.end())
667 0 : return ret;
668 :
669 32 : id_map_.insert(make_pair(vrf->vrf_id(), vrf));
670 32 : return ret;
671 : }
672 :
673 35 : void VrfFlowMgmtTree::FreeNotify(FlowMgmtKey *key, uint32_t gen_id) {
674 35 : FlowMgmtTree::FreeNotify(key, gen_id);
675 :
676 35 : const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
677 35 : VrfIdMap::iterator it = id_map_.find(vrf->vrf_id());
678 35 : if (it != id_map_.end()) {
679 32 : id_map_.erase(it);
680 : }
681 35 : }
682 :
683 439 : void VrfFlowMgmtTree::RetryDelete(uint32_t vrf_id) {
684 439 : VrfIdMap::iterator it = id_map_.find(vrf_id);
685 439 : if (it == id_map_.end())
686 4 : return;
687 :
688 435 : VrfFlowMgmtKey key(it->second);
689 435 : const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(key.db_entry());
690 435 : if (vrf && vrf->AllRouteTablesEmpty()) {
691 14 : FlowMgmtTree::RetryDelete(&key);
692 : }
693 435 : }
694 :
695 61 : 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 61 : InetRouteFlowMgmtKey key(vrf->vrf_id(), Ip4Address(0), 0);
708 61 : FlowMgmtEntry *route_entry = mgr_->ip4_route_flow_mgmt_tree()->Find(&key);
709 61 : 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 61 : 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 61 : }
720 :
721 61 : bool VrfFlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
722 : FlowMgmtKey *key) {
723 61 : const VrfEntry* vrf = static_cast<const VrfEntry *>(req->db_entry());
724 61 : DeleteDefaultRoute(vrf);
725 :
726 61 : return FlowMgmtTree::OperEntryDelete(req, key);
727 : }
|