diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2015-03-07 17:25:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-08 19:30:06 -0400 |
commit | b79bda3d38ae67940f1740f7e015f284eb551680 (patch) | |
tree | fb927e9867e7a013c4ce142a993458d15ee20cef | |
parent | 7d5f41f276b376d567e919530f8b5fd70be25426 (diff) |
neigh: Use neigh table index for neigh_packet_xmit
Remove a little bit of unnecessary work when transmitting a packet with
neigh_packet_xmit. Use the neighbour table index not the address family
as a parameter.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/neighbour.h | 1 | ||||
-rw-r--r-- | net/core/neighbour.c | 22 | ||||
-rw-r--r-- | net/mpls/af_mpls.c | 35 |
3 files changed, 34 insertions, 24 deletions
diff --git a/include/net/neighbour.h b/include/net/neighbour.h index afb8237b0a8c..d48b8ec8b5f4 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h | |||
@@ -226,6 +226,7 @@ enum { | |||
226 | NEIGH_ND_TABLE = 1, | 226 | NEIGH_ND_TABLE = 1, |
227 | NEIGH_DN_TABLE = 2, | 227 | NEIGH_DN_TABLE = 2, |
228 | NEIGH_NR_TABLES, | 228 | NEIGH_NR_TABLES, |
229 | NEIGH_LINK_TABLE = NEIGH_NR_TABLES /* Pseudo table for neigh_xmit */ | ||
229 | }; | 230 | }; |
230 | 231 | ||
231 | static inline int neigh_parms_family(struct neigh_parms *p) | 232 | static inline int neigh_parms_family(struct neigh_parms *p) |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index cffaf00561e7..ad07990e943d 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -2391,22 +2391,15 @@ 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, | 2394 | int neigh_xmit(int index, struct net_device *dev, |
2395 | const void *addr, struct sk_buff *skb) | 2395 | const void *addr, struct sk_buff *skb) |
2396 | { | 2396 | { |
2397 | int err; | 2397 | int err = -EAFNOSUPPORT; |
2398 | if (family == AF_PACKET) { | 2398 | if (likely(index < NEIGH_NR_TABLES)) { |
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; | 2399 | struct neigh_table *tbl; |
2406 | struct neighbour *neigh; | 2400 | struct neighbour *neigh; |
2407 | 2401 | ||
2408 | err = -ENETDOWN; | 2402 | tbl = neigh_tables[index]; |
2409 | tbl = neigh_find_table(family); | ||
2410 | if (!tbl) | 2403 | if (!tbl) |
2411 | goto out; | 2404 | goto out; |
2412 | neigh = __neigh_lookup_noref(tbl, addr, dev); | 2405 | neigh = __neigh_lookup_noref(tbl, addr, dev); |
@@ -2417,6 +2410,13 @@ int neigh_xmit(int family, struct net_device *dev, | |||
2417 | goto out_kfree_skb; | 2410 | goto out_kfree_skb; |
2418 | err = neigh->output(neigh, skb); | 2411 | err = neigh->output(neigh, skb); |
2419 | } | 2412 | } |
2413 | else if (index == NEIGH_LINK_TABLE) { | ||
2414 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | ||
2415 | addr, NULL, skb->len); | ||
2416 | if (err < 0) | ||
2417 | goto out_kfree_skb; | ||
2418 | err = dev_queue_xmit(skb); | ||
2419 | } | ||
2420 | out: | 2420 | out: |
2421 | return err; | 2421 | return err; |
2422 | out_kfree_skb: | 2422 | out_kfree_skb: |
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index e120074157de..0ad8f7141be2 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
@@ -28,9 +28,9 @@ struct mpls_route { /* next hop label forwarding entry */ | |||
28 | struct rcu_head rt_rcu; | 28 | struct rcu_head rt_rcu; |
29 | u32 rt_label[MAX_NEW_LABELS]; | 29 | u32 rt_label[MAX_NEW_LABELS]; |
30 | u8 rt_protocol; /* routing protocol that set this entry */ | 30 | u8 rt_protocol; /* routing protocol that set this entry */ |
31 | u8 rt_labels:2, | 31 | u8 rt_labels; |
32 | rt_via_alen:6; | 32 | u8 rt_via_alen; |
33 | unsigned short rt_via_family; | 33 | u8 rt_via_table; |
34 | u8 rt_via[0]; | 34 | u8 rt_via[0]; |
35 | }; | 35 | }; |
36 | 36 | ||
@@ -201,7 +201,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev, | |||
201 | } | 201 | } |
202 | } | 202 | } |
203 | 203 | ||
204 | err = neigh_xmit(rt->rt_via_family, out_dev, rt->rt_via, skb); | 204 | err = neigh_xmit(rt->rt_via_table, out_dev, rt->rt_via, skb); |
205 | if (err) | 205 | if (err) |
206 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", | 206 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", |
207 | __func__, err); | 207 | __func__, err); |
@@ -225,7 +225,7 @@ static const struct nla_policy rtm_mpls_policy[RTA_MAX+1] = { | |||
225 | struct mpls_route_config { | 225 | struct mpls_route_config { |
226 | u32 rc_protocol; | 226 | u32 rc_protocol; |
227 | u32 rc_ifindex; | 227 | u32 rc_ifindex; |
228 | u16 rc_via_family; | 228 | u16 rc_via_table; |
229 | u16 rc_via_alen; | 229 | u16 rc_via_alen; |
230 | u8 rc_via[MAX_VIA_ALEN]; | 230 | u8 rc_via[MAX_VIA_ALEN]; |
231 | u32 rc_label; | 231 | u32 rc_label; |
@@ -343,7 +343,7 @@ static int mpls_route_add(struct mpls_route_config *cfg) | |||
343 | goto errout; | 343 | goto errout; |
344 | 344 | ||
345 | err = -EINVAL; | 345 | err = -EINVAL; |
346 | if ((cfg->rc_via_family == AF_PACKET) && | 346 | if ((cfg->rc_via_table == NEIGH_LINK_TABLE) && |
347 | (dev->addr_len != cfg->rc_via_alen)) | 347 | (dev->addr_len != cfg->rc_via_alen)) |
348 | goto errout; | 348 | goto errout; |
349 | 349 | ||
@@ -376,7 +376,7 @@ static int mpls_route_add(struct mpls_route_config *cfg) | |||
376 | rt->rt_label[i] = cfg->rc_output_label[i]; | 376 | rt->rt_label[i] = cfg->rc_output_label[i]; |
377 | rt->rt_protocol = cfg->rc_protocol; | 377 | rt->rt_protocol = cfg->rc_protocol; |
378 | RCU_INIT_POINTER(rt->rt_dev, dev); | 378 | RCU_INIT_POINTER(rt->rt_dev, dev); |
379 | rt->rt_via_family = cfg->rc_via_family; | 379 | rt->rt_via_table = cfg->rc_via_table; |
380 | memcpy(rt->rt_via, cfg->rc_via, cfg->rc_via_alen); | 380 | memcpy(rt->rt_via, cfg->rc_via, cfg->rc_via_alen); |
381 | 381 | ||
382 | mpls_route_update(net, index, NULL, rt, &cfg->rc_nlinfo); | 382 | mpls_route_update(net, index, NULL, rt, &cfg->rc_nlinfo); |
@@ -448,15 +448,22 @@ static struct notifier_block mpls_dev_notifier = { | |||
448 | }; | 448 | }; |
449 | 449 | ||
450 | static int nla_put_via(struct sk_buff *skb, | 450 | static int nla_put_via(struct sk_buff *skb, |
451 | u16 family, const void *addr, int alen) | 451 | u8 table, const void *addr, int alen) |
452 | { | 452 | { |
453 | static const int table_to_family[NEIGH_NR_TABLES + 1] = { | ||
454 | AF_INET, AF_INET6, AF_DECnet, AF_PACKET, | ||
455 | }; | ||
453 | struct nlattr *nla; | 456 | struct nlattr *nla; |
454 | struct rtvia *via; | 457 | struct rtvia *via; |
458 | int family = AF_UNSPEC; | ||
455 | 459 | ||
456 | nla = nla_reserve(skb, RTA_VIA, alen + 2); | 460 | nla = nla_reserve(skb, RTA_VIA, alen + 2); |
457 | if (!nla) | 461 | if (!nla) |
458 | return -EMSGSIZE; | 462 | return -EMSGSIZE; |
459 | 463 | ||
464 | if (table <= NEIGH_NR_TABLES) | ||
465 | family = table_to_family[table]; | ||
466 | |||
460 | via = nla_data(nla); | 467 | via = nla_data(nla); |
461 | via->rtvia_family = family; | 468 | via->rtvia_family = family; |
462 | memcpy(via->rtvia_addr, addr, alen); | 469 | memcpy(via->rtvia_addr, addr, alen); |
@@ -599,21 +606,23 @@ static int rtm_to_route_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
599 | struct rtvia *via = nla_data(nla); | 606 | struct rtvia *via = nla_data(nla); |
600 | if (nla_len(nla) < offsetof(struct rtvia, rtvia_addr)) | 607 | if (nla_len(nla) < offsetof(struct rtvia, rtvia_addr)) |
601 | goto errout; | 608 | goto errout; |
602 | cfg->rc_via_family = via->rtvia_family; | ||
603 | cfg->rc_via_alen = nla_len(nla) - | 609 | cfg->rc_via_alen = nla_len(nla) - |
604 | offsetof(struct rtvia, rtvia_addr); | 610 | offsetof(struct rtvia, rtvia_addr); |
605 | if (cfg->rc_via_alen > MAX_VIA_ALEN) | 611 | if (cfg->rc_via_alen > MAX_VIA_ALEN) |
606 | goto errout; | 612 | goto errout; |
607 | 613 | ||
608 | /* Validate the address family */ | 614 | /* Validate the address family */ |
609 | switch(cfg->rc_via_family) { | 615 | switch(via->rtvia_family) { |
610 | case AF_PACKET: | 616 | case AF_PACKET: |
617 | cfg->rc_via_table = NEIGH_LINK_TABLE; | ||
611 | break; | 618 | break; |
612 | case AF_INET: | 619 | case AF_INET: |
620 | cfg->rc_via_table = NEIGH_ARP_TABLE; | ||
613 | if (cfg->rc_via_alen != 4) | 621 | if (cfg->rc_via_alen != 4) |
614 | goto errout; | 622 | goto errout; |
615 | break; | 623 | break; |
616 | case AF_INET6: | 624 | case AF_INET6: |
625 | cfg->rc_via_table = NEIGH_ND_TABLE; | ||
617 | if (cfg->rc_via_alen != 16) | 626 | if (cfg->rc_via_alen != 16) |
618 | goto errout; | 627 | goto errout; |
619 | break; | 628 | break; |
@@ -686,7 +695,7 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event, | |||
686 | if (rt->rt_labels && | 695 | if (rt->rt_labels && |
687 | nla_put_labels(skb, RTA_NEWDST, rt->rt_labels, rt->rt_label)) | 696 | nla_put_labels(skb, RTA_NEWDST, rt->rt_labels, rt->rt_label)) |
688 | goto nla_put_failure; | 697 | goto nla_put_failure; |
689 | if (nla_put_via(skb, rt->rt_via_family, rt->rt_via, rt->rt_via_alen)) | 698 | if (nla_put_via(skb, rt->rt_via_table, rt->rt_via, rt->rt_via_alen)) |
690 | goto nla_put_failure; | 699 | goto nla_put_failure; |
691 | dev = rtnl_dereference(rt->rt_dev); | 700 | dev = rtnl_dereference(rt->rt_dev); |
692 | if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex)) | 701 | if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex)) |
@@ -799,7 +808,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
799 | goto nort0; | 808 | goto nort0; |
800 | RCU_INIT_POINTER(rt0->rt_dev, lo); | 809 | RCU_INIT_POINTER(rt0->rt_dev, lo); |
801 | rt0->rt_protocol = RTPROT_KERNEL; | 810 | rt0->rt_protocol = RTPROT_KERNEL; |
802 | rt0->rt_via_family = AF_PACKET; | 811 | rt0->rt_via_table = NEIGH_LINK_TABLE; |
803 | memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len); | 812 | memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len); |
804 | } | 813 | } |
805 | if (limit > LABEL_IPV6_EXPLICIT_NULL) { | 814 | if (limit > LABEL_IPV6_EXPLICIT_NULL) { |
@@ -809,7 +818,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
809 | goto nort2; | 818 | goto nort2; |
810 | RCU_INIT_POINTER(rt2->rt_dev, lo); | 819 | RCU_INIT_POINTER(rt2->rt_dev, lo); |
811 | rt2->rt_protocol = RTPROT_KERNEL; | 820 | rt2->rt_protocol = RTPROT_KERNEL; |
812 | rt2->rt_via_family = AF_PACKET; | 821 | rt2->rt_via_table = NEIGH_LINK_TABLE; |
813 | memcpy(rt2->rt_via, lo->dev_addr, lo->addr_len); | 822 | memcpy(rt2->rt_via, lo->dev_addr, lo->addr_len); |
814 | } | 823 | } |
815 | 824 | ||