diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-24 21:06:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-24 21:06:47 -0400 |
commit | 37e826c513883099c298317bad1b3b677b2905fb (patch) | |
tree | a032cfe69e0cde179d86eba157cf9dc85d67df86 /net | |
parent | 436c3b66ec9824a633724ae42de1c416af4f2063 (diff) |
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 <ja@ssi.bg>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/fib_lookup.h | 3 | ||||
-rw-r--r-- | net/ipv4/fib_semantics.c | 15 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 12 |
3 files changed, 13 insertions, 17 deletions
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h index 4ec323875a02..af0f14aba169 100644 --- a/net/ipv4/fib_lookup.h +++ b/net/ipv4/fib_lookup.h | |||
@@ -10,7 +10,6 @@ struct fib_alias { | |||
10 | struct fib_info *fa_info; | 10 | struct fib_info *fa_info; |
11 | u8 fa_tos; | 11 | u8 fa_tos; |
12 | u8 fa_type; | 12 | u8 fa_type; |
13 | u8 fa_scope; | ||
14 | u8 fa_state; | 13 | u8 fa_state; |
15 | struct rcu_head rcu; | 14 | struct rcu_head rcu; |
16 | }; | 15 | }; |
@@ -29,7 +28,7 @@ extern void fib_release_info(struct fib_info *); | |||
29 | extern struct fib_info *fib_create_info(struct fib_config *cfg); | 28 | extern struct fib_info *fib_create_info(struct fib_config *cfg); |
30 | extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); | 29 | extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); |
31 | extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | 30 | 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, |
33 | int dst_len, u8 tos, struct fib_info *fi, | 32 | int dst_len, u8 tos, struct fib_info *fi, |
34 | unsigned int); | 33 | unsigned int); |
35 | extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, | 34 | extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 2d4bebca671a..641a5a2a9f9c 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -222,7 +222,7 @@ static inline unsigned int fib_info_hashfn(const struct fib_info *fi) | |||
222 | unsigned int mask = (fib_info_hash_size - 1); | 222 | unsigned int mask = (fib_info_hash_size - 1); |
223 | unsigned int val = fi->fib_nhs; | 223 | unsigned int val = fi->fib_nhs; |
224 | 224 | ||
225 | val ^= fi->fib_protocol; | 225 | val ^= (fi->fib_protocol << 8) | fi->fib_scope; |
226 | val ^= (__force u32)fi->fib_prefsrc; | 226 | val ^= (__force u32)fi->fib_prefsrc; |
227 | val ^= fi->fib_priority; | 227 | val ^= fi->fib_priority; |
228 | for_nexthops(fi) { | 228 | for_nexthops(fi) { |
@@ -248,6 +248,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi) | |||
248 | if (fi->fib_nhs != nfi->fib_nhs) | 248 | if (fi->fib_nhs != nfi->fib_nhs) |
249 | continue; | 249 | continue; |
250 | if (nfi->fib_protocol == fi->fib_protocol && | 250 | if (nfi->fib_protocol == fi->fib_protocol && |
251 | nfi->fib_scope == fi->fib_scope && | ||
251 | nfi->fib_prefsrc == fi->fib_prefsrc && | 252 | nfi->fib_prefsrc == fi->fib_prefsrc && |
252 | nfi->fib_priority == fi->fib_priority && | 253 | nfi->fib_priority == fi->fib_priority && |
253 | memcmp(nfi->fib_metrics, fi->fib_metrics, | 254 | memcmp(nfi->fib_metrics, fi->fib_metrics, |
@@ -328,7 +329,7 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, | |||
328 | goto errout; | 329 | goto errout; |
329 | 330 | ||
330 | err = fib_dump_info(skb, info->pid, seq, event, tb_id, | 331 | 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, |
332 | fa->fa_tos, fa->fa_info, nlm_flags); | 333 | fa->fa_tos, fa->fa_info, nlm_flags); |
333 | if (err < 0) { | 334 | if (err < 0) { |
334 | /* -EMSGSIZE implies BUG in fib_nlmsg_size() */ | 335 | /* -EMSGSIZE implies BUG in fib_nlmsg_size() */ |
@@ -699,7 +700,7 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh) | |||
699 | { | 700 | { |
700 | nh->nh_saddr = inet_select_addr(nh->nh_dev, | 701 | nh->nh_saddr = inet_select_addr(nh->nh_dev, |
701 | nh->nh_gw, | 702 | nh->nh_gw, |
702 | nh->nh_cfg_scope); | 703 | nh->nh_parent->fib_scope); |
703 | nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid); | 704 | nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid); |
704 | 705 | ||
705 | return nh->nh_saddr; | 706 | return nh->nh_saddr; |
@@ -763,6 +764,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
763 | 764 | ||
764 | fi->fib_net = hold_net(net); | 765 | fi->fib_net = hold_net(net); |
765 | fi->fib_protocol = cfg->fc_protocol; | 766 | fi->fib_protocol = cfg->fc_protocol; |
767 | fi->fib_scope = cfg->fc_scope; | ||
766 | fi->fib_flags = cfg->fc_flags; | 768 | fi->fib_flags = cfg->fc_flags; |
767 | fi->fib_priority = cfg->fc_priority; | 769 | fi->fib_priority = cfg->fc_priority; |
768 | fi->fib_prefsrc = cfg->fc_prefsrc; | 770 | fi->fib_prefsrc = cfg->fc_prefsrc; |
@@ -864,7 +866,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
864 | } | 866 | } |
865 | 867 | ||
866 | change_nexthops(fi) { | 868 | change_nexthops(fi) { |
867 | nexthop_nh->nh_cfg_scope = cfg->fc_scope; | ||
868 | fib_info_update_nh_saddr(net, nexthop_nh); | 869 | fib_info_update_nh_saddr(net, nexthop_nh); |
869 | } endfor_nexthops(fi) | 870 | } endfor_nexthops(fi) |
870 | 871 | ||
@@ -914,7 +915,7 @@ failure: | |||
914 | } | 915 | } |
915 | 916 | ||
916 | int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | 917 | 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, |
918 | struct fib_info *fi, unsigned int flags) | 919 | struct fib_info *fi, unsigned int flags) |
919 | { | 920 | { |
920 | struct nlmsghdr *nlh; | 921 | struct nlmsghdr *nlh; |
@@ -936,7 +937,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | |||
936 | NLA_PUT_U32(skb, RTA_TABLE, tb_id); | 937 | NLA_PUT_U32(skb, RTA_TABLE, tb_id); |
937 | rtm->rtm_type = type; | 938 | rtm->rtm_type = type; |
938 | rtm->rtm_flags = fi->fib_flags; | 939 | rtm->rtm_flags = fi->fib_flags; |
939 | rtm->rtm_scope = scope; | 940 | rtm->rtm_scope = fi->fib_scope; |
940 | rtm->rtm_protocol = fi->fib_protocol; | 941 | rtm->rtm_protocol = fi->fib_protocol; |
941 | 942 | ||
942 | if (rtm->rtm_dst_len) | 943 | if (rtm->rtm_dst_len) |
@@ -1092,7 +1093,7 @@ void fib_select_default(struct fib_result *res) | |||
1092 | list_for_each_entry_rcu(fa, fa_head, fa_list) { | 1093 | list_for_each_entry_rcu(fa, fa_head, fa_list) { |
1093 | struct fib_info *next_fi = fa->fa_info; | 1094 | struct fib_info *next_fi = fa->fa_info; |
1094 | 1095 | ||
1095 | if (fa->fa_scope != res->scope || | 1096 | if (next_fi->fib_scope != res->scope || |
1096 | fa->fa_type != RTN_UNICAST) | 1097 | fa->fa_type != RTN_UNICAST) |
1097 | continue; | 1098 | continue; |
1098 | 1099 | ||
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index ac87a49ad50b..90a3ff605591 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1245,7 +1245,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1245 | if (fa->fa_info->fib_priority != fi->fib_priority) | 1245 | if (fa->fa_info->fib_priority != fi->fib_priority) |
1246 | break; | 1246 | break; |
1247 | if (fa->fa_type == cfg->fc_type && | 1247 | if (fa->fa_type == cfg->fc_type && |
1248 | fa->fa_scope == cfg->fc_scope && | ||
1249 | fa->fa_info == fi) { | 1248 | fa->fa_info == fi) { |
1250 | fa_match = fa; | 1249 | fa_match = fa; |
1251 | break; | 1250 | break; |
@@ -1271,7 +1270,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1271 | new_fa->fa_tos = fa->fa_tos; | 1270 | new_fa->fa_tos = fa->fa_tos; |
1272 | new_fa->fa_info = fi; | 1271 | new_fa->fa_info = fi; |
1273 | new_fa->fa_type = cfg->fc_type; | 1272 | new_fa->fa_type = cfg->fc_type; |
1274 | new_fa->fa_scope = cfg->fc_scope; | ||
1275 | state = fa->fa_state; | 1273 | state = fa->fa_state; |
1276 | new_fa->fa_state = state & ~FA_S_ACCESSED; | 1274 | new_fa->fa_state = state & ~FA_S_ACCESSED; |
1277 | 1275 | ||
@@ -1308,7 +1306,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1308 | new_fa->fa_info = fi; | 1306 | new_fa->fa_info = fi; |
1309 | new_fa->fa_tos = tos; | 1307 | new_fa->fa_tos = tos; |
1310 | new_fa->fa_type = cfg->fc_type; | 1308 | new_fa->fa_type = cfg->fc_type; |
1311 | new_fa->fa_scope = cfg->fc_scope; | ||
1312 | new_fa->fa_state = 0; | 1309 | new_fa->fa_state = 0; |
1313 | /* | 1310 | /* |
1314 | * Insert new entry to the list. | 1311 | * Insert new entry to the list. |
@@ -1362,7 +1359,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, | |||
1362 | 1359 | ||
1363 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) | 1360 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) |
1364 | continue; | 1361 | continue; |
1365 | if (fa->fa_scope < flp->flowi4_scope) | 1362 | if (fa->fa_info->fib_scope < flp->flowi4_scope) |
1366 | continue; | 1363 | continue; |
1367 | fib_alias_accessed(fa); | 1364 | fib_alias_accessed(fa); |
1368 | err = fib_props[fa->fa_type].error; | 1365 | 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, | |||
1388 | res->prefixlen = plen; | 1385 | res->prefixlen = plen; |
1389 | res->nh_sel = nhsel; | 1386 | res->nh_sel = nhsel; |
1390 | res->type = fa->fa_type; | 1387 | res->type = fa->fa_type; |
1391 | res->scope = fa->fa_scope; | 1388 | res->scope = fa->fa_info->fib_scope; |
1392 | res->fi = fi; | 1389 | res->fi = fi; |
1393 | res->table = tb; | 1390 | res->table = tb; |
1394 | res->fa_head = &li->falh; | 1391 | res->fa_head = &li->falh; |
@@ -1664,7 +1661,7 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) | |||
1664 | 1661 | ||
1665 | if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && | 1662 | if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && |
1666 | (cfg->fc_scope == RT_SCOPE_NOWHERE || | 1663 | (cfg->fc_scope == RT_SCOPE_NOWHERE || |
1667 | fa->fa_scope == cfg->fc_scope) && | 1664 | fa->fa_info->fib_scope == cfg->fc_scope) && |
1668 | (!cfg->fc_prefsrc || | 1665 | (!cfg->fc_prefsrc || |
1669 | fi->fib_prefsrc == cfg->fc_prefsrc) && | 1666 | fi->fib_prefsrc == cfg->fc_prefsrc) && |
1670 | (!cfg->fc_protocol || | 1667 | (!cfg->fc_protocol || |
@@ -1863,7 +1860,6 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, | |||
1863 | RTM_NEWROUTE, | 1860 | RTM_NEWROUTE, |
1864 | tb->tb_id, | 1861 | tb->tb_id, |
1865 | fa->fa_type, | 1862 | fa->fa_type, |
1866 | fa->fa_scope, | ||
1867 | xkey, | 1863 | xkey, |
1868 | plen, | 1864 | plen, |
1869 | fa->fa_tos, | 1865 | fa->fa_tos, |
@@ -2384,7 +2380,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) | |||
2384 | seq_indent(seq, iter->depth+1); | 2380 | seq_indent(seq, iter->depth+1); |
2385 | seq_printf(seq, " /%d %s %s", li->plen, | 2381 | seq_printf(seq, " /%d %s %s", li->plen, |
2386 | rtn_scope(buf1, sizeof(buf1), | 2382 | rtn_scope(buf1, sizeof(buf1), |
2387 | fa->fa_scope), | 2383 | fa->fa_info->fib_scope), |
2388 | rtn_type(buf2, sizeof(buf2), | 2384 | rtn_type(buf2, sizeof(buf2), |
2389 | fa->fa_type)); | 2385 | fa->fa_type)); |
2390 | if (fa->fa_tos) | 2386 | if (fa->fa_tos) |