LCOV - code coverage report
Current view: top level - vnsw/agent/vrouter/flow_stats - flow_stats_manager.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 121 297 40.7 %
Date: 2026-11-09 02:10:49 Functions: 14 33 42.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <boost/uuid/uuid_io.hpp>
       7             : 
       8             : #include <db/db.h>
       9             : #include <base/util.h>
      10             : 
      11             : #include <cmn/agent_cmn.h>
      12             : #include <boost/functional/factory.hpp>
      13             : #include <cmn/agent_factory.h>
      14             : #include <oper/interface_common.h>
      15             : #include <oper/mirror_table.h>
      16             : 
      17             : #include <ksync/ksync_index.h>
      18             : #include <ksync/ksync_entry.h>
      19             : #include <ksync/ksync_object.h>
      20             : #include <ksync/ksync_netlink.h>
      21             : #include <ksync/ksync_sock.h>
      22             : #include <uve/agent_uve.h>
      23             : #include <vrouter/flow_stats/flow_stats_collector.h>
      24             : #include <vrouter/flow_stats/session_stats_collector.h>
      25             : #include <uve/vn_uve_table.h>
      26             : #include <uve/vm_uve_table.h>
      27             : #include <uve/interface_uve_stats_table.h>
      28             : #include <algorithm>
      29             : #include <pkt/flow_proto.h>
      30             : #include <vrouter/ksync/ksync_init.h>
      31             : #include <vrouter/flow_stats/flow_stats_types.h>
      32             : #include <oper/global_vrouter.h>
      33             : #include <init/agent_param.h>
      34             : 
      35             : SandeshTraceBufferPtr FlowExportStatsTraceBuf(SandeshTraceBufferCreate(
      36             :     "FlowExportStats", 3000));
      37             : const uint8_t FlowStatsManager::kCatchAllProto;
      38             : 
      39           0 : void FlowStatsManager::UpdateThreshold(uint64_t new_value, bool check_oflow) {
      40           0 :     if (check_oflow && new_value < threshold_) {
      41             :         /* Retain the same value for threshold if it results in overflow */
      42           0 :         return;
      43             :     }
      44           0 :     if (new_value < kMinFlowSamplingThreshold) {
      45           0 :         threshold_ = kMinFlowSamplingThreshold;
      46             :     } else {
      47           0 :         threshold_ = new_value;
      48             :     }
      49             : }
      50             : 
      51           0 : void SetFlowStatsInterval_InSeconds::HandleRequest() const {
      52             :     SandeshResponse *resp;
      53           0 :     if (get_interval() > 0) {
      54           0 :         FlowStatsManager *fam = Agent::GetInstance()->flow_stats_manager();
      55           0 :         FlowStatsCollectorObject *obj = fam->default_flow_stats_collector_obj();
      56           0 :         if (obj) {
      57           0 :             obj->SetExpiryTime(get_interval() * 1000);
      58             :         }
      59           0 :         resp = new FlowStatsCfgResp();
      60             :     } else {
      61           0 :         resp = new FlowStatsCfgErrResp();
      62             :     }
      63             : 
      64           0 :     resp->set_context(context());
      65           0 :     resp->Response();
      66           0 :     return;
      67             : }
      68             : 
      69           0 : void GetFlowStatsInterval::HandleRequest() const {
      70             :     FlowStatsIntervalResp_InSeconds *resp =
      71           0 :         new FlowStatsIntervalResp_InSeconds();
      72           0 :     resp->set_flow_stats_interval((Agent::GetInstance()->flow_stats_manager()->
      73           0 :                 default_flow_stats_collector_obj()->GetExpiryTime())/1000);
      74             : 
      75           0 :     resp->set_context(context());
      76           0 :     resp->Response();
      77           0 :     return;
      78             : }
      79             : 
      80           2 : FlowStatsManager::FlowStatsManager(Agent *agent) : agent_(agent),
      81           2 :     request_queue_(agent_->task_scheduler()->GetTaskId("Agent::FlowStatsManager"),
      82             :                    StatsCollector::FlowStatsCollector,
      83             :                    boost::bind(&FlowStatsManager::RequestHandler, this, _1)),
      84           2 :     prev_flow_export_rate_compute_time_(0),
      85           2 :     threshold_(kDefaultFlowSamplingThreshold),
      86           2 :     prev_cfg_flow_export_rate_(0), session_export_rate_(0),
      87           2 :     session_export_count_(), session_sample_exports_(), session_msg_exports_(),
      88           2 :     session_exports_(), session_export_disable_drops_(),
      89           2 :     session_export_sampling_drops_(), session_export_without_sampling_(),
      90           2 :     session_export_drops_(), session_global_slo_logging_drops_(),
      91           2 :     session_slo_logging_drops_(),
      92           2 :     timer_(TimerManager::CreateTimer(*(agent_->event_manager())->io_service(),
      93             :            "FlowThresholdTimer",
      94             :            TaskScheduler::GetInstance()->GetTaskId("Agent::FlowStatsManager"), 0)),
      95           4 :     delete_short_flow_(true) {
      96           2 :     session_export_count_ = 0;
      97           2 :     session_sample_exports_ = 0;
      98           2 :     session_msg_exports_ = 0;
      99           2 :     session_exports_ = 0;
     100           2 :     session_export_disable_drops_ = 0;
     101           2 :     session_export_sampling_drops_ = 0;
     102           2 :     session_export_without_sampling_ = 0;
     103           2 :     session_export_drops_ = 0;
     104           2 :     sessions_sampled_atleast_once_ = false;
     105           2 :     session_global_slo_logging_drops_ = 0;
     106           2 :     session_slo_logging_drops_ = 0;
     107           2 :     request_queue_.set_measure_busy_time(agent->MeasureQueueDelay());
     108         514 :     for (uint16_t i = 0; i < sizeof(protocol_list_)/sizeof(protocol_list_[0]);
     109             :          i++) {
     110         512 :         protocol_list_[i] = NULL;
     111             :     }
     112             :     SessionStatsCollectorPtr session_obj(new SessionStatsCollectorObject(agent,
     113           2 :                                                                         this));
     114           2 :     session_stats_collector_obj_ = session_obj;
     115           2 : }
     116             : 
     117           2 : FlowStatsManager::~FlowStatsManager() {
     118           2 :     assert(flow_aging_table_map_.size() == 0);
     119           2 : }
     120             : 
     121           4 : bool FlowStatsManager::RequestHandler(boost::shared_ptr<FlowStatsCollectorReq>
     122             :                                       req) {
     123           4 :     switch (req->event) {
     124           4 :     case FlowStatsCollectorReq::ADD_FLOW_STATS_COLLECTOR: {
     125           4 :         AddReqHandler(req);
     126           4 :         break;
     127             :     }
     128             : 
     129           0 :     case FlowStatsCollectorReq::DELETE_FLOW_STATS_COLLECTOR: {
     130           0 :         DeleteReqHandler(req);
     131           0 :         break;
     132             :     }
     133             : 
     134           0 :     case FlowStatsCollectorReq::FREE_FLOW_STATS_COLLECTOR: {
     135           0 :         FreeReqHandler(req);
     136           0 :         break;
     137             :     }
     138             : 
     139           0 :     default: {
     140           0 :         assert(0);
     141             :         break;
     142             :     }
     143             :     }
     144           4 :     return true;
     145             : }
     146             : 
     147           4 : void FlowStatsManager::AddReqHandler(boost::shared_ptr<FlowStatsCollectorReq>
     148             :                                      req) {
     149           4 :     FlowAgingTableMap::iterator it = flow_aging_table_map_.find(req->key);
     150           4 :     if (it != flow_aging_table_map_.end()) {
     151           2 :         it->second->SetFlowAgeTime(
     152           2 :                 1000000L * (uint64_t)req->flow_cache_timeout);
     153           2 :         it->second->ClearDelete();
     154           2 :         return;
     155             :     }
     156             : 
     157           2 :     FlowAgingTablePtr aging_table(new FlowStatsCollectorObject(agent(),
     158           2 :                                                                req.get(),
     159           2 :                                                                this));
     160           2 :     flow_aging_table_map_.insert(FlowAgingTableEntry(req->key, aging_table));
     161           2 :     if (req->key.proto == kCatchAllProto && req->key.port == 0) {
     162           2 :         default_flow_stats_collector_obj_ = aging_table;
     163             :     }
     164             : 
     165           2 :     if (req->key.port == 0) {
     166           2 :         protocol_list_[req->key.proto] = aging_table.get();
     167             :     }
     168           2 : }
     169             : 
     170           0 : void FlowStatsManager::DeleteReqHandler(boost::shared_ptr<FlowStatsCollectorReq>
     171             :                                        req) {
     172           0 :     FlowAgingTableMap::iterator it = flow_aging_table_map_.find(req->key);
     173           0 :     if (it == flow_aging_table_map_.end()) {
     174           0 :         return;
     175             :     }
     176             : 
     177           0 :     FlowAgingTablePtr flow_aging_table_ptr = it->second;
     178           0 :     flow_aging_table_ptr->MarkDelete();
     179             : 
     180           0 :     if (flow_aging_table_ptr->CanDelete()) {
     181           0 :         flow_aging_table_map_.erase(it);
     182           0 :         protocol_list_[req->key.proto] = NULL;
     183             :     }
     184           0 : }
     185             : 
     186           0 : void FlowStatsManager::FreeReqHandler(boost::shared_ptr<FlowStatsCollectorReq>
     187             :                                      req) {
     188           0 :     FlowAgingTableMap::iterator it = flow_aging_table_map_.find(req->key);
     189           0 :     if (it == flow_aging_table_map_.end()) {
     190           0 :         return;
     191             :     }
     192             : 
     193           0 :     FlowAgingTablePtr flow_aging_table_ptr = it->second;
     194           0 :     if (flow_aging_table_ptr->IsDeleted() == false) {
     195           0 :         return;
     196             :     }
     197           0 :     assert(flow_aging_table_ptr->CanDelete());
     198           0 :     flow_aging_table_ptr->Shutdown();
     199           0 :     flow_aging_table_map_.erase(it);
     200           0 :     protocol_list_[req->key.proto] = NULL;
     201           0 : }
     202             : 
     203           4 : void FlowStatsManager::Add(const FlowAgingTableKey &key,
     204             :                           uint64_t flow_stats_interval,
     205             :                           uint64_t flow_cache_timeout) {
     206             :     boost::shared_ptr<FlowStatsCollectorReq>
     207             :         req(new FlowStatsCollectorReq(
     208             :                     FlowStatsCollectorReq::ADD_FLOW_STATS_COLLECTOR,
     209           4 :                     key, flow_stats_interval, flow_cache_timeout));
     210           4 :     request_queue_.Enqueue(req);
     211           4 : }
     212             : 
     213           0 : void FlowStatsManager::Delete(const FlowAgingTableKey &key) {
     214           0 :     if (key.proto == kCatchAllProto) {
     215           0 :         return;
     216             :     }
     217             :     boost::shared_ptr<FlowStatsCollectorReq>
     218             :         req(new FlowStatsCollectorReq(
     219             :                     FlowStatsCollectorReq::DELETE_FLOW_STATS_COLLECTOR,
     220           0 :                     key));
     221           0 :     request_queue_.Enqueue(req);
     222           0 : }
     223             : 
     224           0 : void FlowStatsManager::Free(const FlowAgingTableKey &key) {
     225             :     boost::shared_ptr<FlowStatsCollectorReq>
     226             :         req(new FlowStatsCollectorReq(
     227             :                     FlowStatsCollectorReq::FREE_FLOW_STATS_COLLECTOR,
     228           0 :                     key));
     229           0 :     request_queue_.Enqueue(req);
     230           0 : }
     231             : 
     232             : const FlowStatsCollectorObject*
     233           0 : FlowStatsManager::Find(uint32_t proto, uint32_t port) const {
     234             : 
     235           0 :      FlowAgingTableKey key1(proto, port);
     236           0 :      FlowAgingTableMap::const_iterator key1_it = flow_aging_table_map_.find(key1);
     237             : 
     238           0 :      if (key1_it == flow_aging_table_map_.end()){
     239           0 :          return NULL;
     240             :      }
     241             : 
     242           0 :      return key1_it->second.get();
     243             : }
     244             : 
     245             : FlowStatsCollectorObject*
     246          71 : FlowStatsManager::GetFlowStatsCollectorObject(const FlowEntry *flow) const {
     247          71 :     FlowStatsCollectorObject* col = NULL;
     248             : 
     249          71 :     const FlowKey &key = flow->key();
     250          71 :     FlowAgingTableKey key1(key.protocol, key.src_port);
     251             :     FlowAgingTableMap::const_iterator key1_it =
     252          71 :         flow_aging_table_map_.find(key1);
     253             : 
     254          71 :     if (key1_it != flow_aging_table_map_.end()) {
     255           0 :         col = key1_it->second.get();
     256           0 :         if (!col->IsDeleted())
     257           0 :             return col;
     258             :     }
     259             : 
     260          71 :     FlowAgingTableKey key2(key.protocol, key.dst_port);
     261             :     FlowAgingTableMap::const_iterator key2_it =
     262          71 :         flow_aging_table_map_.find(key2);
     263          71 :     if (key2_it != flow_aging_table_map_.end()) {
     264           0 :         col = key2_it->second.get();
     265           0 :         if (!col->IsDeleted())
     266           0 :             return col;
     267             :     }
     268             : 
     269          71 :     if (protocol_list_[key.protocol] != NULL) {
     270           0 :         col = protocol_list_[key.protocol];
     271           0 :         if (!col->IsDeleted())
     272           0 :             return col;
     273             :     }
     274          71 :     return default_flow_stats_collector_obj_.get();
     275             : }
     276             : 
     277             : FlowStatsCollector*
     278         144 : FlowStatsManager::GetFlowStatsCollector(const FlowEntry *flow) const {
     279             :     /* If the reverse flow already has FlowStatsCollector assigned, return
     280             :      * the same to ensure that forward and reverse flows go to same
     281             :      * FlowStatsCollector */
     282         144 :     const FlowEntry *rflow = flow->reverse_flow_entry();
     283         144 :     if (rflow && rflow->fsc()) {
     284          73 :         return rflow->fsc();
     285             :     }
     286          71 :     FlowStatsCollectorObject* obj = GetFlowStatsCollectorObject(flow);
     287             : 
     288          71 :     return obj->FlowToCollector(flow);
     289             : }
     290             : 
     291         230 : void FlowStatsManager::AddEvent(FlowEntryPtr &flow) {
     292         230 :     if (flow == NULL) {
     293           0 :         return;
     294             :     }
     295             : 
     296         230 :     FlowStatsCollector *fsc = NULL;
     297         230 :     if (flow->fsc() == NULL) {
     298         144 :         fsc = GetFlowStatsCollector(flow.get());
     299         144 :         flow->set_fsc(fsc);
     300             :     } else {
     301          86 :         fsc = flow->fsc();
     302             :     }
     303             : 
     304         230 :     fsc->AddEvent(flow);
     305             : 
     306         230 :     SessionStatsCollector *ssc = NULL;
     307         230 :     ssc = session_stats_collector_obj_->FlowToCollector(flow.get());
     308         230 :     if (ssc) {
     309         230 :         ssc->AddEvent(flow);
     310             :     }
     311             : }
     312             : 
     313         144 : void FlowStatsManager::DeleteEvent(const FlowEntryPtr &flow,
     314             :                                    const RevFlowDepParams &params) {
     315         144 :     if (flow == NULL) {
     316           0 :         return;
     317             :     }
     318         144 :     FlowStatsCollector *fsc = flow->fsc();
     319             :     /* Ignore delete requests if FlowStatsCollector is NULL */
     320         144 :     if (fsc != NULL) {
     321         144 :         fsc->DeleteEvent(flow, params);
     322         144 :         flow->set_fsc(NULL);
     323             :     }
     324             : 
     325         144 :     SessionStatsCollector *ssc = NULL;
     326         144 :     ssc = session_stats_collector_obj_->FlowToCollector(flow.get());
     327         144 :     if (ssc) {
     328         144 :         ssc->DeleteEvent(flow, params);
     329             :     }
     330             : }
     331             : 
     332           0 : void FlowStatsManager::UpdateStatsEvent(const FlowEntryPtr &flow,
     333             :                                         uint32_t bytes, uint32_t packets,
     334             :                                         uint32_t oflow_bytes,
     335             :                                         const boost::uuids::uuid &u) {
     336           0 :     if (flow == NULL) {
     337           0 :         return;
     338             :     }
     339             : 
     340           0 :     FlowStatsCollector *fsc = flow->fsc();
     341           0 :     if (fsc == NULL) {
     342             :         /* Ignore stats update request, if the flow does not have any
     343             :          * FlowStatsCollector associated with it */
     344           0 :         return;
     345             :     }
     346             : 
     347           0 :     fsc->UpdateStatsEvent(flow, bytes, packets, oflow_bytes, u);
     348             : 
     349           0 :     SessionStatsCollector *ssc = NULL;
     350           0 :     ssc = session_stats_collector_obj_->FlowToCollector(flow.get());
     351           0 :     if (ssc) {
     352           0 :         ssc->UpdateSessionStatsEvent(flow, bytes, packets, oflow_bytes, u);
     353             :     }
     354             : }
     355             : 
     356           6 : uint32_t FlowStatsManager::AllocateIndex() {
     357           6 :     return instance_table_.Insert(NULL);
     358             : }
     359             : 
     360           6 : void FlowStatsManager::FreeIndex(uint32_t idx) {
     361           6 :     instance_table_.Remove(idx);
     362           6 : }
     363             : 
     364           0 : void FlowStatsManager::FlowStatsReqHandler(Agent *agent,
     365             :         uint32_t protocol, uint32_t port, uint64_t timeout) {
     366           0 :     if (timeout == 0) {
     367           0 :         agent->flow_stats_manager()->Delete(
     368           0 :                 FlowAgingTableKey(protocol, port));
     369             :     } else {
     370           0 :         agent->flow_stats_manager()->Add(
     371           0 :                 FlowAgingTableKey(protocol, port),
     372           0 :                 agent->params()->flow_stats_interval(), timeout);
     373             :     }
     374           0 : }
     375             : 
     376           2 : void FlowStatsManager::RegisterDBClients() {
     377           2 :     session_stats_collector_obj_->RegisterDBClients();
     378           2 :     return;
     379             : }
     380             : 
     381             : 
     382           4 : void FlowStatsManager::Init(uint64_t flow_stats_interval,
     383             :                            uint64_t flow_cache_timeout) {
     384           4 :     Add(FlowAgingTableKey(kCatchAllProto, 0),
     385             :         flow_stats_interval, flow_cache_timeout);
     386             : 
     387           4 :     if (agent_->tsn_enabled()) {
     388             :         /* In TSN mode, we don't support add/delete of FlowStatsCollector
     389             :          * (so we don't invoke set_flow_stats_req_handler)
     390             :          * Also, we don't export flows, so we don't start UpdateSessionThreshold
     391             :          * timer */
     392           0 :         return;
     393             :     }
     394           4 :     agent_->set_flow_stats_req_handler(&(FlowStatsManager::FlowStatsReqHandler));
     395             : 
     396           4 :     timer_->Start(FlowThresoldUpdateTime,
     397             :                   boost::bind(&FlowStatsManager::UpdateSessionThreshold, this));
     398             : }
     399             : 
     400           0 : void FlowStatsManager::InitDone() {
     401           0 :     AgentProfile *profile = agent_->oper_db()->agent_profile();
     402           0 :     profile->RegisterFlowStatsCb(boost::bind(&FlowStatsManager::SetProfileData,
     403             :                                              this, _1));
     404           0 : }
     405             : 
     406           2 : void FlowStatsManager::Shutdown() {
     407           2 :     default_flow_stats_collector_obj_->Shutdown();
     408           2 :     default_flow_stats_collector_obj_.reset();
     409           2 :     session_stats_collector_obj_->Shutdown();
     410           2 :     session_stats_collector_obj_.reset();
     411           2 :     flow_aging_table_map_.clear();
     412           2 :     protocol_list_[0] = NULL;
     413           2 :     timer_->Cancel();
     414           2 :     TimerManager::DeleteTimer(timer_);
     415           2 :     request_queue_.Shutdown();
     416           2 : }
     417             : 
     418           0 : void ShowAgingConfig::HandleRequest() const {
     419             :     SandeshResponse *resp;
     420             : 
     421           0 :     FlowStatsManager *fam = Agent::GetInstance()->flow_stats_manager();
     422           0 :     resp = new AgingConfigResponse();
     423             : 
     424           0 :     FlowStatsManager::FlowAgingTableMap::const_iterator it = fam->begin();
     425           0 :     while (it != fam->end()) {
     426           0 :         AgingConfig cfg;
     427           0 :         cfg.set_protocol(it->first.proto);
     428           0 :         cfg.set_port(it->first.port);
     429           0 :         cfg.set_cache_timeout(it->second->GetAgeTimeInSeconds());
     430           0 :         cfg.set_stats_interval(0);
     431             :         std::vector<AgingConfig> &list =
     432             :             const_cast<std::vector<AgingConfig>&>(
     433           0 :                     ((AgingConfigResponse *)resp)->get_aging_config_list());
     434           0 :         list.push_back(cfg);
     435           0 :         it++;
     436           0 :     }
     437             : 
     438           0 :     resp->set_context(context());
     439           0 :     resp->Response();
     440           0 :     return;
     441             : }
     442             : 
     443           0 : void AddAgingConfig::HandleRequest() const {
     444           0 :     FlowStatsManager *fam = Agent::GetInstance()->flow_stats_manager();
     445           0 :     fam->Add(FlowAgingTableKey(get_protocol(), get_port()),
     446           0 :                                get_stats_interval(), get_cache_timeout());
     447           0 :     SandeshResponse *resp = new FlowStatsCfgResp();
     448           0 :     resp->set_context(context());
     449           0 :     resp->Response();
     450           0 :     return;
     451             : }
     452             : 
     453           0 : void DeleteAgingConfig::HandleRequest() const {
     454           0 :     FlowStatsManager *fam = Agent::GetInstance()->flow_stats_manager();
     455           0 :     fam->Delete(FlowAgingTableKey(get_protocol(), get_port()));
     456             : 
     457           0 :     SandeshResponse *resp = new FlowStatsCfgResp();
     458           0 :     resp->set_context(context());
     459           0 :     resp->Response();
     460           0 :     return;
     461             : }
     462             : 
     463           0 : static void SetQueueStats(Agent *agent, FlowStatsCollector *fsc,
     464             :                           ProfileData::WorkQueueStats *stats) {
     465           0 :     stats->name_ = fsc->queue()->Description();
     466           0 :     stats->queue_count_ = fsc->queue()->Length();
     467           0 :     stats->enqueue_count_ = fsc->queue()->NumEnqueues();
     468           0 :     stats->dequeue_count_ = fsc->queue()->NumDequeues();
     469           0 :     stats->max_queue_count_ = fsc->queue()->max_queue_len();
     470           0 :     stats->start_count_ = fsc->queue()->task_starts();
     471           0 :     stats->busy_time_ = fsc->queue()->busy_time();
     472           0 :     fsc->queue()->set_measure_busy_time(agent->MeasureQueueDelay());
     473           0 :     if (agent->MeasureQueueDelay())
     474           0 :         fsc->queue()->ClearStats();
     475           0 : }
     476             : 
     477           0 : void FlowStatsManager::SetProfileData(ProfileData *data) {
     478           0 :     uint32_t qsize = flow_aging_table_map_.size() *
     479           0 :         FlowStatsCollectorObject::kMaxCollectors;
     480           0 :     data->flow_.flow_stats_queue_.resize(qsize);
     481           0 :     int i = 0;
     482           0 :     FlowAgingTableMap::iterator it = flow_aging_table_map_.begin();
     483           0 :     while (it != flow_aging_table_map_.end()) {
     484           0 :         FlowStatsCollectorObject *obj = it->second.get();
     485           0 :         for (int j = 0; j < FlowStatsCollectorObject::kMaxCollectors; j++) {
     486           0 :             SetQueueStats(agent(), obj->GetCollector(j),
     487           0 :                           &data->flow_.flow_stats_queue_[i]);
     488           0 :             i++;
     489             :         }
     490           0 :         it++;
     491             :     }
     492           0 : }
     493             : 
     494           0 : void FlowStatsManager::UpdateSessionSampleExportStats(uint32_t count) {
     495           0 :     session_sample_exports_ += count;
     496           0 : }
     497             : 
     498           0 : void FlowStatsManager::UpdateSessionMsgExportStats(uint32_t count) {
     499           0 :     session_msg_exports_ += count;
     500           0 : }
     501             : 
     502           0 : void FlowStatsManager::UpdateSessionExportStats(uint32_t count,
     503             :                                                 bool first_export,
     504             :                                                 bool sampled) {
     505           0 :     session_export_count_ += count;
     506           0 :     if (first_export) {
     507           0 :         session_exports_ += count;
     508             :     }
     509           0 :     if (!sampled) {
     510           0 :         session_export_without_sampling_ += count;
     511             :     }
     512           0 : }

Generated by: LCOV version 1.14