aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_frontend.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-24 20:42:21 -0400
committerDavid S. Miller <davem@davemloft.net>2011-03-24 20:42:21 -0400
commit436c3b66ec9824a633724ae42de1c416af4f2063 (patch)
tree8da6452386b6e900c4226c9b67694d1ea21e847e /net/ipv4/fib_frontend.c
parentf7594d42944c0dfca90318f50978a4bdf8504086 (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.c11
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: