1
0
Fork 0
mirror of https://github.com/pavel-odintsov/fastnetmon synced 2024-05-03 22:26:30 +02:00
fastnetmon-rewritten/src/subnet_counter.hpp

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);
}
};