xref: /aosp_15_r20/system/netd/server/TcpSocketMonitor.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
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