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

Generated by: LCOV version 1.14