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;
|
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,
|
static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_hash,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
@@ -2565,7 +2572,7 @@ static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_hash,
|
|||||||
default:
|
default:
|
||||||
rss_hash_type = PKT_HASH_TYPE_NONE;
|
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,
|
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);
|
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 &&
|
can_push = vi->any_header_sg &&
|
||||||
!((unsigned long)skb->data & (__alignof__(*hdr) - 1)) &&
|
!((unsigned long)skb->data & (__alignof__(*hdr) - 1)) &&
|
||||||
!skb_header_cloned(skb) && skb_headroom(skb) >= hdr_len;
|
!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;
|
hash_report = VIRTIO_NET_HASH_REPORT_NONE;
|
||||||
|
|
||||||
*rss_type = virtnet_xdp_rss_type[hash_report];
|
*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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -401,7 +401,8 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb,
|
|||||||
if (!tnl_hdr_negotiated)
|
if (!tnl_hdr_negotiated)
|
||||||
return -EINVAL;
|
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.hash_report = 0;
|
||||||
vhdr->hash_hdr.padding = 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_hash {
|
||||||
struct virtio_net_hdr_v1 hdr;
|
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_NONE 0
|
||||||
#define VIRTIO_NET_HASH_REPORT_IPv4 1
|
#define VIRTIO_NET_HASH_REPORT_IPv4 1
|
||||||
#define VIRTIO_NET_HASH_REPORT_TCPv4 2
|
#define VIRTIO_NET_HASH_REPORT_TCPv4 2
|
||||||
|
|||||||
Reference in New Issue
Block a user