Skip to content

Commit 37e826c

Browse files
committed
ipv4: Fix nexthop caching wrt. scoping.
Move the scope value out of the fib alias entries and into fib_info, so that we always use the correct scope when recomputing the nexthop cached source address. Reported-by: Julian Anastasov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 436c3b6 commit 37e826c

File tree

4 files changed

+16
-20
lines changed

4 files changed

+16
-20
lines changed

include/net/ip_fib.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ struct fib_nh {
5151
struct fib_info *nh_parent;
5252
unsigned nh_flags;
5353
unsigned char nh_scope;
54-
unsigned char nh_cfg_scope;
5554
#ifdef CONFIG_IP_ROUTE_MULTIPATH
5655
int nh_weight;
5756
int nh_power;
@@ -75,9 +74,10 @@ struct fib_info {
7574
struct net *fib_net;
7675
int fib_treeref;
7776
atomic_t fib_clntref;
78-
int fib_dead;
7977
unsigned fib_flags;
80-
int fib_protocol;
78+
unsigned char fib_dead;
79+
unsigned char fib_protocol;
80+
unsigned char fib_scope;
8181
__be32 fib_prefsrc;
8282
u32 fib_priority;
8383
u32 *fib_metrics;

net/ipv4/fib_lookup.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ struct fib_alias {
1010
struct fib_info *fa_info;
1111
u8 fa_tos;
1212
u8 fa_type;
13-
u8 fa_scope;
1413
u8 fa_state;
1514
struct rcu_head rcu;
1615
};
@@ -29,7 +28,7 @@ extern void fib_release_info(struct fib_info *);
2928
extern struct fib_info *fib_create_info(struct fib_config *cfg);
3029
extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi);
3130
extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
32-
u32 tb_id, u8 type, u8 scope, __be32 dst,
31+
u32 tb_id, u8 type, __be32 dst,
3332
int dst_len, u8 tos, struct fib_info *fi,
3433
unsigned int);
3534
extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,

net/ipv4/fib_semantics.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
222222
unsigned int mask = (fib_info_hash_size - 1);
223223
unsigned int val = fi->fib_nhs;
224224

225-
val ^= fi->fib_protocol;
225+
val ^= (fi->fib_protocol << 8) | fi->fib_scope;
226226
val ^= (__force u32)fi->fib_prefsrc;
227227
val ^= fi->fib_priority;
228228
for_nexthops(fi) {
@@ -248,6 +248,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi)
248248
if (fi->fib_nhs != nfi->fib_nhs)
249249
continue;
250250
if (nfi->fib_protocol == fi->fib_protocol &&
251+
nfi->fib_scope == fi->fib_scope &&
251252
nfi->fib_prefsrc == fi->fib_prefsrc &&
252253
nfi->fib_priority == fi->fib_priority &&
253254
memcmp(nfi->fib_metrics, fi->fib_metrics,
@@ -328,7 +329,7 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
328329
goto errout;
329330

330331
err = fib_dump_info(skb, info->pid, seq, event, tb_id,
331-
fa->fa_type, fa->fa_scope, key, dst_len,
332+
fa->fa_type, key, dst_len,
332333
fa->fa_tos, fa->fa_info, nlm_flags);
333334
if (err < 0) {
334335
/* -EMSGSIZE implies BUG in fib_nlmsg_size() */
@@ -699,7 +700,7 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh)
699700
{
700701
nh->nh_saddr = inet_select_addr(nh->nh_dev,
701702
nh->nh_gw,
702-
nh->nh_cfg_scope);
703+
nh->nh_parent->fib_scope);
703704
nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid);
704705

705706
return nh->nh_saddr;
@@ -763,6 +764,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
763764

764765
fi->fib_net = hold_net(net);
765766
fi->fib_protocol = cfg->fc_protocol;
767+
fi->fib_scope = cfg->fc_scope;
766768
fi->fib_flags = cfg->fc_flags;
767769
fi->fib_priority = cfg->fc_priority;
768770
fi->fib_prefsrc = cfg->fc_prefsrc;
@@ -864,7 +866,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
864866
}
865867

866868
change_nexthops(fi) {
867-
nexthop_nh->nh_cfg_scope = cfg->fc_scope;
868869
fib_info_update_nh_saddr(net, nexthop_nh);
869870
} endfor_nexthops(fi)
870871

@@ -914,7 +915,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
914915
}
915916

916917
int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
917-
u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos,
918+
u32 tb_id, u8 type, __be32 dst, int dst_len, u8 tos,
918919
struct fib_info *fi, unsigned int flags)
919920
{
920921
struct nlmsghdr *nlh;
@@ -936,7 +937,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
936937
NLA_PUT_U32(skb, RTA_TABLE, tb_id);
937938
rtm->rtm_type = type;
938939
rtm->rtm_flags = fi->fib_flags;
939-
rtm->rtm_scope = scope;
940+
rtm->rtm_scope = fi->fib_scope;
940941
rtm->rtm_protocol = fi->fib_protocol;
941942

942943
if (rtm->rtm_dst_len)
@@ -1092,7 +1093,7 @@ void fib_select_default(struct fib_result *res)
10921093
list_for_each_entry_rcu(fa, fa_head, fa_list) {
10931094
struct fib_info *next_fi = fa->fa_info;
10941095

1095-
if (fa->fa_scope != res->scope ||
1096+
if (next_fi->fib_scope != res->scope ||
10961097
fa->fa_type != RTN_UNICAST)
10971098
continue;
10981099

net/ipv4/fib_trie.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,7 +1245,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
12451245
if (fa->fa_info->fib_priority != fi->fib_priority)
12461246
break;
12471247
if (fa->fa_type == cfg->fc_type &&
1248-
fa->fa_scope == cfg->fc_scope &&
12491248
fa->fa_info == fi) {
12501249
fa_match = fa;
12511250
break;
@@ -1271,7 +1270,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
12711270
new_fa->fa_tos = fa->fa_tos;
12721271
new_fa->fa_info = fi;
12731272
new_fa->fa_type = cfg->fc_type;
1274-
new_fa->fa_scope = cfg->fc_scope;
12751273
state = fa->fa_state;
12761274
new_fa->fa_state = state & ~FA_S_ACCESSED;
12771275

@@ -1308,7 +1306,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
13081306
new_fa->fa_info = fi;
13091307
new_fa->fa_tos = tos;
13101308
new_fa->fa_type = cfg->fc_type;
1311-
new_fa->fa_scope = cfg->fc_scope;
13121309
new_fa->fa_state = 0;
13131310
/*
13141311
* Insert new entry to the list.
@@ -1362,7 +1359,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
13621359

13631360
if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
13641361
continue;
1365-
if (fa->fa_scope < flp->flowi4_scope)
1362+
if (fa->fa_info->fib_scope < flp->flowi4_scope)
13661363
continue;
13671364
fib_alias_accessed(fa);
13681365
err = fib_props[fa->fa_type].error;
@@ -1388,7 +1385,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
13881385
res->prefixlen = plen;
13891386
res->nh_sel = nhsel;
13901387
res->type = fa->fa_type;
1391-
res->scope = fa->fa_scope;
1388+
res->scope = fa->fa_info->fib_scope;
13921389
res->fi = fi;
13931390
res->table = tb;
13941391
res->fa_head = &li->falh;
@@ -1664,7 +1661,7 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
16641661

16651662
if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
16661663
(cfg->fc_scope == RT_SCOPE_NOWHERE ||
1667-
fa->fa_scope == cfg->fc_scope) &&
1664+
fa->fa_info->fib_scope == cfg->fc_scope) &&
16681665
(!cfg->fc_prefsrc ||
16691666
fi->fib_prefsrc == cfg->fc_prefsrc) &&
16701667
(!cfg->fc_protocol ||
@@ -1863,7 +1860,6 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
18631860
RTM_NEWROUTE,
18641861
tb->tb_id,
18651862
fa->fa_type,
1866-
fa->fa_scope,
18671863
xkey,
18681864
plen,
18691865
fa->fa_tos,
@@ -2384,7 +2380,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
23842380
seq_indent(seq, iter->depth+1);
23852381
seq_printf(seq, " /%d %s %s", li->plen,
23862382
rtn_scope(buf1, sizeof(buf1),
2387-
fa->fa_scope),
2383+
fa->fa_info->fib_scope),
23882384
rtn_type(buf2, sizeof(buf2),
23892385
fa->fa_type));
23902386
if (fa->fa_tos)

0 commit comments

Comments
 (0)