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