mirror of
https://github.com/pavel-odintsov/fastnetmon
synced 2024-05-03 22:26:30 +02:00
162 lines
5.7 KiB
C++
162 lines
5.7 KiB
C++
#include <stdint.h>
|
|
|
|
#include <boost/serialization/nvp.hpp>
|
|
|
|
// This class keeps all our counters for specific traffic type
|
|
class traffic_counter_element_t {
|
|
public:
|
|
uint64_t in_bytes = 0;
|
|
uint64_t out_bytes = 0;
|
|
uint64_t in_packets = 0;
|
|
uint64_t out_packets = 0;
|
|
|
|
void zeroify() {
|
|
in_bytes = 0;
|
|
out_bytes = 0;
|
|
in_packets = 0;
|
|
out_packets = 0;
|
|
}
|
|
|
|
// Returns zero when all counters are zero
|
|
bool is_zero() const {
|
|
return in_bytes == 0 && out_bytes == 0 && in_packets == 0 && out_packets == 0;
|
|
}
|
|
|
|
// This function compares value in object with passed value and updates our object value to it if it passed value exceeds value we have in place
|
|
void update_if_larger(const traffic_counter_element_t& another_value) {
|
|
if (another_value.in_bytes > this->in_bytes) {
|
|
this->in_bytes = another_value.in_bytes;
|
|
}
|
|
|
|
if (another_value.out_bytes > this->out_bytes) {
|
|
this->out_bytes = another_value.out_bytes;
|
|
}
|
|
|
|
if (another_value.in_packets > this->in_packets) {
|
|
this->in_packets = another_value.in_packets;
|
|
}
|
|
|
|
|
|
if (another_value.out_packets > this->out_packets) {
|
|
this->out_packets = another_value.out_packets;
|
|
}
|
|
}
|
|
|
|
template <class Archive> void serialize(Archive& ar, [[maybe_unused]] const unsigned int version) {
|
|
ar& BOOST_SERIALIZATION_NVP(in_bytes);
|
|
ar& BOOST_SERIALIZATION_NVP(out_bytes);
|
|
ar& BOOST_SERIALIZATION_NVP(in_packets);
|
|
ar& BOOST_SERIALIZATION_NVP(out_packets);
|
|
}
|
|
|
|
// Calculates speed for all counters from input data counter
|
|
void calculate_speed(const traffic_counter_element_t& traffic_counter, double speed_calc_period) {
|
|
this->in_packets = uint64_t((double)traffic_counter.in_packets / speed_calc_period);
|
|
this->out_packets = uint64_t((double)traffic_counter.out_packets / speed_calc_period);
|
|
|
|
this->in_bytes = uint64_t((double)traffic_counter.in_bytes / speed_calc_period);
|
|
this->out_bytes = uint64_t((double)traffic_counter.out_bytes / speed_calc_period);
|
|
}
|
|
|
|
// Calculates exponential moving average speed from instant speed
|
|
void calulate_exponential_moving_average_speed(const traffic_counter_element_t& new_speed_element, double exp_value) {
|
|
// Bytes counters
|
|
this->in_bytes =
|
|
uint64_t(new_speed_element.in_bytes + exp_value * ((double)this->in_bytes - (double)new_speed_element.in_bytes));
|
|
|
|
this->out_bytes =
|
|
uint64_t(new_speed_element.out_bytes + exp_value * ((double)this->out_bytes - (double)new_speed_element.out_bytes));
|
|
|
|
// Packet counters
|
|
this->in_packets = uint64_t(new_speed_element.in_packets +
|
|
exp_value * ((double)this->in_packets - (double)new_speed_element.in_packets));
|
|
|
|
this->out_packets = uint64_t(new_speed_element.out_packets +
|
|
exp_value * ((double)this->out_packets - (double)new_speed_element.out_packets));
|
|
}
|
|
};
|
|
|
|
|
|
// Main data structure for storing traffic and speed data for all our IPs
|
|
class subnet_counter_t {
|
|
public:
|
|
// We use inaccurate time source for it because we do not care about precise time in this case
|
|
time_t last_update_time = 0;
|
|
|
|
traffic_counter_element_t total;
|
|
|
|
traffic_counter_element_t tcp;
|
|
traffic_counter_element_t udp;
|
|
traffic_counter_element_t icmp;
|
|
|
|
traffic_counter_element_t fragmented;
|
|
traffic_counter_element_t tcp_syn;
|
|
|
|
// Total number of dropped traffic
|
|
traffic_counter_element_t dropped;
|
|
|
|
// Updates specific value if any of fields from another_value exceed values in our object
|
|
void update_if_larger(const subnet_counter_t& another_value) {
|
|
this->total.update_if_larger(another_value.total);
|
|
|
|
this->tcp.update_if_larger(another_value.tcp);
|
|
this->udp.update_if_larger(another_value.udp);
|
|
this->icmp.update_if_larger(another_value.icmp);
|
|
|
|
this->fragmented.update_if_larger(another_value.fragmented);
|
|
this->tcp_syn.update_if_larger(another_value.tcp_syn);
|
|
|
|
this->dropped.update_if_larger(another_value.dropped);
|
|
|
|
if (in_flows < another_value.in_flows) {
|
|
this->in_flows = another_value.in_flows;
|
|
}
|
|
|
|
if (out_flows < another_value.out_flows) {
|
|
this->out_flows = another_value.out_flows;
|
|
}
|
|
}
|
|
|
|
uint64_t in_flows = 0;
|
|
uint64_t out_flows = 0;
|
|
|
|
// Is total counters fields are zero? We are not handling per protocol counters here because we assume they should
|
|
// be counted twice
|
|
// Once: in total counter (in_bytes) and secondly in per protocol counter (for example: udp_in_bytes)
|
|
bool is_zero() const {
|
|
return total.in_bytes == 0 && total.out_bytes == 0 && total.in_packets == 0 && total.out_packets == 0 &&
|
|
in_flows == 0 && out_flows == 0;
|
|
}
|
|
|
|
// Fill all counters by zeros
|
|
void zeroify() {
|
|
total.zeroify();
|
|
dropped.zeroify();
|
|
|
|
tcp.zeroify();
|
|
udp.zeroify();
|
|
icmp.zeroify();
|
|
|
|
fragmented.zeroify();
|
|
tcp_syn.zeroify();
|
|
|
|
in_flows = 0;
|
|
out_flows = 0;
|
|
}
|
|
|
|
template <class Archive> void serialize(Archive& ar, [[maybe_unused]] const unsigned int version) {
|
|
ar& BOOST_SERIALIZATION_NVP(total);
|
|
ar& BOOST_SERIALIZATION_NVP(dropped);
|
|
|
|
ar& BOOST_SERIALIZATION_NVP(tcp);
|
|
ar& BOOST_SERIALIZATION_NVP(udp);
|
|
ar& BOOST_SERIALIZATION_NVP(icmp);
|
|
|
|
ar& BOOST_SERIALIZATION_NVP(fragmented);
|
|
ar& BOOST_SERIALIZATION_NVP(tcp_syn);
|
|
|
|
ar& BOOST_SERIALIZATION_NVP(in_flows);
|
|
ar& BOOST_SERIALIZATION_NVP(out_flows);
|
|
}
|
|
};
|