-
Notifications
You must be signed in to change notification settings - Fork 0
/
DnsStats.h
139 lines (104 loc) · 4.46 KB
/
DnsStats.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#pragma once
#include <chrono>
#include <deque>
#include <map>
#include <vector>
#include <android-base/thread_annotations.h>
#include <netdutils/DumpWriter.h>
#include <netdutils/InternetAddresses.h>
#include "ResolverStats.h"
#include "stats.pb.h"
namespace android::net {
// The overall information of a StatsRecords.
struct StatsData {
StatsData(const netdutils::IPSockAddr& ipSockAddr) : sockAddr(ipSockAddr) {
lastUpdate = std::chrono::steady_clock::now();
};
// Socket address.
netdutils::IPSockAddr sockAddr;
// The most recent number of records being accumulated.
int total = 0;
// The map used to store the number of each rcode.
std::map<int, int> rcodeCounts;
// The aggregated RTT in microseconds.
// For DNS-over-TCP, it includes TCP handshake.
// For DNS-over-TLS, it might include TCP handshake plus SSL handshake.
std::chrono::microseconds latencyUs = {};
// The last update timestamp.
std::chrono::time_point<std::chrono::steady_clock> lastUpdate;
int averageLatencyMs() const;
std::string toString() const;
// For testing.
bool operator==(const StatsData& o) const;
friend std::ostream& operator<<(std::ostream& os, const StatsData& data) {
return os << data.toString();
}
};
// A circular buffer based class used to store the statistics for a server with a protocol.
class StatsRecords {
public:
struct Record {
int rcode = 0; // NS_R_NO_ERROR
int linux_errno = 0; // SYS_NO_ERROR
std::chrono::microseconds latencyUs;
};
StatsRecords(const netdutils::IPSockAddr& ipSockAddr, size_t size);
void push(const Record& record);
const StatsData& getStatsData() const { return mStatsData; }
// Quantifies the quality based on the current quality factors and the latency, and normalize
// the value to a score between 0 to 100.
double score() const;
void incrementSkippedCount();
private:
void updateStatsData(const Record& record, const bool add);
void updatePenalty(const Record& record);
std::deque<Record> mRecords;
size_t mCapacity;
StatsData mStatsData;
// A quality factor used to distinguish if the server can't be evaluated by latency alone, such
// as instant failure on connect.
int mPenalty = 0;
// A quality factor used to prevent starvation.
int mSkippedCount = 0;
// The maximum of the quantified result. As the sorting is on the basis of server latency, limit
// the maximal value of the quantity to 10000 in correspondence with the maximal cleartext
// query timeout 10000 milliseconds. This helps normalize the value of the quality to a score.
static constexpr int kMaxQuality = 10000;
};
// DnsStats class manages the statistics of DNS servers or MDNS multicast addresses per netId.
// The class itself is not thread-safe.
class DnsStats {
public:
using StatsMap = std::map<netdutils::IPSockAddr, StatsRecords>;
// Add |addrs| to the map, and remove no-longer-used addresses.
// Return true if they are successfully added; otherwise, return false.
bool setAddrs(const std::vector<netdutils::IPSockAddr>& addrs, Protocol protocol);
// Return true if |record| is successfully added into |server|'s stats; otherwise, return false.
bool addStats(const netdutils::IPSockAddr& server, const DnsQueryEvent& record);
std::vector<netdutils::IPSockAddr> getSortedServers(Protocol protocol) const;
// Returns the average query latency in microseconds.
std::optional<std::chrono::microseconds> getAverageLatencyUs(Protocol protocol) const;
void dump(netdutils::DumpWriter& dw);
std::vector<StatsData> getStats(Protocol protocol) const;
// TODO: Compatible support for getResolverInfo().
static constexpr size_t kLogSize = 128;
private:
std::map<Protocol, StatsMap> mStats;
};
} // namespace android::net