diff --git a/VpnPeer.cpp b/VpnPeer.cpp index e071d0c..b40ffbd 100644 --- a/VpnPeer.cpp +++ b/VpnPeer.cpp @@ -63,44 +63,57 @@ void VpnPeer::make_rtta_for(const VpnTlvRTTQ& rttq) { rtta.set_recv_ts(rttq.get_packet().get_reception_timestamp()); } -PacketLossLogger::PacketLossLogger() : _cur_seqno(0) {} +PacketLossLogger::PacketLossLogger() : + _cur_seqno(0), _tot_losses(0), _last_window_losses(0), _win_start_losses(0) +{} void PacketLossLogger::log_packet(uint32_t seqno) { - uint32_t m_seqno = seqno % PACKET_LOSS_HISTSIZE; int64_t diff = (int64_t)seqno - _cur_seqno; if(diff == 1) { _cur_seqno++; - _packet_loss_hist.reset(m_seqno); + maybe_start_window(); while(_received_ahead.test((_cur_seqno + 1) % PACKET_LOST_AFTER)) { _cur_seqno++; - _packet_loss_hist.reset(_cur_seqno % PACKET_LOSS_HISTSIZE); _received_ahead.reset(_cur_seqno % PACKET_LOST_AFTER); + maybe_start_window(); } } else if(LIKELY(diff > 1)) { if(diff < PACKET_LOST_AFTER) _received_ahead.set(seqno % PACKET_LOST_AFTER); - else if(diff < PACKET_LOSS_HISTSIZE) { + else if(diff < PACKET_LOSS_WINDOW) { // Packet too much forwards -- consider _cur_seqno lost - for(int offs=1; offs < PACKET_LOST_AFTER; ++offs) { - _packet_loss_hist[(_cur_seqno + offs) % PACKET_LOSS_HISTSIZE] = - !_received_ahead[(_cur_seqno + offs) % PACKET_LOST_AFTER]; + if(_cur_seqno % PACKET_LOSS_WINDOW > seqno % PACKET_LOSS_WINDOW) { + // This loss crosses a window border + for(int offs=0; offs < PACKET_LOST_AFTER; ++offs) { + maybe_start_window(offs); + if(!_received_ahead[(_cur_seqno + offs) % PACKET_LOST_AFTER]) + _tot_losses++; + } + } else { + _tot_losses += PACKET_LOST_AFTER - _received_ahead.count(); } _received_ahead.reset(); _cur_seqno = seqno; - _packet_loss_hist.reset(m_seqno); } else reboot(); // This is a huge gap -- reboot } else { - if(diff < - 2*PACKET_LOSS_HISTSIZE) + if(diff < - 2*PACKET_LOSS_WINDOW) reboot(); // this is too much backwards -- something's wrong, reboot // else: ignore, we've moved forward and counted the packet as lost } } void PacketLossLogger::reboot() { - _packet_loss_hist.reset(); _received_ahead.reset(); + // _tot_losses unchanged +} + +void PacketLossLogger::maybe_start_window(int offs) { + if(_cur_seqno + offs % PACKET_LOSS_WINDOW == 0) { + _last_window_losses = _win_start_losses; + _win_start_losses = _tot_losses; + } } RTTLogger::RTTLogger() : diff --git a/VpnPeer.hpp b/VpnPeer.hpp index 60fa5e8..ac78665 100644 --- a/VpnPeer.hpp +++ b/VpnPeer.hpp @@ -10,18 +10,15 @@ class UdpVpn; -const int PACKET_LOSS_HISTSIZE = 128, PACKET_LOST_AFTER = 8; +const int PACKET_LOSS_WINDOW = 128, PACKET_LOST_AFTER = 8; class PacketLossLogger { public: PacketLossLogger(); void log_packet(uint32_t seqno); double get_loss_rate() const { - return (double)_packet_loss_hist.count() / PACKET_LOSS_HISTSIZE; - } - - const std::bitset get_loss_hist() const { - return _packet_loss_hist; + return (double)(_win_start_losses - _last_window_losses) + / (double)PACKET_LOSS_WINDOW; } const std::bitset get_received_ahead() const { @@ -29,13 +26,18 @@ class PacketLossLogger { } uint32_t get_cur_seqno() const { return _cur_seqno; } + unsigned int get_tot_losses() const { return _tot_losses; } private: void reboot(); ///< completely reset the internal state - std::bitset _packet_loss_hist; + /// roll loss window values if `_cur_seqno + offs` is a window start. + void maybe_start_window(int offs=0); + std::bitset _received_ahead; uint32_t _cur_seqno; + unsigned int _tot_losses; + unsigned int _last_window_losses, _win_start_losses; }; /** Round-trip time logger. All timestamps/delays are in microseconds. */ @@ -83,8 +85,8 @@ class VpnPeer { void set_int_addr(const in6_addr& int_addr); - const PacketLossLogger& get_loss_logger() { return _packet_loss; } - const RTTLogger& get_rtt() { return _rtt; } + const PacketLossLogger& get_loss_logger() const { return _packet_loss; } + const RTTLogger& get_rtt() const { return _rtt; } void log_rtta(const VpnTlvRTTA& rtta) { _rtt.log(rtta); } diff --git a/tests/test_packetloss.cpp b/tests/test_packetloss.cpp deleted file mode 100644 index dc11290..0000000 --- a/tests/test_packetloss.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include -#include "VpnPeer.hpp" - -template -std::string bitset_to_string( - const std::bitset& bs, - char c_f, char c_t, size_t mark_pos, char cm_f, char cm_t) -{ - std::string out; - for(size_t pos=0; pos < len; ++pos) { - if(pos == mark_pos) - out += bs[pos] ? cm_t : cm_f; - else - out += bs[pos] ? c_t : c_f; - } - return out; -} - -void dump(PacketLossLogger& pllog, int received) { - printf("%03d, %.03lf ## %s ## %s\n", - received, - pllog.get_loss_rate(), - bitset_to_string( - pllog.get_loss_hist(), '_', 'X', - pllog.get_cur_seqno() % PACKET_LOSS_HISTSIZE, - '|', '#').c_str(), - bitset_to_string( - pllog.get_received_ahead(), '_', 'X', - pllog.get_cur_seqno() % PACKET_LOST_AFTER, - '|', '#').c_str()); -} - -int main(void) { - PacketLossLogger pllog; - std::vector sequence({ - 1, 2, 3, 5, 6, 4, 8, 7, 8, 9, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 10, 21 - }); - - dump(pllog, 0); - for(auto val=sequence.begin(); val != sequence.end(); ++val) { - pllog.log_packet(*val); - dump(pllog, *val); - } - - return 0; -}