|
@@ -2563,7 +2563,7 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
|
|
|
|
|
|
netdev_features_t netif_skb_features(struct sk_buff *skb)
|
|
netdev_features_t netif_skb_features(struct sk_buff *skb)
|
|
{
|
|
{
|
|
- const struct net_device *dev = skb->dev;
|
|
|
|
|
|
+ struct net_device *dev = skb->dev;
|
|
netdev_features_t features = dev->features;
|
|
netdev_features_t features = dev->features;
|
|
u16 gso_segs = skb_shinfo(skb)->gso_segs;
|
|
u16 gso_segs = skb_shinfo(skb)->gso_segs;
|
|
__be16 protocol = skb->protocol;
|
|
__be16 protocol = skb->protocol;
|
|
@@ -2571,13 +2571,20 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
|
|
if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs)
|
|
if (gso_segs > dev->gso_max_segs || gso_segs < dev->gso_min_segs)
|
|
features &= ~NETIF_F_GSO_MASK;
|
|
features &= ~NETIF_F_GSO_MASK;
|
|
|
|
|
|
|
|
+ /* If encapsulation offload request, verify we are testing
|
|
|
|
+ * hardware encapsulation features instead of standard
|
|
|
|
+ * features for the netdev
|
|
|
|
+ */
|
|
|
|
+ if (skb->encapsulation)
|
|
|
|
+ features &= dev->hw_enc_features;
|
|
|
|
+
|
|
if (!vlan_tx_tag_present(skb)) {
|
|
if (!vlan_tx_tag_present(skb)) {
|
|
if (unlikely(protocol == htons(ETH_P_8021Q) ||
|
|
if (unlikely(protocol == htons(ETH_P_8021Q) ||
|
|
protocol == htons(ETH_P_8021AD))) {
|
|
protocol == htons(ETH_P_8021AD))) {
|
|
struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
|
|
struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
|
|
protocol = veh->h_vlan_encapsulated_proto;
|
|
protocol = veh->h_vlan_encapsulated_proto;
|
|
} else {
|
|
} else {
|
|
- return harmonize_features(skb, features);
|
|
|
|
|
|
+ goto finalize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2595,6 +2602,11 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
|
|
NETIF_F_HW_VLAN_CTAG_TX |
|
|
NETIF_F_HW_VLAN_CTAG_TX |
|
|
NETIF_F_HW_VLAN_STAG_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);
|
|
|
|
+
|
|
return harmonize_features(skb, features);
|
|
return harmonize_features(skb, features);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(netif_skb_features);
|
|
EXPORT_SYMBOL(netif_skb_features);
|
|
@@ -2665,13 +2677,6 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
|
|
if (unlikely(!skb))
|
|
if (unlikely(!skb))
|
|
goto out_null;
|
|
goto out_null;
|
|
|
|
|
|
- /* If encapsulation offload request, verify we are testing
|
|
|
|
- * hardware encapsulation features instead of standard
|
|
|
|
- * features for the netdev
|
|
|
|
- */
|
|
|
|
- if (skb->encapsulation)
|
|
|
|
- features &= dev->hw_enc_features;
|
|
|
|
-
|
|
|
|
if (netif_needs_gso(dev, skb, features)) {
|
|
if (netif_needs_gso(dev, skb, features)) {
|
|
struct sk_buff *segs;
|
|
struct sk_buff *segs;
|
|
|
|
|