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: 37 193 19.2 %
Date: 2026-08-03 02:19:58 Functions: 7 18 38.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14