|
@@ -2562,12 +2562,26 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
|
|
|
return features;
|
|
|
}
|
|
|
|
|
|
+netdev_features_t passthru_features_check(struct sk_buff *skb,
|
|
|
+ struct net_device *dev,
|
|
|
+ netdev_features_t features)
|
|
|
+{
|
|
|
+ return features;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(passthru_features_check);
|
|
|
+
|
|
|
+static netdev_features_t dflt_features_check(const struct sk_buff *skb,
|
|
|
+ struct net_device *dev,
|
|
|
+ netdev_features_t features)
|
|
|
+{
|
|
|
+ return vlan_features_check(skb, features);
|
|
|
+}
|
|
|
+
|
|
|
netdev_features_t netif_skb_features(struct sk_buff *skb)
|
|
|
{
|
|
|
struct net_device *dev = skb->dev;
|
|
|
netdev_features_t features = dev->features;
|
|
|
u16 gso_segs = skb_shinfo(skb)->gso_segs;
|
|
|
- __be16 protocol = skb->protocol;
|
|
|
|
|
|
if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs)
|
|
|
features &= ~NETIF_F_GSO_MASK;
|
|
@@ -2579,34 +2593,17 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
|
|
|
if (skb->encapsulation)
|
|
|
features &= dev->hw_enc_features;
|
|
|
|
|
|
- if (!skb_vlan_tag_present(skb)) {
|
|
|
- if (unlikely(protocol == htons(ETH_P_8021Q) ||
|
|
|
- protocol == htons(ETH_P_8021AD))) {
|
|
|
- struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
|
|
|
- protocol = veh->h_vlan_encapsulated_proto;
|
|
|
- } else {
|
|
|
- goto finalize;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- features = netdev_intersect_features(features,
|
|
|
- dev->vlan_features |
|
|
|
- NETIF_F_HW_VLAN_CTAG_TX |
|
|
|
- NETIF_F_HW_VLAN_STAG_TX);
|
|
|
-
|
|
|
- if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD))
|
|
|
+ if (skb_vlan_tagged(skb))
|
|
|
features = netdev_intersect_features(features,
|
|
|
- NETIF_F_SG |
|
|
|
- NETIF_F_HIGHDMA |
|
|
|
- NETIF_F_FRAGLIST |
|
|
|
- NETIF_F_GEN_CSUM |
|
|
|
+ dev->vlan_features |
|
|
|
NETIF_F_HW_VLAN_CTAG_TX |
|
|
|
NETIF_F_HW_VLAN_STAG_TX);
|
|
|
|
|
|
-finalize:
|
|
|
if (dev->netdev_ops->ndo_features_check)
|
|
|
features &= dev->netdev_ops->ndo_features_check(skb, dev,
|
|
|
features);
|
|
|
+ else
|
|
|
+ features &= dflt_features_check(skb, dev, features);
|
|
|
|
|
|
return harmonize_features(skb, features);
|
|
|
}
|