diff options
author | David S. Miller <davem@davemloft.net> | 2011-07-17 16:34:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-18 02:11:17 -0400 |
commit | 8f40b161de4f27402b4c0659ad2ae83fad5a0cdd (patch) | |
tree | 9e2dbd4ba8a66916c690b0e5791ac25ea0958c26 | |
parent | 69ecca86da4890c13a5e29c51b4ac76a1a8a62c9 (diff) |
neigh: Pass neighbour entry to output ops.
This will get us closer to being able to do "neigh stuff"
completely independent of the underlying dst_entry for
protocols (ipv4/ipv6) that wish to do so.
We will also be able to make dst entries neigh-less.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/neighbour.h | 19 | ||||
-rw-r--r-- | net/atm/clip.c | 4 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 4 | ||||
-rw-r--r-- | net/core/neighbour.c | 25 | ||||
-rw-r--r-- | net/decnet/dn_neigh.c | 18 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 13 | ||||
-rw-r--r-- | net/ipv4/arp.c | 6 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 6 |
8 files changed, 50 insertions, 45 deletions
diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 334e92f95bbb..4ba8521490ba 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h | |||
@@ -109,7 +109,7 @@ struct neighbour { | |||
109 | seqlock_t ha_lock; | 109 | seqlock_t ha_lock; |
110 | unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; | 110 | unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; |
111 | struct hh_cache hh; | 111 | struct hh_cache hh; |
112 | int (*output)(struct sk_buff *skb); | 112 | int (*output)(struct neighbour *, struct sk_buff *); |
113 | const struct neigh_ops *ops; | 113 | const struct neigh_ops *ops; |
114 | struct rcu_head rcu; | 114 | struct rcu_head rcu; |
115 | struct net_device *dev; | 115 | struct net_device *dev; |
@@ -118,10 +118,10 @@ struct neighbour { | |||
118 | 118 | ||
119 | struct neigh_ops { | 119 | struct neigh_ops { |
120 | int family; | 120 | int family; |
121 | void (*solicit)(struct neighbour *, struct sk_buff*); | 121 | void (*solicit)(struct neighbour *, struct sk_buff *); |
122 | void (*error_report)(struct neighbour *, struct sk_buff*); | 122 | void (*error_report)(struct neighbour *, struct sk_buff *); |
123 | int (*output)(struct sk_buff*); | 123 | int (*output)(struct neighbour *, struct sk_buff *); |
124 | int (*connected_output)(struct sk_buff*); | 124 | int (*connected_output)(struct neighbour *, struct sk_buff *); |
125 | }; | 125 | }; |
126 | 126 | ||
127 | struct pneigh_entry { | 127 | struct pneigh_entry { |
@@ -203,9 +203,10 @@ extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, | |||
203 | u32 flags); | 203 | u32 flags); |
204 | extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); | 204 | extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); |
205 | extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev); | 205 | extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev); |
206 | extern int neigh_resolve_output(struct sk_buff *skb); | 206 | extern int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb); |
207 | extern int neigh_connected_output(struct sk_buff *skb); | 207 | extern int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb); |
208 | extern int neigh_compat_output(struct sk_buff *skb); | 208 | extern int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb); |
209 | extern int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb); | ||
209 | extern struct neighbour *neigh_event_ns(struct neigh_table *tbl, | 210 | extern struct neighbour *neigh_event_ns(struct neigh_table *tbl, |
210 | u8 *lladdr, void *saddr, | 211 | u8 *lladdr, void *saddr, |
211 | struct net_device *dev); | 212 | struct net_device *dev); |
@@ -348,7 +349,7 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb) | |||
348 | if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) | 349 | if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) |
349 | return neigh_hh_output(hh, skb); | 350 | return neigh_hh_output(hh, skb); |
350 | else | 351 | else |
351 | return n->output(skb); | 352 | return n->output(n, skb); |
352 | } | 353 | } |
353 | 354 | ||
354 | static inline struct neighbour * | 355 | static inline struct neighbour * |
diff --git a/net/atm/clip.c b/net/atm/clip.c index 40d736899676..c6cd5318be3f 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -271,8 +271,8 @@ static const struct neigh_ops clip_neigh_ops = { | |||
271 | .family = AF_INET, | 271 | .family = AF_INET, |
272 | .solicit = clip_neigh_solicit, | 272 | .solicit = clip_neigh_solicit, |
273 | .error_report = clip_neigh_error, | 273 | .error_report = clip_neigh_error, |
274 | .output = dev_queue_xmit, | 274 | .output = neigh_direct_output, |
275 | .connected_output = dev_queue_xmit, | 275 | .connected_output = neigh_direct_output, |
276 | }; | 276 | }; |
277 | 277 | ||
278 | static int clip_constructor(struct neighbour *neigh) | 278 | static int clip_constructor(struct neighbour *neigh) |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 75ee421917c7..1fe43fdf9973 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -355,14 +355,14 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) | |||
355 | neigh_hh_bridge(&neigh->hh, skb); | 355 | neigh_hh_bridge(&neigh->hh, skb); |
356 | skb->dev = nf_bridge->physindev; | 356 | skb->dev = nf_bridge->physindev; |
357 | return br_handle_frame_finish(skb); | 357 | return br_handle_frame_finish(skb); |
358 | } else if (dst->neighbour) { | 358 | } else { |
359 | /* the neighbour function below overwrites the complete | 359 | /* the neighbour function below overwrites the complete |
360 | * MAC header, so we save the Ethernet source address and | 360 | * MAC header, so we save the Ethernet source address and |
361 | * protocol number. */ | 361 | * protocol number. */ |
362 | skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); | 362 | skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); |
363 | /* tell br_dev_xmit to continue with forwarding */ | 363 | /* tell br_dev_xmit to continue with forwarding */ |
364 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; | 364 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; |
365 | return dst->neighbour->output(skb); | 365 | return neigh->output(neigh, skb); |
366 | } | 366 | } |
367 | free_skb: | 367 | free_skb: |
368 | kfree_skb(skb); | 368 | kfree_skb(skb); |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b031cf63d6ad..cefb8e52615e 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -98,7 +98,7 @@ static const struct file_operations neigh_stat_seq_fops; | |||
98 | 98 | ||
99 | static DEFINE_RWLOCK(neigh_tbl_lock); | 99 | static DEFINE_RWLOCK(neigh_tbl_lock); |
100 | 100 | ||
101 | static int neigh_blackhole(struct sk_buff *skb) | 101 | static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb) |
102 | { | 102 | { |
103 | kfree_skb(skb); | 103 | kfree_skb(skb); |
104 | return -ENETDOWN; | 104 | return -ENETDOWN; |
@@ -1158,7 +1158,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, | |||
1158 | /* On shaper/eql skb->dst->neighbour != neigh :( */ | 1158 | /* On shaper/eql skb->dst->neighbour != neigh :( */ |
1159 | if (skb_dst(skb) && skb_dst(skb)->neighbour) | 1159 | if (skb_dst(skb) && skb_dst(skb)->neighbour) |
1160 | n1 = skb_dst(skb)->neighbour; | 1160 | n1 = skb_dst(skb)->neighbour; |
1161 | n1->output(skb); | 1161 | n1->output(n1, skb); |
1162 | write_lock_bh(&neigh->lock); | 1162 | write_lock_bh(&neigh->lock); |
1163 | } | 1163 | } |
1164 | skb_queue_purge(&neigh->arp_queue); | 1164 | skb_queue_purge(&neigh->arp_queue); |
@@ -1214,7 +1214,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst) | |||
1214 | * but resolution is not made yet. | 1214 | * but resolution is not made yet. |
1215 | */ | 1215 | */ |
1216 | 1216 | ||
1217 | int neigh_compat_output(struct sk_buff *skb) | 1217 | int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb) |
1218 | { | 1218 | { |
1219 | struct net_device *dev = skb->dev; | 1219 | struct net_device *dev = skb->dev; |
1220 | 1220 | ||
@@ -1231,13 +1231,12 @@ EXPORT_SYMBOL(neigh_compat_output); | |||
1231 | 1231 | ||
1232 | /* Slow and careful. */ | 1232 | /* Slow and careful. */ |
1233 | 1233 | ||
1234 | int neigh_resolve_output(struct sk_buff *skb) | 1234 | int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) |
1235 | { | 1235 | { |
1236 | struct dst_entry *dst = skb_dst(skb); | 1236 | struct dst_entry *dst = skb_dst(skb); |
1237 | struct neighbour *neigh; | ||
1238 | int rc = 0; | 1237 | int rc = 0; |
1239 | 1238 | ||
1240 | if (!dst || !(neigh = dst->neighbour)) | 1239 | if (!dst) |
1241 | goto discard; | 1240 | goto discard; |
1242 | 1241 | ||
1243 | __skb_pull(skb, skb_network_offset(skb)); | 1242 | __skb_pull(skb, skb_network_offset(skb)); |
@@ -1265,7 +1264,7 @@ out: | |||
1265 | return rc; | 1264 | return rc; |
1266 | discard: | 1265 | discard: |
1267 | NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n", | 1266 | NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n", |
1268 | dst, dst ? dst->neighbour : NULL); | 1267 | dst, neigh); |
1269 | out_kfree_skb: | 1268 | out_kfree_skb: |
1270 | rc = -EINVAL; | 1269 | rc = -EINVAL; |
1271 | kfree_skb(skb); | 1270 | kfree_skb(skb); |
@@ -1275,13 +1274,11 @@ EXPORT_SYMBOL(neigh_resolve_output); | |||
1275 | 1274 | ||
1276 | /* As fast as possible without hh cache */ | 1275 | /* As fast as possible without hh cache */ |
1277 | 1276 | ||
1278 | int neigh_connected_output(struct sk_buff *skb) | 1277 | int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb) |
1279 | { | 1278 | { |
1280 | int err; | ||
1281 | struct dst_entry *dst = skb_dst(skb); | ||
1282 | struct neighbour *neigh = dst->neighbour; | ||
1283 | struct net_device *dev = neigh->dev; | 1279 | struct net_device *dev = neigh->dev; |
1284 | unsigned int seq; | 1280 | unsigned int seq; |
1281 | int err; | ||
1285 | 1282 | ||
1286 | __skb_pull(skb, skb_network_offset(skb)); | 1283 | __skb_pull(skb, skb_network_offset(skb)); |
1287 | 1284 | ||
@@ -1301,6 +1298,12 @@ int neigh_connected_output(struct sk_buff *skb) | |||
1301 | } | 1298 | } |
1302 | EXPORT_SYMBOL(neigh_connected_output); | 1299 | EXPORT_SYMBOL(neigh_connected_output); |
1303 | 1300 | ||
1301 | int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb) | ||
1302 | { | ||
1303 | return dev_queue_xmit(skb); | ||
1304 | } | ||
1305 | EXPORT_SYMBOL(neigh_direct_output); | ||
1306 | |||
1304 | static void neigh_proxy_process(unsigned long arg) | 1307 | static void neigh_proxy_process(unsigned long arg) |
1305 | { | 1308 | { |
1306 | struct neigh_table *tbl = (struct neigh_table *)arg; | 1309 | struct neigh_table *tbl = (struct neigh_table *)arg; |
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 84fee8a4f89d..5d61e8965b66 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c | |||
@@ -51,9 +51,9 @@ | |||
51 | static int dn_neigh_construct(struct neighbour *); | 51 | static int dn_neigh_construct(struct neighbour *); |
52 | static void dn_long_error_report(struct neighbour *, struct sk_buff *); | 52 | static void dn_long_error_report(struct neighbour *, struct sk_buff *); |
53 | static void dn_short_error_report(struct neighbour *, struct sk_buff *); | 53 | static void dn_short_error_report(struct neighbour *, struct sk_buff *); |
54 | static int dn_long_output(struct sk_buff *); | 54 | static int dn_long_output(struct neighbour *, struct sk_buff *); |
55 | static int dn_short_output(struct sk_buff *); | 55 | static int dn_short_output(struct neighbour *, struct sk_buff *); |
56 | static int dn_phase3_output(struct sk_buff *); | 56 | static int dn_phase3_output(struct neighbour *, struct sk_buff *); |
57 | 57 | ||
58 | 58 | ||
59 | /* | 59 | /* |
@@ -218,10 +218,8 @@ static int dn_neigh_output_packet(struct sk_buff *skb) | |||
218 | return -EINVAL; | 218 | return -EINVAL; |
219 | } | 219 | } |
220 | 220 | ||
221 | static int dn_long_output(struct sk_buff *skb) | 221 | static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb) |
222 | { | 222 | { |
223 | struct dst_entry *dst = skb_dst(skb); | ||
224 | struct neighbour *neigh = dst->neighbour; | ||
225 | struct net_device *dev = neigh->dev; | 223 | struct net_device *dev = neigh->dev; |
226 | int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3; | 224 | int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3; |
227 | unsigned char *data; | 225 | unsigned char *data; |
@@ -265,10 +263,8 @@ static int dn_long_output(struct sk_buff *skb) | |||
265 | neigh->dev, dn_neigh_output_packet); | 263 | neigh->dev, dn_neigh_output_packet); |
266 | } | 264 | } |
267 | 265 | ||
268 | static int dn_short_output(struct sk_buff *skb) | 266 | static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb) |
269 | { | 267 | { |
270 | struct dst_entry *dst = skb_dst(skb); | ||
271 | struct neighbour *neigh = dst->neighbour; | ||
272 | struct net_device *dev = neigh->dev; | 268 | struct net_device *dev = neigh->dev; |
273 | int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; | 269 | int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; |
274 | struct dn_short_packet *sp; | 270 | struct dn_short_packet *sp; |
@@ -309,10 +305,8 @@ static int dn_short_output(struct sk_buff *skb) | |||
309 | * Phase 3 output is the same is short output, execpt that | 305 | * Phase 3 output is the same is short output, execpt that |
310 | * it clears the area bits before transmission. | 306 | * it clears the area bits before transmission. |
311 | */ | 307 | */ |
312 | static int dn_phase3_output(struct sk_buff *skb) | 308 | static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb) |
313 | { | 309 | { |
314 | struct dst_entry *dst = skb_dst(skb); | ||
315 | struct neighbour *neigh = dst->neighbour; | ||
316 | struct net_device *dev = neigh->dev; | 310 | struct net_device *dev = neigh->dev; |
317 | int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; | 311 | int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; |
318 | struct dn_short_packet *sp; | 312 | struct dn_short_packet *sp; |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index fceb86ca0116..3b6400d17dc2 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -705,6 +705,14 @@ out: | |||
705 | return NET_RX_DROP; | 705 | return NET_RX_DROP; |
706 | } | 706 | } |
707 | 707 | ||
708 | static int dn_to_neigh_output(struct sk_buff *skb) | ||
709 | { | ||
710 | struct dst_entry *dst = skb_dst(skb); | ||
711 | struct neighbour *n = dst->neighbour; | ||
712 | |||
713 | return n->output(n, skb); | ||
714 | } | ||
715 | |||
708 | static int dn_output(struct sk_buff *skb) | 716 | static int dn_output(struct sk_buff *skb) |
709 | { | 717 | { |
710 | struct dst_entry *dst = skb_dst(skb); | 718 | struct dst_entry *dst = skb_dst(skb); |
@@ -733,7 +741,7 @@ static int dn_output(struct sk_buff *skb) | |||
733 | cb->hops = 0; | 741 | cb->hops = 0; |
734 | 742 | ||
735 | return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, skb, NULL, dev, | 743 | return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, skb, NULL, dev, |
736 | neigh->output); | 744 | dn_to_neigh_output); |
737 | 745 | ||
738 | error: | 746 | error: |
739 | if (net_ratelimit()) | 747 | if (net_ratelimit()) |
@@ -750,7 +758,6 @@ static int dn_forward(struct sk_buff *skb) | |||
750 | struct dst_entry *dst = skb_dst(skb); | 758 | struct dst_entry *dst = skb_dst(skb); |
751 | struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr); | 759 | struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr); |
752 | struct dn_route *rt; | 760 | struct dn_route *rt; |
753 | struct neighbour *neigh = dst->neighbour; | ||
754 | int header_len; | 761 | int header_len; |
755 | #ifdef CONFIG_NETFILTER | 762 | #ifdef CONFIG_NETFILTER |
756 | struct net_device *dev = skb->dev; | 763 | struct net_device *dev = skb->dev; |
@@ -783,7 +790,7 @@ static int dn_forward(struct sk_buff *skb) | |||
783 | cb->rt_flags |= DN_RT_F_IE; | 790 | cb->rt_flags |= DN_RT_F_IE; |
784 | 791 | ||
785 | return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, skb, dev, skb->dev, | 792 | return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, skb, dev, skb->dev, |
786 | neigh->output); | 793 | dn_to_neigh_output); |
787 | 794 | ||
788 | drop: | 795 | drop: |
789 | kfree_skb(skb); | 796 | kfree_skb(skb); |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 8a21403cdd3c..96a164aa1367 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -150,8 +150,8 @@ static const struct neigh_ops arp_hh_ops = { | |||
150 | 150 | ||
151 | static const struct neigh_ops arp_direct_ops = { | 151 | static const struct neigh_ops arp_direct_ops = { |
152 | .family = AF_INET, | 152 | .family = AF_INET, |
153 | .output = dev_queue_xmit, | 153 | .output = neigh_direct_output, |
154 | .connected_output = dev_queue_xmit, | 154 | .connected_output = neigh_direct_output, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static const struct neigh_ops arp_broken_ops = { | 157 | static const struct neigh_ops arp_broken_ops = { |
@@ -250,7 +250,7 @@ static int arp_constructor(struct neighbour *neigh) | |||
250 | if (!dev->header_ops) { | 250 | if (!dev->header_ops) { |
251 | neigh->nud_state = NUD_NOARP; | 251 | neigh->nud_state = NUD_NOARP; |
252 | neigh->ops = &arp_direct_ops; | 252 | neigh->ops = &arp_direct_ops; |
253 | neigh->output = dev_queue_xmit; | 253 | neigh->output = neigh_direct_output; |
254 | } else { | 254 | } else { |
255 | /* Good devices (checked by reading texts, but only Ethernet is | 255 | /* Good devices (checked by reading texts, but only Ethernet is |
256 | tested) | 256 | tested) |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 482b970b835a..e08ce552d80b 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -120,8 +120,8 @@ static const struct neigh_ops ndisc_hh_ops = { | |||
120 | 120 | ||
121 | static const struct neigh_ops ndisc_direct_ops = { | 121 | static const struct neigh_ops ndisc_direct_ops = { |
122 | .family = AF_INET6, | 122 | .family = AF_INET6, |
123 | .output = dev_queue_xmit, | 123 | .output = neigh_direct_output, |
124 | .connected_output = dev_queue_xmit, | 124 | .connected_output = neigh_direct_output, |
125 | }; | 125 | }; |
126 | 126 | ||
127 | struct neigh_table nd_tbl = { | 127 | struct neigh_table nd_tbl = { |
@@ -386,7 +386,7 @@ static int ndisc_constructor(struct neighbour *neigh) | |||
386 | if (!dev->header_ops) { | 386 | if (!dev->header_ops) { |
387 | neigh->nud_state = NUD_NOARP; | 387 | neigh->nud_state = NUD_NOARP; |
388 | neigh->ops = &ndisc_direct_ops; | 388 | neigh->ops = &ndisc_direct_ops; |
389 | neigh->output = dev_queue_xmit; | 389 | neigh->output = neigh_direct_output; |
390 | } else { | 390 | } else { |
391 | if (is_multicast) { | 391 | if (is_multicast) { |
392 | neigh->nud_state = NUD_NOARP; | 392 | neigh->nud_state = NUD_NOARP; |