1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker *
4*8542734aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker *
8*8542734aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker *
10*8542734aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker */
16*8542734aSAndroid Build Coastguard Worker
17*8542734aSAndroid Build Coastguard Worker #define LOG_TAG "TcpSocketMonitor"
18*8542734aSAndroid Build Coastguard Worker
19*8542734aSAndroid Build Coastguard Worker #include <chrono>
20*8542734aSAndroid Build Coastguard Worker #include <cinttypes>
21*8542734aSAndroid Build Coastguard Worker #include <thread>
22*8542734aSAndroid Build Coastguard Worker #include <vector>
23*8542734aSAndroid Build Coastguard Worker
24*8542734aSAndroid Build Coastguard Worker #include <arpa/inet.h>
25*8542734aSAndroid Build Coastguard Worker #include <netinet/tcp.h>
26*8542734aSAndroid Build Coastguard Worker #include <linux/tcp.h>
27*8542734aSAndroid Build Coastguard Worker
28*8542734aSAndroid Build Coastguard Worker #include "Controllers.h"
29*8542734aSAndroid Build Coastguard Worker #include "SockDiag.h"
30*8542734aSAndroid Build Coastguard Worker #include "TcpSocketMonitor.h"
31*8542734aSAndroid Build Coastguard Worker #include "netdutils/DumpWriter.h"
32*8542734aSAndroid Build Coastguard Worker
33*8542734aSAndroid Build Coastguard Worker using android::netdutils::DumpWriter;
34*8542734aSAndroid Build Coastguard Worker using android::netdutils::ScopedIndent;
35*8542734aSAndroid Build Coastguard Worker
36*8542734aSAndroid Build Coastguard Worker namespace android {
37*8542734aSAndroid Build Coastguard Worker namespace net {
38*8542734aSAndroid Build Coastguard Worker
39*8542734aSAndroid Build Coastguard Worker using std::chrono::duration_cast;
40*8542734aSAndroid Build Coastguard Worker using std::chrono::steady_clock;
41*8542734aSAndroid Build Coastguard Worker
getTcpStateName(int t)42*8542734aSAndroid Build Coastguard Worker constexpr const char* getTcpStateName(int t) {
43*8542734aSAndroid Build Coastguard Worker switch (t) {
44*8542734aSAndroid Build Coastguard Worker case TCP_ESTABLISHED:
45*8542734aSAndroid Build Coastguard Worker return "ESTABLISHED";
46*8542734aSAndroid Build Coastguard Worker case TCP_SYN_SENT:
47*8542734aSAndroid Build Coastguard Worker return "SYN-SENT";
48*8542734aSAndroid Build Coastguard Worker case TCP_SYN_RECV:
49*8542734aSAndroid Build Coastguard Worker return "SYN-RECV";
50*8542734aSAndroid Build Coastguard Worker case TCP_FIN_WAIT1:
51*8542734aSAndroid Build Coastguard Worker return "FIN-WAIT-1";
52*8542734aSAndroid Build Coastguard Worker case TCP_FIN_WAIT2:
53*8542734aSAndroid Build Coastguard Worker return "FIN-WAIT-2";
54*8542734aSAndroid Build Coastguard Worker case TCP_TIME_WAIT:
55*8542734aSAndroid Build Coastguard Worker return "TIME-WAIT";
56*8542734aSAndroid Build Coastguard Worker case TCP_CLOSE:
57*8542734aSAndroid Build Coastguard Worker return "CLOSE";
58*8542734aSAndroid Build Coastguard Worker case TCP_CLOSE_WAIT:
59*8542734aSAndroid Build Coastguard Worker return "CLOSE-WAIT";
60*8542734aSAndroid Build Coastguard Worker case TCP_LAST_ACK:
61*8542734aSAndroid Build Coastguard Worker return "LAST-ACK";
62*8542734aSAndroid Build Coastguard Worker case TCP_LISTEN:
63*8542734aSAndroid Build Coastguard Worker return "LISTEN";
64*8542734aSAndroid Build Coastguard Worker case TCP_CLOSING:
65*8542734aSAndroid Build Coastguard Worker return "CLOSING";
66*8542734aSAndroid Build Coastguard Worker default:
67*8542734aSAndroid Build Coastguard Worker return "UNKNOWN";
68*8542734aSAndroid Build Coastguard Worker }
69*8542734aSAndroid Build Coastguard Worker }
70*8542734aSAndroid Build Coastguard Worker
71*8542734aSAndroid Build Coastguard Worker // Helper macro for reading fields into struct tcp_info and handling different struct tcp_info
72*8542734aSAndroid Build Coastguard Worker // versions in the kernel.
73*8542734aSAndroid Build Coastguard Worker #define TCPINFO_GET(ptr, fld, len, zero) \
74*8542734aSAndroid Build Coastguard Worker (((ptr) != nullptr && (offsetof(struct tcp_info, fld) + sizeof((ptr)->fld)) < (len)) \
75*8542734aSAndroid Build Coastguard Worker ? (ptr)->fld \
76*8542734aSAndroid Build Coastguard Worker : (zero))
77*8542734aSAndroid Build Coastguard Worker
tcpInfoPrint(DumpWriter & dw,Fwmark mark,const struct inet_diag_msg * sockinfo,const struct tcp_info * tcpinfo,uint32_t tcpinfoLen)78*8542734aSAndroid Build Coastguard Worker static void tcpInfoPrint(DumpWriter &dw, Fwmark mark, const struct inet_diag_msg *sockinfo,
79*8542734aSAndroid Build Coastguard Worker const struct tcp_info *tcpinfo, uint32_t tcpinfoLen) {
80*8542734aSAndroid Build Coastguard Worker char saddr[INET6_ADDRSTRLEN] = {};
81*8542734aSAndroid Build Coastguard Worker char daddr[INET6_ADDRSTRLEN] = {};
82*8542734aSAndroid Build Coastguard Worker inet_ntop(sockinfo->idiag_family, &(sockinfo->id.idiag_src), saddr, sizeof(saddr));
83*8542734aSAndroid Build Coastguard Worker inet_ntop(sockinfo->idiag_family, &(sockinfo->id.idiag_dst), daddr, sizeof(daddr));
84*8542734aSAndroid Build Coastguard Worker
85*8542734aSAndroid Build Coastguard Worker dw.println(
86*8542734aSAndroid Build Coastguard Worker "netId=%d uid=%u mark=0x%x saddr=%s daddr=%s sport=%u dport=%u tcp_state=%s(%u) "
87*8542734aSAndroid Build Coastguard Worker "rtt=%gms sent=%u lost=%u",
88*8542734aSAndroid Build Coastguard Worker mark.netId,
89*8542734aSAndroid Build Coastguard Worker sockinfo->idiag_uid,
90*8542734aSAndroid Build Coastguard Worker mark.intValue,
91*8542734aSAndroid Build Coastguard Worker saddr,
92*8542734aSAndroid Build Coastguard Worker daddr,
93*8542734aSAndroid Build Coastguard Worker ntohs(sockinfo->id.idiag_sport),
94*8542734aSAndroid Build Coastguard Worker ntohs(sockinfo->id.idiag_dport),
95*8542734aSAndroid Build Coastguard Worker getTcpStateName(sockinfo->idiag_state), sockinfo->idiag_state,
96*8542734aSAndroid Build Coastguard Worker TCPINFO_GET(tcpinfo, tcpi_rtt, tcpinfoLen, 0) / 1000.0,
97*8542734aSAndroid Build Coastguard Worker TCPINFO_GET(tcpinfo, tcpi_segs_out, tcpinfoLen, 0),
98*8542734aSAndroid Build Coastguard Worker TCPINFO_GET(tcpinfo, tcpi_lost, tcpinfoLen, 0));
99*8542734aSAndroid Build Coastguard Worker }
100*8542734aSAndroid Build Coastguard Worker
101*8542734aSAndroid Build Coastguard Worker const String16 TcpSocketMonitor::DUMP_KEYWORD = String16("tcp_socket_info");
102*8542734aSAndroid Build Coastguard Worker const milliseconds TcpSocketMonitor::kDefaultPollingInterval = milliseconds(30000);
103*8542734aSAndroid Build Coastguard Worker
dump(DumpWriter & dw)104*8542734aSAndroid Build Coastguard Worker void TcpSocketMonitor::dump(DumpWriter& dw) {
105*8542734aSAndroid Build Coastguard Worker std::lock_guard guard(mLock);
106*8542734aSAndroid Build Coastguard Worker
107*8542734aSAndroid Build Coastguard Worker dw.println("TcpSocketMonitor");
108*8542734aSAndroid Build Coastguard Worker ScopedIndent tcpSocketMonitorDetails(dw);
109*8542734aSAndroid Build Coastguard Worker
110*8542734aSAndroid Build Coastguard Worker const auto now = steady_clock::now();
111*8542734aSAndroid Build Coastguard Worker const auto d = duration_cast<milliseconds>(now - mLastPoll);
112*8542734aSAndroid Build Coastguard Worker dw.println("running=%d, suspended=%d, last poll %lld ms ago",
113*8542734aSAndroid Build Coastguard Worker mIsRunning, mIsSuspended, d.count());
114*8542734aSAndroid Build Coastguard Worker
115*8542734aSAndroid Build Coastguard Worker if (!mNetworkStats.empty()) {
116*8542734aSAndroid Build Coastguard Worker dw.blankline();
117*8542734aSAndroid Build Coastguard Worker dw.println("Network stats:");
118*8542734aSAndroid Build Coastguard Worker for (const std::pair<const uint32_t, TcpStats>& stats : mNetworkStats) {
119*8542734aSAndroid Build Coastguard Worker if (stats.second.nSockets == 0) {
120*8542734aSAndroid Build Coastguard Worker continue;
121*8542734aSAndroid Build Coastguard Worker }
122*8542734aSAndroid Build Coastguard Worker dw.println("netId=%d sent=%d lost=%d rttMs=%gms sentAckDiff=%dms",
123*8542734aSAndroid Build Coastguard Worker stats.first,
124*8542734aSAndroid Build Coastguard Worker stats.second.sent,
125*8542734aSAndroid Build Coastguard Worker stats.second.lost,
126*8542734aSAndroid Build Coastguard Worker stats.second.rttUs / 1000.0 / stats.second.nSockets,
127*8542734aSAndroid Build Coastguard Worker stats.second.sentAckDiffMs / stats.second.nSockets);
128*8542734aSAndroid Build Coastguard Worker }
129*8542734aSAndroid Build Coastguard Worker }
130*8542734aSAndroid Build Coastguard Worker
131*8542734aSAndroid Build Coastguard Worker if (!mSocketEntries.empty()) {
132*8542734aSAndroid Build Coastguard Worker dw.blankline();
133*8542734aSAndroid Build Coastguard Worker dw.println("Socket entries:");
134*8542734aSAndroid Build Coastguard Worker for (const std::pair<const uint64_t, SocketEntry>& stats : mSocketEntries) {
135*8542734aSAndroid Build Coastguard Worker dw.println("netId=%u uid=%u cookie=%" PRIu64, stats.second.mark.netId, stats.second.uid,
136*8542734aSAndroid Build Coastguard Worker stats.first);
137*8542734aSAndroid Build Coastguard Worker }
138*8542734aSAndroid Build Coastguard Worker }
139*8542734aSAndroid Build Coastguard Worker
140*8542734aSAndroid Build Coastguard Worker SockDiag sd;
141*8542734aSAndroid Build Coastguard Worker if (sd.open()) {
142*8542734aSAndroid Build Coastguard Worker dw.blankline();
143*8542734aSAndroid Build Coastguard Worker dw.println("Current socket dump:");
144*8542734aSAndroid Build Coastguard Worker const auto tcpInfoReader = [&dw](Fwmark mark, const struct inet_diag_msg *sockinfo,
145*8542734aSAndroid Build Coastguard Worker const struct tcp_info *tcpinfo, uint32_t tcpinfoLen) {
146*8542734aSAndroid Build Coastguard Worker tcpInfoPrint(dw, mark, sockinfo, tcpinfo, tcpinfoLen);
147*8542734aSAndroid Build Coastguard Worker };
148*8542734aSAndroid Build Coastguard Worker
149*8542734aSAndroid Build Coastguard Worker if (int ret = sd.getLiveTcpInfos(tcpInfoReader)) {
150*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to dump TCP socket info: %s", strerror(-ret));
151*8542734aSAndroid Build Coastguard Worker }
152*8542734aSAndroid Build Coastguard Worker } else {
153*8542734aSAndroid Build Coastguard Worker ALOGE("Error opening sock diag for dumping TCP socket info");
154*8542734aSAndroid Build Coastguard Worker }
155*8542734aSAndroid Build Coastguard Worker }
156*8542734aSAndroid Build Coastguard Worker
setPollingInterval(milliseconds nextSleepDurationMs)157*8542734aSAndroid Build Coastguard Worker void TcpSocketMonitor::setPollingInterval(milliseconds nextSleepDurationMs) {
158*8542734aSAndroid Build Coastguard Worker std::lock_guard guard(mLock);
159*8542734aSAndroid Build Coastguard Worker
160*8542734aSAndroid Build Coastguard Worker mNextSleepDurationMs = nextSleepDurationMs;
161*8542734aSAndroid Build Coastguard Worker
162*8542734aSAndroid Build Coastguard Worker ALOGD("tcpinfo polling interval set to %lld ms", mNextSleepDurationMs.count());
163*8542734aSAndroid Build Coastguard Worker }
164*8542734aSAndroid Build Coastguard Worker
resumePolling()165*8542734aSAndroid Build Coastguard Worker void TcpSocketMonitor::resumePolling() {
166*8542734aSAndroid Build Coastguard Worker bool wasSuspended;
167*8542734aSAndroid Build Coastguard Worker {
168*8542734aSAndroid Build Coastguard Worker std::lock_guard guard(mLock);
169*8542734aSAndroid Build Coastguard Worker
170*8542734aSAndroid Build Coastguard Worker wasSuspended = mIsSuspended;
171*8542734aSAndroid Build Coastguard Worker mIsSuspended = false;
172*8542734aSAndroid Build Coastguard Worker ALOGD("resuming tcpinfo polling (interval=%lldms)", mNextSleepDurationMs.count());
173*8542734aSAndroid Build Coastguard Worker }
174*8542734aSAndroid Build Coastguard Worker
175*8542734aSAndroid Build Coastguard Worker if (wasSuspended) {
176*8542734aSAndroid Build Coastguard Worker mCv.notify_all();
177*8542734aSAndroid Build Coastguard Worker }
178*8542734aSAndroid Build Coastguard Worker }
179*8542734aSAndroid Build Coastguard Worker
suspendPolling()180*8542734aSAndroid Build Coastguard Worker void TcpSocketMonitor::suspendPolling() {
181*8542734aSAndroid Build Coastguard Worker std::lock_guard guard(mLock);
182*8542734aSAndroid Build Coastguard Worker
183*8542734aSAndroid Build Coastguard Worker bool wasSuspended = mIsSuspended;
184*8542734aSAndroid Build Coastguard Worker mIsSuspended = true;
185*8542734aSAndroid Build Coastguard Worker ALOGD("suspending tcpinfo polling");
186*8542734aSAndroid Build Coastguard Worker
187*8542734aSAndroid Build Coastguard Worker if (!wasSuspended) {
188*8542734aSAndroid Build Coastguard Worker mSocketEntries.clear();
189*8542734aSAndroid Build Coastguard Worker }
190*8542734aSAndroid Build Coastguard Worker }
191*8542734aSAndroid Build Coastguard Worker
poll()192*8542734aSAndroid Build Coastguard Worker void TcpSocketMonitor::poll() {
193*8542734aSAndroid Build Coastguard Worker std::lock_guard guard(mLock);
194*8542734aSAndroid Build Coastguard Worker
195*8542734aSAndroid Build Coastguard Worker if (mIsSuspended) {
196*8542734aSAndroid Build Coastguard Worker return;
197*8542734aSAndroid Build Coastguard Worker }
198*8542734aSAndroid Build Coastguard Worker
199*8542734aSAndroid Build Coastguard Worker SockDiag sd;
200*8542734aSAndroid Build Coastguard Worker if (!sd.open()) {
201*8542734aSAndroid Build Coastguard Worker ALOGE("Error opening sock diag for polling TCP socket info");
202*8542734aSAndroid Build Coastguard Worker return;
203*8542734aSAndroid Build Coastguard Worker }
204*8542734aSAndroid Build Coastguard Worker
205*8542734aSAndroid Build Coastguard Worker const auto now = steady_clock::now();
206*8542734aSAndroid Build Coastguard Worker const auto tcpInfoReader = [this, now](Fwmark mark, const struct inet_diag_msg *sockinfo,
207*8542734aSAndroid Build Coastguard Worker const struct tcp_info *tcpinfo,
208*8542734aSAndroid Build Coastguard Worker uint32_t tcpinfoLen) NO_THREAD_SAFETY_ANALYSIS {
209*8542734aSAndroid Build Coastguard Worker if (sockinfo == nullptr || tcpinfo == nullptr || tcpinfoLen == 0 || mark.intValue == 0) {
210*8542734aSAndroid Build Coastguard Worker return;
211*8542734aSAndroid Build Coastguard Worker }
212*8542734aSAndroid Build Coastguard Worker updateSocketStats(now, mark, sockinfo, tcpinfo, tcpinfoLen);
213*8542734aSAndroid Build Coastguard Worker };
214*8542734aSAndroid Build Coastguard Worker
215*8542734aSAndroid Build Coastguard Worker // Reset mNetworkStats
216*8542734aSAndroid Build Coastguard Worker mNetworkStats.clear();
217*8542734aSAndroid Build Coastguard Worker
218*8542734aSAndroid Build Coastguard Worker if (int ret = sd.getLiveTcpInfos(tcpInfoReader)) {
219*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to poll TCP socket info: %s", strerror(-ret));
220*8542734aSAndroid Build Coastguard Worker return;
221*8542734aSAndroid Build Coastguard Worker }
222*8542734aSAndroid Build Coastguard Worker
223*8542734aSAndroid Build Coastguard Worker // Remove any SocketEntry not updated
224*8542734aSAndroid Build Coastguard Worker for (auto it = mSocketEntries.cbegin(); it != mSocketEntries.cend();) {
225*8542734aSAndroid Build Coastguard Worker if (it->second.lastUpdate < now) {
226*8542734aSAndroid Build Coastguard Worker it = mSocketEntries.erase(it);
227*8542734aSAndroid Build Coastguard Worker } else {
228*8542734aSAndroid Build Coastguard Worker it++;
229*8542734aSAndroid Build Coastguard Worker }
230*8542734aSAndroid Build Coastguard Worker }
231*8542734aSAndroid Build Coastguard Worker
232*8542734aSAndroid Build Coastguard Worker const auto listener = gCtls->eventReporter.getNetdEventListener();
233*8542734aSAndroid Build Coastguard Worker if (listener != nullptr) {
234*8542734aSAndroid Build Coastguard Worker std::vector<int> netIds;
235*8542734aSAndroid Build Coastguard Worker std::vector<int> sentPackets;
236*8542734aSAndroid Build Coastguard Worker std::vector<int> lostPackets;
237*8542734aSAndroid Build Coastguard Worker std::vector<int> rtts;
238*8542734aSAndroid Build Coastguard Worker std::vector<int> sentAckDiffs;
239*8542734aSAndroid Build Coastguard Worker for (auto const& stats : mNetworkStats) {
240*8542734aSAndroid Build Coastguard Worker int32_t nSockets = stats.second.nSockets;
241*8542734aSAndroid Build Coastguard Worker if (nSockets == 0) {
242*8542734aSAndroid Build Coastguard Worker continue;
243*8542734aSAndroid Build Coastguard Worker }
244*8542734aSAndroid Build Coastguard Worker netIds.push_back(stats.first);
245*8542734aSAndroid Build Coastguard Worker sentPackets.push_back(stats.second.sent);
246*8542734aSAndroid Build Coastguard Worker lostPackets.push_back(stats.second.lost);
247*8542734aSAndroid Build Coastguard Worker rtts.push_back(stats.second.rttUs / nSockets);
248*8542734aSAndroid Build Coastguard Worker sentAckDiffs.push_back(stats.second.sentAckDiffMs / nSockets);
249*8542734aSAndroid Build Coastguard Worker }
250*8542734aSAndroid Build Coastguard Worker listener->onTcpSocketStatsEvent(netIds, sentPackets, lostPackets, rtts, sentAckDiffs);
251*8542734aSAndroid Build Coastguard Worker }
252*8542734aSAndroid Build Coastguard Worker
253*8542734aSAndroid Build Coastguard Worker mLastPoll = now;
254*8542734aSAndroid Build Coastguard Worker }
255*8542734aSAndroid Build Coastguard Worker
waitForNextPoll()256*8542734aSAndroid Build Coastguard Worker void TcpSocketMonitor::waitForNextPoll() {
257*8542734aSAndroid Build Coastguard Worker bool isSuspended;
258*8542734aSAndroid Build Coastguard Worker milliseconds nextSleepDurationMs;
259*8542734aSAndroid Build Coastguard Worker {
260*8542734aSAndroid Build Coastguard Worker std::lock_guard guard(mLock);
261*8542734aSAndroid Build Coastguard Worker isSuspended = mIsSuspended;
262*8542734aSAndroid Build Coastguard Worker nextSleepDurationMs= mNextSleepDurationMs;
263*8542734aSAndroid Build Coastguard Worker }
264*8542734aSAndroid Build Coastguard Worker
265*8542734aSAndroid Build Coastguard Worker std::unique_lock<std::mutex> ul(mLock);
266*8542734aSAndroid Build Coastguard Worker if (isSuspended) {
267*8542734aSAndroid Build Coastguard Worker mCv.wait(ul);
268*8542734aSAndroid Build Coastguard Worker } else {
269*8542734aSAndroid Build Coastguard Worker mCv.wait_for(ul, nextSleepDurationMs);
270*8542734aSAndroid Build Coastguard Worker }
271*8542734aSAndroid Build Coastguard Worker }
272*8542734aSAndroid Build Coastguard Worker
isRunning()273*8542734aSAndroid Build Coastguard Worker bool TcpSocketMonitor::isRunning() {
274*8542734aSAndroid Build Coastguard Worker std::lock_guard guard(mLock);
275*8542734aSAndroid Build Coastguard Worker return mIsRunning;
276*8542734aSAndroid Build Coastguard Worker }
277*8542734aSAndroid Build Coastguard Worker
updateSocketStats(time_point now,Fwmark mark,const struct inet_diag_msg * sockinfo,const struct tcp_info * tcpinfo,uint32_t tcpinfoLen)278*8542734aSAndroid Build Coastguard Worker void TcpSocketMonitor::updateSocketStats(time_point now, Fwmark mark,
279*8542734aSAndroid Build Coastguard Worker const struct inet_diag_msg *sockinfo,
280*8542734aSAndroid Build Coastguard Worker const struct tcp_info *tcpinfo,
281*8542734aSAndroid Build Coastguard Worker uint32_t tcpinfoLen) NO_THREAD_SAFETY_ANALYSIS {
282*8542734aSAndroid Build Coastguard Worker int32_t lastAck = TCPINFO_GET(tcpinfo, tcpi_last_ack_recv, tcpinfoLen, 0);
283*8542734aSAndroid Build Coastguard Worker int32_t lastSent = TCPINFO_GET(tcpinfo, tcpi_last_data_sent, tcpinfoLen, 0);
284*8542734aSAndroid Build Coastguard Worker TcpStats diff = {
285*8542734aSAndroid Build Coastguard Worker .sent = TCPINFO_GET(tcpinfo, tcpi_segs_out, tcpinfoLen, 0),
286*8542734aSAndroid Build Coastguard Worker .lost = TCPINFO_GET(tcpinfo, tcpi_lost, tcpinfoLen, 0),
287*8542734aSAndroid Build Coastguard Worker .rttUs = TCPINFO_GET(tcpinfo, tcpi_rtt, tcpinfoLen, 0),
288*8542734aSAndroid Build Coastguard Worker .sentAckDiffMs = lastAck - lastSent,
289*8542734aSAndroid Build Coastguard Worker .nSockets = 1,
290*8542734aSAndroid Build Coastguard Worker };
291*8542734aSAndroid Build Coastguard Worker
292*8542734aSAndroid Build Coastguard Worker {
293*8542734aSAndroid Build Coastguard Worker // Update socket stats with the newest entry, computing the diff w.r.t the previous entry.
294*8542734aSAndroid Build Coastguard Worker const uint64_t cookie = (static_cast<uint64_t>(sockinfo->id.idiag_cookie[0]) << 32)
295*8542734aSAndroid Build Coastguard Worker | static_cast<uint64_t>(sockinfo->id.idiag_cookie[1]);
296*8542734aSAndroid Build Coastguard Worker const SocketEntry previous = mSocketEntries[cookie];
297*8542734aSAndroid Build Coastguard Worker mSocketEntries[cookie] = {
298*8542734aSAndroid Build Coastguard Worker .sent = diff.sent,
299*8542734aSAndroid Build Coastguard Worker .lost = diff.lost,
300*8542734aSAndroid Build Coastguard Worker .lastUpdate = now,
301*8542734aSAndroid Build Coastguard Worker .mark = mark,
302*8542734aSAndroid Build Coastguard Worker .uid = sockinfo->idiag_uid,
303*8542734aSAndroid Build Coastguard Worker };
304*8542734aSAndroid Build Coastguard Worker
305*8542734aSAndroid Build Coastguard Worker diff.sent -= previous.sent;
306*8542734aSAndroid Build Coastguard Worker diff.lost -= previous.lost;
307*8542734aSAndroid Build Coastguard Worker }
308*8542734aSAndroid Build Coastguard Worker
309*8542734aSAndroid Build Coastguard Worker {
310*8542734aSAndroid Build Coastguard Worker // Aggregate the diff per network id.
311*8542734aSAndroid Build Coastguard Worker auto& stats = mNetworkStats[mark.netId];
312*8542734aSAndroid Build Coastguard Worker stats.sent += diff.sent;
313*8542734aSAndroid Build Coastguard Worker stats.lost += diff.lost;
314*8542734aSAndroid Build Coastguard Worker stats.rttUs += diff.rttUs;
315*8542734aSAndroid Build Coastguard Worker stats.sentAckDiffMs += diff.sentAckDiffMs;
316*8542734aSAndroid Build Coastguard Worker stats.nSockets += diff.nSockets;
317*8542734aSAndroid Build Coastguard Worker }
318*8542734aSAndroid Build Coastguard Worker }
319*8542734aSAndroid Build Coastguard Worker
TcpSocketMonitor()320*8542734aSAndroid Build Coastguard Worker TcpSocketMonitor::TcpSocketMonitor() {
321*8542734aSAndroid Build Coastguard Worker std::lock_guard guard(mLock);
322*8542734aSAndroid Build Coastguard Worker
323*8542734aSAndroid Build Coastguard Worker mNextSleepDurationMs = kDefaultPollingInterval;
324*8542734aSAndroid Build Coastguard Worker mIsRunning = true;
325*8542734aSAndroid Build Coastguard Worker mIsSuspended = true;
326*8542734aSAndroid Build Coastguard Worker mPollingThread = std::thread([this] {
327*8542734aSAndroid Build Coastguard Worker (void) this;
328*8542734aSAndroid Build Coastguard Worker while (isRunning()) {
329*8542734aSAndroid Build Coastguard Worker poll();
330*8542734aSAndroid Build Coastguard Worker waitForNextPoll();
331*8542734aSAndroid Build Coastguard Worker }
332*8542734aSAndroid Build Coastguard Worker });
333*8542734aSAndroid Build Coastguard Worker }
334*8542734aSAndroid Build Coastguard Worker
~TcpSocketMonitor()335*8542734aSAndroid Build Coastguard Worker TcpSocketMonitor::~TcpSocketMonitor() {
336*8542734aSAndroid Build Coastguard Worker {
337*8542734aSAndroid Build Coastguard Worker std::lock_guard guard(mLock);
338*8542734aSAndroid Build Coastguard Worker mIsRunning = false;
339*8542734aSAndroid Build Coastguard Worker mIsSuspended = true;
340*8542734aSAndroid Build Coastguard Worker }
341*8542734aSAndroid Build Coastguard Worker mCv.notify_all();
342*8542734aSAndroid Build Coastguard Worker mPollingThread.join();
343*8542734aSAndroid Build Coastguard Worker }
344*8542734aSAndroid Build Coastguard Worker
345*8542734aSAndroid Build Coastguard Worker } // namespace net
346*8542734aSAndroid Build Coastguard Worker } // namespace android
347