From 703bdf030095628593f2e8e370983ed2a2020726 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 22 Jul 2025 13:11:25 +0100 Subject: [PATCH] ANDROID: 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 Signed-off-by: Will Deacon Change-Id: Iae8075ce39b3de6471f875e06869e4899f6eed5a --- net/vmw_vsock/virtio_transport_common.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 23c41e3a006b..6945e77df9df 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -333,7 +333,24 @@ out: static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, struct virtio_vsock_pkt_info *info) { - u32 max_skb_len = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; + /* 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; @@ -378,7 +395,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, can_zcopy = virtio_transport_can_zcopy(t_ops, info, pkt_len); if (can_zcopy) - max_skb_len = min_t(u32, VIRTIO_VSOCK_MAX_PKT_BUF_SIZE, + max_skb_len = min_t(u32, max_skb_len, (MAX_SKB_FRAGS * PAGE_SIZE)); }