-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtcp_info.py
110 lines (91 loc) · 3.23 KB
/
tcp_info.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# Adapted from original source:
# https://github.com/ModioAB/snippets/blob/master/src/tcp_info.py
#
import ctypes
import socket
class TcpInfo(ctypes.Structure):
"""TCP_INFO struct in linux 4.2
see /usr/include/linux/tcp.h for details"""
__u8 = ctypes.c_uint8
__u32 = ctypes.c_uint32
__u64 = ctypes.c_uint64
_fields_ = [
("tcpi_state", __u8),
("tcpi_ca_state", __u8),
("tcpi_retransmits", __u8),
("tcpi_probes", __u8),
("tcpi_backoff", __u8),
("tcpi_options", __u8),
("tcpi_snd_wscale", __u8, 4), ("tcpi_rcv_wscale", __u8, 4),
("tcpi_rto", __u32),
("tcpi_ato", __u32),
("tcpi_snd_mss", __u32),
("tcpi_rcv_mss", __u32),
("tcpi_unacked", __u32),
("tcpi_sacked", __u32),
("tcpi_lost", __u32),
("tcpi_retrans", __u32),
("tcpi_fackets", __u32),
# Times
("tcpi_last_data_sent", __u32),
("tcpi_last_ack_sent", __u32),
("tcpi_last_data_recv", __u32),
("tcpi_last_ack_recv", __u32),
# Metrics
("tcpi_pmtu", __u32),
("tcpi_rcv_ssthresh", __u32),
("tcpi_rtt", __u32),
("tcpi_rttvar", __u32),
("tcpi_snd_ssthresh", __u32),
("tcpi_snd_cwnd", __u32),
("tcpi_advmss", __u32),
("tcpi_reordering", __u32),
("tcpi_rcv_rtt", __u32),
("tcpi_rcv_space", __u32),
("tcpi_total_retrans", __u32),
("tcpi_pacing_rate", __u64),
("tcpi_max_pacing_rate", __u64),
# RFC4898 tcpEStatsAppHCThruOctetsAcked
("tcpi_bytes_acked", __u64),
# RFC4898 tcpEStatsAppHCThruOctetsReceived
("tcpi_bytes_received", __u64),
# RFC4898 tcpEStatsPerfSegsOut
("tcpi_segs_out", __u32),
# RFC4898 tcpEStatsPerfSegsIn
("tcpi_segs_in", __u32),
("tcpi_notsent_bytes", __u32),
("tcpi_min_rtt", __u32),
# RFC4898 tcpEStatsDataSegsIn
("tcpi_data_segs_in", __u32),
# RFC4898 tcpEStatsDataSegsOut
("tcpi_data_segs_out", __u32),
("tcpi_delivery_rate", __u64),
# Time (usec) busy sending data
("tcpi_busy_time", __u64),
# Time (usec) limited by receive window
("tcpi_rwnd_limited", __u64),
# Time (usec) limited by send buffer
("tcpi_sndbuf_limited", __u64),
("tcpi_delivered", __u32),
("tcpi_delivered_ce", __u32),
# RFC4898 tcpEStatsPerfHCDataOctetsOut
("tcpi_bytes_sent", __u64),
# RFC4898 tcpEStatsPerfOctetsRetrans
("tcpi_bytes_retrans", __u64),
# RFC4898 tcpEStatsStackDSACKDups
("tcpi_dsack_dups", __u32),
# reordering events seen
("tcpi_reord_seen", __u32),
]
del __u8, __u32, __u64
def __repr__(self):
keyval = ["{}={!r}".format(x[0], getattr(self, x[0]))
for x in self._fields_]
fields = ", ".join(keyval)
return "{}({})".format(self.__class__.__name__, fields)
def from_socket(sock):
padsize = ctypes.sizeof(TcpInfo)
data = sock.getsockopt(socket.SOL_TCP, socket.TCP_INFO, padsize)
# On older kernels, we get fewer bytes, pad with null to fit
padded = data.ljust(padsize, b'\0')
return TcpInfo.from_buffer_copy(padded)