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_frontend.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_frontend.c')
-rw-r--r-- | net/ipv4/fib_frontend.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 02c3ba61884a..f116ce8f1b46 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -228,7 +228,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
228 | if (res.type != RTN_LOCAL || !accept_local) | 228 | if (res.type != RTN_LOCAL || !accept_local) |
229 | goto e_inval; | 229 | goto e_inval; |
230 | } | 230 | } |
231 | *spec_dst = FIB_RES_PREFSRC(res); | 231 | *spec_dst = FIB_RES_PREFSRC(net, res); |
232 | fib_combine_itag(itag, &res); | 232 | fib_combine_itag(itag, &res); |
233 | dev_match = false; | 233 | dev_match = false; |
234 | 234 | ||
@@ -258,7 +258,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
258 | ret = 0; | 258 | ret = 0; |
259 | if (fib_lookup(net, &fl4, &res) == 0) { | 259 | if (fib_lookup(net, &fl4, &res) == 0) { |
260 | if (res.type == RTN_UNICAST) { | 260 | if (res.type == RTN_UNICAST) { |
261 | *spec_dst = FIB_RES_PREFSRC(res); | 261 | *spec_dst = FIB_RES_PREFSRC(net, res); |
262 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; | 262 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; |
263 | } | 263 | } |
264 | } | 264 | } |
@@ -960,6 +960,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
960 | { | 960 | { |
961 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; | 961 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; |
962 | struct net_device *dev = ifa->ifa_dev->dev; | 962 | struct net_device *dev = ifa->ifa_dev->dev; |
963 | struct net *net = dev_net(dev); | ||
963 | 964 | ||
964 | switch (event) { | 965 | switch (event) { |
965 | case NETDEV_UP: | 966 | case NETDEV_UP: |
@@ -967,12 +968,12 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
967 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 968 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
968 | fib_sync_up(dev); | 969 | fib_sync_up(dev); |
969 | #endif | 970 | #endif |
970 | fib_update_nh_saddrs(dev); | 971 | atomic_inc(&net->ipv4.dev_addr_genid); |
971 | rt_cache_flush(dev_net(dev), -1); | 972 | rt_cache_flush(dev_net(dev), -1); |
972 | break; | 973 | break; |
973 | case NETDEV_DOWN: | 974 | case NETDEV_DOWN: |
974 | fib_del_ifaddr(ifa, NULL); | 975 | fib_del_ifaddr(ifa, NULL); |
975 | fib_update_nh_saddrs(dev); | 976 | atomic_inc(&net->ipv4.dev_addr_genid); |
976 | if (ifa->ifa_dev->ifa_list == NULL) { | 977 | if (ifa->ifa_dev->ifa_list == NULL) { |
977 | /* Last address was deleted from this interface. | 978 | /* Last address was deleted from this interface. |
978 | * Disable IP. | 979 | * Disable IP. |
@@ -990,6 +991,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
990 | { | 991 | { |
991 | struct net_device *dev = ptr; | 992 | struct net_device *dev = ptr; |
992 | struct in_device *in_dev = __in_dev_get_rtnl(dev); | 993 | struct in_device *in_dev = __in_dev_get_rtnl(dev); |
994 | struct net *net = dev_net(dev); | ||
993 | 995 | ||
994 | if (event == NETDEV_UNREGISTER) { | 996 | if (event == NETDEV_UNREGISTER) { |
995 | fib_disable_ip(dev, 2, -1); | 997 | fib_disable_ip(dev, 2, -1); |
@@ -1007,6 +1009,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
1007 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1009 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
1008 | fib_sync_up(dev); | 1010 | fib_sync_up(dev); |
1009 | #endif | 1011 | #endif |
1012 | atomic_inc(&net->ipv4.dev_addr_genid); | ||
1010 | rt_cache_flush(dev_net(dev), -1); | 1013 | rt_cache_flush(dev_net(dev), -1); |
1011 | break; | 1014 | break; |
1012 | case NETDEV_DOWN: | 1015 | case NETDEV_DOWN: |