1 /* 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 32 namespace android::net { 33 34 // The overall information of a StatsRecords. 35 struct StatsData { StatsDataStatsData36 StatsData(const netdutils::IPSockAddr& ipSockAddr) : serverSockAddr(ipSockAddr) { 37 lastUpdate = std::chrono::steady_clock::now(); 38 }; 39 40 // Server socket address. 41 netdutils::IPSockAddr serverSockAddr; 42 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 57 std::string toString() const; 58 59 // For testing. 60 bool operator==(const StatsData& o) const; 61 friend std::ostream& operator<<(std::ostream& os, const StatsData& data) { 62 return os << data.toString(); 63 } 64 }; 65 66 // A circular buffer based class used to store the statistics for a server with a protocol. 67 class StatsRecords { 68 public: 69 struct Record { 70 int rcode; 71 std::chrono::microseconds latencyUs; 72 }; 73 74 StatsRecords(const netdutils::IPSockAddr& ipSockAddr, size_t size); 75 76 void push(const Record& record); 77 getStatsData()78 const StatsData& getStatsData() const { return mStatsData; } 79 80 private: 81 void updateStatsData(const Record& record, const bool add); 82 83 std::deque<Record> mRecords; 84 size_t mCapacity; 85 StatsData mStatsData; 86 }; 87 88 // DnsStats class manages the statistics of DNS servers per netId. 89 // The class itself is not thread-safe. 90 class DnsStats { 91 public: 92 using ServerStatsMap = std::map<netdutils::IPSockAddr, StatsRecords>; 93 94 // Add |servers| to the map, and remove no-longer-used servers. 95 // Return true if they are successfully added; otherwise, return false. 96 bool setServers(const std::vector<netdutils::IPSockAddr>& servers, Protocol protocol); 97 98 // Return true if |record| is successfully added into |server|'s stats; otherwise, return false. 99 bool addStats(const netdutils::IPSockAddr& server, const DnsQueryEvent& record); 100 101 void dump(netdutils::DumpWriter& dw); 102 103 // For testing. 104 std::vector<StatsData> getStats(Protocol protocol) const; 105 106 // TODO: Compatible support for getResolverInfo(). 107 // TODO: Support getSortedServers(). 108 109 static constexpr size_t kLogSize = 128; 110 111 private: 112 std::map<Protocol, ServerStatsMap> mStats; 113 }; 114 115 } // namespace android::net 116