]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.20-nethashfix2.patch
- added description of djurban's branch
[packages/kernel.git] / linux-2.4.20-nethashfix2.patch
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    
14 #
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 # --------------------------------------------
26 #
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
30 @@ -295,7 +295,8 @@
31         NET_IPV4_NONLOCAL_BIND=88,
32         NET_IPV4_ICMP_RATELIMIT=89,
33         NET_IPV4_ICMP_RATEMASK=90,
34 -       NET_TCP_TW_REUSE=91
35 +       NET_TCP_TW_REUSE=91,
36 +       NET_IPV4_IPFRAG_SECRET_INTERVAL=94
37  };
38  
39  enum {
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
43 @@ -15,6 +15,8 @@
44  
45  struct flowi;
46  
47 +extern void                            ipv6_frag_init(void);
48 +
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
55 @@ -1100,6 +1100,7 @@
56         }
57  }
58  
59 +extern void ipfrag_init(void);
60  
61  /*
62   *     Called by socket.c on kernel startup.  
63 @@ -1196,6 +1197,9 @@
64         proc_net_create ("tcp", 0, tcp_get_info);
65         proc_net_create ("udp", 0, udp_get_info);
66  #endif         /* CONFIG_PROC_FS */
67 +
68 +       ipfrag_init();
69 +
70         return 0;
71  }
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
76 @@ -31,6 +31,8 @@
77  #include <linux/ip.h>
78  #include <linux/icmp.h>
79  #include <linux/netdevice.h>
80 +#include <linux/jhash.h>
81 +#include <linux/random.h>
82  #include <net/sock.h>
83  #include <net/ip.h>
84  #include <net/icmp.h>
85 @@ -97,6 +99,7 @@
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;
91  
92  static __inline__ void __ipq_unlink(struct ipq *qp)
93 @@ -116,21 +119,51 @@
94         write_unlock(&ipfrag_lock);
95  }
96  
97 -/*
98 - * Was:        ((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
99 - *
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)
102 - */
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)
105  {
106 -       unsigned int h = saddr ^ daddr;
107 -
108 -       h ^= (h>>16)^id;
109 -       h ^= (h>>8)^prot;
110 -       return h & (IPQ_HASHSZ - 1);
111 +       return jhash_3words((u32)id << 16 | prot, saddr, daddr,
112 +                           ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
113  }
114  
115 +static struct timer_list ipfrag_secret_timer;
116 +int sysctl_ipfrag_secret_interval = 10 * 60 * HZ;
117 +
118 +static void ipfrag_secret_rebuild(unsigned long dummy)
119 +{
120 +       unsigned long now = jiffies;
121 +       int i;
122 +
123 +       write_lock(&ipfrag_lock);
124 +       get_random_bytes(&ipfrag_hash_rnd, sizeof(u32));
125 +       for (i = 0; i < IPQ_HASHSZ; i++) {
126 +               struct ipq *q;
127 +
128 +               q = ipq_hash[i];
129 +               while (q) {
130 +                       struct ipq *next = q->next;
131 +                       unsigned int hval = ipqhashfn(q->id, q->saddr,
132 +                                                     q->daddr, q->protocol);
133 +
134 +                       if (hval != i) {
135 +                               /* Unlink. */
136 +                               if (q->next)
137 +                                       q->next->pprev = q->pprev;
138 +                               *q->pprev = q->next;
139 +
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];
145 +                       }
146 +
147 +                       q = next;
148 +               }
149 +       }
150 +       write_unlock(&ipfrag_lock);
151 +
152 +       mod_timer(&ipfrag_secret_timer, now + sysctl_ipfrag_secret_interval);
153 +}
154  
155  atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */
156  
157 @@ -630,4 +663,15 @@
158         IP_INC_STATS_BH(IpReasmFails);
159         kfree_skb(skb);
160         return NULL;
161 +}
162 +
163 +void ipfrag_init(void)
164 +{
165 +       ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
166 +                                (jiffies ^ (jiffies >> 6)));
167 +
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);
172  }
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
176 @@ -27,6 +27,7 @@
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;
181  
182  /* From ip_output.c */
183  extern int sysctl_ip_dynaddr;
184 @@ -225,6 +226,9 @@
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, 
190 +        &sysctl_jiffies},
191         {0}
192  };
193  
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
197 @@ -671,6 +671,7 @@
198         ip6_flowlabel_init();
199         addrconf_init();
200         sit_init();
201 +       ipv6_frag_init();
202  
203         /* Init v6 transport protocols. */
204         udpv6_init();
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
208 @@ -37,6 +37,8 @@
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>
214  
215  #include <net/sock.h>
216  #include <net/snmp.h>
217 @@ -98,6 +100,7 @@
218  
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;
223  
224  static __inline__ void __fq_unlink(struct frag_queue *fq)
225 @@ -117,16 +120,73 @@
226         write_unlock(&ip6_frag_lock);
227  }
228  
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)
233  {
234 -       unsigned int h = saddr->s6_addr32[3] ^ daddr->s6_addr32[3] ^ id;
235 +       u32 a, b, c;
236  
237 -       h ^= (h>>16);
238 -       h ^= (h>>8);
239 -       return h & (IP6Q_HASHSZ - 1);
240 +       a = saddr->s6_addr32[0];
241 +       b = saddr->s6_addr32[1];
242 +       c = saddr->s6_addr32[2];
243 +
244 +       a += JHASH_GOLDEN_RATIO;
245 +       b += JHASH_GOLDEN_RATIO;
246 +       c += ip6_frag_hash_rnd;
247 +       __jhash_mix(a, b, c);
248 +
249 +       a += saddr->s6_addr32[3];
250 +       b += daddr->s6_addr32[0];
251 +       c += daddr->s6_addr32[1];
252 +       __jhash_mix(a, b, c);
253 +
254 +       a += daddr->s6_addr32[2];
255 +       b += daddr->s6_addr32[3];
256 +       c += id;
257 +       __jhash_mix(a, b, c);
258 +
259 +       return c & (IP6Q_HASHSZ - 1);
260  }
261  
262 +static struct timer_list ip6_frag_secret_timer;
263 +static int ip6_frag_secret_interval = 10 * 60 * HZ;
264 +
265 +static void ip6_frag_secret_rebuild(unsigned long dummy)
266 +{
267 +       unsigned long now = jiffies;
268 +       int i;
269 +
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;
274 +
275 +               q = ip6_frag_hash[i];
276 +               while (q) {
277 +                       struct frag_queue *next = q->next;
278 +                       unsigned int hval = ip6qhashfn(q->id,
279 +                                                      &q->saddr,
280 +                                                      &q->daddr);
281 +
282 +                       if (hval != i) {
283 +                               /* Unlink. */
284 +                               if (q->next)
285 +                                       q->next->pprev = q->pprev;
286 +                               *q->pprev = q->next;
287 +
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];
293 +                       }
294 +
295 +                       q = next;
296 +               }
297 +       }
298 +       write_unlock(&ip6_frag_lock);
299 +
300 +       mod_timer(&ip6_frag_secret_timer, now + ip6_frag_secret_interval);
301 +}
302  
303  atomic_t ip6_frag_mem = ATOMIC_INIT(0);
304  
305 @@ -680,4 +740,15 @@
306         IP6_INC_STATS_BH(Ip6ReasmFails);
307         kfree_skb(skb);
308         return -1;
309 +}
310 +
311 +void __init ipv6_frag_init(void)
312 +{
313 +       ip6_frag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
314 +                                  (jiffies ^ (jiffies >> 6)));
315 +
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);
320  }
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
324 @@ -371,9 +371,22 @@
325  
326  static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd)
327  {
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));
331 +       u32 a, b, c;
332 +
333 +       a = raddr->s6_addr32[0];
334 +       b = raddr->s6_addr32[1];
335 +       c = raddr->s6_addr32[2];
336 +
337 +       a += JHASH_GOLDEN_RATIO;
338 +       b += JHASH_GOLDEN_RATIO;
339 +       c += rnd;
340 +       __jhash_mix(a, b, c);
341 +
342 +       a += raddr->s6_addr32[3];
343 +       b += (u32) rport;
344 +       __jhash_mix(a, b, c);
345 +
346 +       return c & (TCP_SYNQ_HSIZE - 1);
347  }
348  
349  static struct open_request *tcp_v6_search_req(struct tcp_opt *tp,
This page took 1.284567 seconds and 3 git commands to generate.