diff -urp v2.6.34/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
--- v2.6.34/linux/include/net/ip_fib.h	2010-02-25 09:01:36.000000000 +0200
+++ linux/include/net/ip_fib.h	2010-05-18 10:13:55.000000000 +0300
@@ -277,4 +277,6 @@ static inline void fib_proc_exit(struct 
 }
 #endif
 
+extern rwlock_t fib_nhflags_lock;
+
 #endif  /* _NET_FIB_H */
diff -urp v2.6.34/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.6.34/linux/net/ipv4/fib_frontend.c	2010-05-17 10:49:01.000000000 +0300
+++ linux/net/ipv4/fib_frontend.c	2010-05-18 10:13:55.000000000 +0300
@@ -917,9 +917,7 @@ static int fib_inetaddr_event(struct not
 	switch (event) {
 	case NETDEV_UP:
 		fib_add_ifaddr(ifa);
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
 		fib_sync_up(dev);
-#endif
 		rt_cache_flush(dev_net(dev), -1);
 		break;
 	case NETDEV_DOWN:
@@ -955,9 +953,7 @@ static int fib_netdev_event(struct notif
 		for_ifa(in_dev) {
 			fib_add_ifaddr(ifa);
 		} endfor_ifa(in_dev);
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
 		fib_sync_up(dev);
-#endif
 		rt_cache_flush(dev_net(dev), -1);
 		break;
 	case NETDEV_DOWN:
diff -urp v2.6.34/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c
--- v2.6.34/linux/net/ipv4/fib_semantics.c	2010-05-17 10:49:01.000000000 +0300
+++ linux/net/ipv4/fib_semantics.c	2010-05-18 10:13:55.000000000 +0300
@@ -51,6 +51,7 @@ static struct hlist_head *fib_info_hash;
 static struct hlist_head *fib_info_laddrhash;
 static unsigned int fib_hash_size;
 static unsigned int fib_info_cnt;
+rwlock_t fib_nhflags_lock = RW_LOCK_UNLOCKED;
 
 #define DEVINDEX_HASHBITS 8
 #define DEVINDEX_HASHSIZE (1U << DEVINDEX_HASHBITS)
@@ -538,8 +539,11 @@ static int fib_check_nh(struct fib_confi
 				return -EINVAL;
 			if ((dev = __dev_get_by_index(net, nh->nh_oif)) == NULL)
 				return -ENODEV;
-			if (!(dev->flags&IFF_UP))
-				return -ENETDOWN;
+			if (!(dev->flags&IFF_UP)) {
+				if (fi->fib_protocol != RTPROT_STATIC)
+					return -ENETDOWN;
+				nh->nh_flags |= RTNH_F_DEAD;
+			}
 			nh->nh_dev = dev;
 			dev_hold(dev);
 			nh->nh_scope = RT_SCOPE_LINK;
@@ -559,24 +563,48 @@ static int fib_check_nh(struct fib_confi
 			/* It is not necessary, but requires a bit of thinking */
 			if (fl.fl4_scope < RT_SCOPE_LINK)
 				fl.fl4_scope = RT_SCOPE_LINK;
-			if ((err = fib_lookup(net, &fl, &res)) != 0)
-				return err;
+			err = fib_lookup(net, &fl, &res);
 		}
-		err = -EINVAL;
-		if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
-			goto out;
-		nh->nh_scope = res.scope;
-		nh->nh_oif = FIB_RES_OIF(res);
-		if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
-			goto out;
-		dev_hold(nh->nh_dev);
-		err = -ENETDOWN;
-		if (!(nh->nh_dev->flags & IFF_UP))
-			goto out;
-		err = 0;
+		if (err) {
+			struct in_device *in_dev;
+
+			if (err != -ENETUNREACH ||
+			    fi->fib_protocol != RTPROT_STATIC)
+				return err;
+
+			in_dev = inetdev_by_index(net, nh->nh_oif);
+			if (in_dev == NULL ||
+			    in_dev->dev->flags & IFF_UP) {
+				if (in_dev)
+					in_dev_put(in_dev);
+				return err;
+			}
+			nh->nh_flags |= RTNH_F_DEAD;
+			nh->nh_scope = RT_SCOPE_LINK;
+			nh->nh_dev = in_dev->dev;
+			dev_hold(nh->nh_dev);
+			in_dev_put(in_dev);
+		} else {
+			err = -EINVAL;
+			if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
+				goto out;
+			nh->nh_scope = res.scope;
+			nh->nh_oif = FIB_RES_OIF(res);
+			if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL)
+				goto out;
+			dev_hold(nh->nh_dev);
+			if (!(nh->nh_dev->flags & IFF_UP)) {
+				if (fi->fib_protocol != RTPROT_STATIC) {
+					err = -ENETDOWN;
+					goto out;
+				}
+				nh->nh_flags |= RTNH_F_DEAD;
+			}
+			err = 0;
 out:
-		fib_res_put(&res);
-		return err;
+			fib_res_put(&res);
+			return err;
+		}
 	} else {
 		struct in_device *in_dev;
 
@@ -587,8 +615,11 @@ out:
 		if (in_dev == NULL)
 			return -ENODEV;
 		if (!(in_dev->dev->flags&IFF_UP)) {
-			in_dev_put(in_dev);
-			return -ENETDOWN;
+			if (fi->fib_protocol != RTPROT_STATIC) {
+				in_dev_put(in_dev);
+				return -ENETDOWN;
+			}
+			nh->nh_flags |= RTNH_F_DEAD;
 		}
 		nh->nh_dev = in_dev->dev;
 		dev_hold(nh->nh_dev);
@@ -1078,18 +1109,29 @@ int fib_sync_down_dev(struct net_device 
 		prev_fi = fi;
 		dead = 0;
 		change_nexthops(fi) {
-			if (nexthop_nh->nh_flags&RTNH_F_DEAD)
-				dead++;
-			else if (nexthop_nh->nh_dev == dev &&
-				 nexthop_nh->nh_scope != scope) {
-				nexthop_nh->nh_flags |= RTNH_F_DEAD;
+			if (nexthop_nh->nh_flags&RTNH_F_DEAD) {
+				if (fi->fib_protocol!=RTPROT_STATIC ||
+				    nexthop_nh->nh_dev == NULL ||
+				    __in_dev_get_rtnl(nexthop_nh->nh_dev) == NULL ||
+				    nexthop_nh->nh_dev->flags&IFF_UP)
+					dead++;
+			} else if (nexthop_nh->nh_dev == dev &&
+				   nexthop_nh->nh_scope != scope) {
+				write_lock_bh(&fib_nhflags_lock);
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-				spin_lock_bh(&fib_multipath_lock);
+				spin_lock(&fib_multipath_lock);
+				nexthop_nh->nh_flags |= RTNH_F_DEAD;
 				fi->fib_power -= nexthop_nh->nh_power;
 				nexthop_nh->nh_power = 0;
-				spin_unlock_bh(&fib_multipath_lock);
+				spin_unlock(&fib_multipath_lock);
+#else
+				nexthop_nh->nh_flags |= RTNH_F_DEAD;
 #endif
-				dead++;
+				write_unlock_bh(&fib_nhflags_lock);
+				if (fi->fib_protocol!=RTPROT_STATIC ||
+				    force ||
+				    __in_dev_get_rtnl(dev) == NULL)
+					dead++;
 			}
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 			if (force > 1 && nexthop_nh->nh_dev == dev) {
@@ -1107,11 +1149,8 @@ int fib_sync_down_dev(struct net_device 
 	return ret;
 }
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
-
 /*
-   Dead device goes up. We wake up dead nexthops.
-   It takes sense only on multipath routes.
+   Dead device goes up or new address is added. We wake up dead nexthops.
  */
 
 int fib_sync_up(struct net_device *dev)
@@ -1121,8 +1160,10 @@ int fib_sync_up(struct net_device *dev)
 	struct hlist_head *head;
 	struct hlist_node *node;
 	struct fib_nh *nh;
-	int ret;
+	struct fib_result res;
+	int ret, rep;
 
+repeat:
 	if (!(dev->flags&IFF_UP))
 		return 0;
 
@@ -1130,6 +1171,7 @@ int fib_sync_up(struct net_device *dev)
 	hash = fib_devindex_hashfn(dev->ifindex);
 	head = &fib_info_devhash[hash];
 	ret = 0;
+	rep = 0;
 
 	hlist_for_each_entry(nh, node, head, nh_hash) {
 		struct fib_info *fi = nh->nh_parent;
@@ -1142,21 +1184,41 @@ int fib_sync_up(struct net_device *dev)
 		prev_fi = fi;
 		alive = 0;
 		change_nexthops(fi) {
-			if (!(nexthop_nh->nh_flags&RTNH_F_DEAD)) {
-				alive++;
+			if (!(nexthop_nh->nh_flags&RTNH_F_DEAD))
 				continue;
-			}
 			if (nexthop_nh->nh_dev == NULL ||
 			    !(nexthop_nh->nh_dev->flags&IFF_UP))
 				continue;
 			if (nexthop_nh->nh_dev != dev ||
 			    !__in_dev_get_rtnl(dev))
 				continue;
+			if (nexthop_nh->nh_gw && fi->fib_protocol == RTPROT_STATIC) {
+				struct flowi fl = {
+					.nl_u = { .ip4_u =
+						  { .daddr = nexthop_nh->nh_gw,
+						    .scope = nexthop_nh->nh_scope } },
+					.oif =  nexthop_nh->nh_oif,
+				};
+				if (fib_lookup(dev_net(dev), &fl, &res) != 0)
+					continue;
+				if (res.type != RTN_UNICAST &&
+				    res.type != RTN_LOCAL) {
+					fib_res_put(&res);
+					continue;
+				}
+				nexthop_nh->nh_scope = res.scope;
+				fib_res_put(&res);
+				rep = 1;
+			}
 			alive++;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
 			spin_lock_bh(&fib_multipath_lock);
 			nexthop_nh->nh_power = 0;
+#endif
 			nexthop_nh->nh_flags &= ~RTNH_F_DEAD;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
 			spin_unlock_bh(&fib_multipath_lock);
+#endif
 		} endfor_nexthops(fi)
 
 		if (alive > 0) {
@@ -1164,10 +1226,14 @@ int fib_sync_up(struct net_device *dev)
 			ret++;
 		}
 	}
+	if (rep)
+		goto repeat;
 
 	return ret;
 }
 
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+
 /*
    The algorithm is suboptimal, but it provides really
    fair weighted route distribution.
