Detailed output of ss command
Meaning of some of these fields can be deduced from source code of
ss and
Linux kernel. Information you see is printed by tcp_show_info()
function in iproute2/misc/ss.c
.
advmss:
In ss.c
:
s.advmss = info->tcpi_advmss;
(...)
if (s->advmss)
out(" advmss:%d", s->advmss);
In linux/include/linux/tcp.h
:
u16 advmss; /* Advertised MSS */
app_limited:
In ss.c
:
s.app_limited = info->tcpi_delivery_rate_app_limited;
(..)
if (s->app_limited)
out(" app_limited");
That one is not documented in linux/include/uapi/linux/tcp.h
in
Linux:
struct tcp_info {
(...)
__u8 tcpi_delivery_rate_app_limited:1;
but surprisingly we can find some information in the commit that introduced it:
commit eb8329e0a04db0061f714f033b4454326ba147f4
Author: Yuchung Cheng <[email protected]>
Date: Mon Sep 19 23:39:16 2016 -0400
tcp: export data delivery rate
This commit export two new fields in struct tcp_info:
tcpi_delivery_rate: The most recent goodput, as measured by
tcp_rate_gen(). If the socket is limited by the sending
application (e.g., no data to send), it reports the highest
measurement instead of the most recent. The unit is bytes per
second (like other rate fields in tcp_info).
tcpi_delivery_rate_app_limited: A boolean indicating if the goodput
was measured when the socket's throughput was limited by the
sending application.
This delivery rate information can be useful for applications that
want to know the current throughput the TCP connection is seeing,
e.g. adaptive bitrate video streaming. It can also be very useful for
debugging or troubleshooting.
A quick git blame
in ss.c
confirms that app_limited
was added
after tcpi_delivery_rate_app_limited
was added to kernel.
busy:
In ss.c
:
s.busy_time = info->tcpi_busy_time;
(..)
if (s->busy_time) {
out(" busy:%llums", s->busy_time / 1000);
And in include/uapi/linux/tcp.h
in Linux it says:
struct tcp_info {
(...)
__u64 tcpi_busy_time; /* Time (usec) busy sending data */
retrans:
In ss.c
:
s.retrans = info->tcpi_retrans;
s.retrans_total = info->tcpi_total_retrans;
(...)
if (s->retrans || s->retrans_total)
out(" retrans:%u/%u", s->retrans, s->retrans_total);
tcpi_total_retrans
is not described in linux/include/uapi/linux/tcp.h
:
struct tcp_info {
(...)
__u32 tcpi_total_retrans;
but it's used in tcp_get_info()
:
void tcp_get_info(struct sock *sk, struct tcp_info *info)
{
const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */
(...)
info->tcpi_total_retrans = tp->total_retrans;
And in linux/include/linux/tcp.h
it says:
struct tcp_sock {
(...)
u32 total_retrans; /* Total retransmits for entire connection */
tcpi_retrans
is also not described but reading tcp_get_info()
again we see:
info->tcpi_retrans = tp->retrans_out;
And in linux/include/linux/tcp.h
:
struct tcp_sock {
(...)
u32 retrans_out; /* Retransmitted packets out */
dsack_dups:
In ss.c
:
s.dsack_dups = info->tcpi_dsack_dups;
(...)
if (s->dsack_dups)
out(" dsack_dups:%u", s->dsack_dups);
In include/uapi/linux/tcp.h
in Linux:
struct tcp_info {
(...)
__u32 tcpi_dsack_dups; /* RFC4898 tcpEStatsStackDSACKDups */
And in https://www.ietf.org/rfc/rfc4898.txt:
The number of duplicate segments reported to the local host by D-SACK blocks.