aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_semantics.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-05-24 03:59:36 -0400
committerTejun Heo <tj@kernel.org>2011-05-24 03:59:36 -0400
commit6988f20fe04e9ef3aea488cb8ab57fbeb78e12f0 (patch)
treec9d7fc50a2e2147a5ca07e3096e7eeb916ad2da9 /net/ipv4/fib_semantics.c
parent0415b00d175e0d8945e6785aad21b5f157976ce0 (diff)
parent6ea0c34dac89611126455537552cffe6c7e832ad (diff)
Merge branch 'fixes-2.6.39' into for-2.6.40
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r--net/ipv4/fib_semantics.c47
1 files changed, 19 insertions, 28 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 622ac4c9502..641a5a2a9f9 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
698struct fib_info *fib_create_info(struct fib_config *cfg) 709struct 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
863link_it: 872link_it:
@@ -906,7 +915,7 @@ failure:
906} 915}
907 916
908int 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,
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
1131void 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/*