Commit 8f40b161 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parent 69ecca86
...@@ -109,7 +109,7 @@ struct neighbour { ...@@ -109,7 +109,7 @@ struct neighbour {
seqlock_t ha_lock; seqlock_t ha_lock;
unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
struct hh_cache hh; struct hh_cache hh;
int (*output)(struct sk_buff *skb); int (*output)(struct neighbour *, struct sk_buff *);
const struct neigh_ops *ops; const struct neigh_ops *ops;
struct rcu_head rcu; struct rcu_head rcu;
struct net_device *dev; struct net_device *dev;
...@@ -118,10 +118,10 @@ struct neighbour { ...@@ -118,10 +118,10 @@ struct neighbour {
struct neigh_ops { struct neigh_ops {
int family; int family;
void (*solicit)(struct neighbour *, struct sk_buff*); void (*solicit)(struct neighbour *, struct sk_buff *);
void (*error_report)(struct neighbour *, struct sk_buff*); void (*error_report)(struct neighbour *, struct sk_buff *);
int (*output)(struct sk_buff*); int (*output)(struct neighbour *, struct sk_buff *);
int (*connected_output)(struct sk_buff*); int (*connected_output)(struct neighbour *, struct sk_buff *);
}; };
struct pneigh_entry { struct pneigh_entry {
...@@ -203,9 +203,10 @@ extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, ...@@ -203,9 +203,10 @@ extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
u32 flags); u32 flags);
extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); extern void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev); extern int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
extern int neigh_resolve_output(struct sk_buff *skb); extern int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
extern int neigh_connected_output(struct sk_buff *skb); extern int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb);
extern int neigh_compat_output(struct sk_buff *skb); extern int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb);
extern int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb);
extern struct neighbour *neigh_event_ns(struct neigh_table *tbl, extern struct neighbour *neigh_event_ns(struct neigh_table *tbl,
u8 *lladdr, void *saddr, u8 *lladdr, void *saddr,
struct net_device *dev); struct net_device *dev);
...@@ -348,7 +349,7 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb) ...@@ -348,7 +349,7 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb)
if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
return neigh_hh_output(hh, skb); return neigh_hh_output(hh, skb);
else else
return n->output(skb); return n->output(n, skb);
} }
static inline struct neighbour * static inline struct neighbour *
......
...@@ -271,8 +271,8 @@ static const struct neigh_ops clip_neigh_ops = { ...@@ -271,8 +271,8 @@ static const struct neigh_ops clip_neigh_ops = {
.family = AF_INET, .family = AF_INET,
.solicit = clip_neigh_solicit, .solicit = clip_neigh_solicit,
.error_report = clip_neigh_error, .error_report = clip_neigh_error,
.output = dev_queue_xmit, .output = neigh_direct_output,
.connected_output = dev_queue_xmit, .connected_output = neigh_direct_output,
}; };
static int clip_constructor(struct neighbour *neigh) static int clip_constructor(struct neighbour *neigh)
......
...@@ -355,14 +355,14 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) ...@@ -355,14 +355,14 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
neigh_hh_bridge(&neigh->hh, skb); neigh_hh_bridge(&neigh->hh, skb);
skb->dev = nf_bridge->physindev; skb->dev = nf_bridge->physindev;
return br_handle_frame_finish(skb); return br_handle_frame_finish(skb);
} else if (dst->neighbour) { } else {
/* the neighbour function below overwrites the complete /* the neighbour function below overwrites the complete
* MAC header, so we save the Ethernet source address and * MAC header, so we save the Ethernet source address and
* protocol number. */ * protocol number. */
skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN);
/* tell br_dev_xmit to continue with forwarding */ /* tell br_dev_xmit to continue with forwarding */
nf_bridge->mask |= BRNF_BRIDGED_DNAT; nf_bridge->mask |= BRNF_BRIDGED_DNAT;
return dst->neighbour->output(skb); return neigh->output(neigh, skb);
} }
free_skb: free_skb:
kfree_skb(skb); kfree_skb(skb);
......
...@@ -98,7 +98,7 @@ static const struct file_operations neigh_stat_seq_fops; ...@@ -98,7 +98,7 @@ static const struct file_operations neigh_stat_seq_fops;
static DEFINE_RWLOCK(neigh_tbl_lock); static DEFINE_RWLOCK(neigh_tbl_lock);
static int neigh_blackhole(struct sk_buff *skb) static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
{ {
kfree_skb(skb); kfree_skb(skb);
return -ENETDOWN; return -ENETDOWN;
...@@ -1158,7 +1158,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, ...@@ -1158,7 +1158,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
/* On shaper/eql skb->dst->neighbour != neigh :( */ /* On shaper/eql skb->dst->neighbour != neigh :( */
if (skb_dst(skb) && skb_dst(skb)->neighbour) if (skb_dst(skb) && skb_dst(skb)->neighbour)
n1 = skb_dst(skb)->neighbour; n1 = skb_dst(skb)->neighbour;
n1->output(skb); n1->output(n1, skb);
write_lock_bh(&neigh->lock); write_lock_bh(&neigh->lock);
} }
skb_queue_purge(&neigh->arp_queue); skb_queue_purge(&neigh->arp_queue);
...@@ -1214,7 +1214,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst) ...@@ -1214,7 +1214,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
* but resolution is not made yet. * but resolution is not made yet.
*/ */
int neigh_compat_output(struct sk_buff *skb) int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
{ {
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
...@@ -1231,13 +1231,12 @@ EXPORT_SYMBOL(neigh_compat_output); ...@@ -1231,13 +1231,12 @@ EXPORT_SYMBOL(neigh_compat_output);
/* Slow and careful. */ /* Slow and careful. */
int neigh_resolve_output(struct sk_buff *skb) int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
{ {
struct dst_entry *dst = skb_dst(skb); struct dst_entry *dst = skb_dst(skb);
struct neighbour *neigh;
int rc = 0; int rc = 0;
if (!dst || !(neigh = dst->neighbour)) if (!dst)
goto discard; goto discard;
__skb_pull(skb, skb_network_offset(skb)); __skb_pull(skb, skb_network_offset(skb));
...@@ -1265,7 +1264,7 @@ int neigh_resolve_output(struct sk_buff *skb) ...@@ -1265,7 +1264,7 @@ int neigh_resolve_output(struct sk_buff *skb)
return rc; return rc;
discard: discard:
NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n", NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n",
dst, dst ? dst->neighbour : NULL); dst, neigh);
out_kfree_skb: out_kfree_skb:
rc = -EINVAL; rc = -EINVAL;
kfree_skb(skb); kfree_skb(skb);
...@@ -1275,13 +1274,11 @@ EXPORT_SYMBOL(neigh_resolve_output); ...@@ -1275,13 +1274,11 @@ EXPORT_SYMBOL(neigh_resolve_output);
/* As fast as possible without hh cache */ /* As fast as possible without hh cache */
int neigh_connected_output(struct sk_buff *skb) int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
{ {
int err;
struct dst_entry *dst = skb_dst(skb);
struct neighbour *neigh = dst->neighbour;
struct net_device *dev = neigh->dev; struct net_device *dev = neigh->dev;
unsigned int seq; unsigned int seq;
int err;
__skb_pull(skb, skb_network_offset(skb)); __skb_pull(skb, skb_network_offset(skb));
...@@ -1301,6 +1298,12 @@ int neigh_connected_output(struct sk_buff *skb) ...@@ -1301,6 +1298,12 @@ int neigh_connected_output(struct sk_buff *skb)
} }
EXPORT_SYMBOL(neigh_connected_output); EXPORT_SYMBOL(neigh_connected_output);
int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
{
return dev_queue_xmit(skb);
}
EXPORT_SYMBOL(neigh_direct_output);
static void neigh_proxy_process(unsigned long arg) static void neigh_proxy_process(unsigned long arg)
{ {
struct neigh_table *tbl = (struct neigh_table *)arg; struct neigh_table *tbl = (struct neigh_table *)arg;
......
...@@ -51,9 +51,9 @@ ...@@ -51,9 +51,9 @@
static int dn_neigh_construct(struct neighbour *); static int dn_neigh_construct(struct neighbour *);
static void dn_long_error_report(struct neighbour *, struct sk_buff *); static void dn_long_error_report(struct neighbour *, struct sk_buff *);
static void dn_short_error_report(struct neighbour *, struct sk_buff *); static void dn_short_error_report(struct neighbour *, struct sk_buff *);
static int dn_long_output(struct sk_buff *); static int dn_long_output(struct neighbour *, struct sk_buff *);
static int dn_short_output(struct sk_buff *); static int dn_short_output(struct neighbour *, struct sk_buff *);
static int dn_phase3_output(struct sk_buff *); static int dn_phase3_output(struct neighbour *, struct sk_buff *);
/* /*
...@@ -218,10 +218,8 @@ static int dn_neigh_output_packet(struct sk_buff *skb) ...@@ -218,10 +218,8 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
return -EINVAL; return -EINVAL;
} }
static int dn_long_output(struct sk_buff *skb) static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
{ {
struct dst_entry *dst = skb_dst(skb);
struct neighbour *neigh = dst->neighbour;
struct net_device *dev = neigh->dev; struct net_device *dev = neigh->dev;
int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3; int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
unsigned char *data; unsigned char *data;
...@@ -265,10 +263,8 @@ static int dn_long_output(struct sk_buff *skb) ...@@ -265,10 +263,8 @@ static int dn_long_output(struct sk_buff *skb)
neigh->dev, dn_neigh_output_packet); neigh->dev, dn_neigh_output_packet);
} }
static int dn_short_output(struct sk_buff *skb) static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
{ {
struct dst_entry *dst = skb_dst(skb);
struct neighbour *neigh = dst->neighbour;
struct net_device *dev = neigh->dev; struct net_device *dev = neigh->dev;
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp; struct dn_short_packet *sp;
...@@ -309,10 +305,8 @@ static int dn_short_output(struct sk_buff *skb) ...@@ -309,10 +305,8 @@ static int dn_short_output(struct sk_buff *skb)
* Phase 3 output is the same is short output, execpt that * Phase 3 output is the same is short output, execpt that
* it clears the area bits before transmission. * it clears the area bits before transmission.
*/ */
static int dn_phase3_output(struct sk_buff *skb) static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb)
{ {
struct dst_entry *dst = skb_dst(skb);
struct neighbour *neigh = dst->neighbour;
struct net_device *dev = neigh->dev; struct net_device *dev = neigh->dev;
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2; int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp; struct dn_short_packet *sp;
......
...@@ -705,6 +705,14 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type ...@@ -705,6 +705,14 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
return NET_RX_DROP; return NET_RX_DROP;
} }
static int dn_to_neigh_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct neighbour *n = dst->neighbour;
return n->output(n, skb);
}
static int dn_output(struct sk_buff *skb) static int dn_output(struct sk_buff *skb)
{ {
struct dst_entry *dst = skb_dst(skb); struct dst_entry *dst = skb_dst(skb);
...@@ -733,7 +741,7 @@ static int dn_output(struct sk_buff *skb) ...@@ -733,7 +741,7 @@ static int dn_output(struct sk_buff *skb)
cb->hops = 0; cb->hops = 0;
return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, skb, NULL, dev, return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, skb, NULL, dev,
neigh->output); dn_to_neigh_output);
error: error:
if (net_ratelimit()) if (net_ratelimit())
...@@ -750,7 +758,6 @@ static int dn_forward(struct sk_buff *skb) ...@@ -750,7 +758,6 @@ static int dn_forward(struct sk_buff *skb)
struct dst_entry *dst = skb_dst(skb); struct dst_entry *dst = skb_dst(skb);
struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr); struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr);
struct dn_route *rt; struct dn_route *rt;
struct neighbour *neigh = dst->neighbour;
int header_len; int header_len;
#ifdef CONFIG_NETFILTER #ifdef CONFIG_NETFILTER
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
...@@ -783,7 +790,7 @@ static int dn_forward(struct sk_buff *skb) ...@@ -783,7 +790,7 @@ static int dn_forward(struct sk_buff *skb)
cb->rt_flags |= DN_RT_F_IE; cb->rt_flags |= DN_RT_F_IE;
return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, skb, dev, skb->dev, return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, skb, dev, skb->dev,
neigh->output); dn_to_neigh_output);
drop: drop:
kfree_skb(skb); kfree_skb(skb);
......
...@@ -150,8 +150,8 @@ static const struct neigh_ops arp_hh_ops = { ...@@ -150,8 +150,8 @@ static const struct neigh_ops arp_hh_ops = {
static const struct neigh_ops arp_direct_ops = { static const struct neigh_ops arp_direct_ops = {
.family = AF_INET, .family = AF_INET,
.output = dev_queue_xmit, .output = neigh_direct_output,
.connected_output = dev_queue_xmit, .connected_output = neigh_direct_output,
}; };
static const struct neigh_ops arp_broken_ops = { static const struct neigh_ops arp_broken_ops = {
...@@ -250,7 +250,7 @@ static int arp_constructor(struct neighbour *neigh) ...@@ -250,7 +250,7 @@ static int arp_constructor(struct neighbour *neigh)
if (!dev->header_ops) { if (!dev->header_ops) {
neigh->nud_state = NUD_NOARP; neigh->nud_state = NUD_NOARP;
neigh->ops = &arp_direct_ops; neigh->ops = &arp_direct_ops;
neigh->output = dev_queue_xmit; neigh->output = neigh_direct_output;
} else { } else {
/* Good devices (checked by reading texts, but only Ethernet is /* Good devices (checked by reading texts, but only Ethernet is
tested) tested)
......
...@@ -120,8 +120,8 @@ static const struct neigh_ops ndisc_hh_ops = { ...@@ -120,8 +120,8 @@ static const struct neigh_ops ndisc_hh_ops = {
static const struct neigh_ops ndisc_direct_ops = { static const struct neigh_ops ndisc_direct_ops = {
.family = AF_INET6, .family = AF_INET6,
.output = dev_queue_xmit, .output = neigh_direct_output,
.connected_output = dev_queue_xmit, .connected_output = neigh_direct_output,
}; };
struct neigh_table nd_tbl = { struct neigh_table nd_tbl = {
...@@ -386,7 +386,7 @@ static int ndisc_constructor(struct neighbour *neigh) ...@@ -386,7 +386,7 @@ static int ndisc_constructor(struct neighbour *neigh)
if (!dev->header_ops) { if (!dev->header_ops) {
neigh->nud_state = NUD_NOARP; neigh->nud_state = NUD_NOARP;
neigh->ops = &ndisc_direct_ops; neigh->ops = &ndisc_direct_ops;
neigh->output = dev_queue_xmit; neigh->output = neigh_direct_output;
} else { } else {
if (is_multicast) { if (is_multicast) {
neigh->nud_state = NUD_NOARP; neigh->nud_state = NUD_NOARP;
......
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