Skip to content

Commit

Permalink
neigh: Pass neighbour entry to output ops.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
davem330 committed Jul 18, 2011
1 parent 69ecca8 commit 8f40b16
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 45 deletions.
19 changes: 10 additions & 9 deletions include/net/neighbour.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct neighbour {
seqlock_t ha_lock;
unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
struct hh_cache hh;
int (*output)(struct sk_buff *skb);
int (*output)(struct neighbour *, struct sk_buff *);
const struct neigh_ops *ops;
struct rcu_head rcu;
struct net_device *dev;
Expand All @@ -118,10 +118,10 @@ struct neighbour {

struct neigh_ops {
int family;
void (*solicit)(struct neighbour *, struct sk_buff*);
void (*error_report)(struct neighbour *, struct sk_buff*);
int (*output)(struct sk_buff*);
int (*connected_output)(struct sk_buff*);
void (*solicit)(struct neighbour *, struct sk_buff *);
void (*error_report)(struct neighbour *, struct sk_buff *);
int (*output)(struct neighbour *, struct sk_buff *);
int (*connected_output)(struct neighbour *, struct sk_buff *);
};

struct pneigh_entry {
Expand Down Expand Up @@ -203,9 +203,10 @@ extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
u32 flags);
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_resolve_output(struct sk_buff *skb);
extern int neigh_connected_output(struct sk_buff *skb);
extern int neigh_compat_output(struct sk_buff *skb);
extern int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
extern int neigh_connected_output(struct neighbour *neigh, 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,
u8 *lladdr, void *saddr,
struct net_device *dev);
Expand Down Expand Up @@ -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)
return neigh_hh_output(hh, skb);
else
return n->output(skb);
return n->output(n, skb);
}

static inline struct neighbour *
Expand Down
4 changes: 2 additions & 2 deletions net/atm/clip.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ static const struct neigh_ops clip_neigh_ops = {
.family = AF_INET,
.solicit = clip_neigh_solicit,
.error_report = clip_neigh_error,
.output = dev_queue_xmit,
.connected_output = dev_queue_xmit,
.output = neigh_direct_output,
.connected_output = neigh_direct_output,
};

static int clip_constructor(struct neighbour *neigh)
Expand Down
4 changes: 2 additions & 2 deletions net/bridge/br_netfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,14 +355,14 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
neigh_hh_bridge(&neigh->hh, skb);
skb->dev = nf_bridge->physindev;
return br_handle_frame_finish(skb);
} else if (dst->neighbour) {
} else {
/* the neighbour function below overwrites the complete
* MAC header, so we save the Ethernet source address and
* protocol number. */
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 */
nf_bridge->mask |= BRNF_BRIDGED_DNAT;
return dst->neighbour->output(skb);
return neigh->output(neigh, skb);
}
free_skb:
kfree_skb(skb);
Expand Down
25 changes: 14 additions & 11 deletions net/core/neighbour.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ static const struct file_operations neigh_stat_seq_fops;

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);
return -ENETDOWN;
Expand Down Expand Up @@ -1158,7 +1158,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
/* On shaper/eql skb->dst->neighbour != neigh :( */
if (skb_dst(skb) && skb_dst(skb)->neighbour)
n1 = skb_dst(skb)->neighbour;
n1->output(skb);
n1->output(n1, skb);
write_lock_bh(&neigh->lock);
}
skb_queue_purge(&neigh->arp_queue);
Expand Down Expand Up @@ -1214,7 +1214,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
* 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;

Expand All @@ -1231,13 +1231,12 @@ EXPORT_SYMBOL(neigh_compat_output);

/* 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 neighbour *neigh;
int rc = 0;

if (!dst || !(neigh = dst->neighbour))
if (!dst)
goto discard;

__skb_pull(skb, skb_network_offset(skb));
Expand Down Expand Up @@ -1265,7 +1264,7 @@ int neigh_resolve_output(struct sk_buff *skb)
return rc;
discard:
NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n",
dst, dst ? dst->neighbour : NULL);
dst, neigh);
out_kfree_skb:
rc = -EINVAL;
kfree_skb(skb);
Expand All @@ -1275,13 +1274,11 @@ EXPORT_SYMBOL(neigh_resolve_output);

/* 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;
unsigned int seq;
int err;

__skb_pull(skb, skb_network_offset(skb));

Expand All @@ -1301,6 +1298,12 @@ int neigh_connected_output(struct sk_buff *skb)
}
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)
{
struct neigh_table *tbl = (struct neigh_table *)arg;
Expand Down
18 changes: 6 additions & 12 deletions net/decnet/dn_neigh.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@
static int dn_neigh_construct(struct neighbour *);
static void dn_long_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_short_output(struct sk_buff *);
static int dn_phase3_output(struct sk_buff *);
static int dn_long_output(struct neighbour *, struct sk_buff *);
static int dn_short_output(struct neighbour *, struct sk_buff *);
static int dn_phase3_output(struct neighbour *, struct sk_buff *);


/*
Expand Down Expand Up @@ -218,10 +218,8 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
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;
int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
unsigned char *data;
Expand Down Expand Up @@ -265,10 +263,8 @@ static int dn_long_output(struct sk_buff *skb)
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;
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp;
Expand Down Expand Up @@ -309,10 +305,8 @@ static int dn_short_output(struct sk_buff *skb)
* Phase 3 output is the same is short output, execpt that
* 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;
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp;
Expand Down
13 changes: 10 additions & 3 deletions net/decnet/dn_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,14 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
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)
{
struct dst_entry *dst = skb_dst(skb);
Expand Down Expand Up @@ -733,7 +741,7 @@ static int dn_output(struct sk_buff *skb)
cb->hops = 0;

return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT, skb, NULL, dev,
neigh->output);
dn_to_neigh_output);

error:
if (net_ratelimit())
Expand All @@ -750,7 +758,6 @@ static int dn_forward(struct sk_buff *skb)
struct dst_entry *dst = skb_dst(skb);
struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr);
struct dn_route *rt;
struct neighbour *neigh = dst->neighbour;
int header_len;
#ifdef CONFIG_NETFILTER
struct net_device *dev = skb->dev;
Expand Down Expand Up @@ -783,7 +790,7 @@ static int dn_forward(struct sk_buff *skb)
cb->rt_flags |= DN_RT_F_IE;

return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD, skb, dev, skb->dev,
neigh->output);
dn_to_neigh_output);

drop:
kfree_skb(skb);
Expand Down
6 changes: 3 additions & 3 deletions net/ipv4/arp.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ static const struct neigh_ops arp_hh_ops = {

static const struct neigh_ops arp_direct_ops = {
.family = AF_INET,
.output = dev_queue_xmit,
.connected_output = dev_queue_xmit,
.output = neigh_direct_output,
.connected_output = neigh_direct_output,
};

static const struct neigh_ops arp_broken_ops = {
Expand Down Expand Up @@ -250,7 +250,7 @@ static int arp_constructor(struct neighbour *neigh)
if (!dev->header_ops) {
neigh->nud_state = NUD_NOARP;
neigh->ops = &arp_direct_ops;
neigh->output = dev_queue_xmit;
neigh->output = neigh_direct_output;
} else {
/* Good devices (checked by reading texts, but only Ethernet is
tested)
Expand Down
6 changes: 3 additions & 3 deletions net/ipv6/ndisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ static const struct neigh_ops ndisc_hh_ops = {

static const struct neigh_ops ndisc_direct_ops = {
.family = AF_INET6,
.output = dev_queue_xmit,
.connected_output = dev_queue_xmit,
.output = neigh_direct_output,
.connected_output = neigh_direct_output,
};

struct neigh_table nd_tbl = {
Expand Down Expand Up @@ -386,7 +386,7 @@ static int ndisc_constructor(struct neighbour *neigh)
if (!dev->header_ops) {
neigh->nud_state = NUD_NOARP;
neigh->ops = &ndisc_direct_ops;
neigh->output = dev_queue_xmit;
neigh->output = neigh_direct_output;
} else {
if (is_multicast) {
neigh->nud_state = NUD_NOARP;
Expand Down

0 comments on commit 8f40b16

Please sign in to comment.