blob: 785f8ce43cd62964b140555b65c226530ebb31cc [file] [log] [blame]
Hugo Benichi7b314e12018-01-15 21:54:00 +09001/*
2 * Copyright (C) 2018 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#ifndef TCP_SOCKET_MONITOR_H
18#define TCP_SOCKET_MONITOR_H
19
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090020#include <chrono>
21#include <condition_variable>
22#include <mutex>
Hugo Benichi8c397672018-01-22 22:06:15 +090023#include <thread>
Hugo Benichi4596d2f2018-01-19 13:36:29 +090024#include <unordered_map>
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090025
26#include <android-base/thread_annotations.h>
Luke Huangb257d612019-03-14 21:19:13 +080027#include "netdutils/DumpWriter.h"
Hugo Benichi7b314e12018-01-15 21:54:00 +090028#include "utils/String16.h"
29
Hugo Benichi4596d2f2018-01-19 13:36:29 +090030#include "Fwmark.h"
31
Hugo Benichi8c397672018-01-22 22:06:15 +090032struct inet_diag_msg;
33struct tcp_info;
34
Hugo Benichi7b314e12018-01-15 21:54:00 +090035namespace android {
36namespace net {
37
Hugo Benichi4596d2f2018-01-19 13:36:29 +090038using std::chrono::milliseconds;
39
Hugo Benichi7b314e12018-01-15 21:54:00 +090040class TcpSocketMonitor {
41 public:
Hugo Benichi4596d2f2018-01-19 13:36:29 +090042 using time_point = std::chrono::time_point<std::chrono::steady_clock>;
43
Hugo Benichi7b314e12018-01-15 21:54:00 +090044 static const String16 DUMP_KEYWORD;
Hugo Benichi4596d2f2018-01-19 13:36:29 +090045 static const milliseconds kDefaultPollingInterval;
46
47 // A subset of fields found in struct inet_diag_msg and struct tcp_info.
48 struct TcpStats {
49 // Number of packets sent. Tracks struct tcp_sock data_segs_out.
50 // Not available on 3.18 kernels.
51 uint32_t sent;
52 // Number of packets lost. Tracks struct tcp_sock lost_out.
53 uint32_t lost;
54 // Smoothed round trip time. Tracks struct tcp_sock srtt_us.
55 uint32_t rttUs;
56 // Milliseconds difference between the last packet sent and last ack received.
57 int32_t sentAckDiffMs;
58 // Number of socket stats aggregated in this TcpStats entry.
59 int32_t nSockets;
60 };
61
62 // Socket metadata used for computing TcpStats diff across sock_diag dumps.
63 struct SocketEntry {
64 // Number of packets sent. Tracks struct tcp_sock data_segs_out.
65 // Not available on 3.18 kernels.
66 uint32_t sent;
67 // Number of packets lost. Tracks struct tcp_sock lost_out.
68 uint32_t lost;
69 // Last update timestamp for that socket.
70 time_point lastUpdate;
71 // Socket mark.
72 Fwmark mark;
73 // The uid owning the socket.
74 uint32_t uid;
75 };
Hugo Benichi7b314e12018-01-15 21:54:00 +090076
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090077 TcpSocketMonitor();
78 ~TcpSocketMonitor();
Hugo Benichi7b314e12018-01-15 21:54:00 +090079
Luke Huangb257d612019-03-14 21:19:13 +080080 void dump(netdutils::DumpWriter& dw);
Hugo Benichi4596d2f2018-01-19 13:36:29 +090081 void setPollingInterval(milliseconds duration);
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090082 void resumePolling();
83 void suspendPolling();
Hugo Benichi7b314e12018-01-15 21:54:00 +090084
85 private:
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090086 void poll();
87 void waitForNextPoll();
88 bool isRunning();
Hugo Benichi4596d2f2018-01-19 13:36:29 +090089 void updateSocketStats(time_point now, Fwmark mark, const struct inet_diag_msg *sockinfo,
90 const struct tcp_info *tcpinfo, uint32_t tcpinfoLen) REQUIRES(mLock);
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090091
92 // Lock guarding all reads and writes to member variables.
93 std::mutex mLock;
94 // Used by the polling thread for sleeping between poll operations.
95 std::condition_variable mCv;
Erik Klineb31fd692018-06-06 20:50:11 +090096 // The thread that polls sock_diag continuously.
Hugo Benichi4596d2f2018-01-19 13:36:29 +090097 std::thread mPollingThread;
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090098 // The duration of a sleep between polls. Can be updated by the instance owner for dynamically
99 // adjusting the polling rate.
Hugo Benichi4596d2f2018-01-19 13:36:29 +0900100 milliseconds mNextSleepDurationMs GUARDED_BY(mLock);
Hugo Benichia9e3c5d2018-01-18 10:33:22 +0900101 // The time of the last successful poll operation.
Hugo Benichi4596d2f2018-01-19 13:36:29 +0900102 time_point mLastPoll GUARDED_BY(mLock);
Hugo Benichia9e3c5d2018-01-18 10:33:22 +0900103 // True if the polling thread should sleep until notified.
104 bool mIsSuspended GUARDED_BY(mLock);
105 // True while the polling thread should poll.
106 bool mIsRunning GUARDED_BY(mLock);
Hugo Benichi4596d2f2018-01-19 13:36:29 +0900107 // Map of SocketEntry structs keyed by socket cookie. This map tracks per-socket data needed for
Erik Klineb31fd692018-06-06 20:50:11 +0900108 // computing diffs between sock_diag dumps. Entries for closed sockets are continuously cleaned
Hugo Benichi4596d2f2018-01-19 13:36:29 +0900109 // after every dump operation based on timestamps of last updates.
110 std::unordered_map<uint64_t, SocketEntry> mSocketEntries GUARDED_BY(mLock);
111 // Map of TcpStats entries aggregated per network and keyed per network id.
112 // This map tracks per-network data for a single sock_diag dump and is cleared before every dump
113 // operation.
114 std::unordered_map<uint32_t, TcpStats> mNetworkStats GUARDED_BY(mLock);
Hugo Benichi7b314e12018-01-15 21:54:00 +0900115};
116
117} // namespace net
118} // namespace android
119
120#endif /* TCP_SOCKET_MONITOR_H */