blob: 43c2c04a18d5c1be030c6904c20faad04f159b28 [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>
Hugo Benichi7b314e12018-01-15 21:54:00 +090027#include "utils/String16.h"
28
Hugo Benichi4596d2f2018-01-19 13:36:29 +090029#include "Fwmark.h"
30
Hugo Benichi8c397672018-01-22 22:06:15 +090031struct inet_diag_msg;
32struct tcp_info;
33
Hugo Benichi7b314e12018-01-15 21:54:00 +090034namespace android {
35namespace net {
36
Hugo Benichi4596d2f2018-01-19 13:36:29 +090037using std::chrono::milliseconds;
38
Hugo Benichi7b314e12018-01-15 21:54:00 +090039class DumpWriter;
40
41class TcpSocketMonitor {
42 public:
Hugo Benichi4596d2f2018-01-19 13:36:29 +090043 using time_point = std::chrono::time_point<std::chrono::steady_clock>;
44
Hugo Benichi7b314e12018-01-15 21:54:00 +090045 static const String16 DUMP_KEYWORD;
Hugo Benichi4596d2f2018-01-19 13:36:29 +090046 static const milliseconds kDefaultPollingInterval;
47
48 // A subset of fields found in struct inet_diag_msg and struct tcp_info.
49 struct TcpStats {
50 // Number of packets sent. Tracks struct tcp_sock data_segs_out.
51 // Not available on 3.18 kernels.
52 uint32_t sent;
53 // Number of packets lost. Tracks struct tcp_sock lost_out.
54 uint32_t lost;
55 // Smoothed round trip time. Tracks struct tcp_sock srtt_us.
56 uint32_t rttUs;
57 // Milliseconds difference between the last packet sent and last ack received.
58 int32_t sentAckDiffMs;
59 // Number of socket stats aggregated in this TcpStats entry.
60 int32_t nSockets;
61 };
62
63 // Socket metadata used for computing TcpStats diff across sock_diag dumps.
64 struct SocketEntry {
65 // Number of packets sent. Tracks struct tcp_sock data_segs_out.
66 // Not available on 3.18 kernels.
67 uint32_t sent;
68 // Number of packets lost. Tracks struct tcp_sock lost_out.
69 uint32_t lost;
70 // Last update timestamp for that socket.
71 time_point lastUpdate;
72 // Socket mark.
73 Fwmark mark;
74 // The uid owning the socket.
75 uint32_t uid;
76 };
Hugo Benichi7b314e12018-01-15 21:54:00 +090077
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090078 TcpSocketMonitor();
79 ~TcpSocketMonitor();
Hugo Benichi7b314e12018-01-15 21:54:00 +090080
81 void dump(DumpWriter& dw);
Hugo Benichi4596d2f2018-01-19 13:36:29 +090082 void setPollingInterval(milliseconds duration);
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090083 void resumePolling();
84 void suspendPolling();
Hugo Benichi7b314e12018-01-15 21:54:00 +090085
86 private:
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090087 void poll();
88 void waitForNextPoll();
89 bool isRunning();
Hugo Benichi4596d2f2018-01-19 13:36:29 +090090 void updateSocketStats(time_point now, Fwmark mark, const struct inet_diag_msg *sockinfo,
91 const struct tcp_info *tcpinfo, uint32_t tcpinfoLen) REQUIRES(mLock);
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090092
93 // Lock guarding all reads and writes to member variables.
94 std::mutex mLock;
95 // Used by the polling thread for sleeping between poll operations.
96 std::condition_variable mCv;
Erik Klineb31fd692018-06-06 20:50:11 +090097 // The thread that polls sock_diag continuously.
Hugo Benichi4596d2f2018-01-19 13:36:29 +090098 std::thread mPollingThread;
Hugo Benichia9e3c5d2018-01-18 10:33:22 +090099 // The duration of a sleep between polls. Can be updated by the instance owner for dynamically
100 // adjusting the polling rate.
Hugo Benichi4596d2f2018-01-19 13:36:29 +0900101 milliseconds mNextSleepDurationMs GUARDED_BY(mLock);
Hugo Benichia9e3c5d2018-01-18 10:33:22 +0900102 // The time of the last successful poll operation.
Hugo Benichi4596d2f2018-01-19 13:36:29 +0900103 time_point mLastPoll GUARDED_BY(mLock);
Hugo Benichia9e3c5d2018-01-18 10:33:22 +0900104 // True if the polling thread should sleep until notified.
105 bool mIsSuspended GUARDED_BY(mLock);
106 // True while the polling thread should poll.
107 bool mIsRunning GUARDED_BY(mLock);
Hugo Benichi4596d2f2018-01-19 13:36:29 +0900108 // Map of SocketEntry structs keyed by socket cookie. This map tracks per-socket data needed for
Erik Klineb31fd692018-06-06 20:50:11 +0900109 // computing diffs between sock_diag dumps. Entries for closed sockets are continuously cleaned
Hugo Benichi4596d2f2018-01-19 13:36:29 +0900110 // after every dump operation based on timestamps of last updates.
111 std::unordered_map<uint64_t, SocketEntry> mSocketEntries GUARDED_BY(mLock);
112 // Map of TcpStats entries aggregated per network and keyed per network id.
113 // This map tracks per-network data for a single sock_diag dump and is cleared before every dump
114 // operation.
115 std::unordered_map<uint32_t, TcpStats> mNetworkStats GUARDED_BY(mLock);
Hugo Benichi7b314e12018-01-15 21:54:00 +0900116};
117
118} // namespace net
119} // namespace android
120
121#endif /* TCP_SOCKET_MONITOR_H */