diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2015-03-03 18:11:16 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-04 00:23:23 -0500 |
commit | 4fd3d7d9e868ffbdb0e7a67c5c8e9dfdcd846a62 (patch) | |
tree | a6ee61e3ac7571516b693c2465c6309a59cd0a08 /net/core | |
parent | 60395a20ffd74166ea373ea91418d6f98fa7fdfb (diff) |
neigh: Add helper function neigh_xmit
For MPLS I am building the code so that either the neighbour mac
address can be specified or we can have a next hop in ipv4 or ipv6.
The kind of next hop we have is indicated by the neighbour table
pointer. A neighbour table pointer of NULL is a link layer address.
A non-NULL neighbour table pointer indicates which neighbour table and
thus which address family the next hop address is in that we need to
look up.
The code either sends a packet directly or looks up the appropriate
neighbour table entry and sends the packet.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/neighbour.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index fe3c6eac5805..cffaf00561e7 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -2391,6 +2391,40 @@ void __neigh_for_each_release(struct neigh_table *tbl, | |||
2391 | } | 2391 | } |
2392 | EXPORT_SYMBOL(__neigh_for_each_release); | 2392 | EXPORT_SYMBOL(__neigh_for_each_release); |
2393 | 2393 | ||
2394 | int neigh_xmit(int family, struct net_device *dev, | ||
2395 | const void *addr, struct sk_buff *skb) | ||
2396 | { | ||
2397 | int err; | ||
2398 | if (family == AF_PACKET) { | ||
2399 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | ||
2400 | addr, NULL, skb->len); | ||
2401 | if (err < 0) | ||
2402 | goto out_kfree_skb; | ||
2403 | err = dev_queue_xmit(skb); | ||
2404 | } else { | ||
2405 | struct neigh_table *tbl; | ||
2406 | struct neighbour *neigh; | ||
2407 | |||
2408 | err = -ENETDOWN; | ||
2409 | tbl = neigh_find_table(family); | ||
2410 | if (!tbl) | ||
2411 | goto out; | ||
2412 | neigh = __neigh_lookup_noref(tbl, addr, dev); | ||
2413 | if (!neigh) | ||
2414 | neigh = __neigh_create(tbl, addr, dev, false); | ||
2415 | err = PTR_ERR(neigh); | ||
2416 | if (IS_ERR(neigh)) | ||
2417 | goto out_kfree_skb; | ||
2418 | err = neigh->output(neigh, skb); | ||
2419 | } | ||
2420 | out: | ||
2421 | return err; | ||
2422 | out_kfree_skb: | ||
2423 | kfree_skb(skb); | ||
2424 | goto out; | ||
2425 | } | ||
2426 | EXPORT_SYMBOL(neigh_xmit); | ||
2427 | |||
2394 | #ifdef CONFIG_PROC_FS | 2428 | #ifdef CONFIG_PROC_FS |
2395 | 2429 | ||
2396 | static struct neighbour *neigh_get_first(struct seq_file *seq) | 2430 | static struct neighbour *neigh_get_first(struct seq_file *seq) |