diff options
-rw-r--r-- | include/net/ip_fib.h | 3 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 4 | ||||
-rw-r--r-- | net/ipv4/fib_semantics.c | 104 |
3 files changed, 57 insertions, 54 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 9daa60b544ba..1b2f008db978 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
@@ -218,7 +218,8 @@ extern void fib_select_default(struct net *net, const struct flowi *flp, | |||
218 | 218 | ||
219 | /* Exported by fib_semantics.c */ | 219 | /* Exported by fib_semantics.c */ |
220 | extern int ip_fib_check_default(__be32 gw, struct net_device *dev); | 220 | extern int ip_fib_check_default(__be32 gw, struct net_device *dev); |
221 | extern int fib_sync_down(__be32 local, struct net_device *dev, int force); | 221 | extern int fib_sync_down_dev(struct net_device *dev, int force); |
222 | extern int fib_sync_down_addr(__be32 local); | ||
222 | extern int fib_sync_up(struct net_device *dev); | 223 | extern int fib_sync_up(struct net_device *dev); |
223 | extern __be32 __fib_res_prefsrc(struct fib_result *res); | 224 | extern __be32 __fib_res_prefsrc(struct fib_result *res); |
224 | extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res); | 225 | extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res); |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index d0507f4f848a..d69ffa2a2e98 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -808,7 +808,7 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
808 | First of all, we scan fib_info list searching | 808 | First of all, we scan fib_info list searching |
809 | for stray nexthop entries, then ignite fib_flush. | 809 | for stray nexthop entries, then ignite fib_flush. |
810 | */ | 810 | */ |
811 | if (fib_sync_down(ifa->ifa_local, NULL, 0)) | 811 | if (fib_sync_down_addr(ifa->ifa_local)) |
812 | fib_flush(dev->nd_net); | 812 | fib_flush(dev->nd_net); |
813 | } | 813 | } |
814 | } | 814 | } |
@@ -898,7 +898,7 @@ static void nl_fib_lookup_exit(struct net *net) | |||
898 | 898 | ||
899 | static void fib_disable_ip(struct net_device *dev, int force) | 899 | static void fib_disable_ip(struct net_device *dev, int force) |
900 | { | 900 | { |
901 | if (fib_sync_down(0, dev, force)) | 901 | if (fib_sync_down_dev(dev, force)) |
902 | fib_flush(dev->nd_net); | 902 | fib_flush(dev->nd_net); |
903 | rt_cache_flush(0); | 903 | rt_cache_flush(0); |
904 | arp_ifdown(dev); | 904 | arp_ifdown(dev); |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index c7912866d987..5beff2e02751 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -1031,70 +1031,72 @@ nla_put_failure: | |||
1031 | referring to it. | 1031 | referring to it. |
1032 | - device went down -> we must shutdown all nexthops going via it. | 1032 | - device went down -> we must shutdown all nexthops going via it. |
1033 | */ | 1033 | */ |
1034 | 1034 | int fib_sync_down_addr(__be32 local) | |
1035 | int fib_sync_down(__be32 local, struct net_device *dev, int force) | ||
1036 | { | 1035 | { |
1037 | int ret = 0; | 1036 | int ret = 0; |
1038 | int scope = RT_SCOPE_NOWHERE; | 1037 | unsigned int hash = fib_laddr_hashfn(local); |
1039 | 1038 | struct hlist_head *head = &fib_info_laddrhash[hash]; | |
1040 | if (force) | 1039 | struct hlist_node *node; |
1041 | scope = -1; | 1040 | struct fib_info *fi; |
1042 | 1041 | ||
1043 | if (local && fib_info_laddrhash) { | 1042 | if (fib_info_laddrhash == NULL || local == 0) |
1044 | unsigned int hash = fib_laddr_hashfn(local); | 1043 | return 0; |
1045 | struct hlist_head *head = &fib_info_laddrhash[hash]; | ||
1046 | struct hlist_node *node; | ||
1047 | struct fib_info *fi; | ||
1048 | 1044 | ||
1049 | hlist_for_each_entry(fi, node, head, fib_lhash) { | 1045 | hlist_for_each_entry(fi, node, head, fib_lhash) { |
1050 | if (fi->fib_prefsrc == local) { | 1046 | if (fi->fib_prefsrc == local) { |
1051 | fi->fib_flags |= RTNH_F_DEAD; | 1047 | fi->fib_flags |= RTNH_F_DEAD; |
1052 | ret++; | 1048 | ret++; |
1053 | } | ||
1054 | } | 1049 | } |
1055 | } | 1050 | } |
1051 | return ret; | ||
1052 | } | ||
1056 | 1053 | ||
1057 | if (dev) { | 1054 | int fib_sync_down_dev(struct net_device *dev, int force) |
1058 | struct fib_info *prev_fi = NULL; | 1055 | { |
1059 | unsigned int hash = fib_devindex_hashfn(dev->ifindex); | 1056 | int ret = 0; |
1060 | struct hlist_head *head = &fib_info_devhash[hash]; | 1057 | int scope = RT_SCOPE_NOWHERE; |
1061 | struct hlist_node *node; | 1058 | struct fib_info *prev_fi = NULL; |
1062 | struct fib_nh *nh; | 1059 | unsigned int hash = fib_devindex_hashfn(dev->ifindex); |
1060 | struct hlist_head *head = &fib_info_devhash[hash]; | ||
1061 | struct hlist_node *node; | ||
1062 | struct fib_nh *nh; | ||
1063 | 1063 | ||
1064 | hlist_for_each_entry(nh, node, head, nh_hash) { | 1064 | if (force) |
1065 | struct fib_info *fi = nh->nh_parent; | 1065 | scope = -1; |
1066 | int dead; | ||
1067 | 1066 | ||
1068 | BUG_ON(!fi->fib_nhs); | 1067 | hlist_for_each_entry(nh, node, head, nh_hash) { |
1069 | if (nh->nh_dev != dev || fi == prev_fi) | 1068 | struct fib_info *fi = nh->nh_parent; |
1070 | continue; | 1069 | int dead; |
1071 | prev_fi = fi; | 1070 | |
1072 | dead = 0; | 1071 | BUG_ON(!fi->fib_nhs); |
1073 | change_nexthops(fi) { | 1072 | if (nh->nh_dev != dev || fi == prev_fi) |
1074 | if (nh->nh_flags&RTNH_F_DEAD) | 1073 | continue; |
1075 | dead++; | 1074 | prev_fi = fi; |
1076 | else if (nh->nh_dev == dev && | 1075 | dead = 0; |
1077 | nh->nh_scope != scope) { | 1076 | change_nexthops(fi) { |
1078 | nh->nh_flags |= RTNH_F_DEAD; | 1077 | if (nh->nh_flags&RTNH_F_DEAD) |
1078 | dead++; | ||
1079 | else if (nh->nh_dev == dev && | ||
1080 | nh->nh_scope != scope) { | ||
1081 | nh->nh_flags |= RTNH_F_DEAD; | ||
1079 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1082 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
1080 | spin_lock_bh(&fib_multipath_lock); | 1083 | spin_lock_bh(&fib_multipath_lock); |
1081 | fi->fib_power -= nh->nh_power; | 1084 | fi->fib_power -= nh->nh_power; |
1082 | nh->nh_power = 0; | 1085 | nh->nh_power = 0; |
1083 | spin_unlock_bh(&fib_multipath_lock); | 1086 | spin_unlock_bh(&fib_multipath_lock); |
1084 | #endif | 1087 | #endif |
1085 | dead++; | 1088 | dead++; |
1086 | } | 1089 | } |
1087 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1090 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
1088 | if (force > 1 && nh->nh_dev == dev) { | 1091 | if (force > 1 && nh->nh_dev == dev) { |
1089 | dead = fi->fib_nhs; | 1092 | dead = fi->fib_nhs; |
1090 | break; | 1093 | break; |
1091 | } | ||
1092 | #endif | ||
1093 | } endfor_nexthops(fi) | ||
1094 | if (dead == fi->fib_nhs) { | ||
1095 | fi->fib_flags |= RTNH_F_DEAD; | ||
1096 | ret++; | ||
1097 | } | 1094 | } |
1095 | #endif | ||
1096 | } endfor_nexthops(fi) | ||
1097 | if (dead == fi->fib_nhs) { | ||
1098 | fi->fib_flags |= RTNH_F_DEAD; | ||
1099 | ret++; | ||
1098 | } | 1100 | } |
1099 | } | 1101 | } |
1100 | 1102 | ||