#endif
        int                     nh_oif;
        __be32                  nh_gw;
+       __be32                  nh_saddr;
 };
 
 /*
 
 #endif /* CONFIG_IP_ROUTE_MULTIPATH */
 
-#define FIB_RES_PREFSRC(res)           ((res).fi->fib_prefsrc ? : __fib_res_prefsrc(&res))
+#define FIB_RES_SADDR(res)             (FIB_RES_NH(res).nh_saddr)
 #define FIB_RES_GW(res)                        (FIB_RES_NH(res).nh_gw)
 #define FIB_RES_DEV(res)               (FIB_RES_NH(res).nh_dev)
 #define FIB_RES_OIF(res)               (FIB_RES_NH(res).nh_oif)
 
+#define FIB_RES_PREFSRC(res)           ((res).fi->fib_prefsrc ? : FIB_RES_SADDR(res))
+
 struct fib_table {
        struct hlist_node tb_hlist;
        u32             tb_id;
 extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
 extern int fib_sync_down_dev(struct net_device *dev, int force);
 extern int fib_sync_down_addr(struct net *net, __be32 local);
+extern void fib_update_nh_saddrs(struct net_device *dev);
 extern int fib_sync_up(struct net_device *dev);
-extern __be32  __fib_res_prefsrc(struct fib_result *res);
 extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
 
 /* Exported by fib_trie.c */
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
                fib_sync_up(dev);
 #endif
+               fib_update_nh_saddrs(dev);
                rt_cache_flush(dev_net(dev), -1);
                break;
        case NETDEV_DOWN:
                fib_del_ifaddr(ifa);
+               fib_update_nh_saddrs(dev);
                if (ifa->ifa_dev->ifa_list == NULL) {
                        /* Last address was deleted from this interface.
                         * Disable IP.
 
                                goto err_inval;
        }
 
+       change_nexthops(fi) {
+               nexthop_nh->nh_saddr = inet_select_addr(nexthop_nh->nh_dev,
+                                                       nexthop_nh->nh_gw,
+                                                       nexthop_nh->nh_scope);
+       } endfor_nexthops(fi)
+
 link_it:
        ofi = fib_find_info(fi);
        if (ofi) {
        return ERR_PTR(err);
 }
 
-/* Find appropriate source address to this destination */
-
-__be32 __fib_res_prefsrc(struct fib_result *res)
-{
-       return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);
-}
-
 int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
                  u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos,
                  struct fib_info *fi, unsigned int flags)
        return;
 }
 
+void fib_update_nh_saddrs(struct net_device *dev)
+{
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct fib_nh *nh;
+       unsigned int hash;
+
+       hash = fib_devindex_hashfn(dev->ifindex);
+       head = &fib_info_devhash[hash];
+       hlist_for_each_entry(nh, node, head, nh_hash) {
+               if (nh->nh_dev != dev)
+                       continue;
+               nh->nh_saddr = inet_select_addr(nh->nh_dev,
+                                               nh->nh_gw,
+                                               nh->nh_scope);
+       }
+}
+
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
 /*