LCOV - code coverage report
Current view: top level - vnsw/agent/uve - vn_uve_entry.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 58 340 17.1 %
Date: 2026-08-03 02:19:58 Functions: 7 25 28.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <uve/vn_uve_entry.h>
       6             : #include <uve/agent_uve_stats.h>
       7             : 
       8          20 : VnUveEntry::VnUveEntry(Agent *agent, const VnEntry *vn)
       9          40 :     : VnUveEntryBase(agent, vn), port_bitmap_(), inter_vn_stats_(), mutex_(),
      10          20 :       in_bytes_(0), out_bytes_(0), prev_stats_update_time_(0),
      11          40 :       prev_in_bytes_(0), prev_out_bytes_(0) {
      12          20 : }
      13             : 
      14           6 : VnUveEntry::VnUveEntry(Agent *agent)
      15          12 :     : VnUveEntryBase(agent, NULL), port_bitmap_(), inter_vn_stats_(), mutex_(),
      16           6 :       in_bytes_(0), out_bytes_(0), prev_stats_update_time_(0),
      17          12 :       prev_in_bytes_(0), prev_out_bytes_(0) {
      18           6 : }
      19             : 
      20          26 : VnUveEntry::~VnUveEntry() {
      21          26 : }
      22             : 
      23          88 : void VnUveEntry::UpdatePortBitmap(uint8_t proto, uint16_t sport,
      24             :                                   uint16_t dport) {
      25          88 :     std::scoped_lock lock(mutex_);
      26          88 :     if (deleted_ && !renewed_) {
      27             :         /* Skip updates on VnUveEntry if it is marked for delete */
      28           0 :         return;
      29             :     }
      30          88 :     port_bitmap_.AddPort(proto, sport, dport);
      31          88 : }
      32             : 
      33          24 : void VnUveEntry::UpdateInterVnStats(const string &dst_vn, uint64_t bytes,
      34             :                                     uint64_t pkts, bool outgoing) {
      35          24 :     std::scoped_lock lock(mutex_);
      36          24 :     if (deleted_ && !renewed_) {
      37             :         /* Skip updates on VnUveEntry if it is marked for delete */
      38           0 :         return;
      39             :     }
      40          24 :     VnStatsPtr key(new VnStats(dst_vn, 0, 0, false));
      41          24 :     VnStatsSet::iterator stats_it = inter_vn_stats_.find(key);
      42          24 :     if (stats_it == inter_vn_stats_.end()) {
      43           4 :         VnStatsPtr stats(new VnStats(dst_vn, bytes, pkts, outgoing));
      44           4 :         inter_vn_stats_.insert(stats);
      45           4 :     } else {
      46          20 :         VnStatsPtr stats_ptr(*stats_it);
      47          20 :         VnStats *stats = stats_ptr.get();
      48          20 :         if (outgoing) {
      49          11 :             stats->out_bytes_ += bytes;
      50          11 :             stats->out_pkts_ += pkts;
      51             :         } else {
      52           9 :             stats->in_bytes_ += bytes;
      53           9 :             stats->in_pkts_ += pkts;
      54             :         }
      55          20 :     }
      56          24 :     if (outgoing) {
      57          13 :         out_bytes_ += bytes;
      58             :     } else {
      59          11 :         in_bytes_ += bytes;
      60             :     }
      61          24 : }
      62             : 
      63             : /* Remove all the elements of map entry value which is a set */
      64           0 : void VnUveEntry::ClearInterVnStats() {
      65           0 :     std::scoped_lock lock(mutex_);
      66           0 :     VnStatsSet::iterator stats_it = inter_vn_stats_.begin();
      67           0 :     VnStatsSet::iterator del_it;
      68           0 :     while(stats_it != inter_vn_stats_.end()) {
      69           0 :         del_it = stats_it;
      70           0 :         stats_it++;
      71           0 :         inter_vn_stats_.erase(del_it);
      72             :     }
      73           0 : }
      74             : 
      75           0 : bool VnUveEntry::SetVnPortBitmap(UveVirtualNetworkAgent &uve) {
      76           0 :     bool changed = false;
      77           0 :     std::scoped_lock lock(mutex_);
      78             : 
      79           0 :     vector<uint32_t> tcp_sport;
      80           0 :     if (port_bitmap_.tcp_sport_.Sync(tcp_sport)) {
      81           0 :         uve.set_tcp_sport_bitmap(tcp_sport);
      82           0 :         changed = true;
      83             :     }
      84             : 
      85           0 :     vector<uint32_t> tcp_dport;
      86           0 :     if (port_bitmap_.tcp_dport_.Sync(tcp_dport)) {
      87           0 :         uve.set_tcp_dport_bitmap(tcp_dport);
      88           0 :         changed = true;
      89             :     }
      90             : 
      91           0 :     vector<uint32_t> udp_sport;
      92           0 :     if (port_bitmap_.udp_sport_.Sync(udp_sport)) {
      93           0 :         uve.set_udp_sport_bitmap(udp_sport);
      94           0 :         changed = true;
      95             :     }
      96             : 
      97           0 :     vector<uint32_t> udp_dport;
      98           0 :     if (port_bitmap_.udp_dport_.Sync(udp_dport)) {
      99           0 :         uve.set_udp_dport_bitmap(udp_dport);
     100           0 :         changed = true;
     101             :     }
     102           0 :     return changed;
     103           0 : }
     104             : 
     105           0 : bool VnUveEntry::UveVnFipCountChanged(int32_t size) const {
     106           0 :     if (!uve_info_.__isset.associated_fip_count) {
     107           0 :         return true;
     108             :     }
     109           0 :     if (size != uve_info_.get_associated_fip_count()) {
     110           0 :         return true;
     111             :     }
     112           0 :     return false;
     113             : }
     114             : 
     115           0 : bool VnUveEntry::UveVnInBandChanged(uint64_t in_band) const {
     116           0 :     if (!uve_info_.__isset.in_bandwidth_usage) {
     117           0 :         return true;
     118             :     }
     119           0 :     if (in_band != uve_info_.get_in_bandwidth_usage()) {
     120           0 :         return true;
     121             :     }
     122           0 :     return false;
     123             : }
     124             : 
     125           0 : bool VnUveEntry::UveVnOutBandChanged(uint64_t out_band) const {
     126           0 :     if (!uve_info_.__isset.out_bandwidth_usage) {
     127           0 :         return true;
     128             :     }
     129           0 :     if (out_band != uve_info_.get_out_bandwidth_usage()) {
     130           0 :         return true;
     131             :     }
     132           0 :     return false;
     133             : }
     134             : 
     135           0 : bool VnUveEntry::UveVnVrfStatsChanged(const vector<UveVrfStats> &vlist) const {
     136           0 :     if (!uve_info_.__isset.vrf_stats_list) {
     137           0 :         return true;
     138             :     }
     139           0 :     if (vlist != uve_info_.get_vrf_stats_list()) {
     140           0 :         return true;
     141             :     }
     142           0 :     return false;
     143             : }
     144             : 
     145           0 : bool VnUveEntry::UveInterVnInStatsChanged(const vector<UveInterVnStats>
     146             :                                           &new_list) const {
     147           0 :     if (!uve_info_.__isset.in_stats) {
     148           0 :         return true;
     149             :     }
     150           0 :     if (new_list != uve_info_.get_in_stats()) {
     151           0 :         return true;
     152             :     }
     153           0 :     return false;
     154             : }
     155             : 
     156           0 : bool VnUveEntry::UveInterVnOutStatsChanged(const vector<UveInterVnStats>
     157             :                                            &new_list) const {
     158           0 :     if (!uve_info_.__isset.out_stats) {
     159           0 :         return true;
     160             :     }
     161           0 :     if (new_list != uve_info_.get_out_stats()) {
     162           0 :         return true;
     163             :     }
     164           0 :     return false;
     165             : }
     166             : 
     167           0 : bool VnUveEntry::UpdateVnFlowCount(const VnEntry *vn,
     168             :                                    UveVirtualNetworkAgent &s_vn) {
     169             :     /* Ingress and Egress flow counts should be sent always regardless of
     170             :      * whether it has changed or not. This is required for collector to do
     171             :      * anomaly detection. The anomaly detection done at collector is based on
     172             :      * streaming of UVE messages */
     173             :     uint32_t in_count, out_count;
     174           0 :     agent_->pkt()->get_flow_proto()->VnFlowCounters(vn, &in_count, &out_count);
     175           0 :     s_vn.set_ingress_flow_count(in_count);
     176           0 :     uve_info_.set_ingress_flow_count(in_count); //required only for UT
     177             : 
     178           0 :     s_vn.set_egress_flow_count(out_count);
     179           0 :     uve_info_.set_egress_flow_count(out_count); //required only for UT
     180           0 :     return true;
     181             : }
     182             : 
     183           0 : bool VnUveEntry::UpdateVnFipCount(int count, UveVirtualNetworkAgent &s_vn) {
     184           0 :     if (UveVnFipCountChanged(count)) {
     185           0 :         s_vn.set_associated_fip_count(count);
     186           0 :         uve_info_.set_associated_fip_count(count);
     187           0 :         return true;
     188             :     }
     189           0 :     return false;
     190             : }
     191             : 
     192           0 : bool VnUveEntry::PopulateInterVnStats(UveVirtualNetworkAgent &s_vn) {
     193           0 :     bool changed = false;
     194             :     /* Aggregate/total current stats are sent in the following fields */
     195           0 :     vector<UveInterVnStats> in_list;
     196           0 :     vector<UveInterVnStats> out_list;
     197             :     /* Only diff since previous dispatch, is sent as part of the following
     198             :      * list */
     199           0 :     vector<InterVnStats> vn_stats_list;
     200             : 
     201             :     {
     202           0 :         std::scoped_lock lock(mutex_);
     203           0 :         VnStatsSet::iterator it = inter_vn_stats_.begin();
     204             :         VnStats *stats;
     205           0 :         VnStatsPtr stats_ptr;
     206           0 :         while (it != inter_vn_stats_.end()) {
     207           0 :             stats_ptr = *it;
     208           0 :             stats = stats_ptr.get();
     209           0 :             UveInterVnStats uve_stats;
     210           0 :             uve_stats.set_other_vn(stats->dst_vn_);
     211             : 
     212           0 :             uve_stats.set_tpkts(stats->in_pkts_);
     213           0 :             uve_stats.set_bytes(stats->in_bytes_);
     214           0 :             in_list.push_back(uve_stats);
     215             : 
     216           0 :             uve_stats.set_tpkts(stats->out_pkts_);
     217           0 :             uve_stats.set_bytes(stats->out_bytes_);
     218           0 :             out_list.push_back(uve_stats);
     219             : 
     220           0 :             InterVnStats diff_stats;
     221           0 :             diff_stats.set_other_vn(stats->dst_vn_);
     222           0 :             diff_stats.set_vrouter(agent_->agent_name());
     223           0 :             diff_stats.set_in_tpkts(stats->in_pkts_ - stats->prev_in_pkts_);
     224           0 :             diff_stats.set_in_bytes(stats->in_bytes_ - stats->prev_in_bytes_);
     225           0 :             diff_stats.set_out_tpkts(stats->out_pkts_ - stats->prev_out_pkts_);
     226           0 :             diff_stats.set_out_bytes(stats->out_bytes_ -
     227           0 :                                      stats->prev_out_bytes_);
     228           0 :             vn_stats_list.push_back(diff_stats);
     229             : 
     230           0 :             stats->prev_in_pkts_ = stats->in_pkts_;
     231           0 :             stats->prev_in_bytes_ = stats->in_bytes_;
     232           0 :             stats->prev_out_pkts_ = stats->out_pkts_;
     233           0 :             stats->prev_out_bytes_ = stats->out_bytes_;
     234           0 :             it++;
     235           0 :         }
     236           0 :     }
     237           0 :     if (!in_list.empty()) {
     238           0 :         if (UveInterVnInStatsChanged(in_list)) {
     239           0 :             s_vn.set_in_stats(in_list);
     240           0 :             uve_info_.set_in_stats(in_list);
     241           0 :             changed = true;
     242             :         }
     243             :     }
     244           0 :     if (!out_list.empty()) {
     245           0 :         if (UveInterVnOutStatsChanged(out_list)) {
     246           0 :             s_vn.set_out_stats(out_list);
     247           0 :             uve_info_.set_out_stats(out_list);
     248           0 :             changed = true;
     249             :         }
     250             :     }
     251           0 :     if (!vn_stats_list.empty()) {
     252           0 :         s_vn.set_vn_stats(vn_stats_list);
     253           0 :         changed = true;
     254             :     }
     255           0 :     return changed;
     256           0 : }
     257             : 
     258           0 : void VnUveEntry::BuildArpStats(const StatsManager::VrfStats *s,
     259             :                                UveVrfStats &vrf_stats) const {
     260           0 :     UveArpStats as;
     261             : 
     262           0 :     UveVmiStats vs;
     263           0 :     UveArpResponses ar1;
     264           0 :     ar1.set_proxies(s->arp_virtual_proxy);
     265           0 :     ar1.set_stitches(s->arp_virtual_stitch);
     266           0 :     ar1.set_floods(s->arp_virtual_flood);
     267           0 :     vs.set_stats(ar1);
     268           0 :     as.set_from_vm_interface(vs);
     269             : 
     270           0 :     UvePhyIntfStats ps;
     271           0 :     UveArpResponses ar2;
     272           0 :     ar2.set_proxies(s->arp_tor_proxy);
     273           0 :     ar2.set_stitches(s->arp_physical_stitch);
     274           0 :     ar2.set_floods(s->arp_physical_flood);
     275           0 :     ps.set_stats(ar2);
     276           0 :     as.set_from_physical_interface(ps);
     277             : 
     278           0 :     vrf_stats.set_arp_packet_counts(as);
     279           0 : }
     280             : 
     281           0 : void VnUveEntry::BuildNhStats(const StatsManager::VrfStats *s,
     282             :                               UveVrfStats &vrf_stats) const {
     283           0 :     UveNhStats nhs;
     284           0 :     nhs.set_discards(s->discards);
     285           0 :     nhs.set_resolves(s->resolves);
     286           0 :     nhs.set_l3_receives(s->receives);
     287           0 :     nhs.set_l2_receives(s->l2_receives);
     288           0 :     nhs.set_local_vm_l3_forwards(s->encaps);
     289           0 :     nhs.set_local_vm_l2_forwards(s->l2_encaps);
     290           0 :     nhs.set_vrf_translates(s->vrf_translates);
     291           0 :     nhs.set_ecmp_forwards(s->ecmp_composites);
     292             : 
     293           0 :     UveTunnelNhStats tns;
     294           0 :     tns.set_udp_encaps(s->udp_tunnels);
     295           0 :     tns.set_mpls_over_udp_encaps(s->udp_mpls_tunnels);
     296           0 :     tns.set_mpls_over_gre_encaps(s->gre_mpls_tunnels);
     297           0 :     tns.set_vxlan_encaps(s->vxlan_tunnels);
     298           0 :     nhs.set_tunnel_nh_stats(tns);
     299             : 
     300           0 :     UveMulticastNhStats mns;
     301           0 :     mns.set_source_replication_forwards(s->evpn_composites);
     302           0 :     mns.set_edge_replication_forwards(s->fabric_composites);
     303           0 :     mns.set_local_vm_l3_forwards(s->encap_composites);
     304           0 :     mns.set_total_multicast_forwards(s->l2_mcast_composites);
     305           0 :     nhs.set_comp_nh_stats(mns);
     306           0 :     vrf_stats.set_nh_packet_counts(nhs);
     307           0 : }
     308             : 
     309           0 : bool VnUveEntry::FillVrfStats(int vrf_id, UveVirtualNetworkAgent &s_vn) {
     310           0 :     bool changed = false;
     311           0 :     UveVrfStats vrf_stats;
     312           0 :     vector<UveVrfStats> vlist;
     313             : 
     314           0 :     AgentUveStats *uve = static_cast<AgentUveStats *>(agent_->uve());
     315           0 :     StatsManager::VrfStats *s = uve->stats_manager()->GetVrfStats(vrf_id);
     316           0 :     if (s != NULL) {
     317           0 :         vrf_stats.set_name(s->name);
     318           0 :         vrf_stats.set_diag_packet_count(s->diags);
     319           0 :         vrf_stats.set_unknown_unicast_floods(s->uuc_floods);
     320             : 
     321           0 :         BuildArpStats(s, vrf_stats);
     322             : 
     323           0 :         UveOffloadStats os;
     324           0 :         os.set_gro(s->gros);
     325           0 :         vrf_stats.set_offload_packet_counts(os);
     326             : 
     327           0 :         BuildNhStats(s, vrf_stats);
     328             : 
     329           0 :         vlist.push_back(vrf_stats);
     330           0 :         if (UveVnVrfStatsChanged(vlist)) {
     331           0 :             s_vn.set_vrf_stats_list(vlist);
     332           0 :             uve_info_.set_vrf_stats_list(vlist);
     333           0 :             changed = true;
     334             :         }
     335           0 :     }
     336           0 :     return changed;
     337           0 : }
     338             : 
     339           0 : bool VnUveEntry::UpdateVrfStats(const VnEntry *vn,
     340             :                                 UveVirtualNetworkAgent &s_vn) {
     341           0 :     bool changed = false;
     342           0 :     VrfEntry *vrf = vn->GetVrf();
     343           0 :     if (vrf) {
     344           0 :         changed = FillVrfStats(vrf->vrf_id(), s_vn);
     345             :     } else {
     346           0 :         vector<UveVrfStats> vlist;
     347           0 :         if (UveVnVrfStatsChanged(vlist)) {
     348           0 :             s_vn.set_vrf_stats_list(vlist);
     349           0 :             uve_info_.set_vrf_stats_list(vlist);
     350           0 :             changed = true;
     351             :         }
     352           0 :     }
     353             : 
     354           0 :     return changed;
     355             : }
     356             : 
     357           0 : bool VnUveEntry::FrameVnStatsMsg(const VnEntry *vn,
     358             :                                  UveVirtualNetworkAgent &uve) {
     359           0 :     bool changed = false;
     360           0 :     assert(!deleted_);
     361           0 :     uve.set_name(vn->GetName());
     362             : 
     363           0 :     if (UpdateVrfStats(vn, uve)) {
     364           0 :         changed = true;
     365             :     }
     366             : 
     367           0 :     int fip_count = 0;
     368           0 :     InterfaceSet::iterator it = interface_tree_.begin();
     369           0 :     while (it != interface_tree_.end()) {
     370           0 :         const Interface *intf = *it;
     371           0 :         ++it;
     372             : 
     373           0 :         const VmInterface *vm_port = static_cast<const VmInterface *>(intf);
     374           0 :         fip_count += vm_port->GetFloatingIpCount();
     375             :     }
     376             : 
     377           0 :     uint64_t diff_in_bytes = 0;
     378           0 :     uint64_t diff_out_bytes = 0;
     379             : 
     380           0 :     uint64_t diff_seconds = 0;
     381           0 :     uint64_t cur_time = UTCTimestampUsec();
     382           0 :     bool send_bandwidth = false;
     383             :     uint64_t in_band, out_band;
     384           0 :     uint64_t b_intvl = agent_->uve()->bandwidth_intvl();
     385           0 :     if (prev_stats_update_time_ == 0) {
     386           0 :         in_band = out_band = 0;
     387           0 :         send_bandwidth = true;
     388           0 :         prev_stats_update_time_ = cur_time;
     389             :     } else {
     390           0 :         diff_seconds = (cur_time - prev_stats_update_time_) / b_intvl;
     391           0 :         if (diff_seconds > 0) {
     392           0 :             diff_in_bytes = in_bytes_ - prev_in_bytes_;
     393           0 :             diff_out_bytes = out_bytes_ - prev_out_bytes_;
     394           0 :             in_band = (diff_in_bytes * 8)/diff_seconds;
     395           0 :             out_band = (diff_out_bytes * 8)/diff_seconds;
     396           0 :             prev_stats_update_time_ = cur_time;
     397           0 :             prev_in_bytes_ = in_bytes_;
     398           0 :             prev_out_bytes_ = out_bytes_;
     399           0 :             send_bandwidth = true;
     400             :         }
     401             :     }
     402           0 :     if (send_bandwidth && UveVnInBandChanged(in_band)) {
     403           0 :         uve.set_in_bandwidth_usage(in_band);
     404           0 :         uve_info_.set_in_bandwidth_usage(in_band);
     405           0 :         changed = true;
     406             :     }
     407             : 
     408           0 :     if (send_bandwidth && UveVnOutBandChanged(out_band)) {
     409           0 :         uve.set_out_bandwidth_usage(out_band);
     410           0 :         uve_info_.set_out_bandwidth_usage(out_band);
     411           0 :         changed = true;
     412             :     }
     413             : 
     414           0 :     if (UpdateVnFlowCount(vn, uve)) {
     415           0 :         changed = true;
     416             :     }
     417             : 
     418           0 :     if (UpdateVnFipCount(fip_count, uve)) {
     419           0 :         changed = true;
     420             :     }
     421             : 
     422             :     /* VM interface list for VN is sent whenever any VM is added or
     423             :      * removed from VN. That message has only two fields set - vn name
     424             :      * and virtualmachine_list */
     425             : 
     426           0 :     if (PopulateInterVnStats(uve)) {
     427           0 :         changed = true;
     428             :     }
     429             : 
     430           0 :     if (SetVnPortBitmap(uve)) {
     431           0 :         changed = true;
     432             :     }
     433             : 
     434           0 :     return changed;
     435             : }
     436             : 
     437           6 : void VnUveEntry::Reset() {
     438           6 :     VnUveEntryBase::Reset();
     439           6 :     port_bitmap_.Reset();
     440           6 :     inter_vn_stats_.clear();
     441           6 :     ace_stats_.clear();
     442           6 :     ace_stats_changed_ = false;
     443           6 :     prev_stats_update_time_ = 0;
     444           6 :     prev_in_bytes_ = 0;
     445           6 :     prev_out_bytes_ = 0;
     446           6 : }
     447             : 
     448          54 : void VnUveEntry::UpdateVnAceStats(const std::string &ace_uuid) {
     449          54 :     VnAceStats key(ace_uuid);
     450          54 :     ace_stats_changed_ = true;
     451          54 :     VnAceStatsSet::const_iterator it = ace_stats_.find(key);
     452          54 :     if (it != ace_stats_.end()) {
     453          44 :         it->count++;
     454          44 :         return;
     455             :     }
     456          10 :     key.count = 1;
     457          10 :     ace_stats_.insert(key);
     458          54 : }
     459             : 
     460           0 : bool VnUveEntry::FrameVnAceStatsMsg(const VnEntry *vn,
     461             :                                     UveVirtualNetworkAgent &uve) {
     462           0 :     if (!ace_stats_changed_) {
     463           0 :         return false;
     464             :     }
     465           0 :     std::vector<NetworkPolicyRuleStats> list;
     466           0 :     bool changed = false;
     467           0 :     VnAceStatsSet::iterator it = ace_stats_.begin();
     468             :     /* Build the updated list */
     469           0 :     while (it != ace_stats_.end()) {
     470           0 :         uint64_t diff_count = it->count - it->prev_count;
     471           0 :         if (diff_count) {
     472             :             //Update prev_count
     473           0 :             it->prev_count = it->count;
     474           0 :             NetworkPolicyRuleStats item;
     475           0 :             item.set_rule(it->ace_uuid);
     476           0 :             item.set_count(diff_count);
     477           0 :             list.push_back(item);
     478           0 :             changed = true;
     479           0 :         }
     480           0 :         ++it;
     481             :     } 
     482             :     /* If all the entries in the list has 0 diff_stats, then UVE won't be
     483             :      * sent */
     484           0 :     if (changed) {
     485           0 :         uve.set_name(vn->GetName());
     486           0 :         uve.set_policy_rule_stats(list);
     487           0 :         ace_stats_changed_ = false;
     488           0 :         return true;
     489             :     }
     490           0 :     return false;
     491           0 : }

Generated by: LCOV version 1.14