ANDROID: BACKPORT: vsock/virtio: Limit size of TX buffers

Prior to I4212a8daf9f19b5bbffc06ce93338c823de7bb19 ("FROMGIT:
vhost/vsock: Allocate nonlinear SKBs for handling large receive
buffers"), vhost would allocate a linear SKB of up to 128KiB in size,
limited by VIRTIO_VSOCK_MAX_PKT_BUF_SIZE and the length of the incoming
packet.

As such large allocations are prone to failure, an Android-specific
command-line option to reduce VIRTIO_VSOCK_MAX_PKT_BUF_SIZE was added in
Ia4f9180025b64d61d9e2b882daa84460b8f08fd2 ("ANDROID: Make vsock virtio
packet buff size configurable"). Since then, Cuttlefish has been
specifying this as 16Kib for its guest kernel images, resulting in a
maximum RX buffer allocation of 32KiB (which correlates with
PAGE_ALLOC_COSTLY_ORDER for architectures using 4KiB pages) on the host.

Now that both the vhost and virtio backends for vsock support non-linear
SKB allocations on the transmit and receive paths, we are guaranteed not
to allocate above PAGE_ALLOC_COSTLY_ORDER and so the Android-specific
command-line tunable can be removed.

Well, almost.

The fly in the ointment is that we are unable to update both the guest
and host kernels atomically and, in the case of Cuttlefish, the host
kernel may be of a sufficient vintage that backporting the support
for non-linear SKBs in vsock is non-trivial and impractical.

In an effort to phase out the command-line option but preserve existing
behaviour with older hosts, limit the TX buffer size to ~28KiB. This
means that the unpatched host will continue to allocate 32KiB RX buffers
but will achieve better utilisation, whilst having a page of wiggle room
in case the size of an SKB increases before it learns about non-linear
allocations. This additionally saves vsock users in AVF from having to
worry about whether or not they need to configure the buffer size
manually.

One day, when all supported hosts are running kernels later than
android16-6.12, we'll be able to revert this. In the meantime, it's a
bit of a mess.

Bug: 421244320
Bug: 149494272
[willdeacon@: Drop zero-copy part]
Signed-off-by: Will Deacon <willdeacon@google.com>
Change-Id: Iae8075ce39b3de6471f875e06869e4899f6eed5a
This commit is contained in:
Will Deacon
2025-07-22 13:11:25 +01:00
committed by Isaac Manjarres
parent 35ae5c9699
commit d89d5bb9ca

View File

@@ -230,6 +230,24 @@ static u16 virtio_transport_get_type(struct sock *sk)
static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
struct virtio_vsock_pkt_info *info)
{
/* ANDROID:
*
* Older host kernels (including the 5.10-based images used by
* Cuttlefish) only support linear SKBs on the RX path.
* Consequently, if we transmit a VIRTIO_VSOCK_MAX_PKT_BUF_SIZE
* packet, the host allocation can fail and the packet will be
* silently dropped.
*
* As a nasty workaround, limit the entire SKB to ~28KiB, which
* allows for 4KiB of SKB wiggle room whilst keeping the
* allocation below PAGE_ALLOC_COSTLY_ORDER.
*
* This can be removed when all supported host kernels have
* support for non-linear RX buffers introduced by Change-Id
* I4212a8daf9f19b5bbffc06ce93338c823de7bb19.
*/
u32 max_skb_len = min_t(u32, VIRTIO_VSOCK_MAX_PKT_BUF_SIZE,
SKB_WITH_OVERHEAD(SZ_32K - VIRTIO_VSOCK_SKB_HEADROOM) - SZ_4K);
u32 src_cid, src_port, dst_cid, dst_port;
const struct virtio_transport *t_ops;
struct virtio_vsock_sock *vvs;
@@ -268,7 +286,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
struct sk_buff *skb;
size_t skb_len;
skb_len = min_t(u32, VIRTIO_VSOCK_MAX_PKT_BUF_SIZE, rest_len);
skb_len = min_t(u32, max_skb_len, rest_len);
skb = virtio_transport_alloc_skb(info, skb_len,
src_cid, src_port,