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: 283 409 69.2 %
Date: 2026-09-28 02:13:17 Functions: 50 61 82.0 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.14