|
@@ -2172,6 +2172,64 @@ static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * i40evf_features_check - Validate encapsulated packet conforms to limits
|
|
|
+ * @skb: skb buff
|
|
|
+ * @netdev: This physical port's netdev
|
|
|
+ * @features: Offload features that the stack believes apply
|
|
|
+ **/
|
|
|
+static netdev_features_t i40evf_features_check(struct sk_buff *skb,
|
|
|
+ struct net_device *dev,
|
|
|
+ netdev_features_t features)
|
|
|
+{
|
|
|
+ size_t len;
|
|
|
+
|
|
|
+ /* No point in doing any of this if neither checksum nor GSO are
|
|
|
+ * being requested for this frame. We can rule out both by just
|
|
|
+ * checking for CHECKSUM_PARTIAL
|
|
|
+ */
|
|
|
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
|
|
|
+ return features;
|
|
|
+
|
|
|
+ /* We cannot support GSO if the MSS is going to be less than
|
|
|
+ * 64 bytes. If it is then we need to drop support for GSO.
|
|
|
+ */
|
|
|
+ if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
|
|
|
+ features &= ~NETIF_F_GSO_MASK;
|
|
|
+
|
|
|
+ /* MACLEN can support at most 63 words */
|
|
|
+ len = skb_network_header(skb) - skb->data;
|
|
|
+ if (len & ~(63 * 2))
|
|
|
+ goto out_err;
|
|
|
+
|
|
|
+ /* IPLEN and EIPLEN can support at most 127 dwords */
|
|
|
+ len = skb_transport_header(skb) - skb_network_header(skb);
|
|
|
+ if (len & ~(127 * 4))
|
|
|
+ goto out_err;
|
|
|
+
|
|
|
+ if (skb->encapsulation) {
|
|
|
+ /* L4TUNLEN can support 127 words */
|
|
|
+ len = skb_inner_network_header(skb) - skb_transport_header(skb);
|
|
|
+ if (len & ~(127 * 2))
|
|
|
+ goto out_err;
|
|
|
+
|
|
|
+ /* IPLEN can support at most 127 dwords */
|
|
|
+ len = skb_inner_transport_header(skb) -
|
|
|
+ skb_inner_network_header(skb);
|
|
|
+ if (len & ~(127 * 4))
|
|
|
+ goto out_err;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* No need to validate L4LEN as TCP is the only protocol with a
|
|
|
+ * a flexible value and we support all possible values supported
|
|
|
+ * by TCP, which is at most 15 dwords
|
|
|
+ */
|
|
|
+
|
|
|
+ return features;
|
|
|
+out_err:
|
|
|
+ return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
|
|
|
+}
|
|
|
+
|
|
|
#define I40EVF_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_TX |\
|
|
|
NETIF_F_HW_VLAN_CTAG_RX |\
|
|
|
NETIF_F_HW_VLAN_CTAG_FILTER)
|
|
@@ -2206,6 +2264,7 @@ static const struct net_device_ops i40evf_netdev_ops = {
|
|
|
.ndo_tx_timeout = i40evf_tx_timeout,
|
|
|
.ndo_vlan_rx_add_vid = i40evf_vlan_rx_add_vid,
|
|
|
.ndo_vlan_rx_kill_vid = i40evf_vlan_rx_kill_vid,
|
|
|
+ .ndo_features_check = i40evf_features_check,
|
|
|
.ndo_fix_features = i40evf_fix_features,
|
|
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
|
|
.ndo_poll_controller = i40evf_netpoll,
|