aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-07-17 16:34:11 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-18 02:11:17 -0400
commit8f40b161de4f27402b4c0659ad2ae83fad5a0cdd (patch)
tree9e2dbd4ba8a66916c690b0e5791ac25ea0958c26
parent69ecca86da4890c13a5e29c51b4ac76a1a8a62c9 (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.h19
-rw-r--r--net/atm/clip.c4
-rw-r--r--net/bridge/br_netfilter.c4
-rw-r--r--net/core/neighbour.c25
-rw-r--r--net/decnet/dn_neigh.c18
-rw-r--r--net/decnet/dn_route.c13
-rw-r--r--net/ipv4/arp.c6
-rw-r--r--net/ipv6/ndisc.c6
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
119struct neigh_ops { 119struct 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
127struct pneigh_entry { 127struct pneigh_entry {
@@ -203,9 +203,10 @@ extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
203 u32 flags); 203 u32 flags);
204extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); 204extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
205extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev); 205extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
206extern int neigh_resolve_output(struct sk_buff *skb); 206extern int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
207extern int neigh_connected_output(struct sk_buff *skb); 207extern int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb);
208extern int neigh_compat_output(struct sk_buff *skb); 208extern int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb);
209extern int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb);
209extern struct neighbour *neigh_event_ns(struct neigh_table *tbl, 210extern 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
354static inline struct neighbour * 355static 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
278static int clip_constructor(struct neighbour *neigh) 278static 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 }
367free_skb: 367free_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
99static DEFINE_RWLOCK(neigh_tbl_lock); 99static DEFINE_RWLOCK(neigh_tbl_lock);
100 100
101static int neigh_blackhole(struct sk_buff *skb) 101static 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
1217int neigh_compat_output(struct sk_buff *skb) 1217int 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
1234int neigh_resolve_output(struct sk_buff *skb) 1234int 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;
1266discard: 1265discard:
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);
1269out_kfree_skb: 1268out_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
1278int neigh_connected_output(struct sk_buff *skb) 1277int 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}
1302EXPORT_SYMBOL(neigh_connected_output); 1299EXPORT_SYMBOL(neigh_connected_output);
1303 1300
1301int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1302{
1303 return dev_queue_xmit(skb);
1304}
1305EXPORT_SYMBOL(neigh_direct_output);
1306
1304static void neigh_proxy_process(unsigned long arg) 1307static 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 @@
51static int dn_neigh_construct(struct neighbour *); 51static int dn_neigh_construct(struct neighbour *);
52static void dn_long_error_report(struct neighbour *, struct sk_buff *); 52static void dn_long_error_report(struct neighbour *, struct sk_buff *);
53static void dn_short_error_report(struct neighbour *, struct sk_buff *); 53static void dn_short_error_report(struct neighbour *, struct sk_buff *);
54static int dn_long_output(struct sk_buff *); 54static int dn_long_output(struct neighbour *, struct sk_buff *);
55static int dn_short_output(struct sk_buff *); 55static int dn_short_output(struct neighbour *, struct sk_buff *);
56static int dn_phase3_output(struct sk_buff *); 56static 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
221static int dn_long_output(struct sk_buff *skb) 221static 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
268static int dn_short_output(struct sk_buff *skb) 266static 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 */
312static int dn_phase3_output(struct sk_buff *skb) 308static 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
708static 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
708static int dn_output(struct sk_buff *skb) 716static 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
738error: 746error:
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
788drop: 795drop:
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
151static const struct neigh_ops arp_direct_ops = { 151static 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
157static const struct neigh_ops arp_broken_ops = { 157static 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
121static const struct neigh_ops ndisc_direct_ops = { 121static 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
127struct neigh_table nd_tbl = { 127struct 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;