aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2010-01-25 18:47:50 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-25 18:47:50 -0500
commitf81074f86176605bfbfafb9944e27628a4e26ce6 (patch)
treeea963e08a132523327986c99ea63768593d5701a
parent4f9a91c81273b66afe0b6a9be460b47581b28246 (diff)
tcp_probe: avoid modulus operation and wrap fix
By rounding up the buffer size to power of 2, several expensive modulus operations can be avoided. This patch also solves a bug where the gap need when ring gets full was not being accounted for. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/tcp_probe.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index bb110c5ce1d2..9bc805df95d2 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -39,9 +39,9 @@ static int port __read_mostly = 0;
39MODULE_PARM_DESC(port, "Port to match (0=all)"); 39MODULE_PARM_DESC(port, "Port to match (0=all)");
40module_param(port, int, 0); 40module_param(port, int, 0);
41 41
42static int bufsize __read_mostly = 4096; 42static unsigned int bufsize __read_mostly = 4096;
43MODULE_PARM_DESC(bufsize, "Log buffer size in packets (4096)"); 43MODULE_PARM_DESC(bufsize, "Log buffer size in packets (4096)");
44module_param(bufsize, int, 0); 44module_param(bufsize, uint, 0);
45 45
46static int full __read_mostly; 46static int full __read_mostly;
47MODULE_PARM_DESC(full, "Full log (1=every ack packet received, 0=only cwnd changes)"); 47MODULE_PARM_DESC(full, "Full log (1=every ack packet received, 0=only cwnd changes)");
@@ -75,12 +75,12 @@ static struct {
75 75
76static inline int tcp_probe_used(void) 76static inline int tcp_probe_used(void)
77{ 77{
78 return (tcp_probe.head - tcp_probe.tail) % bufsize; 78 return (tcp_probe.head - tcp_probe.tail) & (bufsize - 1);
79} 79}
80 80
81static inline int tcp_probe_avail(void) 81static inline int tcp_probe_avail(void)
82{ 82{
83 return bufsize - tcp_probe_used(); 83 return bufsize - tcp_probe_used() - 1;
84} 84}
85 85
86/* 86/*
@@ -116,7 +116,7 @@ static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
116 p->ssthresh = tcp_current_ssthresh(sk); 116 p->ssthresh = tcp_current_ssthresh(sk);
117 p->srtt = tp->srtt >> 3; 117 p->srtt = tp->srtt >> 3;
118 118
119 tcp_probe.head = (tcp_probe.head + 1) % bufsize; 119 tcp_probe.head = (tcp_probe.head + 1) & (bufsize - 1);
120 } 120 }
121 tcp_probe.lastcwnd = tp->snd_cwnd; 121 tcp_probe.lastcwnd = tp->snd_cwnd;
122 spin_unlock(&tcp_probe.lock); 122 spin_unlock(&tcp_probe.lock);
@@ -149,7 +149,7 @@ static int tcpprobe_open(struct inode * inode, struct file * file)
149static int tcpprobe_sprint(char *tbuf, int n) 149static int tcpprobe_sprint(char *tbuf, int n)
150{ 150{
151 const struct tcp_log *p 151 const struct tcp_log *p
152 = tcp_probe.log + tcp_probe.tail % bufsize; 152 = tcp_probe.log + tcp_probe.tail;
153 struct timespec tv 153 struct timespec tv
154 = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start)); 154 = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start));
155 155
@@ -192,7 +192,7 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf,
192 width = tcpprobe_sprint(tbuf, sizeof(tbuf)); 192 width = tcpprobe_sprint(tbuf, sizeof(tbuf));
193 193
194 if (cnt + width < len) 194 if (cnt + width < len)
195 tcp_probe.tail = (tcp_probe.tail + 1) % bufsize; 195 tcp_probe.tail = (tcp_probe.tail + 1) & (bufsize - 1);
196 196
197 spin_unlock_bh(&tcp_probe.lock); 197 spin_unlock_bh(&tcp_probe.lock);
198 198
@@ -222,9 +222,10 @@ static __init int tcpprobe_init(void)
222 init_waitqueue_head(&tcp_probe.wait); 222 init_waitqueue_head(&tcp_probe.wait);
223 spin_lock_init(&tcp_probe.lock); 223 spin_lock_init(&tcp_probe.lock);
224 224
225 if (bufsize < 0) 225 if (bufsize == 0)
226 return -EINVAL; 226 return -EINVAL;
227 227
228 bufsize = roundup_pow_of_two(bufsize);
228 tcp_probe.log = kcalloc(bufsize, sizeof(struct tcp_log), GFP_KERNEL); 229 tcp_probe.log = kcalloc(bufsize, sizeof(struct tcp_log), GFP_KERNEL);
229 if (!tcp_probe.log) 230 if (!tcp_probe.log)
230 goto err0; 231 goto err0;
@@ -236,7 +237,7 @@ static __init int tcpprobe_init(void)
236 if (ret) 237 if (ret)
237 goto err1; 238 goto err1;
238 239
239 pr_info("TCP probe registered (port=%d)\n", port); 240 pr_info("TCP probe registered (port=%d) bufsize=%u\n", port, bufsize);
240 return 0; 241 return 0;
241 err1: 242 err1:
242 proc_net_remove(&init_net, procname); 243 proc_net_remove(&init_net, procname);