aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_semantics.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-01-31 19:16:50 -0500
committerDavid S. Miller <davem@davemloft.net>2011-01-31 19:16:50 -0500
commit0c838ff1ade71162775afffd9e5c6478a60bdca6 (patch)
tree81910cc5582f4862770307784c40c66aa3a44948 /net/ipv4/fib_semantics.c
parent5b4704419cbd0b7597a91c19f9e8e8b17c1af071 (diff)
ipv4: Consolidate all default route selection implementations.
Both fib_trie and fib_hash have a local implementation of fib_table_select_default(). This is completely unnecessary code duplication. Since we now remember the fib_table and the head of the fib alias list of the default route, we can implement one single generic version of this routine. Looking at the fib_hash implementation you may get the impression that it's possible for there to be multiple top-level routes in the table for the default route. The truth is, it isn't, the insert code will only allow one entry to exist in the zero prefix hash table, because all keys evaluate to zero and all keys in a hash table must be unique. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r--net/ipv4/fib_semantics.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 1bf6fb906cfc..b15857d2b77e 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1136,6 +1136,62 @@ int fib_sync_down_dev(struct net_device *dev, int force)
1136 return ret; 1136 return ret;
1137} 1137}
1138 1138
1139/* Must be invoked inside of an RCU protected region. */
1140void fib_select_default(struct fib_result *res)
1141{
1142 struct fib_info *fi = NULL, *last_resort = NULL;
1143 struct list_head *fa_head = res->fa_head;
1144 struct fib_table *tb = res->table;
1145 int order = -1, last_idx = -1;
1146 struct fib_alias *fa;
1147
1148 list_for_each_entry_rcu(fa, fa_head, fa_list) {
1149 struct fib_info *next_fi = fa->fa_info;
1150
1151 if (fa->fa_scope != res->scope ||
1152 fa->fa_type != RTN_UNICAST)
1153 continue;
1154
1155 if (next_fi->fib_priority > res->fi->fib_priority)
1156 break;
1157 if (!next_fi->fib_nh[0].nh_gw ||
1158 next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
1159 continue;
1160
1161 fib_alias_accessed(fa);
1162
1163 if (fi == NULL) {
1164 if (next_fi != res->fi)
1165 break;
1166 } else if (!fib_detect_death(fi, order, &last_resort,
1167 &last_idx, tb->tb_default)) {
1168 fib_result_assign(res, fi);
1169 tb->tb_default = order;
1170 goto out;
1171 }
1172 fi = next_fi;
1173 order++;
1174 }
1175
1176 if (order <= 0 || fi == NULL) {
1177 tb->tb_default = -1;
1178 goto out;
1179 }
1180
1181 if (!fib_detect_death(fi, order, &last_resort, &last_idx,
1182 tb->tb_default)) {
1183 fib_result_assign(res, fi);
1184 tb->tb_default = order;
1185 goto out;
1186 }
1187
1188 if (last_idx >= 0)
1189 fib_result_assign(res, last_resort);
1190 tb->tb_default = last_idx;
1191out:
1192 rcu_read_unlock();
1193}
1194
1139#ifdef CONFIG_IP_ROUTE_MULTIPATH 1195#ifdef CONFIG_IP_ROUTE_MULTIPATH
1140 1196
1141/* 1197/*