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

Generated by: LCOV version 1.14