mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
virtio_net: fix alignment for virtio_net_hdr_v1_hash
Changing alignment of header would mean it's no longer safe to cast a
2 byte aligned pointer between formats. Use two 16 bit fields to make
it 2 byte aligned as previously.
This fixes the performance regression since
commit ("virtio_net: enable gso over UDP tunnel support.") as it uses
virtio_net_hdr_v1_hash_tunnel which embeds
virtio_net_hdr_v1_hash. Pktgen in guest + XDP_DROP on TAP + vhost_net
shows the TX PPS is recovered from 2.4Mpps to 4.45Mpps.
Fixes: 56a06bd40f ("virtio_net: enable gso over UDP tunnel support.")
Cc: stable@vger.kernel.org
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Link: https://patch.msgid.link/20251031060551.126-1-jasowang@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
e120f46768
commit
c3838262b8
@@ -2539,6 +2539,13 @@ err_buf:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
virtio_net_hash_value(const struct virtio_net_hdr_v1_hash *hdr_hash)
|
||||
{
|
||||
return __le16_to_cpu(hdr_hash->hash_value_lo) |
|
||||
(__le16_to_cpu(hdr_hash->hash_value_hi) << 16);
|
||||
}
|
||||
|
||||
static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_hash,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@@ -2565,7 +2572,7 @@ static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_hash,
|
||||
default:
|
||||
rss_hash_type = PKT_HASH_TYPE_NONE;
|
||||
}
|
||||
skb_set_hash(skb, __le32_to_cpu(hdr_hash->hash_value), rss_hash_type);
|
||||
skb_set_hash(skb, virtio_net_hash_value(hdr_hash), rss_hash_type);
|
||||
}
|
||||
|
||||
static void virtnet_receive_done(struct virtnet_info *vi, struct receive_queue *rq,
|
||||
@@ -3311,6 +3318,10 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb, bool orphan)
|
||||
|
||||
pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
|
||||
|
||||
/* Make sure it's safe to cast between formats */
|
||||
BUILD_BUG_ON(__alignof__(*hdr) != __alignof__(hdr->hash_hdr));
|
||||
BUILD_BUG_ON(__alignof__(*hdr) != __alignof__(hdr->hash_hdr.hdr));
|
||||
|
||||
can_push = vi->any_header_sg &&
|
||||
!((unsigned long)skb->data & (__alignof__(*hdr) - 1)) &&
|
||||
!skb_header_cloned(skb) && skb_headroom(skb) >= hdr_len;
|
||||
@@ -6750,7 +6761,7 @@ static int virtnet_xdp_rx_hash(const struct xdp_md *_ctx, u32 *hash,
|
||||
hash_report = VIRTIO_NET_HASH_REPORT_NONE;
|
||||
|
||||
*rss_type = virtnet_xdp_rss_type[hash_report];
|
||||
*hash = __le32_to_cpu(hdr_hash->hash_value);
|
||||
*hash = virtio_net_hash_value(hdr_hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -401,7 +401,8 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb,
|
||||
if (!tnl_hdr_negotiated)
|
||||
return -EINVAL;
|
||||
|
||||
vhdr->hash_hdr.hash_value = 0;
|
||||
vhdr->hash_hdr.hash_value_lo = 0;
|
||||
vhdr->hash_hdr.hash_value_hi = 0;
|
||||
vhdr->hash_hdr.hash_report = 0;
|
||||
vhdr->hash_hdr.padding = 0;
|
||||
|
||||
|
||||
@@ -193,7 +193,8 @@ struct virtio_net_hdr_v1 {
|
||||
|
||||
struct virtio_net_hdr_v1_hash {
|
||||
struct virtio_net_hdr_v1 hdr;
|
||||
__le32 hash_value;
|
||||
__le16 hash_value_lo;
|
||||
__le16 hash_value_hi;
|
||||
#define VIRTIO_NET_HASH_REPORT_NONE 0
|
||||
#define VIRTIO_NET_HASH_REPORT_IPv4 1
|
||||
#define VIRTIO_NET_HASH_REPORT_TCPv4 2
|
||||
|
||||
Reference in New Issue
Block a user