|
@@ -9070,10 +9070,6 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|
|
0, 0, nlflags, filter_mask, NULL);
|
|
|
}
|
|
|
|
|
|
-/* Hardware supports L4 tunnel length of 128B (=2^7) which includes
|
|
|
- * inner mac plus all inner ethertypes.
|
|
|
- */
|
|
|
-#define I40E_MAX_TUNNEL_HDR_LEN 128
|
|
|
/**
|
|
|
* i40e_features_check - Validate encapsulated packet conforms to limits
|
|
|
* @skb: skb buff
|
|
@@ -9084,12 +9080,52 @@ static netdev_features_t i40e_features_check(struct sk_buff *skb,
|
|
|
struct net_device *dev,
|
|
|
netdev_features_t features)
|
|
|
{
|
|
|
- if (skb->encapsulation &&
|
|
|
- ((skb_inner_network_header(skb) - skb_transport_header(skb)) >
|
|
|
- I40E_MAX_TUNNEL_HDR_LEN))
|
|
|
- return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
|
|
|
+ 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);
|
|
|
}
|
|
|
|
|
|
static const struct net_device_ops i40e_netdev_ops = {
|