1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3 2*2f2c4c7aSAndroid Build Coastguard Worker# 3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2017 The Android Open Source Project 4*2f2c4c7aSAndroid Build Coastguard Worker# 5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*2f2c4c7aSAndroid Build Coastguard Worker# 9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*2f2c4c7aSAndroid Build Coastguard Worker# 11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License. 16*2f2c4c7aSAndroid Build Coastguard Worker 17*2f2c4c7aSAndroid Build Coastguard Worker"""Generic netlink interface to TCP metrics.""" 18*2f2c4c7aSAndroid Build Coastguard Worker 19*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import * # pylint: disable=wildcard-import 20*2f2c4c7aSAndroid Build Coastguard Workerimport struct 21*2f2c4c7aSAndroid Build Coastguard Worker 22*2f2c4c7aSAndroid Build Coastguard Workerimport binascii 23*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct 24*2f2c4c7aSAndroid Build Coastguard Workerimport genetlink 25*2f2c4c7aSAndroid Build Coastguard Workerimport net_test 26*2f2c4c7aSAndroid Build Coastguard Workerimport netlink 27*2f2c4c7aSAndroid Build Coastguard Worker 28*2f2c4c7aSAndroid Build Coastguard Worker 29*2f2c4c7aSAndroid Build Coastguard Worker### TCP metrics constants. See include/uapi/linux/tcp_metrics.h. 30*2f2c4c7aSAndroid Build Coastguard Worker# Family name and version 31*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_GENL_NAME = "tcp_metrics" 32*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_GENL_VERSION = 1 33*2f2c4c7aSAndroid Build Coastguard Worker 34*2f2c4c7aSAndroid Build Coastguard Worker# Message types. 35*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_CMD_GET = 1 36*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_CMD_DEL = 2 37*2f2c4c7aSAndroid Build Coastguard Worker 38*2f2c4c7aSAndroid Build Coastguard Worker# Attributes. 39*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_UNSPEC = 0 40*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_ADDR_IPV4 = 1 41*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_ADDR_IPV6 = 2 42*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_AGE = 3 43*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_TW_TSVAL = 4 44*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_TW_TS_STAMP = 5 45*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_VALS = 6 46*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_FOPEN_MSS = 7 47*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_FOPEN_SYN_DROPS = 8 48*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_FOPEN_SYN_DROP_TS = 9 49*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_FOPEN_COOKIE = 10 50*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_SADDR_IPV4 = 11 51*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_SADDR_IPV6 = 12 52*2f2c4c7aSAndroid Build Coastguard WorkerTCP_METRICS_ATTR_PAD = 13 53*2f2c4c7aSAndroid Build Coastguard Worker 54*2f2c4c7aSAndroid Build Coastguard Worker 55*2f2c4c7aSAndroid Build Coastguard Workerclass TcpMetrics(genetlink.GenericNetlink): 56*2f2c4c7aSAndroid Build Coastguard Worker 57*2f2c4c7aSAndroid Build Coastguard Worker NL_DEBUG = ["ALL"] 58*2f2c4c7aSAndroid Build Coastguard Worker 59*2f2c4c7aSAndroid Build Coastguard Worker def __init__(self): 60*2f2c4c7aSAndroid Build Coastguard Worker super(TcpMetrics, self).__init__() 61*2f2c4c7aSAndroid Build Coastguard Worker # Generic netlink family IDs are dynamically assigned. Find ours. 62*2f2c4c7aSAndroid Build Coastguard Worker ctrl = genetlink.GenericNetlinkControl() 63*2f2c4c7aSAndroid Build Coastguard Worker self.family = ctrl.GetFamily(TCP_METRICS_GENL_NAME) 64*2f2c4c7aSAndroid Build Coastguard Worker 65*2f2c4c7aSAndroid Build Coastguard Worker def _Decode(self, command, msg, nla_type, nla_data, nested): 66*2f2c4c7aSAndroid Build Coastguard Worker """Decodes TCP metrics netlink attributes to human-readable format.""" 67*2f2c4c7aSAndroid Build Coastguard Worker 68*2f2c4c7aSAndroid Build Coastguard Worker name = self._GetConstantName(__name__, nla_type, "TCP_METRICS_ATTR_") 69*2f2c4c7aSAndroid Build Coastguard Worker 70*2f2c4c7aSAndroid Build Coastguard Worker if name in ["TCP_METRICS_ATTR_ADDR_IPV4", "TCP_METRICS_ATTR_SADDR_IPV4"]: 71*2f2c4c7aSAndroid Build Coastguard Worker data = inet_ntop(AF_INET, nla_data) 72*2f2c4c7aSAndroid Build Coastguard Worker elif name in ["TCP_METRICS_ATTR_ADDR_IPV6", "TCP_METRICS_ATTR_SADDR_IPV6"]: 73*2f2c4c7aSAndroid Build Coastguard Worker data = inet_ntop(AF_INET6, nla_data) 74*2f2c4c7aSAndroid Build Coastguard Worker elif name in ["TCP_METRICS_ATTR_AGE"]: 75*2f2c4c7aSAndroid Build Coastguard Worker data = struct.unpack("=Q", nla_data)[0] 76*2f2c4c7aSAndroid Build Coastguard Worker elif name in ["TCP_METRICS_ATTR_TW_TSVAL", "TCP_METRICS_ATTR_TW_TS_STAMP"]: 77*2f2c4c7aSAndroid Build Coastguard Worker data = struct.unpack("=I", nla_data)[0] 78*2f2c4c7aSAndroid Build Coastguard Worker elif name == "TCP_METRICS_ATTR_FOPEN_MSS": 79*2f2c4c7aSAndroid Build Coastguard Worker data = struct.unpack("=H", nla_data)[0] 80*2f2c4c7aSAndroid Build Coastguard Worker elif name == "TCP_METRICS_ATTR_FOPEN_COOKIE": 81*2f2c4c7aSAndroid Build Coastguard Worker data = nla_data 82*2f2c4c7aSAndroid Build Coastguard Worker else: 83*2f2c4c7aSAndroid Build Coastguard Worker data = binascii.hexlify(nla_data) 84*2f2c4c7aSAndroid Build Coastguard Worker 85*2f2c4c7aSAndroid Build Coastguard Worker return name, data 86*2f2c4c7aSAndroid Build Coastguard Worker 87*2f2c4c7aSAndroid Build Coastguard Worker def MaybeDebugCommand(self, command, unused_flags, data): 88*2f2c4c7aSAndroid Build Coastguard Worker if "ALL" not in self.NL_DEBUG and command not in self.NL_DEBUG: 89*2f2c4c7aSAndroid Build Coastguard Worker return 90*2f2c4c7aSAndroid Build Coastguard Worker parsed = self._ParseNLMsg(data, genetlink.Genlmsghdr) 91*2f2c4c7aSAndroid Build Coastguard Worker 92*2f2c4c7aSAndroid Build Coastguard Worker def _NlAttrSaddr(self, address): 93*2f2c4c7aSAndroid Build Coastguard Worker if ":" not in address: 94*2f2c4c7aSAndroid Build Coastguard Worker family = AF_INET 95*2f2c4c7aSAndroid Build Coastguard Worker nla_type = TCP_METRICS_ATTR_SADDR_IPV4 96*2f2c4c7aSAndroid Build Coastguard Worker else: 97*2f2c4c7aSAndroid Build Coastguard Worker family = AF_INET6 98*2f2c4c7aSAndroid Build Coastguard Worker nla_type = TCP_METRICS_ATTR_SADDR_IPV6 99*2f2c4c7aSAndroid Build Coastguard Worker return self._NlAttrIPAddress(nla_type, family, address) 100*2f2c4c7aSAndroid Build Coastguard Worker 101*2f2c4c7aSAndroid Build Coastguard Worker def _NlAttrTcpMetricsAddr(self, address, is_source): 102*2f2c4c7aSAndroid Build Coastguard Worker version = net_test.GetAddressVersion(address) 103*2f2c4c7aSAndroid Build Coastguard Worker family = net_test.GetAddressFamily(version) 104*2f2c4c7aSAndroid Build Coastguard Worker if version == 5: 105*2f2c4c7aSAndroid Build Coastguard Worker address = address.replace("::ffff:", "") 106*2f2c4c7aSAndroid Build Coastguard Worker nla_name = "TCP_METRICS_ATTR_%s_IPV%d" % ( 107*2f2c4c7aSAndroid Build Coastguard Worker "SADDR" if is_source else "ADDR", version) 108*2f2c4c7aSAndroid Build Coastguard Worker nla_type = globals()[nla_name] 109*2f2c4c7aSAndroid Build Coastguard Worker return self._NlAttrIPAddress(nla_type, family, address) 110*2f2c4c7aSAndroid Build Coastguard Worker 111*2f2c4c7aSAndroid Build Coastguard Worker def _NlAttrAddr(self, address): 112*2f2c4c7aSAndroid Build Coastguard Worker return self._NlAttrTcpMetricsAddr(address, False) 113*2f2c4c7aSAndroid Build Coastguard Worker 114*2f2c4c7aSAndroid Build Coastguard Worker def _NlAttrSaddr(self, address): 115*2f2c4c7aSAndroid Build Coastguard Worker return self._NlAttrTcpMetricsAddr(address, True) 116*2f2c4c7aSAndroid Build Coastguard Worker 117*2f2c4c7aSAndroid Build Coastguard Worker def DumpMetrics(self): 118*2f2c4c7aSAndroid Build Coastguard Worker """Dumps all TCP metrics.""" 119*2f2c4c7aSAndroid Build Coastguard Worker return self._Dump(self.family, TCP_METRICS_CMD_GET, 1) 120*2f2c4c7aSAndroid Build Coastguard Worker 121*2f2c4c7aSAndroid Build Coastguard Worker def GetMetrics(self, saddr, daddr): 122*2f2c4c7aSAndroid Build Coastguard Worker """Returns TCP metrics for the specified src/dst pair.""" 123*2f2c4c7aSAndroid Build Coastguard Worker data = self._NlAttrSaddr(saddr) + self._NlAttrAddr(daddr) 124*2f2c4c7aSAndroid Build Coastguard Worker self._SendCommand(self.family, TCP_METRICS_CMD_GET, 1, data, 125*2f2c4c7aSAndroid Build Coastguard Worker netlink.NLM_F_REQUEST) 126*2f2c4c7aSAndroid Build Coastguard Worker hdr, attrs = self._GetMsg(genetlink.Genlmsghdr) 127*2f2c4c7aSAndroid Build Coastguard Worker return attrs 128*2f2c4c7aSAndroid Build Coastguard Worker 129*2f2c4c7aSAndroid Build Coastguard Worker def DelMetrics(self, saddr, daddr): 130*2f2c4c7aSAndroid Build Coastguard Worker """Deletes TCP metrics for the specified src/dst pair.""" 131*2f2c4c7aSAndroid Build Coastguard Worker data = self._NlAttrSaddr(saddr) + self._NlAttrAddr(daddr) 132*2f2c4c7aSAndroid Build Coastguard Worker self._SendCommand(self.family, TCP_METRICS_CMD_DEL, 1, data, 133*2f2c4c7aSAndroid Build Coastguard Worker netlink.NLM_F_REQUEST) 134*2f2c4c7aSAndroid Build Coastguard Worker 135*2f2c4c7aSAndroid Build Coastguard Worker 136*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__": 137*2f2c4c7aSAndroid Build Coastguard Worker t = TcpMetrics() 138*2f2c4c7aSAndroid Build Coastguard Worker print(t.DumpMetrics()) 139