Commit caa702e2 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji Committed by David S. Miller

[NET]: Add dst->ifdown callback.

Use it to release protocol specific objects that may be
tied to a dst cache object, at ifdown time.  Currently
this is used to release ipv4/ipv6 specific device state.
parent c4519d3c
...@@ -89,6 +89,7 @@ struct dst_ops ...@@ -89,6 +89,7 @@ struct dst_ops
int (*gc)(void); int (*gc)(void);
struct dst_entry * (*check)(struct dst_entry *, __u32 cookie); struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
void (*destroy)(struct dst_entry *); void (*destroy)(struct dst_entry *);
void (*ifdown)(struct dst_entry *, int how);
struct dst_entry * (*negative_advice)(struct dst_entry *); struct dst_entry * (*negative_advice)(struct dst_entry *);
void (*link_failure)(struct sk_buff *); void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, u32 mtu); void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
......
...@@ -230,8 +230,8 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void ...@@ -230,8 +230,8 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
if (event!=NETDEV_DOWN && if (event!=NETDEV_DOWN &&
dst->output == dst_discard_out) { dst->output == dst_discard_out) {
dst->dev = &loopback_dev; dst->dev = &loopback_dev;
dev_put(dev);
dev_hold(&loopback_dev); dev_hold(&loopback_dev);
dev_put(dev);
dst->output = dst_discard_out; dst->output = dst_discard_out;
if (dst->neighbour && dst->neighbour->dev == dev) { if (dst->neighbour && dst->neighbour->dev == dev) {
dst->neighbour->dev = &loopback_dev; dst->neighbour->dev = &loopback_dev;
...@@ -242,6 +242,8 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void ...@@ -242,6 +242,8 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
dst->input = dst_discard_in; dst->input = dst_discard_in;
dst->output = dst_discard_out; dst->output = dst_discard_out;
} }
if (dst->ops->ifdown)
dst->ops->ifdown(dst, event != NETDEV_DOWN);
} }
} }
spin_unlock_bh(&dst_lock); spin_unlock_bh(&dst_lock);
......
...@@ -138,6 +138,7 @@ static struct timer_list rt_secret_timer; ...@@ -138,6 +138,7 @@ static struct timer_list rt_secret_timer;
static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
static void ipv4_dst_destroy(struct dst_entry *dst); static void ipv4_dst_destroy(struct dst_entry *dst);
static void ipv4_dst_ifdown(struct dst_entry *dst, int how);
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
static void ipv4_link_failure(struct sk_buff *skb); static void ipv4_link_failure(struct sk_buff *skb);
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu); static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
...@@ -150,6 +151,7 @@ static struct dst_ops ipv4_dst_ops = { ...@@ -150,6 +151,7 @@ static struct dst_ops ipv4_dst_ops = {
.gc = rt_garbage_collect, .gc = rt_garbage_collect,
.check = ipv4_dst_check, .check = ipv4_dst_check,
.destroy = ipv4_dst_destroy, .destroy = ipv4_dst_destroy,
.ifdown = ipv4_dst_ifdown,
.negative_advice = ipv4_negative_advice, .negative_advice = ipv4_negative_advice,
.link_failure = ipv4_link_failure, .link_failure = ipv4_link_failure,
.update_pmtu = ip_rt_update_pmtu, .update_pmtu = ip_rt_update_pmtu,
...@@ -1336,6 +1338,16 @@ static void ipv4_dst_destroy(struct dst_entry *dst) ...@@ -1336,6 +1338,16 @@ static void ipv4_dst_destroy(struct dst_entry *dst)
} }
} }
static void ipv4_dst_ifdown(struct dst_entry *dst, int how)
{
struct rtable *rt = (struct rtable *) dst;
struct in_device *idev = rt->idev;
if (idev) {
rt->idev = NULL;
in_dev_put(idev);
}
}
static void ipv4_link_failure(struct sk_buff *skb) static void ipv4_link_failure(struct sk_buff *skb)
{ {
struct rtable *rt; struct rtable *rt;
......
...@@ -84,6 +84,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); ...@@ -84,6 +84,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort);
static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
static struct dst_entry *ip6_negative_advice(struct dst_entry *); static struct dst_entry *ip6_negative_advice(struct dst_entry *);
static void ip6_dst_destroy(struct dst_entry *); static void ip6_dst_destroy(struct dst_entry *);
static void ip6_dst_ifdown(struct dst_entry *, int how);
static int ip6_dst_gc(void); static int ip6_dst_gc(void);
static int ip6_pkt_discard(struct sk_buff *skb); static int ip6_pkt_discard(struct sk_buff *skb);
...@@ -98,6 +99,7 @@ static struct dst_ops ip6_dst_ops = { ...@@ -98,6 +99,7 @@ static struct dst_ops ip6_dst_ops = {
.gc_thresh = 1024, .gc_thresh = 1024,
.check = ip6_dst_check, .check = ip6_dst_check,
.destroy = ip6_dst_destroy, .destroy = ip6_dst_destroy,
.ifdown = ip6_dst_ifdown,
.negative_advice = ip6_negative_advice, .negative_advice = ip6_negative_advice,
.link_failure = ip6_link_failure, .link_failure = ip6_link_failure,
.update_pmtu = ip6_rt_update_pmtu, .update_pmtu = ip6_rt_update_pmtu,
...@@ -143,9 +145,17 @@ static __inline__ struct rt6_info *ip6_dst_alloc(void) ...@@ -143,9 +145,17 @@ static __inline__ struct rt6_info *ip6_dst_alloc(void)
static void ip6_dst_destroy(struct dst_entry *dst) static void ip6_dst_destroy(struct dst_entry *dst)
{ {
struct rt6_info *rt = (struct rt6_info *)dst; struct rt6_info *rt = (struct rt6_info *)dst;
if (rt->rt6i_idev != NULL) struct inet6_dev *idev = rt->rt6i_idev;
in6_dev_put(rt->rt6i_idev);
if (idev != NULL) {
rt->rt6i_idev = NULL;
in6_dev_put(idev);
}
}
static void ip6_dst_ifdown(struct dst_entry *dst, int how)
{
ip6_dst_destroy(dst);
} }
/* /*
......
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