Bug 54491

Summary: UFO (UDP fragmentation offload) does not work if the payload size specified is within the range ( (MTU-28) to (MTU-8) )
Product: Networking Reporter: Sergey Berezin (hnk437)
Component: IPV4Assignee: Stephen Hemminger (stephen)
Status: NEW ---    
Severity: normal CC: szg00000
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 3.3.4 Subsystem:
Regression: No Bisected commit-id:

Description Sergey Berezin 2013-02-26 08:52:24 UTC
For IPv4/UDP if the payload size specified is within the range ( (MTU-28) 
to (MTU-8) ) packet gets segmented in kernel even if the following netdev features are set:

NETIF_F_SG 
NETIF_F_GEN_CSUM 
NETIF_F_UFO 
NETIF_F_TSO 
NETIF_F_GSO 
NETIF_F_GSO_ROBUST

Analysis:
udp_sendmsg() computes packet length by adding UDP header size to payload size: “ulen += sizeof(struct udphdr)”
Then the function calls ip_make_skb(), however IP header size is not added to the packet length.
ip_make_skb() in turn calls __ip_append_data(). The same packet length is used here. 
__ip_append_data() compares the packet length with MTU. The packet length still does not include IP header size (20 bytes).
In result, when payload size “is within the range ( (MTU-28) to (MTU-8) )” standard branch is taken rather than ip_ufo_append_data(). Gso_size is not computed, therefore IP fragmentation is triggered from ip_finish_output().

The issue was reproduced on 3.4.3 as well