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.

Tags:

Tcp

Ss