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