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

Generated by: LCOV version 1.14