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)); }