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