diff options
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r-- | net/ipv4/fib_semantics.c | 104 |
1 files changed, 53 insertions, 51 deletions
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 | ||