From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: passt.top; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=OIHJM/ec; dkim-atps=neutral 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 17F665A0652 for ; Thu, 17 Apr 2025 18:52:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1744908755; 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; bh=oFUhEmmMO3UQbtFv7BV6d/dnUq0Iz/msAXgmJ7LIdnY=; b=OIHJM/ectF6DqP396YeApayvVnqKfqkWzTJc03JQ6GB3OoKAr3FonzRM4hiA/goOSYtwH5 jsNy2bz3RMVes67ZnNwSApqvUaOoGlXL6gQHsnIlL4L4kFqkAfJfznM7+EtUT/2FzdWvx8 4kdpfWBjwIBuRkoD5o1dbiWspO0I4dU= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-677-hO19m80FNEe7CuhFZuADxw-1; Thu, 17 Apr 2025 12:52:34 -0400 X-MC-Unique: hO19m80FNEe7CuhFZuADxw-1 X-Mimecast-MFC-AGG-ID: hO19m80FNEe7CuhFZuADxw_1744908753 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4097418001E0 for ; Thu, 17 Apr 2025 16:52:33 +0000 (UTC) Received: from lenovo-t14s.redhat.com (unknown [10.44.32.6]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2D07F19560BA; Thu, 17 Apr 2025 16:52:31 +0000 (UTC) From: Laurent Vivier To: passt-dev@passt.top Subject: [PATCH v5 29/29] packet: use buf to store iovec array Date: Thu, 17 Apr 2025 18:51:36 +0200 Message-ID: <20250417165136.2688884-30-lvivier@redhat.com> In-Reply-To: <20250417165136.2688884-1-lvivier@redhat.com> References: <20250417165136.2688884-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 2vCAl1_MHnWeWbEMVahWTmoYdNMAs44N9URU3qKE9yE_1744908753 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true Message-ID-Hash: YRYFAS4FEJWPG5ZTBGHNL7S2VCCXABWZ X-Message-ID-Hash: YRYFAS4FEJWPG5ZTBGHNL7S2VCCXABWZ 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: Laurent Vivier 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: When we use vhost-user we don't use the memory buffer of the pool to store the packet, so we can use it to store iovec array that points to the memory provided by vhost-user. Signed-off-by: Laurent Vivier --- packet.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 147 insertions(+), 16 deletions(-) diff --git a/packet.c b/packet.c index 0a2ad28d3d25..ccd98ff3aa36 100644 --- a/packet.c +++ b/packet.c @@ -84,6 +84,121 @@ bool pool_full(const struct pool *p) return p->count >= p->size; } +/** + * packet_iov_max_cnt() - Return the maximum number of iovec we can store + * @p: Pointer to packet pool + * + * Return: the maximum number of iovec we can store in the memory of + * the pool buffer + */ +static size_t packet_iov_max_cnt(const struct pool *p) +{ + return p->buf_size / sizeof(struct iovec); +} + +/** + * packet_iov_idx() - For a given packet index, return the iovec index and + * the number of iovec entry of the packet + * @p: Pointer to packet pool + * @idx: Index of packet descriptor in pool + * @iov_cnt: Pointer to store the number of the iovec entry of the packet + * @func: For tracing: name of calling function + * @line: For tracing: caller line of function call + * + * Return: the iovec index for the given packet index, @iov_cnt is set + * to the number of the iovec entry of the packet + */ +static int packet_iov_idx(const struct pool *p, size_t idx, size_t *iov_cnt, + const char *func, int line) +{ + size_t iov_idx, max = packet_iov_max_cnt(p); + + iov_idx = (size_t)p->pkt[idx].iov_base; + *iov_cnt = p->pkt[idx].iov_len; + + ASSERT_WITH_MSG(iov_idx + *iov_cnt <= max, + "Corrupt iov entry: (%zu, %zu), max: %zu, %s:%i", + iov_idx, *iov_cnt, max, func, line); + + return iov_idx; +} + +/** + * packet_iov_next_idx() - Give the the next available iovec index + * @p: Pointer to packet pool + * @idx: Index of packet descriptor in pool + * @func: For tracing: name of calling function + * @line: For tracing: caller line of function call + * + * Return: the next available iovec index + */ +static size_t packet_iov_next_idx(const struct pool *p, size_t idx, + const char *func, int line) +{ + size_t iov_idx, iov_cnt; + + if (idx == 0) + return 0; + + iov_idx = packet_iov_idx(p, idx - 1, &iov_cnt, func, line); + + return iov_idx + iov_cnt; +} + +/** + * packet_iov_data() - For a given packet index, provide the iovec array + * @p: Pointer to packet pool + * @idx: Index of packet descriptor in pool + * @data: iov_tail to store iovec array and count + * (offset is always set to 0) + * @func: For tracing: name of calling function + * @line: For tracing: caller line of function call + */ +static void packet_iov_data(const struct pool *p, size_t idx, + struct iov_tail *data, + const char *func, int line) +{ + struct iovec *iov = (struct iovec *)p->buf; + size_t iov_idx, iov_cnt; + + iov_idx = packet_iov_idx(p, idx, &iov_cnt, func, line); + + data->iov = &iov[iov_idx]; + data->cnt = iov_cnt; + data->off = 0; +} + +/** + * packet_iov_check_range() - Check if iovec array is valid for a pool + * @p: Pointer to packet pool + * @data: iov_tail that stores the iovec array to check + * @func: For tracing: name of calling function + * @line: For tracing: caller line of function call + * + * Return: 0 if the range is valid, -1 otherwise + */ +static int packet_iov_check_range(const struct pool *p, + const struct iov_tail *data, + const char *func, int line) +{ + size_t offset, i; + + offset = data->off; + for (i = 0; i < data->cnt; i++) { + int ret; + + ret = packet_check_range(p, + (char *)data->iov[i].iov_base + offset, + data->iov[i].iov_len - offset, + func, line); + if (ret) + return ret; + offset = 0; + } + + return 0; +} + /** * packet_add_do() - Add data as packet descriptor to given pool * @p: Existing pool @@ -107,14 +222,32 @@ void packet_add_do(struct pool *p, struct iov_tail *data, if (!iov_tail_prune(data)) return; - ASSERT(data->cnt == 1); /* we don't support iovec */ + if (packet_iov_check_range(p, data, func, line)) + return; + + if (p->memory) { + size_t iov_max_cnt = packet_iov_max_cnt(p); + struct iovec *iov = (struct iovec *)p->buf; + size_t iov_idx; + int iov_cnt; - len = data->iov[0].iov_len - data->off; - start = (char *)data->iov[0].iov_base + data->off; + iov_idx = packet_iov_next_idx(p, idx, func, line); - if (packet_check_range(p, start, len, func, line)) - return; + iov_cnt = iov_tail_slice(&iov[iov_idx], iov_max_cnt - iov_idx, + data, NULL); + if (iov_cnt < 0) { + debug("add iov (%zu,%zu) to buf with size %zu, %s:%i", + iov_idx, data->cnt, iov_max_cnt, func, line); + return; + } + len = iov_cnt; + /* NOLINTNEXTLINE(performance-no-int-to-ptr) */ + start = (char *)iov_idx; + } else { + len = data->iov[0].iov_len - data->off; + start = (char *)data->iov[0].iov_base + data->off; + } p->pkt[idx].iov_base = (void *)start; p->pkt[idx].iov_len = len; @@ -135,8 +268,6 @@ bool packet_data_do(const struct pool *p, size_t idx, struct iov_tail *data, const char *func, int line) { - size_t i; - ASSERT_WITH_MSG(p->count <= p->size, "Corrupt pool count: %zu, size: %zu, %s:%i", p->count, p->size, func, line); @@ -147,17 +278,17 @@ bool packet_data_do(const struct pool *p, size_t idx, return false; } - data->cnt = 1; - data->off = 0; - data->iov = &p->pkt[idx]; - - for (i = 0; i < data->cnt; i++) { - ASSERT_WITH_MSG(!packet_check_range(p, data->iov[i].iov_base, - data->iov[i].iov_len, - func, line), - "Corrupt packet pool, %s:%i", func, line); + if (p->memory) { + packet_iov_data(p, idx, data, func, line); + } else { + data->cnt = 1; + data->off = 0; + data->iov = &p->pkt[idx]; } + ASSERT_WITH_MSG(!packet_iov_check_range(p, data, func, line), + "Corrupt packet pool, %s:%i", func, line); + return true; } -- 2.49.0