Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -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;
@@ -120,8 +120,8 @@ 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*);
	int			(*output)(struct neighbour *, struct sk_buff *);
	int			(*connected_output)(struct neighbour *, struct sk_buff *);
};

struct pneigh_entry {
@@ -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);
@@ -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 *
+2 −2
Original line number Diff line number Diff line
@@ -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)
+2 −2
Original line number Diff line number Diff line
@@ -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);
+14 −11
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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;

@@ -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));
@@ -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);
@@ -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));

@@ -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;
+6 −12
Original line number Diff line number Diff line
@@ -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 *);


/*
@@ -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;
@@ -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;
@@ -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;
Loading