LCOV - code coverage report
Current view: top level - vnsw/agent/uve - interface_uve_stats_table.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 48 193 24.9 %
Date: 2026-11-09 02:10:49 Functions: 8 18 44.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <oper/interface_common.h>
       7             : #include <uve/interface_uve_stats_table.h>
       8             : #include <uve/agent_uve_stats.h>
       9             : 
      10           4 : InterfaceUveStatsTable::InterfaceUveStatsTable(Agent *agent,
      11           4 :                                                uint32_t default_intvl)
      12           4 :     : InterfaceUveTable(agent, default_intvl) {
      13           4 : }
      14             : 
      15           6 : InterfaceUveStatsTable::~InterfaceUveStatsTable() {
      16           6 : }
      17             : 
      18           0 : bool InterfaceUveStatsTable::FrameInterfaceObjectLog(UveInterfaceEntry* entry,
      19             :                                             EndpointSecurityStats *obj) const {
      20           0 :     assert(!entry->deleted_);
      21           0 :     const VmInterface *vm_intf = entry->intf_;
      22           0 :     if (vm_intf->cfg_name().empty()) {
      23           0 :         return false;
      24             :     }
      25           0 :     entry->FillEndpointStats(agent_, obj);
      26           0 :     return true;
      27             : }
      28             : 
      29           0 : bool InterfaceUveStatsTable::FrameInterfaceStatsMsg(UveInterfaceEntry* entry,
      30             :                                                     VMIStats *uve) const {
      31           0 :     uint64_t in_band = 0, out_band = 0;
      32           0 :     bool diff_fip_list_non_zero = false;
      33           0 :     VmInterfaceStats if_stats;
      34           0 :     vector<VmFloatingIPStats> agg_fip_list;
      35           0 :     vector<VmFloatingIPStats> diff_fip_list;
      36             : 
      37           0 :     const VmInterface *vm_intf = entry->intf_;
      38           0 :     assert(!entry->deleted_);
      39           0 :     if (vm_intf->cfg_name().empty()) {
      40           0 :         return false;
      41             :     }
      42           0 :     uve->set_name(vm_intf->cfg_name());
      43           0 :     entry->SetVMIStatsVnVm(uve);
      44             : 
      45           0 :     const Interface *intf = static_cast<const Interface *>(vm_intf);
      46           0 :     AgentUveStats *agent_uve = static_cast<AgentUveStats *>(agent_->uve());
      47             :     StatsManager::InterfaceStats *s =
      48           0 :         agent_uve->stats_manager()->GetInterfaceStats(intf);
      49           0 :     if (s == NULL) {
      50           0 :         return false;
      51             :     }
      52             : 
      53           0 :     AgentDropStats ds;
      54           0 :     agent_uve->stats_manager()->BuildDropStats(s->drop_stats, ds);
      55           0 :     uve->set_raw_drop_stats(ds);
      56             : 
      57             :     /* Send aggregate interface stats always */
      58           0 :     if_stats.set_in_pkts(s->in_pkts);
      59           0 :     if_stats.set_in_bytes(s->in_bytes);
      60           0 :     if_stats.set_out_pkts(s->out_pkts);
      61           0 :     if_stats.set_out_bytes(s->out_bytes);
      62           0 :     uve->set_raw_if_stats(if_stats);
      63             : 
      64             :     /* Compute bandwidth only if there is change in statistics */
      65             :     uint64_t in_b, out_b;
      66           0 :     s->GetDiffStats(&in_b, &out_b);
      67           0 :     if ((in_b != 0) || (out_b != 0)) {
      68           0 :         in_band = GetVmPortBandwidth(s, true);
      69           0 :         out_band = GetVmPortBandwidth(s, false);
      70             :     }
      71             : 
      72           0 :     if (entry->InBandChanged(in_band)) {
      73           0 :         uve->set_in_bw_usage(in_band);
      74           0 :         entry->uve_stats_.set_in_bw_usage(in_band);
      75             :     }
      76           0 :     if (entry->OutBandChanged(out_band)) {
      77           0 :         uve->set_out_bw_usage(out_band);
      78           0 :         entry->uve_stats_.set_out_bw_usage(out_band);
      79             :     }
      80           0 :     s->stats_time = UTCTimestampUsec();
      81             : 
      82             :     /* Make sure that update of prev_in_bytes and prev_out_bytes are done only
      83             :      * after GetVmPortBandwidth is done for both directions as they get used
      84             :      * in those APIs. */
      85           0 :     s->UpdatePrevStats();
      86             : 
      87           0 :     PortBucketBitmap map;
      88           0 :     L4PortBitmap &port_bmap = entry->port_bitmap_;
      89           0 :     port_bmap.Encode(map);
      90           0 :     if (entry->PortBitmapChanged(map)) {
      91           0 :         uve->set_port_bucket_bmap(map);
      92           0 :         entry->uve_stats_.set_port_bucket_bmap(map);
      93             :     }
      94             : 
      95           0 :     FrameFipStatsMsg(vm_intf, agg_fip_list, diff_fip_list,
      96             :                      diff_fip_list_non_zero);
      97           0 :     if (entry->FipAggStatsChanged(agg_fip_list)) {
      98           0 :         uve->set_fip_agg_stats(agg_fip_list);
      99           0 :         entry->uve_stats_.set_fip_agg_stats(agg_fip_list);
     100             :     }
     101             :     /* Diff stats need not be sent if the value of the stats is 0.
     102             :      * If any of the entry in diff_fip_list has non-zero stats, then
     103             :      * diff_fip_list_non_zero is expected to be true */
     104           0 :     if (diff_fip_list_non_zero) {
     105           0 :         uve->set_fip_diff_stats(diff_fip_list);
     106             :     }
     107             : 
     108           0 :     VrouterFlowRate flow_rate;
     109           0 :     uint64_t created = 0, aged = 0;
     110           0 :     uint32_t active_flows = 0;
     111           0 :     agent_->pkt()->get_flow_proto()->InterfaceFlowCount(vm_intf, &created,
     112             :                                                         &aged, &active_flows);
     113           0 :     bool built = agent_uve->stats_manager()->BuildFlowRate(s->added, s->deleted,
     114           0 :                                                            s->flow_info,
     115             :                                                            flow_rate);
     116           0 :     if (built) {
     117           0 :         flow_rate.set_active_flows(active_flows);
     118           0 :         uve->set_flow_rate(flow_rate);
     119             :     }
     120             :     /* Populate TagSet and policy-list in UVE */
     121           0 :     entry->FillTagSetAndPolicyList(uve);
     122             : 
     123           0 :     return true;
     124           0 : }
     125             : 
     126           0 : void InterfaceUveStatsTable::SendInterfaceStatsMsg(UveInterfaceEntry* entry) {
     127           0 :     if (entry->deleted_) {
     128           0 :         return;
     129             :     }
     130           0 :     VMIStats uve;
     131             : 
     132           0 :     bool send = FrameInterfaceStatsMsg(entry, &uve);
     133           0 :     if (send) {
     134           0 :         DispatchVMIStatsMsg(uve);
     135             :     }
     136           0 :     EndpointSecurityStats *obj_log = ENDPOINT_SECURITY_STATS_CREATE();
     137           0 :     send = FrameInterfaceObjectLog(entry, obj_log);
     138           0 :     if (send) {
     139           0 :         DispatchInterfaceObjectLog(obj_log);
     140             :     }
     141           0 : }
     142             : 
     143           0 : void InterfaceUveStatsTable::SendInterfaceStats(void) {
     144           0 :     InterfaceMap::iterator it = interface_tree_.begin();
     145           0 :     while (it != interface_tree_.end()) {
     146           0 :         UveInterfaceEntry* entry = it->second.get();
     147             :         {
     148           0 :             std::scoped_lock lock(entry->mutex_);
     149           0 :             SendInterfaceStatsMsg(entry);
     150           0 :         }
     151           0 :         it++;
     152             :     }
     153           0 : }
     154             : 
     155           0 : uint64_t InterfaceUveStatsTable::GetVmPortBandwidth
     156             :     (StatsManager::InterfaceStats *s, bool dir_in) const {
     157           0 :     if (s->stats_time == 0) {
     158           0 :         return 0;
     159             :     }
     160             :     uint64_t bits;
     161           0 :     if (dir_in) {
     162           0 :         bits = (s->in_bytes - s->prev_in_bytes) * 8;
     163             :     } else {
     164           0 :         bits = (s->out_bytes - s->prev_out_bytes) * 8;
     165             :     }
     166           0 :     uint64_t cur_time = UTCTimestampUsec();
     167           0 :     uint64_t b_intvl = agent_->uve()->bandwidth_intvl();
     168           0 :     uint64_t diff_seconds = (cur_time - s->stats_time) / b_intvl;
     169           0 :     if (diff_seconds == 0) {
     170           0 :         return 0;
     171             :     }
     172           0 :     return bits/diff_seconds;
     173             : }
     174             : 
     175          22 : void InterfaceUveStatsTable::UpdateFloatingIpStats(const FipInfo &fip_info) {
     176          22 :     Interface *intf = dynamic_cast<Interface *>
     177          22 :         (agent_->interface_table()->FindActiveEntry(&fip_info.fip_vmi_));
     178          22 :     if (intf == NULL) {
     179           0 :         return;
     180             :     }
     181          22 :     std::scoped_lock lock(interface_tree_mutex_);
     182          22 :     VmInterface *vmi = static_cast<VmInterface *>(intf);
     183          22 :     InterfaceMap::iterator intf_it = interface_tree_.find(vmi->cfg_name());
     184             : 
     185             :     /*
     186             :      *  1. VM interface with floating-ip becomes active
     187             :      *  2. Flow is created on this interface and interface floating ip info is
     188             :      *     stored in flow record
     189             :      *  3. VM Interface is disassociated from VM
     190             :      *  4. VM Interface info is removed from interface_tree_ because of
     191             :      *     disassociation
     192             :      *  5. FlowStats collection task initiates export of flow stats
     193             :      *  6. Since interface is absent in interface_tree_ we cannot update
     194             :      *     stats in this case
     195             :      */
     196          22 :     if (intf_it != interface_tree_.end()) {
     197          22 :         UveInterfaceEntry *entry = intf_it->second.get();
     198          22 :         entry->UpdateFloatingIpStats(fip_info);
     199             :     }
     200          22 : }
     201             : 
     202           0 : bool InterfaceUveStatsTable::FrameFipStatsMsg(const VmInterface *itf,
     203             :                           vector<VmFloatingIPStats> &fip_list,
     204             :                           vector<VmFloatingIPStats> &diff_list,
     205             :                           bool &diff_list_send) const {
     206           0 :     bool changed = false;
     207           0 :     diff_list_send = false;
     208           0 :     InterfaceMap::const_iterator it = interface_tree_.find(itf->cfg_name());
     209             : 
     210           0 :     if (it != interface_tree_.end()) {
     211           0 :         UveInterfaceEntry *entry = it->second.get();
     212           0 :         changed = entry->FillFloatingIpStats(fip_list, diff_list,
     213             :                                              diff_list_send);
     214             :     }
     215           0 :     return changed;
     216             : }
     217             : 
     218             : 
     219         150 : void InterfaceUveStatsTable::UpdatePortBitmap
     220             :     (const string &name, uint8_t proto, uint16_t sport, uint16_t dport) {
     221         150 :     std::scoped_lock lock(interface_tree_mutex_);
     222         150 :     InterfaceMap::const_iterator it = interface_tree_.find(name);
     223             : 
     224         150 :     if (it != interface_tree_.end()) {
     225         150 :         UveInterfaceEntry *entry = it->second.get();
     226         150 :         entry->UpdatePortBitmap(proto, sport, dport);
     227             :     }
     228         150 : }
     229             : 
     230           0 : InterfaceUveTable::FloatingIp * InterfaceUveStatsTable::FipEntry
     231             :     (uint32_t fip, const string &vn, Interface *intf) {
     232           0 :     std::scoped_lock lock(interface_tree_mutex_);
     233           0 :     VmInterface *vmi = static_cast<VmInterface *>(intf);
     234           0 :     InterfaceMap::iterator intf_it = interface_tree_.find(vmi->cfg_name());
     235             : 
     236           0 :     if (intf_it == interface_tree_.end()) {
     237           0 :         return NULL;
     238             :     }
     239             : 
     240           0 :     UveInterfaceEntry *entry = intf_it->second.get();
     241           0 :     return entry->FipEntry(fip, vn);
     242           0 : }
     243             : 
     244         179 : void InterfaceUveStatsTable::IncrInterfaceAceStats
     245             :     (const FlowUveStatsRequest *req) {
     246         179 :     if (!req->sg_info_valid()) {
     247          10 :         return;
     248             :     }
     249         169 :     InterfaceMap::iterator intf_it = interface_tree_.find(req->interface());
     250             : 
     251         169 :     if (intf_it != interface_tree_.end()) {
     252         169 :         UveInterfaceEntry *entry = intf_it->second.get();
     253         169 :         entry->UpdateInterfaceAceStats(req->sg_rule_uuid());
     254             :     }
     255             : }
     256             : 
     257         208 : bool InterfaceUveStatsTable::IncrInterfaceEndpointHits(const string &itf,
     258             :     const FlowUveFwPolicyInfo &info) {
     259         208 :     if (!info.is_valid_) {
     260          66 :         return false;
     261             :     }
     262         142 :     InterfaceMap::iterator intf_it = interface_tree_.find(itf);
     263             : 
     264         142 :     if (intf_it != interface_tree_.end()) {
     265         142 :         UveInterfaceEntry *entry = intf_it->second.get();
     266             :         /* We don't send EndpointSecurityStats objectlog for deleted interfaces.
     267             :          * So, there is no need to update stats on deleted interfaces */
     268         142 :         if (entry->deleted_) {
     269         128 :             return false;
     270             :         }
     271          14 :         entry->UpdateInterfaceFwPolicyStats(info);
     272          14 :         return true;
     273             :     }
     274           0 :     return false;
     275             : }
     276             : 
     277           0 : void InterfaceUveStatsTable::SendInterfaceAceStats(const string &name,
     278             :                                                    UveInterfaceEntry *entry) {
     279           0 :     VMIStats uve;
     280           0 :     if (entry->FrameInterfaceAceStatsMsg(name, &uve)) {
     281           0 :         DispatchVMIStatsMsg(uve);
     282             :     }
     283           0 : }
     284             : 
     285          43 : void InterfaceUveStatsTable::UpdateVmiTagBasedStats(const EndpointStatsInfo
     286             :                                                     &info) {
     287          43 :     std::scoped_lock lock(interface_tree_mutex_);
     288          43 :     InterfaceMap::iterator intf_it = interface_tree_.find(info.vmi->cfg_name());
     289          43 :     if (intf_it != interface_tree_.end()) {
     290          27 :         UveInterfaceEntry *entry = intf_it->second.get();
     291          27 :         entry->UpdateSecurityPolicyStats(info);
     292             :     }
     293          43 : }
     294             : 
     295           0 : void InterfaceUveStatsTable::BuildInterfaceUveInfo(InterfaceUveInfoResp *r) {
     296             : 
     297             :     vector<InterfaceUveInfo> &list =
     298           0 :         const_cast<std::vector<InterfaceUveInfo>&>(r->get_resp_list());
     299           0 :     std::scoped_lock lock(interface_tree_mutex_);
     300           0 :     InterfaceMap::iterator intf_it = interface_tree_.begin();
     301           0 :     while (intf_it != interface_tree_.end()) {
     302           0 :         InterfaceUveInfo item;
     303           0 :         UveInterfaceEntry *entry = intf_it->second.get();
     304           0 :         ++intf_it;
     305           0 :         entry->BuildInterfaceUveInfo(&item);
     306           0 :         list.push_back(item);
     307           0 :     }
     308             : 
     309           0 : }
     310             : 
     311           0 : void InterfaceUveInfoReq::HandleRequest() const {
     312           0 :     InterfaceUveInfoResp *resp = new InterfaceUveInfoResp();
     313           0 :     Agent *agent = Agent::GetInstance();
     314             :     InterfaceUveStatsTable *table = static_cast<InterfaceUveStatsTable *>
     315           0 :         (agent->uve()->interface_uve_table());
     316           0 :     table->BuildInterfaceUveInfo(resp);
     317           0 :     resp->set_context(context());
     318           0 :     resp->Response();
     319           0 :     return;
     320             : }

Generated by: LCOV version 1.14