From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=fail (p=quarantine dis=none) header.from=redhat.com Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by passt.top (Postfix) with ESMTPS id 905D55A0265 for ; Mon, 02 Nov 2026 14:03:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1793624597; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:autocrypt:autocrypt; bh=JCuD+H9K/Duk9vEABRSmSGDU1uyIEsiw9vTJ8n9umb8=; b=OW7EEL4KkiXDRINCCoLTCsfaTXkoGk7BZjM0qC7DH/cyeH3DC1p50ZN7nyOnaiMk8muwDo Y+mi3WIOxt9Nv0MpsI1VmPZzkYjWbdy10sE5wx9B+m4kenzKIytMIxnSrVOlRSFVVXDTk4 XukMnM3Q7Rn0jaYX624r3cKJWFrc444= Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-623-LUGfVNAWOraaj6Dhp0DIuA-1; Mon, 02 Nov 2026 08:03:16 -0500 X-MC-Unique: LUGfVNAWOraaj6Dhp0DIuA-1 X-Mimecast-MFC-AGG-ID: LUGfVNAWOraaj6Dhp0DIuA_1793624595 Received: by mail-ej1-f69.google.com with SMTP id a640c23a62f3a-c3f88d2ff28so256664266b.0 for ; Mon, 02 Nov 2026 05:03:15 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793624595; x=1794229395; h=content-transfer-encoding:content-type:in-reply-to:autocrypt:from :content-language:references:cc:to:subject:user-agent:mime-version :date:message-id:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=JCuD+H9K/Duk9vEABRSmSGDU1uyIEsiw9vTJ8n9umb8=; b=ZY4pUSMr1DKQCVZ2SLsxO/qLaUEt9sNNrwX0d2GxY/uFRHGjqPB5tnzDKSlikn3SOW gXotQhWL2yrF+OVzhmegV1Z6hWZv/58QKyJ0ahmuWAi3aeX+4pCf2dO091ZwoSG+NDZM bPWO5BO1UqR7og7zmGK9TI15cUdLQXRaeVtwZli2nFuQEItiBhp9gQsKyT8tw04/yuGl SZqlA+N1HmfMg5u97yBKokDNtbLtS2pl6K5fM+Sb6hp2aOI/Iek/E5pFzRH6H9GZYrfq h6ONB44Q36OWf6QiOIkznL8LQDWbwTRFx9qUyMJh/HPxBqjtpgO1+HGXhQH57mjhwNiw AwgA== X-Forwarded-Encrypted: i=1; AKwUvBwQyRGtPzij+TTjiV8Hf+ZHbl/33noOotZOdEfxrOOCKvlpnR8olXfZ+dvAKb12EJa8W/e890CZWqg=@passt.top X-Gm-Message-State: APuU4Z9iyEKmrsfY+9GHVqBLRycsv1iss6JC02fkBXEeVEFnNBU0qgCp s8KeMzhEPSnhRMEbWbBAGukgL6oEeowGsKxiMJDj9Y2Nsw7ps3mm240sCKetdPspn4992zV7BiB FIetNDFcUMzU6x8uKkAuPJCzuNeTMU87NHSIWXg8vQ20d8+2YGbMNyw== X-Gm-Gg: AYBFou1wNiodzh3cltqyloD32kNSddBwZ+bHjRKx9bWZJNtvro9SeSnVhueILFiDS8K JLiSN74VGXINZWQHjCCC98e7fmzPGTiRCt+tr8+qE8DHuASViDCTDYx21M4pQPXLnl/nL6FcaH2 E60mFATTm3L3OENlaj0J+xC2oNzxpOIztBILandiIH9I7u+aTfjPsHePpkH/aVbBOsFw4gXZF26 r9wGMc3J20tQb9SfaK474PRlXNQUeCM3VTyV9eiofvtTvj38dkwzTpAZaVc5SCRE2HMldDEJEqD 2BUTM239q0VMrBDkhbPYSfXqDWuPI/Z+8YFkYFrioKVpjl6xYVeL8ftJTcYxF30jzfwR5W3NDjp 1RrGlzADZ1M7lBDcxQDKo6v7bTskWBid2AOXR4an7o3mVtE/mdTQfeWtUvbd+WayTYfRYEKVfHX yODOi+5b8bISFdcns= X-Received: by 2002:a17:907:3f95:b0:c29:4a1f:76be with SMTP id a640c23a62f3a-c4ca7a74b33mr763780966b.20.1793624594565; Mon, 02 Nov 2026 05:03:14 -0800 (PST) X-Received: by 2002:a17:907:3f95:b0:c29:4a1f:76be with SMTP id a640c23a62f3a-c4ca7a74b33mr763775166b.20.1793624593845; Mon, 02 Nov 2026 05:03:13 -0800 (PST) Received: from ?IPV6:2a01:e0a:e10:ef90:e9e7:d9a0:a4eb:dc4b? ([2a01:e0a:e10:ef90:e9e7:d9a0:a4eb:dc4b]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-48e71b7815fsm20510967f8f.22.2026.11.02.05.03.12 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 02 Nov 2026 05:03:13 -0800 (PST) Message-ID: <15a03a23-c8fb-49dc-8f65-6620e48b2941@redhat.com> Date: Mon, 2 Nov 2026 14:03:11 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] packet: Fix pool traversal for multi-iovec packets To: luochunsheng@ustc.edu, passt-dev@passt.top References: <20261102073011.3537587-1-luochunsheng@ustc.edu> From: Laurent Vivier Autocrypt: addr=lvivier@redhat.com; keydata= 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 In-Reply-To: <20261102073011.3537587-1-luochunsheng@ustc.edu> X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: npxzDWzqGgofl9g0aRdSUz5XTQUdqWpg90elWrhDo-8_1793624595 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Message-ID-Hash: LRWCXPHTIVALZY2SVC5ZO3YPDY3BTRXW X-Message-ID-Hash: LRWCXPHTIVALZY2SVC5ZO3YPDY3BTRXW X-MailFrom: lvivier@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: luffyluo X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: On 11/2/26 08:30, luochunsheng@ustc.edu wrote: > From: luffyluo > > With vhost-user a guest frame can span several descriptors. The pool > stores such a packet as a marker slot (iov_base == NULL, iov_len = N) > followed by N data slots, and packet_get() uses the marker to return > all N iovecs at once. > > The traversal loops in tap4_handler(), tap6_handler(), > tcp_data_from_tap() and udp_tap_handler() don't know about markers and > advance one slot at a time: after handling the packet from its marker > they land on its first data slot, where iov_base != NULL, so > packet_get() hands back that slot alone, as if it were a whole > single-iovec packet. Parsing that fragment as a complete frame is > what breaks: in tcp_data_from_tap() a fragment shorter than a TCP > header makes IOV_PEEK_HEADER() fail ("TCP header not contiguous"), and > a longer one gives a th->doff read from payload bytes, so > off = th->doff * 4 exceeds the fragment length. In udp_tap_handler() > the fragments go out as extra datagrams. > > Fix it with packet_next(), returning the index of the packet following > the one at a given index, and use it to advance those loops, so they > skip the data slots of the packet they just handled. For single-iovec > packets it returns idx + 1, so tap and pasta, which always build > single-iovec tails with IOV_TAIL_FROM_BUF(), are unaffected. > > Fixes: ca38be0141d1 ("packet: Add support for multi-vector packets") > Signed-off-by: luffyluo Thank you for your patch, it looks correct. There is a remaining problem: the handlers return the number of consumed slots (generally they comsume everything so they return p->count - idx) but udp_tap_handler() returns the return value of sendmmsg() that doesn't reflect the actual number of consumed slot. Thanks, Laurent > --- > packet.c | 16 ++++++++++++++++ > packet.h | 1 + > tap.c | 4 ++-- > tcp.c | 2 +- > udp.c | 7 +++++-- > 5 files changed, 25 insertions(+), 5 deletions(-) > > diff --git a/packet.c b/packet.c > index 7a347be..f202245 100644 > --- a/packet.c > +++ b/packet.c > @@ -207,3 +207,19 @@ void pool_flush(struct pool *p) > { > p->count = 0; > } > + > +/** > + * packet_next() - Index of the packet following the one at @idx > + * @p: Packet pool > + * @idx: Slot index of the current packet (marker or single iovec) > + * > + * A multi-iovec packet is stored as a marker slot (iov_base == NULL) whose > + * iov_len holds the number of iovec slots that follow it. Return the slot > + * index of the next packet. > + */ > +size_t packet_next(const struct pool *p, size_t idx) > +{ > + if (p->pkt[idx].iov_base == NULL) > + return idx + p->pkt[idx].iov_len + 1; > + return idx + 1; > +} > diff --git a/packet.h b/packet.h > index 7b7fa71..03821f6 100644 > --- a/packet.h > +++ b/packet.h > @@ -41,6 +41,7 @@ bool packet_get_do(const struct pool *p, const size_t idx, > struct iov_tail *data, const char *func, int line); > bool pool_can_fit(const struct pool *p, struct iov_tail *data); > void pool_flush(struct pool *p); > +size_t packet_next(const struct pool *p, size_t idx); > > #define packet_add(p, data) \ > packet_add_do(p, data, __func__, __LINE__) > diff --git a/tap.c b/tap.c > index dfa66c7..1a310fe 100644 > --- a/tap.c > +++ b/tap.c > @@ -700,7 +700,7 @@ static int tap4_handler(struct ctx *c, const struct pool *in, > > i = 0; > resume: > - for (seq_count = 0, seq = NULL; i < in->count; i++) { > + for (seq_count = 0, seq = NULL; i < in->count; i = packet_next(in, i)) { > struct iovec trim_iov[UIO_MAXIOV]; > size_t l3len, hlen, l4len, check; > struct ethhdr eh_storage; > @@ -948,7 +948,7 @@ static int tap6_handler(struct ctx *c, const struct pool *in, > > i = 0; > resume: > - for (seq_count = 0, seq = NULL; i < in->count; i++) { > + for (seq_count = 0, seq = NULL; i < in->count; i = packet_next(in, i)) { > size_t l4len, plen, check; > struct in6_addr *saddr, *daddr; > struct ipv6hdr ip6h_storage; > diff --git a/tcp.c b/tcp.c > index 95f4f3e..a3bb8b9 100644 > --- a/tcp.c > +++ b/tcp.c > @@ -1946,7 +1946,7 @@ static int tcp_data_from_tap(const struct ctx *c, struct tcp_tap_conn *conn, > > assert(conn->events & ESTABLISHED); > > - for (i = idx, iov_i = 0; i < (int)p->count; i++) { > + for (i = idx, iov_i = 0; i < (int)p->count; i = packet_next(p, i)) { > uint32_t seq, seq_offset, ack_seq; > struct tcphdr th_storage; > const struct tcphdr *th; > diff --git a/udp.c b/udp.c > index 505e554..bd5e241 100644 > --- a/udp.c > +++ b/udp.c > @@ -1029,6 +1029,7 @@ int udp_tap_handler(const struct ctx *c, uint8_t pif, > const struct udphdr *uh; > struct udp_flow *uflow; > int i, j, s, count = 0; > + size_t slot; > struct iov_tail data; > flow_sidx_t tosidx; > in_port_t src, dst; > @@ -1077,10 +1078,12 @@ int udp_tap_handler(const struct ctx *c, uint8_t pif, > > pif_sockaddr(c, &to_sa, topif, &toside->eaddr, toside->eport); > > - for (i = 0, j = 0; i < (int)p->count - idx && j < UIO_MAXIOV; i++) { > + for (i = 0, j = 0, slot = idx; > + slot < p->count && j < UIO_MAXIOV; > + slot = packet_next(p, slot), i++) { > const struct udphdr *uh_send; > > - if (!packet_get(p, idx + i, &data)) > + if (!packet_get(p, slot, &data)) > return p->count - idx; > > uh_send = IOV_REMOVE_HEADER(&data, uh_storage);