]> git.pld-linux.org Git - packages/kernel.git/blame - 01_alt_routes-2.5.50-8.diff
+CONFIG_IP_NF_MATCH_LAYER7=m
[packages/kernel.git] / 01_alt_routes-2.5.50-8.diff
CommitLineData
2581e8f3 1diff -ur v2.5.50/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h
2--- v2.5.50/linux/include/linux/rtnetlink.h Thu Oct 31 04:03:27 2002
3+++ linux/include/linux/rtnetlink.h Sun Dec 1 17:04:46 2002
4@@ -229,6 +229,8 @@
5 #define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */
6 #define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */
7 #define RTNH_F_ONLINK 4 /* Gateway is forced on link */
8+#define RTNH_F_SUSPECT 8 /* We don't know the real state */
9+#define RTNH_F_BADSTATE (RTNH_F_DEAD | RTNH_F_SUSPECT)
10
11 /* Macros to handle hexthops */
12
13diff -ur v2.5.50/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
14--- v2.5.50/linux/include/net/ip_fib.h Tue Nov 19 00:13:38 2002
15+++ linux/include/net/ip_fib.h Sun Dec 1 17:04:46 2002
16@@ -162,7 +162,8 @@
17
18 static inline void fib_select_default(const struct flowi *flp, struct fib_result *res)
19 {
20- if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
21+ if ((FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) ||
22+ FIB_RES_NH(*res).nh_scope == RT_SCOPE_HOST)
23 ip_fib_main_table->tb_select_default(ip_fib_main_table, flp, res);
24 }
25
26@@ -174,6 +175,7 @@
27 extern int fib_lookup(const struct flowi *flp, struct fib_result *res);
28 extern struct fib_table *__fib_new_table(int id);
29 extern void fib_rule_put(struct fib_rule *r);
30+extern __inline__ int fib_result_table(struct fib_result *res);
31
32 static inline struct fib_table *fib_get_table(int id)
33 {
34diff -ur v2.5.50/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
35--- v2.5.50/linux/net/ipv4/fib_frontend.c Thu Oct 17 03:43:21 2002
36+++ linux/net/ipv4/fib_frontend.c Sun Dec 1 17:04:46 2002
37@@ -53,6 +53,8 @@
38 struct fib_table *ip_fib_local_table;
39 struct fib_table *ip_fib_main_table;
40
41+#define FIB_RES_TABLE(r) (RT_TABLE_MAIN)
42+
43 #else
44
45 #define RT_TABLE_MIN 1
46@@ -70,6 +72,7 @@
47 return tb;
48 }
49
50+#define FIB_RES_TABLE(r) (fib_result_table(r))
51
52 #endif /* CONFIG_IP_MULTIPLE_TABLES */
53
54@@ -167,6 +170,9 @@
55 .tos = tos } },
56 .iif = oif };
57 struct fib_result res;
58+ int table;
59+ unsigned char prefixlen;
60+ unsigned char scope;
61 int no_addr, rpf;
62 int ret;
63
64@@ -188,31 +194,35 @@
65 goto e_inval_res;
66 *spec_dst = FIB_RES_PREFSRC(res);
67 fib_combine_itag(itag, &res);
68-#ifdef CONFIG_IP_ROUTE_MULTIPATH
69- if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
70-#else
71 if (FIB_RES_DEV(res) == dev)
72-#endif
73 {
74 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
75 fib_res_put(&res);
76 return ret;
77 }
78+ table = FIB_RES_TABLE(&res);
79+ prefixlen = res.prefixlen;
80+ scope = res.scope;
81 fib_res_put(&res);
82 if (no_addr)
83 goto last_resort;
84- if (rpf)
85- goto e_inval;
86 fl.oif = dev->ifindex;
87
88 ret = 0;
89 if (fib_lookup(&fl, &res) == 0) {
90- if (res.type == RTN_UNICAST) {
91+ if (res.type == RTN_UNICAST &&
92+ ((table == FIB_RES_TABLE(&res) &&
93+ res.prefixlen >= prefixlen && res.scope >= scope) ||
94+ !rpf)) {
95 *spec_dst = FIB_RES_PREFSRC(res);
96 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
97+ fib_res_put(&res);
98+ return ret;
99 }
100 fib_res_put(&res);
101 }
102+ if (rpf)
103+ goto e_inval;
104 return ret;
105
106 last_resort:
107diff -ur v2.5.50/linux/net/ipv4/fib_hash.c linux/net/ipv4/fib_hash.c
108--- v2.5.50/linux/net/ipv4/fib_hash.c Tue Nov 19 00:13:40 2002
109+++ linux/net/ipv4/fib_hash.c Sun Dec 1 17:04:46 2002
110@@ -71,6 +71,7 @@
111 struct fib_info *fn_info;
112 #define FIB_INFO(f) ((f)->fn_info)
113 fn_key_t fn_key;
114+ int fn_last_dflt;
115 u8 fn_tos;
116 u8 fn_type;
117 u8 fn_scope;
118@@ -312,72 +313,120 @@
119 return err;
120 }
121
122-static int fn_hash_last_dflt=-1;
123-
124-static int fib_detect_death(struct fib_info *fi, int order,
125- struct fib_info **last_resort, int *last_idx)
126+static int fib_detect_death(struct fib_info *fi, int order, int last_dflt,
127+ struct fib_info **last_resort, int *last_idx,
128+ int *last_nhsel, const struct flowi *flp)
129 {
130 struct neighbour *n;
131- int state = NUD_NONE;
132+ int nhsel;
133+ int state;
134+ struct fib_nh * nh;
135+ u32 dst;
136+ int flag, dead = 1;
137+
138+ /* change_nexthops(fi) { */
139+ for (nhsel = 0, nh = fi->fib_nh; nhsel < fi->fib_nhs; nh++, nhsel++) {
140+ if (flp->oif && flp->oif != nh->nh_oif)
141+ continue;
142+ if (nh->nh_flags & RTNH_F_DEAD)
143+ continue;
144+
145+ flag = 0;
146+ if (nh->nh_dev->flags & IFF_NOARP) {
147+ dead = 0;
148+ goto setfl;
149+ }
150+
151+ dst = nh->nh_gw;
152+ if (!nh->nh_gw || nh->nh_scope != RT_SCOPE_LINK)
153+ dst = flp->fl4_dst;
154+
155+ state = NUD_NONE;
156+ n = neigh_lookup(&arp_tbl, &dst, nh->nh_dev);
157+ if (n) {
158+ state = n->nud_state;
159+ neigh_release(n);
160+ }
161+ if (state==NUD_REACHABLE ||
162+ ((state&NUD_VALID) && order != last_dflt)) {
163+ dead = 0;
164+ goto setfl;
165+ }
166+ if (!(state&NUD_VALID))
167+ flag = 1;
168+ if (!dead)
169+ goto setfl;
170+ if ((state&NUD_VALID) ||
171+ (*last_idx<0 && order >= last_dflt)) {
172+ *last_resort = fi;
173+ *last_idx = order;
174+ *last_nhsel = nhsel;
175+ }
176
177- n = neigh_lookup(&arp_tbl, &fi->fib_nh[0].nh_gw, fi->fib_dev);
178- if (n) {
179- state = n->nud_state;
180- neigh_release(n);
181- }
182- if (state==NUD_REACHABLE)
183- return 0;
184- if ((state&NUD_VALID) && order != fn_hash_last_dflt)
185- return 0;
186- if ((state&NUD_VALID) ||
187- (*last_idx<0 && order > fn_hash_last_dflt)) {
188- *last_resort = fi;
189- *last_idx = order;
190+ setfl:
191+
192+ read_lock_bh(&fib_nhflags_lock);
193+ if (flag)
194+ nh->nh_flags |= RTNH_F_SUSPECT;
195+ else
196+ nh->nh_flags &= ~RTNH_F_SUSPECT;
197+ read_unlock_bh(&fib_nhflags_lock);
198 }
199- return 1;
200+ /* } endfor_nexthops(fi) */
201+
202+ return dead;
203 }
204
205 static void
206 fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
207 {
208- int order, last_idx;
209- struct fib_node *f;
210+ int order, last_idx, last_dflt, last_nhsel;
211+ struct fib_node *f, *first_node;
212 struct fib_info *fi = NULL;
213 struct fib_info *last_resort;
214 struct fn_hash *t = (struct fn_hash*)tb->tb_data;
215- struct fn_zone *fz = t->fn_zones[0];
216+ struct fn_zone *fz = t->fn_zones[res->prefixlen];
217+ fn_key_t k;
218
219 if (fz == NULL)
220 return;
221
222+ k = fz_key(flp->fl4_dst, fz);
223+ last_dflt = -2;
224+ first_node = NULL;
225 last_idx = -1;
226 last_resort = NULL;
227+ last_nhsel = 0;
228 order = -1;
229
230 read_lock(&fib_hash_lock);
231- for (f = fz->fz_hash[0]; f; f = f->fn_next) {
232+ for (f = fz_chain(k, fz); f; f = f->fn_next) {
233 struct fib_info *next_fi = FIB_INFO(f);
234
235- if ((f->fn_state&FN_S_ZOMBIE) ||
236+ if (!fn_key_eq(k, f->fn_key) ||
237+ (f->fn_state&FN_S_ZOMBIE) ||
238 f->fn_scope != res->scope ||
239+#ifdef CONFIG_IP_ROUTE_TOS
240+ (f->fn_tos && f->fn_tos != flp->fl4_tos) ||
241+#endif
242 f->fn_type != RTN_UNICAST)
243 continue;
244
245 if (next_fi->fib_priority > res->fi->fib_priority)
246 break;
247- if (!next_fi->fib_nh[0].nh_gw || next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
248- continue;
249 f->fn_state |= FN_S_ACCESSED;
250
251- if (fi == NULL) {
252- if (next_fi != res->fi)
253- break;
254- } else if (!fib_detect_death(fi, order, &last_resort, &last_idx)) {
255+ if (!first_node) {
256+ last_dflt = f->fn_last_dflt;
257+ first_node = f;
258+ }
259+ if (fi && !fib_detect_death(fi, order, last_dflt,
260+ &last_resort, &last_idx, &last_nhsel, flp)) {
261 if (res->fi)
262 fib_info_put(res->fi);
263 res->fi = fi;
264 atomic_inc(&fi->fib_clntref);
265- fn_hash_last_dflt = order;
266+ first_node->fn_last_dflt = order;
267 goto out;
268 }
269 fi = next_fi;
270@@ -385,16 +434,25 @@
271 }
272
273 if (order<=0 || fi==NULL) {
274- fn_hash_last_dflt = -1;
275+ if (fi && fi->fib_nhs > 1 &&
276+ fib_detect_death(fi, order, last_dflt,
277+ &last_resort, &last_idx, &last_nhsel, flp) &&
278+ last_resort == fi) {
279+ read_lock_bh(&fib_nhflags_lock);
280+ fi->fib_nh[last_nhsel].nh_flags &= ~RTNH_F_SUSPECT;
281+ read_unlock_bh(&fib_nhflags_lock);
282+ }
283+ if (first_node) first_node->fn_last_dflt = -1;
284 goto out;
285 }
286
287- if (!fib_detect_death(fi, order, &last_resort, &last_idx)) {
288+ if (!fib_detect_death(fi, order, last_dflt, &last_resort, &last_idx,
289+ &last_nhsel, flp)) {
290 if (res->fi)
291 fib_info_put(res->fi);
292 res->fi = fi;
293 atomic_inc(&fi->fib_clntref);
294- fn_hash_last_dflt = order;
295+ first_node->fn_last_dflt = order;
296 goto out;
297 }
298
299@@ -404,8 +462,11 @@
300 res->fi = last_resort;
301 if (last_resort)
302 atomic_inc(&last_resort->fib_clntref);
303+ read_lock_bh(&fib_nhflags_lock);
304+ last_resort->fib_nh[last_nhsel].nh_flags &= ~RTNH_F_SUSPECT;
305+ read_unlock_bh(&fib_nhflags_lock);
306+ first_node->fn_last_dflt = last_idx;
307 }
308- fn_hash_last_dflt = last_idx;
309 out:
310 read_unlock(&fib_hash_lock);
311 }
312@@ -567,6 +628,7 @@
313
314 memset(new_f, 0, sizeof(struct fib_node));
315
316+ new_f->fn_last_dflt = -1;
317 new_f->fn_key = key;
318 #ifdef CONFIG_IP_ROUTE_TOS
319 new_f->fn_tos = tos;
320diff -ur v2.5.50/linux/net/ipv4/fib_rules.c linux/net/ipv4/fib_rules.c
321--- v2.5.50/linux/net/ipv4/fib_rules.c Thu Oct 17 03:43:21 2002
322+++ linux/net/ipv4/fib_rules.c Sun Dec 1 17:04:46 2002
323@@ -307,6 +307,11 @@
324 }
325 }
326
327+int fib_result_table(struct fib_result *res)
328+{
329+ return res->r->r_table;
330+}
331+
332 int fib_lookup(const struct flowi *flp, struct fib_result *res)
333 {
334 int err;
335@@ -371,8 +376,10 @@
336
337 void fib_select_default(const struct flowi *flp, struct fib_result *res)
338 {
339- if (res->r && res->r->r_action == RTN_UNICAST &&
340- FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
341+ if (res->r &&
342+ (res->r->r_action == RTN_UNICAST || res->r->r_action == RTN_NAT) &&
343+ ((FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) ||
344+ FIB_RES_NH(*res).nh_scope == RT_SCOPE_HOST)) {
345 struct fib_table *tb;
346 if ((tb = fib_get_table(res->r->r_table)) != NULL)
347 tb->tb_select_default(tb, flp, res);
348diff -ur v2.5.50/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c
349--- v2.5.50/linux/net/ipv4/fib_semantics.c Thu Oct 31 04:03:33 2002
350+++ linux/net/ipv4/fib_semantics.c Sun Dec 1 17:45:35 2002
351@@ -150,7 +150,7 @@
352 #ifdef CONFIG_NET_CLS_ROUTE
353 nh->nh_tclassid != onh->nh_tclassid ||
354 #endif
355- ((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD))
356+ ((nh->nh_flags^onh->nh_flags)&~RTNH_F_BADSTATE))
357 return -1;
358 onh++;
359 } endfor_nexthops(fi);
360@@ -166,7 +166,7 @@
361 nfi->fib_prefsrc == fi->fib_prefsrc &&
362 nfi->fib_priority == fi->fib_priority &&
363 memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 &&
364- ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
365+ ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_BADSTATE) == 0 &&
366 (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0))
367 return fi;
368 } endfor_fib_info();
369@@ -953,24 +953,42 @@
370 void fib_select_multipath(const struct flowi *flp, struct fib_result *res)
371 {
372 struct fib_info *fi = res->fi;
373- int w;
374+ int w, alive;
375
376 spin_lock_bh(&fib_multipath_lock);
377+ if (flp->oif) {
378+ int sel = -1;
379+ w = -1;
380+ change_nexthops(fi) {
381+ if (flp->oif != nh->nh_oif)
382+ continue;
383+ if (!(nh->nh_flags&RTNH_F_BADSTATE)) {
384+ if (nh->nh_power > w) {
385+ w = nh->nh_power;
386+ sel = nhsel;
387+ }
388+ }
389+ } endfor_nexthops(fi);
390+ if (sel >= 0) {
391+ spin_unlock_bh(&fib_multipath_lock);
392+ res->nh_sel = sel;
393+ return;
394+ }
395+ goto last_resort;
396+ }
397+
398+repeat:
399 if (fi->fib_power <= 0) {
400 int power = 0;
401 change_nexthops(fi) {
402- if (!(nh->nh_flags&RTNH_F_DEAD)) {
403+ if (!(nh->nh_flags&RTNH_F_BADSTATE)) {
404 power += nh->nh_weight;
405 nh->nh_power = nh->nh_weight;
406 }
407 } endfor_nexthops(fi);
408 fi->fib_power = power;
409- if (power <= 0) {
410- spin_unlock_bh(&fib_multipath_lock);
411- /* Race condition: route has just become dead. */
412- res->nh_sel = 0;
413- return;
414- }
415+ if (power <= 0)
416+ goto last_resort;
417 }
418
419
420@@ -980,20 +998,37 @@
421
422 w = jiffies % fi->fib_power;
423
424+ alive = 0;
425 change_nexthops(fi) {
426- if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) {
427+ if (!(nh->nh_flags&RTNH_F_BADSTATE) && nh->nh_power) {
428 if ((w -= nh->nh_power) <= 0) {
429 nh->nh_power--;
430 fi->fib_power--;
431+ spin_unlock_bh(&fib_multipath_lock);
432 res->nh_sel = nhsel;
433+ return;
434+ }
435+ alive = 1;
436+ }
437+ } endfor_nexthops(fi);
438+ if (alive) {
439+ fi->fib_power = 0;
440+ goto repeat;
441+ }
442+
443+last_resort:
444+
445+ for_nexthops(fi) {
446+ if (!(nh->nh_flags&RTNH_F_DEAD)) {
447+ if (!flp->oif || flp->oif == nh->nh_oif) {
448 spin_unlock_bh(&fib_multipath_lock);
449+ res->nh_sel = nhsel;
450 return;
451 }
452 }
453 } endfor_nexthops(fi);
454
455 /* Race condition: route has just become dead. */
456- res->nh_sel = 0;
457 spin_unlock_bh(&fib_multipath_lock);
458 }
459 #endif
460diff -ur v2.5.50/linux/net/ipv4/route.c linux/net/ipv4/route.c
461--- v2.5.50/linux/net/ipv4/route.c Mon Nov 11 23:43:59 2002
462+++ linux/net/ipv4/route.c Sun Dec 1 17:04:46 2002
463@@ -1433,8 +1433,9 @@
464 if (res.type != RTN_UNICAST)
465 goto martian_destination;
466
467+ fib_select_default(&fl, &res);
468 #ifdef CONFIG_IP_ROUTE_MULTIPATH
469- if (res.fi->fib_nhs > 1 && fl.oif == 0)
470+ if (res.fi->fib_nhs > 1)
471 fib_select_multipath(&fl, &res);
472 #endif
473 out_dev = in_dev_get(FIB_RES_DEV(res));
474@@ -1823,7 +1824,7 @@
475
476 if (fib_lookup(&fl, &res)) {
477 res.fi = NULL;
478- if (oldflp->oif) {
479+ if (oldflp->oif && dev_out->flags&IFF_UP) {
480 /* Apparently, routing tables are wrong. Assume,
481 that the destination is on link.
482
483@@ -1873,13 +1874,12 @@
484 goto make_route;
485 }
486
487+ if (res.type == RTN_UNICAST)
488+ fib_select_default(&fl, &res);
489 #ifdef CONFIG_IP_ROUTE_MULTIPATH
490- if (res.fi->fib_nhs > 1 && fl.oif == 0)
491+ if (res.fi->fib_nhs > 1)
492 fib_select_multipath(&fl, &res);
493- else
494 #endif
495- if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif)
496- fib_select_default(&fl, &res);
497
498 if (!fl.fl4_src)
499 fl.fl4_src = FIB_RES_PREFSRC(res);
This page took 0.105576 seconds and 4 git commands to generate.