Skip to content

Commit 0c838ff

Browse files
committed
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 <[email protected]>
1 parent 5b47044 commit 0c838ff

File tree

6 files changed

+58
-167
lines changed

6 files changed

+58
-167
lines changed

include/net/ip_fib.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,6 @@ extern int fib_table_delete(struct fib_table *, struct fib_config *);
158158
extern int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
159159
struct netlink_callback *cb);
160160
extern int fib_table_flush(struct fib_table *table);
161-
extern void fib_table_select_default(struct fib_table *table,
162-
const struct flowi *flp,
163-
struct fib_result *res);
164161
extern void fib_free_table(struct fib_table *tb);
165162

166163

@@ -221,8 +218,7 @@ extern void ip_fib_init(void);
221218
extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
222219
struct net_device *dev, __be32 *spec_dst,
223220
u32 *itag, u32 mark);
224-
extern void fib_select_default(struct net *net, const struct flowi *flp,
225-
struct fib_result *res);
221+
extern void fib_select_default(struct fib_result *res);
226222

227223
/* Exported by fib_semantics.c */
228224
extern int ip_fib_check_default(__be32 gw, struct net_device *dev);

net/ipv4/fib_frontend.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -114,21 +114,6 @@ struct fib_table *fib_get_table(struct net *net, u32 id)
114114
}
115115
#endif /* CONFIG_IP_MULTIPLE_TABLES */
116116

117-
void fib_select_default(struct net *net,
118-
const struct flowi *flp, struct fib_result *res)
119-
{
120-
struct fib_table *tb;
121-
int table = RT_TABLE_MAIN;
122-
#ifdef CONFIG_IP_MULTIPLE_TABLES
123-
if (res->r == NULL || res->r->action != FR_ACT_TO_TBL)
124-
return;
125-
table = res->r->table;
126-
#endif
127-
tb = fib_get_table(net, table);
128-
if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
129-
fib_table_select_default(tb, flp, res);
130-
}
131-
132117
static void fib_flush(struct net *net)
133118
{
134119
int flushed = 0;

net/ipv4/fib_hash.c

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -302,78 +302,6 @@ int fib_table_lookup(struct fib_table *tb,
302302
return err;
303303
}
304304

305-
void fib_table_select_default(struct fib_table *tb,
306-
const struct flowi *flp, struct fib_result *res)
307-
{
308-
int order, last_idx;
309-
struct hlist_node *node;
310-
struct fib_node *f;
311-
struct fib_info *fi = NULL;
312-
struct fib_info *last_resort;
313-
struct fn_hash *t = (struct fn_hash *)tb->tb_data;
314-
struct fn_zone *fz = t->fn_zones[0];
315-
struct hlist_head *head;
316-
317-
if (fz == NULL)
318-
return;
319-
320-
last_idx = -1;
321-
last_resort = NULL;
322-
order = -1;
323-
324-
rcu_read_lock();
325-
head = rcu_dereference(fz->fz_hash);
326-
hlist_for_each_entry_rcu(f, node, head, fn_hash) {
327-
struct fib_alias *fa;
328-
329-
list_for_each_entry_rcu(fa, &f->fn_alias, fa_list) {
330-
struct fib_info *next_fi = fa->fa_info;
331-
332-
if (fa->fa_scope != res->scope ||
333-
fa->fa_type != RTN_UNICAST)
334-
continue;
335-
336-
if (next_fi->fib_priority > res->fi->fib_priority)
337-
break;
338-
if (!next_fi->fib_nh[0].nh_gw ||
339-
next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
340-
continue;
341-
342-
fib_alias_accessed(fa);
343-
344-
if (fi == NULL) {
345-
if (next_fi != res->fi)
346-
break;
347-
} else if (!fib_detect_death(fi, order, &last_resort,
348-
&last_idx, tb->tb_default)) {
349-
fib_result_assign(res, fi);
350-
tb->tb_default = order;
351-
goto out;
352-
}
353-
fi = next_fi;
354-
order++;
355-
}
356-
}
357-
358-
if (order <= 0 || fi == NULL) {
359-
tb->tb_default = -1;
360-
goto out;
361-
}
362-
363-
if (!fib_detect_death(fi, order, &last_resort, &last_idx,
364-
tb->tb_default)) {
365-
fib_result_assign(res, fi);
366-
tb->tb_default = order;
367-
goto out;
368-
}
369-
370-
if (last_idx >= 0)
371-
fib_result_assign(res, last_resort);
372-
tb->tb_default = last_idx;
373-
out:
374-
rcu_read_unlock();
375-
}
376-
377305
/* Insert node F to FZ. */
378306
static inline void fib_insert_node(struct fn_zone *fz, struct fib_node *f)
379307
{

net/ipv4/fib_semantics.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,62 @@ int fib_sync_down_dev(struct net_device *dev, int force)
11361136
return ret;
11371137
}
11381138

1139+
/* Must be invoked inside of an RCU protected region. */
1140+
void 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;
1191+
out:
1192+
rcu_read_unlock();
1193+
}
1194+
11391195
#ifdef CONFIG_IP_ROUTE_MULTIPATH
11401196

11411197
/*

net/ipv4/fib_trie.c

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,80 +1802,6 @@ void fib_free_table(struct fib_table *tb)
18021802
kfree(tb);
18031803
}
18041804

1805-
void fib_table_select_default(struct fib_table *tb,
1806-
const struct flowi *flp,
1807-
struct fib_result *res)
1808-
{
1809-
struct trie *t = (struct trie *) tb->tb_data;
1810-
int order, last_idx;
1811-
struct fib_info *fi = NULL;
1812-
struct fib_info *last_resort;
1813-
struct fib_alias *fa = NULL;
1814-
struct list_head *fa_head;
1815-
struct leaf *l;
1816-
1817-
last_idx = -1;
1818-
last_resort = NULL;
1819-
order = -1;
1820-
1821-
rcu_read_lock();
1822-
1823-
l = fib_find_node(t, 0);
1824-
if (!l)
1825-
goto out;
1826-
1827-
fa_head = get_fa_head(l, 0);
1828-
if (!fa_head)
1829-
goto out;
1830-
1831-
if (list_empty(fa_head))
1832-
goto out;
1833-
1834-
list_for_each_entry_rcu(fa, fa_head, fa_list) {
1835-
struct fib_info *next_fi = fa->fa_info;
1836-
1837-
if (fa->fa_scope != res->scope ||
1838-
fa->fa_type != RTN_UNICAST)
1839-
continue;
1840-
1841-
if (next_fi->fib_priority > res->fi->fib_priority)
1842-
break;
1843-
if (!next_fi->fib_nh[0].nh_gw ||
1844-
next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
1845-
continue;
1846-
1847-
fib_alias_accessed(fa);
1848-
1849-
if (fi == NULL) {
1850-
if (next_fi != res->fi)
1851-
break;
1852-
} else if (!fib_detect_death(fi, order, &last_resort,
1853-
&last_idx, tb->tb_default)) {
1854-
fib_result_assign(res, fi);
1855-
tb->tb_default = order;
1856-
goto out;
1857-
}
1858-
fi = next_fi;
1859-
order++;
1860-
}
1861-
if (order <= 0 || fi == NULL) {
1862-
tb->tb_default = -1;
1863-
goto out;
1864-
}
1865-
1866-
if (!fib_detect_death(fi, order, &last_resort, &last_idx,
1867-
tb->tb_default)) {
1868-
fib_result_assign(res, fi);
1869-
tb->tb_default = order;
1870-
goto out;
1871-
}
1872-
if (last_idx >= 0)
1873-
fib_result_assign(res, last_resort);
1874-
tb->tb_default = last_idx;
1875-
out:
1876-
rcu_read_unlock();
1877-
}
1878-
18791805
static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
18801806
struct fib_table *tb,
18811807
struct sk_buff *skb, struct netlink_callback *cb)

net/ipv4/route.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2711,7 +2711,7 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
27112711
else
27122712
#endif
27132713
if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif)
2714-
fib_select_default(net, &fl, &res);
2714+
fib_select_default(&res);
27152715

27162716
if (!fl.fl4_src)
27172717
fl.fl4_src = FIB_RES_PREFSRC(res);

0 commit comments

Comments
 (0)