diff options
-rw-r--r-- | include/net/dn_route.h | 2 | ||||
-rw-r--r-- | net/decnet/dn_neigh.c | 2 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 36 |
3 files changed, 32 insertions, 8 deletions
diff --git a/include/net/dn_route.h b/include/net/dn_route.h index c507e05d172f..4f7d6a182381 100644 --- a/include/net/dn_route.h +++ b/include/net/dn_route.h | |||
@@ -67,6 +67,8 @@ extern void dn_rt_cache_flush(int delay); | |||
67 | struct dn_route { | 67 | struct dn_route { |
68 | struct dst_entry dst; | 68 | struct dst_entry dst; |
69 | 69 | ||
70 | struct neighbour *n; | ||
71 | |||
70 | struct flowidn fld; | 72 | struct flowidn fld; |
71 | 73 | ||
72 | __le16 rt_saddr; | 74 | __le16 rt_saddr; |
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 8e9a35b17df4..3aede1b459fd 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c | |||
@@ -202,7 +202,7 @@ static int dn_neigh_output_packet(struct sk_buff *skb) | |||
202 | { | 202 | { |
203 | struct dst_entry *dst = skb_dst(skb); | 203 | struct dst_entry *dst = skb_dst(skb); |
204 | struct dn_route *rt = (struct dn_route *)dst; | 204 | struct dn_route *rt = (struct dn_route *)dst; |
205 | struct neighbour *neigh = dst_get_neighbour_noref(dst); | 205 | struct neighbour *neigh = rt->n; |
206 | struct net_device *dev = neigh->dev; | 206 | struct net_device *dev = neigh->dev; |
207 | char mac_addr[ETH_ALEN]; | 207 | char mac_addr[ETH_ALEN]; |
208 | unsigned int seq; | 208 | unsigned int seq; |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 60e4c6e1bac0..6e74b3f110bc 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -114,6 +114,7 @@ static struct dst_entry *dn_dst_check(struct dst_entry *, __u32); | |||
114 | static unsigned int dn_dst_default_advmss(const struct dst_entry *dst); | 114 | static unsigned int dn_dst_default_advmss(const struct dst_entry *dst); |
115 | static unsigned int dn_dst_mtu(const struct dst_entry *dst); | 115 | static unsigned int dn_dst_mtu(const struct dst_entry *dst); |
116 | static void dn_dst_destroy(struct dst_entry *); | 116 | static void dn_dst_destroy(struct dst_entry *); |
117 | static void dn_dst_ifdown(struct dst_entry *, struct net_device *dev, int how); | ||
117 | static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); | 118 | static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); |
118 | static void dn_dst_link_failure(struct sk_buff *); | 119 | static void dn_dst_link_failure(struct sk_buff *); |
119 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); | 120 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); |
@@ -140,6 +141,7 @@ static struct dst_ops dn_dst_ops = { | |||
140 | .mtu = dn_dst_mtu, | 141 | .mtu = dn_dst_mtu, |
141 | .cow_metrics = dst_cow_metrics_generic, | 142 | .cow_metrics = dst_cow_metrics_generic, |
142 | .destroy = dn_dst_destroy, | 143 | .destroy = dn_dst_destroy, |
144 | .ifdown = dn_dst_ifdown, | ||
143 | .negative_advice = dn_dst_negative_advice, | 145 | .negative_advice = dn_dst_negative_advice, |
144 | .link_failure = dn_dst_link_failure, | 146 | .link_failure = dn_dst_link_failure, |
145 | .update_pmtu = dn_dst_update_pmtu, | 147 | .update_pmtu = dn_dst_update_pmtu, |
@@ -148,9 +150,27 @@ static struct dst_ops dn_dst_ops = { | |||
148 | 150 | ||
149 | static void dn_dst_destroy(struct dst_entry *dst) | 151 | static void dn_dst_destroy(struct dst_entry *dst) |
150 | { | 152 | { |
153 | struct dn_route *rt = (struct dn_route *) dst; | ||
154 | |||
155 | if (rt->n) | ||
156 | neigh_release(rt->n); | ||
151 | dst_destroy_metrics_generic(dst); | 157 | dst_destroy_metrics_generic(dst); |
152 | } | 158 | } |
153 | 159 | ||
160 | static void dn_dst_ifdown(struct dst_entry *dst, struct net_device *dev, int how) | ||
161 | { | ||
162 | if (how) { | ||
163 | struct dn_route *rt = (struct dn_route *) dst; | ||
164 | struct neighbour *n = rt->n; | ||
165 | |||
166 | if (n && n->dev == dev) { | ||
167 | n->dev = dev_net(dev)->loopback_dev; | ||
168 | dev_hold(n->dev); | ||
169 | dev_put(dev); | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | |||
154 | static __inline__ unsigned int dn_hash(__le16 src, __le16 dst) | 174 | static __inline__ unsigned int dn_hash(__le16 src, __le16 dst) |
155 | { | 175 | { |
156 | __u16 tmp = (__u16 __force)(src ^ dst); | 176 | __u16 tmp = (__u16 __force)(src ^ dst); |
@@ -246,7 +266,8 @@ static int dn_dst_gc(struct dst_ops *ops) | |||
246 | */ | 266 | */ |
247 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) | 267 | static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) |
248 | { | 268 | { |
249 | struct neighbour *n = dst_get_neighbour_noref(dst); | 269 | struct dn_route *rt = (struct dn_route *) dst; |
270 | struct neighbour *n = rt->n; | ||
250 | u32 min_mtu = 230; | 271 | u32 min_mtu = 230; |
251 | struct dn_dev *dn; | 272 | struct dn_dev *dn; |
252 | 273 | ||
@@ -715,7 +736,8 @@ out: | |||
715 | static int dn_to_neigh_output(struct sk_buff *skb) | 736 | static int dn_to_neigh_output(struct sk_buff *skb) |
716 | { | 737 | { |
717 | struct dst_entry *dst = skb_dst(skb); | 738 | struct dst_entry *dst = skb_dst(skb); |
718 | struct neighbour *n = dst_get_neighbour_noref(dst); | 739 | struct dn_route *rt = (struct dn_route *) dst; |
740 | struct neighbour *n = rt->n; | ||
719 | 741 | ||
720 | return n->output(n, skb); | 742 | return n->output(n, skb); |
721 | } | 743 | } |
@@ -729,7 +751,7 @@ static int dn_output(struct sk_buff *skb) | |||
729 | 751 | ||
730 | int err = -EINVAL; | 752 | int err = -EINVAL; |
731 | 753 | ||
732 | if (dst_get_neighbour_noref(dst) == NULL) | 754 | if (rt->n == NULL) |
733 | goto error; | 755 | goto error; |
734 | 756 | ||
735 | skb->dev = dev; | 757 | skb->dev = dev; |
@@ -852,11 +874,11 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) | |||
852 | } | 874 | } |
853 | rt->rt_type = res->type; | 875 | rt->rt_type = res->type; |
854 | 876 | ||
855 | if (dev != NULL && dst_get_neighbour_noref(&rt->dst) == NULL) { | 877 | if (dev != NULL && rt->n == NULL) { |
856 | n = __neigh_lookup_errno(&dn_neigh_table, &rt->rt_gateway, dev); | 878 | n = __neigh_lookup_errno(&dn_neigh_table, &rt->rt_gateway, dev); |
857 | if (IS_ERR(n)) | 879 | if (IS_ERR(n)) |
858 | return PTR_ERR(n); | 880 | return PTR_ERR(n); |
859 | dst_set_neighbour(&rt->dst, n); | 881 | rt->n = n; |
860 | } | 882 | } |
861 | 883 | ||
862 | if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) | 884 | if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) |
@@ -1163,7 +1185,7 @@ make_route: | |||
1163 | rt->rt_dst_map = fld.daddr; | 1185 | rt->rt_dst_map = fld.daddr; |
1164 | rt->rt_src_map = fld.saddr; | 1186 | rt->rt_src_map = fld.saddr; |
1165 | 1187 | ||
1166 | dst_set_neighbour(&rt->dst, neigh); | 1188 | rt->n = neigh; |
1167 | neigh = NULL; | 1189 | neigh = NULL; |
1168 | 1190 | ||
1169 | rt->dst.lastuse = jiffies; | 1191 | rt->dst.lastuse = jiffies; |
@@ -1433,7 +1455,7 @@ make_route: | |||
1433 | rt->fld.flowidn_iif = in_dev->ifindex; | 1455 | rt->fld.flowidn_iif = in_dev->ifindex; |
1434 | rt->fld.flowidn_mark = fld.flowidn_mark; | 1456 | rt->fld.flowidn_mark = fld.flowidn_mark; |
1435 | 1457 | ||
1436 | dst_set_neighbour(&rt->dst, neigh); | 1458 | rt->n = neigh; |
1437 | rt->dst.lastuse = jiffies; | 1459 | rt->dst.lastuse = jiffies; |
1438 | rt->dst.output = dn_rt_bug; | 1460 | rt->dst.output = dn_rt_bug; |
1439 | switch (res.type) { | 1461 | switch (res.type) { |