Skip to content

Commit ae7ef81

Browse files
marceloleitnerdavem330
authored andcommitted
skbuff: introduce skb_gso_validate_mtu
skb_gso_network_seglen is not enough for checking fragment sizes if skb is using GSO_BY_FRAGS as we have to check frag per frag. This patch introduces skb_gso_validate_mtu, based on the former, which will wrap the use case inside it as all calls to skb_gso_network_seglen were to validate if it fits on a given TMU, and improve the check. Signed-off-by: Marcelo Ricardo Leitner <[email protected]> Tested-by: Xin Long <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3953c46 commit ae7ef81

File tree

6 files changed

+36
-4
lines changed

6 files changed

+36
-4
lines changed

include/linux/skbuff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2992,6 +2992,7 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len);
29922992
int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
29932993
void skb_scrub_packet(struct sk_buff *skb, bool xnet);
29942994
unsigned int skb_gso_transport_seglen(const struct sk_buff *skb);
2995+
bool skb_gso_validate_mtu(const struct sk_buff *skb, unsigned int mtu);
29952996
struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features);
29962997
struct sk_buff *skb_vlan_untag(struct sk_buff *skb);
29972998
int skb_ensure_writable(struct sk_buff *skb, int write_len);

net/core/skbuff.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4392,6 +4392,37 @@ unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
43924392
}
43934393
EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
43944394

4395+
/**
4396+
* skb_gso_validate_mtu - Return in case such skb fits a given MTU
4397+
*
4398+
* @skb: GSO skb
4399+
*
4400+
* skb_gso_validate_mtu validates if a given skb will fit a wanted MTU
4401+
* once split.
4402+
*/
4403+
bool skb_gso_validate_mtu(const struct sk_buff *skb, unsigned int mtu)
4404+
{
4405+
const struct skb_shared_info *shinfo = skb_shinfo(skb);
4406+
const struct sk_buff *iter;
4407+
unsigned int hlen;
4408+
4409+
hlen = skb_gso_network_seglen(skb);
4410+
4411+
if (shinfo->gso_size != GSO_BY_FRAGS)
4412+
return hlen <= mtu;
4413+
4414+
/* Undo this so we can re-use header sizes */
4415+
hlen -= GSO_BY_FRAGS;
4416+
4417+
skb_walk_frags(skb, iter) {
4418+
if (hlen + skb_headlen(iter) > mtu)
4419+
return false;
4420+
}
4421+
4422+
return true;
4423+
}
4424+
EXPORT_SYMBOL_GPL(skb_gso_validate_mtu);
4425+
43954426
static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
43964427
{
43974428
if (skb_cow(skb, skb_headroom(skb)) < 0) {

net/ipv4/ip_forward.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
5454
if (skb->ignore_df)
5555
return false;
5656

57-
if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
57+
if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu))
5858
return false;
5959

6060
return true;

net/ipv4/ip_output.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk,
225225

226226
/* common case: locally created skb or seglen is <= mtu */
227227
if (((IPCB(skb)->flags & IPSKB_FORWARDED) == 0) ||
228-
skb_gso_network_seglen(skb) <= mtu)
228+
skb_gso_validate_mtu(skb, mtu))
229229
return ip_finish_output2(net, sk, skb);
230230

231231
/* Slowpath - GSO segment length is exceeding the dst MTU.

net/ipv6/ip6_output.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
368368
if (skb->ignore_df)
369369
return false;
370370

371-
if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
371+
if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu))
372372
return false;
373373

374374
return true;

net/mpls/af_mpls.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
9191
if (skb->len <= mtu)
9292
return false;
9393

94-
if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
94+
if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu))
9595
return false;
9696

9797
return true;

0 commit comments

Comments
 (0)