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