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 | ||
