diff options
Diffstat (limited to 'net/ipv4/fib_semantics.c')
| -rw-r--r-- | net/ipv4/fib_semantics.c | 47 |
1 files changed, 19 insertions, 28 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 622ac4c95026..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,10 +248,11 @@ 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, |
| 254 | sizeof(fi->fib_metrics)) == 0 && | 255 | sizeof(u32) * RTAX_MAX) == 0 && |
| 255 | ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 && | 256 | ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 && |
| 256 | (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0)) | 257 | (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0)) |
| 257 | return fi; | 258 | return fi; |
| @@ -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() */ |
| @@ -695,6 +696,16 @@ static void fib_info_hash_move(struct hlist_head *new_info_hash, | |||
| 695 | fib_info_hash_free(old_laddrhash, bytes); | 696 | fib_info_hash_free(old_laddrhash, bytes); |
| 696 | } | 697 | } |
| 697 | 698 | ||
| 699 | __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh) | ||
| 700 | { | ||
| 701 | nh->nh_saddr = inet_select_addr(nh->nh_dev, | ||
| 702 | nh->nh_gw, | ||
| 703 | nh->nh_parent->fib_scope); | ||
| 704 | nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid); | ||
| 705 | |||
| 706 | return nh->nh_saddr; | ||
| 707 | } | ||
| 708 | |||
| 698 | struct fib_info *fib_create_info(struct fib_config *cfg) | 709 | struct fib_info *fib_create_info(struct fib_config *cfg) |
| 699 | { | 710 | { |
| 700 | int err; | 711 | int err; |
| @@ -753,6 +764,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
| 753 | 764 | ||
| 754 | fi->fib_net = hold_net(net); | 765 | fi->fib_net = hold_net(net); |
| 755 | fi->fib_protocol = cfg->fc_protocol; | 766 | fi->fib_protocol = cfg->fc_protocol; |
| 767 | fi->fib_scope = cfg->fc_scope; | ||
| 756 | fi->fib_flags = cfg->fc_flags; | 768 | fi->fib_flags = cfg->fc_flags; |
| 757 | fi->fib_priority = cfg->fc_priority; | 769 | fi->fib_priority = cfg->fc_priority; |
| 758 | fi->fib_prefsrc = cfg->fc_prefsrc; | 770 | fi->fib_prefsrc = cfg->fc_prefsrc; |
| @@ -854,10 +866,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
| 854 | } | 866 | } |
| 855 | 867 | ||
| 856 | change_nexthops(fi) { | 868 | change_nexthops(fi) { |
| 857 | nexthop_nh->nh_cfg_scope = cfg->fc_scope; | 869 | fib_info_update_nh_saddr(net, nexthop_nh); |
| 858 | nexthop_nh->nh_saddr = inet_select_addr(nexthop_nh->nh_dev, | ||
| 859 | nexthop_nh->nh_gw, | ||
| 860 | nexthop_nh->nh_cfg_scope); | ||
| 861 | } endfor_nexthops(fi) | 870 | } endfor_nexthops(fi) |
| 862 | 871 | ||
| 863 | link_it: | 872 | link_it: |
| @@ -906,7 +915,7 @@ failure: | |||
| 906 | } | 915 | } |
| 907 | 916 | ||
| 908 | 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, |
| 909 | 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, |
| 910 | struct fib_info *fi, unsigned int flags) | 919 | struct fib_info *fi, unsigned int flags) |
| 911 | { | 920 | { |
| 912 | struct nlmsghdr *nlh; | 921 | struct nlmsghdr *nlh; |
| @@ -928,7 +937,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | |||
| 928 | NLA_PUT_U32(skb, RTA_TABLE, tb_id); | 937 | NLA_PUT_U32(skb, RTA_TABLE, tb_id); |
| 929 | rtm->rtm_type = type; | 938 | rtm->rtm_type = type; |
| 930 | rtm->rtm_flags = fi->fib_flags; | 939 | rtm->rtm_flags = fi->fib_flags; |
| 931 | rtm->rtm_scope = scope; | 940 | rtm->rtm_scope = fi->fib_scope; |
| 932 | rtm->rtm_protocol = fi->fib_protocol; | 941 | rtm->rtm_protocol = fi->fib_protocol; |
| 933 | 942 | ||
| 934 | if (rtm->rtm_dst_len) | 943 | if (rtm->rtm_dst_len) |
| @@ -1084,7 +1093,7 @@ void fib_select_default(struct fib_result *res) | |||
| 1084 | list_for_each_entry_rcu(fa, fa_head, fa_list) { | 1093 | list_for_each_entry_rcu(fa, fa_head, fa_list) { |
| 1085 | struct fib_info *next_fi = fa->fa_info; | 1094 | struct fib_info *next_fi = fa->fa_info; |
| 1086 | 1095 | ||
| 1087 | if (fa->fa_scope != res->scope || | 1096 | if (next_fi->fib_scope != res->scope || |
| 1088 | fa->fa_type != RTN_UNICAST) | 1097 | fa->fa_type != RTN_UNICAST) |
| 1089 | continue; | 1098 | continue; |
| 1090 | 1099 | ||
| @@ -1128,24 +1137,6 @@ out: | |||
| 1128 | return; | 1137 | return; |
| 1129 | } | 1138 | } |
| 1130 | 1139 | ||
| 1131 | void fib_update_nh_saddrs(struct net_device *dev) | ||
| 1132 | { | ||
| 1133 | struct hlist_head *head; | ||
| 1134 | struct hlist_node *node; | ||
| 1135 | struct fib_nh *nh; | ||
| 1136 | unsigned int hash; | ||
| 1137 | |||
| 1138 | hash = fib_devindex_hashfn(dev->ifindex); | ||
| 1139 | head = &fib_info_devhash[hash]; | ||
| 1140 | hlist_for_each_entry(nh, node, head, nh_hash) { | ||
| 1141 | if (nh->nh_dev != dev) | ||
| 1142 | continue; | ||
| 1143 | nh->nh_saddr = inet_select_addr(nh->nh_dev, | ||
| 1144 | nh->nh_gw, | ||
| 1145 | nh->nh_cfg_scope); | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1140 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
| 1150 | 1141 | ||
| 1151 | /* | 1142 | /* |
