aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-24 21:06:47 -0400
committerDavid S. Miller <davem@davemloft.net>2011-03-24 21:06:47 -0400
commit37e826c513883099c298317bad1b3b677b2905fb (patch)
treea032cfe69e0cde179d86eba157cf9dc85d67df86 /net/ipv4
parent436c3b66ec9824a633724ae42de1c416af4f2063 (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/ipv4')
-rw-r--r--net/ipv4/fib_lookup.h3
-rw-r--r--net/ipv4/fib_semantics.c15
-rw-r--r--net/ipv4/fib_trie.c12
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 *);
29extern struct fib_info *fib_create_info(struct fib_config *cfg); 28extern struct fib_info *fib_create_info(struct fib_config *cfg);
30extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); 29extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi);
31extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, 30extern 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);
35extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, 34extern 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
916int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, 917int 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)