|
@@ -4392,6 +4392,37 @@ unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
|
|
|
|
|
|
+/**
|
|
|
+ * skb_gso_validate_mtu - Return in case such skb fits a given MTU
|
|
|
+ *
|
|
|
+ * @skb: GSO skb
|
|
|
+ *
|
|
|
+ * skb_gso_validate_mtu validates if a given skb will fit a wanted MTU
|
|
|
+ * once split.
|
|
|
+ */
|
|
|
+bool skb_gso_validate_mtu(const struct sk_buff *skb, unsigned int mtu)
|
|
|
+{
|
|
|
+ const struct skb_shared_info *shinfo = skb_shinfo(skb);
|
|
|
+ const struct sk_buff *iter;
|
|
|
+ unsigned int hlen;
|
|
|
+
|
|
|
+ hlen = skb_gso_network_seglen(skb);
|
|
|
+
|
|
|
+ if (shinfo->gso_size != GSO_BY_FRAGS)
|
|
|
+ return hlen <= mtu;
|
|
|
+
|
|
|
+ /* Undo this so we can re-use header sizes */
|
|
|
+ hlen -= GSO_BY_FRAGS;
|
|
|
+
|
|
|
+ skb_walk_frags(skb, iter) {
|
|
|
+ if (hlen + skb_headlen(iter) > mtu)
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(skb_gso_validate_mtu);
|
|
|
+
|
|
|
static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
|
|
|
{
|
|
|
if (skb_cow(skb, skb_headroom(skb)) < 0) {
|