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