aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index d8befd06da04..a51dfd7b56fb 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2017,22 +2017,41 @@ static inline void skb_orphan_try(struct sk_buff *skb)
2017 } 2017 }
2018} 2018}
2019 2019
2020int netif_get_vlan_features(struct sk_buff *skb, struct net_device *dev) 2020static int harmonize_features(struct sk_buff *skb, __be16 protocol, int features)
2021{
2022 if (!can_checksum_protocol(protocol, features)) {
2023 features &= ~NETIF_F_ALL_CSUM;
2024 features &= ~NETIF_F_SG;
2025 } else if (illegal_highdma(skb->dev, skb)) {
2026 features &= ~NETIF_F_SG;
2027 }
2028
2029 return features;
2030}
2031
2032int netif_skb_features(struct sk_buff *skb)
2021{ 2033{
2022 __be16 protocol = skb->protocol; 2034 __be16 protocol = skb->protocol;
2035 int features = skb->dev->features;
2023 2036
2024 if (protocol == htons(ETH_P_8021Q)) { 2037 if (protocol == htons(ETH_P_8021Q)) {
2025 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; 2038 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
2026 protocol = veh->h_vlan_encapsulated_proto; 2039 protocol = veh->h_vlan_encapsulated_proto;
2027 } else if (!skb->vlan_tci) 2040 } else if (!vlan_tx_tag_present(skb)) {
2028 return dev->features; 2041 return harmonize_features(skb, protocol, features);
2042 }
2029 2043
2030 if (protocol != htons(ETH_P_8021Q)) 2044 features &= skb->dev->vlan_features;
2031 return dev->features & dev->vlan_features; 2045
2032 else 2046 if (protocol != htons(ETH_P_8021Q)) {
2033 return 0; 2047 return harmonize_features(skb, protocol, features);
2048 } else {
2049 features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
2050 NETIF_F_GEN_CSUM;
2051 return harmonize_features(skb, protocol, features);
2052 }
2034} 2053}
2035EXPORT_SYMBOL(netif_get_vlan_features); 2054EXPORT_SYMBOL(netif_skb_features);
2036 2055
2037/* 2056/*
2038 * Returns true if either: 2057 * Returns true if either: