aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis V. Lunev <den@openvz.org>2008-01-31 21:48:47 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-31 22:28:39 -0500
commit85326fa54b5516d8859617cc5fdfce8ae19c1480 (patch)
tree82129844e755914183bc262b250301d06b7db398
parent4b8aa9abee2e108b132dea7a7c4e81a167895354 (diff)
[IPV4]: fib_sync_down rework.
fib_sync_down can be called with an address and with a device. In reality it is called either with address OR with a device. The codepath inside is completely different, so lets separate it into two calls for these two cases. Signed-off-by: Denis V. Lunev <den@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ip_fib.h3
-rw-r--r--net/ipv4/fib_frontend.c4
-rw-r--r--net/ipv4/fib_semantics.c104
3 files changed, 57 insertions, 54 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 9daa60b544b..1b2f008db97 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 */
220extern int ip_fib_check_default(__be32 gw, struct net_device *dev); 220extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
221extern int fib_sync_down(__be32 local, struct net_device *dev, int force); 221extern int fib_sync_down_dev(struct net_device *dev, int force);
222extern int fib_sync_down_addr(__be32 local);
222extern int fib_sync_up(struct net_device *dev); 223extern int fib_sync_up(struct net_device *dev);
223extern __be32 __fib_res_prefsrc(struct fib_result *res); 224extern __be32 __fib_res_prefsrc(struct fib_result *res);
224extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res); 225extern 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 d0507f4f848..d69ffa2a2e9 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 c7912866d98..5beff2e0275 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