diff --git a/.gitattributes b/.gitattributes index 8fac67c..11ed88f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/cmake/ApplyPatch.cmake b/cmake/ApplyPatch.cmake new file mode 100644 index 0000000..d6fcccb --- /dev/null +++ b/cmake/ApplyPatch.cmake @@ -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() diff --git a/cmake/Dpdk.cmake b/cmake/Dpdk.cmake index 3a58958..082c894 100644 --- a/cmake/Dpdk.cmake +++ b/cmake/Dpdk.cmake @@ -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") diff --git a/cmake/Freebsd.cmake b/cmake/Freebsd.cmake index 95eb13f..188cd74 100644 --- a/cmake/Freebsd.cmake +++ b/cmake/Freebsd.cmake @@ -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) diff --git a/cmake/build_freebsd.py b/cmake/build_freebsd.py index ad82fa8..b85b005 100644 --- a/cmake/build_freebsd.py +++ b/cmake/build_freebsd.py @@ -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", diff --git a/cmake/patches/.gitattributes b/cmake/patches/.gitattributes deleted file mode 100644 index 3ebfc56..0000000 --- a/cmake/patches/.gitattributes +++ /dev/null @@ -1,16 +0,0 @@ -# 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. - -# Unified diffs retain context prefixes, tabs, and blank context lines. -*.patch -whitespace diff --git a/docs/dpdk-prototype.md b/docs/dpdk-prototype.md index 08d7c8e..0a0e854 100644 --- a/docs/dpdk-prototype.md +++ b/docs/dpdk-prototype.md @@ -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//`. +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=`. 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 diff --git a/third_party/patches/dpdk/netvsc-realloc.patch b/third_party/patches/dpdk/netvsc-realloc.patch new file mode 100644 index 0000000..ea08fa3 --- /dev/null +++ b/third_party/patches/dpdk/netvsc-realloc.patch @@ -0,0 +1,58 @@ +From b30b45c6b547c96ac4ee0267d4a016d68fb1c459 Mon Sep 17 00:00:00 2001 +From: Chen Zhao +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 +--- + .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 Stoll + Chas Williams <3chas3@gmail.com> + Chas Williams <3chas3@gmail.com> ++Chen Zhao + Chenbo Xia + Cheng Jiang + Cheng Liu +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 + diff --git a/cmake/patches/freebsd-tcp-iss-retirement.patch b/third_party/patches/freebsd/freebsd-tcp-iss-retirement.patch similarity index 100% rename from cmake/patches/freebsd-tcp-iss-retirement.patch rename to third_party/patches/freebsd/freebsd-tcp-iss-retirement.patch