1

I have a java and cpp client applications which runs on Linux and creates TCP connections to a server. These application after establishing TCP connection modifies the Keep Alive parameters for those TCP connections (i.e. Linux default for Keepalive 7200 seconds is modified to 300 from application for specific TCP connection).

$cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
$cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
$cat /proc/sys/net/ipv4/tcp_keepalive_probes
9

CPP

setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, 300, sizeof(int));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, 60, sizeof(int));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, 5, sizeof(int));

Java

sslSocket.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, 300);
sslSocket.setOption(ExtendedSocketOptions.TCP_KEEPINTERVAL, 60);
sslSocket.setOption(ExtendedSocketOptions.TCP_KEEPCOUNT, 5);

My questions Is there a way to see what are the keep alive interval/delay/probecount values specific to an already established TCP connection (for the specific connection created by these application) from Linux terminal.

Once I identify the specific TCP connection established from the application, I want to print the keep alive values for those specific connections (and verify that those TCP connections are having Keep Alive values that I set from my application instead of the OS defaults ).

2 Answers2

0

I don't think there is a way to do this from any shell I'm aware of. ss itself can't even show this information – it might simply be process state that's not exported to any other process through any meaningful way.

Hence, the "instrumentalizing debugger" might be the only way to get this:

ptrace-Attach to that target process, halting it; then [do what gdb's call does, namely, save a bit of state, set up a stack, set the right registers, then set the instruction pointer to the getsockopt, run until the popping of the last stack frame, handle the result, restore state and the original original instruction pointer and continue running.

Not something you can do from a shell!

0

TCP Keep-alive exists separately on the two peers (they don't negotiate nor know the other's setting). So if the client sets keep-alive this can be checked (only) on the client

The information is partially available (at least) with newer tools using the (rt)netlink socket: ss obsoletes netstat on Linux. The current state is retrievable, not the socket configuration.

So as an example a client has established (a) connection(s) to host 192.0.2.4 port 5555 and sets keep alive idle time to 120s. Reproducible with socat like this:

socat -d -d tcp4:192.0.2.4:5555,keepalive=1,keepidle=120 -

One can retrieve this information on the client system with the additional -e / --extended option of ss (tested on kernel 5.17.x and iproute2 5.18.0):

$ ss -tne dst == 192.0.2.4 and dport == 5555
State   Recv-Q   Send-Q     Local Address:Port      Peer Address:Port  Process  
ESTAB   0        0              192.0.2.3:40498        192.0.2.4:5555   timer:(keepalive,1min58sec,0) uid:1000 ino:4007748 sk:432 cgroup:/user.slice/user-1000.slice/session-2.scope <->

Here: timer:(keepalive,1min58sec,0) is the information about current keep-alive's state on the socket. As it was done about 2 seconds after the connection, it shows 1min58sec. The 2mn initial configuration is not available here.


With simple applications one could use a debugger tool like GDB to inject getsockopt(2) system calls to retrieve and display what was configured on a given socket (also requires ss's -p option to retrieve the PID (possibly one amont multiple PID sharing this socket) and FD for this socket). Here's an example of mine in this Q/A where the information wasn't available for the given kernel: How to find the connection between tap interface and its file descriptor?

But with a multi-threaded application like java which uses a lot of synchronization between threads with futex & co, I'm not sure using a debugger on it might not have side effects caused by timing disruption.

A.B
  • 36,364
  • 2
  • 73
  • 118