diff options
author | Patrick McHardy <kaber@trash.net> | 2008-07-08 14:23:36 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-08 14:23:36 +0400 |
commit | 7750f403cbe56971336d575b354365190b4e3227 (patch) | |
tree | bc8a65b0dd0d5cc3faac943f7e3df0c6dfedeaf6 /net/8021q | |
parent | 75b8846acd11ad3fc736d4df3413fe946bbf367c (diff) | |
download | linux-7750f403cbe56971336d575b354365190b4e3227.tar.xz |
vlan: uninline __vlan_hwaccel_rx
The function is huge and included at least once in every VLAN acceleration
capable driver. Uninline it; to avoid having drivers depend on the VLAN
module, the function is always built in statically when VLAN is enabled.
With all VLAN acceleration capable drivers that build on x86_64 enabled,
this results in:
text data bss dec hex filename
6515227 854044 343968 7713239 75b1d7 vmlinux.inlined
6505637 854044 343968 7703649 758c61 vmlinux.uninlined
----------------------------------------------------------
-9590
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/8021q')
-rw-r--r-- | net/8021q/Makefile | 9 | ||||
-rw-r--r-- | net/8021q/vlan.h | 8 | ||||
-rw-r--r-- | net/8021q/vlan_core.c | 48 |
3 files changed, 61 insertions, 4 deletions
diff --git a/net/8021q/Makefile b/net/8021q/Makefile index 3006e9ed7b08..9f4f174ead1c 100644 --- a/net/8021q/Makefile +++ b/net/8021q/Makefile @@ -1,9 +1,10 @@ # # Makefile for the Linux VLAN layer. # +obj-$(subst m,y,$(CONFIG_VLAN_8021Q)) += vlan_core.o +obj-$(CONFIG_VLAN_8021Q) += 8021q.o -obj-$(CONFIG_VLAN_8021Q) += 8021q.o +8021q-y := vlan.o vlan_dev.o vlan_netlink.o +8021q-$(CONFIG_VLAN_8021Q_GVRP) += vlan_gvrp.o +8021q-$(CONFIG_PROC_FS) += vlanproc.o -8021q-y := vlan.o vlan_dev.o vlan_netlink.o -8021q-$(CONFIG_VLAN_8021Q_GVRP) += vlan_gvrp.o -8021q-$(CONFIG_PROC_FS) += vlanproc.o diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 097b2e04c928..7cc1a97c42fc 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -37,6 +37,14 @@ void vlan_setup(struct net_device *dev); int register_vlan_dev(struct net_device *dev); void unregister_vlan_dev(struct net_device *dev); +static inline u32 vlan_get_ingress_priority(struct net_device *dev, + unsigned short vlan_tag) +{ + struct vlan_dev_info *vip = vlan_dev_info(dev); + + return vip->ingress_priority_map[(vlan_tag >> 13) & 0x7]; +} + #ifdef CONFIG_VLAN_8021Q_GVRP extern int vlan_gvrp_request_join(const struct net_device *dev); extern void vlan_gvrp_request_leave(const struct net_device *dev); diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c new file mode 100644 index 000000000000..85c94edb000f --- /dev/null +++ b/net/8021q/vlan_core.c @@ -0,0 +1,48 @@ +#include <linux/skbuff.h> +#include <linux/netdevice.h> +#include <linux/if_vlan.h> +#include "vlan.h" + +/* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ +int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, + unsigned short vlan_tag, int polling) +{ + struct net_device_stats *stats; + + if (skb_bond_should_drop(skb)) { + dev_kfree_skb_any(skb); + return NET_RX_DROP; + } + + skb->dev = vlan_group_get_device(grp, vlan_tag & VLAN_VID_MASK); + if (skb->dev == NULL) { + dev_kfree_skb_any(skb); + /* Not NET_RX_DROP, this is not being dropped + * due to congestion. */ + return NET_RX_SUCCESS; + } + skb->dev->last_rx = jiffies; + + stats = &skb->dev->stats; + stats->rx_packets++; + stats->rx_bytes += skb->len; + + skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tag); + switch (skb->pkt_type) { + case PACKET_BROADCAST: + break; + case PACKET_MULTICAST: + stats->multicast++; + break; + case PACKET_OTHERHOST: + /* Our lower layer thinks this is not local, let's make sure. + * This allows the VLAN to have a different MAC than the + * underlying device, and still route correctly. */ + if (!compare_ether_addr(eth_hdr(skb)->h_dest, + skb->dev->dev_addr)) + skb->pkt_type = PACKET_HOST; + break; + }; + return (polling ? netif_receive_skb(skb) : netif_rx(skb)); +} +EXPORT_SYMBOL(__vlan_hwaccel_rx); |