diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:30:19 -0400 |
---|---|---|
committer | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:45:36 -0400 |
commit | b8c6bcee1dbc1aadcd67af998e414e73fa166a7d (patch) | |
tree | ac391375ffdbb5c3617fcb8672b83c6eff72bbe6 /net/dccp | |
parent | a9c1656ab10480cc6f6d34f193bcde2729fe8037 (diff) |
dccp: Reduce noise in output and convert to ktime_t
This fixes the problem that dccp_probe output can grow quite large without
apparent benefit (many identical data points), creating huge files (up to
over one Gigabyte for a few minutes' test run) which are very hard to
post-process (in one instance it got so bad that gnuplot ate up all memory
plus swap).
The cause for the problem is that the kprobe is inserted into dccp_sendmsg(),
which can be called in a polling-mode (whenever the TX queue is full due to
congestion-control issues, EAGAIN is returned). This creates many very
similar data points, i.e. the increase of processing time does not increase
the quality/information of the probe output.
The fix is to attach the probe to a different function -- write_xmit was
chosen since it gets called continually (both via userspace and timer);
an input-path function would stop sampling as soon as the other end stops
sending feedback.
For comparison the output file sizes for the same 20 second test
run over a lossy link:
* before / without patch: 118 Megabytes
* after / with patch: 1.2 Megabytes
and there was much less noise in the output.
To allow backward compatibility with scripts that people use, the now-unused
`size' field in the output has been replaced with the CCID identifier. This
also serves for future compatibility - support for CCID2 is work in progress
(depends on the still unfinished SRTT/RTTVAR updates).
While at it, the update to ktime_t was also performed.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/probe.c | 66 |
1 files changed, 25 insertions, 41 deletions
diff --git a/net/dccp/probe.c b/net/dccp/probe.c index a87fd4fc1b3d..eaa59d82ab0f 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c | |||
@@ -46,70 +46,54 @@ static struct { | |||
46 | struct kfifo *fifo; | 46 | struct kfifo *fifo; |
47 | spinlock_t lock; | 47 | spinlock_t lock; |
48 | wait_queue_head_t wait; | 48 | wait_queue_head_t wait; |
49 | struct timespec tstart; | 49 | ktime_t start; |
50 | } dccpw; | 50 | } dccpw; |
51 | 51 | ||
52 | static void printl(const char *fmt, ...) | 52 | static void jdccp_write_xmit(struct sock *sk) |
53 | { | ||
54 | va_list args; | ||
55 | int len; | ||
56 | struct timespec now; | ||
57 | char tbuf[256]; | ||
58 | |||
59 | va_start(args, fmt); | ||
60 | getnstimeofday(&now); | ||
61 | |||
62 | now = timespec_sub(now, dccpw.tstart); | ||
63 | |||
64 | len = sprintf(tbuf, "%lu.%06lu ", | ||
65 | (unsigned long) now.tv_sec, | ||
66 | (unsigned long) now.tv_nsec / NSEC_PER_USEC); | ||
67 | len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args); | ||
68 | va_end(args); | ||
69 | |||
70 | kfifo_put(dccpw.fifo, tbuf, len); | ||
71 | wake_up(&dccpw.wait); | ||
72 | } | ||
73 | |||
74 | static int jdccp_sendmsg(struct kiocb *iocb, struct sock *sk, | ||
75 | struct msghdr *msg, size_t size) | ||
76 | { | 53 | { |
77 | const struct inet_sock *inet = inet_sk(sk); | 54 | const struct inet_sock *inet = inet_sk(sk); |
78 | struct ccid3_hc_tx_sock *hctx = NULL; | 55 | struct ccid3_hc_tx_sock *hctx = NULL; |
56 | struct timespec tv; | ||
57 | char buf[256]; | ||
58 | int len, ccid = ccid_get_current_tx_ccid(dccp_sk(sk)); | ||
79 | 59 | ||
80 | if (ccid_get_current_tx_ccid(dccp_sk(sk)) == DCCPC_CCID3) | 60 | if (ccid == DCCPC_CCID3) |
81 | hctx = ccid3_hc_tx_sk(sk); | 61 | hctx = ccid3_hc_tx_sk(sk); |
82 | 62 | ||
83 | if (port == 0 || ntohs(inet->dport) == port || | 63 | if (!port || ntohs(inet->dport) == port || ntohs(inet->sport) == port) { |
84 | ntohs(inet->sport) == port) { | 64 | |
85 | if (hctx) | 65 | tv = ktime_to_timespec(ktime_sub(ktime_get(), dccpw.start)); |
86 | printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %d %d %d %u " | 66 | len = sprintf(buf, "%lu.%09lu %d.%d.%d.%d:%u %d.%d.%d.%d:%u %d", |
87 | "%llu %llu %d\n", | 67 | (unsigned long)tv.tv_sec, |
68 | (unsigned long)tv.tv_nsec, | ||
88 | NIPQUAD(inet->saddr), ntohs(inet->sport), | 69 | NIPQUAD(inet->saddr), ntohs(inet->sport), |
89 | NIPQUAD(inet->daddr), ntohs(inet->dport), size, | 70 | NIPQUAD(inet->daddr), ntohs(inet->dport), ccid); |
71 | |||
72 | if (hctx) | ||
73 | len += sprintf(buf + len, " %d %d %d %u %u %u %d", | ||
90 | hctx->s, hctx->rtt, hctx->p, hctx->x_calc, | 74 | hctx->s, hctx->rtt, hctx->p, hctx->x_calc, |
91 | hctx->x_recv >> 6, hctx->x >> 6, hctx->t_ipi); | 75 | (unsigned)(hctx->x_recv >> 6), |
92 | else | 76 | (unsigned)(hctx->x >> 6), hctx->t_ipi); |
93 | printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d\n", | 77 | |
94 | NIPQUAD(inet->saddr), ntohs(inet->sport), | 78 | len += sprintf(buf + len, "\n"); |
95 | NIPQUAD(inet->daddr), ntohs(inet->dport), size); | 79 | kfifo_put(dccpw.fifo, buf, len); |
80 | wake_up(&dccpw.wait); | ||
96 | } | 81 | } |
97 | 82 | ||
98 | jprobe_return(); | 83 | jprobe_return(); |
99 | return 0; | ||
100 | } | 84 | } |
101 | 85 | ||
102 | static struct jprobe dccp_send_probe = { | 86 | static struct jprobe dccp_send_probe = { |
103 | .kp = { | 87 | .kp = { |
104 | .symbol_name = "dccp_sendmsg", | 88 | .symbol_name = "dccp_write_xmit", |
105 | }, | 89 | }, |
106 | .entry = jdccp_sendmsg, | 90 | .entry = jdccp_write_xmit, |
107 | }; | 91 | }; |
108 | 92 | ||
109 | static int dccpprobe_open(struct inode *inode, struct file *file) | 93 | static int dccpprobe_open(struct inode *inode, struct file *file) |
110 | { | 94 | { |
111 | kfifo_reset(dccpw.fifo); | 95 | kfifo_reset(dccpw.fifo); |
112 | getnstimeofday(&dccpw.tstart); | 96 | dccpw.start = ktime_get(); |
113 | return 0; | 97 | return 0; |
114 | } | 98 | } |
115 | 99 | ||