Commit 62f26000 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[IPSEC]: Move dst->child loop from dst_ifdown to xfrm_dst_ifdown.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent de91b473
...@@ -220,31 +220,26 @@ struct dst_entry *dst_destroy(struct dst_entry * dst) ...@@ -220,31 +220,26 @@ struct dst_entry *dst_destroy(struct dst_entry * dst)
* *
* Commented and originally written by Alexey. * 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; struct net_device *dev = dst->dev;
if (dst->ops->ifdown)
dst->ops->ifdown(dst, unregister);
if (!unregister) { if (!unregister) {
dst->input = dst_discard_in; dst->input = dst_discard_in;
dst->output = dst_discard_out; dst->output = dst_discard_out;
} } else {
dst->dev = &loopback_dev;
do { dev_hold(&loopback_dev);
if (unregister) { dev_put(dev);
dst->dev = &loopback_dev; if (dst->neighbour && dst->neighbour->dev == dev) {
dev_hold(&loopback_dev); dst->neighbour->dev = &loopback_dev;
dev_put(dev); dev_put(dev);
if (dst->neighbour && dst->neighbour->dev == dev) { dev_hold(&loopback_dev);
dst->neighbour->dev = &loopback_dev;
dev_put(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) static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
......
...@@ -1043,6 +1043,20 @@ static void xfrm_dst_destroy(struct dst_entry *dst) ...@@ -1043,6 +1043,20 @@ static void xfrm_dst_destroy(struct dst_entry *dst)
dst->xfrm = NULL; 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) static void xfrm_link_failure(struct sk_buff *skb)
{ {
/* Impossible. Such dst must be popped before reaches point of failure. */ /* Impossible. Such dst must be popped before reaches point of failure. */
...@@ -1166,6 +1180,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) ...@@ -1166,6 +1180,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
dst_ops->check = xfrm_dst_check; dst_ops->check = xfrm_dst_check;
if (likely(dst_ops->destroy == NULL)) if (likely(dst_ops->destroy == NULL))
dst_ops->destroy = xfrm_dst_destroy; 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)) if (likely(dst_ops->negative_advice == NULL))
dst_ops->negative_advice = xfrm_negative_advice; dst_ops->negative_advice = xfrm_negative_advice;
if (likely(dst_ops->link_failure == NULL)) if (likely(dst_ops->link_failure == NULL))
...@@ -1198,6 +1214,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) ...@@ -1198,6 +1214,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
dst_ops->kmem_cachep = NULL; dst_ops->kmem_cachep = NULL;
dst_ops->check = NULL; dst_ops->check = NULL;
dst_ops->destroy = NULL; dst_ops->destroy = NULL;
dst_ops->ifdown = NULL;
dst_ops->negative_advice = NULL; dst_ops->negative_advice = NULL;
dst_ops->link_failure = NULL; dst_ops->link_failure = NULL;
dst_ops->get_mss = NULL; dst_ops->get_mss = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment