1 # This is a BitKeeper generated patch for the following project:
2 # Project Name: Linux kernel tree
3 # This patch format is intended for GNU patch command version 2.5 or higher.
4 # This patch includes the following deltas:
5 # ChangeSet 1.1226 -> 1.1229
6 # include/linux/sysctl.h 1.23 -> 1.24
7 # net/ipv6/tcp_ipv6.c 1.23 -> 1.24
8 # net/ipv6/af_inet6.c 1.9 -> 1.10
9 # net/ipv4/af_inet.c 1.10 -> 1.11
10 # net/ipv4/ip_fragment.c 1.6 -> 1.8
11 # net/ipv6/reassembly.c 1.6 -> 1.7
12 # include/net/transp_v6.h 1.1 -> 1.2
13 # net/ipv4/sysctl_net_ipv4.c 1.8 -> 1.9
15 # The following is the BitKeeper ChangeSet Log
16 # --------------------------------------------
17 # 03/05/27 davem@nuts.ninka.net 1.1227
18 # [IPV4/IPV6]: Use Jenkins hash for fragment reassembly handling.
19 # --------------------------------------------
20 # 03/05/27 davem@nuts.ninka.net 1.1228
21 # [IPV6]: Input full addresses into TCP_SYNQ hash function.
22 # --------------------------------------------
23 # 03/05/28 davem@nuts.ninka.net 1.1229
24 # [IPV4]: Add sysctl to control ipfrag_secret_interval.
25 # --------------------------------------------
27 diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
28 --- a/include/linux/sysctl.h Wed May 28 01:21:40 2003
29 +++ b/include/linux/sysctl.h Wed May 28 01:21:40 2003
31 NET_IPV4_NONLOCAL_BIND=88,
32 NET_IPV4_ICMP_RATELIMIT=89,
33 NET_IPV4_ICMP_RATEMASK=90,
35 + NET_TCP_TW_REUSE=91,
36 + NET_IPV4_IPFRAG_SECRET_INTERVAL=94
40 diff -Nru a/include/net/transp_v6.h b/include/net/transp_v6.h
41 --- a/include/net/transp_v6.h Wed May 28 01:21:40 2003
42 +++ b/include/net/transp_v6.h Wed May 28 01:21:40 2003
47 +extern void ipv6_frag_init(void);
49 extern void rawv6_init(void);
50 extern void udpv6_init(void);
51 extern void tcpv6_init(void);
52 diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
53 --- a/net/ipv4/af_inet.c Wed May 28 01:21:40 2003
54 +++ b/net/ipv4/af_inet.c Wed May 28 01:21:40 2003
59 +extern void ipfrag_init(void);
62 * Called by socket.c on kernel startup.
64 proc_net_create ("tcp", 0, tcp_get_info);
65 proc_net_create ("udp", 0, udp_get_info);
66 #endif /* CONFIG_PROC_FS */
72 module_init(inet_init);
73 diff -Nru a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
74 --- a/net/ipv4/ip_fragment.c Wed May 28 01:21:40 2003
75 +++ b/net/ipv4/ip_fragment.c Wed May 28 01:21:40 2003
78 #include <linux/icmp.h>
79 #include <linux/netdevice.h>
80 +#include <linux/jhash.h>
81 +#include <linux/random.h>
86 /* Per-bucket lock is easy to add now. */
87 static struct ipq *ipq_hash[IPQ_HASHSZ];
88 static rwlock_t ipfrag_lock = RW_LOCK_UNLOCKED;
89 +static u32 ipfrag_hash_rnd;
90 int ip_frag_nqueues = 0;
92 static __inline__ void __ipq_unlink(struct ipq *qp)
94 write_unlock(&ipfrag_lock);
98 - * Was: ((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
100 - * I see, I see evil hand of bigendian mafia. On Intel all the packets hit
101 - * one hash bucket with this hash function. 8)
103 -static __inline__ unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot)
104 +static unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot)
106 - unsigned int h = saddr ^ daddr;
110 - return h & (IPQ_HASHSZ - 1);
111 + return jhash_3words((u32)id << 16 | prot, saddr, daddr,
112 + ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
115 +static struct timer_list ipfrag_secret_timer;
116 +int sysctl_ipfrag_secret_interval = 10 * 60 * HZ;
118 +static void ipfrag_secret_rebuild(unsigned long dummy)
120 + unsigned long now = jiffies;
123 + write_lock(&ipfrag_lock);
124 + get_random_bytes(&ipfrag_hash_rnd, sizeof(u32));
125 + for (i = 0; i < IPQ_HASHSZ; i++) {
130 + struct ipq *next = q->next;
131 + unsigned int hval = ipqhashfn(q->id, q->saddr,
132 + q->daddr, q->protocol);
137 + q->next->pprev = q->pprev;
138 + *q->pprev = q->next;
140 + /* Relink to new hash chain. */
141 + if ((q->next = ipq_hash[hval]) != NULL)
142 + q->next->pprev = &q->next;
143 + ipq_hash[hval] = q;
144 + q->pprev = &ipq_hash[hval];
150 + write_unlock(&ipfrag_lock);
152 + mod_timer(&ipfrag_secret_timer, now + sysctl_ipfrag_secret_interval);
155 atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */
158 IP_INC_STATS_BH(IpReasmFails);
163 +void ipfrag_init(void)
165 + ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
166 + (jiffies ^ (jiffies >> 6)));
168 + init_timer(&ipfrag_secret_timer);
169 + ipfrag_secret_timer.function = ipfrag_secret_rebuild;
170 + ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
171 + add_timer(&ipfrag_secret_timer);
173 diff -Nru a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
174 --- a/net/ipv4/sysctl_net_ipv4.c Wed May 28 01:21:40 2003
175 +++ b/net/ipv4/sysctl_net_ipv4.c Wed May 28 01:21:40 2003
177 extern int sysctl_ipfrag_low_thresh;
178 extern int sysctl_ipfrag_high_thresh;
179 extern int sysctl_ipfrag_time;
180 +extern int sysctl_ipfrag_secret_interval;
182 /* From ip_output.c */
183 extern int sysctl_ip_dynaddr;
185 &sysctl_icmp_ratemask, sizeof(int), 0644, NULL, &proc_dointvec},
186 {NET_TCP_TW_REUSE, "tcp_tw_reuse",
187 &sysctl_tcp_tw_reuse, sizeof(int), 0644, NULL, &proc_dointvec},
188 + {NET_IPV4_IPFRAG_SECRET_INTERVAL, "ipfrag_secret_interval",
189 + &sysctl_ipfrag_secret_interval, sizeof(int), 0644, NULL, &proc_dointvec_jiffies,
194 diff -Nru a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
195 --- a/net/ipv6/af_inet6.c Wed May 28 01:21:40 2003
196 +++ b/net/ipv6/af_inet6.c Wed May 28 01:21:40 2003
198 ip6_flowlabel_init();
203 /* Init v6 transport protocols. */
205 diff -Nru a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
206 --- a/net/ipv6/reassembly.c Wed May 28 01:21:40 2003
207 +++ b/net/ipv6/reassembly.c Wed May 28 01:21:40 2003
209 #include <linux/in6.h>
210 #include <linux/ipv6.h>
211 #include <linux/icmpv6.h>
212 +#include <linux/random.h>
213 +#include <linux/jhash.h>
215 #include <net/sock.h>
216 #include <net/snmp.h>
219 static struct frag_queue *ip6_frag_hash[IP6Q_HASHSZ];
220 static rwlock_t ip6_frag_lock = RW_LOCK_UNLOCKED;
221 +static u32 ip6_frag_hash_rnd;
222 int ip6_frag_nqueues = 0;
224 static __inline__ void __fq_unlink(struct frag_queue *fq)
225 @@ -117,16 +120,73 @@
226 write_unlock(&ip6_frag_lock);
229 -static __inline__ unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
230 - struct in6_addr *daddr)
231 +static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
232 + struct in6_addr *daddr)
234 - unsigned int h = saddr->s6_addr32[3] ^ daddr->s6_addr32[3] ^ id;
239 - return h & (IP6Q_HASHSZ - 1);
240 + a = saddr->s6_addr32[0];
241 + b = saddr->s6_addr32[1];
242 + c = saddr->s6_addr32[2];
244 + a += JHASH_GOLDEN_RATIO;
245 + b += JHASH_GOLDEN_RATIO;
246 + c += ip6_frag_hash_rnd;
247 + __jhash_mix(a, b, c);
249 + a += saddr->s6_addr32[3];
250 + b += daddr->s6_addr32[0];
251 + c += daddr->s6_addr32[1];
252 + __jhash_mix(a, b, c);
254 + a += daddr->s6_addr32[2];
255 + b += daddr->s6_addr32[3];
257 + __jhash_mix(a, b, c);
259 + return c & (IP6Q_HASHSZ - 1);
262 +static struct timer_list ip6_frag_secret_timer;
263 +static int ip6_frag_secret_interval = 10 * 60 * HZ;
265 +static void ip6_frag_secret_rebuild(unsigned long dummy)
267 + unsigned long now = jiffies;
270 + write_lock(&ip6_frag_lock);
271 + get_random_bytes(&ip6_frag_hash_rnd, sizeof(u32));
272 + for (i = 0; i < IP6Q_HASHSZ; i++) {
273 + struct frag_queue *q;
275 + q = ip6_frag_hash[i];
277 + struct frag_queue *next = q->next;
278 + unsigned int hval = ip6qhashfn(q->id,
285 + q->next->pprev = q->pprev;
286 + *q->pprev = q->next;
288 + /* Relink to new hash chain. */
289 + if ((q->next = ip6_frag_hash[hval]) != NULL)
290 + q->next->pprev = &q->next;
291 + ip6_frag_hash[hval] = q;
292 + q->pprev = &ip6_frag_hash[hval];
298 + write_unlock(&ip6_frag_lock);
300 + mod_timer(&ip6_frag_secret_timer, now + ip6_frag_secret_interval);
303 atomic_t ip6_frag_mem = ATOMIC_INIT(0);
306 IP6_INC_STATS_BH(Ip6ReasmFails);
311 +void __init ipv6_frag_init(void)
313 + ip6_frag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
314 + (jiffies ^ (jiffies >> 6)));
316 + init_timer(&ip6_frag_secret_timer);
317 + ip6_frag_secret_timer.function = ip6_frag_secret_rebuild;
318 + ip6_frag_secret_timer.expires = jiffies + ip6_frag_secret_interval;
319 + add_timer(&ip6_frag_secret_timer);
321 diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
322 --- a/net/ipv6/tcp_ipv6.c Wed May 28 01:21:40 2003
323 +++ b/net/ipv6/tcp_ipv6.c Wed May 28 01:21:40 2003
326 static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd)
328 - return (jhash_3words(raddr->s6_addr32[0] ^ raddr->s6_addr32[1],
329 - raddr->s6_addr32[2] ^ raddr->s6_addr32[3],
330 - (u32) rport, rnd) & (TCP_SYNQ_HSIZE - 1));
333 + a = raddr->s6_addr32[0];
334 + b = raddr->s6_addr32[1];
335 + c = raddr->s6_addr32[2];
337 + a += JHASH_GOLDEN_RATIO;
338 + b += JHASH_GOLDEN_RATIO;
340 + __jhash_mix(a, b, c);
342 + a += raddr->s6_addr32[3];
344 + __jhash_mix(a, b, c);
346 + return c & (TCP_SYNQ_HSIZE - 1);
349 static struct open_request *tcp_v6_search_req(struct tcp_opt *tp,