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: 118 228 51.8 %
Date: 2026-08-03 02:19:58 Functions: 19 27 70.4 %
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         485 : bool FlowMgmtEntry::Add(FlowEntry *flow, FlowMgmtKeyNode *node) {
      11         485 :     if (node) {
      12         213 :         flow_list_.push_back(*node);
      13         213 :         return true;
      14             :     }
      15         272 :     return false;
      16             : }
      17             : 
      18         213 : bool FlowMgmtEntry::Delete(FlowEntry *flow, FlowMgmtKeyNode *node) {
      19         426 :     flow_list_.erase(flow_list_.iterator_to(*node));
      20         213 :     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         578 : bool FlowMgmtEntry::CanDelete() const {
      27         578 :     assert(oper_state_ != INVALID);
      28         578 :     if (flow_list_.size())
      29         179 :         return false;
      30             : 
      31         399 :     return (oper_state_ != OPER_ADD_SEEN);
      32             : }
      33             : 
      34             : // Handle Add/Change event for DBEntry
      35         511 : bool FlowMgmtEntry::OperEntryAdd(FlowMgmtManager *mgr,
      36             :                                  const FlowMgmtRequest *req, FlowMgmtKey *key) {
      37         511 :     oper_state_ = OPER_ADD_SEEN;
      38         511 :     FlowEvent::Event event = req->GetResponseEvent();
      39         511 :     if (event == FlowEvent::INVALID)
      40          12 :         return false;
      41             : 
      42         499 :     FlowList::iterator it = flow_list_.begin();
      43        1096 :     while (it != flow_list_.end()) {
      44          49 :         FlowMgmtKeyNode *node = &(*it);
      45          49 :         mgr->DBEntryEvent(event, key, node->flow_entry());
      46          49 :         it++;
      47             :     }
      48             : 
      49         499 :     return true;
      50             : }
      51             : 
      52          11 : bool FlowMgmtEntry::OperEntryChange(FlowMgmtManager *mgr,
      53             :                                     const FlowMgmtRequest *req,
      54             :                                     FlowMgmtKey *key) {
      55          11 :     return OperEntryAdd(mgr, req, key);
      56             : }
      57             : 
      58             : // Handle Delete event for DBEntry
      59         350 : bool FlowMgmtEntry::OperEntryDelete(FlowMgmtManager *mgr,
      60             :                                     const FlowMgmtRequest *req,
      61             :                                     FlowMgmtKey *key) {
      62         350 :     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         350 :         oper_state_ = OPER_DEL_SEEN;
      67         350 :         gen_id_ = req->gen_id();
      68             :     }
      69             : 
      70         350 :     FlowEvent::Event event = req->GetResponseEvent();
      71         350 :     if (event == FlowEvent::INVALID)
      72          18 :         return false;
      73             : 
      74         332 :     FlowList::iterator it = flow_list_.begin();
      75         854 :     while (it != flow_list_.end()) {
      76          95 :         FlowMgmtKeyNode *node = &(*it);
      77          95 :         mgr->DBEntryEvent(event, key, node->flow_entry());
      78          95 :         it++;
      79             :     }
      80             : 
      81         332 :     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          29 : void AclFlowMgmtEntry::DecrementAceIdCountMap(const AclEntryIDList *id_list) {
     169          29 :     AclEntryIDList::const_iterator id_it;
     170          51 :     for (id_it = id_list->begin(); id_it != id_list->end(); ++id_it) {
     171          22 :         aceid_cnt_map_[id_it->id_] -= 1;
     172             :     }
     173          29 : }
     174             : 
     175          32 : bool AclFlowMgmtEntry::Add(const AclEntryIDList *id_list, FlowEntry *flow,
     176             :                            const AclEntryIDList *old_id_list,
     177             :                            FlowMgmtKeyNode *node) {
     178          32 :     if (old_id_list) {
     179          25 :         DecrementAceIdCountMap(old_id_list);
     180             :     }
     181          32 :     if (id_list->size()) {
     182          25 :         AclEntryIDList::const_iterator id_it;
     183          50 :         for (id_it = id_list->begin(); id_it != id_list->end(); ++id_it) {
     184          25 :             aceid_cnt_map_[id_it->id_] += 1;
     185             :         }
     186             :     } else {
     187           7 :         flow_miss_++;
     188             :     }
     189          32 :     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         100 : void VnFlowMgmtEntry::UpdateCounterOnAdd(FlowEntry *flow, bool add_flow,
     241             :                                          bool local_flow, bool old_ingress) {
     242         100 :     if (add_flow) {
     243          44 :         if (flow->is_flags_set(FlowEntry::LocalFlow)) {
     244          14 :             ingress_flow_count_++;
     245          14 :             egress_flow_count_++;
     246          30 :         } else if (flow->is_flags_set(FlowEntry::IngressDir)) {
     247          15 :             ingress_flow_count_++;
     248             :         } else {
     249          15 :             egress_flow_count_++;
     250             :         }
     251             : 
     252          44 :         return;
     253             :     }
     254             : 
     255          56 :     if (local_flow)
     256          28 :         return;
     257             : 
     258          28 :     bool new_ingress = flow->is_flags_set(FlowEntry::IngressDir);
     259          28 :     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          44 : void VnFlowMgmtEntry::UpdateCounterOnDel(FlowEntry *flow, bool local_flow,
     271             :                                          bool old_ingress) {
     272          44 :     if (local_flow) {
     273          14 :         ingress_flow_count_--;
     274          14 :         egress_flow_count_--;
     275          14 :         return;
     276             :     }
     277             : 
     278          30 :     if (old_ingress) {
     279          15 :         ingress_flow_count_--;
     280             :     } else {
     281          15 :         egress_flow_count_--;
     282             :     }
     283             : }
     284             : 
     285         100 : bool InterfaceFlowMgmtEntry::Add(FlowEntry *flow, FlowMgmtKeyNode *node) {
     286         100 :     bool added = FlowMgmtEntry::Add(flow, node);
     287         100 :     if (added) {
     288          44 :         flow_created_++;
     289             :     }
     290         100 :     return added;
     291             : }
     292             : 
     293          44 : bool InterfaceFlowMgmtEntry::Delete(FlowEntry *flow, FlowMgmtKeyNode *node) {
     294          44 :     flow_aged_++;
     295          44 :     return FlowMgmtEntry::Delete(flow, node);
     296             : }
     297             : 
     298          67 : bool InetRouteFlowMgmtEntry::RecomputeCoveringRouteEntry
     299             : (FlowMgmtManager *mgr, InetRouteFlowMgmtKey *covering_route,
     300             :  InetRouteFlowMgmtKey *key){
     301          67 :     FlowList::iterator it = flow_list_.begin();
     302         134 :     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          67 :     return true;
     313             : }
     314             : 
     315           0 : bool InetRouteFlowMgmtEntry::HandleNhChange(FlowMgmtManager *mgr,
     316             :                                             const FlowMgmtRequest *req,
     317             :                                             FlowMgmtKey *key) {
     318           0 :     assert(req->event() == FlowMgmtRequest::DELETE_LAYER2_FLOW);
     319             : 
     320           0 :     FlowList::iterator it = flow_list_.begin();
     321           0 :     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           0 :     return true;
     336             : }
     337             : 
     338          12 : VrfFlowMgmtEntry::VrfFlowMgmtEntry(VrfFlowMgmtTree *vrf_tree,
     339          12 :                                    const VrfEntry *vrf) :
     340          24 :     vrf_(vrf), vrf_id_(vrf->vrf_id()),
     341          12 :     inet4_(this, vrf, vrf->GetRouteTable(Agent::INET4_UNICAST)),
     342          12 :     inet6_(this, vrf, vrf->GetRouteTable(Agent::INET6_UNICAST)),
     343          12 :     bridge_(this, vrf, vrf->GetRouteTable(Agent::BRIDGE)),
     344          12 :     vrf_tree_(vrf_tree) {
     345          12 : }
     346             : 
     347          33 : bool VrfFlowMgmtEntry::CanDelete() const {
     348          33 :     if (FlowMgmtEntry::CanDelete() == false)
     349           0 :         return false;
     350             : 
     351          45 :     if (inet4_.deleted() == false || inet6_.deleted() == false ||
     352          12 :         bridge_.deleted() == false) {
     353          21 :         return false;
     354             :     }
     355             : 
     356          12 :     return (vrf_tree_->mgr()->HasVrfFlows(vrf_id_) == false);
     357             : }
     358             : 
     359          36 : VrfFlowMgmtEntry::Data::Data(VrfFlowMgmtEntry *vrf_mgmt_entry,
     360          36 :                              const VrfEntry *vrf, AgentRouteTable *table) :
     361          36 :     deleted_(false), table_ref_(this, NULL),
     362          36 :     vrf_mgmt_entry_(vrf_mgmt_entry), vrf_(vrf) {
     363          36 :     if (vrf->IsDeleted() == false) {
     364          36 :         table_ref_.Reset(table->deleter());
     365             :     } else {
     366           0 :         deleted_ = true;
     367             :     }
     368          36 : }
     369             : 
     370          36 : VrfFlowMgmtEntry::Data::~Data() {
     371          36 :     table_ref_.Reset(NULL);
     372          36 : }
     373             : 
     374          36 : void VrfFlowMgmtEntry::Data::ManagedDelete() {
     375          36 :     deleted_ = true;
     376          36 :     vrf_mgmt_entry_->vrf_tree()->mgr()->RetryVrfDeleteEvent(vrf_);
     377          36 : }

Generated by: LCOV version 1.14