From: Lennert Buytenhek <buytenh@wantstofly.org>
To: "David S. Miller" <davem@davemloft.net>
Cc: netdev@oss.sgi.com
Subject: Re: way of figuring out total number of retransmitted packets on a TCP socket?
Date: Tue, 26 Oct 2004 15:47:02 +0200 [thread overview]
Message-ID: <20041026134702.GA2891@xi.wantstofly.org> (raw)
In-Reply-To: <20041020213739.6e669fdd.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 673 bytes --]
On Wed, Oct 20, 2004 at 09:37:39PM -0700, David S. Miller wrote:
> Please give this 2.6.x patch a spin:
Works quite nicely, thank you very much. I've attached the sources
of the tools that we're using in combination with this -- basically
just a discard server and a client. (You need the libivykis async
I/O lib installed to compile the server.)
A 1GB cross-atlantic transfer (~715kpackets) over a proper provider
typically shows something like this: (Discard server is on a GbE
connection in LA, the transmitter on FastE in Amsterdam.)
[...]
tcpi_total_retrans 2
The same test done over a second-rate provider:
[...]
tcpi_total_retrans 3482
--L
[-- Attachment #2: eat.c --]
[-- Type: text/plain, Size: 1731 bytes --]
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <iv.h>
#include <netinet/in.h>
#include <syslog.h>
#include <sys/socket.h>
#include <unistd.h>
struct iv_fd master_fd;
struct connection
{
struct iv_fd fd;
};
void connection_handler(void *_conn)
{
struct connection *conn = (struct connection *)_conn;
char buf[65536];
int len;
len = iv_read(&(conn->fd), buf, sizeof(buf));
if (len <= 0) {
if (len == 0 || errno != EAGAIN) {
iv_unregister_fd(&(conn->fd));
close(conn->fd.fd);
free(conn);
}
return;
}
}
void new_connection(void *_dummy)
{
struct sockaddr_in addr;
socklen_t addrlen;
struct connection *conn;
int fd;
addrlen = sizeof(addr);
fd = iv_accept(&master_fd, (struct sockaddr *)&addr, &addrlen);
if (fd <= 0) {
if (fd < 0 && errno == EAGAIN)
return;
perror("iv_accept");
exit(-1);
}
conn = malloc(sizeof(*conn));
if (conn == NULL) {
syslog(LOG_ALERT, "new_connection: memory allocation error, dropping connection");
close(fd);
return;
}
INIT_IV_FD(&(conn->fd));
conn->fd.fd = fd;
conn->fd.cookie = (void *)conn;
conn->fd.handler_in = connection_handler;
iv_register_fd(&(conn->fd));
}
int main()
{
struct sockaddr_in addr;
int fd;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
exit(-1);
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(9);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
exit(-1);
}
if (listen(fd, 1000) < 0) {
perror("listen");
exit(-1);
}
iv_init();
INIT_IV_FD(&(master_fd));
master_fd.fd = fd;
master_fd.handler_in = new_connection;
iv_register_fd(&(master_fd));
iv_main();
return 0;
}
[-- Attachment #3: feed.c --]
[-- Type: text/plain, Size: 5941 bytes --]
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/sockios.h>
#include <linux/tcp.h>
#ifndef SOL_TCP
#define SOL_TCP 6
#endif
struct tcp_info2
{
u_int8_t tcpi_state;
u_int8_t tcpi_ca_state;
u_int8_t tcpi_retransmits;
u_int8_t tcpi_probes;
u_int8_t tcpi_backoff;
u_int8_t tcpi_options;
u_int8_t tcpi_snd_wscale:4, tcpi_rcv_wscale:4;
u_int32_t tcpi_rto;
u_int32_t tcpi_ato;
u_int32_t tcpi_snd_mss;
u_int32_t tcpi_rcv_mss;
u_int32_t tcpi_unacked;
u_int32_t tcpi_sacked;
u_int32_t tcpi_lost;
u_int32_t tcpi_retrans;
u_int32_t tcpi_fackets;
/* Times. */
u_int32_t tcpi_last_data_sent;
u_int32_t tcpi_last_ack_sent; /* Not remembered, sorry. */
u_int32_t tcpi_last_data_recv;
u_int32_t tcpi_last_ack_recv;
/* Metrics. */
u_int32_t tcpi_pmtu;
u_int32_t tcpi_rcv_ssthresh;
u_int32_t tcpi_rtt;
u_int32_t tcpi_rttvar;
u_int32_t tcpi_snd_ssthresh;
u_int32_t tcpi_snd_cwnd;
u_int32_t tcpi_advmss;
u_int32_t tcpi_reordering;
u_int32_t tcpi_rcv_rtt;
u_int32_t tcpi_rcv_space;
u_int32_t tcpi_total_retrans;
};
static unsigned char zeroes[65536];
static char *tcpi_state(int state)
{
switch (state) {
case TCP_ESTABLISHED: return "ESTABLISHED";
case TCP_SYN_SENT: return "SYN_SENT";
case TCP_SYN_RECV: return "SYN_RECV";
case TCP_FIN_WAIT1: return "FIN_WAIT1";
case TCP_FIN_WAIT2: return "FIN_WAIT2";
case TCP_TIME_WAIT: return "TIME_WAIT";
case TCP_CLOSE: return "CLOSE";
case TCP_CLOSE_WAIT: return "CLOSE_WAIT";
case TCP_LAST_ACK: return "LAST_ACK";
case TCP_LISTEN: return "LISTEN";
case TCP_CLOSING: return "CLOSING";
}
return "invalid";
}
static char *tcpi_ca_state(int state)
{
switch (state) {
case TCP_CA_Open: return "CA_Open";
case TCP_CA_Disorder: return "CA_Disorder";
case TCP_CA_CWR: return "CA_CWR";
case TCP_CA_Recovery: return "CA_Recovery";
case TCP_CA_Loss: return "CA_Loss";
}
return "invalid";
}
int main(int argc, char *argv[])
{
struct sockaddr_in addr;
struct tcp_info2 tcpi;
struct hostent *he;
int bytes;
int port;
int ret;
int fd;
if (argc <= 1) {
fprintf(stderr, "syntax: %s <hostname> [port] [megs]\n", argv[0]);
exit(-1);
}
he = gethostbyname(argv[1]);
if (he == NULL) {
herror("gethostbyname");
exit(-1);
}
addr.sin_family = he->h_addrtype;
memcpy(&(addr.sin_addr), he->h_addr_list[0], he->h_length);
endhostent();
port = 9;
if (argc > 2 && sscanf(argv[2], "%d", &port) != 1) {
fprintf(stderr, "%s: second argument not numeric\n", argv[0]);
exit(-1);
}
addr.sin_port = htons(port);
bytes = 1024;
if (argc > 3 && sscanf(argv[3], "%d", &bytes) != 1) {
fprintf(stderr, "%s: third argument not numeric\n", argv[0]);
exit(-1);
}
bytes <<= 20;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return 1;
}
ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
perror("connect");
return 1;
}
ret = sizeof(tcpi);
if (getsockopt(fd, SOL_TCP, TCP_INFO, &tcpi, &ret) < 0) {
perror("getsockopt(TCP_INFO)");
return 1;
}
while (bytes) {
int tosend;
tosend = bytes;
if (tosend > sizeof(zeroes))
tosend = sizeof(zeroes);
ret = write(fd, zeroes, tosend);
if (ret < 0) {
perror("write");
break;
}
bytes -= ret;
}
shutdown(fd, SHUT_RDWR);
sleep(1);
tcpi.tcpi_total_retrans = 0xdeadbeef;
ret = sizeof(tcpi);
if (getsockopt(fd, SOL_TCP, TCP_INFO, &tcpi, &ret) < 0) {
perror("getsockopt(TCP_INFO)");
return 1;
}
printf("tcpi_state\t\t%d, %s\n", tcpi.tcpi_state, tcpi_state(tcpi.tcpi_state));
printf("tcpi_ca_state\t\t%d, %s\n", tcpi.tcpi_ca_state, tcpi_ca_state(tcpi.tcpi_ca_state));
printf("tcpi_retransmits\t%d\n", tcpi.tcpi_retransmits);
printf("tcpi_probes\t\t%d\n", tcpi.tcpi_probes);
printf("tcpi_backoff\t\t%d\n", tcpi.tcpi_backoff);
printf("tcpi_options\t\t%d", tcpi.tcpi_options);
if (tcpi.tcpi_options) {
printf(" [");
if (tcpi.tcpi_options & TCPI_OPT_TIMESTAMPS)
printf("TIMESTAMPS ");
if (tcpi.tcpi_options & TCPI_OPT_SACK)
printf("SACK ");
if (tcpi.tcpi_options & TCPI_OPT_WSCALE)
printf("WSCALE ");
if (tcpi.tcpi_options & TCPI_OPT_ECN)
printf("ECN ");
printf("]");
}
printf("\n");
if (tcpi.tcpi_options & TCPI_OPT_WSCALE) {
printf("tcpi_snd_wscale\t\t%d\n", tcpi.tcpi_snd_wscale);
printf("tcpi_rcv_wscale\t\t%d\n", tcpi.tcpi_rcv_wscale);
}
printf("\n");
printf("tcpi_rto\t\t%d\n", tcpi.tcpi_rto);
printf("tcpi_ato\t\t%d\n", tcpi.tcpi_ato);
printf("tcpi_snd_mss\t\t%d\n", tcpi.tcpi_snd_mss);
printf("tcpi_rcv_mss\t\t%d\n", tcpi.tcpi_rcv_mss);
printf("\n");
printf("tcpi_unacked\t\t%d\n", tcpi.tcpi_unacked);
printf("tcpi_sacked\t\t%d\n", tcpi.tcpi_sacked);
printf("tcpi_lost\t\t%d\n", tcpi.tcpi_lost);
printf("tcpi_retrans\t\t%d\n", tcpi.tcpi_retrans);
printf("tcpi_fackets\t\t%d\n", tcpi.tcpi_fackets);
printf("\n");
printf("tcpi_last_data_sent\t%d\n", tcpi.tcpi_last_data_sent);
printf("tcpi_last_ack_sent\t%d\n", tcpi.tcpi_last_ack_sent);
printf("tcpi_last_data_recv\t%d\n", tcpi.tcpi_last_data_recv);
printf("tcpi_last_ack_recv\t%d\n", tcpi.tcpi_last_ack_recv);
printf("\n");
printf("tcpi_pmtu\t\t%d\n", tcpi.tcpi_pmtu);
printf("tcpi_rcv_sstresh\t%d\n", tcpi.tcpi_rcv_ssthresh);
printf("tcpi_rtt\t\t%d\n", tcpi.tcpi_rtt);
printf("tcpi_rttvar\t\t%d\n", tcpi.tcpi_rttvar);
printf("tcpi_snd_sstresh\t%d\n", tcpi.tcpi_snd_ssthresh);
printf("tcpi_snd_cwnd\t\t%d\n", tcpi.tcpi_snd_cwnd);
printf("tcpi_advmss\t\t%d\n", tcpi.tcpi_advmss);
printf("tcpi_reordering\t\t%d\n", tcpi.tcpi_reordering);
printf("\n");
printf("tcpi_rcv_rtt\t\t%d\n", tcpi.tcpi_rcv_rtt);
printf("tcpi_rcv_space\t\t%d\n", tcpi.tcpi_rcv_space);
printf("\n");
if (tcpi.tcpi_total_retrans != 0xdeadbeef) {
printf("tcpi_total_retrans\t%d\n", tcpi.tcpi_total_retrans);
printf("\n");
}
close(fd);
return 0;
}
prev parent reply other threads:[~2004-10-26 13:47 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-10-20 13:01 way of figuring out total number of retransmitted packets on a TCP socket? Lennert Buytenhek
2004-10-20 13:25 ` Baruch Even
2004-10-20 22:16 ` David S. Miller
2004-10-20 22:14 ` David S. Miller
2004-10-20 22:35 ` Lennert Buytenhek
2004-10-20 22:53 ` David S. Miller
2004-10-20 23:04 ` Andi Kleen
2004-10-20 23:07 ` David S. Miller
2004-10-20 23:27 ` Andi Kleen
2004-10-20 23:42 ` David S. Miller
2004-10-21 1:18 ` Arnaldo Carvalho de Melo
2004-10-20 23:44 ` Lennert Buytenhek
2004-10-20 23:44 ` David S. Miller
2004-10-21 9:01 ` Lennert Buytenhek
2004-10-21 4:37 ` David S. Miller
2004-10-26 13:47 ` Lennert Buytenhek [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20041026134702.GA2891@xi.wantstofly.org \
--to=buytenh@wantstofly.org \
--cc=davem@davemloft.net \
--cc=netdev@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).