X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=net%2Fipv4%2Ftcp_probe.c;h=3938d5dbdf208292157573aa6448e088505a3145;hb=da99f0565477899f08b76ffcb32afbf6fa95d64a;hp=4be336f17883ca21e129fd93a146d6e73c338fb1;hpb=97d41e90fe61399b99d74820cb7f2d6e0fbac91d;p=powerpc.git diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index 4be336f178..3938d5dbdf 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c @@ -26,51 +26,55 @@ #include #include #include +#include +#include #include #include -MODULE_AUTHOR("Stephen Hemminger "); +MODULE_AUTHOR("Stephen Hemminger "); MODULE_DESCRIPTION("TCP cwnd snooper"); MODULE_LICENSE("GPL"); -static int port = 0; +static int port __read_mostly = 0; MODULE_PARM_DESC(port, "Port to match (0=all)"); module_param(port, int, 0); -static int bufsize = 64*1024; +static int bufsize __read_mostly = 64*1024; MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)"); module_param(bufsize, int, 0); +static int full __read_mostly; +MODULE_PARM_DESC(full, "Full log (1=every ack packet received, 0=only cwnd changes)"); +module_param(full, int, 0); + static const char procname[] = "tcpprobe"; struct { - struct kfifo *fifo; - spinlock_t lock; + struct kfifo *fifo; + spinlock_t lock; wait_queue_head_t wait; - struct timeval tstart; + ktime_t start; + u32 lastcwnd; } tcpw; +/* + * Print to log with timestamps. + * FIXME: causes an extra copy + */ static void printl(const char *fmt, ...) { va_list args; int len; - struct timeval now; + struct timespec tv; char tbuf[256]; va_start(args, fmt); - do_gettimeofday(&now); + /* want monotonic time since start of tcp_probe */ + tv = ktime_to_timespec(ktime_sub(ktime_get(), tcpw.start)); - now.tv_sec -= tcpw.tstart.tv_sec; - now.tv_usec -= tcpw.tstart.tv_usec; - if (now.tv_usec < 0) { - --now.tv_sec; - now.tv_usec += 1000000; - } - - len = sprintf(tbuf, "%lu.%06lu ", - (unsigned long) now.tv_sec, - (unsigned long) now.tv_usec); + len = sprintf(tbuf, "%lu.%09lu ", + (unsigned long) tv.tv_sec, (unsigned long) tv.tv_nsec); len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args); va_end(args); @@ -78,38 +82,44 @@ static void printl(const char *fmt, ...) wake_up(&tcpw.wait); } -static int jtcp_sendmsg(struct kiocb *iocb, struct sock *sk, - struct msghdr *msg, size_t size) +/* + * Hook inserted to be called before each receive packet. + * Note: arguments must match tcp_rcv_established()! + */ +static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb, + struct tcphdr *th, unsigned len) { const struct tcp_sock *tp = tcp_sk(sk); const struct inet_sock *inet = inet_sk(sk); - if (port == 0 || ntohs(inet->dport) == port || - ntohs(inet->sport) == port) { + /* Only update if port matches */ + if ((port == 0 || ntohs(inet->dport) == port || ntohs(inet->sport) == port) + && (full || tp->snd_cwnd != tcpw.lastcwnd)) { printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %#x %#x %u %u %u\n", NIPQUAD(inet->saddr), ntohs(inet->sport), NIPQUAD(inet->daddr), ntohs(inet->dport), - size, tp->snd_nxt, tp->snd_una, + skb->len, tp->snd_nxt, tp->snd_una, tp->snd_cwnd, tcp_current_ssthresh(sk), - tp->snd_wnd); + tp->snd_wnd, tp->srtt >> 3); + tcpw.lastcwnd = tp->snd_cwnd; } jprobe_return(); return 0; } -static struct jprobe tcp_send_probe = { +static struct jprobe tcp_probe = { .kp = { - .symbol_name = "tcp_sendmsg", + .symbol_name = "tcp_rcv_established", }, - .entry = JPROBE_ENTRY(jtcp_sendmsg), + .entry = JPROBE_ENTRY(jtcp_rcv_established), }; static int tcpprobe_open(struct inode * inode, struct file * file) { kfifo_reset(tcpw.fifo); - do_gettimeofday(&tcpw.tstart); + tcpw.start = ktime_get(); return 0; } @@ -143,7 +153,7 @@ out_free: return error ? error : cnt; } -static struct file_operations tcpprobe_fops = { +static const struct file_operations tcpprobe_fops = { .owner = THIS_MODULE, .open = tcpprobe_open, .read = tcpprobe_read, @@ -156,11 +166,13 @@ static __init int tcpprobe_init(void) init_waitqueue_head(&tcpw.wait); spin_lock_init(&tcpw.lock); tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock); + if (IS_ERR(tcpw.fifo)) + return PTR_ERR(tcpw.fifo); if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops)) goto err0; - ret = register_jprobe(&tcp_send_probe); + ret = register_jprobe(&tcp_probe); if (ret) goto err1; @@ -178,7 +190,7 @@ static __exit void tcpprobe_exit(void) { kfifo_free(tcpw.fifo); proc_net_remove(procname); - unregister_jprobe(&tcp_send_probe); + unregister_jprobe(&tcp_probe); } module_exit(tcpprobe_exit);