From b846c8ca6e405a73eac6fe71cf3f08245844310e Mon Sep 17 00:00:00 2001 From: neirac Date: Sat, 18 Nov 2023 18:01:26 +0000 Subject: [PATCH] 14744 Add TCP_INFO socket option --- usr/src/man/man3head/tcp.h.3head | 13 ++++++ .../uts/common/brand/lx/syscall/lx_socket.c | 4 +- usr/src/uts/common/inet/tcp/tcp_opt_data.c | 36 +++++++++++++++ usr/src/uts/common/netinet/tcp.h | 44 +++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) diff --git a/usr/src/man/man3head/tcp.h.3head b/usr/src/man/man3head/tcp.h.3head index 4685b47192..b23e516b44 100644 --- a/usr/src/man/man3head/tcp.h.3head +++ b/usr/src/man/man3head/tcp.h.3head @@ -66,11 +66,24 @@ socket option at the \fBIPPROTO_TCP\fR level: Avoid coalescing of small segments. .RE +.sp +.LP +\fB\fBTCP_INFO\fR\fR +.ad +.RS 15n +Information about a socket's underlying TCP session may be retrieved by passing the read-only option +TCP_INFO to getsockopt(2). It accepts a single argu ment: a pointer to an instance of struct tcp_info. +.RE + .sp .LP The macro is defined in the header. The implementation need not allow the value of the option to be set with \fBsetsockopt()\fR or retrieved with \fBgetsockopt()\fR. +.sp +.LP + + .SH ATTRIBUTES .sp .LP diff --git a/usr/src/uts/common/brand/lx/syscall/lx_socket.c b/usr/src/uts/common/brand/lx/syscall/lx_socket.c index 727fc60bf2..5322b86ac7 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_socket.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_socket.c @@ -24,6 +24,7 @@ * Use is subject to license terms. * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. * Copyright 2022 Joyent, Inc. + * Copyright 2023 Carlos Neira */ #include @@ -2825,7 +2826,7 @@ static const lx_sockopt_map_t ltos_tcp_sockopts[LX_TCP_NOTSENT_LOWAT + 1] = { { TCP_LINGER2, sizeof (int) }, /* TCP_LINGER2 */ { OPTNOTSUP, 0 }, /* TCP_DEFER_ACCEPT - in code */ { OPTNOTSUP, 0 }, /* TCP_WINDOW_CLAMP - in code */ - { OPTNOTSUP, 0 }, /* TCP_INFO */ + { TCP_INFO, sizeof (tcp_info_t) }, /* TCP_INFO */ { TCP_QUICKACK, sizeof (int) }, /* TCP_QUICKACK */ { TCP_CONGESTION, CC_ALGO_NAME_MAX }, /* TCP_CONGESTION */ { OPTNOTSUP, 0 }, /* TCP_MD5SIG */ @@ -3865,6 +3866,7 @@ lx_getsockopt_tcp(sonode_t *so, int optname, void *optval, socklen_t *optlen) lx_proto_opts_t sockopts_tbl = PROTO_SOCKOPTS(ltos_tcp_sockopts); switch (optname) { + case LX_TCP_WINDOW_CLAMP: /* * We do not support these options but some apps rely on them. diff --git a/usr/src/uts/common/inet/tcp/tcp_opt_data.c b/usr/src/uts/common/inet/tcp/tcp_opt_data.c index 15e49ae070..87f403662f 100644 --- a/usr/src/uts/common/inet/tcp/tcp_opt_data.c +++ b/usr/src/uts/common/inet/tcp/tcp_opt_data.c @@ -25,6 +25,7 @@ * Copyright (c) 2016 by Delphix. All rights reserved. * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. * Copyright 2022 Oxide Computer Company + * Copyright 2023 Carlos Neira */ #include @@ -46,8 +47,10 @@ #include #include #include +#include static int tcp_opt_default(queue_t *, int, int, uchar_t *); +static int tcp_fill_info(tcp_t *tcp, tcp_info_t *ptr); /* * Table of all known options handled on a TCP protocol stack. @@ -96,6 +99,10 @@ opdes_t tcp_opt_arr[] = { { TCP_NODELAY, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, + +{ TCP_INFO, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, + sizeof (struct tcp_info), -1 }, + { TCP_MAXSEG, IPPROTO_TCP, OA_R, OA_R, OP_NP, 0, sizeof (uint_t), 536 }, @@ -421,6 +428,9 @@ tcp_opt_get(conn_t *connp, int level, int name, uchar_t *ptr) case TCP_KEEPALIVE_THRESHOLD: *i1 = tcp->tcp_ka_interval; return (sizeof (int)); + case TCP_INFO: + tcp_fill_info(tcp, (tcp_info_t *)ptr); + return (sizeof (tcp_info_t)); /* * TCP_KEEPIDLE expects value in seconds, but @@ -1274,3 +1284,29 @@ tcp_opt_set(conn_t *connp, uint_t optset_context, int level, int name, } return (0); } + +/* + * Export internal TCP state information via a struct tcp_info + * */ +int +tcp_fill_info(tcp_t *tp, tcp_info_t *ti) +{ + ti->tcpi_state = tp->tcp_state; + ti->tcpi_rto = tp->tcp_rto_initial; + ti->tcpi_last_data_recv = tp->tcp_ts_recent; + ti->tcpi_rtt = NSEC2USEC(tp->tcp_rtt_sa); + ti->tcpi_rttvar = NSEC2USEC(tp->tcp_rtt_sd); + ti->tcpi_snd_ssthresh = tp->tcp_swnd; + ti->tcpi_snd_cwnd = tp->tcp_cwnd; + ti->tcpi_snd_mss = tp->tcp_mss; + + ti->tcpi_unacked = tp->tcp_suna; + ti->tcpi_sacked = tp->tcp_rack_cnt; + ti->tcpi_pmtu = tp->tcp_initial_pmtu; + ti->tcpi_total_retrans = tp->tcp_suna; + ti->tcpi_unacked = tp->tcp_suna; + ti->tcpi_sacked = tp->tcp_rack_cnt; + ti->tcpi_rcv_space = tp->tcp_rcv_ws; + + return 0; +} diff --git a/usr/src/uts/common/netinet/tcp.h b/usr/src/uts/common/netinet/tcp.h index a433695f52..3f5823d650 100644 --- a/usr/src/uts/common/netinet/tcp.h +++ b/usr/src/uts/common/netinet/tcp.h @@ -23,6 +23,7 @@ * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2022 Oxide Computer Company + * Copyright 2023 Carlos Neira */ /* @@ -75,6 +76,9 @@ struct tcphdr { uint16_t th_urp; /* urgent pointer */ }; + + + #define TCPOPT_EOL 0 #define TCPOPT_NOP 1 #define TCPOPT_MAXSEG 2 @@ -89,6 +93,8 @@ struct tcphdr { */ #define TCP_MSS 536 + + /* * Options for use with [gs]etsockopt at the TCP level. * @@ -109,6 +115,44 @@ struct tcphdr { #define TCP_KEEPALIVE 0x8 /* set keepalive timer */ #endif +#ifndef TCP_INFO +#define TCP_INFO 0x09 /* retrieve tcp_info structure */ +#endif + typedef struct tcp_info { + uint8_t tcpi_state; + uint8_t tcpi_ca_state; + uint8_t tcpi_retransmits; + uint8_t tcpi_probes; + uint8_t tcpi_backoff; + uint8_t tcpi_options; + uint8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; + uint32_t tcpi_rto; + uint32_t tcpi_ato; + uint32_t tcpi_snd_mss; + uint32_t tcpi_rcv_mss; + uint32_t tcpi_unacked; + uint32_t tcpi_sacked; + uint32_t tcpi_lost; + uint32_t tcpi_retrans; + uint32_t tcpi_fackets; + /* Times. */ + uint32_t tcpi_last_data_sent; + uint32_t tcpi_last_ack_sent; + uint32_t tcpi_last_data_recv; + uint32_t tcpi_last_ack_recv; + /* Metrics. */ + uint32_t tcpi_pmtu; + uint32_t tcpi_rcv_ssthresh; + uint32_t tcpi_rtt; + uint32_t tcpi_rttvar; + uint32_t tcpi_snd_ssthresh; + uint32_t tcpi_snd_cwnd; + uint32_t tcpi_advmss; + uint32_t tcpi_reordering; + uint32_t tcpi_rcv_rtt; + uint32_t tcpi_rcv_space; + uint32_t tcpi_total_retrans; + } tcp_info_t; #define TCP_NOTIFY_THRESHOLD 0x10 #define TCP_ABORT_THRESHOLD 0x11 -- 2.34.1