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

Generated by: LCOV version 1.14