|
@@ -1454,6 +1454,27 @@ static inline void net_timestamp_check(struct sk_buff *skb)
|
|
|
__net_timestamp(skb);
|
|
|
}
|
|
|
|
|
|
+static inline bool is_skb_forwardable(struct net_device *dev,
|
|
|
+ struct sk_buff *skb)
|
|
|
+{
|
|
|
+ unsigned int len;
|
|
|
+
|
|
|
+ if (!(dev->flags & IFF_UP))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ len = dev->mtu + dev->hard_header_len + VLAN_HLEN;
|
|
|
+ if (skb->len <= len)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ /* if TSO is enabled, we don't care about the length as the packet
|
|
|
+ * could be forwarded without being segmented before
|
|
|
+ */
|
|
|
+ if (skb_is_gso(skb))
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* dev_forward_skb - loopback an skb to another netif
|
|
|
*
|
|
@@ -1477,8 +1498,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
|
|
|
skb_orphan(skb);
|
|
|
nf_reset(skb);
|
|
|
|
|
|
- if (unlikely(!(dev->flags & IFF_UP) ||
|
|
|
- (skb->len > (dev->mtu + dev->hard_header_len + VLAN_HLEN)))) {
|
|
|
+ if (unlikely(!is_skb_forwardable(dev, skb))) {
|
|
|
atomic_long_inc(&dev->rx_dropped);
|
|
|
kfree_skb(skb);
|
|
|
return NET_RX_DROP;
|