#define _GNU_SOURCE
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>
#include <signal.h>
#include <netinet/tcp.h>
#include <sys/syscall.h>
/*
* THIS WORKS FOR SCP WHERE ONLY ONE CONNECTION IS USED
*/
int (*real_socket)(int domain, int type, int protocol) = NULL;
int sockfd = 0;
struct sigaction sact;
long long start_time;
/*
* Periodically dump the info from the socket.
* Note this assumes that the tcp_info struct includes tcpi_total_retrans.
* Older versions do not support tcpi_total_retrans
*/
void periodic_alarm( int sig )
{
struct tcp_info info;
int infoLen = sizeof(info);
struct timeval now;
long long curr_time;
gettimeofday(&now, NULL);
curr_time = (now.tv_sec*1000)+(now.tv_usec/1000);
getsockopt(sockfd, SOL_TCP, TCP_INFO, (void *)&info, (socklen_t *)&infoLen);
fprintf(stderr,"%llu %llu %u %u %u %u %u %u %u %u %u %u\n", curr_time,
curr_time - start_time, info.tcpi_snd_cwnd, info.tcpi_snd_ssthresh,
info.tcpi_unacked, info.tcpi_lost, info.tcpi_retrans, info.tcpi_total_retrans,
info.tcpi_rtt, info.tcpi_rttvar, info.tcpi_rcv_rtt, info.tcpi_rto);
}
int socket(int domain, int type, int protocol)
{
int fd;
struct timeval now;
if (NULL == real_socket)
{
real_socket = dlsym(RTLD_NEXT, "socket");
}
fd = real_socket(domain, type, protocol);
/*
* For scp the first socket is enough
*/
if (SOCK_STREAM == type&SOCK_STREAM && 0 == sockfd)
{
gettimeofday(&now, NULL);
start_time = (now.tv_sec*1000)+(now.tv_usec/1000);
// if (sact.sa_handler != periodic_alarm)
sigemptyset(&sact.sa_mask);
sact.sa_flags = 0;
sact.sa_handler = periodic_alarm;
sigaction(SIGALRM, &sact, NULL);
ualarm(999000,10000);// Wait for 1 second then every 10 ms
sockfd = fd;
}
return fd;
}
/*
Compile with the following command
gcc -shared -ldl -fPIC wrap_socket.c -o wrap_socket.so
Run scp as follows
LD_PRELOAD=./wrap_socket.so scp fname username@machine:path 2>logs-1
*/
Ashwin's Blog
February 14, 2012
Logging TCP state variables such as Congestion Window from user space
If you are familiar with hijacking library calls using LD_PRELOAD then this should be very intuitive. The following code should help you monitor some of the tcp state variables. I am using the following code to log the evolution of the TCP congestion window during an scp session. Please have a look at tcp_info structure available at /usr/include/linux/tcp.h and the tcp_info structure in the kernel tree. I needed only the variable related to the congestion window and timers for my work. You can modify the periodic_alarm function to suit your need. This code works for scp, for other applications you might need to modify the socket descriptor used in the periodic alarm file. Happy Hacking!
Subscribe to:
Posts (Atom)