LCOV - code coverage report
Current view: top level - vnsw/agent/pkt/flow_mgmt - flow_mgmt_entry.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 123 228 53.9 %
Date: 2026-09-07 02:14:47 Functions: 20 27 74.1 %
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_entry.h>
       6             : #include <pkt/flow_event.h>
       7             : #include <pkt/flow_mgmt/flow_mgmt_request.h>
       8             : #include <pkt/flow_mgmt.h>
       9             : 
      10         497 : bool FlowMgmtEntry::Add(FlowEntry *flow, FlowMgmtKeyNode *node) {
      11         497 :     if (node) {
      12         231 :         flow_list_.push_back(*node);
      13         231 :         return true;
      14             :     }
      15         266 :     return false;
      16             : }
      17             : 
      18         231 : bool FlowMgmtEntry::Delete(FlowEntry *flow, FlowMgmtKeyNode *node) {
      19         462 :     flow_list_.erase(flow_list_.iterator_to(*node));
      20         231 :     return flow_list_.size();
      21             : }
      22             : 
      23             : // An entry *cannot* be deleted if
      24             : //    - It contains flows
      25             : //    - It has seen ADD but not seen any DELETE
      26         553 : bool FlowMgmtEntry::CanDelete() const {
      27         553 :     assert(oper_state_ != INVALID);
      28         553 :     if (flow_list_.size())
      29         194 :         return false;
      30             : 
      31         359 :     return (oper_state_ != OPER_ADD_SEEN);
      32             : }
      33             : 
      34             : // Handle Add/Change event for DBEntry
      35         459 : bool FlowMgmtEntry::OperEntryAdd(FlowMgmtManager *mgr,
      36             :                                  const FlowMgmtRequest *req, FlowMgmtKey *key) {
      37         459 :     oper_state_ = OPER_ADD_SEEN;
      38         459 :     FlowEvent::Event event = req->GetResponseEvent();
      39         459 :     if (event == FlowEvent::INVALID)
      40           9 :         return false;
      41             : 
      42         450 :     FlowList::iterator it = flow_list_.begin();
      43         990 :     while (it != flow_list_.end()) {
      44          45 :         FlowMgmtKeyNode *node = &(*it);
      45          45 :         mgr->DBEntryEvent(event, key, node->flow_entry());
      46          45 :         it++;
      47             :     }
      48             : 
      49         450 :     return true;
      50             : }
      51             : 
      52          10 : bool FlowMgmtEntry::OperEntryChange(FlowMgmtManager *mgr,
      53             :                                     const FlowMgmtRequest *req,
      54             :                                     FlowMgmtKey *key) {
      55          10 :     return OperEntryAdd(mgr, req, key);
      56             : }
      57             : 
      58             : // Handle Delete event for DBEntry
      59         317 : bool FlowMgmtEntry::OperEntryDelete(FlowMgmtManager *mgr,
      60             :                                     const FlowMgmtRequest *req,
      61             :                                     FlowMgmtKey *key) {
      62         317 :     if (req->event() != FlowMgmtRequest::IMPLICIT_ROUTE_DELETE) {
      63             :         //If the delete is implicit there is no DB entry
      64             :         //and hence no free notify should be sent, hence
      65             :         //dont update the state to DEL SEEN
      66         317 :         oper_state_ = OPER_DEL_SEEN;
      67         317 :         gen_id_ = req->gen_id();
      68             :     }
      69             : 
      70         317 :     FlowEvent::Event event = req->GetResponseEvent();
      71         317 :     if (event == FlowEvent::INVALID)
      72          16 :         return false;
      73             : 
      74         301 :     FlowList::iterator it = flow_list_.begin();
      75         806 :     while (it != flow_list_.end()) {
      76         102 :         FlowMgmtKeyNode *node = &(*it);
      77         102 :         mgr->DBEntryEvent(event, key, node->flow_entry());
      78         102 :         it++;
      79             :     }
      80             : 
      81         301 :     return true;
      82             : }
      83             : 
      84           0 : string AclFlowMgmtEntry::GetAclFlowSandeshDataKey(const AclDBEntry *acl,
      85             :                                                   const int last_count) const {
      86           0 :     string uuid_str = UuidToString(acl->GetUuid());
      87           0 :     std::stringstream ss;
      88           0 :     ss << uuid_str << ":";
      89           0 :     ss << last_count;
      90           0 :     return ss.str();
      91           0 : }
      92             : 
      93           0 : string AclFlowMgmtEntry::GetAceSandeshDataKey(const AclDBEntry *acl,
      94             :                                               const std::string &ace_id) {
      95           0 :     string uuid_str = UuidToString(acl->GetUuid());
      96           0 :     std::stringstream ss;
      97           0 :     ss << uuid_str << ":";
      98           0 :     ss << ace_id;
      99           0 :     return ss.str();
     100           0 : }
     101             : 
     102           0 : void AclFlowMgmtEntry::FillAceFlowSandeshInfo(const AclDBEntry *acl,
     103             :                                               AclFlowCountResp &data,
     104             :                                               const std::string& ace_id) {
     105           0 :     int count = 0;
     106           0 :     bool key_set = false;
     107           0 :     AceIdFlowCntMap::iterator aceid_it = aceid_cnt_map_.upper_bound(ace_id);
     108           0 :     std::vector<AceIdFlowCnt> id_cnt_l;
     109           0 :     while (aceid_it != aceid_cnt_map_.end()) {
     110           0 :         AceIdFlowCnt id_cnt_s;
     111           0 :         id_cnt_s.ace_id = aceid_it->first;
     112           0 :         id_cnt_s.flow_cnt = aceid_it->second;
     113           0 :         id_cnt_l.push_back(id_cnt_s);
     114           0 :         count++;
     115           0 :         ++aceid_it;
     116           0 :         if (count == MaxResponses && aceid_it != aceid_cnt_map_.end()) {
     117           0 :             data.set_iteration_key(GetAceSandeshDataKey(acl, id_cnt_s.ace_id));
     118           0 :             key_set = true;
     119           0 :             break;
     120             :         }
     121           0 :     }
     122           0 :     data.set_aceid_cnt_list(id_cnt_l);
     123             : 
     124           0 :     data.set_flow_count(Size());
     125           0 :     data.set_flow_miss(flow_miss_);
     126             : 
     127           0 :     if (!key_set) {
     128           0 :         data.set_iteration_key(GetAceSandeshDataKey(acl, Agent::NullString()));
     129             :     }
     130           0 : }
     131             : 
     132           0 : void AclFlowMgmtEntry::FillAclFlowSandeshInfo(const AclDBEntry *acl,
     133             :                                               AclFlowResp &data,
     134             :                                               const int last_count,
     135             :                                               Agent *agent) {
     136           0 :     int count = 0;
     137           0 :     bool key_set = false;
     138           0 :     FlowList::iterator fe_tree_it = flow_list_.begin();
     139           0 :     while (fe_tree_it != flow_list_.end() && (count + 1) < last_count) {
     140           0 :         fe_tree_it++;
     141           0 :         count++;
     142             :     }
     143           0 :     data.set_flow_count(Size());
     144           0 :     data.set_flow_miss(flow_miss_);
     145           0 :     std::vector<FlowSandeshData> flow_entries_l;
     146           0 :     while(fe_tree_it != flow_list_.end()) {
     147           0 :         FlowMgmtKeyNode *node = &(*fe_tree_it);
     148           0 :         const FlowEntry *fe = node->flow_entry();
     149           0 :         FlowSandeshData fe_sandesh_data;
     150           0 :         fe->SetAclFlowSandeshData(acl, fe_sandesh_data, agent);
     151             : 
     152           0 :         flow_entries_l.push_back(fe_sandesh_data);
     153           0 :         count++;
     154             :         ++fe_tree_it;
     155           0 :         if (count == (MaxResponses + last_count) &&
     156           0 :             fe_tree_it != flow_list_.end()) {
     157           0 :             data.set_iteration_key(GetAclFlowSandeshDataKey(acl, count));
     158           0 :             key_set = true;
     159           0 :             break;
     160             :         }
     161           0 :     }
     162           0 :     data.set_flow_entries(flow_entries_l);
     163           0 :     if (!key_set) {
     164           0 :         data.set_iteration_key(GetAclFlowSandeshDataKey(acl, 0));
     165             :     }
     166           0 : }
     167             : 
     168          27 : void AclFlowMgmtEntry::DecrementAceIdCountMap(const AclEntryIDList *id_list) {
     169          27 :     AclEntryIDList::const_iterator id_it;
     170          47 :     for (id_it = id_list->begin(); id_it != id_list->end(); ++id_it) {
     171          20 :         aceid_cnt_map_[id_it->id_] -= 1;
     172             :     }
     173          27 : }
     174             : 
     175          30 : bool AclFlowMgmtEntry::Add(const AclEntryIDList *id_list, FlowEntry *flow,
     176             :                            const AclEntryIDList *old_id_list,
     177             :                            FlowMgmtKeyNode *node) {
     178          30 :     if (old_id_list) {
     179          23 :         DecrementAceIdCountMap(old_id_list);
     180             :     }
     181          30 :     if (id_list->size()) {
     182          23 :         AclEntryIDList::const_iterator id_it;
     183          46 :         for (id_it = id_list->begin(); id_it != id_list->end(); ++id_it) {
     184          23 :             aceid_cnt_map_[id_it->id_] += 1;
     185             :         }
     186             :     } else {
     187           7 :         flow_miss_++;
     188             :     }
     189          30 :     return FlowMgmtEntry::Add(flow, node);
     190             : }
     191             : 
     192           7 : bool AclFlowMgmtEntry::Delete(const AclEntryIDList *id_list, FlowEntry *flow,
     193             :                               FlowMgmtKeyNode *node) {
     194           7 :     if (id_list->size()) {
     195           4 :         DecrementAceIdCountMap(id_list);
     196             :     }
     197           7 :     return FlowMgmtEntry::Delete(flow, node);
     198             : }
     199             : 
     200           0 : bool BgpAsAServiceFlowMgmtEntry::NonOperEntryDelete(FlowMgmtManager *mgr,
     201             :                                                     const FlowMgmtRequest *req,
     202             :                                                     FlowMgmtKey *key) {
     203           0 :     oper_state_ = OPER_DEL_SEEN;
     204           0 :     gen_id_ = req->gen_id();
     205           0 :     FlowEvent::Event event = req->GetResponseEvent();
     206           0 :     if (event == FlowEvent::INVALID)
     207           0 :         return false;
     208             : 
     209           0 :     FlowList::iterator it = flow_list_.begin();
     210           0 :     while (it != flow_list_.end()) {
     211           0 :         FlowMgmtKeyNode *node = &(*it);
     212           0 :         mgr->NonOperEntryEvent(event, node->flow_entry());
     213           0 :         it++;
     214             :     }
     215           0 :     return true;
     216             : }
     217             : 
     218             : // Update health check on all the BgpAsAService flows
     219           0 : bool BgpAsAServiceFlowMgmtEntry::HealthCheckUpdate(
     220             :         Agent *agent, FlowMgmtManager *mgr,
     221             :         BgpAsAServiceFlowMgmtKey &key,
     222             :         BgpAsAServiceFlowMgmtRequest *req) {
     223           0 :     for (FlowList::iterator it = flow_list_.begin();
     224           0 :          it != flow_list_.end(); ++it) {
     225           0 :         FlowMgmtKeyNode *node = &(*it);
     226             :         BgpAsAServiceFlowMgmtKey *bkey =
     227           0 :             mgr->FindBgpAsAServiceInfo(node->flow_entry(), key);
     228           0 :         if (bkey == NULL)
     229           0 :             continue;
     230             : 
     231           0 :         if (req->type() == BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_ADD)
     232           0 :             bkey->StartHealthCheck(agent, node->flow_entry(),
     233             :                                    req->health_check_uuid());
     234             :         else
     235           0 :             bkey->StopHealthCheck(node->flow_entry());
     236             :     }
     237           0 :     return true;
     238             : }
     239             : 
     240         104 : void VnFlowMgmtEntry::UpdateCounterOnAdd(FlowEntry *flow, bool add_flow,
     241             :                                          bool local_flow, bool old_ingress) {
     242         104 :     if (add_flow) {
     243          48 :         if (flow->is_flags_set(FlowEntry::LocalFlow)) {
     244          14 :             ingress_flow_count_++;
     245          14 :             egress_flow_count_++;
     246          34 :         } else if (flow->is_flags_set(FlowEntry::IngressDir)) {
     247          17 :             ingress_flow_count_++;
     248             :         } else {
     249          17 :             egress_flow_count_++;
     250             :         }
     251             : 
     252          48 :         return;
     253             :     }
     254             : 
     255          56 :     if (local_flow)
     256          26 :         return;
     257             : 
     258          30 :     bool new_ingress = flow->is_flags_set(FlowEntry::IngressDir);
     259          30 :     if (new_ingress != old_ingress) {
     260           0 :         if (new_ingress) {
     261           0 :             ingress_flow_count_++;
     262           0 :             egress_flow_count_--;
     263             :         } else {
     264           0 :             ingress_flow_count_--;
     265           0 :             egress_flow_count_++;
     266             :         }
     267             :     }
     268             : }
     269             : 
     270          48 : void VnFlowMgmtEntry::UpdateCounterOnDel(FlowEntry *flow, bool local_flow,
     271             :                                          bool old_ingress) {
     272          48 :     if (local_flow) {
     273          14 :         ingress_flow_count_--;
     274          14 :         egress_flow_count_--;
     275          14 :         return;
     276             :     }
     277             : 
     278          34 :     if (old_ingress) {
     279          17 :         ingress_flow_count_--;
     280             :     } else {
     281          17 :         egress_flow_count_--;
     282             :     }
     283             : }
     284             : 
     285         104 : bool InterfaceFlowMgmtEntry::Add(FlowEntry *flow, FlowMgmtKeyNode *node) {
     286         104 :     bool added = FlowMgmtEntry::Add(flow, node);
     287         104 :     if (added) {
     288          48 :         flow_created_++;
     289             :     }
     290         104 :     return added;
     291             : }
     292             : 
     293          48 : bool InterfaceFlowMgmtEntry::Delete(FlowEntry *flow, FlowMgmtKeyNode *node) {
     294          48 :     flow_aged_++;
     295          48 :     return FlowMgmtEntry::Delete(flow, node);
     296             : }
     297             : 
     298          55 : bool InetRouteFlowMgmtEntry::RecomputeCoveringRouteEntry
     299             : (FlowMgmtManager *mgr, InetRouteFlowMgmtKey *covering_route,
     300             :  InetRouteFlowMgmtKey *key){
     301          55 :     FlowList::iterator it = flow_list_.begin();
     302         110 :     while (it != flow_list_.end()) {
     303           0 :         FlowMgmtKeyNode *node = &(*it);
     304             :         // Queue the DB Event only route key  matches src or dst ip matches.
     305           0 :         if (key->NeedsReCompute(node->flow_entry())) {
     306           0 :             mgr->DBEntryEvent(FlowEvent::RECOMPUTE_FLOW, covering_route,
     307             :                               node->flow_entry());
     308             :         }
     309           0 :         it++;
     310             :     }
     311             : 
     312          55 :     return true;
     313             : }
     314             : 
     315           1 : bool InetRouteFlowMgmtEntry::HandleNhChange(FlowMgmtManager *mgr,
     316             :                                             const FlowMgmtRequest *req,
     317             :                                             FlowMgmtKey *key) {
     318           1 :     assert(req->event() == FlowMgmtRequest::DELETE_LAYER2_FLOW);
     319             : 
     320           1 :     FlowList::iterator it = flow_list_.begin();
     321           2 :     while (it != flow_list_.end()) {
     322             :         FlowEvent::Event event;
     323           0 :         FlowMgmtKeyNode *node = &(*it);
     324           0 :         it++;
     325           0 :         FlowEntry *fe = node->flow_entry();
     326           0 :         if (fe->l3_flow()) {
     327           0 :             event = FlowEvent::RECOMPUTE_FLOW;
     328             :         } else {
     329           0 :             event = FlowEvent::DELETE_FLOW;
     330             :         }
     331             : 
     332           0 :         mgr->DBEntryEvent(event, key, fe);
     333             :     }
     334             : 
     335           1 :     return true;
     336             : }
     337             : 
     338           9 : VrfFlowMgmtEntry::VrfFlowMgmtEntry(VrfFlowMgmtTree *vrf_tree,
     339           9 :                                    const VrfEntry *vrf) :
     340          18 :     vrf_(vrf), vrf_id_(vrf->vrf_id()),
     341           9 :     inet4_(this, vrf, vrf->GetRouteTable(Agent::INET4_UNICAST)),
     342           9 :     inet6_(this, vrf, vrf->GetRouteTable(Agent::INET6_UNICAST)),
     343           9 :     bridge_(this, vrf, vrf->GetRouteTable(Agent::BRIDGE)),
     344           9 :     vrf_tree_(vrf_tree) {
     345           9 : }
     346             : 
     347          21 : bool VrfFlowMgmtEntry::CanDelete() const {
     348          21 :     if (FlowMgmtEntry::CanDelete() == false)
     349           0 :         return false;
     350             : 
     351          30 :     if (inet4_.deleted() == false || inet6_.deleted() == false ||
     352           9 :         bridge_.deleted() == false) {
     353          12 :         return false;
     354             :     }
     355             : 
     356           9 :     return (vrf_tree_->mgr()->HasVrfFlows(vrf_id_) == false);
     357             : }
     358             : 
     359          27 : VrfFlowMgmtEntry::Data::Data(VrfFlowMgmtEntry *vrf_mgmt_entry,
     360          27 :                              const VrfEntry *vrf, AgentRouteTable *table) :
     361          27 :     deleted_(false), table_ref_(this, NULL),
     362          27 :     vrf_mgmt_entry_(vrf_mgmt_entry), vrf_(vrf) {
     363          27 :     if (vrf->IsDeleted() == false) {
     364          27 :         table_ref_.Reset(table->deleter());
     365             :     } else {
     366           0 :         deleted_ = true;
     367             :     }
     368          27 : }
     369             : 
     370          27 : VrfFlowMgmtEntry::Data::~Data() {
     371          27 :     table_ref_.Reset(NULL);
     372          27 : }
     373             : 
     374          27 : void VrfFlowMgmtEntry::Data::ManagedDelete() {
     375          27 :     deleted_ = true;
     376          27 :     vrf_mgmt_entry_->vrf_tree()->mgr()->RetryVrfDeleteEvent(vrf_);
     377          27 : }

Generated by: LCOV version 1.14