summaryrefslogtreecommitdiffstats
path: root/server/TcpSocketMonitor.cpp
diff options
context:
space:
mode:
authorHugo Benichi <hugobenichi@google.com>2018-01-15 21:54:00 +0900
committerHugo Benichi <hugobenichi@google.com>2018-01-17 12:56:36 +0900
commit7b314e1b017de35e7552d452aa5645029b39b199 (patch)
tree0f7093224688e3d6d8819cc2ae7691ba8ed33f4a /server/TcpSocketMonitor.cpp
parentdee9481c70b8203ba8836dd53b947b65b526d3e4 (diff)
downloadplatform_system_netd-7b314e1b017de35e7552d452aa5645029b39b199.tar.gz
platform_system_netd-7b314e1b017de35e7552d452aa5645029b39b199.tar.bz2
platform_system_netd-7b314e1b017de35e7552d452aa5645029b39b199.zip
Define TcpSocketMonitor with a single dump method
This patch adds a TcpSocketMonitor registered in Controllers and implementing a single dump method for pretty printing socket info dumped with SockDiag for all sockets on the system. The dump method can be called with $ adb shell dumpsys netd tcp_socket_info Example of output is: TcpSocketMonitor uid=1021 saddr=192.168.2.29 daddr=192.168.2.228 sport=49766 dport=80 state=ESTABLISHED(1) rqueue=0 wqueue=339 rtt=0ms var_rtt=67373.1ms rcv_rtt=1.11372e+06ms unacked=1792 snd_cwnd=0 uid=0 saddr=192.168.2.29 daddr=8.8.4.4 sport=37050 dport=853 state=SYN-SENT(2) rqueue=0 wqueue=1 rtt=0ms var_rtt=134744ms rcv_rtt=1.11372e+06ms unacked=2816 snd_cwnd=0 uid=0 saddr=192.168.2.29 daddr=8.8.8.8 sport=38674 dport=853 state=SYN-SENT(2) rqueue=0 wqueue=1 rtt=1.9084e+06ms var_rtt=0.121ms rcv_rtt=1.90841e+06ms unacked=2816 snd_cwnd=0 uid=0 saddr=2001::0db8:4:fd00:51eb:5323:2a88:7e5a daddr=2001::0db8:4860::8844 sport=42521 dport=853 state=SYN-SENT(2) rqueue=0 wqueue=1 rtt=1.51824e+06ms var_rtt=1.61533e+06ms rcv_rtt=1.34365e+06ms unacked=2816 snd_cwnd=0 uid=0 saddr=2001::0db8:4:fd00:51eb:5323:2a88:7e5a daddr=2001::0db8:4860::8888 sport=44725 dport=853 state=SYN-SENT(2) rqueue=0 wqueue=1 rtt=0ms var_rtt=134744ms rcv_rtt=1.11372e+06ms unacked=2816 snd_cwnd=0 Bug: 64147860 Test: manual tests with newly introduced commands Change-Id: Iad68cc141bc517f38c2c0ec3937269cb11fa8aa4
Diffstat (limited to 'server/TcpSocketMonitor.cpp')
-rw-r--r--server/TcpSocketMonitor.cpp111
1 files changed, 111 insertions, 0 deletions
diff --git a/server/TcpSocketMonitor.cpp b/server/TcpSocketMonitor.cpp
new file mode 100644
index 000000000..3af799031
--- /dev/null
+++ b/server/TcpSocketMonitor.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "TcpSocketMonitor"
+
+#include "TcpSocketMonitor.h"
+#include "DumpWriter.h"
+
+#include "SockDiag.h"
+
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include <linux/tcp.h>
+
+namespace android {
+namespace net {
+
+constexpr const char* getTcpStateName(int t) {
+ switch (t) {
+ case TCP_ESTABLISHED:
+ return "ESTABLISHED";
+ case TCP_SYN_SENT:
+ return "SYN-SENT";
+ case TCP_SYN_RECV:
+ return "SYN-RECV";
+ case TCP_FIN_WAIT1:
+ return "FIN-WAIT-1";
+ case TCP_FIN_WAIT2:
+ return "FIN-WAIT-2";
+ case TCP_TIME_WAIT:
+ return "TIME-WAIT";
+ case TCP_CLOSE:
+ return "CLOSE";
+ case TCP_CLOSE_WAIT:
+ return "CLOSE-WAIT";
+ case TCP_LAST_ACK:
+ return "LAST-ACK";
+ case TCP_LISTEN:
+ return "LISTEN";
+ case TCP_CLOSING:
+ return "CLOSING";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static void tcpInfoPrint(DumpWriter &dw, const struct inet_diag_msg *sockinfo,
+ const struct tcp_info *tcpinfo) {
+ char saddr[INET6_ADDRSTRLEN] = {};
+ char daddr[INET6_ADDRSTRLEN] = {};
+ inet_ntop(sockinfo->idiag_family, &(sockinfo->id.idiag_src), saddr, sizeof(saddr));
+ inet_ntop(sockinfo->idiag_family, &(sockinfo->id.idiag_dst), daddr, sizeof(daddr));
+
+ dw.println(
+ "uid=%u saddr=%s daddr=%s sport=%u dport=%u tcp_state=%s(%u) "
+ "rqueue=%u wqueue=%u rtt=%gms var_rtt=%gms rcv_rtt=%gms unacked=%u snd_cwnd=%u",
+ sockinfo->idiag_uid,
+ saddr,
+ daddr,
+ ntohs(sockinfo->id.idiag_sport),
+ ntohs(sockinfo->id.idiag_dport),
+ getTcpStateName(sockinfo->idiag_state), sockinfo->idiag_state,
+ sockinfo->idiag_rqueue,
+ sockinfo->idiag_wqueue,
+ tcpinfo != nullptr ? tcpinfo->tcpi_rtt/1000.0 : 0,
+ tcpinfo != nullptr ? tcpinfo->tcpi_rttvar/1000.0 : 0,
+ tcpinfo != nullptr ? tcpinfo->tcpi_rcv_rtt/1000.0 : 0,
+ tcpinfo != nullptr ? tcpinfo->tcpi_unacked : 0,
+ tcpinfo != nullptr ? tcpinfo->tcpi_snd_cwnd : 0);
+}
+
+const String16 TcpSocketMonitor::DUMP_KEYWORD = String16("tcp_socket_info");
+
+void TcpSocketMonitor::dump(DumpWriter& dw) {
+ dw.println("TcpSocketMonitor");
+ dw.incIndent();
+
+ SockDiag sd;
+ if (!sd.open()) {
+ ALOGE("Error opening sock diag for dumping TCP socket info");
+ return;
+ }
+
+ const auto tcpInfoReader = [&dw](const struct inet_diag_msg *sockinfo,
+ const struct tcp_info *tcpinfo) {
+ tcpInfoPrint(dw, sockinfo, tcpinfo);
+ };
+
+ if (int ret = sd.getLiveTcpInfos(tcpInfoReader)) {
+ ALOGE("Failed to dump TCP socket info: %s", strerror(-ret));
+ return;
+ }
+
+ dw.decIndent();
+}
+
+} // namespace net
+} // namespace android