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: 305 409 74.6 %
Date: 2026-08-03 02:19:58 Functions: 51 61 83.6 %
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        1590 : FlowMgmtEntry *FlowMgmtTree::Find(FlowMgmtKey *key) {
      12        1590 :     Tree::iterator it = tree_.find(key);
      13        1590 :     if (it == tree_.end())
      14         364 :         return NULL;
      15             : 
      16        1226 :     return it->second;
      17             : }
      18             : 
      19         985 : FlowMgmtEntry *FlowMgmtTree::Locate(FlowMgmtKey *key) {
      20         985 :     FlowMgmtEntry *entry = Find(key);
      21         985 :     if (entry == NULL) {
      22         346 :         entry = Allocate(key);
      23         346 :         InsertEntry(key->Clone(), entry);
      24             :     }
      25             : 
      26         985 :     return entry;
      27             : }
      28             : 
      29         346 : void FlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry) {
      30         346 :     tree_[key] = entry;
      31         346 : }
      32             : 
      33          36 : FlowMgmtKey *FlowMgmtTree::LowerBound(FlowMgmtKey *key) {
      34          36 :     Tree::iterator it = tree_.lower_bound(key);
      35          36 :     if (it == tree_.end())
      36          36 :         return NULL;
      37             : 
      38           0 :     return it->first;
      39             : }
      40             : 
      41         578 : bool FlowMgmtTree::TryDelete(FlowMgmtKey *key, FlowMgmtEntry *entry) {
      42         578 :     if (entry->CanDelete() == false)
      43         232 :         return false;
      44             : 
      45             :     // Send message only if we have seen DELETE message from FlowTable
      46         346 :     if (entry->oper_state() == FlowMgmtEntry::OPER_DEL_SEEN) {
      47         344 :         FreeNotify(key, entry->gen_id());
      48             :     }
      49             : 
      50         346 :     Tree::iterator it = tree_.find(key);
      51         346 :     assert(it != tree_.end());
      52         346 :     FlowMgmtKey *first = it->first;
      53         346 :     RemoveEntry(it);
      54         346 :     delete entry;
      55         346 :     delete first;
      56             : 
      57         346 :     return true;
      58             : }
      59             : 
      60         346 : void FlowMgmtTree::RemoveEntry(Tree::iterator it) {
      61         346 :     tree_.erase(it);
      62         346 : }
      63             : 
      64             : /////////////////////////////////////////////////////////////////////////////
      65             : // Generic Event handler on tree for add/delete of a flow
      66             : /////////////////////////////////////////////////////////////////////////////
      67         648 : bool FlowMgmtTree::AddFlowMgmtKey(FlowMgmtKeyTree *tree, FlowMgmtKey *key) {
      68         648 :     FlowMgmtKeyNode *node = new FlowMgmtKeyNode();
      69         648 :     std::pair<FlowMgmtKeyTree::iterator, bool> ret;
      70         648 :     ret = tree->insert(make_pair(key, node));
      71         648 :     if (ret.second == false) {
      72         163 :         delete key;
      73         163 :         delete node;
      74             :     }
      75         648 :     return ret.second;
      76             : }
      77             : 
      78             : // Adds Flow to a FlowMgmtEntry defined by key. Does not allocate FlowMgmtEntry
      79             : // if its not already present
      80         453 : bool FlowMgmtTree::Add(FlowMgmtKey *key, FlowEntry *flow,
      81             :                        FlowMgmtKeyNode *node) {
      82         453 :     FlowMgmtEntry *entry = Locate(key);
      83         453 :     if (entry == NULL) {
      84           0 :         return false;
      85             :     }
      86             : 
      87         453 :     return entry->Add(flow, node);
      88             : }
      89             : 
      90         206 : bool FlowMgmtTree::Delete(FlowMgmtKey *key, FlowEntry *flow,
      91             :                           FlowMgmtKeyNode *node) {
      92         206 :     Tree::iterator it = tree_.find(key);
      93         206 :     if (it == tree_.end()) {
      94           0 :         return false;
      95             :     }
      96             : 
      97         206 :     FlowMgmtEntry *entry = it->second;
      98         206 :     bool ret = entry->Delete(flow, node);
      99             : 
     100         206 :     TryDelete(it->first, entry);
     101         206 :     return ret;
     102             : }
     103             : 
     104             : /////////////////////////////////////////////////////////////////////////////
     105             : // Event handler for add/delete/change of an object
     106             : /////////////////////////////////////////////////////////////////////////////
     107             : 
     108             : // Send DBEntry Free message to DB Client module
     109         344 : void FlowMgmtTree::FreeNotify(FlowMgmtKey *key, uint32_t gen_id) {
     110         344 :     assert(key->db_entry() != NULL);
     111         344 :     FlowEvent::Event event = key->FreeDBEntryEvent();
     112         344 :     if (event == FlowEvent::INVALID)
     113           0 :         return;
     114         344 :     mgr_->FreeDBEntryEvent(event, key, gen_id);
     115             : }
     116             : 
     117             : // An object is added/updated. Enqueue REVALUATE for flows dependent on it
     118         500 : bool FlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req, FlowMgmtKey *key) {
     119         500 :     FlowMgmtEntry *entry = Locate(key);
     120         500 :     entry->OperEntryAdd(mgr_, req, key);
     121         500 :     return true;
     122             : }
     123             : 
     124          11 : bool FlowMgmtTree::OperEntryChange(const FlowMgmtRequest *req,
     125             :                                    FlowMgmtKey *key) {
     126          11 :     FlowMgmtEntry *entry = Find(key);
     127          11 :     if (entry) {
     128          11 :         entry->OperEntryChange(mgr_, req, key);
     129             :     }
     130          11 :     return true;
     131             : }
     132             : 
     133             : // Send DELETE Entry message to FlowTable module
     134         350 : bool FlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
     135             :                                    FlowMgmtKey *key) {
     136         350 :     FlowMgmtEntry *entry = Find(key);
     137         350 :     if (entry == NULL) {
     138           0 :         FreeNotify(key, req->gen_id());
     139           0 :         return true;
     140             :     }
     141             : 
     142         350 :     entry->OperEntryDelete(mgr_, req, key);
     143         350 :     return TryDelete(key, entry);
     144             : }
     145             : 
     146          15 : bool FlowMgmtTree::RetryDelete(FlowMgmtKey *key) {
     147          15 :     FlowMgmtEntry *entry = Find(key);
     148          15 :     if (entry == NULL) {
     149           0 :         return true;
     150             :     }
     151             : 
     152          15 :     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           4 : void BgpAsAServiceFlowMgmtTree::DeleteAll() {
     205           4 :     Tree::iterator it = tree_.begin();
     206           4 :     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           4 : }
     213             : 
     214           0 : int BgpAsAServiceFlowMgmtTree::GetCNIndex(const FlowEntry *flow) {
     215           0 :     IpAddress dest_ip = IpAddress();
     216           0 :     if (flow->is_flags_set(FlowEntry::ReverseFlow)) {
     217           0 :         dest_ip = flow->key().src_addr;
     218             :     } else {
     219             :         //No reverse flow means no CN to map to so dont add flow key.
     220           0 :         if (flow->reverse_flow_entry() == NULL)
     221           0 :             return BgpAsAServiceFlowMgmtTree::kInvalidCnIndex;
     222           0 :         dest_ip = flow->reverse_flow_entry()->key().src_addr;
     223             :     }
     224           0 :     for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
     225           0 :         if (flow->flow_table()->agent()->controller_ifmap_xmpp_server(count) ==
     226           0 :             dest_ip.to_string()) {
     227           0 :             return count;
     228             :         }
     229             :     }
     230           0 :     return BgpAsAServiceFlowMgmtTree::kInvalidCnIndex;
     231             : }
     232             : 
     233             : /////////////////////////////////////////////////////////////////////////////
     234             : // Acl Flow Management
     235             : /////////////////////////////////////////////////////////////////////////////
     236        1300 : void AclFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree,
     237             :                                   const MatchAclParamsList *acl_list) {
     238        1300 :     std::list<MatchAclParams>::const_iterator it;
     239        1332 :     for (it = acl_list->begin(); it != acl_list->end(); it++) {
     240          32 :         AclFlowMgmtKey *key = new AclFlowMgmtKey(it->acl.get(),
     241          32 :                                                  &it->ace_id_list);
     242          32 :         AddFlowMgmtKey(tree, key);
     243             :     }
     244        1300 : }
     245             : 
     246         100 : void AclFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
     247         100 :     ExtractKeys(flow, tree, &flow->match_p().m_acl_l);
     248         100 :     ExtractKeys(flow, tree, &flow->match_p().m_out_acl_l);
     249         100 :     ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_acl_l);
     250         100 :     ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_out_acl_l);
     251         100 :     ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_reverse_acl_l);
     252         100 :     ExtractKeys(flow, tree, &flow->match_p().sg_policy.m_reverse_out_acl_l);
     253         100 :     ExtractKeys(flow, tree, &flow->match_p().m_mirror_acl_l);
     254         100 :     ExtractKeys(flow, tree, &flow->match_p().m_out_mirror_acl_l);
     255         100 :     ExtractKeys(flow, tree, &flow->match_p().m_vrf_assign_acl_l);
     256         100 :     ExtractKeys(flow, tree, &flow->match_p().aps_policy.m_acl_l);
     257         100 :     ExtractKeys(flow, tree, &flow->match_p().aps_policy.m_out_acl_l);
     258         100 :     ExtractKeys(flow, tree, &flow->match_p().fwaas_policy.m_acl_l);
     259         100 :     ExtractKeys(flow, tree, &flow->match_p().fwaas_policy.m_out_acl_l);
     260         100 : }
     261             : 
     262           4 : FlowMgmtEntry *AclFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
     263           4 :     return new AclFlowMgmtEntry();
     264             : }
     265             : 
     266          32 : bool AclFlowMgmtTree::Add(FlowMgmtKey *key, FlowEntry *flow,
     267             :                           FlowMgmtKey *old_key, FlowMgmtKeyNode *node) {
     268          32 :     AclFlowMgmtEntry *entry = static_cast<AclFlowMgmtEntry *>(Locate(key));
     269          32 :     if (entry == NULL) {
     270           0 :         return false;
     271             :     }
     272             : 
     273          32 :     AclFlowMgmtKey *acl_key = static_cast<AclFlowMgmtKey *>(key);
     274          32 :     const AclEntryIDList *old_ace_id_list = NULL;
     275          32 :     if (old_key) {
     276          25 :         AclFlowMgmtKey *old_acl_key = static_cast<AclFlowMgmtKey *>(old_key);
     277          25 :         old_ace_id_list = old_acl_key->ace_id_list();
     278             :     }
     279          32 :     return entry->Add(acl_key->ace_id_list(), flow, old_ace_id_list, node);
     280             : }
     281             : 
     282           7 : bool AclFlowMgmtTree::Delete(FlowMgmtKey *key, FlowEntry *flow,
     283             :                              FlowMgmtKeyNode *node) {
     284           7 :     Tree::iterator it = tree_.find(key);
     285           7 :     if (it == tree_.end()) {
     286           0 :         return false;
     287             :     }
     288             : 
     289           7 :     AclFlowMgmtKey *acl_key = static_cast<AclFlowMgmtKey *>(key);
     290           7 :     AclFlowMgmtEntry *entry = static_cast<AclFlowMgmtEntry *>(it->second);
     291           7 :     bool ret = entry->Delete(acl_key->ace_id_list(), flow, node);
     292             : 
     293           7 :     TryDelete(it->first, entry);
     294           7 :     return ret;
     295             : }
     296             : 
     297             : /////////////////////////////////////////////////////////////////////////////
     298             : // VN Flow Management
     299             : /////////////////////////////////////////////////////////////////////////////
     300         100 : void VnFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
     301         100 :     if (flow->vn_entry() == NULL)
     302           0 :         return;
     303         100 :     VnFlowMgmtKey *key = new VnFlowMgmtKey(flow->vn_entry());
     304         100 :     AddFlowMgmtKey(tree, key);
     305             : }
     306             : 
     307           6 : FlowMgmtEntry *VnFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
     308           6 :     return new VnFlowMgmtEntry();
     309             : }
     310             : 
     311           6 : void VnFlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry) {
     312           6 :     std::scoped_lock mutex(mutex_);
     313           6 :     FlowMgmtTree::InsertEntry(key, entry);
     314           6 : }
     315             : 
     316           6 : void VnFlowMgmtTree::RemoveEntry(Tree::iterator it) {
     317           6 :     std::scoped_lock mutex(mutex_);
     318           6 :     FlowMgmtTree::RemoveEntry(it);
     319           6 : }
     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          31 : void InterfaceFlowMgmtTree::InsertEntry(FlowMgmtKey *key, FlowMgmtEntry *entry){
     337          31 :     std::scoped_lock mutex(mutex_);
     338          31 :     FlowMgmtTree::InsertEntry(key, entry);
     339          31 : }
     340             : 
     341          31 : void InterfaceFlowMgmtTree::RemoveEntry(Tree::iterator it) {
     342          31 :     std::scoped_lock mutex(mutex_);
     343          31 :     FlowMgmtTree::RemoveEntry(it);
     344          31 : }
     345             : 
     346           0 : void InterfaceFlowMgmtTree::InterfaceFlowCount(const Interface *itf,
     347             :                                                uint64_t *created,
     348             :                                                uint64_t *aged,
     349             :                                                uint32_t *active_flows) {
     350           0 :     InterfaceFlowMgmtKey key(itf);
     351           0 :     std::scoped_lock mutex(mutex_);
     352             :     InterfaceFlowMgmtEntry *entry = static_cast<InterfaceFlowMgmtEntry *>
     353           0 :         (Find(&key));
     354           0 :     if (entry) {
     355           0 :         *created += entry->flow_created();
     356           0 :         *aged += entry->flow_aged();
     357           0 :         *active_flows += entry->Size();
     358             :     }
     359           0 : }
     360             : 
     361         100 : void InterfaceFlowMgmtTree::ExtractKeys(FlowEntry *flow,
     362             :                                         FlowMgmtKeyTree *tree) {
     363         100 :     if (flow->intf_entry() == NULL)
     364           0 :         return;
     365             :     InterfaceFlowMgmtKey *key =
     366         100 :         new InterfaceFlowMgmtKey(flow->intf_entry());
     367         100 :     AddFlowMgmtKey(tree, key);
     368             : }
     369             : 
     370          31 : FlowMgmtEntry *InterfaceFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
     371          31 :     return new InterfaceFlowMgmtEntry();
     372             : }
     373             : 
     374             : /////////////////////////////////////////////////////////////////////////////
     375             : // Nh Flow Management
     376             : /////////////////////////////////////////////////////////////////////////////
     377         100 : void NhFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
     378         100 :     if (flow->rpf_nh() == NULL)
     379          10 :         return;
     380          90 :     NhFlowMgmtKey *key = new NhFlowMgmtKey(flow->rpf_nh());
     381          90 :     AddFlowMgmtKey(tree, key);
     382             : }
     383             : 
     384         160 : FlowMgmtEntry *NhFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
     385         160 :     return new NhFlowMgmtEntry();
     386             : }
     387             : 
     388             : /////////////////////////////////////////////////////////////////////////////
     389             : // Route Flow Management
     390             : /////////////////////////////////////////////////////////////////////////////
     391          72 : bool RouteFlowMgmtTree::Delete(FlowMgmtKey *key, FlowEntry *flow,
     392             :                                FlowMgmtKeyNode *node) {
     393          72 :     bool ret = FlowMgmtTree::Delete(key, flow, node);
     394          72 :     RouteFlowMgmtKey *route_key = static_cast<RouteFlowMgmtKey *>(key);
     395          72 :     mgr_->RetryVrfDelete(route_key->vrf_id());
     396          72 :     return ret;
     397             : }
     398             : 
     399         406 : void RouteFlowMgmtTree::SetDBEntry(const FlowMgmtRequest *req,
     400             :                                    FlowMgmtKey *key) {
     401         406 :     Tree::iterator it = tree_.find(key);
     402         406 :     if (it == tree_.end()) {
     403           0 :         return;
     404             :     }
     405             : 
     406         406 :     if (req->db_entry() == NULL) {
     407           0 :         return;
     408             :     }
     409             : 
     410         406 :     if (it->first->db_entry()) {
     411         275 :         assert(it->first->db_entry() == req->db_entry());
     412         275 :         return;
     413             :     }
     414         131 :     it->first->set_db_entry(req->db_entry());
     415         131 :     return;
     416             : }
     417             : 
     418         131 : 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         131 :     SetDBEntry(req, key);
     423         131 :     bool ret = FlowMgmtTree::OperEntryDelete(req, key);
     424         131 :     RouteFlowMgmtKey *route_key = static_cast<RouteFlowMgmtKey *>(key);
     425         131 :     mgr_->RetryVrfDelete(route_key->vrf_id());
     426         131 :     return ret;
     427             : }
     428             : 
     429         275 : bool RouteFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
     430             :                                      FlowMgmtKey *key) {
     431         275 :     bool ret = FlowMgmtTree::OperEntryAdd(req, key);
     432         275 :     if (req->db_entry() == NULL)
     433           0 :         return ret;
     434             : 
     435             :     // Set the DBEntry in the flow-mgmt-entry
     436         275 :     SetDBEntry(req, key);
     437         275 :     return ret;
     438             : }
     439             : 
     440             : /////////////////////////////////////////////////////////////////////////////
     441             : // Inet Route Flow Management
     442             : /////////////////////////////////////////////////////////////////////////////
     443         220 : void InetRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree,
     444             :                                         uint32_t vrf, const IpAddress &ip,
     445             :                                         uint8_t plen) {
     446             :     // We do not support renewal of VRF, so skip flow if VRF is deleted
     447         220 :     VrfEntry *vrfp = mgr_->agent()->vrf_table()->FindVrfFromId(vrf);
     448         220 :     if (vrfp == NULL) {
     449           0 :         return;
     450             :     }
     451             : 
     452         220 :     InetRouteFlowMgmtKey *key = NULL;
     453             :     /*
     454             :      * For L2 flows, plen is found using LPMFind
     455             :      * when route is not found plen is set to -1(255)
     456             :      * in that case key should not be added
     457             :      */ 
     458         220 :     if (flow->l3_flow() || (plen != 255)) {
     459         202 :         if (ip.is_v4()) {
     460         202 :             Ip4Address ip4 = Address::GetIp4SubnetAddress(ip.to_v4(), plen);
     461         202 :             key = new InetRouteFlowMgmtKey(vrf, ip4, plen);
     462             :         } else {
     463           0 :             Ip6Address ip6 = Address::GetIp6SubnetAddress(ip.to_v6(), plen);
     464           0 :             key = new InetRouteFlowMgmtKey(vrf, ip6, plen);
     465             :         }
     466             :     }
     467             : 
     468         220 :     if (key) {
     469         202 :         AddFlowMgmtKey(tree, key);
     470             :     }
     471             : }
     472             : 
     473          88 : void InetRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree,
     474             :                                         const IpAddress &ip,
     475             :                                         const FlowRouteRefMap *rt_list) {
     476          88 :     FlowRouteRefMap::const_iterator it;
     477          96 :     for (it = rt_list->begin(); it != rt_list->end(); it++) {
     478           8 :         ExtractKeys(flow, tree, it->first, ip, it->second);
     479             :     }
     480          88 : }
     481             : 
     482         200 : void InetRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow,
     483             :                                         FlowMgmtKeyTree *tree) {
     484             : 
     485         200 :     if (flow->l3_flow() == false) {
     486             :         // For l2-flows Track INET route for RPF only
     487         156 :         if (flow->data().rpf_vrf != VrfEntry::kInvalidIndex) {
     488         140 :             ExtractKeys(flow, tree, flow->data().rpf_vrf,
     489         140 :                         flow->key().src_addr, flow->data().rpf_plen);
     490             :         }
     491         156 :         return;
     492             :     }
     493             : 
     494          44 :     if (flow->data().flow_source_vrf != VrfEntry::kInvalidIndex) {
     495          36 :         ExtractKeys(flow, tree, flow->data().flow_source_vrf,
     496          36 :                     flow->key().src_addr, flow->data().source_plen);
     497             :     }
     498             : 
     499          44 :     if (flow->data().acl_assigned_vrf_index_ != VrfEntry::kInvalidIndex) {
     500           0 :         ExtractKeys(flow, tree, flow->data().acl_assigned_vrf_index_,
     501           0 :                     flow->key().src_addr, flow->data().source_plen);
     502           0 :         ExtractKeys(flow, tree, flow->data().acl_assigned_vrf_index_,
     503           0 :                     flow->key().dst_addr, flow->data().dest_plen);
     504             :     }
     505             : 
     506          44 :     ExtractKeys(flow, tree, flow->key().src_addr,
     507          44 :                 &flow->data().flow_source_plen_map);
     508             : 
     509          44 :     if (flow->data().flow_dest_vrf != VrfEntry::kInvalidIndex) {
     510          36 :         ExtractKeys(flow, tree, flow->data().flow_dest_vrf,
     511          36 :                     flow->key().dst_addr, flow->data().dest_plen);
     512             :     }
     513          44 :     ExtractKeys(flow, tree, flow->key().dst_addr,
     514          44 :                 &flow->data().flow_dest_plen_map);
     515             : 
     516          44 :     if (flow->data().src_policy_vrf != VrfEntry::kInvalidIndex) {
     517           0 :         ExtractKeys(flow, tree, flow->data().src_policy_vrf,
     518           0 :                     flow->key().src_addr, flow->data().src_policy_plen);
     519             :     }
     520             : 
     521          44 :     if (flow->data().dst_policy_vrf != VrfEntry::kInvalidIndex) {
     522           0 :         ExtractKeys(flow, tree, flow->data().dst_policy_vrf,
     523           0 :                     flow->key().dst_addr, flow->data().dst_policy_plen);
     524             :     }
     525             : 
     526             : }
     527             : 
     528          81 : FlowMgmtEntry *InetRouteFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
     529          81 :     return new InetRouteFlowMgmtEntry();
     530             : }
     531             : 
     532          24 : bool InetRouteFlowMgmtTree::HasVrfFlows(uint32_t vrf,
     533             :                                         Agent::RouteTableType type) {
     534          24 :     InetRouteFlowMgmtKey *next_key = NULL;
     535             : 
     536          24 :     if (type == Agent::INET4_UNICAST) {
     537          12 :         InetRouteFlowMgmtKey key(vrf, Ip4Address(0), 0);
     538          12 :         next_key = static_cast<InetRouteFlowMgmtKey *>(LowerBound(&key));
     539          24 :     } else if (type == Agent::INET6_UNICAST) {
     540          12 :         InetRouteFlowMgmtKey key(vrf, Ip6Address(), 0);
     541          12 :         next_key = static_cast<InetRouteFlowMgmtKey *>(LowerBound(&key));
     542          12 :     } else {
     543           0 :         return false;
     544             :     }
     545             : 
     546          24 :     if (next_key == NULL)
     547          24 :         return false;
     548             : 
     549           0 :     if (next_key->vrf_id() != vrf)
     550           0 :         return false;
     551             : 
     552           0 :     return true;
     553             : }
     554             : 
     555         164 : bool InetRouteFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
     556             :                                          FlowMgmtKey *key) {
     557         164 :     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         164 :     InetRouteFlowMgmtKey *rt_key = static_cast<InetRouteFlowMgmtKey *>(key);
     564         164 :     AddToLPMTree(rt_key);
     565         164 :     if (rt_key->plen_ > 0) {
     566         150 :         InetRouteFlowMgmtKey lpm_key(rt_key->vrf_id_, rt_key->ip_,
     567         150 :                                      rt_key->plen_ - 1);
     568         150 :         InetRouteFlowMgmtKey *covering_route = LPM(&lpm_key);
     569         150 :         if (covering_route != NULL) {
     570          67 :             ret = RecomputeCoveringRoute(covering_route, rt_key);
     571             :         }
     572         150 :         rt_key->plen_ += 1;
     573         150 :     }
     574             : 
     575         164 :     return ret;
     576             : }
     577             : 
     578          67 : bool InetRouteFlowMgmtTree::RecomputeCoveringRoute
     579             : (InetRouteFlowMgmtKey *covering_route, InetRouteFlowMgmtKey *key) {
     580          67 :     InetRouteFlowMgmtEntry *entry = dynamic_cast<InetRouteFlowMgmtEntry *>
     581          67 :                                     (Find(covering_route));
     582          67 :     if (entry == NULL) {
     583           0 :         return true;
     584             :     }
     585             : 
     586          67 :     return entry->RecomputeCoveringRouteEntry(mgr_, covering_route, key);
     587             : }
     588             : 
     589          79 : bool InetRouteFlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
     590             :                                             FlowMgmtKey *key) {
     591          79 :     InetRouteFlowMgmtKey *rt_key = static_cast<InetRouteFlowMgmtKey *>(key);
     592          79 :     DelFromLPMTree(rt_key);
     593          79 :     return RouteFlowMgmtTree::OperEntryDelete(req, key);
     594             : }
     595             : 
     596           0 : bool InetRouteFlowMgmtTree::RouteNHChangeEvent(const FlowMgmtRequest *req,
     597             :                                                FlowMgmtKey *key) {
     598             :     InetRouteFlowMgmtEntry *entry = static_cast<InetRouteFlowMgmtEntry*>
     599           0 :         (Find(key));
     600           0 :     if (entry == NULL) {
     601           0 :         return true;
     602             :     }
     603             : 
     604           0 :     return entry->HandleNhChange(mgr_, req, key);
     605             : }
     606             : 
     607             : /////////////////////////////////////////////////////////////////////////////
     608             : // Bridge Route Flow Management
     609             : /////////////////////////////////////////////////////////////////////////////
     610         100 : void BridgeRouteFlowMgmtTree::ExtractKeys(FlowEntry *flow,
     611             :                                           FlowMgmtKeyTree *tree) {
     612         100 :     if (flow->l3_flow() == true)
     613          22 :         return;
     614             : 
     615          78 :     VrfTable *table = mgr_->agent()->vrf_table();
     616          78 :     uint32_t vrf = flow->data().flow_source_vrf;
     617          78 :     if (vrf != VrfEntry::kInvalidIndex && table->FindVrfFromId(vrf) != NULL) {
     618             :         BridgeRouteFlowMgmtKey *key =
     619          62 :             new BridgeRouteFlowMgmtKey(vrf, flow->data().smac);
     620          62 :         AddFlowMgmtKey(tree, key);
     621             :     }
     622             : 
     623          78 :     vrf = flow->data().flow_dest_vrf;
     624          78 :     if (vrf != VrfEntry::kInvalidIndex && table->FindVrfFromId(vrf) != NULL) {
     625             :         BridgeRouteFlowMgmtKey *key =
     626          62 :             new BridgeRouteFlowMgmtKey(vrf, flow->data().smac);
     627          62 :         AddFlowMgmtKey(tree, key);
     628             :     }
     629             : }
     630             : 
     631          52 : FlowMgmtEntry *BridgeRouteFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
     632          52 :     return new BridgeRouteFlowMgmtEntry();
     633             : }
     634             : 
     635          12 : bool BridgeRouteFlowMgmtTree::HasVrfFlows(uint32_t vrf,
     636             :                                           Agent::RouteTableType type) {
     637          12 :     BridgeRouteFlowMgmtKey key(vrf, MacAddress::ZeroMac());
     638             :     BridgeRouteFlowMgmtKey *next_key = static_cast<BridgeRouteFlowMgmtKey *>
     639          12 :         (LowerBound(&key));
     640          12 :     if (next_key == NULL)
     641          12 :         return false;
     642             : 
     643           0 :     if (next_key->vrf_id() != vrf)
     644           0 :         return false;
     645             : 
     646           0 :     return true;
     647          12 : }
     648             : 
     649             : /////////////////////////////////////////////////////////////////////////////
     650             : // Vrf Flow Management
     651             : /////////////////////////////////////////////////////////////////////////////
     652           0 : void VrfFlowMgmtTree::ExtractKeys(FlowEntry *flow, FlowMgmtKeyTree *tree) {
     653           0 : }
     654             : 
     655          12 : FlowMgmtEntry *VrfFlowMgmtTree::Allocate(const FlowMgmtKey *key) {
     656          12 :     const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
     657          12 :     return new VrfFlowMgmtEntry(this, vrf);
     658             : }
     659             : 
     660          12 : bool VrfFlowMgmtTree::OperEntryAdd(const FlowMgmtRequest *req,
     661             :                                    FlowMgmtKey *key) {
     662          12 :     bool ret = FlowMgmtTree::OperEntryAdd(req, key);
     663             : 
     664          12 :     const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
     665          12 :     VrfIdMap::iterator it = id_map_.find(vrf->vrf_id());
     666          12 :     if (it != id_map_.end())
     667           0 :         return ret;
     668             : 
     669          12 :     id_map_.insert(make_pair(vrf->vrf_id(), vrf));
     670          12 :     return ret;
     671             : }
     672             : 
     673          12 : void VrfFlowMgmtTree::FreeNotify(FlowMgmtKey *key, uint32_t gen_id) {
     674          12 :     FlowMgmtTree::FreeNotify(key, gen_id);
     675             : 
     676          12 :     const VrfEntry *vrf = static_cast<const VrfEntry *>(key->db_entry());
     677          12 :     VrfIdMap::iterator it = id_map_.find(vrf->vrf_id());
     678          12 :     if (it != id_map_.end()) {
     679          12 :         id_map_.erase(it);
     680             :     }
     681          12 : }
     682             : 
     683         239 : void VrfFlowMgmtTree::RetryDelete(uint32_t vrf_id) {
     684         239 :     VrfIdMap::iterator it = id_map_.find(vrf_id);
     685         239 :     if (it == id_map_.end())
     686           3 :         return;
     687             : 
     688         236 :     VrfFlowMgmtKey key(it->second);
     689         236 :     const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(key.db_entry());
     690         236 :     if (vrf && vrf->AllRouteTablesEmpty()) {
     691          15 :         FlowMgmtTree::RetryDelete(&key);
     692             :     }
     693         236 : }
     694             : 
     695          18 : 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          18 :     InetRouteFlowMgmtKey key(vrf->vrf_id(), Ip4Address(0), 0);
     708          18 :     FlowMgmtEntry *route_entry = mgr_->ip4_route_flow_mgmt_tree()->Find(&key);
     709          18 :     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          18 :         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          18 : }
     720             : 
     721          18 : bool VrfFlowMgmtTree::OperEntryDelete(const FlowMgmtRequest *req,
     722             :                                       FlowMgmtKey *key) {
     723          18 :     const VrfEntry* vrf = static_cast<const VrfEntry *>(req->db_entry());
     724          18 :     DeleteDefaultRoute(vrf);
     725             : 
     726          18 :     return FlowMgmtTree::OperEntryDelete(req, key);
     727             : }

Generated by: LCOV version 1.14