virtio-net: correct hdr_len handling for VIRTIO_NET_F_GUEST_HDRLEN
The commitbe50da3e9d("net: virtio_net: implement exact header length guest feature") introduces support for the VIRTIO_NET_F_GUEST_HDRLEN feature in virtio-net. This feature requires virtio-net to set hdr_len to the actual header length of the packet when transmitting, the number of bytes from the start of the packet to the beginning of the transport-layer payload. However, in practice, hdr_len was being set using skb_headlen(skb), which is clearly incorrect. This commit fixes that issue. Fixes:be50da3e9d("net: virtio_net: implement exact header length guest feature") Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Link: https://patch.msgid.link/20260320021818.111741-2-xuanzhuo@linux.alibaba.com Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
70b439bf06
commit
38ec410b99
|
|
@ -244,7 +244,7 @@ tun_vnet_hdr_tnl_from_skb(unsigned int flags,
|
|||
|
||||
if (virtio_net_hdr_tnl_from_skb(skb, tnl_hdr, has_tnl_offload,
|
||||
tun_vnet_is_little_endian(flags),
|
||||
vlan_hlen, true)) {
|
||||
vlan_hlen, true, false)) {
|
||||
struct virtio_net_hdr_v1 *hdr = &tnl_hdr->hash_hdr.hdr;
|
||||
struct skb_shared_info *sinfo = skb_shinfo(skb);
|
||||
|
||||
|
|
|
|||
|
|
@ -3267,8 +3267,12 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb, bool orphan)
|
|||
struct virtio_net_hdr_v1_hash_tunnel *hdr;
|
||||
int num_sg;
|
||||
unsigned hdr_len = vi->hdr_len;
|
||||
bool feature_hdrlen;
|
||||
bool can_push;
|
||||
|
||||
feature_hdrlen = virtio_has_feature(vi->vdev,
|
||||
VIRTIO_NET_F_GUEST_HDRLEN);
|
||||
|
||||
pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
|
||||
|
||||
/* Make sure it's safe to cast between formats */
|
||||
|
|
@ -3288,7 +3292,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb, bool orphan)
|
|||
|
||||
if (virtio_net_hdr_tnl_from_skb(skb, hdr, vi->tx_tnl,
|
||||
virtio_is_little_endian(vi->vdev), 0,
|
||||
false))
|
||||
false, feature_hdrlen))
|
||||
return -EPROTO;
|
||||
|
||||
if (vi->mergeable_rx_bufs)
|
||||
|
|
|
|||
|
|
@ -207,6 +207,23 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
|
|||
return __virtio_net_hdr_to_skb(skb, hdr, little_endian, hdr->gso_type);
|
||||
}
|
||||
|
||||
/* This function must be called after virtio_net_hdr_from_skb(). */
|
||||
static inline void __virtio_net_set_hdrlen(const struct sk_buff *skb,
|
||||
struct virtio_net_hdr *hdr,
|
||||
bool little_endian)
|
||||
{
|
||||
u16 hdr_len;
|
||||
|
||||
hdr_len = skb_transport_offset(skb);
|
||||
|
||||
if (hdr->gso_type == VIRTIO_NET_HDR_GSO_UDP_L4)
|
||||
hdr_len += sizeof(struct udphdr);
|
||||
else
|
||||
hdr_len += tcp_hdrlen(skb);
|
||||
|
||||
hdr->hdr_len = __cpu_to_virtio16(little_endian, hdr_len);
|
||||
}
|
||||
|
||||
static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
|
||||
struct virtio_net_hdr *hdr,
|
||||
bool little_endian,
|
||||
|
|
@ -385,7 +402,8 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb,
|
|||
bool tnl_hdr_negotiated,
|
||||
bool little_endian,
|
||||
int vlan_hlen,
|
||||
bool has_data_valid)
|
||||
bool has_data_valid,
|
||||
bool feature_hdrlen)
|
||||
{
|
||||
struct virtio_net_hdr *hdr = (struct virtio_net_hdr *)vhdr;
|
||||
unsigned int inner_nh, outer_th;
|
||||
|
|
@ -394,9 +412,17 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb,
|
|||
|
||||
tnl_gso_type = skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL |
|
||||
SKB_GSO_UDP_TUNNEL_CSUM);
|
||||
if (!tnl_gso_type)
|
||||
return virtio_net_hdr_from_skb(skb, hdr, little_endian,
|
||||
has_data_valid, vlan_hlen);
|
||||
if (!tnl_gso_type) {
|
||||
ret = virtio_net_hdr_from_skb(skb, hdr, little_endian,
|
||||
has_data_valid, vlan_hlen);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (feature_hdrlen && hdr->hdr_len)
|
||||
__virtio_net_set_hdrlen(skb, hdr, little_endian);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Tunnel support not negotiated but skb ask for it. */
|
||||
if (!tnl_hdr_negotiated)
|
||||
|
|
|
|||
Loading…
Reference in New Issue