1 diff -ur v2.6.0-test1/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
2 --- v2.6.0-test1/linux/include/net/ip_fib.h Sat Jul 26 16:38:32 2003
3 +++ linux/include/net/ip_fib.h Sun Jul 27 14:23:10 2003
8 +extern rwlock_t fib_nhflags_lock;
10 #endif /* _NET_FIB_H */
11 diff -ur v2.6.0-test1/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
12 --- v2.6.0-test1/linux/net/ipv4/fib_frontend.c Sat Jul 26 16:38:42 2003
13 +++ linux/net/ipv4/fib_frontend.c Sun Jul 27 14:23:10 2003
18 -#ifdef CONFIG_IP_ROUTE_MULTIPATH
19 fib_sync_up(ifa->ifa_dev->dev);
28 -#ifdef CONFIG_IP_ROUTE_MULTIPATH
34 diff -ur v2.6.0-test1/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c
35 --- v2.6.0-test1/linux/net/ipv4/fib_semantics.c Sat Jul 26 16:38:42 2003
36 +++ linux/net/ipv4/fib_semantics.c Sun Jul 27 14:23:10 2003
38 static struct fib_info *fib_info_list;
39 static rwlock_t fib_info_lock = RW_LOCK_UNLOCKED;
41 +rwlock_t fib_nhflags_lock = RW_LOCK_UNLOCKED;
43 #define for_fib_info() { struct fib_info *fi; \
44 for (fi = fib_info_list; fi; fi = fi->fib_next)
47 if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
49 - if (!(dev->flags&IFF_UP))
51 + if (!(dev->flags&IFF_UP)) {
52 + if (fi->fib_protocol != RTPROT_STATIC)
54 + nh->nh_flags |= RTNH_F_DEAD;
58 nh->nh_scope = RT_SCOPE_LINK;
60 /* It is not necessary, but requires a bit of thinking */
61 if (fl.fl4_scope < RT_SCOPE_LINK)
62 fl.fl4_scope = RT_SCOPE_LINK;
63 - if ((err = fib_lookup(&fl, &res)) != 0)
65 + err = fib_lookup(&fl, &res);
68 - if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
70 - nh->nh_scope = res.scope;
71 - nh->nh_oif = FIB_RES_OIF(res);
72 - if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
74 - dev_hold(nh->nh_dev);
76 - if (!(nh->nh_dev->flags & IFF_UP))
80 + struct in_device *in_dev;
82 + if (err != -ENETUNREACH ||
83 + fi->fib_protocol != RTPROT_STATIC)
86 + in_dev = inetdev_by_index(nh->nh_oif);
87 + if (in_dev == NULL ||
88 + in_dev->dev->flags & IFF_UP) {
93 + nh->nh_flags |= RTNH_F_DEAD;
94 + nh->nh_scope = RT_SCOPE_LINK;
95 + nh->nh_dev = in_dev->dev;
96 + dev_hold(nh->nh_dev);
100 + if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
102 + nh->nh_scope = res.scope;
103 + nh->nh_oif = FIB_RES_OIF(res);
104 + if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
106 + dev_hold(nh->nh_dev);
107 + if (!(nh->nh_dev->flags & IFF_UP)) {
108 + if (fi->fib_protocol != RTPROT_STATIC) {
112 + nh->nh_flags |= RTNH_F_DEAD;
122 struct in_device *in_dev;
127 if (!(in_dev->dev->flags&IFF_UP)) {
128 - in_dev_put(in_dev);
130 + if (fi->fib_protocol != RTPROT_STATIC) {
131 + in_dev_put(in_dev);
134 + nh->nh_flags |= RTNH_F_DEAD;
136 nh->nh_dev = in_dev->dev;
137 dev_hold(nh->nh_dev);
138 @@ -910,22 +941,35 @@
139 if (local && fi->fib_prefsrc == local) {
140 fi->fib_flags |= RTNH_F_DEAD;
142 - } else if (dev && fi->fib_nhs) {
143 + } else if (fi->fib_nhs) {
146 change_nexthops(fi) {
147 - if (nh->nh_flags&RTNH_F_DEAD)
149 - else if (nh->nh_dev == dev &&
150 - nh->nh_scope != scope) {
151 - nh->nh_flags |= RTNH_F_DEAD;
152 + if (nh->nh_flags&RTNH_F_DEAD) {
153 + if (fi->fib_protocol!=RTPROT_STATIC ||
154 + nh->nh_dev == NULL ||
155 + !__in_dev_get(nh->nh_dev) ||
156 + nh->nh_dev->flags&IFF_UP)
158 + } else if ((nh->nh_dev == dev && dev &&
159 + nh->nh_scope != scope) ||
160 + (local == nh->nh_gw && local &&
162 + write_lock_bh(&fib_nhflags_lock);
163 #ifdef CONFIG_IP_ROUTE_MULTIPATH
164 - spin_lock_bh(&fib_multipath_lock);
165 + spin_lock(&fib_multipath_lock);
166 + nh->nh_flags |= RTNH_F_DEAD;
167 fi->fib_power -= nh->nh_power;
169 - spin_unlock_bh(&fib_multipath_lock);
170 + spin_unlock(&fib_multipath_lock);
172 + nh->nh_flags |= RTNH_F_DEAD;
175 + write_unlock_bh(&fib_nhflags_lock);
176 + if (fi->fib_protocol!=RTPROT_STATIC ||
178 + (dev && __in_dev_get(dev) == NULL))
181 #ifdef CONFIG_IP_ROUTE_MULTIPATH
182 if (force > 1 && nh->nh_dev == dev) {
183 @@ -943,37 +987,56 @@
187 -#ifdef CONFIG_IP_ROUTE_MULTIPATH
190 - Dead device goes up. We wake up dead nexthops.
191 - It takes sense only on multipath routes.
192 + Dead device goes up or new address is added. We wake up dead nexthops.
195 int fib_sync_up(struct net_device *dev)
198 + struct fib_result res;
202 if (!(dev->flags&IFF_UP))
210 change_nexthops(fi) {
211 - if (!(nh->nh_flags&RTNH_F_DEAD)) {
213 + if (!(nh->nh_flags&RTNH_F_DEAD))
216 if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
218 if (nh->nh_dev != dev || __in_dev_get(dev) == NULL)
220 + if (nh->nh_gw && fi->fib_protocol == RTPROT_STATIC) {
221 + struct flowi fl = {
223 + { .daddr = nh->nh_gw,
224 + .scope = nh->nh_scope } },
227 + if (fib_lookup(&fl, &res) != 0)
229 + if (res.type != RTN_UNICAST &&
230 + res.type != RTN_LOCAL) {
234 + nh->nh_scope = res.scope;
239 +#ifdef CONFIG_IP_ROUTE_MULTIPATH
240 spin_lock_bh(&fib_multipath_lock);
242 nh->nh_flags &= ~RTNH_F_DEAD;
243 spin_unlock_bh(&fib_multipath_lock);
245 } endfor_nexthops(fi)
248 @@ -981,8 +1044,12 @@
257 +#ifdef CONFIG_IP_ROUTE_MULTIPATH
260 The algorithm is suboptimal, but it provides really