aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2010-10-20 09:56:04 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-21 04:26:52 -0400
commit7b9c60903714bf0a19d746b228864bad3497284e (patch)
treec9dd632ea640b1f56634de8a1f029dd88dea2599 /net/core
parenteab6d18d20fc5b5ba04a7e7fcd6f357197870e51 (diff)
vlan: Enable software emulation for vlan accleration.
Currently users of hardware vlan accleration need to know whether the device supports it before generating packets. However, vlan acceleration will soon be available in a more flexible manner so knowing ahead of time becomes much more difficult. This adds a software fallback path for vlan packets on devices without the necessary offloading support, similar to other types of hardware accleration. Signed-off-by: Jesse Gross <jesse@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 4c3ac53e4b16..1bfd96b1fbd4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1694,7 +1694,12 @@ static bool can_checksum_protocol(unsigned long features, __be16 protocol)
1694 1694
1695static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb) 1695static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb)
1696{ 1696{
1697 if (can_checksum_protocol(dev->features, skb->protocol)) 1697 int features = dev->features;
1698
1699 if (vlan_tx_tag_present(skb))
1700 features &= dev->vlan_features;
1701
1702 if (can_checksum_protocol(features, skb->protocol))
1698 return true; 1703 return true;
1699 1704
1700 if (skb->protocol == htons(ETH_P_8021Q)) { 1705 if (skb->protocol == htons(ETH_P_8021Q)) {
@@ -1793,6 +1798,16 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
1793 __be16 type = skb->protocol; 1798 __be16 type = skb->protocol;
1794 int err; 1799 int err;
1795 1800
1801 if (type == htons(ETH_P_8021Q)) {
1802 struct vlan_ethhdr *veh;
1803
1804 if (unlikely(!pskb_may_pull(skb, VLAN_ETH_HLEN)))
1805 return ERR_PTR(-EINVAL);
1806
1807 veh = (struct vlan_ethhdr *)skb->data;
1808 type = veh->h_vlan_encapsulated_proto;
1809 }
1810
1796 skb_reset_mac_header(skb); 1811 skb_reset_mac_header(skb);
1797 skb->mac_len = skb->network_header - skb->mac_header; 1812 skb->mac_len = skb->network_header - skb->mac_header;
1798 __skb_pull(skb, skb->mac_len); 1813 __skb_pull(skb, skb->mac_len);
@@ -1964,9 +1979,14 @@ static inline void skb_orphan_try(struct sk_buff *skb)
1964static inline int skb_needs_linearize(struct sk_buff *skb, 1979static inline int skb_needs_linearize(struct sk_buff *skb,
1965 struct net_device *dev) 1980 struct net_device *dev)
1966{ 1981{
1982 int features = dev->features;
1983
1984 if (skb->protocol == htons(ETH_P_8021Q) || vlan_tx_tag_present(skb))
1985 features &= dev->vlan_features;
1986
1967 return skb_is_nonlinear(skb) && 1987 return skb_is_nonlinear(skb) &&
1968 ((skb_has_frag_list(skb) && !(dev->features & NETIF_F_FRAGLIST)) || 1988 ((skb_has_frag_list(skb) && !(features & NETIF_F_FRAGLIST)) ||
1969 (skb_shinfo(skb)->nr_frags && (!(dev->features & NETIF_F_SG) || 1989 (skb_shinfo(skb)->nr_frags && (!(features & NETIF_F_SG) ||
1970 illegal_highdma(dev, skb)))); 1990 illegal_highdma(dev, skb))));
1971} 1991}
1972 1992
@@ -1989,6 +2009,15 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
1989 2009
1990 skb_orphan_try(skb); 2010 skb_orphan_try(skb);
1991 2011
2012 if (vlan_tx_tag_present(skb) &&
2013 !(dev->features & NETIF_F_HW_VLAN_TX)) {
2014 skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb));
2015 if (unlikely(!skb))
2016 goto out;
2017
2018 skb->vlan_tci = 0;
2019 }
2020
1992 if (netif_needs_gso(dev, skb)) { 2021 if (netif_needs_gso(dev, skb)) {
1993 if (unlikely(dev_gso_segment(skb))) 2022 if (unlikely(dev_gso_segment(skb)))
1994 goto out_kfree_skb; 2023 goto out_kfree_skb;
@@ -2050,6 +2079,7 @@ out_kfree_gso_skb:
2050 skb->destructor = DEV_GSO_CB(skb)->destructor; 2079 skb->destructor = DEV_GSO_CB(skb)->destructor;
2051out_kfree_skb: 2080out_kfree_skb:
2052 kfree_skb(skb); 2081 kfree_skb(skb);
2082out:
2053 return rc; 2083 return rc;
2054} 2084}
2055 2085