On Sun, Feb 06, 2005 at 05:51:17PM +1100, herbert wrote: > > The idea is to move the check into dst->ops->ifdown. By definition > ipv6_dst_ifdown will only see rt6_info entries. So dst_dev_event > will become
Here are the patches to do this. Do they look sane? This one moves the dst->child processing from dst_ifdown into xfrm_dst_ifdown. Signed-off-by: Herbert Xu <[EMAIL PROTECTED]> Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
===== net/core/dst.c 1.26 vs edited ===== --- 1.26/net/core/dst.c 2005-02-06 14:23:59 +11:00 +++ edited/net/core/dst.c 2005-02-08 12:11:39 +11:00 @@ -220,31 +220,26 @@ * * Commented and originally written by Alexey. */ -static void dst_ifdown(struct dst_entry *dst, int unregister) +static inline void dst_ifdown(struct dst_entry *dst, int unregister) { struct net_device *dev = dst->dev; + if (dst->ops->ifdown) + dst->ops->ifdown(dst, unregister); + if (!unregister) { dst->input = dst_discard_in; dst->output = dst_discard_out; - } - - do { - if (unregister) { - dst->dev = &loopback_dev; - dev_hold(&loopback_dev); + } else { + dst->dev = &loopback_dev; + dev_hold(&loopback_dev); + dev_put(dev); + if (dst->neighbour && dst->neighbour->dev == dev) { + dst->neighbour->dev = &loopback_dev; dev_put(dev); - if (dst->neighbour && dst->neighbour->dev == dev) { - dst->neighbour->dev = &loopback_dev; - dev_put(dev); - dev_hold(&loopback_dev); - } + dev_hold(&loopback_dev); } - - if (dst->ops->ifdown) - dst->ops->ifdown(dst, unregister); - } while ((dst = dst->child) && dst->flags & DST_NOHASH && - dst->dev == dev); + } } static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr) ===== net/xfrm/xfrm_policy.c 1.63 vs edited ===== --- 1.63/net/xfrm/xfrm_policy.c 2005-01-19 07:08:19 +11:00 +++ edited/net/xfrm/xfrm_policy.c 2005-02-08 12:10:47 +11:00 @@ -1027,6 +1027,20 @@ dst->xfrm = NULL; } +static void xfrm_dst_ifdown(struct dst_entry *dst, int unregister) +{ + struct net_device *dev = dst->dev; + + if (!unregister) + return; + + while ((dst = dst->child) && dst->xfrm && dst->dev == dev) { + dst->dev = &loopback_dev; + dev_hold(&loopback_dev); + dev_put(dev); + } +} + static void xfrm_link_failure(struct sk_buff *skb) { /* Impossible. Such dst must be popped before reaches point of failure. */ @@ -1150,6 +1164,8 @@ dst_ops->check = xfrm_dst_check; if (likely(dst_ops->destroy == NULL)) dst_ops->destroy = xfrm_dst_destroy; + if (likely(dst_ops->ifdown == NULL)) + dst_ops->ifdown = xfrm_dst_ifdown; if (likely(dst_ops->negative_advice == NULL)) dst_ops->negative_advice = xfrm_negative_advice; if (likely(dst_ops->link_failure == NULL)) @@ -1181,6 +1197,7 @@ dst_ops->kmem_cachep = NULL; dst_ops->check = NULL; dst_ops->destroy = NULL; + dst_ops->ifdown = NULL; dst_ops->negative_advice = NULL; dst_ops->link_failure = NULL; dst_ops->get_mss = NULL;