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