diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-24 20:42:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-24 20:42:21 -0400 |
commit | 436c3b66ec9824a633724ae42de1c416af4f2063 (patch) | |
tree | 8da6452386b6e900c4226c9b67694d1ea21e847e /net/ipv4/fib_semantics.c | |
parent | f7594d42944c0dfca90318f50978a4bdf8504086 (diff) |
ipv4: Invalidate nexthop cache nh_saddr more correctly.
Any operation that:
1) Brings up an interface
2) Adds an IP address to an interface
3) Deletes an IP address from an interface
can potentially invalidate the nh_saddr value, requiring
it to be recomputed.
Perform the recomputation lazily using a generation ID.
Reported-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r-- | net/ipv4/fib_semantics.c | 32 |
1 files changed, 11 insertions, 21 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 75b9fb5d5d37..2d4bebca671a 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -695,6 +695,16 @@ static void fib_info_hash_move(struct hlist_head *new_info_hash, | |||
695 | fib_info_hash_free(old_laddrhash, bytes); | 695 | fib_info_hash_free(old_laddrhash, bytes); |
696 | } | 696 | } |
697 | 697 | ||
698 | __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh) | ||
699 | { | ||
700 | nh->nh_saddr = inet_select_addr(nh->nh_dev, | ||
701 | nh->nh_gw, | ||
702 | nh->nh_cfg_scope); | ||
703 | nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid); | ||
704 | |||
705 | return nh->nh_saddr; | ||
706 | } | ||
707 | |||
698 | struct fib_info *fib_create_info(struct fib_config *cfg) | 708 | struct fib_info *fib_create_info(struct fib_config *cfg) |
699 | { | 709 | { |
700 | int err; | 710 | int err; |
@@ -855,9 +865,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
855 | 865 | ||
856 | change_nexthops(fi) { | 866 | change_nexthops(fi) { |
857 | nexthop_nh->nh_cfg_scope = cfg->fc_scope; | 867 | nexthop_nh->nh_cfg_scope = cfg->fc_scope; |
858 | nexthop_nh->nh_saddr = inet_select_addr(nexthop_nh->nh_dev, | 868 | fib_info_update_nh_saddr(net, nexthop_nh); |
859 | nexthop_nh->nh_gw, | ||
860 | nexthop_nh->nh_cfg_scope); | ||
861 | } endfor_nexthops(fi) | 869 | } endfor_nexthops(fi) |
862 | 870 | ||
863 | link_it: | 871 | link_it: |
@@ -1128,24 +1136,6 @@ out: | |||
1128 | return; | 1136 | return; |
1129 | } | 1137 | } |
1130 | 1138 | ||
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 | 1139 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
1150 | 1140 | ||
1151 | /* | 1141 | /* |