mirror of https://gitee.com/openkylin/linux.git
Merge branch 'fib_select_default-fixes'
Julian Anastasov says: ==================== ipv4: fib_select_default changes This patchset contains 2 changes for the alternative routes, one to add tb_id/fa_slen check needed after the recent fib_trie optimizations for fib aliases and the second change attempts to support alternative routes with TOS requirement. Sorry that I don't have access to the original report from Hagen Paul Pfeifer. I hope he will see this change. The second change adds fa_default field to the fib aliases (which can be many) and if the feature to filter the alternative routes by TOS is not worth it, this second patch can be scrapped. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
c42a6e8b29
|
@ -183,7 +183,6 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
|
|||
struct fib_table {
|
||||
struct hlist_node tb_hlist;
|
||||
u32 tb_id;
|
||||
int tb_default;
|
||||
int tb_num_default;
|
||||
struct rcu_head rcu;
|
||||
unsigned long *tb_data;
|
||||
|
@ -290,7 +289,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb);
|
|||
int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
|
||||
u8 tos, int oif, struct net_device *dev,
|
||||
struct in_device *idev, u32 *itag);
|
||||
void fib_select_default(struct fib_result *res);
|
||||
void fib_select_default(const struct flowi4 *flp, struct fib_result *res);
|
||||
#ifdef CONFIG_IP_ROUTE_CLASSID
|
||||
static inline int fib_num_tclassid_users(struct net *net)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@ struct fib_alias {
|
|||
u8 fa_state;
|
||||
u8 fa_slen;
|
||||
u32 tb_id;
|
||||
s16 fa_default;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
|
|
|
@ -1202,23 +1202,40 @@ int fib_sync_down_dev(struct net_device *dev, unsigned long event)
|
|||
}
|
||||
|
||||
/* Must be invoked inside of an RCU protected region. */
|
||||
void fib_select_default(struct fib_result *res)
|
||||
void fib_select_default(const struct flowi4 *flp, struct fib_result *res)
|
||||
{
|
||||
struct fib_info *fi = NULL, *last_resort = NULL;
|
||||
struct hlist_head *fa_head = res->fa_head;
|
||||
struct fib_table *tb = res->table;
|
||||
u8 slen = 32 - res->prefixlen;
|
||||
int order = -1, last_idx = -1;
|
||||
struct fib_alias *fa;
|
||||
struct fib_alias *fa, *fa1 = NULL;
|
||||
u32 last_prio = res->fi->fib_priority;
|
||||
u8 last_tos = 0;
|
||||
|
||||
hlist_for_each_entry_rcu(fa, fa_head, fa_list) {
|
||||
struct fib_info *next_fi = fa->fa_info;
|
||||
|
||||
if (fa->fa_slen != slen)
|
||||
continue;
|
||||
if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
|
||||
continue;
|
||||
if (fa->tb_id != tb->tb_id)
|
||||
continue;
|
||||
if (next_fi->fib_priority > last_prio &&
|
||||
fa->fa_tos == last_tos) {
|
||||
if (last_tos)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (next_fi->fib_flags & RTNH_F_DEAD)
|
||||
continue;
|
||||
last_tos = fa->fa_tos;
|
||||
last_prio = next_fi->fib_priority;
|
||||
|
||||
if (next_fi->fib_scope != res->scope ||
|
||||
fa->fa_type != RTN_UNICAST)
|
||||
continue;
|
||||
|
||||
if (next_fi->fib_priority > res->fi->fib_priority)
|
||||
break;
|
||||
if (!next_fi->fib_nh[0].nh_gw ||
|
||||
next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
|
||||
continue;
|
||||
|
@ -1228,10 +1245,11 @@ void fib_select_default(struct fib_result *res)
|
|||
if (!fi) {
|
||||
if (next_fi != res->fi)
|
||||
break;
|
||||
fa1 = fa;
|
||||
} else if (!fib_detect_death(fi, order, &last_resort,
|
||||
&last_idx, tb->tb_default)) {
|
||||
&last_idx, fa1->fa_default)) {
|
||||
fib_result_assign(res, fi);
|
||||
tb->tb_default = order;
|
||||
fa1->fa_default = order;
|
||||
goto out;
|
||||
}
|
||||
fi = next_fi;
|
||||
|
@ -1239,20 +1257,21 @@ void fib_select_default(struct fib_result *res)
|
|||
}
|
||||
|
||||
if (order <= 0 || !fi) {
|
||||
tb->tb_default = -1;
|
||||
if (fa1)
|
||||
fa1->fa_default = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fib_detect_death(fi, order, &last_resort, &last_idx,
|
||||
tb->tb_default)) {
|
||||
fa1->fa_default)) {
|
||||
fib_result_assign(res, fi);
|
||||
tb->tb_default = order;
|
||||
fa1->fa_default = order;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (last_idx >= 0)
|
||||
fib_result_assign(res, last_resort);
|
||||
tb->tb_default = last_idx;
|
||||
fa1->fa_default = last_idx;
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1171,6 +1171,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
|
|||
new_fa->fa_state = state & ~FA_S_ACCESSED;
|
||||
new_fa->fa_slen = fa->fa_slen;
|
||||
new_fa->tb_id = tb->tb_id;
|
||||
new_fa->fa_default = -1;
|
||||
|
||||
err = switchdev_fib_ipv4_add(key, plen, fi,
|
||||
new_fa->fa_tos,
|
||||
|
@ -1222,6 +1223,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
|
|||
new_fa->fa_state = 0;
|
||||
new_fa->fa_slen = slen;
|
||||
new_fa->tb_id = tb->tb_id;
|
||||
new_fa->fa_default = -1;
|
||||
|
||||
/* (Optionally) offload fib entry to switch hardware. */
|
||||
err = switchdev_fib_ipv4_add(key, plen, fi, tos, cfg->fc_type,
|
||||
|
@ -1990,7 +1992,6 @@ struct fib_table *fib_trie_table(u32 id, struct fib_table *alias)
|
|||
return NULL;
|
||||
|
||||
tb->tb_id = id;
|
||||
tb->tb_default = -1;
|
||||
tb->tb_num_default = 0;
|
||||
tb->tb_data = (alias ? alias->__data : tb->__data);
|
||||
|
||||
|
|
|
@ -2176,7 +2176,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
|
|||
if (!res.prefixlen &&
|
||||
res.table->tb_num_default > 1 &&
|
||||
res.type == RTN_UNICAST && !fl4->flowi4_oif)
|
||||
fib_select_default(&res);
|
||||
fib_select_default(fl4, &res);
|
||||
|
||||
if (!fl4->saddr)
|
||||
fl4->saddr = FIB_RES_PREFSRC(net, res);
|
||||
|
|
Loading…
Reference in New Issue