Saturday, July 09, 2011

per-socket statistics

Think twice before you pick the source of information about network behaviour…
Especially, /proc/$PID/net and friends are _not_ process-dependent as you might think. At least, not until your process got a dedicated _namespace_ to work with. So yes, every `struct sock` has a sk_net field that eventually leads to some statistics (`sock->sk_net->mib.net_statistics`), but if you look closely enough, e.g. by hooking one of the less frequent system calls and insert the following:

      {  // DEBUG CHECK
    struct net* n = sk?sk->sk_net:0;
    struct inet_connection_sock* ics = inet_csk(sk); // see net/inet_connection_sock.h
    struct tcp_sock* ts=tcp_sk(sk); // see linux/tcp.h

    printk(KERN_ERR “socket %p (#%i) has net@%p and stats@%p\n”,
    sk, index, n, n?n->mib.net_statistics:(void*)0xdeadbeef);

You’ll see in your logs reports of various sockets addresses that all share the same net@xxxxxxxx and stats@yyyyyyyy … in other words, whatever you read there is not specific. Only if two sockets are in different namespaces (which could occur due to virtualization, chrooting and similar effects), they will have distinct statistics … if they’re from distinct process, that is. All the connections from your firefox browser will still share the same “fate” here.

So what should we look for ?

Well, give a look at the `tcp_get_info()` function, for instance. At the request of some `getsockopt()` call from user-land, it starts filling a `tcp_info` structure with information coming from the different “layers” of the `sock` structure. TCP retransmissions, for instance, are present in `inet_connection_sock.icsk_retransmits`. Running estimation of the RTT (yes, TCP does that for you) can be found in `tcp_sock.rcv_rtt_est`, and so on.

Always hunt for first-hand information.

No comments: