aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/fib_frontend.c4
-rw-r--r--net/ipv4/fib_semantics.c104
2 files changed, 55 insertions, 53 deletions
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
899static void fib_disable_ip(struct net_device *dev, int force) 899static 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 1034int fib_sync_down_addr(__be32 local)
1035int 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) { 1054int 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