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>

+16 -20
+3 -3
include/net/ip_fib.h
··· 51 51 struct fib_info *nh_parent; 52 52 unsigned nh_flags; 53 53 unsigned char nh_scope; 54 - unsigned char nh_cfg_scope; 55 54 #ifdef CONFIG_IP_ROUTE_MULTIPATH 56 55 int nh_weight; 57 56 int nh_power; ··· 74 75 struct net *fib_net; 75 76 int fib_treeref; 76 77 atomic_t fib_clntref; 77 - int fib_dead; 78 78 unsigned fib_flags; 79 - int fib_protocol; 79 + unsigned char fib_dead; 80 + unsigned char fib_protocol; 81 + unsigned char fib_scope; 80 82 __be32 fib_prefsrc; 81 83 u32 fib_priority; 82 84 u32 *fib_metrics;
+1 -2
net/ipv4/fib_lookup.h
··· 10 10 struct fib_info *fa_info; 11 11 u8 fa_tos; 12 12 u8 fa_type; 13 - u8 fa_scope; 14 13 u8 fa_state; 15 14 struct rcu_head rcu; 16 15 }; ··· 28 29 extern struct fib_info *fib_create_info(struct fib_config *cfg); 29 30 extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); 30 31 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, 31 - u32 tb_id, u8 type, u8 scope, __be32 dst, 32 + u32 tb_id, u8 type, __be32 dst, 32 33 int dst_len, u8 tos, struct fib_info *fi, 33 34 unsigned int); 34 35 extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
+8 -7
net/ipv4/fib_semantics.c
··· 222 222 unsigned int mask = (fib_info_hash_size - 1); 223 223 unsigned int val = fi->fib_nhs; 224 224 225 - val ^= fi->fib_protocol; 225 + val ^= (fi->fib_protocol << 8) | fi->fib_scope; 226 226 val ^= (__force u32)fi->fib_prefsrc; 227 227 val ^= fi->fib_priority; 228 228 for_nexthops(fi) { ··· 248 248 if (fi->fib_nhs != nfi->fib_nhs) 249 249 continue; 250 250 if (nfi->fib_protocol == fi->fib_protocol && 251 + nfi->fib_scope == fi->fib_scope && 251 252 nfi->fib_prefsrc == fi->fib_prefsrc && 252 253 nfi->fib_priority == fi->fib_priority && 253 254 memcmp(nfi->fib_metrics, fi->fib_metrics, ··· 329 328 goto errout; 330 329 331 330 err = fib_dump_info(skb, info->pid, seq, event, tb_id, 332 - fa->fa_type, fa->fa_scope, key, dst_len, 331 + fa->fa_type, key, dst_len, 333 332 fa->fa_tos, fa->fa_info, nlm_flags); 334 333 if (err < 0) { 335 334 /* -EMSGSIZE implies BUG in fib_nlmsg_size() */ ··· 700 699 { 701 700 nh->nh_saddr = inet_select_addr(nh->nh_dev, 702 701 nh->nh_gw, 703 - nh->nh_cfg_scope); 702 + nh->nh_parent->fib_scope); 704 703 nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid); 705 704 706 705 return nh->nh_saddr; ··· 764 763 765 764 fi->fib_net = hold_net(net); 766 765 fi->fib_protocol = cfg->fc_protocol; 766 + fi->fib_scope = cfg->fc_scope; 767 767 fi->fib_flags = cfg->fc_flags; 768 768 fi->fib_priority = cfg->fc_priority; 769 769 fi->fib_prefsrc = cfg->fc_prefsrc; ··· 866 864 } 867 865 868 866 change_nexthops(fi) { 869 - nexthop_nh->nh_cfg_scope = cfg->fc_scope; 870 867 fib_info_update_nh_saddr(net, nexthop_nh); 871 868 } endfor_nexthops(fi) 872 869 ··· 915 914 } 916 915 917 916 int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, 918 - u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos, 917 + u32 tb_id, u8 type, __be32 dst, int dst_len, u8 tos, 919 918 struct fib_info *fi, unsigned int flags) 920 919 { 921 920 struct nlmsghdr *nlh; ··· 937 936 NLA_PUT_U32(skb, RTA_TABLE, tb_id); 938 937 rtm->rtm_type = type; 939 938 rtm->rtm_flags = fi->fib_flags; 940 - rtm->rtm_scope = scope; 939 + rtm->rtm_scope = fi->fib_scope; 941 940 rtm->rtm_protocol = fi->fib_protocol; 942 941 943 942 if (rtm->rtm_dst_len) ··· 1093 1092 list_for_each_entry_rcu(fa, fa_head, fa_list) { 1094 1093 struct fib_info *next_fi = fa->fa_info; 1095 1094 1096 - if (fa->fa_scope != res->scope || 1095 + if (next_fi->fib_scope != res->scope || 1097 1096 fa->fa_type != RTN_UNICAST) 1098 1097 continue; 1099 1098
+4 -8
net/ipv4/fib_trie.c
··· 1245 1245 if (fa->fa_info->fib_priority != fi->fib_priority) 1246 1246 break; 1247 1247 if (fa->fa_type == cfg->fc_type && 1248 - fa->fa_scope == cfg->fc_scope && 1249 1248 fa->fa_info == fi) { 1250 1249 fa_match = fa; 1251 1250 break; ··· 1270 1271 new_fa->fa_tos = fa->fa_tos; 1271 1272 new_fa->fa_info = fi; 1272 1273 new_fa->fa_type = cfg->fc_type; 1273 - new_fa->fa_scope = cfg->fc_scope; 1274 1274 state = fa->fa_state; 1275 1275 new_fa->fa_state = state & ~FA_S_ACCESSED; 1276 1276 ··· 1306 1308 new_fa->fa_info = fi; 1307 1309 new_fa->fa_tos = tos; 1308 1310 new_fa->fa_type = cfg->fc_type; 1309 - new_fa->fa_scope = cfg->fc_scope; 1310 1311 new_fa->fa_state = 0; 1311 1312 /* 1312 1313 * Insert new entry to the list. ··· 1359 1362 1360 1363 if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) 1361 1364 continue; 1362 - if (fa->fa_scope < flp->flowi4_scope) 1365 + if (fa->fa_info->fib_scope < flp->flowi4_scope) 1363 1366 continue; 1364 1367 fib_alias_accessed(fa); 1365 1368 err = fib_props[fa->fa_type].error; ··· 1385 1388 res->prefixlen = plen; 1386 1389 res->nh_sel = nhsel; 1387 1390 res->type = fa->fa_type; 1388 - res->scope = fa->fa_scope; 1391 + res->scope = fa->fa_info->fib_scope; 1389 1392 res->fi = fi; 1390 1393 res->table = tb; 1391 1394 res->fa_head = &li->falh; ··· 1661 1664 1662 1665 if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && 1663 1666 (cfg->fc_scope == RT_SCOPE_NOWHERE || 1664 - fa->fa_scope == cfg->fc_scope) && 1667 + fa->fa_info->fib_scope == cfg->fc_scope) && 1665 1668 (!cfg->fc_prefsrc || 1666 1669 fi->fib_prefsrc == cfg->fc_prefsrc) && 1667 1670 (!cfg->fc_protocol || ··· 1860 1863 RTM_NEWROUTE, 1861 1864 tb->tb_id, 1862 1865 fa->fa_type, 1863 - fa->fa_scope, 1864 1866 xkey, 1865 1867 plen, 1866 1868 fa->fa_tos, ··· 2380 2384 seq_indent(seq, iter->depth+1); 2381 2385 seq_printf(seq, " /%d %s %s", li->plen, 2382 2386 rtn_scope(buf1, sizeof(buf1), 2383 - fa->fa_scope), 2387 + fa->fa_info->fib_scope), 2384 2388 rtn_type(buf2, sizeof(buf2), 2385 2389 fa->fa_type)); 2386 2390 if (fa->fa_tos)