diff options
| author | Hugo Benichi <hugobenichi@google.com> | 2018-01-15 21:54:00 +0900 |
|---|---|---|
| committer | Hugo Benichi <hugobenichi@google.com> | 2018-01-17 12:56:36 +0900 |
| commit | 7b314e1b017de35e7552d452aa5645029b39b199 (patch) | |
| tree | 0f7093224688e3d6d8819cc2ae7691ba8ed33f4a /server/TcpSocketMonitor.cpp | |
| parent | dee9481c70b8203ba8836dd53b947b65b526d3e4 (diff) | |
| download | platform_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.cpp | 111 |
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 |
