Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@
# verifies them; Git checkout and whitespace cleanup must not rewrite them.
third_party/freebsd/sys/** -text -whitespace
third_party/freebsd/COPYRIGHT -text -whitespace

# Preserve upstream patch context and email trailers verbatim.
third_party/patches/**/*.patch -text -whitespace
45 changes: 45 additions & 0 deletions cmake/ApplyPatch.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright (C) 2026 EloqData Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Apply a dependency patch without touching the index. Check the complete patch
# in either direction so reconfiguration is idempotent, while conflicts or a
# partially applied patch fail before compiling an unpatched dependency.
function(bycorf_apply_patch source_dir patch_file)
find_package(Git REQUIRED)
execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${source_dir}" apply --reverse --check
"${patch_file}"
RESULT_VARIABLE reverse_result
OUTPUT_QUIET ERROR_QUIET)
if (reverse_result EQUAL 0)
message(STATUS "Dependency patch already applied: ${patch_file}")
return()
endif()

execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${source_dir}" apply --check "${patch_file}"
RESULT_VARIABLE check_result
OUTPUT_VARIABLE check_output ERROR_VARIABLE check_error)
if (NOT check_result EQUAL 0)
message(FATAL_ERROR
"Cannot apply dependency patch ${patch_file} to ${source_dir}; "
"it is neither applicable nor fully applied.\n"
"${check_output}${check_error}")
endif()

execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${source_dir}" apply "${patch_file}"
COMMAND_ERROR_IS_FATAL ANY)
message(STATUS "Applied dependency patch: ${patch_file}")
endfunction()
10 changes: 10 additions & 0 deletions cmake/Dpdk.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ math(EXPR BYCORF_DPDK_REQUIRED_LCORES "${BYCORF_DPDK_MAX_WORKERS} + 1")
target_compile_definitions(bycorf PRIVATE
BYCORF_DPDK_MAX_WORKERS=${BYCORF_DPDK_MAX_WORKERS})
if (NOT BYCORF_DPDK_PREFIX)
include("${CMAKE_CURRENT_LIST_DIR}/ApplyPatch.cmake")
set(BYCORF_DPDK_PATCHES
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/patches/dpdk/netvsc-realloc.patch")
# Patch changes must rerun configuration, which owns the DPDK build/install.
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
${BYCORF_DPDK_PATCHES})
foreach(patch_file IN LISTS BYCORF_DPDK_PATCHES)
bycorf_apply_patch("${CMAKE_CURRENT_SOURCE_DIR}/third_party/dpdk"
"${patch_file}")
endforeach()
find_program(BYCORF_MESON_EXECUTABLE meson REQUIRED)
find_program(BYCORF_NINJA_EXECUTABLE ninja REQUIRED)
set(BYCORF_DPDK_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/dpdk-install")
Expand Down
2 changes: 1 addition & 1 deletion cmake/Freebsd.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ add_custom_command(OUTPUT "${BYCORF_FREEBSD_ARCHIVE}"
--target "${BYCORF_FREEBSD_TARGET}"
--max-workers "${BYCORF_DPDK_MAX_WORKERS}"
DEPENDS ${BYCORF_FREEBSD_INPUTS} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/build_freebsd.py"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/patches/freebsd-tcp-iss-retirement.patch"
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/patches/freebsd/freebsd-tcp-iss-retirement.patch"
COMMENT "Building the private FreeBSD IPv4/TCP stack" VERBATIM)
add_custom_target(bycorf_freebsd_build DEPENDS "${BYCORF_FREEBSD_ARCHIVE}")
add_library(bycorf_freebsd STATIC IMPORTED GLOBAL)
Expand Down
3 changes: 2 additions & 1 deletion cmake/build_freebsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def tcp_input_overlay(upstream, output, patch_tool="patch"):
incremental rebuild never applies the fix twice or edits imported files.
"""
path = upstream / "sys/netinet/tcp_input.c"
patch = Path(__file__).resolve().parent / "patches/freebsd-tcp-iss-retirement.patch"
patch = (Path(__file__).resolve().parents[1] /
"third_party/patches/freebsd/freebsd-tcp-iss-retirement.patch")
generated = output / "tcp_input.c"
generated.write_bytes(path.read_bytes())
run([patch_tool, "--batch", "--forward", "--fuzz=0", "--no-backup-if-mismatch",
Expand Down
16 changes: 0 additions & 16 deletions cmake/patches/.gitattributes

This file was deleted.

13 changes: 12 additions & 1 deletion docs/dpdk-prototype.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,21 @@ cmake -S . -B build-dpdk-net -G Ninja \
cmake --build build-dpdk-net -j4
```

Dependency patches are grouped under `third_party/patches/<dependency>/`.
The FreeBSD build applies the TCP patch from `third_party/patches/freebsd/`
to a fresh build-directory source copy, preserving the imported source digests.

Bycorf builds and installs one static DPDK, then configures SPDK with
`--with-dpdk=<that-installation>`. It never builds SPDK's nested DPDK.
CMake applies the patches in `third_party/patches/dpdk/` to the direct DPDK
submodule before compiling it. These are working-tree changes, not commits;
reconfiguration recognizes fully applied patches, and conflicting or partially
applied patches stop configuration. The netvsc patch frees the old event buffer
when expansion fails, preventing a leak before the next allocation attempt.
`BYCORF_DPDK_PREFIX` may point to an existing installation built from the same
pinned DPDK commit, with static libraries in `lib/` and headers in `include/`.
pinned DPDK commit with those patches applied, with static libraries in `lib/`
and headers in `include/`. An external prefix skips the source build and patch
application; its provider is responsible for including the fixes.
`BYCORF_DPDK_DRIVERS` defaults to `net/tap,net/ring,net/virtio`; select additional
PMDs at configuration time for other hardware. SPDK currently builds in its
submodule directory, so configure builds that use different DPDK prefixes
Expand Down
58 changes: 58 additions & 0 deletions third_party/patches/dpdk/netvsc-realloc.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
From b30b45c6b547c96ac4ee0267d4a016d68fb1c459 Mon Sep 17 00:00:00 2001
From: Chen Zhao <ch3nzhao@gmail.com>
Date: Sun, 25 Oct 2026 01:22:25 +0000
Subject: [PATCH] net/netvsc: fix event buffer leak on realloc failure

rte_realloc() failure overwrites event_buf and leaks the old allocation.
Save the old pointer and free it on failure before resetting event_sz.

Fixes: 1f2766b7ee02 ("net/netvsc: resize event buffer as needed")
Cc: sthemmin@microsoft.com
Cc: stable@dpdk.org
Signed-off-by: Chen Zhao <ch3nzhao@gmail.com>
---
.mailmap | 1 +
drivers/net/netvsc/hn_rxtx.c | 8 ++++++--
2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/.mailmap b/.mailmap
index 6d9e262cfb..deae6514dd 100644
--- a/.mailmap
+++ b/.mailmap
@@ -267,6 +267,7 @@ Charles Myers <charles.myers@spirent.com>
Charles Stoll <charles.stoll@intel.com>
Chas Williams <3chas3@gmail.com> <chas3@att.com>
Chas Williams <3chas3@gmail.com> <ciwillia@brocade.com>
+Chen Zhao <ch3nzhao@gmail.com>
Chenbo Xia <chenbox@nvidia.com> <chenbo.xia@intel.com>
Cheng Jiang <honest.jiang@foxmail.com> <cheng1.jiang@intel.com>
Cheng Liu <liucheng11@huawei.com>
diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c
index 6f536610f2..4db6c933c9 100644
--- a/drivers/net/netvsc/hn_rxtx.c
+++ b/drivers/net/netvsc/hn_rxtx.c
@@ -1131,15 +1131,19 @@ uint32_t hn_process_events(struct hn_data *hv, uint16_t queue_id,

if (unlikely(ret == -ENOBUFS)) {
/* event buffer not large enough to read ring */
+ void *old_buf = rxq->event_buf;

PMD_DRV_LOG(DEBUG,
"event buffer expansion (need %u)", len);
rxq->event_sz = len + len / 4;
- rxq->event_buf = rte_realloc(rxq->event_buf, rxq->event_sz,
+ rxq->event_buf = rte_realloc(old_buf, rxq->event_sz,
RTE_CACHE_LINE_SIZE);
if (rxq->event_buf)
goto retry;
- /* out of memory, no more events now */
+ /*
+ * out of memory, free the old buffer, no more events now
+ */
+ rte_free(old_buf);
rxq->event_sz = 0;
break;
}
--
2.43.0