Cleanup packet statistics

This commit is contained in:
Ludvig Strigeus 2018-12-15 23:03:15 +01:00
parent 27b75b83de
commit 983af5cf3e
6 changed files with 83 additions and 55 deletions

View file

@ -2072,8 +2072,8 @@ void TunsafeBackendWin32::CollectStats() {
stats_ = runner_->wg_proc_.GetStats();
float data[2] = {
// unit is megabits/second
stats_.tun_bytes_in_per_second * (1.0f / 125000),
stats_.tun_bytes_out_per_second * (1.0f / 125000),
stats_.data_bytes_out_per_second * (1.0f / 125000),
stats_.data_bytes_in_per_second * (1.0f / 125000),
};
stats_collector_.AddSamples(data);
stats_mutex_.Release();

View file

@ -163,14 +163,14 @@ public:
InvalidatePaintbox();
char buf[64];
uint32 mbs_in = (uint32)(stats.tun_bytes_out_per_second * (1.0 / 1250));
uint32 gb_in = (uint32)(stats.tun_bytes_out * (1.0 / (1024 * 1024 * 1024 / 100)));
uint32 mbs_in = (uint32)(stats.data_bytes_in_per_second * (1.0 / 1250));
uint32 gb_in = (uint32)(stats.data_bytes_in * (1.0 / (1024 * 1024 * 1024 / 100)));
snprintf(buf, ARRAYSIZE(buf), "D: %d.%.2d Mbps (%d.%.2d GB)", mbs_in / 100, mbs_in % 100, gb_in / 100, gb_in % 100);
SendMessage(hwndStatus, SB_SETTEXT, 1, (LPARAM)buf);
uint32 mbs_out = (uint32)(stats.tun_bytes_in_per_second * (1.0 / 1250));
uint32 gb_out = (uint32)(stats.tun_bytes_in * (1.0 / (1024 * 1024 * 1024 / 100)));
uint32 mbs_out = (uint32)(stats.data_bytes_out_per_second * (1.0 / 1250));
uint32 gb_out = (uint32)(stats.data_bytes_out * (1.0 / (1024 * 1024 * 1024 / 100)));
snprintf(buf, ARRAYSIZE(buf), "U: %d.%.2d Mbps (%d.%.2d GB)", mbs_out / 100, mbs_out % 100, gb_out / 100, gb_out % 100);
SendMessage(hwndStatus, SB_SETTEXT, 2, (LPARAM)buf);
@ -1521,6 +1521,7 @@ static const AdvancedTextInfo ADVANCED_TEXT_INFOS[] = {
{Y + 19 * 4, 66, ""},
{Y + 19 * 5, 66, "Overhead:"},
{Y + 19 * 6, 66, "Packet Loss:"},
{Y + 19 * 7, 66, "Invalid:"},
#undef Y
};
@ -1576,8 +1577,8 @@ static const char *GetAdvancedInfoValue(char buffer[256], int i) {
case 2:
snprintf(buffer, 256, "%s in (%lld packets), %s out (%lld packets)",
PrintMB(tmp, ps->udp_bytes_in), ps->udp_packets_in,
PrintMB(tmp2, ps->udp_bytes_out), ps->udp_packets_out/*, udp_qsize2 - udp_qsize1, g_tun_reads*/);
PrintMB(tmp, ps->total_bytes_in), ps->packets_in,
PrintMB(tmp2, ps->total_bytes_out), ps->packets_out/*, udp_qsize2 - udp_qsize1, g_tun_reads*/);
return buffer;
case 3: return PrintLastHandshakeAt(buffer, ps);
case 4: {
@ -1587,11 +1588,11 @@ static const char *GetAdvancedInfoValue(char buffer[256], int i) {
return buffer;
}
case 5: {
uint64 overhead_in = ps->udp_bytes_in + ps->udp_packets_in * 40 - ps->tun_bytes_out;
uint32 overhead_in_pct = ps->tun_bytes_out ? (uint32)(overhead_in * 100000 / ps->tun_bytes_out) : 0;
uint64 overhead_in = ps->total_bytes_in + ps->packets_in * 40 - ps->data_bytes_in;
uint32 overhead_in_pct = ps->data_bytes_in ? (uint32)(overhead_in * 100000 / ps->data_bytes_in) : 0;
uint64 overhead_out = ps->udp_bytes_out + ps->udp_packets_out * 40 - ps->tun_bytes_in;
uint32 overhead_out_pct = ps->tun_bytes_in ? (uint32)(overhead_out * 100000 / ps->tun_bytes_in) : 0;
uint64 overhead_out = ps->total_bytes_out + ps->packets_out * 40 - ps->data_bytes_out;
uint32 overhead_out_pct = ps->data_bytes_out ? (uint32)(overhead_out * 100000 / ps->data_bytes_out) : 0;
snprintf(buffer, 256, "%d.%.3d%% in, %d.%.3d%% out", overhead_in_pct / 1000, overhead_in_pct % 1000,
overhead_out_pct / 1000, overhead_out_pct % 1000);
@ -1603,6 +1604,10 @@ static const char *GetAdvancedInfoValue(char buffer[256], int i) {
(int)(ps->lost_packets_tot - ps->lost_packets_valid));
return buffer;
}
case 7: {
snprintf(buffer, 256, "%s in (%lld packets)", PrintMB(tmp, ps->invalid_bytes_in), ps->invalid_packets_in);
return buffer;
}
default: return "";
}
}

View file

@ -344,8 +344,6 @@ void WireguardProcessor::HandleTunPacket(Packet *packet) {
void WireguardProcessor::HandleUdpPacket(Packet *packet, bool overload) {
PacketResult result = HandleUdpPacket2(packet, overload);
if (result == kPacketResult_ForwardTun) {
//stats_.tun_bytes_out += size_from_header;
//stats_.tun_packets_out++;
tun_->WriteTunPacket(packet);
} else if (result == kPacketResult_ForwardUdp) {
udp_->WriteUdpPacket(packet);
@ -441,9 +439,6 @@ WireguardProcessor::PacketResult WireguardProcessor::WriteAndEncryptPacketToUdp_
}
assert(!peer->marked_for_delete_);
stats_.tun_bytes_in += size;
stats_.tun_packets_in++;
want_handshake = (send_ctr >= REKEY_AFTER_MESSAGES ||
keypair->send_key_state == WgKeypair::KEY_WANT_REFRESH);
keypair->send_ctr = send_ctr + 1;
@ -563,8 +558,9 @@ need_big_packet:
if (want_handshake)
peer->ScheduleNewHandshake();
stats_.udp_packets_out++;
stats_.udp_bytes_out += packet->size;
stats_.packets_out++;
stats_.data_bytes_out += orig_size;
stats_.total_bytes_out += packet->size;
return kPacketResult_ForwardUdp;
@ -577,8 +573,8 @@ void WireguardProcessor::PrepareOutgoingHandshakePacket(WgPeer *peer, Packet *pa
assert(dev_.IsMainThread());
if (dev_.plugin_)
dev_.plugin_->OnOutgoingHandshakePacket(peer, packet);
stats_.udp_packets_out++;
stats_.udp_bytes_out += packet->size;
stats_.packets_out++;
stats_.total_bytes_out += packet->size;
}
void WireguardProcessor::RunAllMainThreadScheduled() {
@ -666,9 +662,6 @@ WireguardProcessor::PacketResult WireguardProcessor::HandleUdpPacket2(Packet *pa
uint32 type;
assert(packet->protocol != 0xCD && (uint16)packet->addr.sin.sin_family != 0xCDCD); // catch msvc uninit mem
stats_.udp_bytes_in += packet->size;
stats_.udp_packets_in++;
if (packet->size < sizeof(uint32))
goto invalid_size;
type = ReadLE32((uint32*)packet->data);
@ -707,6 +700,8 @@ WireguardProcessor::PacketResult WireguardProcessor::HandleUdpPacket2(Packet *pa
} else {
// unknown packet
invalid_size:
stats_.invalid_packets_in++;
stats_.invalid_bytes_in += packet->size;
return kPacketResult_Free;
}
}
@ -819,8 +814,7 @@ WireguardProcessor::PacketResultd WireguardProcessor::HandleShortHeaderFormatPac
keypair->can_use_short_key_for_outgoing = (ack_tag & WG_ACK_HEADER_KEY_MASK) * WG_SHORT_HEADER_KEY_ID;
packet->data = data;
packet->size = bytes_left - keypair->auth_tag_length;
return HandleAuthenticatedDataPacket_WillUnlock(keypair, packet);
return HandleAuthenticatedDataPacket_WillUnlock(keypair, packet, bytes_left - keypair->auth_tag_length);
getout_unlock:
WG_RELEASE_LOCK(keypair->peer->mutex_);
getout:
@ -840,7 +834,7 @@ void WireguardProcessor::NotifyHandshakeComplete() {
procdel_->OnConnected();
}
WireguardProcessor::PacketResult WireguardProcessor::HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *keypair, Packet *packet) {
WireguardProcessor::PacketResult WireguardProcessor::HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *keypair, Packet *packet, uint data_size) {
WgPeer *peer = keypair->peer;
assert(peer->IsPeerLocked());
assert(packet->addr.sin.sin_family != 0);
@ -865,7 +859,7 @@ WireguardProcessor::PacketResult WireguardProcessor::HandleAuthenticatedDataPack
}
}
WG_EXTENSION_HOOKS::OnPeerIncomingUdp(peer, packet);
WG_EXTENSION_HOOKS::OnPeerIncomingUdp(peer, packet, data_size);
// Remember how many incoming packets we've seen so we can approximate loss
keypair->incoming_packet_count++;
@ -886,11 +880,12 @@ WireguardProcessor::PacketResult WireguardProcessor::HandleAuthenticatedDataPack
peer->ScheduleNewHandshake();
}
uint32 data_size = packet->size;
if (data_size == 0) {
peer->OnKeepaliveReceived();
WG_RELEASE_LOCK(peer->mutex_);
goto getout;
stats_.packets_in++;
stats_.total_bytes_in += packet->size;
return kPacketResult_Free;
}
peer->OnDataReceived();
WG_RELEASE_LOCK(peer->mutex_);
@ -899,7 +894,7 @@ WireguardProcessor::PacketResult WireguardProcessor::HandleAuthenticatedDataPack
if (WITH_PACKET_COMPRESSION && keypair->compress_handler_) {
WgCompressHandler::CompressState st = keypair->compress_handler_->Decompress(packet);
if (st == WgCompressHandler::COMPRESS_FAIL)
goto getout;
goto getout_error_header;
if (st == WgCompressHandler::COMPRESS_YES)
stats_.compression_hdr_saved_in += (int32)(packet->size - exch(data_size, packet->size));
}
@ -943,13 +938,18 @@ WireguardProcessor::PacketResult WireguardProcessor::HandleAuthenticatedDataPack
if (size_from_header > data_size)
goto getout_error_header;
stats_.packets_in++;
stats_.data_bytes_in += size_from_header;
stats_.total_bytes_in += packet->size;
packet->size = size_from_header;
return kPacketResult_ForwardTun;
getout_error_header:
stats_.error_header++;
getout:
stats_.invalid_packets_in++;
stats_.invalid_bytes_in += packet->size;
return kPacketResult_Free;
}
@ -963,12 +963,14 @@ WireguardProcessor::PacketResult WireguardProcessor::HandleDataPacket(Packet *pa
WgKeypair *keypair = dev_.LookupKeypairByKeyId(key_id);
if (keypair == NULL || counter >= REJECT_AFTER_MESSAGES) {
stats_.error_key_id++;
getout:
getout:
stats_.invalid_packets_in++;
stats_.invalid_bytes_in += data_size;
return kPacketResult_Free;
}
packet->data = data + sizeof(MessageData);
packet->size = data_size - sizeof(MessageData) - keypair->auth_tag_length;
uint32 data_size_after = data_size - sizeof(MessageData) - keypair->auth_tag_length;
if (!WgKeypairDecryptPayload(data + sizeof(MessageData), data_size - sizeof(MessageData),
NULL, 0, counter, keypair)) {
@ -988,7 +990,7 @@ getout:
goto getout;
} else {
assert(!keypair->peer->marked_for_delete_);
return HandleAuthenticatedDataPacket_WillUnlock(keypair, packet);
return HandleAuthenticatedDataPacket_WillUnlock(keypair, packet, data_size_after);
}
}
@ -1003,8 +1005,12 @@ static uint64 GetIpForRateLimit(Packet *packet) {
WireguardProcessor::PacketResult WireguardProcessor::CheckIncomingHandshakeRateLimit(Packet *packet, bool overload) {
assert(dev_.IsMainThread());
WgRateLimit::RateLimitResult rr = dev_.rate_limiter()->CheckRateLimit(GetIpForRateLimit(packet));
if ((overload && rr.is_rate_limited()) || !dev_.CheckCookieMac1(packet))
if ((overload && rr.is_rate_limited()) || !dev_.CheckCookieMac1(packet)) {
stats_.invalid_packets_in++;
stats_.invalid_bytes_in += packet->size;
return kPacketResult_Free;
}
dev_.rate_limiter()->CommitResult(rr);
if (overload && !rr.is_first_ip() && !dev_.CheckCookieMac2(packet)) {
@ -1021,11 +1027,20 @@ WireguardProcessor::PacketResult WireguardProcessor::CheckIncomingHandshakeRateL
// server receives this when client wants to setup a session
WireguardProcessor::PacketResult WireguardProcessor::HandleHandshakeInitiationPacket(Packet *packet) {
assert(dev_.IsMainThread());
uint original_size = packet->size;
WgPeer *peer = WgPeer::ParseMessageHandshakeInitiation(&dev_, packet);
if (peer) {
PrepareOutgoingHandshakePacket(peer, packet);
stats_.packets_in++;
stats_.packets_out++;
stats_.total_bytes_in += original_size;
stats_.total_bytes_out += packet->size;
return kPacketResult_ForwardUdp;
} else {
stats_.invalid_packets_in++;
stats_.invalid_bytes_in += original_size;
return kPacketResult_Free;
}
}
@ -1033,14 +1048,21 @@ WireguardProcessor::PacketResult WireguardProcessor::HandleHandshakeInitiationPa
// client receives this after session is established
WireguardProcessor::PacketResult WireguardProcessor::HandleHandshakeResponsePacket(Packet *packet) {
assert(dev_.IsMainThread());
uint original_size = packet->size;
WgPeer *peer = WgPeer::ParseMessageHandshakeResponse(&dev_, packet);
if (peer) {
stats_.packets_in++;
stats_.total_bytes_in += original_size;
stats_.handshakes_out_success++;
WG_SCOPED_LOCK(peer->mutex_);
peer->OnHandshakeAuthComplete();
peer->OnHandshakeFullyComplete();
NotifyHandshakeComplete();
SendKeepalive_Locked(peer);
} else {
stats_.invalid_packets_in++;
stats_.invalid_bytes_in += original_size;
}
return kPacketResult_Free;
}
@ -1093,19 +1115,16 @@ void WireguardProcessor::SecondLoop() {
assert(dev_.IsMainThread());
uint64 now = OsGetMilliseconds();
uint64 bytes_in = stats_.tun_bytes_in - stats_last_bytes_in_;
uint64 bytes_out = stats_.tun_bytes_out - stats_last_bytes_out_;
stats_last_bytes_in_ = stats_.tun_bytes_in;
stats_last_bytes_out_ = stats_.tun_bytes_out;
uint64 bytes_out = stats_.data_bytes_out - exch(stats_last_bytes_out_, stats_.data_bytes_out);
uint64 bytes_in = stats_.data_bytes_in - exch(stats_last_bytes_in_, stats_.data_bytes_in);
uint64 millis = now - stats_last_ts_;
stats_last_ts_ = now;
double f = 1000.0 / std::max<uint32>((uint32)millis, 500);
stats_.tun_bytes_in_per_second = (float)(bytes_in * f);
stats_.tun_bytes_out_per_second = (float)(bytes_out * f);
stats_.data_bytes_out_per_second = (float)(bytes_out * f);
stats_.data_bytes_in_per_second = (float)(bytes_in * f);
for (WgPeer *peer = dev_.first_peer(); peer; peer = peer->next_peer_) {
WgKeypair *keypair = peer->curr_keypair_;

View file

@ -7,14 +7,18 @@
// todo: for multithreaded use case need to use atomic ops.
struct WgProcessorStats {
// Number of bytes sent/received over the physical UDP connection
uint64 udp_bytes_in, udp_bytes_out;
uint64 udp_packets_in, udp_packets_out;
// The amount of authenticated data received over the wireguard connection.
uint64 packets_in, data_bytes_in, total_bytes_in;
// Number of valid packets sent/received over the TUN interface
uint64 tun_bytes_in, tun_bytes_out;
uint64 tun_packets_in, tun_packets_out;
// The amount of authenticated data sent across the wireguard connection.
// |data_bytes_out| holds the actual bytes, while |total_bytes_out|
// includes wireguard overhead.
uint64 packets_out, data_bytes_out, total_bytes_out;
// The amount of invalid data received from the network
uint64 invalid_packets_in, invalid_bytes_in;
// Error types
uint32 error_key_id;
uint32 error_mac;
@ -22,8 +26,8 @@ struct WgProcessorStats {
uint32 error_source_addr;
uint32 error_header;
// Current speed of TUN packets
float tun_bytes_in_per_second, tun_bytes_out_per_second;
// Current speed
float data_bytes_out_per_second, data_bytes_in_per_second;
// Timestamp of handshakes
uint64 first_complete_handshake_timestamp;
@ -143,7 +147,7 @@ private:
PacketResult HandleHandshakeCookiePacket(Packet *packet);
PacketResult HandleDataPacket(Packet *packet);
PacketResult HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *keypair, Packet *packet);
PacketResult HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *keypair, Packet *packet, uint data_size);
PacketResult HandleShortHeaderFormatPacket(uint32 tag, Packet *packet);
PacketResult CheckIncomingHandshakeRateLimit(Packet *packet, bool overload);
bool HandleIcmpv6NeighborSolicitation(const byte *data, size_t data_size);

View file

@ -794,7 +794,7 @@ WgPeer *WgPeer::ParseMessageHandshakeResponse(WgDevice *dev, const Packet *packe
peer->data_endpoint_ = peer->endpoint_;
}
WG_EXTENSION_HOOKS::OnPeerIncomingUdp(peer, packet);
WG_EXTENSION_HOOKS::OnPeerIncomingUdp(peer, packet, packet->size);
peer->rx_bytes_ += packet->size;
peer->InsertKeypairInPeer_Locked(keypair);

View file

@ -819,7 +819,7 @@ bool WgKeypairDecryptPayload(uint8 *dst, const size_t src_len,
struct WgExtensionHooksDefault {
static uint32 GetIpv4Target(Packet *packet, uint8 *data) { return ReadBE32(data + 16); }
static void OnPeerIncomingUdp(WgPeer *peer, const Packet *packet) { }
static void OnPeerIncomingUdp(WgPeer *peer, const Packet *packet, uint data_size) { }
static void OnPeerOutgoingUdp(WgPeer *peer, Packet *packet) { }
static bool DisableSourceAddressVerification(WgPeer *peer) { return false; }
};