LCOV - code coverage report
Current view: top level - vnsw/agent/pkt/flow_mgmt - flow_mgmt_tree.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 317 409 77.5 %
Date: 2026-11-09 02:10:49 Functions: 52 61 85.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14