From 55569ba9fff8108d924abd7bb94fcafb25f9fb15898a9426c2832da6e5e136c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Mon, 4 May 2026 21:02:43 +0800 Subject: [PATCH 01/14] Stashed changes --- build.env | 12 +- devtools/create-join-token.sh | 1 - docker/ask.Dockerfile | 193 ++++++++++++++++++++++++++++ docker/download-packages.Dockerfile | 73 ++++++++++- kernel-extra.config | 6 + makefile | 57 +++++++- patches/mono-ask.mk | 87 +++++++++++++ 7 files changed, 423 insertions(+), 6 deletions(-) create mode 100644 docker/ask.Dockerfile create mode 100644 patches/mono-ask.mk diff --git a/build.env b/build.env index 970850f..ea7f3a0 100644 --- a/build.env +++ b/build.env @@ -11,7 +11,17 @@ FMC_VERSION=lf-$(LINUX_FACTORY) DPDK_VERSION=lf-$(LINUX_FACTORY) VPP_VERSION=lf-$(LINUX_FACTORY) VPP_UPSTREAM_VERSION=23.10 -MONO_ASK_VERSION=mt-$(LINUX_FACTORY) + +# ASK's deps +MONO_ASK_VERSION=mt-6.12.49-2.2.0 +LIBNFNETLINK_VERSION=1.0.2 +LIBMNL_VERSION=1.0.5 +LIBNFCT_VERSION=1.1.0 +LIBCLI_VERSION=1.10.7 +# Check the package version for Debian trixies (what ASK uses) +LIBXML2_VERSION=2.11.7 +TCLAP_VERSION=1.2.5 +LIBPCAP_VERSION=1.10.4 CRIO_VERSION=cri-o.arm64.v1.35.2 KUBE_VERSION=v1.35.3 diff --git a/devtools/create-join-token.sh b/devtools/create-join-token.sh index 977435d..bf3ea93 100755 --- a/devtools/create-join-token.sh +++ b/devtools/create-join-token.sh @@ -188,7 +188,6 @@ make cluster-config \\ MKS_CNI_PLUGIN=none EOF - if [ "$signed" != "true" ]; then echo >&2 echo "warning: cluster-info was not signed within ${WAIT_SECONDS}s." >&2 diff --git a/docker/ask.Dockerfile b/docker/ask.Dockerfile new file mode 100644 index 0000000..16c79d8 --- /dev/null +++ b/docker/ask.Dockerfile @@ -0,0 +1,193 @@ +ARG BUILD_BASE_TAG=dev +ARG DOCKER_IMAGE_ROOT=monok8s + +FROM --platform=$BUILDPLATFORM ${DOCKER_IMAGE_ROOT}/build-base:${BUILD_BASE_TAG} AS build + +# Install glibc cross-compiler for kernel and standard build dependencies +RUN apt-get update && apt-get install -y pkg-config + +WORKDIR /src + +ARG AARCH64_MUSL_CC_TAR +ARG NXP_TAR +ARG MONO_ASK_TAR +ARG LIBNFNETLINK_TAR +ARG LIBMNL_TAR +ARG LIBNFCT_TAR +ARG FMLIB_TAR +ARG FMC_TAR +ARG LIBXML2_TAR +ARG LIBPCAP_TAR +ARG LIBCLI_TAR +ARG TCLAP_TAR + +# ASK's version pins (hardcoded wget) +ARG LIBNFNETLINK_VERSION +ARG LIBNFCT_VERSION + +# MUSL Cross Compiler +COPY "${AARCH64_MUSL_CC_TAR}" ./aarch64_musl_cc.tar.gz + +# Linux kernel +COPY "${NXP_TAR}" ./kernel.tar.gz + +# Copy the ASK deps +COPY "${MONO_ASK_TAR}" ./mono-ask.tar.gz +COPY "${FMC_TAR}" ./fmc.tar.gz +COPY "${FMLIB_TAR}" ./fmlib.tar.gz +COPY "${LIBXML2_TAR}" ./libxml2.tar.xz +COPY "${LIBPCAP_TAR}" ./libpcap.tar.xz +COPY "${TCLAP_TAR}" ./tclap.tar.gz +COPY "${LIBMNL_TAR}" ./libmnl.tar.bz2 +COPY "${LIBCLI_TAR}" ./libcli.tar.gz +# Pinned version should keep version names +COPY "${LIBNFNETLINK_TAR}" ./libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2 +COPY "${LIBNFCT_TAR}" ./libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz + +# Provision the musl cross-compiler from musl.cc +RUN tar zxf "aarch64_musl_cc.tar.gz" -C /opt + +# Expose the musl compiler to the PATH +ENV PATH="/opt/aarch64-linux-musl-cross/bin:${PATH}" + +# Extract and build the dependency libraries +RUN mkdir -p ASK/sources/tarballs && \ + tar zxf "mono-ask.tar.gz" -C "ASK" --strip-components=1 && \ + mv libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2 ASK/sources/tarballs/ && \ + mv libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz ASK/sources/tarballs/ + +RUN mkdir linux && tar zxf "kernel.tar.gz" -C "linux" --strip-components=1 + +# tclap +RUN mkdir -p tclap && tar zxf "tclap.tar.gz" -C "tclap" --strip-components=1 && \ + cp -r tclap/include/tclap /opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/ && \ + rm -rf tclap + +# libxml2 +RUN mkdir -p libxml2 && tar xf "libxml2.tar.xz" -C "libxml2" --strip-components=1 && \ + cd libxml2 && \ + CC=aarch64-linux-musl-gcc ./configure --host=aarch64-linux-musl \ + --prefix=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ + --enable-static --disable-shared --without-python --without-zlib --without-lzma && \ + make -j$(nproc) && make install && \ + cd .. && rm -rf libxml2 + +# libmnl +RUN mkdir -p libmnl && tar xjf "libmnl.tar.bz2" -C "libmnl" --strip-components=1 && \ + cd libmnl && \ + CC=aarch64-linux-musl-gcc ./configure --host=aarch64-linux-musl \ + --prefix=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ + --enable-static --disable-shared && \ + make -j$(nproc) && make install && \ + cd .. && rm -rf libmnl + +# libcli +RUN mkdir -p libcli && tar zxf "libcli.tar.gz" -C "libcli" --strip-components=1 && \ + cd libcli && \ + make CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar libcli.a && \ + cp libcli.h /opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/ && \ + cp libcli.a /opt/aarch64-linux-musl-cross/aarch64-linux-musl/lib/ && \ + cd .. && rm -rf libcli + +# libpcap +RUN mkdir -p libpcap && tar xf "libpcap.tar.xz" -C "libpcap" --strip-components=1 && \ + cd libpcap && \ + CC=aarch64-linux-musl-gcc ./configure --host=aarch64-linux-musl \ + --prefix=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ + --with-pcap=linux --enable-static --disable-shared \ + --disable-usb --disable-netmap --disable-bluetooth --disable-dbus && \ + make -j$(nproc) && make install && \ + cd .. && rm -rf libpcap + +RUN git config --global user.email "monok8s@localhost" && \ + git config --global user.name "monok8s authors" && \ + git config --global --add safe.directory '*' + +# cd .. && \ +# mkdir -p fmc && \ +# tar zxf "fmc.tar.gz" -C "fmc" --strip-components=1 && \ +# # Handle fmc: Initialize dummy repo, patch, and build \ +# cd fmc && git init -q && git add -A && git commit -q -m "base" && \ +# git apply /src/ASK/patches/fmc/01-mono-ask-extensions.patch \ +# make CC="aarch64-linux-musl-gcc -static" CXX="aarch64-linux-musl-g++ -static" AR=aarch64-linux-musl-ar \ +# MACHINE=ls1046 \ +# FMD_USPACE_HEADER_PATH=../fmlib/include/fmd \ +# FMD_USPACE_LIB_PATH=../fmlib \ +# LIBXML2_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/libxml2 \ +# TCLAP_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include + +# # -- libfci ---------------------------------------------------------------- +# +# $(S)/libfci: +# @echo "==> libfci: build" +# $(MAKE) -C $(LIBFCI_DIR) CC=$(CC) AR=$(AR) +# @touch $@ +# +# # -- libnfnetlink (patched) ------------------------------------------------ +# +# $(S)/libnfnetlink: +# @echo "==> libnfnetlink: fetch + patch + build" +# mkdir -p $(SRCDIR)/tarballs +# [ -f $(SRCDIR)/tarballs/libnfnetlink-$(LIBNFNETLINK_VER).tar.bz2 ] || \ +# wget -q -P $(SRCDIR)/tarballs $(LIBNFNETLINK_URL) +# rm -rf $(SRCDIR)/libnfnetlink-$(LIBNFNETLINK_VER) +# tar xf $(SRCDIR)/tarballs/libnfnetlink-$(LIBNFNETLINK_VER).tar.bz2 -C $(SRCDIR) +# cd $(SRCDIR)/libnfnetlink-$(LIBNFNETLINK_VER) && \ +# git init -q && git add -A && git commit -q -m "upstream" && \ +# git apply $(PATCHES)/libnfnetlink/01-nxp-ask-nonblocking-heap-buffer.patch && \ +# ./configure --host=$(HOST) --prefix=$(SYSROOT) --enable-static --disable-shared -q && \ +# $(MAKE) -j$$(nproc) -s && $(MAKE) install -s +# @touch $@ +# +# # -- libnetfilter_conntrack (patched) -------------------------------------- +# +# $(S)/libnfct: $(S)/libnfnetlink +# @echo "==> libnetfilter_conntrack: fetch + patch + build" +# mkdir -p $(SRCDIR)/tarballs +# [ -f $(SRCDIR)/tarballs/libnetfilter_conntrack-$(LIBNFCT_VER).tar.xz ] || \ +# wget -q -P $(SRCDIR)/tarballs $(LIBNFCT_URL) +# rm -rf $(SRCDIR)/libnetfilter_conntrack-$(LIBNFCT_VER) +# tar xf $(SRCDIR)/tarballs/libnetfilter_conntrack-$(LIBNFCT_VER).tar.xz -C $(SRCDIR) +# cd $(SRCDIR)/libnetfilter_conntrack-$(LIBNFCT_VER) && \ +# git init -q && git add -A && git commit -q -m "upstream" && \ +# git apply $(PATCHES)/libnetfilter-conntrack/01-nxp-ask-comcerto-fp-extensions.patch && \ +# PKG_CONFIG_PATH=$(SYSROOT)/lib/pkgconfig \ +# ./configure --host=$(HOST) --prefix=$(SYSROOT) --enable-static --disable-shared -q \ +# CFLAGS="-I$(SYSROOT)/include" LDFLAGS="-L$(SYSROOT)/lib" && \ +# $(MAKE) -j$$(nproc) -s && $(MAKE) install -s +# @touch $@ +# +# modules: cdx fci auto_bridge +# +# cdx: +# $(MAKE) -C cdx $(CDX_ARGS) modules +# +# fci: cdx +# $(MAKE) -C fci $(FCI_ARGS) modules +# +# auto_bridge: +# $(MAKE) -C auto_bridge $(ABM_ARGS) +# +# # ============================================================================ +# # Userspace binaries +# # ============================================================================ +# +# userspace: fmc cmm dpa_app +# +# fmc: $(S)/fmc +# @true +# +# cmm: $(S)/libfci $(S)/libnfct +# $(MAKE) -C cmm CC=$(CC) \ +# LIBFCI_DIR=$(LIBFCI_DIR) \ +# ABM_DIR=$(ABM_DIR) \ +# SYSROOT=$(SYSROOT) +# +# dpa_app: $(S)/fmc +# $(MAKE) -C dpa_app CC=$(CC) \ +# CFLAGS="-DDPAA_DEBUG_ENABLE -DNCSW_LINUX \ +# -I$(FMC_DIR) -I$(CURDIR)/cdx \ +# -I$(FMLIB_DIR)/include/fmd \ +# -I$(FMLIB_DIR)/include/fmd/Peripherals \ +# -I$(FMLIB_DIR)/include/fmd/integrations" \ +# LDFLAGS="-lpthread -lcli -L$(FMC_DIR) -lfmc -L$(FMLIB_DIR) -lfm -lstdc++ -lxml2 -lm" diff --git a/docker/download-packages.Dockerfile b/docker/download-packages.Dockerfile index d423894..94919b1 100644 --- a/docker/download-packages.Dockerfile +++ b/docker/download-packages.Dockerfile @@ -70,6 +70,68 @@ WORKDIR /out/nxp/vpp RUN curl -fL --retry 3 -o "${VPP_VERSION}.tar.gz" \ "https://github.com/nxp-qoriq/vpp/archive/refs/tags/${VPP_VERSION}.tar.gz" +# ---- MUSL CC ---- +FROM base AS aarch64_musl_cc +WORKDIR /out +RUN curl -fL --retry 3 -o "aarch64-linux-musl-cross.tgz" \ + "https://musl.cc/aarch64-linux-musl-cross.tgz" + +# ---- ASK ---- +FROM base AS mono_ask +ARG MONO_ASK_VERSION +WORKDIR /out/ask +RUN curl -fL --retry 3 -o "${MONO_ASK_VERSION}.tar.gz" \ + "https://github.com/we-are-mono/ASK/archive/refs/tags/${MONO_ASK_VERSION}.tar.gz" + +# ---- libnfnetlink ---- +FROM base AS libnfnetlink +ARG LIBNFNETLINK_VERSION +WORKDIR /out/ask/libnfnetlink +RUN curl -fL --retry 3 -o "${LIBNFNETLINK_VERSION}.tar.bz2" \ + "https://www.netfilter.org/projects/libnfnetlink/files/libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2" + +# ---- libnfct ---- +FROM base AS libnfct +ARG LIBNFCT_VERSION +WORKDIR /out/ask/libnfct +RUN curl -fL --retry 3 -o "${LIBNFCT_VERSION}.tar.xz" \ + "https://www.netfilter.org/projects/libnetfilter_conntrack/files/libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz" + +# ---- libmnl ---- +FROM base AS libmnl +ARG LIBMNL_VERSION +WORKDIR /out/ask/libmnl +RUN curl -fL --retry 3 -o "${LIBMNL_VERSION}.tar.bz2" \ + "https://www.netfilter.org/projects/libmnl/files/libmnl-${LIBMNL_VERSION}.tar.bz2" + +# ---- tclap ---- +FROM base AS tclap +ARG TCLAP_VERSION +WORKDIR /out/ask/tclap +RUN curl -fL --retry 3 -o "${TCLAP_VERSION}.tar.gz" \ + "https://sourceforge.net/projects/tclap/files/tclap-${TCLAP_VERSION}.tar.gz" + +# ---- libxml2 ---- +FROM base AS libxml2 +ARG LIBXML2_VERSION +WORKDIR /out/ask/libxml2 +RUN curl -fL --retry 3 -o "${LIBXML2_VERSION}.tar.xz" \ + "https://download.gnome.org/sources/libxml2/2.11/libxml2-${LIBXML2_VERSION}.tar.xz" + +# ---- libcli ---- +FROM base AS libcli +ARG LIBCLI_VERSION +WORKDIR /out/ask/libcli +RUN curl -fL --retry 3 -o "${LIBCLI_VERSION}.tar.gz" \ + "https://github.com/dparrish/libcli/archive/refs/tags/V${LIBCLI_VERSION}.tar.gz" + +# ---- libpcap ---- +FROM base AS libpcap +ARG LIBPCAP_VERSION +WORKDIR /out/ask/libpcap +RUN curl -fL --retry 3 -o "${LIBPCAP_VERSION}.tar.xz" \ + "https://www.tcpdump.org/release/libpcap-${LIBPCAP_VERSION}.tar.xz" + # ---- alpine rootfs ---- FROM base AS alpine_rootfs ARG ALPINE_SERIES @@ -101,9 +163,18 @@ COPY --from=kubectl /out/ / COPY --from=busybox /out/ / COPY --from=e2fsprogs /out/ / COPY --from=dpdk /out/ / +COPY --from=aarch64_musl_cc /out/ / +COPY --from=mono_ask /out/ / +COPY --from=vpp /out/ / COPY --from=fmlib /out/ / COPY --from=fmc /out/ / -COPY --from=vpp /out/ / +COPY --from=libnfnetlink /out/ / +COPY --from=libnfct /out/ / +COPY --from=libmnl /out/ / +COPY --from=libcli /out/ / +COPY --from=libpcap /out/ / +COPY --from=libxml2 /out/ / +COPY --from=tclap /out/ / COPY --from=alpine_rootfs /out/ / COPY --from=nxp_linux /out/ / COPY --from=crio /out/ / diff --git a/kernel-extra.config b/kernel-extra.config index d9d7f04..e221d2c 100644 --- a/kernel-extra.config +++ b/kernel-extra.config @@ -247,3 +247,9 @@ CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_TASKSTATS=y CONFIG_TASK_XACCT=y + +############################################################################### +# NXP +############################################################################### + +CONFIG_CDX_BUS=y diff --git a/makefile b/makefile index 7c7187e..064ebc9 100644 --- a/makefile +++ b/makefile @@ -11,12 +11,24 @@ E2FSPROGS_TAR := $(PACKAGES_DIR)/e2fsprogs-$(E2FSPROGS_VERSION).tar.gz BUSYBOX_TAR := $(PACKAGES_DIR)/busybox-$(BUSYBOX_VERSION).tar.gz ALPINE_TAR := $(PACKAGES_DIR)/alpine-minirootfs-$(ALPINE_VER)-$(ALPINE_ARCH).tar.gz NXP_TAR := $(PACKAGES_DIR)/nxp/kernel/$(NXP_VERSION).tar.gz -FMLIB_TAR := $(PACKAGES_DIR)/nxp/fmlib/$(FMLIB_VERSION).tar.gz -FMC_TAR := $(PACKAGES_DIR)/nxp/fmc/$(FMC_VERSION).tar.gz VPP_TAR := $(PACKAGES_DIR)/nxp/vpp/$(VPP_VERSION).tar.gz DPDK_TAR := $(PACKAGES_DIR)/nxp/dpdk/$(DPDK_VERSION).tar.gz CRIO_TAR := $(PACKAGES_DIR)/$(CRIO_VERSION).tar.gz +AARCH64_MUSL_CC_TAR := $(PACKAGES_DIR)/aarch64-linux-musl-cross.tgz + +# ASK-specific +MONO_ASK_TAR := $(PACKAGES_DIR)/ask/$(MONO_ASK_VERSION).tar.gz +FMLIB_TAR := $(PACKAGES_DIR)/nxp/fmlib/$(FMLIB_VERSION).tar.gz +FMC_TAR := $(PACKAGES_DIR)/nxp/fmc/$(FMC_VERSION).tar.gz +LIBNFNETLINK_TAR := $(PACKAGES_DIR)/ask/libnfnetlink/$(LIBNFNETLINK_VERSION).tar.bz2 +LIBNFCT_TAR := $(PACKAGES_DIR)/ask/libnfct/$(LIBNFCT_VERSION).tar.xz +LIBMNL_TAR := $(PACKAGES_DIR)/ask/libmnl/$(LIBMNL_VERSION).tar.bz2 +LIBCLI_TAR := $(PACKAGES_DIR)/ask/libcli/$(LIBCLI_VERSION).tar.gz +TCLAP_TAR := $(PACKAGES_DIR)/ask/tclap/$(TCLAP_VERSION).tar.gz +LIBXML2_TAR := $(PACKAGES_DIR)/ask/libxml2/$(LIBXML2_VERSION).tar.xz +LIBPCAP_TAR := $(PACKAGES_DIR)/ask/libpcap/$(LIBPCAP_VERSION).tar.xz + # Kubernetes components KUBELET_BIN := $(PACKAGES_DIR)/kubernetes/kubelet-$(KUBE_VERSION) KUBEADM_BIN := $(PACKAGES_DIR)/kubernetes/kubeadm-$(KUBE_VERSION) @@ -118,11 +130,20 @@ $(DOWNLOAD_PACKAGES_STAMP): docker/download-packages.Dockerfile build.env makefi --build-arg KUBE_VERSION=$(KUBE_VERSION) \ --build-arg ARCH=$(ARCH) \ --build-arg BUSYBOX_VERSION=$(BUSYBOX_VERSION) \ + --build-arg DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \ --build-arg E2FSPROGS_VERSION=$(E2FSPROGS_VERSION) \ --build-arg DPDK_VERSION=$(DPDK_VERSION) \ --build-arg FMLIB_VERSION=$(FMLIB_VERSION) \ --build-arg FMC_VERSION=$(FMC_VERSION) \ --build-arg VPP_VERSION=$(VPP_VERSION) \ + --build-arg MONO_ASK_VERSION=$(MONO_ASK_VERSION) \ + --build-arg LIBNFNETLINK_VERSION=$(LIBNFNETLINK_VERSION) \ + --build-arg LIBMNL_VERSION=$(LIBMNL_VERSION) \ + --build-arg LIBNFCT_VERSION=$(LIBNFCT_VERSION) \ + --build-arg LIBCLI_VERSION=$(LIBCLI_VERSION) \ + --build-arg LIBXML2_VERSION=$(LIBXML2_VERSION) \ + --build-arg LIBPCAP_VERSION=$(LIBPCAP_VERSION) \ + --build-arg TCLAP_VERSION=$(TCLAP_VERSION) \ --build-arg ALPINE_SERIES=$(ALPINE_SERIES) \ --build-arg ALPINE_ARCH=$(ALPINE_ARCH) \ --build-arg ALPINE_VER=$(ALPINE_VER) \ @@ -183,6 +204,36 @@ $(INITRAMFS): $(INITRAMFS_DEPS) $(DOWNLOAD_PACKAGES_STAMP) | $(OUT_DIR) $(CLITOOLS_BIN): $(CLITOOLS_SRCS) $(MAKE) -C clitools build-local VERSION="$(TAG)" +ASK: $(ASK_TAR) $(LIBNFCT_TAR) $(LIBNFNETLINK_TAR) $(TCLAP_TAR) $(LIBXML2_TAR) | $(OUT_DIR) + @echo "Building NXP ASK components and Kernel..." + rm -rf "$(OUT_DIR)/ASK" + mkdir -p "$(OUT_DIR)/ASK" + @build_base_tag=$$(docker image inspect \ + --format '{{.Id}}' \ + $(DOCKER_IMAGE_ROOT)/build-base:$(TAG) \ + | cut -d':' -f2 \ + | cut -c -8); \ + docker build \ + -f docker/ask.Dockerfile \ + --platform linux/amd64 \ + --build-arg DOCKER_IMAGE_ROOT=$(DOCKER_IMAGE_ROOT) \ + --build-arg BUILD_BASE_TAG=$$build_base_tag \ + --build-arg MONO_ASK_TAR=$(MONO_ASK_TAR) \ + --build-arg AARCH64_MUSL_CC_TAR=$(AARCH64_MUSL_CC_TAR) \ + --build-arg NXP_TAR=$(NXP_TAR) \ + --build-arg FMLIB_TAR=$(FMLIB_TAR) \ + --build-arg FMC_TAR=$(FMC_TAR) \ + --build-arg LIBNFNETLINK_TAR=$(LIBNFNETLINK_TAR) \ + --build-arg LIBMNL_TAR=$(LIBMNL_TAR) \ + --build-arg LIBNFCT_TAR=$(LIBNFCT_TAR) \ + --build-arg LIBXML2_TAR=$(LIBXML2_TAR) \ + --build-arg LIBPCAP_TAR=$(LIBPCAP_TAR) \ + --build-arg TCLAP_TAR=$(TCLAP_TAR) \ + --build-arg LIBCLI_TAR=$(LIBCLI_TAR) \ + --build-arg LIBNFNETLINK_VERSION=$(LIBNFNETLINK_VERSION) \ + --build-arg LIBNFCT_VERSION=$(LIBNFCT_VERSION) \ + --output type=local,dest=./$(OUT_DIR)/ASK . + vpp: $(BUILD_BASE_STAMP) $(VPP_TAR) $(DPDK_TAR) $(FMLIB_TAR) $(FMC_TAR) $(NXP_TAR) @build_base_tag=$$(docker image inspect \ --format '{{.Id}}' \ @@ -339,5 +390,5 @@ pkgclean: rm -rf $(PACKAGES_DIR) .PHONY: release kernel initramfs itb build-base clitools clean distclean pkgclean \ - vpp \ + vpp ASK \ cluster-config cluster-defconfig cluster-print diff --git a/patches/mono-ask.mk b/patches/mono-ask.mk new file mode 100644 index 0000000..39ddb77 --- /dev/null +++ b/patches/mono-ask.mk @@ -0,0 +1,87 @@ +# mono-ask.mk +# Custom wrapper to build the NXP ASK for the monok8s Alpine/musl ecosystem + +# Define default paths and cross-compilers +KDIR?= /src/linux +ASK_DIR?= $(CURDIR) +ARCH?= arm64 +GNU_CROSS?= aarch64-linux-gnu- +MUSL_HOST?= aarch64-linux-musl + +STAMPS_DIR := $(ASK_DIR)/sources/.stamps +FMLIB_DIR := $(ASK_DIR)/sources/fmlib +FMC_BASE := $(ASK_DIR)/sources/fmc +FMC_DIR := $(FMC_BASE)/source + +SYSROOT_PATH := /opt/aarch64-linux-musl-cross/aarch64-linux-musl + +.PHONY: prepare-kernel build-kernel modules userspace dist + +prepare-preloaded-sources: + @echo "--> Initializing dummy git repos and building preloaded fmlib/fmc..." + mkdir -p $(STAMPS_DIR) + + git config --global user.email "monok8s@localhost" + git config --global user.name "monok8s authors" + git config --global --add safe.directory '*' + + # Inject libmnl.pc into the vendor's isolated sysroot to satisfy pkg-config + mkdir -p $(ASK_DIR)/sources/sysroot/lib/pkgconfig + cp -a $(SYSROOT_PATH)/lib/pkgconfig/libmnl.pc $(ASK_DIR)/sources/sysroot/lib/pkgconfig/ + + # Handle fmlib: Initialize dummy repo, patch, and build + cd $(FMLIB_DIR) && git init -q && git add -A && git commit -q -m "base" + cd $(FMLIB_DIR) && git apply $(ASK_DIR)/patches/fmlib/01-mono-ask-extensions.patch + $(MAKE) -C $(FMLIB_DIR) CROSS_COMPILE=$(MUSL_HOST)- KERNEL_SRC=$(KDIR) libfm-arm.a + ln -sf libfm-arm.a $(FMLIB_DIR)/libfm.a + touch $(STAMPS_DIR)/fmlib + + # Handle fmc: Initialize dummy repo, patch, and build + cd $(FMC_BASE) && git init -q && git add -A && git commit -q -m "base" + cd $(FMC_BASE) && git apply $(ASK_DIR)/patches/fmc/01-mono-ask-extensions.patch + $(MAKE) -C $(FMC_DIR) CC="$(MUSL_HOST)-gcc -static" CXX="$(MUSL_HOST)-g++ -static" AR=$(MUSL_HOST)-ar \ + MACHINE=ls1046 \ + FMD_USPACE_HEADER_PATH=$(FMLIB_DIR)/include/fmd \ + FMD_USPACE_LIB_PATH=$(FMLIB_DIR) \ + LIBXML2_HEADER_PATH=$(SYSROOT_PATH)/include/libxml2 \ + TCLAP_HEADER_PATH=$(SYSROOT_PATH)/include + touch $(STAMPS_DIR)/fmc + +# 1. Patch the kernel and merge our custom Kubernetes configuration +prepare-kernel: + @echo "--> Patching the Linux kernel with NXP DPAA extensions..." + cd $(KDIR) && patch -p1 < $(ASK_DIR)/patches/kernel/002-mono-gateway-ask-kernel_linux_6_12.patch + @echo "--> Merging NXP defconfig with Kubernetes extra config..." + cp $(ASK_DIR)/config/kernel/defconfig $(KDIR)/.config + cd $(KDIR) && ./scripts/kconfig/merge_config.sh -m .config /src/kernel-extra.config + $(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(GNU_CROSS) olddefconfig + /src/ensure-kconfig.sh $(KDIR)/.config /src/kernel-extra.config + +# 2. Build the kernel tree (mandatory before out-of-tree modules can be built) +build-kernel: prepare-kernel + @echo "--> Building the Linux kernel natively..." + # Replace "dtbs" with the exact path to your target dtb + $(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(GNU_CROSS) -j$$(nproc) \ + Image modules freescale/mono-gateway-dk-sdk.dtb + +# 3. Build the ASK out-of-tree modules using the vendor Makefile +modules: build-kernel + @echo "--> Building ASK out-of-tree modules..." + $(MAKE) -f Makefile modules KDIR=$(KDIR) CROSS_COMPILE=$(GNU_CROSS) ARCH=$(ARCH) + +# 4. Build the ASK userspace daemons using the musl cross-compiler +userspace: prepare-preloaded-sources + @echo "--> Building ASK sources and libraries..." + $(MAKE) -f Makefile sources KDIR=$(KDIR) CROSS_COMPILE=$(MUSL_HOST)- ARCH=$(ARCH) HOST=$(MUSL_HOST) + + @echo "--> Stripping -Werror from vendor Makefiles for modern GCC compatibility..." + sed -i 's/-Werror//g' $(ASK_DIR)/cmm/Makefile + sed -i 's/-Werror//g' $(ASK_DIR)/dpa_app/Makefile + + @echo "--> Building ASK userspace executables statically..." + $(MAKE) -f Makefile userspace KDIR=$(KDIR) CROSS_COMPILE=$(MUSL_HOST)- ARCH=$(ARCH) HOST=$(MUSL_HOST) CC='"$(MUSL_HOST)-gcc -static"' CXX='"$(MUSL_HOST)-g++ -static"' + +# 5. Extract artifacts +dist: + @echo "--> Staging artifacts..." + $(MAKE) -f Makefile dist KDIR=$(KDIR) CROSS_COMPILE=$(GNU_CROSS) ARCH=$(ARCH) From 9c6fb5194ea9ab384301252d9b3f4d3d0ca4b9c1eb28727d9fd63ed95a483e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sat, 9 May 2026 05:23:55 +0800 Subject: [PATCH 02/14] port ASK kernel patchset to 6.18 application state --- docker/ask.Dockerfile | 240 ++-- kernel-extra.config | 2 +- ...1-cdx-adapt-dpa-wifi-a050385-to-6.18.patch | 76 ++ ...net__freescale__sdk_dpaa__dpaa_eth.h.patch | 71 ++ ...__freescale__sdk_dpaa__dpaa_eth_sg.c.patch | 1113 +++++++++++++++++ ...062-drivers__net__ppp__ppp_generic.c.patch | 30 + ...ers__staging__fsl_qbman__qman_high.c.patch | 371 ++++++ .../0071-include__linux__if_bridge.h.patch | 28 + .../kernel/0078-include__net__xfrm.h.patch | 76 ++ ...ux__netfilter__nfnetlink_conntrack.h.patch | 36 + .../0100-net__bridge__br_private.h.patch | 28 + .../ask/kernel/0103-net__core__dev.c.patch | 131 ++ .../kernel/0108-net__ipv4__ip_output.c.patch | 79 ++ .../kernel/0112-net__ipv6__ip6_output.c.patch | 73 ++ .../0115-net__ipv6__output_core.c.patch | 38 + .../ask/kernel/0119-net__key__af_key.c.patch | 949 ++++++++++++++ ...t__netfilter__nf_conntrack_netlink.c.patch | 288 +++++ .../kernel/0129-net__wireless__Kconfig.patch | 21 + .../ask/kernel/0131-net__xfrm__Makefile.patch | 9 + .../0136-net__xfrm__xfrm_policy.c.patch | 163 +++ .../kernel/0137-net__xfrm__xfrm_state.c.patch | 291 +++++ patches/split-kernel-patch.sh | 249 ++++ 22 files changed, 4270 insertions(+), 92 deletions(-) create mode 100644 patches/ask/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch create mode 100644 patches/ask/kernel/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch create mode 100644 patches/ask/kernel/0009-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth_sg.c.patch create mode 100644 patches/ask/kernel/0062-drivers__net__ppp__ppp_generic.c.patch create mode 100644 patches/ask/kernel/0068-drivers__staging__fsl_qbman__qman_high.c.patch create mode 100644 patches/ask/kernel/0071-include__linux__if_bridge.h.patch create mode 100644 patches/ask/kernel/0078-include__net__xfrm.h.patch create mode 100644 patches/ask/kernel/0086-include__uapi__linux__netfilter__nfnetlink_conntrack.h.patch create mode 100644 patches/ask/kernel/0100-net__bridge__br_private.h.patch create mode 100644 patches/ask/kernel/0103-net__core__dev.c.patch create mode 100644 patches/ask/kernel/0108-net__ipv4__ip_output.c.patch create mode 100644 patches/ask/kernel/0112-net__ipv6__ip6_output.c.patch create mode 100644 patches/ask/kernel/0115-net__ipv6__output_core.c.patch create mode 100644 patches/ask/kernel/0119-net__key__af_key.c.patch create mode 100644 patches/ask/kernel/0124-net__netfilter__nf_conntrack_netlink.c.patch create mode 100644 patches/ask/kernel/0129-net__wireless__Kconfig.patch create mode 100644 patches/ask/kernel/0131-net__xfrm__Makefile.patch create mode 100644 patches/ask/kernel/0136-net__xfrm__xfrm_policy.c.patch create mode 100644 patches/ask/kernel/0137-net__xfrm__xfrm_state.c.patch create mode 100644 patches/split-kernel-patch.sh diff --git a/docker/ask.Dockerfile b/docker/ask.Dockerfile index 16c79d8..4b2dced 100644 --- a/docker/ask.Dockerfile +++ b/docker/ask.Dockerfile @@ -6,6 +6,10 @@ FROM --platform=$BUILDPLATFORM ${DOCKER_IMAGE_ROOT}/build-base:${BUILD_BASE_TAG} # Install glibc cross-compiler for kernel and standard build dependencies RUN apt-get update && apt-get install -y pkg-config +RUN git config --global user.email "monok8s@localhost" && \ + git config --global user.name "monok8s authors" && \ + git config --global --add safe.directory '*' + WORKDIR /src ARG AARCH64_MUSL_CC_TAR @@ -56,7 +60,19 @@ RUN mkdir -p ASK/sources/tarballs && \ mv libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2 ASK/sources/tarballs/ && \ mv libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz ASK/sources/tarballs/ -RUN mkdir linux && tar zxf "kernel.tar.gz" -C "linux" --strip-components=1 +RUN mkdir linux && tar zxf "kernel.tar.gz" -C "linux" --strip-components=1 && \ + mkdir -p /src/ASK/patches/kernel/updated-patch + +# ASK's Kernel patches +COPY patches/split-kernel-patch.sh /src/split-kernel-patch.sh +COPY patches/ask/kernel/*.patch /src/ASK/patches/kernel/updated-patch/ + +RUN chmod +x /src/split-kernel-patch.sh && \ + PATCH_FILE="/src/ASK/patches/kernel/002-mono-gateway-ask-kernel_linux_6_12.patch" \ + LINUX_DIR="/src/linux" \ + OUT_DIR="/src/ASK/patches/kernel/split-002" \ + /src/split-kernel-patch.sh split && \ + /src/split-kernel-patch.sh apply # tclap RUN mkdir -p tclap && tar zxf "tclap.tar.gz" -C "tclap" --strip-components=1 && \ @@ -99,95 +115,137 @@ RUN mkdir -p libpcap && tar xf "libpcap.tar.xz" -C "libpcap" --strip-components= make -j$(nproc) && make install && \ cd .. && rm -rf libpcap -RUN git config --global user.email "monok8s@localhost" && \ - git config --global user.name "monok8s authors" && \ - git config --global --add safe.directory '*' +# fmlib, fmc +RUN mkdir fmlib && \ + tar zxf "fmlib.tar.gz" -C "fmlib" --strip-components=1 && \ + cd fmlib && git init -q && git add -A && git commit -q -m "base" && \ + git apply /src/ASK/patches/fmlib/01-mono-ask-extensions.patch && \ + make CROSS_COMPILE=aarch64-linux-musl- KERNEL_SRC=../linux libfm-arm.a && \ + ln -sf libfm-arm.a libfm.a && \ + cd ../ && \ + mkdir -p fmc && \ + tar zxf "fmc.tar.gz" -C "fmc" --strip-components=1 && \ + # Handle fmc: Initialize dummy repo, patch, and build \ + cd fmc && git init -q && git add -A && git commit -q -m "base" && \ + git apply /src/ASK/patches/fmc/01-mono-ask-extensions.patch && \ + make -C "source" CC="aarch64-linux-musl-gcc -static" CXX="aarch64-linux-musl-g++ -static" AR=aarch64-linux-musl-ar \ + MACHINE=ls1046 \ + FMD_USPACE_HEADER_PATH=../../fmlib/include/fmd \ + FMD_USPACE_LIB_PATH=../../fmlib \ + LIBXML2_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/libxml2 \ + TCLAP_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include -# cd .. && \ -# mkdir -p fmc && \ -# tar zxf "fmc.tar.gz" -C "fmc" --strip-components=1 && \ -# # Handle fmc: Initialize dummy repo, patch, and build \ -# cd fmc && git init -q && git add -A && git commit -q -m "base" && \ -# git apply /src/ASK/patches/fmc/01-mono-ask-extensions.patch \ -# make CC="aarch64-linux-musl-gcc -static" CXX="aarch64-linux-musl-g++ -static" AR=aarch64-linux-musl-ar \ -# MACHINE=ls1046 \ -# FMD_USPACE_HEADER_PATH=../fmlib/include/fmd \ -# FMD_USPACE_LIB_PATH=../fmlib \ -# LIBXML2_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/libxml2 \ -# TCLAP_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include +# Common paths / flags for the remaining ASK build. +# Keep userspace fully static against the musl sysroot. +ENV ASK_DIR=/src/ASK \ + KERNEL_DIR=/src/linux \ + SYSROOT=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ + HOST=aarch64-linux-musl \ + CROSS_COMPILE=aarch64-linux-musl- \ + ARCH=arm64 \ + PLATFORM=LS1043A -# # -- libfci ---------------------------------------------------------------- -# -# $(S)/libfci: -# @echo "==> libfci: build" -# $(MAKE) -C $(LIBFCI_DIR) CC=$(CC) AR=$(AR) -# @touch $@ -# -# # -- libnfnetlink (patched) ------------------------------------------------ -# -# $(S)/libnfnetlink: -# @echo "==> libnfnetlink: fetch + patch + build" -# mkdir -p $(SRCDIR)/tarballs -# [ -f $(SRCDIR)/tarballs/libnfnetlink-$(LIBNFNETLINK_VER).tar.bz2 ] || \ -# wget -q -P $(SRCDIR)/tarballs $(LIBNFNETLINK_URL) -# rm -rf $(SRCDIR)/libnfnetlink-$(LIBNFNETLINK_VER) -# tar xf $(SRCDIR)/tarballs/libnfnetlink-$(LIBNFNETLINK_VER).tar.bz2 -C $(SRCDIR) -# cd $(SRCDIR)/libnfnetlink-$(LIBNFNETLINK_VER) && \ -# git init -q && git add -A && git commit -q -m "upstream" && \ -# git apply $(PATCHES)/libnfnetlink/01-nxp-ask-nonblocking-heap-buffer.patch && \ -# ./configure --host=$(HOST) --prefix=$(SYSROOT) --enable-static --disable-shared -q && \ -# $(MAKE) -j$$(nproc) -s && $(MAKE) install -s -# @touch $@ -# -# # -- libnetfilter_conntrack (patched) -------------------------------------- -# -# $(S)/libnfct: $(S)/libnfnetlink -# @echo "==> libnetfilter_conntrack: fetch + patch + build" -# mkdir -p $(SRCDIR)/tarballs -# [ -f $(SRCDIR)/tarballs/libnetfilter_conntrack-$(LIBNFCT_VER).tar.xz ] || \ -# wget -q -P $(SRCDIR)/tarballs $(LIBNFCT_URL) -# rm -rf $(SRCDIR)/libnetfilter_conntrack-$(LIBNFCT_VER) -# tar xf $(SRCDIR)/tarballs/libnetfilter_conntrack-$(LIBNFCT_VER).tar.xz -C $(SRCDIR) -# cd $(SRCDIR)/libnetfilter_conntrack-$(LIBNFCT_VER) && \ -# git init -q && git add -A && git commit -q -m "upstream" && \ -# git apply $(PATCHES)/libnetfilter-conntrack/01-nxp-ask-comcerto-fp-extensions.patch && \ -# PKG_CONFIG_PATH=$(SYSROOT)/lib/pkgconfig \ -# ./configure --host=$(HOST) --prefix=$(SYSROOT) --enable-static --disable-shared -q \ -# CFLAGS="-I$(SYSROOT)/include" LDFLAGS="-L$(SYSROOT)/lib" && \ -# $(MAKE) -j$$(nproc) -s && $(MAKE) install -s -# @touch $@ -# -# modules: cdx fci auto_bridge -# -# cdx: -# $(MAKE) -C cdx $(CDX_ARGS) modules -# -# fci: cdx -# $(MAKE) -C fci $(FCI_ARGS) modules -# -# auto_bridge: -# $(MAKE) -C auto_bridge $(ABM_ARGS) -# -# # ============================================================================ -# # Userspace binaries -# # ============================================================================ -# -# userspace: fmc cmm dpa_app -# -# fmc: $(S)/fmc -# @true -# -# cmm: $(S)/libfci $(S)/libnfct -# $(MAKE) -C cmm CC=$(CC) \ -# LIBFCI_DIR=$(LIBFCI_DIR) \ -# ABM_DIR=$(ABM_DIR) \ -# SYSROOT=$(SYSROOT) -# -# dpa_app: $(S)/fmc -# $(MAKE) -C dpa_app CC=$(CC) \ -# CFLAGS="-DDPAA_DEBUG_ENABLE -DNCSW_LINUX \ -# -I$(FMC_DIR) -I$(CURDIR)/cdx \ -# -I$(FMLIB_DIR)/include/fmd \ -# -I$(FMLIB_DIR)/include/fmd/Peripherals \ -# -I$(FMLIB_DIR)/include/fmd/integrations" \ -# LDFLAGS="-lpthread -lcli -L$(FMC_DIR) -lfmc -L$(FMLIB_DIR) -lfm -lstdc++ -lxml2 -lm" +# Build patched libnfnetlink + libnetfilter_conntrack into the musl sysroot. +# These are needed by cmm through pkg-config. +RUN mkdir -p "${ASK_DIR}/sources" && \ + mkdir -p libnfnetlink && \ + tar xjf "${ASK_DIR}/sources/tarballs/libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2" \ + -C libnfnetlink --strip-components=1 && \ + cd libnfnetlink && \ + git init -q && git add -A && git commit -q -m "upstream" && \ + git apply "${ASK_DIR}/patches/libnfnetlink/01-nxp-ask-nonblocking-heap-buffer.patch" && \ + CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar RANLIB=aarch64-linux-musl-ranlib \ + ./configure --host="${HOST}" --prefix="${SYSROOT}" \ + --enable-static --disable-shared && \ + make -j$(nproc) && make install && \ + cd /src && rm -rf libnfnetlink && \ + mkdir -p libnetfilter_conntrack && \ + tar xf "${ASK_DIR}/sources/tarballs/libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz" \ + -C libnetfilter_conntrack --strip-components=1 && \ + cd libnetfilter_conntrack && \ + git init -q && git add -A && git commit -q -m "upstream" && \ + git apply "${ASK_DIR}/patches/libnetfilter-conntrack/01-nxp-ask-comcerto-fp-extensions.patch" && \ + PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" \ + CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar RANLIB=aarch64-linux-musl-ranlib \ + ./configure --host="${HOST}" --prefix="${SYSROOT}" \ + --enable-static --disable-shared \ + CFLAGS="-I${SYSROOT}/include" \ + LDFLAGS="-L${SYSROOT}/lib" && \ + make -j$(nproc) && make install && \ + cd /src && rm -rf libnetfilter_conntrack + +# Build libfci, used by cmm. +RUN make -C "${ASK_DIR}/fci/lib" \ + CC=aarch64-linux-musl-gcc \ + AR=aarch64-linux-musl-ar + +COPY patches/ask/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch /src/ + +RUN cd /src/ASK && \ + git init -q && git add -A && git commit -q -m "base" && \ + git apply /src/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch + +# Build the kernel +COPY kernel-extra.config /src/kernel-extra.config +COPY kernel-build/dts/*.dts /src/linux/arch/arm64/boot/dts/freescale/ +COPY kernel-build/ensure-kconfig.sh /src/ + +# NXP tree: use the LSDK defconfig target +RUN cd /src/linux \ + && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" defconfig lsdk.config \ + && ./scripts/kconfig/merge_config.sh -m .config "${ASK_DIR}/config/kernel/defconfig" /src/kernel-extra.config \ + && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" olddefconfig \ + && /src/ensure-kconfig.sh .config /src/kernel-extra.config \ + && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" -j"$(nproc)" + + +# Build out-of-tree ASK kernel modules: cdx -> fci, plus auto_bridge. +RUN make -C "${ASK_DIR}/cdx" \ + CROSS_COMPILE="${CROSS_COMPILE}" \ + ARCH="${ARCH}" \ + KERNELDIR="${KERNEL_DIR}" \ + PLATFORM="${PLATFORM}" \ + modules && \ + make -C "${ASK_DIR}/fci" \ + CROSS_COMPILE="${CROSS_COMPILE}" \ + ARCH="${ARCH}" \ + KERNEL_SOURCE="${KERNEL_DIR}" \ + BOARD_ARCH="${ARCH}" \ + KBUILD_EXTRA_SYMBOLS="${ASK_DIR}/cdx/Module.symvers" \ + modules && \ + make -C "${ASK_DIR}/auto_bridge" \ + CROSS_COMPILE="${CROSS_COMPILE}" \ + ARCH="${ARCH}" \ + KERNEL_SOURCE="${KERNEL_DIR}" \ + PLATFORM="${PLATFORM}" + +# Build remaining userspace binaries: cmm and dpa_app. +RUN make -C "${ASK_DIR}/cmm" \ + CC="aarch64-linux-musl-gcc -static" \ + LIBFCI_DIR="${ASK_DIR}/fci/lib" \ + ABM_DIR="${ASK_DIR}/auto_bridge" \ + SYSROOT="${SYSROOT}" \ + PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" && \ + make -C "${ASK_DIR}/dpa_app" \ + CC="aarch64-linux-musl-gcc -static" \ + CFLAGS="-DDPAA_DEBUG_ENABLE -DNCSW_LINUX \ + -I/src/fmc/source \ + -I${ASK_DIR}/cdx \ + -I/src/fmlib/include/fmd \ + -I/src/fmlib/include/fmd/Peripherals \ + -I/src/fmlib/include/fmd/integrations" \ + LDFLAGS="-static -L/src/fmc/source -L/src/fmlib -L${SYSROOT}/lib \ + -lfmc -lfm -lcli -lxml2 -lstdc++ -lpthread -lm" + +# Stage outputs. +RUN mkdir -p /out/ask && \ + cp "${ASK_DIR}/cdx/cdx.ko" /out/ask/ && \ + cp "${ASK_DIR}/fci/fci.ko" /out/ask/ && \ + cp "${ASK_DIR}/auto_bridge/auto_bridge.ko" /out/ask/ && \ + cp /src/fmc/source/fmc /out/ask/ && \ + cp "${ASK_DIR}/cmm/src/cmm" /out/ask/ && \ + cp "${ASK_DIR}/dpa_app/dpa_app" /out/ask/ && \ + aarch64-linux-musl-strip /out/ask/fmc /out/ask/cmm /out/ask/dpa_app || true + +FROM scratch AS ask-artifacts +COPY --from=build /out/ask/ / diff --git a/kernel-extra.config b/kernel-extra.config index e221d2c..5b8ef26 100644 --- a/kernel-extra.config +++ b/kernel-extra.config @@ -252,4 +252,4 @@ CONFIG_TASK_XACCT=y # NXP ############################################################################### -CONFIG_CDX_BUS=y +# CONFIG_CDX_BUS=y diff --git a/patches/ask/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch b/patches/ask/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch new file mode 100644 index 0000000..f018088 --- /dev/null +++ b/patches/ask/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch @@ -0,0 +1,76 @@ +--- a/cdx/dpa_wifi.c 2026-05-08 15:39:41.418608108 +0000 ++++ b/cdx/dpa_wifi.c 2026-05-08 15:39:41.434536563 +0000 +@@ -840,17 +840,15 @@ + /* Get a page frag to store the SGTable, or a full page if the errata + * is in place and we need to avoid crossing a 4k boundary. + */ +-#ifdef FM_ERRATUM_A050385 + if (unlikely(fm_has_errata_a050385())) { + struct page *new_page = alloc_page(GFP_ATOMIC); + + if (unlikely(!new_page)) + return -ENOMEM; + sgt_buf = page_address(new_page); +- } +- else +-#endif ++ } else { + sgt_buf = netdev_alloc_frag(priv->eth_priv->tx_headroom + sgt_size); ++ } + + if (unlikely(!sgt_buf)) { + dev_err(dpa_bp->dev, "netdev_alloc_frag() failed\n"); +@@ -1082,11 +1080,7 @@ + /* We do not support Jumbo frames on LS1043 and thus we edit + * the skb truesize only when the 4k errata is not present. + */ +-#ifdef FM_ERRATUM_A050385 + if (likely(!fm_has_errata_a050385())) { +-#else +- if (likely(!dpaa_errata_a010022)) { +-#endif + skb->truesize = SKB_TRUESIZE(dpa_fd_length(fd)); + } + } +@@ -1152,11 +1146,8 @@ + err = custom_vwd_skb_to_sg_fd(priv, skb, &fd); + INCR_PER_CPU_STAT(vap_dev->vap_stats, pkts_tx_sg); + #else +-#ifdef FM_ERRATUM_A050385 + if (unlikely(fm_has_errata_a050385()) && a050385_check_skb(skb, priv->eth_priv)) + skb_need_wa = true; +-#endif +- + + nonlinear = skb_is_nonlinear(skb); + +@@ -1217,7 +1208,6 @@ + * more fragments than we support. In this case, + * we have no choice but to linearize it ourselves. + */ +-#ifdef FM_ERRATUM_A050385 + /* No point in linearizing the skb now if we are going + * to realign and linearize it again further down due + * to the A050385 errata +@@ -1226,13 +1216,11 @@ + skb_need_wa = true; + else + err = __skb_linearize(skb); +-#endif + } + if (unlikely(!skb || err < 0)) + /* Common out-of-memory error path */ + goto skb_to_fd_failed; + +-#ifdef FM_ERRATUM_A050385 + /* Verify the skb a second time if it has been updated since + * the previous check + */ +@@ -1248,7 +1236,6 @@ + dev_kfree_skb(skb); + skb = nskb; + } +-#endif + + err = vwd_skb_to_contig_fd(priv, skb, &fd, &offset); + } diff --git a/patches/ask/kernel/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch b/patches/ask/kernel/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch new file mode 100644 index 0000000..69c897f --- /dev/null +++ b/patches/ask/kernel/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch @@ -0,0 +1,71 @@ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +index 12a409d..740793d 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +@@ -37,6 +37,7 @@ + #include /* struct qman_fq */ + + #include "fm_ext.h" ++#include "fm_ehash.h" + #include "dpaa_eth_trace.h" + + extern int dpa_rx_extra_headroom; +@@ -88,8 +89,13 @@ static inline void DPA_BUG_ON(bool cond) + (FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT | \ + FM_PORT_FRM_ERR_LENGTH | FM_PORT_FRM_ERR_DMA) + +-/* The raw buffer size must be cacheline aligned. */ +-#define DPA_BP_RAW_SIZE 2048 ++/* The raw buffer size must be cacheline aligned. ++ * As 1518 byte packets are received in scatter gather buffers from DPAA, ++ * and these buffers are used by Wi-Fi which requires contiguous buffers, ++ * increase the raw buffer size from 2048 to 2176 to accommodate them in a ++ * contiguous FD. ++ */ ++#define DPA_BP_RAW_SIZE 2176 + + /* This is what FMan is ever allowed to use. + * FMan-DMA requires 16-byte alignment for Rx buffers, but SKB_DATA_ALIGN is +@@ -174,6 +180,7 @@ static inline void DPA_BUG_ON(bool cond) + #endif + + #define DPAA_ETH_RX_QUEUES 128 ++#define DPAA_IP_VERSION_4 4 + + /* Convenience macros for storing/retrieving the skb back-pointers. They must + * accommodate both recycling and confirmation paths - i.e. cases when the buf +@@ -304,6 +311,10 @@ struct dpa_percpu_priv_s { + u64 tx_frag_skbuffs; + /* number of S/G frames received */ + u64 rx_sg; ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) && defined(CONFIG_CPE_FAST_PATH) ++ u64 tx_caam_enc; ++ u64 tx_caam_dec; ++#endif + + struct rtnl_link_stats64 stats; + struct dpa_rx_errors rx_errors; +@@ -375,9 +386,13 @@ struct dpa_priv_s { + int loop_id; + int loop_to; + #endif +-#ifdef CONFIG_FSL_DPAA_CEETM ++#if defined(CONFIG_FSL_DPAA_CEETM) || defined(CONFIG_CPE_FAST_PATH) + bool ceetm_en; /* CEETM QoS enabled */ ++#ifdef CONFIG_CPE_FAST_PATH ++ void *qm_ctx; /* CEETM context */ ++#endif + #endif ++ void *ifinfo; + }; + + struct fm_port_fqs { +@@ -392,7 +407,7 @@ struct fm_port_fqs { + extern struct net_device *dpa_loop_netdevs[20]; + #endif + +-int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp, int *count_ptr); ++int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp, int *count_ptr, int threshold); + void __hot _dpa_rx(struct net_device *net_dev, + struct qman_portal *portal, + const struct dpa_priv_s *priv, diff --git a/patches/ask/kernel/0009-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth_sg.c.patch b/patches/ask/kernel/0009-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth_sg.c.patch new file mode 100644 index 0000000..d335909 --- /dev/null +++ b/patches/ask/kernel/0009-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth_sg.c.patch @@ -0,0 +1,1113 @@ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index a993a93..48d9609 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -52,6 +52,55 @@ + #endif + #ifdef CONFIG_FSL_DPAA_CEETM + #include "dpaa_eth_ceetm.h" ++#endif ++#if defined(CONFIG_IP_NF_CONNTRACK_MARK) || defined(CONFIG_NF_CONNTRACK_MARK) ++#include "net/netfilter/nf_conntrack.h" ++#endif // CONFIG_IP_NF_CONNTRACK_MARK || CONFIG_NF_CONNTRACK_MARK ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++#include ++#include ++#include ++#include ++#endif ++ ++#define DPAA_EXTRA_BUF_SIZE_4_SKB SMP_CACHE_BYTES + DPA_MAX_FD_OFFSET + \ ++ sizeof(struct skb_shared_info) + 128 ++ ++#ifndef EXCLUDE_FMAN_IPR_OFFLOAD ++//added for IPR offload to FMAN ++static dpaa_eth_bpool_replenish_hook_t dpaa_eth_bpool_replenish_hook; ++#endif ++ ++/* registered function to get ceetm Fqs */ ++#ifdef CONFIG_CPE_FAST_PATH ++static cdx_get_ceetm_egressfq ceetm_fqget_func; ++static cdx_get_ceetm_dscp_fq ceetm_dscp_fqget_func; ++/* This function registers two cdx functions, which are to get the egress fq. ++ One is based on channel and classqueue and another one is based on dscp. */ ++int dpa_register_ceetm_get_egress_fq(cdx_get_ceetm_egressfq egress_fq_func, cdx_get_ceetm_dscp_fq dscp_fq_func) ++{ ++ ceetm_fqget_func = egress_fq_func; ++ ceetm_dscp_fqget_func = dscp_fq_func; ++ return 0; ++} ++EXPORT_SYMBOL(dpa_register_ceetm_get_egress_fq); ++#endif ++ ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++cdx_get_ipsec_fq_hook_t cdx_get_ipsec_fq_hookfn; ++ ++int dpa_register_ipsec_fq_handler(cdx_get_ipsec_fq_hook_t hookfn) ++{ ++ if (cdx_get_ipsec_fq_hookfn) { ++ printk("%s::hook already registered\n", __func__); ++ return -1; ++ } ++ cdx_get_ipsec_fq_hookfn = hookfn; ++ return 0; ++} ++ ++EXPORT_SYMBOL(dpa_register_ipsec_fq_handler); ++ + #endif + + /* DMA map and add a page frag back into the bpool. +@@ -81,6 +130,109 @@ static void dpa_bp_recycle_frag(struct dpa_bp *dpa_bp, unsigned long vaddr, + (*count_ptr)++; + } + ++// adding a new function which allocates memory for buffers and adds bman pool ++int dpaa_bp_alloc_n_add_buffs(const struct dpa_bp *dpa_bp, uint32_t nbuffs, bool act_skb) ++{ ++ struct bm_buffer bmb[8]; ++ char *new_buf, *ptr_buf; ++ dma_addr_t addr; ++ int ii,entries_in_bmb,buffs2fill; ++ struct device *dev = dpa_bp->dev; ++ struct sk_buff *skb = NULL, **skbh; ++ uint32_t bufsize; ++ ++ if (act_skb) ++ bufsize = DPAA_EXTRA_BUF_SIZE_4_SKB + dpa_bp->size; ++ else ++ bufsize = SMP_CACHE_BYTES + dpa_bp->size + DPA_MAX_FD_OFFSET + 128; ++ ++ /* aligning to SMP_CACHE_BYTES */ ++ bufsize = DPA_SKB_SIZE(bufsize); ++ ++ buffs2fill= 0; ++ while (buffs2fill < nbuffs) ++ { ++ memset(bmb, 0, sizeof(struct bm_buffer) * 8); ++ ++ if ((nbuffs - buffs2fill) < 8) ++ entries_in_bmb = (nbuffs - buffs2fill); ++ else ++ entries_in_bmb = 8; ++ for (ii= 0; iisize, DMA_BIDIRECTIONAL); ++ if (unlikely(dma_mapping_error(dev, addr))) ++ { ++ pr_err("%s(%d) ii %d buffs2fill %d dma_mapping_error failed \n", ++ __func__,__LINE__,ii,buffs2fill); ++ if (act_skb) ++ { ++ kfree_skb(skb); ++ } ++ kfree(new_buf); ++ goto handle_fail; ++ } ++ bm_buffer_set64(&bmb[ii], addr); ++ ++ bmb[ii].bpid = cpu_to_be16(dpa_bp->bpid & 0xff); ++ } ++ while (unlikely(bman_release(dpa_bp->pool, bmb, entries_in_bmb, 0))) ++ cpu_relax(); ++ buffs2fill+= entries_in_bmb; ++ /* printk("%s(%d) adrsses %lx %lx %lx %lx %lx %lx %lx %lx\n", ++ __func__,__LINE__,bm_buffer_get64(&bmb[0]),bm_buffer_get64(&bmb[1]), ++ bm_buffer_get64(&bmb[2]),bm_buffer_get64(&bmb[3]),bm_buffer_get64(&bmb[4]), ++ bm_buffer_get64(&bmb[5]),bm_buffer_get64(&bmb[6]),bm_buffer_get64(&bmb[7])); */ ++ } ++ /* printk("%s(%d) buff allocation and bman release success buffs2fill %d\n", ++ __func__,__LINE__,buffs2fill); */ ++ return 0; ++ ++handle_fail: ++ if (ii) ++ { ++ while (unlikely(bman_release(dpa_bp->pool, bmb, ii, 0))) ++ cpu_relax(); ++ } ++ return ii+buffs2fill; ++ ++} ++EXPORT_SYMBOL(dpaa_bp_alloc_n_add_buffs); ++ ++ + static int _dpa_bp_add_8_bufs(const struct dpa_bp *dpa_bp) + { + void *new_buf, *fman_buf; +@@ -189,12 +341,13 @@ err_release_previous_bufs: + /* Add buffers/(pages) for Rx processing whenever bpool count falls below + * REFILL_THRESHOLD. + */ +-int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp, int *countptr) ++int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp, int *countptr, int threshold) + { + int count = *countptr; + int new_bufs; ++ int percpu_buf_cfg_count = dpa_bp->config_count; + +- if (unlikely(count < CONFIG_FSL_DPAA_ETH_REFILL_THRESHOLD)) { ++ if (unlikely(count <= (percpu_buf_cfg_count - threshold))) { + do { + new_bufs = _dpa_bp_add_8_bufs(dpa_bp); + if (unlikely(!new_bufs)) { +@@ -205,10 +358,10 @@ int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp, int *countptr) + break; + } + count += new_bufs; +- } while (count < CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT); ++ } while (count < percpu_buf_cfg_count); + + *countptr = count; +- if (unlikely(count < CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT)) ++ if (unlikely(count < percpu_buf_cfg_count)) + return -ENOMEM; + } + +@@ -372,7 +525,7 @@ EXPORT_SYMBOL(dpa_buf_is_recyclable); + * We are guaranteed there is enough room at the end of the data buffer to + * accommodate the shared info area of the skb. + */ +-static struct sk_buff *__hot contig_fd_to_skb(const struct dpa_priv_s *priv, ++struct sk_buff *__hot contig_fd_to_skb(const struct dpa_priv_s *priv, + const struct qm_fd *fd, + bool *use_gro, bool dcl4c_valid) + { +@@ -410,14 +563,14 @@ static struct sk_buff *__hot contig_fd_to_skb(const struct dpa_priv_s *priv, + + return skb; + } +- ++EXPORT_SYMBOL(contig_fd_to_skb); + + /* Build an skb with the data of the first S/G entry in the linear portion and + * the rest of the frame as skb fragments. + * + * The page fragment holding the S/G Table is recycled here. + */ +-static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, ++struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + const struct qm_fd *fd, bool *use_gro, + int *count_ptr, bool dcl4c_valid) + { +@@ -437,7 +590,8 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + vaddr = phys_to_virt(addr); + DPA_BUG_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES)); + +- dpa_bp = priv->dpa_bp; ++/* dpa_bp = priv->dpa_bp; */ ++ dpa_bp = dpa_bpid2pool(fd->bpid); + /* Iterate through the SGT entries and add data buffers to the skb */ + sgt = vaddr + fd_off; + for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { +@@ -445,9 +599,9 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + DPA_BUG_ON(qm_sg_entry_get_ext(&sgt[i])); + + /* We use a single global Rx pool */ +- DPA_BUG_ON(dpa_bp != ++/* DPA_BUG_ON(dpa_bp != + dpa_bpid2pool(qm_sg_entry_get_bpid(&sgt[i]))); +- ++*/ + sg_addr = qm_sg_addr(&sgt[i]); + sg_vaddr = phys_to_virt(sg_addr); + DPA_BUG_ON(!IS_ALIGNED((unsigned long)sg_vaddr, +@@ -530,6 +684,7 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + dpa_bp_recycle_frag(dpa_bp, (unsigned long)vaddr, count_ptr); + return skb; + } ++EXPORT_SYMBOL(sg_fd_to_skb); + + #ifdef CONFIG_FSL_DPAA_DBG_LOOP + static inline int dpa_skb_loop(const struct dpa_priv_s *priv, +@@ -547,6 +702,14 @@ static inline int dpa_skb_loop(const struct dpa_priv_s *priv, + } + #endif + ++#ifndef EXCLUDE_FMAN_IPR_OFFLOAD ++void register_dpaa_eth_bpool_replenish_hook(dpaa_eth_bpool_replenish_hook_t func) ++{ ++ dpaa_eth_bpool_replenish_hook = func; ++} ++EXPORT_SYMBOL(register_dpaa_eth_bpool_replenish_hook); ++#endif ++ + void __hot _dpa_rx(struct net_device *net_dev, + struct qman_portal *portal, + const struct dpa_priv_s *priv, +@@ -566,7 +729,7 @@ void __hot _dpa_rx(struct net_device *net_dev, + + if (unlikely(fd_status & FM_FD_STAT_RX_ERRORS) != 0) { + if (netif_msg_hw(priv) && net_ratelimit()) +- netdev_warn(net_dev, "FD status = 0x%08x\n", ++ netdev_warn(net_dev, "_dpa_rx FD status = 0x%08x\n", + fd_status & FM_FD_STAT_RX_ERRORS); + + percpu_stats->rx_errors++; +@@ -592,6 +755,15 @@ void __hot _dpa_rx(struct net_device *net_dev, + /* won't count the rx bytes in */ + return; + } ++#endif ++#ifndef EXCLUDE_FMAN_IPR_OFFLOAD ++ if (dpaa_eth_bpool_replenish_hook) { ++ if (dpaa_eth_bpool_replenish_hook(net_dev, fd->bpid)) { ++ //could not replenish buffer, drop packet ?? ++ printk("%s::could not replenish buffer to pool\n", ++ __func__); ++ } ++ } + #endif + skb = contig_fd_to_skb(priv, fd, &use_gro, dcl4c_valid); + } else { +@@ -638,6 +810,7 @@ void __hot _dpa_rx(struct net_device *net_dev, + _release_frame: + dpa_fd_release(net_dev, fd); + } ++EXPORT_SYMBOL(_dpa_rx); + + int __hot skb_to_contig_fd(struct dpa_priv_s *priv, + struct sk_buff *skb, struct qm_fd *fd, +@@ -738,7 +911,7 @@ EXPORT_SYMBOL(skb_to_contig_fd); + * - SG fragments that aren't mod 16 bytes in size (except for the last + * fragment) + */ +-static bool a050385_check_skb(struct sk_buff *skb, struct dpa_priv_s *priv) ++bool a050385_check_skb(struct sk_buff *skb, struct dpa_priv_s *priv) + { + skb_frag_t *frag; + int i, nr_frags; +@@ -800,12 +973,13 @@ static bool a050385_check_skb(struct sk_buff *skb, struct dpa_priv_s *priv) + + return false; + } ++EXPORT_SYMBOL(a050385_check_skb); + + /* Realign the skb by copying its contents at the start of a newly allocated + * page. Build a new skb around the new buffer and release the old one. + * A performance drop should be expected. + */ +-static struct sk_buff *a050385_realign_skb(struct sk_buff *skb, ++struct sk_buff *a050385_realign_skb(struct sk_buff *skb, + struct dpa_priv_s *priv) + { + int trans_offset = skb_transport_offset(skb); +@@ -874,7 +1048,212 @@ err: + put_page(npage); + return NULL; + } ++EXPORT_SYMBOL(a050385_realign_skb); ++ ++struct dpa_bp *sg_bpool_g; ++EXPORT_SYMBOL(sg_bpool_g); ++ ++struct dpa_bp *skb_2bfreed_bpool_g; //if no recyclable skbs exist in skb fraglist, those should be freed back, SEC engine will add to this bman pool ++EXPORT_SYMBOL(skb_2bfreed_bpool_g); ++ ++struct device* dpa_get_bp_device(void) ++{ ++ if (skb_2bfreed_bpool_g) ++ return skb_2bfreed_bpool_g->dev; ++ else ++ return NULL; ++} ++ ++/* ++ *This functions unmaps all the mapped skb sg so far and stored in sgt. ++*/ ++static void dma_unmap_skb_sg_addrs(struct device *dev, struct sk_buff *skb, ++ struct qm_sg_entry *sgt, int skb_list_frags) ++{ ++ dma_addr_t addr; ++ struct sk_buff *list_skb; ++ struct sk_buff *cur_skb; ++ const enum dma_data_direction dma_dir = DMA_TO_DEVICE; ++ int sgt_idx = 0; ++ int nr_frags = 0; ++ + ++ for (cur_skb = skb, list_skb = skb_shinfo(skb)->frag_list; ++ (sgt_idx < skb_list_frags) && (cur_skb); ) ++ { ++ addr = qm_sg_addr(&sgt[sgt_idx]); ++ dma_unmap_single(dev, addr, qm_sg_entry_get_len(&sgt[sgt_idx]), dma_dir); ++ sgt_idx++; ++ ++ nr_frags = skb_shinfo(cur_skb)->nr_frags; ++ while(nr_frags) ++ { ++ addr = qm_sg_addr(&sgt[sgt_idx]); ++ dma_unmap_page(dev, addr, qm_sg_entry_get_len(&sgt[sgt_idx]), dma_dir); ++ nr_frags--; ++ sgt_idx++; ++ } ++ cur_skb = list_skb; ++ if (list_skb) ++ list_skb = list_skb->next; ++ } ++ ++ return; ++} ++ ++/* ++ * This inline function updates the sgt entry parameters. ++ */ ++static inline void prepare_qm_sg_entry(struct qm_sg_entry *sgt, int sgt_idx, ++ unsigned int len, dma_addr_t addr) ++{ ++ qm_sg_entry_set_ext(&sgt[sgt_idx], 0); ++ qm_sg_entry_set_final(&sgt[sgt_idx], 0); ++ /* fill the first entry with skb details */ ++ qm_sg_entry_set_bpid(&sgt[sgt_idx], 0xff); ++ /* set the offset and addr pointers such that ++ in next alloc, that addr should point to skb*/ ++ qm_sg_entry_set_offset(&sgt[sgt_idx],0); ++ qm_sg_entry_set_len(&sgt[sgt_idx], len); ++ qm_sg_entry_set64(&sgt[sgt_idx], addr); ++ ++ return; ++} ++ ++int __hot skb_fraglist_to_sg_fd(struct device *dev, struct net_device *net_dev , struct sk_buff *skb, struct qm_fd *fd, u32 fd_cmd) ++{ ++ dma_addr_t addr, sg_addr; ++ struct sk_buff *list_skb; ++ struct sk_buff *cur_skb; ++ int sgt_size; ++ int err; ++ struct qm_sg_entry *sgt; ++ struct bm_buffer bmb; ++ int sgt_index = 0, nr_frags = 0; ++ const enum dma_data_direction dma_dir = DMA_TO_DEVICE; ++ int dma_map_size; ++ skb_frag_t *frag; ++ ++ // calculate the number of fragments ++ // check if any of skb is not recyclable ++ nr_frags = 1 + skb_shinfo(skb)->nr_frags; ++ skb_walk_frags(skb, list_skb) ++ { ++ nr_frags += 1 + skb_shinfo(list_skb)->nr_frags; ++ } ++ ++ /* The below condition covers nr_frags + 1(This is to store skb address in opaque variable at the end.)*/ ++ if (nr_frags > (DPA_SGT_MAX_ENTRIES)) ++ { ++ /* TODO linearize */ ++ pr_err("%s()::%d number of skb frags %d crossed the MAX SGT entries%d", __func__, __LINE__, nr_frags, DPA_SGT_MAX_ENTRIES); ++ return -1; ++ } ++ ++ fd->format = qm_fd_sg; ++ /* allocate an SG buffer from SG BMAN POOL ++ if any entries in skb_2bfreed_bpool_g, acquire and free skb and use the SG buffer */ ++ if (bman_acquire(skb_2bfreed_bpool_g->pool, &bmb, 1, 0) == 1) ++ { ++ sgt = (struct qm_sg_entry *)phys_to_virt(bmb.addr); ++ while (!qm_sg_entry_get_final(&sgt[sgt_index])) ++ sgt_index++; ++ addr = sgt[sgt_index+1].opaque; ++ if (addr) /* free the old skb */ ++ { ++ list_skb = (struct sk_buff *)(addr); ++ kfree_skb(list_skb); ++ } ++ sgt[sgt_index+1].opaque = 0; /* set to 0*/ ++ } ++ else if (bman_acquire(sg_bpool_g->pool, &bmb, 1, 0) == 1) ++ { ++ sgt = (struct qm_sg_entry *)phys_to_virt(bmb.addr); ++ } ++ else ++ { ++ printk("%s(%d) bman_acquire of SG bman buffer failed\n", ++ __func__,__LINE__); ++ return -1; ++ } ++ ++ ++ /* net_crit_ratelimited("%s(%d) nr_frags %d, MAX frags %d \n", __func__,__LINE__,nr_frags,DPA_SGT_MAX_ENTRIES);*/ ++ /* After nr_frags, in next index of sgt array storing skb address in opaque. So doing memset for (nr_frags+1).*/ ++ sgt_size = sizeof(struct qm_sg_entry) * (nr_frags + 1); ++ ++ ++ /* memset to 0s of size sgt_size*/ ++ memset(sgt, 0, sgt_size); ++ ++ ++ ++ sgt_index = 0; ++ for (cur_skb = skb, list_skb = skb_shinfo(skb)->frag_list; cur_skb;) ++ { ++ dma_map_size = skb_headlen(cur_skb); ++ addr = dma_map_single(dev, cur_skb->data, dma_map_size, dma_dir); ++ if (unlikely(dma_mapping_error(dev, addr))) { ++ if (net_ratelimit()) ++ netdev_err(net_dev, "skb_fraglist_to_sg_fd : 2.DMA mappping error"); ++ err = -EINVAL; ++ dma_unmap_skb_sg_addrs(dev, skb, sgt, sgt_index); ++ bman_release(sg_bpool_g->pool, &bmb, 1, 0); ++ return -1; ++ } ++ prepare_qm_sg_entry(sgt, sgt_index, dma_map_size, addr); ++ sgt_index++; ++ ++ nr_frags = skb_shinfo(cur_skb)->nr_frags; ++ frag = skb_shinfo(cur_skb)->frags; ++ while(nr_frags) ++ { ++ addr = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), dma_dir); ++ if (unlikely(dma_mapping_error(dev, addr))) { ++ if (net_ratelimit()) ++ netdev_err(net_dev, "skb_fraglist_to_sg_fd : 2.DMA mappping error"); ++ dma_unmap_skb_sg_addrs(dev, skb, sgt, sgt_index); ++ err = -EINVAL; ++ bman_release(sg_bpool_g->pool, &bmb, 1, 0); ++ return -1; ++ } ++ prepare_qm_sg_entry(sgt, sgt_index, skb_frag_size(frag), addr); ++ frag++; ++ nr_frags--; ++ sgt_index++; ++ } ++ cur_skb = list_skb; ++ if (list_skb) ++ list_skb = list_skb->next; ++ } ++ ++ qm_sg_entry_set_final(&sgt[sgt_index-1], 1); ++ ++ addr = (dma_addr_t) (skb); ++ sgt[sgt_index].opaque = addr; ++ ++ sg_addr = dma_map_single(dev, sgt, sgt_size, dma_dir); ++ if (unlikely(dma_mapping_error(dev, sg_addr))) { ++ /*if (netif_msg_tx_err(priv) && net_ratelimit())*/ ++ dma_unmap_skb_sg_addrs(dev, skb, sgt, sgt_index); ++ if (net_ratelimit()) ++ netdev_err(net_dev, "skb_fraglist_to_sg_fd : 2.DMA mappping error"); ++ err = -EINVAL; ++ bman_release(sg_bpool_g->pool, &bmb, 1, 0); ++ return -1; ++ } ++ qm_fd_addr_set64(fd, sg_addr); ++ fd->bpid = skb_2bfreed_bpool_g->bpid; /*sg_bpool_g->bpid;*/ ++ fd->cmd = fd_cmd; ++ fd->length20 = skb->len; ++ fd->offset = 0; ++ ++ /*net_crit_ratelimited("%s(%d) sgt_index %d, addr %p \n",__func__, __LINE__,sgt_index,(void *)(sgt[sgt_index].opaque)); */ ++ /* percpu_priv->tx_returned++; */ ++ return 0; ++} ++ ++EXPORT_SYMBOL(skb_fraglist_to_sg_fd); + int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + struct sk_buff *skb, struct qm_fd *fd) + { +@@ -1019,9 +1398,532 @@ csum_failed: + } + EXPORT_SYMBOL(skb_to_sg_fd); + +-int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev) ++#define EMAC_QUEUENUM_MASK 0xff ++ ++#ifdef CONFIG_CPE_FAST_PATH ++static int pfe_eth_get_queuenum( struct sk_buff *skb ) ++{ ++ ++#if defined(CONFIG_IP_NF_CONNTRACK_MARK) || defined(CONFIG_NF_CONNTRACK_MARK) ++ /* Use conntrack mark (if conntrack exists) */ ++ if (skb->_nfct) { ++ enum ip_conntrack_info cinfo; ++ struct nf_conn *ct; ++ ++ ct = nf_ct_get(skb, &cinfo); ++ if (ct) { ++ u_int64_t markval; ++ ++ markval = ct->qosconnmark; ++ if (cinfo >= IP_CT_IS_REPLY) { ++ if (markval & ((uint64_t)1 << 63)) ++ markval >>= 32; ++ else ++ markval = 0; ++ } ++ markval &= 0x7fffffff; ++ return markval; ++ ++ } ++ } ++#endif ++ /* use packet mark (if any) */ ++ if (skb->mark) { ++ return (skb->mark & EMAC_QUEUENUM_MASK); ++ } ++ /* These are packets through control path, assign highest priority */ ++ return (QOS_DEFAULT_QUEUE); ++} ++#endif /*endif for CONFIG_CPE_FAST_PATH */ ++ ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++unsigned int ipsec_offload_pkt_cnt; ++void print_ipsec_offload_pkt_count(void) ++{ ++ printk("%s:: Ipsec offload slow path packet count = %d\n",__func__,ipsec_offload_pkt_cnt); ++ ipsec_offload_pkt_cnt = 0; ++} ++EXPORT_SYMBOL(print_ipsec_offload_pkt_count); ++#endif ++ ++#ifdef CONFIG_XFRM ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ ++#define ETH_HDR_SIZE 14 ++#define VLAN_HDR_SIZE 4 ++#define PPPOE_HDR_SIZE 8 ++#define ETHHDR_MACEND_OFFSET 12 ++ ++#define DPOVRD_ENABLE 0x80000000 ++ ++unsigned char* dpa_get_skb_nh(struct sk_buff* skb, unsigned short *l3_proto, unsigned short* l3_offset) ++{ ++ unsigned short type_id; ++ unsigned short offset = ETH_HDR_SIZE; ++ type_id = *((unsigned short*) (skb->data + offset - 2)); ++ while (1) ++ { ++ switch (type_id) ++ { ++ case htons(ETH_P_PPP_SES): ++ offset += PPPOE_HDR_SIZE; ++ type_id = *(unsigned short*)(skb->data + offset - 2); ++ ++ if (type_id == htons(PPP_IP)) ++ type_id = ntohs(ETH_P_IP); ++ else if (type_id == htons(PPP_IPV6)) ++ type_id = ntohs(ETH_P_IPV6); ++ break; ++ case htons(ETH_P_8021Q): ++ offset += VLAN_HDR_SIZE; ++ type_id = *(unsigned short*) (skb->data + offset - 2); ++ break; ++ case htons(ETH_P_IP): ++ case htons(ETH_P_IPV6): ++ *l3_proto = type_id; ++ *l3_offset = offset; ++ return (skb->data + offset); ++ default: ++ *l3_proto = type_id; ++ *l3_offset = offset; ++ return NULL; ++ } ++ } ++} ++ ++ __hot void dpaa_submit_outb_pkt_to_SEC(struct sk_buff *skb, struct net_device *net_dev, struct dpa_bp *dpa_bp) ++{ ++ struct xfrm_state *x; ++ struct qman_fq *egress_fq = NULL; ++ struct qm_fd fd; ++ int err = 0,ii; ++ int new_ethhdr_end, old_ethhdr_end; ++ unsigned short l3_proto, l3_offset; ++ unsigned char* skb_nh ; ++ struct sec_path *sp; ++ unsigned int dpovrd = 0; ++ ++ sp = skb_sec_path(skb); ++ ++ if ((cdx_get_ipsec_fq_hookfn) && (sp) && (sp->len)) ++ { ++ x = sp->xvec[0]; ++ ++ egress_fq = cdx_get_ipsec_fq_hookfn(x->handle); ++ ++ /* when a packet is submitting to SEC engine, ++ use the below code */ ++ if (!egress_fq) ++ { ++ printk("%s(%d) egress frame queue not found \n", ++ __func__, __LINE__); ++ goto sec_submit_failed; ++ } ++ ++ /* ++ * For packets with L2 headers other than ethernet header, L2 headers are ++ * stripped off and only ethernet header is maintained. These L2 headers ++ * will be added again in offline port classification table entry ++ * after SEC processing. ++ */ ++ ++ skb_nh = dpa_get_skb_nh(skb, &l3_proto, &l3_offset); ++ ++ if (skb_nh) ++ { ++ if(l3_offset != ETH_HDR_SIZE) ++ { ++ new_ethhdr_end = l3_offset - 2 ; /*l3 offset - protocol(2bytes) */ ++ old_ethhdr_end = ETHHDR_MACEND_OFFSET ; ++ while(old_ethhdr_end >= 0) ++ skb->data[new_ethhdr_end--] = skb->data[old_ethhdr_end--]; ++ ++ *((unsigned short*) (skb->data + l3_offset - 2) ) = l3_proto; ++ skb->data = skb->data + l3_offset - ETH_HDR_SIZE; ++ skb->len = skb->len - l3_offset + ETH_HDR_SIZE; ++ } ++ if ((*skb_nh >> 4) == IPVERSION) /* Extracting ip version from network header */ ++ { ++ dpovrd = IPPROTO_IPIP; /* ESP trailer NH type. Here traffic is IPv4 */ ++ } ++ else ++ { ++ dpovrd = IPPROTO_IPV6; /* ESP trailer NH type. Here traffic is IPv4 */ ++ } ++ dpovrd |= DPOVRD_ENABLE; /* OVRD enable */ ++ } ++ ++ ++ err = skb_fraglist_to_sg_fd(dpa_bp->dev, net_dev, skb, &fd, dpovrd); ++ if (unlikely(err < 0)) ++ { ++ printk("%s(%d) skb_fraglist_to_sg_fd \n",__func__,__LINE__); ++ goto sec_submit_failed; ++ } ++ ++ ++ for (ii = 0; ii < 100000; ii++) { ++ err = qman_enqueue(egress_fq, &fd, 0); ++ if (err != -EBUSY) ++ break; ++ } ++ ++ if (unlikely(err < 0)) { ++ struct bm_buffer bmb; ++ dma_addr_t addr; ++ ++ printk("%s(%d) dpa_xmit failed\n",__func__,__LINE__); ++ /* put the buffer back to sg pool */ ++ addr = qm_fd_addr(&fd); ++ bm_buffer_set64(&bmb, addr); ++ while (bman_release(sg_bpool_g->pool, &bmb, 1, 0)) ++ cpu_relax(); ++ /* release skb and retuen */ ++ goto sec_submit_failed; ++ } ++ ++ /* sucessful transmit to CAAM */ ++ netif_trans_update(net_dev); ++ ipsec_offload_pkt_cnt++; ++ return; ++ } ++sec_submit_failed: ++ dev_kfree_skb(skb); ++ return; ++ ++} ++ ++EXPORT_SYMBOL(dpaa_submit_outb_pkt_to_SEC); ++ ++/** ++ * dpa_add_dummy_eth_hdr - Add dummy Ethernet header space to SKB ++ * @skb_in: Pointer to SKB pointer (may be reallocated) ++ * @priv_headroom: Private headroom to reserve (not used, for API compatibility) ++ * @hdroom_realloc: Set to 1 if headroom was reallocated ++ * ++ * This function ensures there is space for an Ethernet header in the SKB ++ * headroom for cellular interfaces that don't have a MAC header. ++ * Returns 0 on success, negative on failure. ++ */ ++int dpa_add_dummy_eth_hdr(struct sk_buff **skb_in, int priv_headroom, ++ unsigned char *hdroom_realloc) ++{ ++ struct sk_buff *skb = *skb_in; ++ struct ethhdr *eth; ++ __be16 proto; ++ int headroom_needed = ETH_HLEN + priv_headroom; ++ int ipv; ++ ++ /* Check if we have enough headroom */ ++ if (skb_headroom(skb) < headroom_needed) { ++ struct sk_buff *new_skb; ++ ++ new_skb = skb_realloc_headroom(skb, headroom_needed); ++ if (!new_skb) ++ return -ENOMEM; ++ ++ dev_kfree_skb(skb); ++ *skb_in = new_skb; ++ skb = new_skb; ++ *hdroom_realloc = 1; ++ } ++ ++ /* Determine IP version from first byte of packet */ ++ ipv = (skb->data[0] >> 4) & 0xf; ++ ++ /* Set protocol based on IP version */ ++ if (ipv == 6) ++ proto = htons(ETH_P_IPV6); ++ else ++ proto = htons(ETH_P_IP); ++ ++ /* Push ethernet header space */ ++ eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); ++ ++ /* Initialize with dummy MAC addresses (will be overwritten later) */ ++ memset(eth->h_dest, 0, ETH_ALEN); ++ memset(eth->h_source, 0, ETH_ALEN); ++ eth->h_proto = proto; ++ ++ /* Reset SKB pointers - caller will adjust data/len */ ++ skb_pull(skb, ETH_HLEN); ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_add_dummy_eth_hdr); ++ ++#ifdef UNIT_TEST ++unsigned char temp_ethhdr[16]; ++#endif ++/* This function is invoked from xfrm_input.c to submit IPSEC packets ++ to SEC engine, if the corresponding SA is programmed in ucode ++*/ ++int dpaa_submit_inb_pkt_to_SEC(struct sk_buff *skb, uint16_t sagd) ++{ ++ struct qman_fq *sec_fq = NULL; ++ struct dpa_priv_s *priv = NULL; ++ struct dpa_percpu_priv_s *percpu_priv = NULL; ++ struct qm_fd fd; ++ int err, ii, ret; ++ uint8_t tmp_len = 0, data[ETH_HLEN],ipvsn; ++ struct net_device *netdev; ++ struct device* dev; ++ unsigned char hdroom_realloced = 0; ++#ifdef UNIT_TEST ++ unsigned short dev_type = skb->dev->type; ++#endif ++ struct net_device *real_dev = NULL; ++ ++ if (cdx_get_ipsec_fq_hookfn) ++ { ++ /*net_crit_ratelimited("%s(%d) x->handle %d, skb->data %p, machdr %p\n", ++ __func__,__LINE__, sagd,skb->data, skb_mac_header(skb)); */ ++ /* Get the SEC FQID corresponding to sagd */ ++ sec_fq = cdx_get_ipsec_fq_hookfn(sagd); ++ ++ /*if no SEC FQID found, return non-zero to return pkt to linux*/ ++ if (!sec_fq || !(skb->dev)) ++ { ++ return -1; /* give packet to linux */ ++ } ++#ifdef UNIT_TEST ++ { ++ skb->dev->type = ARPHRD_NONE; ++ skb->mac_len = 0; ++ } ++#endif ++ if (skb->dev->type == ARPHRD_ETHER) ++ { ++ /* Get the corresponding physical device info, if the skb->dev corresponds to vlan*/ ++ real_dev = is_vlan_dev(skb->dev) ? vlan_dev_real_dev(skb->dev) : skb->dev; ++ priv = netdev_priv(real_dev); ++ /* SEC shared descriptor designed to take packet including MAC hdr */ ++ /* modify skb->data to point to MAC hdr */ ++ tmp_len = (skb->data - skb_mac_header(skb)); ++ skb->len += tmp_len; ++ skb->data = skb_mac_header(skb); ++ } ++ else if (skb->dev->type == ARPHRD_PPP) ++ { ++ /* Get the corresponding physica device info */ ++ netdev = __dev_get_by_index(dev_net(skb->dev), skb->iif_index); ++ if (!netdev) ++ { ++ return -1; ++ } ++ priv = netdev_priv(netdev); ++ /* observation in case of PPPoE skb_mac_header is pointing to IP header*/ ++ /* get the IP version*/ ++ /*printk("%s(%d), MAC header ptr: \n", ++ __func__,__LINE__); ++ display_buf_data(&skb->head[skb->mac_header] ,16);*/ ++ ipvsn = ((skb->head[skb->mac_header]) & 0xf0) >> 4; ++ /*printk(KERN_INFO "iif_dev :%s, ifindex %d, ipvsn %d\n", netdev->name, netdev->ifindex, ipvsn);*/ ++ /* SEC shared descriptor designed to take packet including MAC hdr */ ++ /* modify skb->data to point to MAC hdr */ ++ tmp_len = (skb->data - skb_mac_header(skb) + ETH_HLEN); ++ skb->len += tmp_len; ++ skb->data = skb_mac_header(skb) - ETH_HLEN; ++ /* Copy MAC hdr to the skb->data */ ++ /* have a backup data in case of failure */ ++ memcpy(data, skb->data, ETH_HLEN); ++ /* copying 8 bytes and then 4 bytes from the backup , as there is overlap*/ ++ memcpy(skb->data, skb->data-PPPOE_SES_HLEN, PPPOE_SES_HLEN); ++ memcpy(skb->data+PPPOE_SES_HLEN, data, 4); ++ /* setting IPv4/IPv6 ethernet protocol value */ ++ if (ipvsn == DPAA_IP_VERSION_4) ++ { ++ skb->data[12] = 0x08; ++ skb->data[13] = 0x00; ++ } ++ else /* IP v6 */ ++ { ++ skb->data[12] = 0x86; ++ skb->data[13] = 0xdd; ++ } ++ /*printk("%s(%d), modified header : \n", ++ __func__,__LINE__); ++ display_buf_data(skb->data,16);*/ ++ } ++ ++ if (skb->dev->wifi_offload_dev) ++ { ++ dev = dpa_get_bp_device(); ++ netdev = skb->dev; ++ /* Following code is added for cellular interfaces */ ++ /* FIX :May be we can check for device type as ARPHRD_NONE */ ++ if (skb->mac_len == 0) ++ { ++ tmp_len = (skb->data - skb_network_header(skb)); ++ skb->len += tmp_len; ++ skb->data = skb_network_header(skb); ++#ifdef UNIT_TEST ++ memcpy(temp_ethhdr, (skb->data - ETH_HLEN), 12); ++#endif ++ /* Add mac_header */ ++ ret = dpa_add_dummy_eth_hdr(&skb, 0, &hdroom_realloced); ++ if (ret < 0) ++ return -1; ++ ++ skb->data -= ETH_HLEN; ++ skb->len += ETH_HLEN; ++ tmp_len += ETH_HLEN; ++#ifdef UNIT_TEST ++ memcpy(skb->data ,temp_ethhdr,12); ++ skb->dev->type = dev_type; ++ skb->mac_len = ETH_HLEN; ++#endif ++ } ++ } ++ else ++ { ++ if (!priv) ++ return -1; ++ dev = priv->dpa_bp->dev; ++ netdev = priv->net_dev; ++ } ++ /*FIXME: skb->dev->type other than ARPHRD_ETHER and ARPHRD_PPP priv is uninitialized. Here else case should add to address it. */ ++ /*net_crit_ratelimited("%s(%d) x->handle %d, skb->data %p, machdr %p, len %d, skb->dev %p\n", ++ __func__,__LINE__, sagd, skb->data, skb_mac_header(skb),skb->len, skb->dev); */ ++ err = skb_fraglist_to_sg_fd(dev, netdev, skb, &fd, 0); ++ if (unlikely(err < 0)) ++ { ++ printk("%s(%d) skb_fraglist_to_sg_fd failed\n", ++ __func__,__LINE__); ++ if (skb->dev->type == ARPHRD_PPP) ++ memcpy(skb->data, data, ETH_HLEN); ++ ++ skb->len -= tmp_len; ++ skb->data += tmp_len; ++ return -1; /* give packet to linux */ ++ } ++ ++ for (ii = 0; ii < 100000; ii++) { ++ err = qman_enqueue(sec_fq, &fd, 0); ++ if (err != -EBUSY) ++ break; ++ } ++ ++ if (unlikely(err < 0)) { ++ struct bm_buffer bmb; ++ dma_addr_t addr; ++ ++ printk("%s(%d) qman_enqueue failed\n", ++ __func__,__LINE__); ++ /* put the buffer back to sg pool */ ++ addr = qm_fd_addr(&fd); ++ bm_buffer_set64(&bmb, addr); ++ while (bman_release(sg_bpool_g->pool, &bmb, 1, 0)) ++ cpu_relax(); ++ return -1; /* give packet to linux */ ++ } ++ if (priv) ++ { ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ percpu_priv->tx_caam_dec++; ++ } ++ } ++ return 0; ++} ++#endif ++#endif ++ ++#ifdef CONFIG_CPE_FAST_PATH ++#define CHANNEL_BIT_POSITION 24 ++ ++int cpe_fp_tx(struct sk_buff *skb, struct net_device *net_dev) + { + struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ int channel_id; ++ int queuenum; ++ int markval,ff=0; ++ struct qman_fq *egress_fq, *conf_fq; ++ uint8_t get_ceetm_cm_egress_fq; ++ uint8_t dscp; ++ unsigned char* skb_nh ; ++ uint16_t l3_proto = 0, l3_offset = 0; ++ ++ priv = netdev_priv(net_dev); ++#ifdef CONFIG_XFRM ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ if(skb->ipsec_offload) { ++ dpaa_submit_outb_pkt_to_SEC(skb, net_dev, priv->dpa_bp); ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ percpu_priv->tx_caam_enc++; ++ return NETDEV_TX_OK; ++ } ++#endif ++#endif ++ if (priv->ceetm_en) { ++ /* markval also using to know qosconnmark is present for this packet. */ ++ /* If markval is 0 assuming qosconnmark is not present for this packet(connection). */ ++ markval = pfe_eth_get_queuenum(skb); ++ queuenum = markval & 0xf; ++ channel_id = (markval >> CHANNEL_BIT_POSITION) & 0xf; ++ egress_fq = NULL; ++ get_ceetm_cm_egress_fq = 1; /* This becomes 0 when qosconnark(markval is 0) is not present or ++ can't find egress fq for dscp */ ++ /* markval is 0 means qosconnmark is not configured, so getting dscp from skb. */ ++ /* using dscp get the egress fq. */ ++ if (!markval) { ++ skb_nh = dpa_get_skb_nh(skb, &l3_proto, &l3_offset); ++ if (skb_nh) ++ { ++ /* skb_nh is non NULL means either it is pointing to ipv4 or ipv6 header only */ ++ if (l3_proto == htons(ETH_P_IP)) ++ { ++ /* Getting the DSCP value from IPv4 header*/ ++ dscp = (((struct iphdr *)skb_nh)->tos) >> 2; /* tos 8 bit size, DSCP 6 bit value, shifting 2 bits right to get actual DSCP value*/ ++ } ++ else ++ { ++ /* Getting the DSCP value from IPv6 header*/ ++ dscp = ((((struct ipv6hdr *)skb_nh)->priority) << 2) /* priority is 4 bit size, shifting 2 bits left to give space for flow_lbl[0] 2 bits */ ++ + ((((struct ipv6hdr *)skb_nh)->flow_lbl[0]) >> 6); /* flow_lbl[0] is 8 bit size, DSCP 2 bits are here, so shifting 6 bits right*/ ++ } ++ egress_fq = ceetm_dscp_fqget_func(priv->qm_ctx, dscp); ++ if (egress_fq) ++ get_ceetm_cm_egress_fq = 0; ++ } ++ } ++ if (get_ceetm_cm_egress_fq) ++ { ++ if (ceetm_fqget_func) { ++ egress_fq = ceetm_fqget_func(priv->qm_ctx, ++ channel_id,queuenum,ff); ++ } ++ if (!egress_fq) { ++ printk(KERN_CRIT "%s::unable to get ceetm fq, mark %08x registered func %p" ++ "dropping packet\n", ++ __func__, markval , ceetm_fqget_func); ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++ } ++ } ++ } else ++ { ++ queuenum = dpa_get_queue_mapping(skb); ++ if (unlikely(queuenum >= DPAA_ETH_TX_QUEUES)) ++ queuenum = queuenum % DPAA_ETH_TX_QUEUES; ++ egress_fq = priv->egress_fqs[queuenum]; ++ } ++ conf_fq = priv->conf_fqs[queuenum & (DPAA_ETH_TX_QUEUES-1)]; ++ return dpa_tx_extended(skb, net_dev, egress_fq, conf_fq); ++} ++#endif ++ ++static inline void skb_reset_truesize(struct sk_buff *skb, unsigned int size) ++{ ++ size -= SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); ++ skb->truesize = SKB_TRUESIZE(size); ++ ++ return; ++} ++ ++int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv; + int queue_mapping = dpa_get_queue_mapping(skb); + struct qman_fq *egress_fq, *conf_fq; + +@@ -1033,6 +1935,10 @@ int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev) + return NETDEV_TX_OK; + #endif + ++#ifdef CONFIG_CPE_FAST_PATH ++ return cpe_fp_tx(skb, net_dev); ++#endif ++ + priv = netdev_priv(net_dev); + + #ifdef CONFIG_FSL_DPAA_CEETM +@@ -1101,6 +2007,7 @@ int __hot dpa_tx_extended(struct sk_buff *skb, struct net_device *net_dev, + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + #endif /* CONFIG_FSL_DPAA_TS */ + ++ + /* MAX_SKB_FRAGS is larger than our DPA_SGT_MAX_ENTRIES; make sure + * we don't feed FMan with more fragments than it supports. + * Btw, we're using the first sgt entry to store the linear part of +@@ -1195,13 +2102,18 @@ int __hot dpa_tx_extended(struct sk_buff *skb, struct net_device *net_dev, + * but we need the skb to look as if returned by build_skb(). + * We need to manually adjust the tailptr as well. + */ ++ /* skb_reset_truesize() resets the skb truesize, to avoid ++ * skb truesize gets increment continuously when the same ++ * skb used for next fragments. ++ */ ++ skb_reset_truesize(skb, SMP_CACHE_BYTES + DPA_SKB_SIZE(priv->dpa_bp->size) + ++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))); + skb->data = skb->head + offset; + skb_reset_tail_pointer(skb); + + (*countptr)++; + percpu_priv->tx_returned++; + } +- + if (unlikely(dpa_xmit(priv, percpu_stats, &fd, egress_fq, conf_fq) < 0)) + goto xmit_failed; + diff --git a/patches/ask/kernel/0062-drivers__net__ppp__ppp_generic.c.patch b/patches/ask/kernel/0062-drivers__net__ppp__ppp_generic.c.patch new file mode 100644 index 0000000..0fddbb6 --- /dev/null +++ b/patches/ask/kernel/0062-drivers__net__ppp__ppp_generic.c.patch @@ -0,0 +1,30 @@ +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index f9f0f16..1f94967 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -55,6 +55,10 @@ + #include + #include + ++#if defined(CONFIG_CPE_FAST_PATH) ++#include ++#endif ++ + #define PPP_VERSION "2.4.2" + + /* +@@ -3535,6 +3539,14 @@ ppp_connect_channel(struct channel *pch, int unit) + + outl: + spin_unlock(&pch->upl); ++#if defined(CONFIG_CPE_FAST_PATH) ++ if ((ppp->dev) && (!ppp->closing)) { ++ rtnl_lock(); ++ rtmsg_ifinfo(RTM_NEWLINK, ppp->dev, 0, GFP_KERNEL, 0, NULL); ++ rtnl_unlock(); ++ } ++#endif ++ + out: + mutex_unlock(&pn->all_ppp_mutex); + return ret; diff --git a/patches/ask/kernel/0068-drivers__staging__fsl_qbman__qman_high.c.patch b/patches/ask/kernel/0068-drivers__staging__fsl_qbman__qman_high.c.patch new file mode 100644 index 0000000..5e5b21c --- /dev/null +++ b/patches/ask/kernel/0068-drivers__staging__fsl_qbman__qman_high.c.patch @@ -0,0 +1,371 @@ +diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c +index 4085aa9a2dcb..96c3122e665b 100644 +--- a/drivers/staging/fsl_qbman/qman_high.c ++++ b/drivers/staging/fsl_qbman/qman_high.c +@@ -34,6 +34,9 @@ + + #include "qman_low.h" + ++#include ++#include ++ + /* Compilation constants */ + #define DQRR_MAXFILL 15 + #define EQCR_ITHRESH 4 /* if EQCR congests, interrupt threshold */ +@@ -69,6 +72,33 @@ + spin_unlock(&__fq478->fqlock); \ + } while (0) + ++#if 1 ++#define display_ceetm_cmd(a,b,c) ++#else ++#define display_ceetm_cmd(a, b, c) _display_ceetm_cmd((char *)__func__, a, b, c) ++static void _display_ceetm_cmd(char *func, uint32_t verb, void *buf, uint32_t size) ++{ ++ uint8_t *ptr; ++ uint32_t ii,jj=0; ++ uint8_t buff[200]; ++ ++ ptr = buf; ++ jj = sprintf(buff, "%s::\n%02x ", func, verb); ++ for (ii = 1; ii <= size; ii++) { ++ if (ii && ((ii % 16) == 0)) ++ { ++ buff[jj] = 0; ++ printk("%s\n", buff); ++ jj = 0; ++ } ++ jj += sprintf(buff+jj, "%02x ", *ptr); ++ ptr++; ++ } ++ buff[jj] = 0; ++ printk("%s\n\n", buff); ++} ++#endif ++ + static inline void fq_set(struct qman_fq *fq, u32 mask) + { + set_bits(mask, &fq->flags); +@@ -128,6 +158,10 @@ struct qman_portal { + u8 alloced; + /* power management data */ + u32 save_isdr; ++#ifdef CONFIG_FSL_ASK_QMAN_PORTAL_NAPI ++ struct net_device *dummy_dev; ++ struct napi_struct napi; ++#endif + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + /* Keep a shadow copy of the DQRR on LE systems as the SW needs to + * do byte swaps of DQRR read only memory. First entry must be aligned +@@ -473,7 +507,16 @@ static irqreturn_t portal_isr(__always_unused int irq, void *ptr) + + /* DQRR-handling if it's interrupt-driven */ + if (is & QM_PIRQ_DQRI) { ++#ifndef CONFIG_FSL_ASK_QMAN_PORTAL_NAPI + __poll_portal_fast(p, CONFIG_FSL_QMAN_POLL_LIMIT); ++#else ++ /* Disable QMan IRQ and invoke NAPI */ ++ qman_p_irqsource_remove(p, QM_PIRQ_DQRI); ++ if (napi_schedule_prep(&p->napi)) ++ { ++ __napi_schedule(&p->napi); ++ } ++#endif + clear = QM_DQAVAIL_MASK | QM_PIRQ_DQRI; + } + +@@ -575,6 +618,27 @@ struct dev_pm_domain qman_portal_device_pm_domain = { + } + }; + ++ ++ ++#ifdef CONFIG_FSL_ASK_QMAN_PORTAL_NAPI ++static int qman_portal_dqrr_poll(struct napi_struct *napi, int budget) ++{ ++ struct qman_portal *portal = container_of(napi, struct qman_portal, napi); ++ ++ int cleaned = qman_p_poll_dqrr(portal, budget); ++ ++ if (cleaned < budget) { ++ int tmp; ++ napi_complete(napi); ++ tmp = qman_p_irqsource_add(portal, QM_PIRQ_DQRI); ++ // DPA_BUG_ON(tmp); ++ } ++ ++ return cleaned; ++} ++#endif ++ ++ + struct qman_portal *qman_create_portal( + struct qman_portal *portal, + const struct qm_portal_config *config, +@@ -737,6 +801,15 @@ struct qman_portal *qman_create_portal( + goto fail_dqrr_mr_empty; + } + } ++#ifdef CONFIG_FSL_ASK_QMAN_PORTAL_NAPI ++ /* Initialize NAPI for Rx processing */ ++ portal->dummy_dev = alloc_netdev_dummy(0); ++ if (!portal->dummy_dev) ++ goto fail_dqrr_mr_empty; ++ ++ netif_napi_add(portal->dummy_dev, &portal->napi, qman_portal_dqrr_poll); ++ napi_enable(&portal->napi); ++#endif + /* Success */ + portal->config = config; + /* +@@ -832,6 +902,15 @@ void qman_destroy_portal(struct qman_portal *qm) + const struct qm_portal_config *pcfg; + int i; + ++#ifdef CONFIG_FSL_ASK_QMAN_PORTAL_NAPI ++ if (qm->dummy_dev) { ++ napi_disable(&qm->napi); ++ netif_napi_del(&qm->napi); ++ free_netdev(qm->dummy_dev); ++ qm->dummy_dev = NULL; ++ } ++#endif ++ + /* Stop dequeues on the portal */ + qm_dqrr_sdqcr_set(&qm->p, 0); + +@@ -3170,6 +3245,7 @@ static int qman_ceetm_configure_lfqmt(struct qm_mcc_ceetm_lfqmt_config *opts) + p = get_affine_portal(); + PORTAL_IRQ_LOCK(p, irqflags); + ++ display_ceetm_cmd(QM_CEETM_VERB_LFQMT_CONFIG, opts, sizeof(struct qm_mcc_ceetm_lfqmt_config)); + mcc = qm_mc_start(&p->p); + mcc->lfqmt_config = *opts; + qm_mc_commit(&p->p, QM_CEETM_VERB_LFQMT_CONFIG); +@@ -3233,6 +3309,7 @@ static int qman_ceetm_configure_cq(struct qm_mcc_ceetm_cq_config *opts) + + mcc = qm_mc_start(&p->p); + mcc->cq_config = *opts; ++ display_ceetm_cmd(QM_CEETM_VERB_CQ_CONFIG, opts, sizeof(struct qm_mcc_ceetm_cq_config)); + qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_CONFIG); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); +@@ -3296,7 +3373,7 @@ static int qman_ceetm_configure_dct(struct qm_mcc_ceetm_dct_config *opts) + + p = get_affine_portal(); + PORTAL_IRQ_LOCK(p, irqflags); +- ++ display_ceetm_cmd(QM_CEETM_VERB_DCT_CONFIG, opts, sizeof(struct qm_mcc_ceetm_dct_config)); + mcc = qm_mc_start(&p->p); + mcc->dct_config = *opts; + qm_mc_commit(&p->p, QM_CEETM_VERB_DCT_CONFIG); +@@ -3360,6 +3437,8 @@ static int qman_ceetm_configure_class_scheduler( + + mcc = qm_mc_start(&p->p); + mcc->csch_config = *opts; ++ display_ceetm_cmd(QM_CEETM_VERB_CLASS_SCHEDULER_CONFIG, opts, ++ sizeof(struct qm_mcc_ceetm_class_scheduler_config)); + qm_mc_commit(&p->p, QM_CEETM_VERB_CLASS_SCHEDULER_CONFIG); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); +@@ -3410,7 +3489,7 @@ static int qman_ceetm_query_class_scheduler(struct qm_ceetm_channel *channel, + return 0; + } + +-static int qman_ceetm_configure_mapping_shaper_tcfc( ++int qman_ceetm_configure_mapping_shaper_tcfc( + struct qm_mcc_ceetm_mapping_shaper_tcfc_config *opts) + { + struct qm_mc_command *mcc; +@@ -3423,6 +3502,8 @@ static int qman_ceetm_configure_mapping_shaper_tcfc( + PORTAL_IRQ_LOCK(p, irqflags); + + mcc = qm_mc_start(&p->p); ++ display_ceetm_cmd(QM_CEETM_VERB_MAPPING_SHAPER_TCFC_CONFIG, opts, ++ sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + mcc->mst_config = *opts; + qm_mc_commit(&p->p, QM_CEETM_VERB_MAPPING_SHAPER_TCFC_CONFIG); + while (!(mcr = qm_mc_result(&p->p))) +@@ -3440,6 +3521,7 @@ static int qman_ceetm_configure_mapping_shaper_tcfc( + } + return 0; + } ++EXPORT_SYMBOL(qman_ceetm_configure_mapping_shaper_tcfc); + + static int qman_ceetm_query_mapping_shaper_tcfc( + struct qm_mcc_ceetm_mapping_shaper_tcfc_query *opts, +@@ -3485,7 +3567,7 @@ static int qman_ceetm_configure_ccgr(struct qm_mcc_ceetm_ccgr_config *opts) + + p = get_affine_portal(); + PORTAL_IRQ_LOCK(p, irqflags); +- ++ display_ceetm_cmd(QM_CEETM_VERB_CCGR_CONFIG, opts, sizeof(struct qm_mcc_ceetm_ccgr_config)); + mcc = qm_mc_start(&p->p); + mcc->ccgr_config = *opts; + +@@ -3903,6 +3985,7 @@ int qman_ceetm_lni_enable_shaper(struct qm_ceetm_lni *lni, int coupled, + lni->shaper_couple = coupled; + lni->oal = oal; + ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + config_opts.cid = cpu_to_be16(CEETM_COMMAND_LNI_SHAPER | lni->idx); + config_opts.dcpid = lni->dcp_idx; + config_opts.shaper_config.cpl = coupled; +@@ -3936,7 +4019,8 @@ int qman_ceetm_lni_disable_shaper(struct qm_ceetm_lni *lni) + pr_err("The shaper has been disabled\n"); + return -EINVAL; + } +- ++ ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + config_opts.cid = cpu_to_be16(CEETM_COMMAND_LNI_SHAPER | lni->idx); + config_opts.dcpid = lni->dcp_idx; + config_opts.shaper_config.cpl = lni->shaper_couple; +@@ -4173,6 +4257,7 @@ int qman_ceetm_lni_set_tcfcc(struct qm_ceetm_lni *lni, + return -EINVAL; + } + ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + query_opts.cid = cpu_to_be16(CEETM_COMMAND_TCFC | lni->idx); + query_opts.dcpid = lni->dcp_idx; + if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { +@@ -4254,6 +4339,7 @@ int qman_ceetm_channel_claim(struct qm_ceetm_channel **channel, + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + p->idx = channel_idx; + p->dcp_idx = lni->dcp_idx; + p->lni_idx = lni->idx; +@@ -4264,7 +4350,7 @@ int qman_ceetm_channel_claim(struct qm_ceetm_channel **channel, + channel_idx); + config_opts.dcpid = lni->dcp_idx; + config_opts.channel_mapping.map_lni_id = lni->idx; +- config_opts.channel_mapping.map_shaped = 0; ++ config_opts.channel_mapping.map_shaped = 1; + if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) { + pr_err("Can't map channel#%d for LNI#%d\n", + channel_idx, lni->idx); +@@ -4296,7 +4382,7 @@ int qman_ceetm_channel_release(struct qm_ceetm_channel *channel) + channel->dcp_idx); + return -EINVAL; + } +- ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + config_opts.cid = cpu_to_be16(CEETM_COMMAND_CHANNEL_SHAPER | + channel->idx); + config_opts.dcpid = channel->dcp_idx; +@@ -4334,7 +4420,7 @@ int qman_ceetm_channel_enable_shaper(struct qm_ceetm_channel *channel, + pr_err("This channel shaper has been enabled!\n"); + return -EINVAL; + } +- ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + channel->shaper_enable = 1; + channel->shaper_couple = coupled; + +@@ -4347,6 +4433,7 @@ int qman_ceetm_channel_enable_shaper(struct qm_ceetm_channel *channel, + return -EINVAL; + } + ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + config_opts.cid = cpu_to_be16(CEETM_COMMAND_CHANNEL_MAPPING | + channel->idx); + config_opts.dcpid = channel->dcp_idx; +@@ -4441,7 +4528,7 @@ int qman_ceetm_channel_set_commit_rate(struct qm_ceetm_channel *channel, + pr_err("Fail to get the current channel shaper setting\n"); + return -EINVAL; + } +- ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + channel->cr_token_rate.whole = token_rate->whole; + channel->cr_token_rate.fraction = token_rate->fraction; + channel->cr_token_bucket_limit = token_limit; +@@ -4534,7 +4621,8 @@ int qman_ceetm_channel_set_excess_rate(struct qm_ceetm_channel *channel, + pr_err("Fail to get the current channel shaper setting\n"); + return -EINVAL; + } +- ++ ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + channel->er_token_rate.whole = token_rate->whole; + channel->er_token_rate.fraction = token_rate->fraction; + channel->er_token_bucket_limit = token_limit; +@@ -4618,7 +4706,7 @@ int qman_ceetm_channel_set_weight(struct qm_ceetm_channel *channel, + pr_err("This channel is a shaped one\n"); + return -EINVAL; + } +- ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + channel->cr_token_bucket_limit = token_limit; + config_opts.cid = cpu_to_be16(CEETM_COMMAND_CHANNEL_SHAPER | + channel->idx); +@@ -4668,7 +4756,7 @@ int qman_ceetm_channel_set_group(struct qm_ceetm_channel *channel, int group_b, + pr_err("Can't query channel#%d's scheduler!\n", channel->idx); + return -EINVAL; + } +- ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_mapping_shaper_tcfc_config)); + config_opts.cqcid = cpu_to_be16(channel->idx); + config_opts.dcpid = channel->dcp_idx; + config_opts.gpc_combine_flag = !group_b; +@@ -4759,6 +4847,7 @@ int qman_ceetm_channel_set_group_er_eligibility(struct qm_ceetm_channel + channel->idx); + return -EINVAL; + } ++ memset(&csch_config, 0, sizeof(struct qm_mcc_ceetm_class_scheduler_config)); + csch_config.cqcid = cpu_to_be16(channel->idx); + csch_config.dcpid = channel->dcp_idx; + csch_config.gpc_combine_flag = csch_query.gpc_combine_flag; +@@ -4806,6 +4895,7 @@ int qman_ceetm_channel_set_cq_cr_eligibility(struct qm_ceetm_channel *channel, + channel->idx); + return -EINVAL; + } ++ memset(&csch_config, 0, sizeof(struct qm_mcc_ceetm_class_scheduler_config)); + csch_config.cqcid = cpu_to_be16(channel->idx); + csch_config.dcpid = channel->dcp_idx; + csch_config.gpc_combine_flag = csch_query.gpc_combine_flag; +@@ -4889,7 +4979,7 @@ int qman_ceetm_cq_claim(struct qm_ceetm_cq **cq, + pr_err("Can't allocate memory for CQ#%d!\n", idx); + return -ENOMEM; + } +- ++ memset(&cq_config, 0, sizeof(struct qm_mcc_ceetm_cq_config)); + list_add_tail(&p->node, &channel->class_queues); + p->idx = idx; + p->is_claimed = 1; +@@ -4938,7 +5028,7 @@ int qman_ceetm_cq_claim_A(struct qm_ceetm_cq **cq, + pr_err("Can't allocate memory for CQ#%d!\n", idx); + return -ENOMEM; + } +- ++ memset(&cq_config, 0, sizeof(struct qm_mcc_ceetm_cq_config)); + list_add_tail(&p->node, &channel->class_queues); + p->idx = idx; + p->is_claimed = 1; +@@ -4986,7 +5076,7 @@ int qman_ceetm_cq_claim_B(struct qm_ceetm_cq **cq, + pr_err("Can't allocate memory for CQ#%d!\n", idx); + return -ENOMEM; + } +- ++ memset(&cq_config, 0, sizeof(struct qm_mcc_ceetm_cq_config)); + list_add_tail(&p->node, &channel->class_queues); + p->idx = idx; + p->is_claimed = 1; +@@ -5040,7 +5130,7 @@ int qman_ceetm_set_queue_weight(struct qm_ceetm_cq *cq, + cq->parent->idx); + return -EINVAL; + } +- ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_class_scheduler_config)); + config_opts.cqcid = cpu_to_be16(cq->parent->idx); + config_opts.dcpid = cq->parent->dcp_idx; + config_opts.crem = query_result.crem; +@@ -5257,6 +5347,7 @@ int qman_ceetm_lfq_claim(struct qm_ceetm_lfq **lfq, + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; ++ memset(&lfqmt_config, 0, sizeof(struct qm_mcc_ceetm_lfqmt_config)); + p->idx = lfqid; + p->dctidx = (u16)(lfqid & CEETM_LFQMT_LFQID_LSB); + p->parent = cq->parent; diff --git a/patches/ask/kernel/0071-include__linux__if_bridge.h.patch b/patches/ask/kernel/0071-include__linux__if_bridge.h.patch new file mode 100644 index 0000000..6bf854c --- /dev/null +++ b/patches/ask/kernel/0071-include__linux__if_bridge.h.patch @@ -0,0 +1,28 @@ +diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h +index 6d4e3d1b1111..7c0d4c2e2222 100644 +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -65,6 +65,23 @@ void brioctl_set(int (*hook)(struct net *net, unsigned int cmd, + void __user *uarg)); + int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg); + ++#if defined(CONFIG_CPE_FAST_PATH) ++struct brevent_fdb_update { ++ char *mac_addr; ++ struct net_device *dev; ++ struct net_device *brdev; ++}; ++ ++enum brevent_notif_type { ++ BREVENT_PORT_DOWN = 1, /* arg is struct net_device ptr */ ++ BREVENT_FDB_UPDATE /* arg is struct brevent_fdb_update ptr */ ++}; ++ ++int register_brevent_notifier(struct notifier_block *nb); ++int unregister_brevent_notifier(struct notifier_block *nb); ++int call_brevent_notifiers(unsigned long val, void *v); ++#endif ++ + #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING) + int br_multicast_list_adjacent(struct net_device *dev, + struct list_head *br_ip_list); diff --git a/patches/ask/kernel/0078-include__net__xfrm.h.patch b/patches/ask/kernel/0078-include__net__xfrm.h.patch new file mode 100644 index 0000000..5e11b93 --- /dev/null +++ b/patches/ask/kernel/0078-include__net__xfrm.h.patch @@ -0,0 +1,76 @@ +diff --git a/include/net/xfrm.h b/include/net/xfrm.h +index 0a14daa..ff8a1ad 100644 +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -196,6 +196,12 @@ struct xfrm_state { + struct hlist_node bysrc; + }; + struct hlist_node byspi; ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ struct hlist_node byh; ++ u16 handle; ++ u16 in_byh_hash; ++ u16 parent_sa_handle; /* handle of the old SA from which this SA is created using rekey */ ++#endif + struct hlist_node byseq; + struct hlist_node state_cache; + struct hlist_node state_cache_input; +@@ -314,6 +320,11 @@ struct xfrm_state { + /* Private data of this transformer, format is opaque, + * interpreted by xfrm_type methods. */ + void *data; ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ /* Intended direction of this state, used for offloading */ ++ int offloaded; ++ u64 curr_time; ++#endif + u8 dir; + + const struct xfrm_mode_cbs *mode_cbs; +@@ -337,6 +348,13 @@ enum { + XFRM_STATE_EXPIRED, + XFRM_STATE_DEAD + }; ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++enum { ++ XFRM_STATE_DIR_UNKNOWN, ++ XFRM_STATE_DIR_IN, ++ XFRM_STATE_DIR_OUT, ++}; ++#endif + + /* callback structure passed from either netlink or pfkey */ + struct km_event { +@@ -1173,6 +1191,32 @@ struct sec_path { + + struct sec_path *secpath_set(struct sk_buff *skb); + ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++struct xfrm_input_shared { ++ struct sk_buff *skb; ++ int xfrm_nr, first, xfrm_encap; ++ struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; ++ __u16 encap_type; ++ int decaps; ++ u32 seq, spi; ++ unsigned int nhoff; ++ int nexthdr; ++ int (*callback)(struct xfrm_input_shared *sh); ++ atomic_t refcnt; ++}; ++ ++static inline void xfrm_shared_get(struct xfrm_input_shared *sh) ++{ ++ atomic_inc(&sh->refcnt); ++} ++ ++static inline void xfrm_shared_put(struct xfrm_input_shared *sh) ++{ ++ if (atomic_dec_and_test(&sh->refcnt)) ++ kfree(sh); ++} ++#endif ++ + static inline void + secpath_reset(struct sk_buff *skb) + { diff --git a/patches/ask/kernel/0086-include__uapi__linux__netfilter__nfnetlink_conntrack.h.patch b/patches/ask/kernel/0086-include__uapi__linux__netfilter__nfnetlink_conntrack.h.patch new file mode 100644 index 0000000..8ba47df --- /dev/null +++ b/patches/ask/kernel/0086-include__uapi__linux__netfilter__nfnetlink_conntrack.h.patch @@ -0,0 +1,36 @@ +diff --git a/include/uapi/linux/netfilter/nfnetlink_conntrack.h b/include/uapi/linux/netfilter/nfnetlink_conntrack.h +index 43233af..2e401ae 100644 +--- a/include/uapi/linux/netfilter/nfnetlink_conntrack.h ++++ b/include/uapi/linux/netfilter/nfnetlink_conntrack.h +@@ -58,6 +58,10 @@ enum ctattr_type { + CTA_FILTER, + CTA_STATUS_MASK, + CTA_TIMESTAMP_EVENT, ++ CTA_LAYERSCAPE_FP_ORIG, ++ CTA_LAYERSCAPE_FP_REPLY, ++ CTA_QOSCONNMARK, ++ CTA_QOSCONNMARK_PAD, + __CTA_MAX + }; + #define CTA_MAX (__CTA_MAX - 1) +@@ -243,6 +247,20 @@ enum ctattr_secctx { + }; + #define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1) + ++enum ctattr_comcerto_fp { ++ CTA_COMCERTO_FP_UNSPEC, ++ CTA_COMCERTO_FP_MARK, ++ CTA_COMCERTO_FP_IFINDEX, ++ CTA_COMCERTO_FP_IIF, ++ CTA_COMCERTO_FP_UNDERLYING_IIF, ++ CTA_COMCERTO_FP_UNDERLYING_VID, ++#ifndef IPSEC_FLOW_CACHE ++ CTA_COMCERTO_FP_XFRM_HANDLE, ++#endif ++ __CTA_COMCERTO_FP_MAX ++}; ++#define CTA_COMCERTO_FP_MAX (__CTA_COMCERTO_FP_MAX - 1) ++ + enum ctattr_stats_cpu { + CTA_STATS_UNSPEC, + CTA_STATS_SEARCHED, /* no longer used */ diff --git a/patches/ask/kernel/0100-net__bridge__br_private.h.patch b/patches/ask/kernel/0100-net__bridge__br_private.h.patch new file mode 100644 index 0000000..189ee5b --- /dev/null +++ b/patches/ask/kernel/0100-net__bridge__br_private.h.patch @@ -0,0 +1,28 @@ +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index 9a3d6f2b8c1e..b4f7b2c1d9aa 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -620,6 +620,11 @@ struct br_input_skb_cb { + #endif + + u32 backup_nhid; ++ ++#ifdef CONFIG_CPE_FAST_PATH ++ u16 vid; ++ u8 untagged:1; ++#endif + }; + + #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) +@@ -859,6 +864,11 @@ int br_fdb_add_local(struct net_bridge *br, struct net_bridge_port *source, + void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, + const unsigned char *addr, u16 vid, unsigned long flags); + ++#if defined(CONFIG_CPE_FAST_PATH) ++extern void br_fdb_register_can_expire_cb(int(*cb)(unsigned char *mac_addr, struct net_device *dev)); ++extern void br_fdb_deregister_can_expire_cb(void); ++#endif ++ + int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, const unsigned char *addr, u16 vid, + bool *notified, struct netlink_ext_ack *extack); diff --git a/patches/ask/kernel/0103-net__core__dev.c.patch b/patches/ask/kernel/0103-net__core__dev.c.patch new file mode 100644 index 0000000..78bdc3e --- /dev/null +++ b/patches/ask/kernel/0103-net__core__dev.c.patch @@ -0,0 +1,131 @@ +diff --git a/net/core/dev.c b/net/core/dev.c +index 2acfa44..02e304b 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -176,6 +176,10 @@ static int call_netdevice_notifiers_extack(unsigned long val, + struct net_device *dev, + struct netlink_ext_ack *extack); + ++#if defined(CONFIG_CPE_FAST_PATH) ++static fp_iface_stats_get fast_path_stats_get; ++#endif ++ + static DEFINE_MUTEX(ifalias_mutex); + + /* protects napi_hash addition/deletion and napi_gen_id */ +@@ -4002,9 +4006,15 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device + skb = segs; + } + } else { +- if (skb_needs_linearize(skb, features) && +- __skb_linearize(skb)) +- goto out_kfree_skb; ++ /* Linearize only if IPsec policy is not selected. */ ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ if (!skb->ipsec_offload) ++#endif ++ { ++ if (skb_needs_linearize(skb, features) && ++ __skb_linearize(skb)) ++ goto out_kfree_skb; ++ } + + /* If packet is not checksummed and device does not + * support checksumming for this protocol, complete +@@ -4792,6 +4802,40 @@ out: + } + EXPORT_SYMBOL(__dev_queue_xmit); + ++#if defined(CONFIG_CPE_FAST_PATH) ++/* WiFi IPsec offload hook - allows cdx to intercept packets for IPsec ++ * processing when the packet is transmitted on a wifi interface. ++ */ ++dpaa_wifi_xmit_local_hook_t dpaa_wifi_xmit_local_ipsec_handler; ++EXPORT_SYMBOL(dpaa_wifi_xmit_local_ipsec_handler); ++ ++/* Register a hook function for IPsec offload on wifi interfaces. */ ++int dpa_register_wifi_xmit_local_hook(dpaa_wifi_xmit_local_hook_t hookfn) ++{ ++ if (dpaa_wifi_xmit_local_ipsec_handler) { ++ pr_warn("%s: hook already registered\n", __func__); ++ return -1; ++ } ++ dpaa_wifi_xmit_local_ipsec_handler = hookfn; ++ return 0; ++} ++EXPORT_SYMBOL(dpa_register_wifi_xmit_local_hook); ++ ++/* Unregister the IPsec offload hook. */ ++void dpa_unregister_wifi_xmit_local_hook(void) ++{ ++ dpaa_wifi_xmit_local_ipsec_handler = NULL; ++} ++EXPORT_SYMBOL(dpa_unregister_wifi_xmit_local_hook); ++ ++/* Original dev_queue_xmit - called when wifi hook is not applicable. */ ++int original_dev_queue_xmit(struct sk_buff *skb) ++{ ++ return __dev_queue_xmit(skb, NULL); ++} ++EXPORT_SYMBOL(original_dev_queue_xmit); ++#endif ++ + int __dev_direct_xmit(struct sk_buff *skb, u16 queue_id) + { + struct net_device *dev = skb->dev; +@@ -5862,6 +5906,15 @@ static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc, + + trace_netif_receive_skb(skb); + ++#ifdef CONFIG_CPE_FAST_PATH ++ /* ifindex of device we arrived on, now skb->skb_iif ++ * always tracks skb->dev. ++ */ ++ if (!skb->iif_index) ++ skb->iif_index = skb->dev->ifindex; ++ if (!skb->underlying_iif) ++ skb->underlying_iif = skb->dev->ifindex; ++#endif + orig_dev = skb->dev; + + skb_reset_network_header(skb); +@@ -7627,9 +7680,9 @@ static int __napi_poll(struct napi_struct *n, bool *repoll) + return work; + } + + /* Flush too old packets. If HZ < 1000, flush all packets */ +- gro_flush_normal(&n->gro, HZ >= 1000); ++ gro_flush(&n->gro, HZ >= 1000); + + /* Some drivers may have called napi_schedule + * prior to exhausting their budget. + */ +@@ -11762,10 +11812,28 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, + storage->rx_otherhost_dropped += READ_ONCE(core_stats->rx_otherhost_dropped); + } + } ++#if defined(CONFIG_CPE_FAST_PATH) ++ if (fast_path_stats_get) ++ fast_path_stats_get(dev, storage); ++#endif + return storage; + } + EXPORT_SYMBOL(dev_get_stats); + ++#if defined(CONFIG_CPE_FAST_PATH) ++void dev_fp_stats_get_register(fp_iface_stats_get func) ++{ ++ fast_path_stats_get = func; ++} ++EXPORT_SYMBOL(dev_fp_stats_get_register); ++ ++void dev_fp_stats_get_deregister(void) ++{ ++ fast_path_stats_get = NULL; ++} ++EXPORT_SYMBOL(dev_fp_stats_get_deregister); ++#endif ++ + /** + * dev_fetch_sw_netstats - get per-cpu network device statistics + * @s: place to store stats diff --git a/patches/ask/kernel/0108-net__ipv4__ip_output.c.patch b/patches/ask/kernel/0108-net__ipv4__ip_output.c.patch new file mode 100644 index 0000000..6a16fb0 --- /dev/null +++ b/patches/ask/kernel/0108-net__ipv4__ip_output.c.patch @@ -0,0 +1,79 @@ +diff -uNr a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +--- a/net/ipv4/ip_output.c 2026-05-08 18:06:42.017639432 +0000 ++++ b/net/ipv4/ip_output.c 2026-05-08 18:06:42.100831810 +0000 +@@ -103,6 +103,17 @@ + { + struct iphdr *iph = ip_hdr(skb); + ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) ++ /* ++ * The tunnel header is not added in slow path and packet may be ipv6 ++ * (IPv6 traffic and IPv4 IPSec tunnel) in case IPv6 over IPv4 IPsec ++ * tunnel. When it assumes as IPv4 and accessing IP header from SKB ++ * causing invalid accesses it leading to kernel panic. ++ * Avoiding ip header checks. ++ */ ++ if ((skb->ipsec_offload) && (iph->version == 6)) ++ goto sendout; ++#endif /* endif for CONFIG_INET_IPSEC_OFFLOAD */ + IP_INC_STATS(net, IPSTATS_MIB_OUTREQUESTS); + + iph_set_totlen(iph, skb->len); +@@ -115,8 +126,17 @@ + if (unlikely(!skb)) + return 0; + ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) ++sendout: ++#endif + skb->protocol = htons(ETH_P_IP); + ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) ++ if (skb->ipsec_offload) { ++ dst_output(net, sk, skb); ++ return 0; ++ } else ++#endif /* endif for CONFIG_INET_IPSEC_OFFLOAD */ + return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, + net, sk, skb, NULL, skb_dst_dev(skb), + dst_output); +@@ -309,7 +329,11 @@ + if (skb_is_gso(skb)) + return ip_finish_output_gso(net, sk, skb, mtu); + +- if (skb->len > mtu || IPCB(skb)->frag_max_size) ++ if ( ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) ++ (skb->ipsec_offload == 0) && ++#endif ++ (skb->len > mtu || IPCB(skb)->frag_max_size)) + return ip_fragment(net, sk, skb, mtu, ip_finish_output2); + + return ip_finish_output2(net, sk, skb); +@@ -435,6 +459,16 @@ + skb->dev = dev; + skb->protocol = htons(ETH_P_IP); + ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) ++ /* Bypass invoking post routing hooks since the tunnel header and ESP ++ * processing is not done in slow path for IPSec offloaded cases ++ */ ++ if (skb->ipsec_offload) { ++ ret_val = ip_finish_output(net, sk, skb); ++ rcu_read_unlock(); ++ return ret_val; ++ } ++#endif + ret_val = NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, + net, sk, skb, indev, dev, + ip_finish_output, +@@ -559,6 +593,9 @@ + skb_dst_copy(to, from); + to->dev = from->dev; + to->mark = from->mark; ++#if defined(CONFIG_CPE_FAST_PATH) ++ to->qosmark = from->qosmark; ++#endif + + skb_copy_hash(to, from); + diff --git a/patches/ask/kernel/0112-net__ipv6__ip6_output.c.patch b/patches/ask/kernel/0112-net__ipv6__ip6_output.c.patch new file mode 100644 index 0000000..3158c5f --- /dev/null +++ b/patches/ask/kernel/0112-net__ipv6__ip6_output.c.patch @@ -0,0 +1,73 @@ +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index f904739..e26e743 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -80,6 +80,13 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + + hdr = ipv6_hdr(skb); + daddr = &hdr->daddr; ++#if defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ /* For IPv4 over IPv6 IPsec tunnel cases, just send the packet out ++ * since the packet is IPv4 ++ */ ++ if((skb->ipsec_offload) && (hdr->version == 4)) ++ goto sendout; ++#endif /* endif for CONFIG_INET6_IPSEC_OFFLOAD */ + if (ipv6_addr_is_multicast(daddr)) { + if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(sk) && + ((mroute6_is_socket(net, skb) && +@@ -111,6 +118,9 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + } + } + ++#if defined(CONFIG_INET6_IPSEC_OFFLOAD) ++sendout: ++#endif /* endif for CONFIG_INET6_IPSEC_OFFLOAD */ + if (lwtunnel_xmit_redirect(dst->lwtstate)) { + int res = lwtunnel_xmit(skb); + +@@ -202,8 +212,15 @@ static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff + if (skb_is_gso(skb)) + return ip6_finish_output_gso(net, sk, skb, mtu); + +- if (skb->len > mtu || +- (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) ++ if ( ++#if defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ /* If ipsec offload is there, do not do fragment. So, when IPSec ++ * offload is enabled it directly calls ip6_finish_output2 ++ */ ++ (skb->ipsec_offload == 0) && ++#endif ++ ((skb->len > mtu) || ++ (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size))) + return ip6_fragment(net, sk, skb, ip6_finish_output2); + + return ip6_finish_output2(net, sk, skb); +@@ -244,6 +261,16 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb) + return 0; + } + ++#if defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ /* Bypass invoking post routing hooks since the tunnel header and ESP ++ * processing is not done in slow path for IPSec offloaded cases ++ */ ++ if (skb->ipsec_offload) { ++ ret = ip6_finish_output(net, sk, skb); ++ rcu_read_unlock(); ++ return ret; ++ } ++#endif + ret = NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, + net, sk, skb, indev, dev, + ip6_finish_output, +@@ -697,6 +724,9 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) + skb_dst_set(to, dst_clone(skb_dst(from))); + to->dev = from->dev; + to->mark = from->mark; ++#if defined(CONFIG_CPE_FAST_PATH) ++ to->qosmark = from->qosmark; ++#endif + + skb_copy_hash(to, from); + diff --git a/patches/ask/kernel/0115-net__ipv6__output_core.c.patch b/patches/ask/kernel/0115-net__ipv6__output_core.c.patch new file mode 100644 index 0000000..65c7704 --- /dev/null +++ b/patches/ask/kernel/0115-net__ipv6__output_core.c.patch @@ -0,0 +1,38 @@ +diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c +index 1c9b283..5682505 100644 +--- a/net/ipv6/output_core.c ++++ b/net/ipv6/output_core.c +@@ -130,7 +130,19 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb) + len = skb->len - sizeof(struct ipv6hdr); + if (len > IPV6_MAXPLEN) + len = 0; ++ ++#if defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ /* ++ * Since tunnel header is not added in slow path and route cache entry ++ * lookup is changed to perform lookup on tunnel header, dst_output() ++ * may reach IPv6 output for IPv4-over-IPv6 IPsec tunnel packets. Only ++ * update the IPv6 payload length when the skb really carries IPv6 here. ++ */ ++ if (ipv6_hdr(skb)->version == 6) ++ ipv6_hdr(skb)->payload_len = htons(len); ++#else + ipv6_hdr(skb)->payload_len = htons(len); ++#endif + IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); + + /* if egress device is enslaved to an L3 master device pass the +@@ -142,6 +154,13 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb) + + skb->protocol = htons(ETH_P_IPV6); + ++#if defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ if (skb->ipsec_offload) { ++ dst_output(net, sk, skb); ++ return 0; ++ } ++#endif ++ + return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, + net, sk, skb, NULL, skb_dst_dev(skb), + dst_output); diff --git a/patches/ask/kernel/0119-net__key__af_key.c.patch b/patches/ask/kernel/0119-net__key__af_key.c.patch new file mode 100644 index 0000000..39a33ab --- /dev/null +++ b/patches/ask/kernel/0119-net__key__af_key.c.patch @@ -0,0 +1,949 @@ +diff --git a/net/key/af_key.c b/net/key/af_key.c +index c56bb4f451e6..7225be6880e1 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -26,8 +26,184 @@ + #include + #include + #include ++#if defined(CONFIG_INET_IPSEC_OFFLOAD)|| defined(CONFIG_INET6_IPSEC_OFFLOAD) ++#include ++#endif + + #include ++#if defined(CONFIG_INET_IPSEC_OFFLOAD)|| defined(CONFIG_INET6_IPSEC_OFFLOAD) ++#include ++#define NLKEY_SUPPORT 1 ++#else ++#undef NLKEY_SUPPORT ++#endif ++ ++#ifdef NLKEY_SUPPORT ++#include ++#include ++#include ++#include ++ ++ ++extern int xfrm_get_tos(struct flowi *fl, int family); ++ ++ ++#define NLKEY_SA_CREATE 0x0A01 ++#define NLKEY_SA_DELETE 0x0A02 ++#define NLKEY_SA_FLUSH 0x0A03 ++#define NLKEY_SA_SET_KEYS 0x0A04 ++#define NLKEY_SA_SET_TUNNEL 0x0A05 ++#define NLKEY_SA_SET_NATT 0x0A06 ++#define NLKEY_SA_SET_STATE 0x0A07 ++#define NLKEY_SA_SET_LIFETIME 0x0A08 ++#define NLKEY_SA_NOTIFY 0x0A09 ++#define NLKEY_SA_INFO_UPDATE 0x0A0C ++#define NLKEY_SA_SET_OFFLOAD 0x0A0D ++#define NLKEY_FLOW_ADD 0x0A11 ++#define NLKEY_FLOW_REMOVE 0x0A12 ++#define NLKEY_FLOW_NOTIFY 0x0A13 ++#define NLKEY_NULL_MSG 0x0000 ++ ++#define NLKEY_HDR_LEN 4 ++#define NLKEY_MSG_LEN 256 ++ ++#define NLKEY_MAX_NUM_KEYS 2 ++#define NLKEY_MAX_KEY_LEN (512 / 8) ++ ++struct nlkey_msg { ++ /* message data */ ++ unsigned short fcode; ++ unsigned short length; ++ unsigned short payload[(NLKEY_MSG_LEN /sizeof(unsigned short))]; ++}; ++/* sizeof(nlkey_msg) = 4 + 256 */ ++ ++struct nlkey_sa_id { ++ unsigned int spi; ++ unsigned char sa_type; ++ unsigned char proto_family; ++ unsigned char replay_window; ++#define NLKEY_SAFLAGS_ESN 0x1 ++#define NLKEY_SAFLAGS_INBOUND 0x2 ++ unsigned char flags; ++ unsigned int dst_ip[4]; ++ unsigned int src_ip[4]; ++ unsigned short mtu; ++ unsigned short dev_mtu; ++ ++}; ++/* sizeof(nlkey_sa_id) = 24 */ ++ ++struct nlkey_sa_create { ++ unsigned short sagd; ++ unsigned short parent_sa_sagd; /*sagd value of old SA from which this SA is rekeyed.*/ ++ struct nlkey_sa_id said; ++}; ++/* sizeof(nlkey_sa_delete) = 28 */ ++ ++struct nlkey_sa_delete { ++ unsigned short sagd; ++ unsigned short rsvd; ++}; ++/* sizeof(nlkey_sa_delete) = 4 */ ++ ++struct nlkey_sa_set_tunnel { ++ unsigned short sagd; ++ unsigned char rsvd; ++ unsigned char proto_family; ++ union { ++ struct iphdr ipv4h; ++ struct ipv6hdr ipv6h; ++ } h; ++}; ++/* sizeof(nlkey_sa_set_tunnel) = 36 */ ++ ++struct nlkey_sa_set_natt { ++ unsigned short sagd; ++ unsigned short sport; ++ unsigned short dport; ++ unsigned short rsvd; ++}; ++/* sizeof(nlkey_sa_set_natt) = 4 */ ++ ++struct nlkey_sa_set_state { ++ unsigned short sagd; ++ unsigned short parent_sa_sagd; ++ unsigned short state; ++ unsigned short rsvd2; ++}; ++/* sizeof(nlkey_sa_set_natt) = 8 */ ++ ++struct nlkey_key_desc { ++ unsigned short key_bits; ++ unsigned char key_alg; ++ unsigned char key_type; ++ unsigned char key[NLKEY_MAX_KEY_LEN]; ++}; ++/* sizeof(nlkey_key_desc) = 36 */ ++ ++struct nlkey_sa_set_keys { ++ unsigned short sagd; ++ unsigned short rsvd; ++ unsigned short num_keys; ++ unsigned short rsvd2; ++ struct nlkey_key_desc keys[NLKEY_MAX_NUM_KEYS]; ++}; ++/* sizeof(nlkey_sa_set_keys) = 80 */ ++ ++struct nlkey_lifetime_desc { ++ unsigned int allocations; ++ unsigned int bytes[2]; ++}; ++/* sizeof(nlkey_sa_set_lifetime) = 12 */ ++ ++struct nlkey_sa_set_lifetime { ++ unsigned short sagd; ++ unsigned short rsvd; ++ struct nlkey_lifetime_desc hard_time; ++ struct nlkey_lifetime_desc soft_time; ++ struct nlkey_lifetime_desc current_time; ++}; ++/* sizeof(nlkey_sa_set_lifetime) = 40 */ ++ ++/* SA notifications */ ++#define IPSEC_SOFT_EXPIRE 0 ++#define IPSEC_HARD_EXPIRE 1 ++ ++struct nlkey_sa_notify { ++ unsigned short sagd; ++ unsigned short rsvd; ++ unsigned int action; ++}; ++/* sizeof(nlkey_sa_notify) = 8 */ ++ ++/* SA Info update */ ++ ++struct nlkey_sa_info { ++ unsigned short sagd; ++ unsigned short rsvd; ++ unsigned long long bytes; ++ unsigned long long packets; ++}; ++/* sizeof(nlkey_sa_info) = */ ++ ++ ++static int ipsec_nlkey_send(struct net *net, struct xfrm_state *x, const struct km_event *c); ++static void ipsec_nlkey_rcv(struct sk_buff *skb); ++static void ipsec_nlkey_init(void); ++static unsigned short ipsec_sacode_to_nlkeycode(unsigned short sa_code); ++static struct sk_buff * ipsec_xfrm2nlkey (struct net *net, struct xfrm_state *x, ++ const struct km_event *c, unsigned short *msg_id); ++static int ipsec_nlkey_set_said(struct net *net, struct xfrm_state *x, const struct km_event *c, struct nlkey_sa_id *said); ++ ++void flow_cache_remove(const struct flowi *fl, unsigned short family, ++ unsigned short dir); ++/* netlink NETLINK_KEY socket */ ++struct sock *nlkey_socket = NULL; ++ ++#endif ++/************************************************************************************/ ++ + + #define _X2KEY(x) ((x) == XFRM_INF ? 0 : (x)) + #define _KEY2X(x) ((x) == 0 ? XFRM_INF : (x)) +@@ -876,6 +1051,10 @@ static struct sk_buff *__pfkey_xfrm_state2msg(const struct xfrm_state *x, + sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP; + if (x->props.flags & XFRM_STATE_NOPMTUDISC) + sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC; ++#ifdef NLKEY_SUPPORT ++ if (x->props.flags & XFRM_STATE_ESN) ++ sa->sadb_sa_flags |= SADB_SAFLAGS_ESN; ++#endif + + /* hard time */ + if (hsc & 2) { +@@ -908,6 +1087,11 @@ static struct sk_buff *__pfkey_xfrm_state2msg(const struct xfrm_state *x, + lifetime->sadb_lifetime_bytes = x->curlft.bytes; + lifetime->sadb_lifetime_addtime = x->curlft.add_time; + lifetime->sadb_lifetime_usetime = x->curlft.use_time; ++ ++#if defined(CONFIG_INET_IPSEC_OFFLOAD)|| defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ lifetime->sadb_lifetime_usetime = x->curr_time; ++#endif ++ + /* src address */ + addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size); + addr->sadb_address_len = +@@ -1133,6 +1317,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, + x->props.flags |= XFRM_STATE_DECAP_DSCP; + if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC) + x->props.flags |= XFRM_STATE_NOPMTUDISC; ++#ifdef NLKEY_SUPPORT ++ if (sa->sadb_sa_flags & SADB_SAFLAGS_ESN) ++ x->props.flags |= XFRM_STATE_ESN; ++#endif + + lifetime = ext_hdrs[SADB_EXT_LIFETIME_HARD - 1]; + if (lifetime != NULL) { +@@ -3076,6 +3264,12 @@ static int pfkey_send_notify(struct xfrm_state *x, const struct km_event *c) + struct net *net = x ? xs_net(x) : c->net; + struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); + ++ ++#ifdef NLKEY_SUPPORT ++ /* send message to the user space through NETLINK_KEY socket*/ ++ ipsec_nlkey_send(net, x, c); ++#endif ++ + if (atomic_read(&net_pfkey->socks_nr) == 0) + return 0; + +@@ -3863,6 +4057,687 @@ static struct xfrm_mgr pfkeyv2_mgr = + .is_alive = pfkey_is_alive, + }; + ++ ++#ifdef NLKEY_SUPPORT ++extern struct xfrm_state *xfrm_state_lookup_byhandle(struct net *net, u16 handle); ++ ++static unsigned short ipsec_sacode_to_nlkeycode(unsigned short sa_code) ++{ ++ unsigned nlkey_code; ++ ++ switch (sa_code) ++ { ++ case XFRM_MSG_DELSA: ++ nlkey_code = NLKEY_SA_DELETE; ++ break; ++ case XFRM_MSG_NEWSA: ++ case XFRM_MSG_UPDSA: ++ nlkey_code = NLKEY_SA_CREATE; ++ break; ++ case XFRM_MSG_FLUSHSA: ++ nlkey_code = NLKEY_SA_FLUSH; ++ break; ++ case XFRM_MSG_EXPIRE: ++ nlkey_code = NLKEY_SA_SET_STATE; ++ break; ++ default: ++ nlkey_code = NLKEY_NULL_MSG; ++ break; ++ } ++ ++ return nlkey_code; ++} ++ ++static void ipsec_nlkey_rcv(struct sk_buff *skb) ++{ ++ struct nlmsghdr *nlh = NULL; ++ struct nlkey_msg *msg = NULL; ++ struct flowi flow; ++ unsigned short *p; ++ unsigned short family, dir; ++ struct xfrm_state *x; ++ struct nlkey_sa_notify sa_notify_msg; ++ struct nlkey_sa_info sa_info_msg; ++ ++ /* extract message from skb */ ++ nlh = (struct nlmsghdr *)skb->data; ++ ++ msg = (struct nlkey_msg *)NLMSG_DATA(nlh); ++ ++ //printk(KERN_INFO "ipsec_nlkey_rcv fcode: 0x%x length: %d bytes\n",msg->fcode,msg->length); ++ ++ /* process command received from user space */ ++ switch(msg->fcode) ++ { ++ case NLKEY_FLOW_REMOVE: ++ //printk(KERN_INFO "ipsec_nlkey_rcv NLKEY_FLOW_REMOVE\n"); ++ p = msg->payload; ++ memcpy(&flow, p, sizeof(struct flowi)); p += sizeof(struct flowi)/2; ++ family = *p; p++; ++ dir = *p; p++; ++ flow_cache_remove(&flow, family, dir); ++ break; ++ ++ case NLKEY_SA_NOTIFY: ++ //printk(KERN_INFO "ipsec_nlkey_rcv NLKEY_SA_NOTIFY\n"); ++ memcpy(&sa_notify_msg, msg->payload, sizeof(struct nlkey_sa_notify)); ++ x = xfrm_state_lookup_byhandle(&init_net, sa_notify_msg.sagd); ++ if (x) { ++ spin_lock(&x->lock); ++ ++ if (sa_notify_msg.action) { ++ // hard expired ++ x->km.state = XFRM_STATE_EXPIRED; ++ hrtimer_start(&x->mtimer, ktime_set(0,0), HRTIMER_MODE_REL_SOFT); ++ } ++ else if (!x->km.dying) { ++ x->km.dying = 1; ++ km_state_expired(x, 0, 0); ++ } ++ ++ spin_unlock(&x->lock); ++ xfrm_state_put(x); ++ } ++ break; ++ ++ case NLKEY_SA_INFO_UPDATE: ++ memcpy(&sa_info_msg, msg->payload, sizeof(struct nlkey_sa_info)); ++ ++ x = xfrm_state_lookup_byhandle(&init_net,sa_info_msg.sagd); ++ if (x) { ++ spin_lock(&x->lock); ++ ++ if (x->curlft.bytes != sa_info_msg.bytes) ++ x->curr_time = ktime_get_real_seconds(); ++ ++ x->curlft.bytes = sa_info_msg.bytes; ++ x->curlft.packets = sa_info_msg.packets; ++ ++ spin_unlock(&x->lock); ++ xfrm_state_put(x); ++ } ++ break; ++ ++ case NLKEY_SA_SET_OFFLOAD: ++ memcpy(&sa_notify_msg, msg->payload, sizeof(struct nlkey_sa_notify)); ++ x = xfrm_state_lookup_byhandle(&init_net,sa_notify_msg.sagd); ++ if (x) { ++ spin_lock(&x->lock); ++ if(sa_notify_msg.action) ++ x->offloaded = 1; ++ else ++ x->offloaded = 0; ++ spin_unlock(&x->lock); ++ xfrm_state_put(x); ++ } ++ break; ++ default: ++ //printk(KERN_INFO "ipsec_nlkey_rcv fcode 0x%x not supported\n", msg->fcode); ++ break; ++ } ++ ++} ++static int ipsec_nlkey_set_said(struct net *net, struct xfrm_state *x, ++ const struct km_event *c, struct nlkey_sa_id *said) ++{ ++ ++ struct flowi fl; ++ int tos; ++ xfrm_address_t saddr, daddr; ++ struct dst_entry *dst; ++ struct rt6_info *rt; ++ int rc = 0; ++ int oif = 0; ++ ++ memset(&fl, 0, sizeof(struct flowi)); ++ ++ /* SPI */ ++ said->spi = x->id.spi; ++ /* SA Type (AH or ESP) */ ++ said->sa_type = x->id.proto; ++ /* Protocol Family (IPv4 or IPv6) */ ++ said->proto_family = x->props.family; ++ /* Replay window */ ++ said->replay_window = x->props.replay_window; ++ /* Destination IP Address */ ++ if(x->props.family == AF_INET6) { ++ memcpy(&said->dst_ip, x->id.daddr.a6, sizeof(struct in6_addr)); ++ fl.u.ip6.daddr = *(struct in6_addr *)x->id.daddr.a6; ++ memcpy(&said->src_ip, x->props.saddr.a6, sizeof(struct in6_addr)); ++ } ++ else { ++ said->dst_ip[0] = x->id.daddr.a4; ++ fl.u.ip4.daddr = x->id.daddr.a4; ++ said->src_ip[0] = x->props.saddr.a4; ++ } ++ said->mtu = 0; ++ ++ if(x->props.flags & XFRM_STATE_ESN) ++ said->flags = NLKEY_SAFLAGS_ESN; ++ xfrm_flowi_addr_get(&fl, &saddr, &daddr, x->props.family); ++ ++ tos = xfrm_get_tos(&fl, x->props.family); ++ if (tos < 0) { ++ printk(KERN_ERR "%s:%d: FIXME\n",__func__,__LINE__); ++ rc = -1; ++ goto error; ++ } ++ ++ switch (x->props.family) ++ { ++ case AF_INET: ++ if (!__ip_route_output_key(net, &(fl.u.ip4))) ++ { ++ printk(KERN_ERR "%s:%d: FIXME\n",__func__,__LINE__); ++ rc = -1; ++ goto error; ++ } ++ oif = fl.u.ip4.flowi4_oif; ++ break; ++ ++ case AF_INET6: ++ rt = rt6_lookup(net, &fl.u.ip6.daddr, NULL, 0, NULL, 0); ++ if ((!rt) || (!rt->dst.dev)) ++ { ++ printk(KERN_ERR "%s:%d: FIXME\n",__func__,__LINE__); ++ rc = -1; ++ goto error; ++ } ++ oif = rt->dst.dev->ifindex; ++ break; ++ } ++ ++ { ++ struct xfrm_dst_lookup_params params = { ++ .net = net, ++ .dscp = inet_dsfield_to_dscp(tos), ++ .oif = oif, ++ .saddr = NULL, ++ .daddr = &daddr, ++ .mark = xfrm_smark_get(0, x), ++ }; ++ dst = __xfrm_dst_lookup(x->props.family, ¶ms); ++ } ++ if (IS_ERR(dst)) { ++ printk(KERN_ERR "%s:%d: FIXME\n",__func__,__LINE__); ++ rc = -1; ++ goto error; ++ } ++ ++ if (strcmp(dst->dev->name, "lo") == 0) ++ said->flags |= NLKEY_SAFLAGS_INBOUND; ++ ++ said->dev_mtu = dst_mtu(dst); ++ said->mtu = xfrm_state_mtu(x,dst_mtu(dst)); ++ ++ dst_release(dst); ++error: ++ return rc; ++} ++ ++static struct sk_buff * ipsec_xfrm2nlkey (struct net *net, struct xfrm_state *x, ++ const struct km_event *c, unsigned short *msg_id) ++{ ++ struct nlkey_sa_id sa_id_msg; ++ struct nlkey_sa_create sa_create_msg; ++ struct nlkey_sa_delete sa_delete_msg; ++ struct nlkey_sa_set_keys sa_set_keys_msg; ++ struct nlkey_sa_set_tunnel sa_set_tunnel_msg; ++ struct nlkey_sa_set_natt sa_set_natt_msg; ++ struct nlkey_sa_set_state sa_set_state_msg; ++ struct nlkey_sa_set_lifetime sa_set_lifetime_msg; ++ struct nlkey_msg msg; ++ struct sk_buff *skb = NULL; ++ struct nlmsghdr *nlh = NULL; ++ gfp_t allocation = GFP_ATOMIC; //This may called from atomic context ++ unsigned char tunnel, keys, natt, state, lifetime; ++ ++ /* supported SA informations */ ++ keys = 1; state = 1; tunnel = 1; lifetime = 1; natt = 1; ++ ++ /* next message to build */ ++ memset(&msg, 0, sizeof(struct nlkey_msg)); ++ msg.fcode = *msg_id; ++ ++ //printk(KERN_INFO "\n\nipsec_xfrm2nlkey: processing event 0x%x\n", msg.fcode); ++ ++ switch (msg.fcode) ++ { ++ case NLKEY_SA_CREATE: ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: NLKEY_SA_CREATE\n"); ++ if(x) { ++ /* some check before builing message */ ++ if(x->id.proto != IPPROTO_ESP) { ++ printk(KERN_ERR "protocol %d not supported in fast path.\n", x->id.proto); ++ *msg_id = NLKEY_NULL_MSG; ++ goto exit; ++ } ++ ++ memset(&sa_create_msg, 0, sizeof(struct nlkey_sa_create)); ++ ++ /* SA global handler */ ++ sa_create_msg.sagd = x->handle; ++ ++ sa_create_msg.parent_sa_sagd = x->parent_sa_handle; ++ ++ /* SA identifier */ ++ if(ipsec_nlkey_set_said(net, x, c, &sa_create_msg.said) < 0) ++ { ++ printk(KERN_ERR "%s: set sa ID failed\n", __func__); ++ *msg_id = NLKEY_NULL_MSG; /* next message */ ++ goto exit; ++ } ++ memcpy(msg.payload, &sa_create_msg, sizeof(struct nlkey_sa_create)); ++ msg.length = sizeof(struct nlkey_sa_create); ++ *msg_id = NLKEY_SA_SET_KEYS; /* next message */ ++ } else { ++ *msg_id = NLKEY_NULL_MSG; /* next message */ ++ goto exit; ++ } ++ ++ break; ++ ++ case NLKEY_SA_SET_KEYS: ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: NLKEY_SA_SET_KEYS\n"); ++ if(keys) { ++ memset(&sa_set_keys_msg, 0, sizeof(struct nlkey_sa_set_keys)); ++ ++ /* SA global handler */ ++ sa_set_keys_msg.sagd = x->handle; ++ ++ /* auth key */ ++ if(x->aalg) { ++ if (x->aalg->alg_key_len) { ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_bits = x->aalg->alg_key_len; ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg = x->props.aalgo; ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_type = 0; ++ memcpy(sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key, x->aalg->alg_key,(sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_bits / 8)); ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: AUTH - algo %d key %d bits\n", sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg, sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_bits); ++ sa_set_keys_msg.num_keys++; ++ } ++ } ++ /* encrypt key */ ++ if(x->ealg) { ++ if (x->ealg->alg_key_len) { ++ ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_bits = x->ealg->alg_key_len; ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg = x->props.ealgo; ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_type = 1; ++ memcpy(sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key, x->ealg->alg_key,(sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_bits / 8)); ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: ENCRYPT - algo %d key %d bits\n", sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg, sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_bits); ++ sa_set_keys_msg.num_keys++; ++ } ++ } ++ /* combined key */ ++ if (x->aead) { ++ if (x->aead->alg_key_len) { ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_bits = x->aead->alg_key_len; ++ if (strstr(x->aead->alg_name, "rfc4106(gcm")) /* AES GCM support */ ++ { ++ if (x->aead->alg_icv_len == 64) ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg = SADB_X_EALG_AES_GCM_ICV8; ++ else if (x->aead->alg_icv_len == 96) ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg = SADB_X_EALG_AES_GCM_ICV12; ++ else if (x->aead->alg_icv_len == 128) ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg = SADB_X_EALG_AES_GCM_ICV16; ++ } ++ else if (strstr(x->aead->alg_name, "ccm")) /* AES CCM */ ++ { ++ if (x->aead->alg_icv_len == 64) ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg = SADB_X_EALG_AES_CCM_ICV8; ++ else if (x->aead->alg_icv_len == 96) ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg = SADB_X_EALG_AES_CCM_ICV12; ++ else if (x->aead->alg_icv_len == 128) ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg = SADB_X_EALG_AES_CCM_ICV16; ++ } ++ else if (strstr(x->aead->alg_name, "rfc4543(gcm")) /* AES GMAC defined in RFC 4543 derived from AES GCM */ ++ { ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg = SADB_X_EALG_NULL_AES_GMAC; ++ } ++ ++ sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_type = 1; ++ memcpy(sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key, x->aead->alg_key,(sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_bits/ 8)); ++ /* ++ printk(KERN_INFO "ipsec_xfrm2nlkey: ENCRYPT -alg name %s algo %d key %d bits\n", ++ x->aead->alg_name, sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_alg, sa_set_keys_msg.keys[sa_set_keys_msg.num_keys].key_bits); ++ */ ++ sa_set_keys_msg.num_keys++; ++ } ++ } ++ ++ memcpy(msg.payload, &sa_set_keys_msg, sizeof(struct nlkey_sa_set_keys)); ++ msg.length = sizeof(struct nlkey_sa_set_keys); ++ *msg_id = NLKEY_SA_SET_TUNNEL; /* next message */ ++ } else { ++ *msg_id = NLKEY_SA_SET_TUNNEL; /* next message */ ++ goto exit; ++ } ++ break; ++ ++ case NLKEY_SA_SET_TUNNEL: ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: NLKEY_SA_SET_TUNNEL\n"); ++ if(tunnel && (x->props.mode == XFRM_MODE_TUNNEL)) { ++ memset(&sa_set_tunnel_msg, 0, sizeof(struct nlkey_sa_set_tunnel)); ++ ++ /* SA global handler */ ++ sa_set_tunnel_msg.sagd = x->handle; ++ ++ /* Tunnel */ ++ sa_set_tunnel_msg.proto_family = x->props.family; ++ if(x->props.family == AF_INET6) { ++ struct ipv6hdr *top_iph = &sa_set_tunnel_msg.h.ipv6h; ++ int dsfield; ++ top_iph->version = 6; ++ top_iph->priority = 0; ++ top_iph->flow_lbl[0] = 0; ++ top_iph->flow_lbl[1] = 0; ++ top_iph->flow_lbl[2] = 0; ++ top_iph->nexthdr = IPPROTO_IPIP; ++ dsfield = ipv6_get_dsfield(top_iph); ++ dsfield = INET_ECN_encapsulate(dsfield, dsfield); ++ if (x->props.flags & XFRM_STATE_NOECN) ++ dsfield &= ~INET_ECN_MASK; ++ ipv6_change_dsfield(top_iph, 0, dsfield); ++ top_iph->hop_limit = 64; ++ memcpy(&top_iph->daddr, x->id.daddr.a6, sizeof(struct in6_addr)); ++ memcpy(&top_iph->saddr, x->props.saddr.a6, sizeof(struct in6_addr)); ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: IPv6 tunnel\n"); ++ //printk(KERN_INFO "dst: %x %x %x %x\n", x->id.daddr.a6[0], x->id.daddr.a6[1], x->id.daddr.a6[2], x->id.daddr.a6[3]); ++ //(KERN_INFO "src: %x %x %x %x\n", x->props.saddr.a6[0], x->props.saddr.a6[1], x->props.saddr.a6[2], x->props.saddr.a6[3]); ++ } ++ else { ++ struct iphdr *top_iph = &sa_set_tunnel_msg.h.ipv4h; ++ top_iph->ihl = 5; ++ top_iph->version = 4; ++ top_iph->tos = 0; ++ top_iph->frag_off = 0; ++ top_iph->ttl = 64; ++ top_iph->saddr = x->props.saddr.a4; ++ top_iph->daddr = x->id.daddr.a4; ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: IPv4 tunnel dst:%x - src:%x \n", x->id.daddr.a4, x->props.saddr.a4); ++ } ++ memcpy(msg.payload, &sa_set_tunnel_msg, sizeof(struct nlkey_sa_set_tunnel)); ++ msg.length = sizeof(struct nlkey_sa_set_tunnel); ++ *msg_id = NLKEY_SA_SET_NATT; /* next message */ ++ } else { ++ *msg_id = NLKEY_SA_SET_NATT; /* next message */ ++ goto exit; ++ } ++ break; ++ ++ case NLKEY_SA_SET_NATT: ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: NLKEY_SA_SET_NATT\n"); ++ if((natt) && (x->encap)){ ++ memset(&sa_set_natt_msg, 0, sizeof(struct nlkey_sa_set_natt)); ++ ++ /* SA global handler */ ++ sa_set_natt_msg.sagd = x->handle; ++ sa_set_natt_msg.sport = x->encap->encap_sport; ++ sa_set_natt_msg.dport = x->encap->encap_dport; ++ //printk(KERN_INFO "src port: %d dst port: %d \n", ntohs(sa_set_natt_msg.sport), ntohs( sa_set_natt_msg.dport)); ++ memcpy(msg.payload, &sa_set_natt_msg, sizeof(struct nlkey_sa_set_natt)); ++ msg.length = sizeof(struct nlkey_sa_set_natt); ++ *msg_id = NLKEY_SA_SET_LIFETIME; /* next message */ ++ } else { ++ *msg_id = NLKEY_SA_SET_LIFETIME; /* next message */ ++ goto exit; ++ } ++ break; ++ ++ case NLKEY_SA_SET_LIFETIME: ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: NLKEY_SA_SET_LIFETIME\n"); ++ if(lifetime) { ++ memset(&sa_set_lifetime_msg, 0, sizeof(struct nlkey_sa_set_lifetime)); ++ ++ /* SA global handler */ ++ sa_set_lifetime_msg.sagd = x->handle; ++ ++ /* hard time */ ++ sa_set_lifetime_msg.hard_time.allocations = _X2KEY(x->lft.hard_packet_limit); ++ if(_X2KEY(x->lft.hard_byte_limit)) ++ memcpy(sa_set_lifetime_msg.hard_time.bytes, &x->lft.hard_byte_limit, sizeof(uint64_t)); ++ ++ /* soft time */ ++ sa_set_lifetime_msg.soft_time.allocations = _X2KEY(x->lft.soft_packet_limit); ++ if(_X2KEY(x->lft.soft_byte_limit)) ++ memcpy(sa_set_lifetime_msg.soft_time.bytes, &x->lft.soft_byte_limit, sizeof(uint64_t)); ++ ++ /* current time */ ++ sa_set_lifetime_msg.current_time.allocations = x->curlft.packets; ++ memcpy(sa_set_lifetime_msg.current_time.bytes, &x->curlft.bytes, sizeof(uint64_t)); ++ ++ memcpy(msg.payload, &sa_set_lifetime_msg, sizeof(struct nlkey_sa_set_lifetime)); ++ msg.length = sizeof(struct nlkey_sa_set_lifetime); ++ *msg_id = NLKEY_SA_SET_STATE; /* next message */ ++ } else { ++ *msg_id = NLKEY_SA_SET_STATE; /* next message */ ++ goto exit; ++ } ++ break; ++ ++ case NLKEY_SA_SET_STATE: ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: NLKEY_SET_STATE\n"); ++ if(state) { ++ memset(&sa_set_state_msg, 0, sizeof(struct nlkey_sa_set_state)); ++ memset(&sa_id_msg, 0, sizeof(struct nlkey_sa_id)); ++ ++ /* SA global handler */ ++ sa_set_state_msg.sagd = x->handle; ++ sa_set_state_msg.parent_sa_sagd = x->parent_sa_handle; ++ /* State */ ++ sa_set_state_msg.state = x->km.state; ++ // TODO: set the offloaded state once ack received ! ++ ++ memcpy(msg.payload, &sa_set_state_msg, sizeof(struct nlkey_sa_set_state)); ++ msg.length = sizeof(struct nlkey_sa_set_state); ++ *msg_id = NLKEY_NULL_MSG; /* next message */ ++ } else { ++ *msg_id = NLKEY_NULL_MSG; /* next message */ ++ goto exit; ++ } ++ break; ++ ++ case NLKEY_SA_DELETE: ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: NLKEY_SA_DELETE\n"); ++ memset(&sa_delete_msg, 0, sizeof(struct nlkey_sa_delete)); ++ ++ /* SA global handler */ ++ sa_delete_msg.sagd = x->handle; ++ memcpy(msg.payload, &sa_delete_msg, sizeof(struct nlkey_sa_delete)); ++ msg.length = sizeof(struct nlkey_sa_delete); ++ ++ ++ *msg_id = NLKEY_NULL_MSG; /* next message */ ++ break; ++ ++ case NLKEY_SA_FLUSH: ++ //printk(KERN_INFO "ipsec_xfrm2nlkey: NLKEY_SA_FLUSH\n"); ++ /* No data required for flush SA command */ ++ ++ *msg_id = NLKEY_NULL_MSG; /* next message */ ++ break; ++ ++ default: ++ printk(KERN_ERR "ipsec_xfrm2nlkey: event 0x%x not supported\n", c->event); ++ *msg_id = NLKEY_NULL_MSG; /* next message */ ++ break; ++ } ++ ++ /* prepare netlink message for kernel to user space direction */ ++ if(msg.length > NLKEY_MSG_LEN) ++ { ++ printk(KERN_ERR "ipsec_xfrm2nlkey: maximum message size reached (%d bytes)\n", msg.length); ++ goto exit; ++ } ++ ++ skb = alloc_skb(NLMSG_SPACE(NLKEY_MSG_LEN + NLKEY_HDR_LEN), allocation); ++ if (skb == NULL) ++ goto exit; ++ ++ nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_SPACE(NLKEY_HDR_LEN + msg.length)); ++ memcpy(NLMSG_DATA(nlh), (unsigned char *)&msg, (NLKEY_HDR_LEN + msg.length)); ++ ++ /* whole length of the message i.e. header + payload */ ++ nlh->nlmsg_len = NLMSG_SPACE(NLKEY_HDR_LEN + msg.length); ++ ++ /* from kernel */ ++ nlh->nlmsg_pid = 0; ++ nlh->nlmsg_flags = 0; ++ nlh->nlmsg_type = 0; ++ NETLINK_CB(skb).portid = 0; ++ NETLINK_CB(skb).dst_group = 1; ++exit: ++ return skb; ++} ++ ++static int ipsec_nlkey_send(struct net *net, struct xfrm_state *x, const struct km_event *c) ++{ ++ struct sk_buff *skb; ++ unsigned short msg_type; ++ int rc = 0; ++ ++ /* We may generate more than one message when adding new SA (sa_create + sa_set_state + sa_set_tunnel...) */ ++ msg_type = ipsec_sacode_to_nlkeycode((unsigned short)c->event); ++ ++ while(msg_type != NLKEY_NULL_MSG) ++ { ++ /* build nlkey message */ ++ skb = ipsec_xfrm2nlkey(net, x, c, &msg_type); ++ ++ if(skb != NULL) ++ if((rc = netlink_broadcast(nlkey_socket, skb, 0, 1, GFP_ATOMIC)) < 0) ++ return rc; ++ } ++ ++ return rc; ++} ++ ++ ++int ipsec_nlkey_flow(u16 xfrm_nr, u16 *xfrm_handle, const struct flowi *fl, u16 family, u16 dir, u16 ignore_neigh) ++{ ++ struct sk_buff *skb; ++ struct nlkey_msg msg; ++ struct nlmsghdr *nlh = NULL; ++ unsigned short *p; ++ gfp_t allocation = GFP_ATOMIC; //This may called from atomic context ++ ++ //printk(KERN_INFO "ipsec_nlkey_flow \n"); ++ ++ /* next message to build */ ++ memset(&msg, 0, sizeof(struct nlkey_msg)); ++ msg.fcode = NLKEY_FLOW_ADD; ++ ++ // Number of SA for this flow ++ p = msg.payload; ++ *p++ = xfrm_nr; ++ msg.length += sizeof(unsigned short); ++ // SA handles list ++ memcpy(p, xfrm_handle, xfrm_nr*sizeof(unsigned short)); ++ msg.length += xfrm_nr*sizeof(unsigned short); ++ p+=xfrm_nr; ++ // flow family ++ *p++ = family; ++ msg.length += sizeof(unsigned short); ++ // flow family ++ *p++ = dir; ++ msg.length += sizeof(unsigned short); ++ // flow mode ++ *p++ = ignore_neigh; ++ msg.length += sizeof(unsigned short); ++ // flow descriptor ++ memcpy(p, fl, sizeof(struct flowi)); ++ msg.length +=sizeof(struct flowi); ++ p+=sizeof(struct flowi) / sizeof(u16); ++ ++ skb = alloc_skb(NLMSG_SPACE(NLKEY_MSG_LEN + NLKEY_HDR_LEN), allocation); ++ if (skb == NULL) ++ return -ENOMEM; ++ ++ /* prepare netlink message for kernel to user space direction */ ++ nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_SPACE(NLKEY_HDR_LEN + msg.length)); ++ memcpy(NLMSG_DATA(nlh), (unsigned char *)&msg, (NLKEY_HDR_LEN + msg.length)); ++ ++ /* whole length of the message i.e. header + payload */ ++ nlh->nlmsg_len = NLMSG_SPACE(NLKEY_HDR_LEN + msg.length); ++ ++ /* from kernel */ ++ nlh->nlmsg_pid = 0; ++ nlh->nlmsg_flags = 0; ++ nlh->nlmsg_type = 0; ++ NETLINK_CB(skb).portid = 0; ++ NETLINK_CB(skb).dst_group = 1; ++ ++ return(netlink_broadcast(nlkey_socket, skb, 0, 1, allocation)); ++} ++EXPORT_SYMBOL(ipsec_nlkey_flow); ++ ++ ++int ipsec_nlkey_flow_remove(struct flowi *fl, u16 family, u16 dir) ++{ ++ struct sk_buff *skb; ++ struct nlkey_msg msg; ++ struct nlmsghdr *nlh = NULL; ++ unsigned short *p; ++ gfp_t allocation = GFP_ATOMIC; //This may called from atomic context ++ ++ ++ //printk(KERN_INFO "ipsec_nlkey_flow_remove\n"); ++ ++ /* next message to build */ ++ memset(&msg, 0, sizeof(struct nlkey_msg)); ++ msg.fcode = NLKEY_FLOW_REMOVE; ++ ++ p = msg.payload; ++ // flow family ++ *p++ = family; ++ msg.length += sizeof(unsigned short); ++ // flow family ++ *p++ = dir; ++ msg.length += sizeof(unsigned short); ++ // flow descriptor ++ memcpy(p, fl, sizeof(struct flowi)); ++ msg.length +=sizeof(struct flowi); ++ p+=sizeof(struct flowi) / sizeof(u16); ++ ++ skb = alloc_skb(NLMSG_SPACE(NLKEY_MSG_LEN + NLKEY_HDR_LEN), allocation); ++ if (skb == NULL) ++ return -ENOMEM; ++ ++ /* prepare netlink message for kernel to user space direction */ ++ nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_SPACE(NLKEY_HDR_LEN + msg.length)); ++ memcpy(NLMSG_DATA(nlh), (unsigned char *)&msg, (NLKEY_HDR_LEN + msg.length)); ++ ++ /* whole length of the message i.e. header + payload */ ++ nlh->nlmsg_len = NLMSG_SPACE(NLKEY_HDR_LEN + msg.length); ++ ++ /* from kernel */ ++ nlh->nlmsg_pid = 0; ++ nlh->nlmsg_flags = 0; ++ nlh->nlmsg_type = 0; ++ NETLINK_CB(skb).portid = 0; ++ NETLINK_CB(skb).dst_group = 1; ++ ++ ++ return(netlink_broadcast(nlkey_socket, skb, 0, 1, allocation)); ++ ++ ++} ++EXPORT_SYMBOL(ipsec_nlkey_flow_remove); ++ ++ ++ ++static void ipsec_nlkey_init(void) ++{ ++ struct netlink_kernel_cfg cfg = { ++ .groups = 1, ++ .input = ipsec_nlkey_rcv, ++ }; ++ printk(KERN_INFO "Initializing NETLINK_KEY socket\n"); ++ nlkey_socket = netlink_kernel_create(&init_net, NETLINK_KEY, &cfg); ++} ++#endif ++ ++ + static int __net_init pfkey_net_init(struct net *net) + { + struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); +@@ -3897,6 +4772,11 @@ static void __exit ipsec_pfkey_exit(void) + sock_unregister(PF_KEY); + unregister_pernet_subsys(&pfkey_net_ops); + proto_unregister(&key_proto); ++ ++#ifdef NLKEY_SUPPORT ++ /* release NETLINK_KEY socket */ ++ sock_release(nlkey_socket->sk_socket); ++#endif + } + + static int __init ipsec_pfkey_init(void) +@@ -3913,6 +4793,12 @@ static int __init ipsec_pfkey_init(void) + if (err != 0) + goto out_unregister_pernet; + xfrm_register_km(&pfkeyv2_mgr); ++ ++#ifdef NLKEY_SUPPORT ++ /* create NETLINK_KEY socket for IPSec offload on Comcerto */ ++ ipsec_nlkey_init(); ++#endif ++ + out: + return err; + diff --git a/patches/ask/kernel/0124-net__netfilter__nf_conntrack_netlink.c.patch b/patches/ask/kernel/0124-net__netfilter__nf_conntrack_netlink.c.patch new file mode 100644 index 0000000..c8e98cf --- /dev/null +++ b/patches/ask/kernel/0124-net__netfilter__nf_conntrack_netlink.c.patch @@ -0,0 +1,288 @@ +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index 3a04665..7e7d13d 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -28,6 +28,11 @@ + #include + #include + #include ++#if defined(CONFIG_CPE_FAST_PATH) ++#ifndef IPSEC_FLOW_CACHE ++#include ++#endif ++#endif + #include + #include + +@@ -202,9 +207,16 @@ static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct, + struct nlattr *nest_proto; + int ret; + ++#ifdef CONFIG_CPE_FAST_PATH ++ rcu_read_lock(); ++#endif + l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct)); +- if (!l4proto->to_nlattr) ++ if (!l4proto->to_nlattr) { ++#ifdef CONFIG_CPE_FAST_PATH ++ rcu_read_unlock(); ++#endif + return 0; ++ } + + nest_proto = nla_nest_start(skb, CTA_PROTOINFO); + if (!nest_proto) +@@ -214,9 +226,15 @@ static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct, + + nla_nest_end(skb, nest_proto); + ++#ifdef CONFIG_CPE_FAST_PATH ++ rcu_read_unlock(); ++#endif + return ret; + + nla_put_failure: ++#ifdef CONFIG_CPE_FAST_PATH ++ rcu_read_unlock(); ++#endif + return -1; + } + +@@ -353,6 +371,18 @@ nla_put_failure: + #define ctnetlink_dump_mark(a, b, c) (0) + #endif + ++#if defined(CONFIG_CPE_FAST_PATH) ++static inline int ++ctnetlink_dump_qosconnmark(struct sk_buff *skb, const struct nf_conn *ct) ++{ ++ nla_put_be64(skb, CTA_QOSCONNMARK, cpu_to_be64(ct->qosconnmark), ++ CTA_QOSCONNMARK_PAD); ++ return 0; ++} ++#else ++#define ctnetlink_dump_qosconnmark(a, b) (0) ++#endif ++ + #ifdef CONFIG_NF_CONNTRACK_SECMARK + static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct) + { +@@ -430,6 +460,59 @@ ctnetlink_dump_labels(struct sk_buff *skb, const struct nf_conn *ct) + return 0; + } + ++#if defined(CONFIG_CPE_FAST_PATH) ++static int ++ctnetlink_dump_comcerto_fp(struct sk_buff *skb, const struct nf_conn *ct) ++{ ++ struct nlattr *nest_count; ++ ++ nest_count = nla_nest_start(skb, CTA_LAYERSCAPE_FP_ORIG | NLA_F_NESTED); ++ if (!nest_count) ++ goto nla_put_failure; ++ ++ nla_put_u32(skb, CTA_COMCERTO_FP_MARK, ct->fp_info[IP_CT_DIR_ORIGINAL].mark); ++ nla_put_u32(skb, CTA_COMCERTO_FP_IFINDEX, ct->fp_info[IP_CT_DIR_ORIGINAL].ifindex); ++ nla_put_u32(skb, CTA_COMCERTO_FP_IIF, ct->fp_info[IP_CT_DIR_ORIGINAL].iif); ++ nla_put_u32(skb, CTA_COMCERTO_FP_UNDERLYING_IIF, ct->fp_info[IP_CT_DIR_ORIGINAL].underlying_iif); ++ nla_put_u16(skb, CTA_COMCERTO_FP_UNDERLYING_VID, ct->fp_info[IP_CT_DIR_ORIGINAL].underlying_vlan_id); ++#ifndef IPSEC_FLOW_CACHE ++ if ((ct->fp_info[IP_CT_DIR_ORIGINAL].xfrm_handle[0]) || ++ (ct->fp_info[IP_CT_DIR_ORIGINAL].xfrm_handle[MAX_SUPPORTED_XFRMS_PER_DIR])) ++ { ++ nla_put(skb, CTA_COMCERTO_FP_XFRM_HANDLE, sizeof(ct->fp_info[IP_CT_DIR_ORIGINAL].xfrm_handle), ++ ct->fp_info[IP_CT_DIR_ORIGINAL].xfrm_handle); ++ } ++#endif /* IPSEC_FLOW_CACHE */ ++ nla_nest_end(skb, nest_count); ++ ++ nest_count = nla_nest_start(skb, CTA_LAYERSCAPE_FP_REPLY | NLA_F_NESTED); ++ if (!nest_count) ++ goto nla_put_failure; ++ ++ nla_put_u32(skb, CTA_COMCERTO_FP_MARK, ct->fp_info[IP_CT_DIR_REPLY].mark); ++ nla_put_u32(skb, CTA_COMCERTO_FP_IFINDEX, ct->fp_info[IP_CT_DIR_REPLY].ifindex); ++ nla_put_u32(skb, CTA_COMCERTO_FP_IIF, ct->fp_info[IP_CT_DIR_REPLY].iif); ++ nla_put_u32(skb, CTA_COMCERTO_FP_UNDERLYING_IIF, ct->fp_info[IP_CT_DIR_REPLY].underlying_iif); ++ nla_put_u16(skb, CTA_COMCERTO_FP_UNDERLYING_VID, ct->fp_info[IP_CT_DIR_REPLY].underlying_vlan_id); ++#ifndef IPSEC_FLOW_CACHE ++ if ((ct->fp_info[IP_CT_DIR_REPLY].xfrm_handle[0]) || ++ (ct->fp_info[IP_CT_DIR_REPLY].xfrm_handle[MAX_SUPPORTED_XFRMS_PER_DIR])) ++ { ++ nla_put(skb, CTA_COMCERTO_FP_XFRM_HANDLE, sizeof(ct->fp_info[IP_CT_DIR_REPLY].xfrm_handle), ++ ct->fp_info[IP_CT_DIR_REPLY].xfrm_handle); ++ } ++#endif /* IPSEC_FLOW_CACHE */ ++ nla_nest_end(skb, nest_count); ++ ++ return 0; ++ ++nla_put_failure: ++ return -1; ++} ++#else ++#define ctnetlink_dump_comcerto_fp(a, b) (0) ++#endif ++ + #define master_tuple(ct) &(ct->master->tuplehash[IP_CT_DIR_ORIGINAL].tuple) + + static int ctnetlink_dump_master(struct sk_buff *skb, const struct nf_conn *ct) +@@ -570,7 +653,11 @@ static int ctnetlink_dump_info(struct sk_buff *skb, struct nf_conn *ct) + { + if (ctnetlink_dump_status(skb, ct) < 0 || + ctnetlink_dump_mark(skb, ct, true) < 0 || ++ ctnetlink_dump_qosconnmark(skb, ct) < 0 || + ctnetlink_dump_secctx(skb, ct) < 0 || ++#ifdef CONFIG_CPE_FAST_PATH ++ ctnetlink_dump_comcerto_fp(skb, ct) < 0 || ++#endif + ctnetlink_dump_id(skb, ct) < 0 || + ctnetlink_dump_use(skb, ct) < 0 || + ctnetlink_dump_master(skb, ct) < 0) +@@ -722,6 +809,13 @@ static size_t ctnetlink_nlmsg_size(const struct nf_conn *ct) + + nla_total_size(0) /* CTA_HELP */ + + nla_total_size(NF_CT_HELPER_NAME_LEN) /* CTA_HELP_NAME */ + + ctnetlink_secctx_size(ct) ++#ifdef CONFIG_CPE_FAST_PATH ++ + 2 * nla_total_size(0) /* CTA_LAYERSCAPE_FP_ORIG|REPL */ ++ + 2 * nla_total_size(sizeof(uint32_t)) /* CTA_COMCERTO_FP_MARK */ ++ + 2 * nla_total_size(sizeof(uint32_t)) /* CTA_COMCERTO_FP_IFINDEX */ ++ + 2 * nla_total_size(sizeof(uint32_t)) /* CTA_COMCERTO_FP_IIF */ ++ + 2 * nla_total_size(sizeof(uint32_t)) /* CTA_COMCERTO_FP_UNDERLYING_IIF */ ++#endif + #if IS_ENABLED(CONFIG_NF_NAT) + + 2 * nla_total_size(0) /* CTA_NAT_SEQ_ADJ_ORIG|REPL */ + + 6 * nla_total_size(sizeof(u_int32_t)) /* CTA_NAT_SEQ_OFFSET */ +@@ -729,6 +823,9 @@ static size_t ctnetlink_nlmsg_size(const struct nf_conn *ct) + #ifdef CONFIG_NF_CONNTRACK_MARK + + nla_total_size(sizeof(u_int32_t)) /* CTA_MARK */ + #endif ++#if defined(CONFIG_CPE_FAST_PATH) ++ + nla_total_size(sizeof(u_int64_t)) /* CTA_QOSCONNMARK */ ++#endif + #ifdef CONFIG_NF_CONNTRACK_ZONES + + nla_total_size(sizeof(u_int16_t)) /* CTA_ZONE|CTA_TUPLE_ZONE */ + #endif +@@ -806,6 +903,11 @@ ctnetlink_conntrack_event(unsigned int events, const struct nf_ct_event *item) + NF_CT_DEFAULT_ZONE_DIR) < 0) + goto nla_put_failure; + ++#if defined(CONFIG_CPE_FAST_PATH) ++ if (ctnetlink_dump_comcerto_fp(skb, ct) < 0) ++ goto nla_put_failure; ++#endif ++ + if (ctnetlink_dump_id(skb, ct) < 0) + goto nla_put_failure; + +@@ -858,6 +960,11 @@ ctnetlink_conntrack_event(unsigned int events, const struct nf_ct_event *item) + if (ctnetlink_dump_mark(skb, ct, events & (1 << IPCT_MARK))) + goto nla_put_failure; + #endif ++#if defined(CONFIG_CPE_FAST_PATH) ++ if ((events & (1 << IPCT_QOSCONNMARK) || ct->qosconnmark) && ++ ctnetlink_dump_qosconnmark(skb, ct) < 0) ++ goto nla_put_failure; ++#endif + + if (ctnetlink_dump_event_timestamp(skb, ct)) + goto nla_put_failure; +@@ -1570,6 +1677,9 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { + [CTA_NAT_SRC] = { .type = NLA_NESTED }, + [CTA_TIMEOUT] = { .type = NLA_U32 }, + [CTA_MARK] = { .type = NLA_U32 }, ++#if defined(CONFIG_CPE_FAST_PATH) ++ [CTA_QOSCONNMARK] = { .type = NLA_U64 }, ++#endif + [CTA_ID] = { .type = NLA_U32 }, + [CTA_NAT_DST] = { .type = NLA_NESTED }, + [CTA_TUPLE_MASTER] = { .type = NLA_NESTED }, +@@ -1906,6 +2016,48 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[]) + return nf_ct_change_status_common(ct, ntohl(nla_get_be32(cda[CTA_STATUS]))); + } + ++#if defined(CONFIG_CPE_FAST_PATH) ++/* ++ * This function detects ctnetlink messages that require ++ * to set the conntrack status to IPS_PERMANENT. ++ * It updates only this bit regardless of other possible ++ * changes. ++ * Return 0 if succesfull ++ */ ++static int ++ctnetlink_change_permanent(struct nf_conn *ct, const struct nlattr * const cda[]) ++{ ++ unsigned int status; ++ u_int32_t id; ++ __be32 conntrack_id = ntohl((__force __be32)nf_ct_get_id(ct)); ++ ++ if (cda[CTA_STATUS] && cda[CTA_ID]) { ++ status = ntohl(nla_get_be32(cda[CTA_STATUS])); ++ id = ntohl(nla_get_be32(cda[CTA_ID])); ++ ++ if (status & IPS_PERMANENT) { ++ if (conntrack_id == id) { ++ ct->status |= IPS_PERMANENT; ++ return 0; ++ } ++ else ++ return -ENOENT; ++ } ++ else if (nf_ct_is_permanent(ct)) ++ { ++ /* Clear the PERMANENT bit. */ ++ if (conntrack_id == id) { ++ clear_bit(IPS_PERMANENT_BIT, &ct->status); ++ return 0; ++ } ++ else ++ return -ENOENT; ++ } ++ } ++ return -1; ++} ++#endif ++ + static int + ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[]) + { +@@ -2209,6 +2361,11 @@ ctnetlink_change_conntrack(struct nf_conn *ct, + return err; + } + ++#if defined(CONFIG_CPE_FAST_PATH) ++ if (cda[CTA_QOSCONNMARK]) ++ ct->qosconnmark = be64_to_cpu(nla_get_be64(cda[CTA_QOSCONNMARK])); ++#endif ++ + #if defined(CONFIG_NF_CONNTRACK_MARK) + if (cda[CTA_MARK]) + ctnetlink_change_mark(ct, cda); +@@ -2347,6 +2504,11 @@ ctnetlink_create_conntrack(struct net *net, + goto err2; + } + ++#if defined(CONFIG_CPE_FAST_PATH) ++ if (cda[CTA_QOSCONNMARK]) ++ ct->qosconnmark = be64_to_cpu(nla_get_be64(cda[CTA_QOSCONNMARK])); ++#endif ++ + #if defined(CONFIG_NF_CONNTRACK_MARK) + if (cda[CTA_MARK]) + ctnetlink_change_mark(ct, cda); +@@ -2473,6 +2635,15 @@ static int ctnetlink_new_conntrack(struct sk_buff *skb, + err = -EEXIST; + ct = nf_ct_tuplehash_to_ctrack(h); + if (!(info->nlh->nlmsg_flags & NLM_F_EXCL)) { ++#if defined(CONFIG_CPE_FAST_PATH) ++ /* If the permanent status has been set, this is a specific ++ * message. Don't broadcast the event and don't update the ct */ ++ err = ctnetlink_change_permanent(ct, cda); ++ if ((err == 0) || (err == -ENOENT)) { ++ nf_ct_put(ct); ++ return err; ++ } ++#endif + err = ctnetlink_change_conntrack(ct, cda); + if (err == 0) { + nf_conntrack_eventmask_report((1 << IPCT_REPLY) | diff --git a/patches/ask/kernel/0129-net__wireless__Kconfig.patch b/patches/ask/kernel/0129-net__wireless__Kconfig.patch new file mode 100644 index 0000000..468514c --- /dev/null +++ b/patches/ask/kernel/0129-net__wireless__Kconfig.patch @@ -0,0 +1,21 @@ +diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig +index 5d6a0b2b4f3a..7c3d10e2e8b1 100644 +--- a/net/wireless/Kconfig ++++ b/net/wireless/Kconfig +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + config WIRELESS_EXT +- bool ++ def_bool y + + config WEXT_CORE + def_bool y +@@ -11,7 +11,7 @@ config WEXT_PROC + depends on WEXT_CORE + + config WEXT_PRIV +- bool ++ def_bool y + + config CFG80211 + tristate "cfg80211 - wireless configuration API" diff --git a/patches/ask/kernel/0131-net__xfrm__Makefile.patch b/patches/ask/kernel/0131-net__xfrm__Makefile.patch new file mode 100644 index 0000000..7183410 --- /dev/null +++ b/patches/ask/kernel/0131-net__xfrm__Makefile.patch @@ -0,0 +1,9 @@ +diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile +index 0a0a0a0..0b0b0b0 100644 +--- a/net/xfrm/Makefile ++++ b/net/xfrm/Makefile +@@ -24,3 +24,4 @@ obj-$(CONFIG_XFRM_INTERFACE) += xfrm_interface.o + obj-$(CONFIG_XFRM_IPTFS) += xfrm_iptfs.o + obj-$(CONFIG_XFRM_ESPINTCP) += espintcp.o + obj-$(CONFIG_DEBUG_INFO_BTF) += xfrm_state_bpf.o ++obj-$(CONFIG_INET_IPSEC_OFFLOAD) += ipsec_flow.o diff --git a/patches/ask/kernel/0136-net__xfrm__xfrm_policy.c.patch b/patches/ask/kernel/0136-net__xfrm__xfrm_policy.c.patch new file mode 100644 index 0000000..30460f8 --- /dev/null +++ b/patches/ask/kernel/0136-net__xfrm__xfrm_policy.c.patch @@ -0,0 +1,163 @@ +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 62486f8..3cbe4f8 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -48,6 +48,11 @@ + #include + + #include "xfrm_hash.h" ++#ifdef IPSEC_FLOW_CACHE ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++#include "ipsec_flow.h" ++#endif ++#endif + + #define XFRM_QUEUE_TMO_MIN ((unsigned)(HZ/10)) + #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) +@@ -179,6 +184,15 @@ static struct xfrm_policy_afinfo const __rcu *xfrm_policy_afinfo[AF_INET6 + 1] + + static struct kmem_cache *xfrm_dst_cache __ro_after_init; + ++#ifdef IPSEC_FLOW_CACHE ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++extern int ipsec_nlkey_flow(u16 xfrm_nr, u16 *xfrm_handle, ++ const struct flowi *fl, u16 family, u16 dir, u16 ignore_neigh); ++int ipsec_flow_init(struct net *net); ++void ipsec_flow_fini(struct net *net); ++#endif ++#endif ++ + static struct rhashtable xfrm_policy_inexact_table; + static const struct rhashtable_params xfrm_pol_inexact_params; + +@@ -2599,6 +2613,17 @@ static dscp_t xfrm_get_dscp(const struct flowi *fl, int family) + return 0; + } + ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++int xfrm_get_tos(const struct flowi *fl, int family) ++{ ++ if (family == AF_INET) ++ return inet_dscp_to_dsfield(fl->u.ip4.flowi4_dscp) & INET_DSCP_MASK; ++ ++ return 0; ++} ++EXPORT_SYMBOL(xfrm_get_tos); ++#endif ++ + static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) + { + const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); +@@ -3295,6 +3320,37 @@ no_transform: + dst = dst_orig; + } + ++#ifdef IPSEC_FLOW_CACHE ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ { ++ struct dst_entry *dst1 = dst; ++ struct xfrm_state *x; ++ u16 xfrm_handle[XFRM_POLICY_TYPE_MAX]; ++ u16 ignore_neigh = 0; ++ ++ num_xfrms = 0; ++ memset(xfrm_handle, 0, XFRM_POLICY_TYPE_MAX * sizeof(u16)); ++ while (((x = dst1->xfrm) != NULL) && ++ (num_xfrms < XFRM_POLICY_TYPE_MAX)) { ++ xfrm_handle[num_xfrms++] = x->handle; ++ if (x->props.mode == XFRM_MODE_TUNNEL) ++ ignore_neigh = 1; ++ dst1 = xfrm_dst_child(dst1); ++ ++ if (dst1 == NULL) { ++ err = -EHOSTUNREACH; ++ goto error; ++ } ++ } ++ if (ipsec_flow_add(net, fl, family, dir, xfrm_handle)) { ++ /* sent flow notification to cmm with sa_handle */ ++ ipsec_nlkey_flow(num_xfrms, xfrm_handle, fl, family, ++ (unsigned short)dir, ignore_neigh); ++ } ++ } ++#endif ++#endif ++ + ok: + xfrm_pols_put(pols, drop_pols); + if (dst->xfrm && +@@ -3853,6 +3909,34 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, + goto reject; + } + ++#ifdef IPSEC_FLOW_CACHE ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ { ++ struct xfrm_state *x; ++ u16 xfrm_handle[XFRM_POLICY_TYPE_MAX]; ++ ++ xfrm_nr = 0; ++ memset(xfrm_handle, 0, XFRM_POLICY_TYPE_MAX * sizeof(u16)); ++ for (i = sp->len - 1; ++ (i >= 0) && (xfrm_nr < XFRM_POLICY_TYPE_MAX); i--) { ++ x = sp->xvec[i]; ++ xfrm_handle[xfrm_nr++] = x->handle; ++ } ++ if (ipsec_flow_add(net, (const struct flowi *)&fl, family, dir, ++ xfrm_handle)) { ++ /* sent flow notification to cmm with sa_handle */ ++ ipsec_nlkey_flow(xfrm_nr, xfrm_handle, ++ (const struct flowi *)&fl, family, dir, 0); ++ } ++ } ++ ++ /* Hub and spoke changes: Setting the POLICY_IN direction in the packet */ ++ skb->ipsec_xfrm_dir |= (1 << XFRM_POLICY_IN); ++ ++std_path: ++#endif ++#endif ++ + xfrm_pols_put(pols, npols); + sp->verified_cnt = k; + +@@ -4328,6 +4412,14 @@ static int __net_init xfrm_net_init(struct net *net) + if (rv < 0) + goto out_sysctl; + ++#ifdef IPSEC_FLOW_CACHE ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ rv = ipsec_flow_init(net); ++ if (rv < 0) ++ goto out_ipsec_flow; ++#endif ++#endif ++ + rv = xfrm_nat_keepalive_net_init(net); + if (rv < 0) + goto out_nat_keepalive; +@@ -4335,6 +4427,12 @@ static int __net_init xfrm_net_init(struct net *net) + return 0; + + out_nat_keepalive: ++#ifdef IPSEC_FLOW_CACHE ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ ipsec_flow_fini(net); ++out_ipsec_flow: ++#endif ++#endif + xfrm_sysctl_fini(net); + out_sysctl: + xfrm_policy_fini(net); +@@ -4349,6 +4447,11 @@ out_statistics: + static void __net_exit xfrm_net_exit(struct net *net) + { + xfrm_nat_keepalive_net_fini(net); ++#ifdef IPSEC_FLOW_CACHE ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ ipsec_flow_fini(net); ++#endif ++#endif + xfrm_sysctl_fini(net); + xfrm_policy_fini(net); + xfrm_state_fini(net); diff --git a/patches/ask/kernel/0137-net__xfrm__xfrm_state.c.patch b/patches/ask/kernel/0137-net__xfrm__xfrm_state.c.patch new file mode 100644 index 0000000..36db635 --- /dev/null +++ b/patches/ask/kernel/0137-net__xfrm__xfrm_state.c.patch @@ -0,0 +1,291 @@ +diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c +index 9e14e45..d685ed7 100644 +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -58,6 +58,10 @@ static inline bool xfrm_state_hold_rcu(struct xfrm_state __rcu *x) + return refcount_inc_not_zero(&x->refcnt); + } + ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++static unsigned short xfrm_state_handle; ++#endif ++ + static inline unsigned int xfrm_dst_hash(struct net *net, + const xfrm_address_t *daddr, + const xfrm_address_t *saddr, +@@ -119,6 +123,9 @@ static void xfrm_hash_transfer(struct hlist_head *list, + struct hlist_head *nsrctable, + struct hlist_head *nspitable, + struct hlist_head *nseqtable, ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ struct hlist_head *nhtable, ++#endif + unsigned int nhashmask) + { + struct hlist_node *tmp; +@@ -150,6 +157,13 @@ static void xfrm_hash_transfer(struct hlist_head *list, + XFRM_STATE_INSERT(byseq, &x->byseq, nseqtable + h, + x->xso.type); + } ++ ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ if (x->handle && x->in_byh_hash) { ++ h = x->handle & nhashmask; ++ hlist_add_head_rcu(&x->byh, nhtable + h); ++ } ++#endif + } + } + +@@ -162,6 +176,9 @@ static void xfrm_hash_resize(struct work_struct *work) + { + struct net *net = container_of(work, struct net, xfrm.state_hash_work); + struct hlist_head *ndst, *nsrc, *nspi, *nseq, *odst, *osrc, *ospi, *oseq; ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ struct hlist_head *nh, *oh; ++#endif + unsigned long nsize, osize; + unsigned int nhashmask, ohashmask; + int i; +@@ -188,6 +205,16 @@ static void xfrm_hash_resize(struct work_struct *work) + xfrm_hash_free(nspi, nsize); + return; + } ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ nh = xfrm_hash_alloc(nsize); ++ if (!nh) { ++ xfrm_hash_free(ndst, nsize); ++ xfrm_hash_free(nsrc, nsize); ++ xfrm_hash_free(nspi, nsize); ++ xfrm_hash_free(nseq, nsize); ++ return; ++ } ++#endif + + spin_lock_bh(&net->xfrm.xfrm_state_lock); + write_seqcount_begin(&net->xfrm.xfrm_state_hash_generation); +@@ -195,17 +222,27 @@ static void xfrm_hash_resize(struct work_struct *work) + nhashmask = (nsize / sizeof(struct hlist_head)) - 1U; + odst = xfrm_state_deref_prot(net->xfrm.state_bydst, net); + for (i = net->xfrm.state_hmask; i >= 0; i--) +- xfrm_hash_transfer(odst + i, ndst, nsrc, nspi, nseq, nhashmask); ++ xfrm_hash_transfer(odst + i, ndst, nsrc, nspi, nseq, ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ nh, ++#endif ++ nhashmask); + + osrc = xfrm_state_deref_prot(net->xfrm.state_bysrc, net); + ospi = xfrm_state_deref_prot(net->xfrm.state_byspi, net); + oseq = xfrm_state_deref_prot(net->xfrm.state_byseq, net); ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ oh = xfrm_state_deref_prot(net->xfrm.state_byh, net); ++#endif + ohashmask = net->xfrm.state_hmask; + + rcu_assign_pointer(net->xfrm.state_bydst, ndst); + rcu_assign_pointer(net->xfrm.state_bysrc, nsrc); + rcu_assign_pointer(net->xfrm.state_byspi, nspi); + rcu_assign_pointer(net->xfrm.state_byseq, nseq); ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ rcu_assign_pointer(net->xfrm.state_byh, nh); ++#endif + net->xfrm.state_hmask = nhashmask; + + write_seqcount_end(&net->xfrm.xfrm_state_hash_generation); +@@ -219,6 +256,9 @@ static void xfrm_hash_resize(struct work_struct *work) + xfrm_hash_free(osrc, osize); + xfrm_hash_free(ospi, osize); + xfrm_hash_free(oseq, osize); ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ xfrm_hash_free(oh, osize); ++#endif + } + + static DEFINE_SPINLOCK(xfrm_state_afinfo_lock); +@@ -744,6 +784,9 @@ struct xfrm_state *xfrm_state_alloc(struct net *net) + INIT_HLIST_NODE(&x->bysrc); + INIT_HLIST_NODE(&x->byspi); + INIT_HLIST_NODE(&x->byseq); ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ INIT_HLIST_NODE(&x->byh); ++#endif + hrtimer_setup(&x->mtimer, xfrm_timer_handler, CLOCK_BOOTTIME, + HRTIMER_MODE_ABS_SOFT); + timer_setup(&x->rtimer, xfrm_replay_timer_handler, 0); +@@ -754,6 +797,12 @@ struct xfrm_state *xfrm_state_alloc(struct net *net) + x->lft.hard_packet_limit = XFRM_INF; + x->replay_maxage = 0; + x->replay_maxdiff = 0; ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ do { ++ x->handle = xfrm_state_handle++; ++ } while (x->handle == 0); ++ x->in_byh_hash = 0; ++#endif + x->pcpu_num = UINT_MAX; + spin_lock_init(&x->lock); + x->mode_data = NULL; +@@ -829,6 +878,12 @@ int __xfrm_state_delete(struct xfrm_state *x) + + if (x->id.spi) + hlist_del_rcu(&x->byspi); ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ if (x->handle && x->in_byh_hash) { ++ hlist_del_rcu(&x->byh); ++ x->in_byh_hash = 0; ++ } ++#endif + net->xfrm.state_num--; + xfrm_nat_keepalive_state_updated(x); + spin_unlock(&net->xfrm.xfrm_state_lock); +@@ -1582,6 +1637,13 @@ found: + net->xfrm.state_byseq + h, + x->xso.type); + } ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ if (x->handle && !x->in_byh_hash) { ++ h = x->handle & net->xfrm.state_hmask; ++ hlist_add_head_rcu(&x->byh, net->xfrm.state_byh + h); ++ x->in_byh_hash = 1; ++ } ++#endif + x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; + hrtimer_start(&x->mtimer, + ktime_set(net->xfrm.sysctl_acq_expires, 0), +@@ -1752,6 +1814,14 @@ static void __xfrm_state_insert(struct xfrm_state *x) + x->xso.type); + } + ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ if (x->handle && !x->in_byh_hash) { ++ h = x->handle & net->xfrm.state_hmask; ++ hlist_add_head_rcu(&x->byh, net->xfrm.state_byh + h); ++ x->in_byh_hash = 1; ++ } ++#endif ++ + hrtimer_start(&x->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL_SOFT); + if (x->replay_maxage) + mod_timer(&x->rtimer, jiffies + x->replay_maxage); +@@ -1773,6 +1843,9 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew) + u32 mark = xnew->mark.v & xnew->mark.m; + u32 if_id = xnew->if_id; + u32 cpu_id = xnew->pcpu_num; ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ u16 parent_sa_handle = 0; ++#endif + + h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family); + hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) { +@@ -1782,9 +1855,17 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew) + x->pcpu_num == cpu_id && + (mark & x->mark.m) == x->mark.v && + xfrm_addr_equal(&x->id.daddr, &xnew->id.daddr, family) && +- xfrm_addr_equal(&x->props.saddr, &xnew->props.saddr, family)) ++ xfrm_addr_equal(&x->props.saddr, &xnew->props.saddr, family)) { + x->genid++; ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ if (!parent_sa_handle) ++ parent_sa_handle = x->handle; ++#endif ++ } + } ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ xnew->parent_sa_handle = parent_sa_handle; ++#endif + } + + void xfrm_state_insert(struct xfrm_state *x) +@@ -2352,6 +2433,37 @@ xfrm_state_lookup_byaddr(struct net *net, u32 mark, + } + EXPORT_SYMBOL(xfrm_state_lookup_byaddr); + ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++struct xfrm_state *__xfrm_state_lookup_byhandle(struct net *net, u16 handle) ++{ ++ unsigned int h = handle & net->xfrm.state_hmask; ++ struct xfrm_state *x; ++ ++ hlist_for_each_entry(x, net->xfrm.state_byh + h, byh) { ++ if (x->handle != handle) ++ continue; ++ ++ xfrm_state_hold(x); ++ return x; ++ } ++ ++ return NULL; ++} ++ ++struct xfrm_state * ++xfrm_state_lookup_byhandle(struct net *net, u16 handle) ++{ ++ struct xfrm_state *x; ++ ++ spin_lock_bh(&net->xfrm.xfrm_state_lock); ++ x = __xfrm_state_lookup_byhandle(net, handle); ++ spin_unlock_bh(&net->xfrm.xfrm_state_lock); ++ ++ return x; ++} ++EXPORT_SYMBOL(xfrm_state_lookup_byhandle); ++#endif ++ + struct xfrm_state * + xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid, + u32 if_id, u32 pcpu_num, u8 proto, const xfrm_address_t *daddr, +@@ -2603,6 +2715,13 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high, + x->id.spi = newspi; + h = xfrm_spi_hash(net, &x->id.daddr, newspi, x->id.proto, x->props.family); + XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, x->xso.type); ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ if (x->handle && !x->in_byh_hash) { ++ h = x->handle & net->xfrm.state_hmask; ++ hlist_add_head_rcu(&x->byh, net->xfrm.state_byh + h); ++ x->in_byh_hash = 1; ++ } ++#endif + spin_unlock_bh(&net->xfrm.xfrm_state_lock); + err = 0; + goto unlock; +@@ -3279,6 +3398,12 @@ int __net_init xfrm_state_init(struct net *net) + net->xfrm.state_byseq = xfrm_hash_alloc(sz); + if (!net->xfrm.state_byseq) + goto out_byseq; ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ net->xfrm.state_byh = xfrm_hash_alloc(sz); ++ if (!net->xfrm.state_byh) ++ goto out_byh; ++ get_random_bytes(&xfrm_state_handle, sizeof(xfrm_state_handle)); ++#endif + + net->xfrm.state_cache_input = alloc_percpu(struct hlist_head); + if (!net->xfrm.state_cache_input) +@@ -3294,6 +3419,10 @@ int __net_init xfrm_state_init(struct net *net) + return 0; + + out_state_cache_input: ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ xfrm_hash_free(net->xfrm.state_byh, sz); ++out_byh: ++#endif + xfrm_hash_free(net->xfrm.state_byseq, sz); + out_byseq: + xfrm_hash_free(net->xfrm.state_byspi, sz); +@@ -3321,9 +3450,15 @@ void xfrm_state_fini(struct net *net) + WARN_ON(!hlist_empty(net->xfrm.state_byspi + i)); + WARN_ON(!hlist_empty(net->xfrm.state_bysrc + i)); + WARN_ON(!hlist_empty(net->xfrm.state_bydst + i)); ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ WARN_ON(!hlist_empty(net->xfrm.state_byh + i)); ++#endif + } + + sz = (net->xfrm.state_hmask + 1) * sizeof(struct hlist_head); ++#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD) ++ xfrm_hash_free(net->xfrm.state_byh, sz); ++#endif + xfrm_hash_free(net->xfrm.state_byseq, sz); + xfrm_hash_free(net->xfrm.state_byspi, sz); + xfrm_hash_free(net->xfrm.state_bysrc, sz); diff --git a/patches/split-kernel-patch.sh b/patches/split-kernel-patch.sh new file mode 100644 index 0000000..142833e --- /dev/null +++ b/patches/split-kernel-patch.sh @@ -0,0 +1,249 @@ +#!/usr/bin/env bash +set -euo pipefail + +# split-kernel-patch.sh +# Split one big git-style patch into one patch file per touched file, then +# optionally apply them one by one and stop at the first failure. +# +# Defaults match your ASK kernel patch workflow. +# +# Usage: +# ./split-kernel-patch.sh split +# ./split-kernel-patch.sh apply +# ./split-kernel-patch.sh check +# ./split-kernel-patch.sh reset-output +# +# Env overrides: +# PATCH_FILE=/src/ASK/patches/kernel/002-mono-gateway-ask-kernel_linux_6_12.patch +# LINUX_DIR=/src/linux +# OUT_DIR=/src/ASK/patches/kernel/split-002 +# FUZZ=0 +# USE_PATCH=0 # 0 = git apply, 1 = patch utility +# THREEWAY=0 # git apply --3way when USE_PATCH=0 +# UPDATED_PATCH_DIR=/src/ASK/patches/kernel/updated-patch +# # If a file with the same basename exists here, use it +# # instead of the generated split fragment. + +PATCH_FILE="${PATCH_FILE:-/src/ASK/patches/kernel/002-mono-gateway-ask-kernel_linux_6_12.patch}" +LINUX_DIR="${LINUX_DIR:-/src/linux}" +OUT_DIR="${OUT_DIR:-/src/ASK/patches/kernel/split-002}" +FUZZ="${FUZZ:-0}" +USE_PATCH="${USE_PATCH:-0}" +THREEWAY="${THREEWAY:-0}" +UPDATED_PATCH_DIR="${UPDATED_PATCH_DIR:-$(dirname "$OUT_DIR")/updated-patch}" +SERIES_FILE="${OUT_DIR}/series" +LOG_FILE="${OUT_DIR}/apply.log" + +usage() { + sed -n '1,35p' "$0" >&2 +} + +need_file() { + [ -f "$1" ] || { echo "ERROR: missing file: $1" >&2; exit 1; } +} + +need_dir() { + [ -d "$1" ] || { echo "ERROR: missing directory: $1" >&2; exit 1; } +} + +resolve_patch_file() { + # Generated split fragments are immutable-ish. During porting, put a + # corrected replacement patch in UPDATED_PATCH_DIR with the exact same + # basename, e.g.: + # updated-patch/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch + # The apply/check loop will use that replacement instead. + local generated="$1" + local replacement="${UPDATED_PATCH_DIR}/$(basename "$generated")" + + if [ -f "$replacement" ]; then + printf '%s\n' "$replacement" + else + printf '%s\n' "$generated" + fi +} + +patch_target_file() { + # Best-effort target display for one split fragment. Prefer the b/ path + # from the diff header, fall back to +++ if needed. + awk ' + /^diff --git / { + p = $4 + sub(/^b\//, "", p) + print p + exit + } + /^\+\+\+ / && $2 != "/dev/null" { + p = $2 + sub(/^b\//, "", p) + print p + exit + } + ' "$1" +} + +reset_output() { + rm -rf "$OUT_DIR" + mkdir -p "$OUT_DIR" +} + +split_patch() { + need_file "$PATCH_FILE" + reset_output + + # Lossless split: do NOT trim trailing whitespace and do NOT rewrite content. + # Each output starts at a 'diff --git ...' boundary. + awk -v outdir="$OUT_DIR" -v series="$SERIES_FILE" ' + function sanitize(s) { + sub(/^b\//, "", s) + gsub(/^\"|\"$/, "", s) + gsub(/\//, "__", s) + gsub(/[^A-Za-z0-9._+-]/, "_", s) + if (length(s) > 160) s = substr(s, 1, 160) + return s + } + BEGIN { + n = 0 + out = "" + } + /^diff --git / { + if (out != "") close(out) + n++ + path = $4 + safe = sanitize(path) + out = sprintf("%s/%04d-%s.patch", outdir, n, safe) + print out >> series + } + { + if (out != "") print $0 > out + } + END { + if (out != "") close(out) + if (n == 0) { + print "ERROR: no diff --git sections found" > "/dev/stderr" + exit 2 + } + print n > outdir "/count" + } + ' "$PATCH_FILE" + + echo "Split $(cat "$OUT_DIR/count") patch fragments into: $OUT_DIR" + echo "Series file: $SERIES_FILE" +} + +ensure_split_exists() { + if [ ! -s "$SERIES_FILE" ]; then + echo "=> No split series found, splitting first..." + split_patch + fi +} + +apply_one_git() { + patch_file="$1" + + args=(--verbose) + if [ "$THREEWAY" = "1" ]; then + args+=(--3way) + fi + + git apply "${args[@]}" --check "$patch_file" + git apply "${args[@]}" "$patch_file" +} + +apply_one_patch_utility() { + patch_file="$1" + + # --forward avoids reapplying already-applied hunks. + # --reject leaves .rej files for manual whack-a-mole. + patch -p1 --forward --batch --fuzz="$FUZZ" --dry-run < "$patch_file" + patch -p1 --forward --batch --fuzz="$FUZZ" --reject < "$patch_file" +} + +check_or_apply() { + mode="$1" + ensure_split_exists + need_dir "$LINUX_DIR" + + : > "$LOG_FILE" + cd "$LINUX_DIR" + + i=0 + total=$(wc -l < "$SERIES_FILE" | tr -d ' ') + + while IFS= read -r patch_file; do + i=$((i + 1)) + generated_patch_file="$patch_file" + patch_file=$(resolve_patch_file "$generated_patch_file") + base=$(basename "$generated_patch_file") + patching_target=$(patch_target_file "$patch_file") + if [ -z "$patching_target" ]; then + patching_target="unknown" + fi + + if [ "$patch_file" != "$generated_patch_file" ]; then + echo "=> [$i/$total] $base (using updated-patch override)" | tee -a "$LOG_FILE" + echo " override: $patch_file" >>"$LOG_FILE" + else + echo "=> [$i/$total] $base" | tee -a "$LOG_FILE" + fi + + if [ "$mode" = "check" ]; then + if git apply --check "$patch_file" >>"$LOG_FILE" 2>&1; then + echo " OK" | tee -a "$LOG_FILE" + continue + fi + echo " FAIL: $patch_file" | tee -a "$LOG_FILE" + echo "Stopped at: $patch_file" + echo "Inspect log: $LOG_FILE" + echo "Target file: $patching_target" + echo "" + exit 1 + fi + + if [ "$USE_PATCH" = "1" ]; then + if apply_one_patch_utility "$patch_file" >>"$LOG_FILE" 2>&1; then + echo " applied" | tee -a "$LOG_FILE" + continue + fi + else + if apply_one_git "$patch_file" >>"$LOG_FILE" 2>&1; then + echo " applied" | tee -a "$LOG_FILE" + continue + fi + fi + + echo " FAILED: $patch_file" | tee -a "$LOG_FILE" + echo "" + echo "Stopped at: $patch_file" + echo "Inspect log: $LOG_FILE" + echo "Target file: $patching_target" + echo "" + echo "Useful next commands:" + echo " cd $LINUX_DIR" + echo " git diff" + echo " git status --short" + echo " ${USE_PATCH:+find . -name '*.rej' -o -name '*.orig'}" + exit 1 + done < "$SERIES_FILE" + + echo "All $total patch fragments ${mode}ed successfully." +} + +cmd="${1:-split}" +case "$cmd" in + split) + split_patch + ;; + check) + check_or_apply check + ;; + apply) + check_or_apply apply + ;; + reset-output) + reset_output + ;; + *) + usage + exit 2 + ;; +esac From 9fd18cfe6f97f11aeaf9d8d7cf9eeab6232b137b2dc3bb2fd7e91186979e9c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 10 May 2026 04:35:55 +0800 Subject: [PATCH 03/14] Successfully build based on ASK and run k8s, cdx pending --- alpine/rootfs-extra/etc/fancontrol | 17 +- docker/ask.Dockerfile | 344 ++++++++++-------- kernel-build/dts/mono-gateway-dk-sdk.dts | 32 +- makefile | 17 +- ...-auto-bridge-adapt-timer-api-to-6.18.patch | 62 ++++ ...not-start-dpa_app-from-kernel-module.patch | 24 ++ ...module-init-for-absent-optional-offl.patch | 39 ++ ...-cdx-adapt-dpa-wifi-a050385-to-6.18.patch} | 0 ...4-cdx-add-oh-port-registration-debug.patch | 52 +++ patches/{ => ask}/split-kernel-patch.sh | 0 patches/mono-ask.mk | 87 ----- 11 files changed, 403 insertions(+), 271 deletions(-) create mode 100644 patches/ask/auto_bridge/0001-auto-bridge-adapt-timer-api-to-6.18.patch create mode 100644 patches/ask/cdx/0001-cdx-do-not-start-dpa_app-from-kernel-module.patch create mode 100644 patches/ask/cdx/0002-cdx-do-not-fail-module-init-for-absent-optional-offl.patch rename patches/ask/{0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch => cdx/0003-cdx-adapt-dpa-wifi-a050385-to-6.18.patch} (100%) create mode 100644 patches/ask/cdx/0004-cdx-add-oh-port-registration-debug.patch rename patches/{ => ask}/split-kernel-patch.sh (100%) delete mode 100644 patches/mono-ask.mk diff --git a/alpine/rootfs-extra/etc/fancontrol b/alpine/rootfs-extra/etc/fancontrol index 143d6eb..ddb9db2 100644 --- a/alpine/rootfs-extra/etc/fancontrol +++ b/alpine/rootfs-extra/etc/fancontrol @@ -1,9 +1,10 @@ INTERVAL=10 -DEVPATH=hwmon0=devices/platform/soc/2180000.i2c/i2c-0/i2c-7/7-002e hwmon1=devices/virtual/thermal/thermal_zone0 -DEVNAME=hwmon0=emc2305 hwmon1=ddr_thermal -FCTEMPS=hwmon0/pwm2=hwmon1/temp1_input -FCFANS= hwmon0/pwm2=hwmon0/fan1_input -MINTEMP=hwmon0/pwm2=35 -MAXTEMP=hwmon0/pwm2=60 -MINSTART=hwmon0/pwm2=60 -MINSTOP=hwmon0/pwm2=45 +DEVPATH=hwmon0=devices/platform/soc/1a00000.fman/1afd000.mdio/mdio_bus/0x0000000001afd000/0x0000000001afd000:00 hwmon3=devices/platform/soc/2180000.i2c/i2c-0/i2c-7/7-002e +DEVNAME=hwmon0=0x0000000001afd000:00 hwmon3=emc2305 +FCTEMPS=hwmon3/pwm1=hwmon0/temp1_input +FCFANS= hwmon3/pwm1=hwmon3/fan1_input +MINTEMP=hwmon3/pwm1=35 +MAXTEMP=hwmon3/pwm1=60 +MINSTART=hwmon3/pwm1=60 +MINSTOP=hwmon3/pwm1=45 +MINPWM=hwmon3/pwm1=0 diff --git a/docker/ask.Dockerfile b/docker/ask.Dockerfile index 4b2dced..065ded2 100644 --- a/docker/ask.Dockerfile +++ b/docker/ask.Dockerfile @@ -33,20 +33,20 @@ ARG LIBNFCT_VERSION COPY "${AARCH64_MUSL_CC_TAR}" ./aarch64_musl_cc.tar.gz # Linux kernel -COPY "${NXP_TAR}" ./kernel.tar.gz +COPY "${NXP_TAR}" ./kernel.tar.gz # Copy the ASK deps -COPY "${MONO_ASK_TAR}" ./mono-ask.tar.gz -COPY "${FMC_TAR}" ./fmc.tar.gz -COPY "${FMLIB_TAR}" ./fmlib.tar.gz -COPY "${LIBXML2_TAR}" ./libxml2.tar.xz -COPY "${LIBPCAP_TAR}" ./libpcap.tar.xz -COPY "${TCLAP_TAR}" ./tclap.tar.gz -COPY "${LIBMNL_TAR}" ./libmnl.tar.bz2 -COPY "${LIBCLI_TAR}" ./libcli.tar.gz +COPY "${MONO_ASK_TAR}" ./mono-ask.tar.gz +COPY "${FMC_TAR}" ./fmc.tar.gz +COPY "${FMLIB_TAR}" ./fmlib.tar.gz +COPY "${LIBXML2_TAR}" ./libxml2.tar.xz +COPY "${LIBPCAP_TAR}" ./libpcap.tar.xz +COPY "${TCLAP_TAR}" ./tclap.tar.gz +COPY "${LIBMNL_TAR}" ./libmnl.tar.bz2 +COPY "${LIBCLI_TAR}" ./libcli.tar.gz # Pinned version should keep version names COPY "${LIBNFNETLINK_TAR}" ./libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2 -COPY "${LIBNFCT_TAR}" ./libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz +COPY "${LIBNFCT_TAR}" ./libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz # Provision the musl cross-compiler from musl.cc RUN tar zxf "aarch64_musl_cc.tar.gz" -C /opt @@ -56,141 +56,133 @@ ENV PATH="/opt/aarch64-linux-musl-cross/bin:${PATH}" # Extract and build the dependency libraries RUN mkdir -p ASK/sources/tarballs && \ - tar zxf "mono-ask.tar.gz" -C "ASK" --strip-components=1 && \ - mv libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2 ASK/sources/tarballs/ && \ - mv libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz ASK/sources/tarballs/ + tar zxf "mono-ask.tar.gz" -C "ASK" --strip-components=1 && \ + mv libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2 ASK/sources/tarballs/ && \ + mv libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz ASK/sources/tarballs/ RUN mkdir linux && tar zxf "kernel.tar.gz" -C "linux" --strip-components=1 && \ - mkdir -p /src/ASK/patches/kernel/updated-patch + mkdir -p /src/ASK/patches/kernel/updated-patch # ASK's Kernel patches -COPY patches/split-kernel-patch.sh /src/split-kernel-patch.sh +COPY patches/ask/split-kernel-patch.sh /src/split-kernel-patch.sh COPY patches/ask/kernel/*.patch /src/ASK/patches/kernel/updated-patch/ RUN chmod +x /src/split-kernel-patch.sh && \ - PATCH_FILE="/src/ASK/patches/kernel/002-mono-gateway-ask-kernel_linux_6_12.patch" \ - LINUX_DIR="/src/linux" \ - OUT_DIR="/src/ASK/patches/kernel/split-002" \ - /src/split-kernel-patch.sh split && \ - /src/split-kernel-patch.sh apply + PATCH_FILE="/src/ASK/patches/kernel/002-mono-gateway-ask-kernel_linux_6_12.patch" \ + LINUX_DIR="/src/linux" \ + OUT_DIR="/src/ASK/patches/kernel/split-002" \ + /src/split-kernel-patch.sh split && \ + /src/split-kernel-patch.sh apply # tclap RUN mkdir -p tclap && tar zxf "tclap.tar.gz" -C "tclap" --strip-components=1 && \ - cp -r tclap/include/tclap /opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/ && \ - rm -rf tclap + cp -r tclap/include/tclap /opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/ && \ + rm -rf tclap # libxml2 RUN mkdir -p libxml2 && tar xf "libxml2.tar.xz" -C "libxml2" --strip-components=1 && \ - cd libxml2 && \ - CC=aarch64-linux-musl-gcc ./configure --host=aarch64-linux-musl \ - --prefix=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ - --enable-static --disable-shared --without-python --without-zlib --without-lzma && \ - make -j$(nproc) && make install && \ - cd .. && rm -rf libxml2 + cd libxml2 && \ + CC=aarch64-linux-musl-gcc ./configure --host=aarch64-linux-musl \ + --prefix=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ + --enable-static --disable-shared --without-python --without-zlib --without-lzma && \ + make -j$(nproc) && make install && \ + cd .. && rm -rf libxml2 # libmnl RUN mkdir -p libmnl && tar xjf "libmnl.tar.bz2" -C "libmnl" --strip-components=1 && \ - cd libmnl && \ - CC=aarch64-linux-musl-gcc ./configure --host=aarch64-linux-musl \ - --prefix=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ - --enable-static --disable-shared && \ - make -j$(nproc) && make install && \ - cd .. && rm -rf libmnl + cd libmnl && \ + CC=aarch64-linux-musl-gcc ./configure --host=aarch64-linux-musl \ + --prefix=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ + --enable-static --disable-shared && \ + make -j$(nproc) && make install && \ + cd .. && rm -rf libmnl # libcli RUN mkdir -p libcli && tar zxf "libcli.tar.gz" -C "libcli" --strip-components=1 && \ - cd libcli && \ - make CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar libcli.a && \ - cp libcli.h /opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/ && \ - cp libcli.a /opt/aarch64-linux-musl-cross/aarch64-linux-musl/lib/ && \ - cd .. && rm -rf libcli + cd libcli && \ + make CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar libcli.a && \ + cp libcli.h /opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/ && \ + cp libcli.a /opt/aarch64-linux-musl-cross/aarch64-linux-musl/lib/ && \ + cd .. && rm -rf libcli # libpcap RUN mkdir -p libpcap && tar xf "libpcap.tar.xz" -C "libpcap" --strip-components=1 && \ - cd libpcap && \ - CC=aarch64-linux-musl-gcc ./configure --host=aarch64-linux-musl \ - --prefix=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ - --with-pcap=linux --enable-static --disable-shared \ - --disable-usb --disable-netmap --disable-bluetooth --disable-dbus && \ - make -j$(nproc) && make install && \ - cd .. && rm -rf libpcap + cd libpcap && \ + CC=aarch64-linux-musl-gcc ./configure --host=aarch64-linux-musl \ + --prefix=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ + --with-pcap=linux --enable-static --disable-shared \ + --disable-usb --disable-netmap --disable-bluetooth --disable-dbus && \ + make -j$(nproc) && make install && \ + cd .. && rm -rf libpcap # fmlib, fmc RUN mkdir fmlib && \ - tar zxf "fmlib.tar.gz" -C "fmlib" --strip-components=1 && \ - cd fmlib && git init -q && git add -A && git commit -q -m "base" && \ - git apply /src/ASK/patches/fmlib/01-mono-ask-extensions.patch && \ - make CROSS_COMPILE=aarch64-linux-musl- KERNEL_SRC=../linux libfm-arm.a && \ - ln -sf libfm-arm.a libfm.a && \ - cd ../ && \ - mkdir -p fmc && \ - tar zxf "fmc.tar.gz" -C "fmc" --strip-components=1 && \ - # Handle fmc: Initialize dummy repo, patch, and build \ - cd fmc && git init -q && git add -A && git commit -q -m "base" && \ - git apply /src/ASK/patches/fmc/01-mono-ask-extensions.patch && \ - make -C "source" CC="aarch64-linux-musl-gcc -static" CXX="aarch64-linux-musl-g++ -static" AR=aarch64-linux-musl-ar \ - MACHINE=ls1046 \ - FMD_USPACE_HEADER_PATH=../../fmlib/include/fmd \ - FMD_USPACE_LIB_PATH=../../fmlib \ - LIBXML2_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/libxml2 \ - TCLAP_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include + tar zxf "fmlib.tar.gz" -C "fmlib" --strip-components=1 && \ + cd fmlib && git init -q && git add -A && git commit -q -m "base" && \ + git apply /src/ASK/patches/fmlib/01-mono-ask-extensions.patch && \ + make CROSS_COMPILE=aarch64-linux-musl- KERNEL_SRC=../linux libfm-arm.a && \ + ln -sf libfm-arm.a libfm.a && \ + cd ../ && \ + mkdir -p fmc && \ + tar zxf "fmc.tar.gz" -C "fmc" --strip-components=1 && \ + # Handle fmc: Initialize dummy repo, patch, and build \ + cd fmc && git init -q && git add -A && git commit -q -m "base" && \ + git apply /src/ASK/patches/fmc/01-mono-ask-extensions.patch && \ + make -C "source" CC="aarch64-linux-musl-gcc -static" CXX="aarch64-linux-musl-g++ -static" AR=aarch64-linux-musl-ar \ + MACHINE=ls1046 \ + FMD_USPACE_HEADER_PATH=../../fmlib/include/fmd \ + FMD_USPACE_LIB_PATH=../../fmlib \ + LIBXML2_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/libxml2 \ + TCLAP_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include # Common paths / flags for the remaining ASK build. # Keep userspace fully static against the musl sysroot. ENV ASK_DIR=/src/ASK \ - KERNEL_DIR=/src/linux \ - SYSROOT=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ - HOST=aarch64-linux-musl \ - CROSS_COMPILE=aarch64-linux-musl- \ - ARCH=arm64 \ - PLATFORM=LS1043A + KERNEL_DIR=/src/linux \ + SYSROOT=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ + HOST=aarch64-linux-musl \ + CROSS_COMPILE=aarch64-linux-musl- \ + ARCH=arm64 \ + PLATFORM=LS1043A # Build patched libnfnetlink + libnetfilter_conntrack into the musl sysroot. # These are needed by cmm through pkg-config. RUN mkdir -p "${ASK_DIR}/sources" && \ - mkdir -p libnfnetlink && \ - tar xjf "${ASK_DIR}/sources/tarballs/libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2" \ - -C libnfnetlink --strip-components=1 && \ - cd libnfnetlink && \ - git init -q && git add -A && git commit -q -m "upstream" && \ - git apply "${ASK_DIR}/patches/libnfnetlink/01-nxp-ask-nonblocking-heap-buffer.patch" && \ - CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar RANLIB=aarch64-linux-musl-ranlib \ - ./configure --host="${HOST}" --prefix="${SYSROOT}" \ - --enable-static --disable-shared && \ - make -j$(nproc) && make install && \ - cd /src && rm -rf libnfnetlink && \ - mkdir -p libnetfilter_conntrack && \ - tar xf "${ASK_DIR}/sources/tarballs/libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz" \ - -C libnetfilter_conntrack --strip-components=1 && \ - cd libnetfilter_conntrack && \ - git init -q && git add -A && git commit -q -m "upstream" && \ - git apply "${ASK_DIR}/patches/libnetfilter-conntrack/01-nxp-ask-comcerto-fp-extensions.patch" && \ - PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" \ - CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar RANLIB=aarch64-linux-musl-ranlib \ - ./configure --host="${HOST}" --prefix="${SYSROOT}" \ - --enable-static --disable-shared \ - CFLAGS="-I${SYSROOT}/include" \ - LDFLAGS="-L${SYSROOT}/lib" && \ - make -j$(nproc) && make install && \ - cd /src && rm -rf libnetfilter_conntrack + mkdir -p libnfnetlink && \ + tar xjf "${ASK_DIR}/sources/tarballs/libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2" \ + -C libnfnetlink --strip-components=1 && \ + cd libnfnetlink && \ + git init -q && git add -A && git commit -q -m "upstream" && \ + git apply "${ASK_DIR}/patches/libnfnetlink/01-nxp-ask-nonblocking-heap-buffer.patch" && \ + CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar RANLIB=aarch64-linux-musl-ranlib \ + ./configure --host="${HOST}" --prefix="${SYSROOT}" \ + --enable-static --disable-shared && \ + make -j$(nproc) && make install && \ + cd /src && rm -rf libnfnetlink && \ + mkdir -p libnetfilter_conntrack && \ + tar xf "${ASK_DIR}/sources/tarballs/libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz" \ + -C libnetfilter_conntrack --strip-components=1 && \ + cd libnetfilter_conntrack && \ + git init -q && git add -A && git commit -q -m "upstream" && \ + git apply "${ASK_DIR}/patches/libnetfilter-conntrack/01-nxp-ask-comcerto-fp-extensions.patch" && \ + PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" \ + CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar RANLIB=aarch64-linux-musl-ranlib \ + ./configure --host="${HOST}" --prefix="${SYSROOT}" \ + --enable-static --disable-shared \ + CFLAGS="-I${SYSROOT}/include" \ + LDFLAGS="-L${SYSROOT}/lib" && \ + make -j$(nproc) && make install && \ + cd /src && rm -rf libnetfilter_conntrack # Build libfci, used by cmm. RUN make -C "${ASK_DIR}/fci/lib" \ - CC=aarch64-linux-musl-gcc \ - AR=aarch64-linux-musl-ar + CC=aarch64-linux-musl-gcc \ + AR=aarch64-linux-musl-ar -COPY patches/ask/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch /src/ - -RUN cd /src/ASK && \ - git init -q && git add -A && git commit -q -m "base" && \ - git apply /src/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch - -# Build the kernel +# Build the kernel first, without the custom DTS COPY kernel-extra.config /src/kernel-extra.config -COPY kernel-build/dts/*.dts /src/linux/arch/arm64/boot/dts/freescale/ COPY kernel-build/ensure-kconfig.sh /src/ -# NXP tree: use the LSDK defconfig target RUN cd /src/linux \ && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" defconfig lsdk.config \ && ./scripts/kconfig/merge_config.sh -m .config "${ASK_DIR}/config/kernel/defconfig" /src/kernel-extra.config \ @@ -198,54 +190,110 @@ RUN cd /src/linux \ && /src/ensure-kconfig.sh .config /src/kernel-extra.config \ && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" -j"$(nproc)" +# DTS changes happen after the expensive kernel build layer +COPY kernel-build/dts/*.dts /src/linux/arch/arm64/boot/dts/freescale/ + +ARG DEVICE_TREE_TARGET + +RUN cd /src/linux \ + && grep -q "^dtb-\\\$(CONFIG_ARCH_LAYERSCAPE) += ${DEVICE_TREE_TARGET}.dtb$" \ + arch/arm64/boot/dts/freescale/Makefile \ + || echo "dtb-\$(CONFIG_ARCH_LAYERSCAPE) += ${DEVICE_TREE_TARGET}.dtb" \ + >> arch/arm64/boot/dts/freescale/Makefile \ + && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" \ + "freescale/${DEVICE_TREE_TARGET}.dtb" + +# Patch verdor's modules +RUN mkdir -p /src/patches/ask +COPY patches/ask/ /src/patches/ask/ + +RUN cd /src/ASK && \ + git init -q && git add -A && git commit -q -m "base" && \ + find /src/patches/ask \ + -path /src/patches/ask/kernel -prune -o \ + -name '*.patch' -print \ + | sort > /tmp/ask-module-patches.list && \ + test ! -s /tmp/ask-module-patches.list || xargs -a /tmp/ask-module-patches.list git apply --check && \ + test ! -s /tmp/ask-module-patches.list || xargs -a /tmp/ask-module-patches.list git apply # Build out-of-tree ASK kernel modules: cdx -> fci, plus auto_bridge. RUN make -C "${ASK_DIR}/cdx" \ - CROSS_COMPILE="${CROSS_COMPILE}" \ - ARCH="${ARCH}" \ - KERNELDIR="${KERNEL_DIR}" \ - PLATFORM="${PLATFORM}" \ - modules && \ - make -C "${ASK_DIR}/fci" \ - CROSS_COMPILE="${CROSS_COMPILE}" \ - ARCH="${ARCH}" \ - KERNEL_SOURCE="${KERNEL_DIR}" \ - BOARD_ARCH="${ARCH}" \ - KBUILD_EXTRA_SYMBOLS="${ASK_DIR}/cdx/Module.symvers" \ - modules && \ - make -C "${ASK_DIR}/auto_bridge" \ - CROSS_COMPILE="${CROSS_COMPILE}" \ - ARCH="${ARCH}" \ - KERNEL_SOURCE="${KERNEL_DIR}" \ - PLATFORM="${PLATFORM}" + CROSS_COMPILE="${CROSS_COMPILE}" \ + ARCH="${ARCH}" \ + KERNELDIR="${KERNEL_DIR}" \ + PLATFORM="${PLATFORM}" \ + modules && \ + make -C "${ASK_DIR}/fci" \ + CROSS_COMPILE="${CROSS_COMPILE}" \ + ARCH="${ARCH}" \ + KERNEL_SOURCE="${KERNEL_DIR}" \ + BOARD_ARCH="${ARCH}" \ + KBUILD_EXTRA_SYMBOLS="${ASK_DIR}/cdx/Module.symvers" \ + modules && \ + make -C "${ASK_DIR}/auto_bridge" \ + CROSS_COMPILE="${CROSS_COMPILE}" \ + ARCH="${ARCH}" \ + KERNEL_SOURCE="${KERNEL_DIR}" \ + PLATFORM="${PLATFORM}" + +# Patch vendor's binaries +RUN sed -i '/^[[:space:]]*CFLAGS[[:space:]]*+=.*-Wall.*-Werror/a CFLAGS += -Wno-address-of-packed-member' "${ASK_DIR}/cmm/Makefile" # Build remaining userspace binaries: cmm and dpa_app. RUN make -C "${ASK_DIR}/cmm" \ - CC="aarch64-linux-musl-gcc -static" \ - LIBFCI_DIR="${ASK_DIR}/fci/lib" \ - ABM_DIR="${ASK_DIR}/auto_bridge" \ - SYSROOT="${SYSROOT}" \ - PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" && \ - make -C "${ASK_DIR}/dpa_app" \ - CC="aarch64-linux-musl-gcc -static" \ - CFLAGS="-DDPAA_DEBUG_ENABLE -DNCSW_LINUX \ - -I/src/fmc/source \ - -I${ASK_DIR}/cdx \ - -I/src/fmlib/include/fmd \ - -I/src/fmlib/include/fmd/Peripherals \ - -I/src/fmlib/include/fmd/integrations" \ - LDFLAGS="-static -L/src/fmc/source -L/src/fmlib -L${SYSROOT}/lib \ - -lfmc -lfm -lcli -lxml2 -lstdc++ -lpthread -lm" + CC="aarch64-linux-musl-gcc -static" \ + LIBFCI_DIR="${ASK_DIR}/fci/lib" \ + ABM_DIR="${ASK_DIR}/auto_bridge" \ + SYSROOT="${SYSROOT}" \ + PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" && \ + make -C "${ASK_DIR}/dpa_app" \ + CC="aarch64-linux-musl-gcc -static" \ + CFLAGS="-DDPAA_DEBUG_ENABLE -DNCSW_LINUX \ + -I/src/fmc/source \ + -I${ASK_DIR}/cdx \ + -I/src/fmlib/include/fmd \ + -I/src/fmlib/include/fmd/Peripherals \ + -I/src/fmlib/include/fmd/integrations" \ + LDFLAGS="-static -L/src/fmc/source -L/src/fmlib -L${SYSROOT}/lib \ + -lfmc -lfm -lcli -lxml2 -lstdc++ -lpthread -lm" -# Stage outputs. -RUN mkdir -p /out/ask && \ - cp "${ASK_DIR}/cdx/cdx.ko" /out/ask/ && \ - cp "${ASK_DIR}/fci/fci.ko" /out/ask/ && \ - cp "${ASK_DIR}/auto_bridge/auto_bridge.ko" /out/ask/ && \ - cp /src/fmc/source/fmc /out/ask/ && \ - cp "${ASK_DIR}/cmm/src/cmm" /out/ask/ && \ - cp "${ASK_DIR}/dpa_app/dpa_app" /out/ask/ && \ - aarch64-linux-musl-strip /out/ask/fmc /out/ask/cmm /out/ask/dpa_app || true +# Stage outputs +RUN mkdir -p /out/ASK/dist && \ + cp "${ASK_DIR}/cdx/cdx.ko" /out/ASK/dist && \ + cp "${ASK_DIR}/fci/fci.ko" /out/ASK/dist && \ + cp "${ASK_DIR}/auto_bridge/auto_bridge.ko" /out/ASK/dist && \ + mkdir -p /out/ask/bin && \ + cp /src/fmc/source/fmc /out/ASK/bin && \ + cp "${ASK_DIR}/cmm/src/cmm" /out/ASK/bin && \ + cp "${ASK_DIR}/dpa_app/dpa_app" /out/ASK/bin && \ + aarch64-linux-musl-strip /out/ASK/bin/fmc /out/ASK/bin/cmm /out/ASK/bin/dpa_app || true -FROM scratch AS ask-artifacts -COPY --from=build /out/ask/ / +# in-tree Linux kernel modules +RUN mkdir -p /out/rootfs && \ + make -C /src/linux ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \ + modules_install INSTALL_MOD_PATH=/out/rootfs + +RUN KERNEL_VER=$(ls /out/rootfs/lib/modules/) && \ + mkdir -p /out/rootfs/lib/modules/$KERNEL_VER/extra && \ + mv /out/ASK/dist/*.ko /out/rootfs/lib/modules/$KERNEL_VER/extra/ && \ + depmod -b /out/rootfs $KERNEL_VER && \ + cd /out && tar zcf rootfs.tar.gz rootfs + +FROM scratch AS export + +ARG DEVICE_TREE_TARGET + +# Export the newly staged in-tree modules +COPY --from=build /out/rootfs.tar.gz / +COPY --from=build \ + /src/linux/System.map \ + /src/linux/.config \ + /src/linux/arch/arm64/boot/Image.gz \ + /src/linux/arch/arm64/boot/dts/freescale/${DEVICE_TREE_TARGET}.dtb \ + /kernel/ + +# Grab the proprietary Mono Gateway XML configs +COPY --from=build \ + /src/ASK/config/gateway-dk/cdx_cfg.xml \ + /src/ASK/dpa_app/files/etc/cdx_pcd.xml \ + /xml/ diff --git a/kernel-build/dts/mono-gateway-dk-sdk.dts b/kernel-build/dts/mono-gateway-dk-sdk.dts index 8270375..8ea2c5b 100644 --- a/kernel-build/dts/mono-gateway-dk-sdk.dts +++ b/kernel-build/dts/mono-gateway-dk-sdk.dts @@ -347,22 +347,6 @@ phy-connection-type = "xgmii"; }; - /* DPA Offline port bindings - required for CDX. - * Use phandles fman0_oh_0x3 (port@83000) and fman0_oh_0x4 (port@84000). - * Cell-index overridden to SDK-style (1 and 2) in port nodes above. - */ - dpa-fman0-oh@2 { - compatible = "fsl,dpa-oh"; - fsl,qman-frame-queues-oh = <0x60 0x01 0x61 0x01>; - fsl,fman-oh-port = <&fman0_oh_0x3>; - }; - - dpa-fman0-oh@3 { - compatible = "fsl,dpa-oh"; - fsl,qman-frame-queues-oh = <0x62 0x01 0x63 0x01>; - fsl,fman-oh-port = <&fman0_oh_0x4>; - }; - /* Override OH port cell-index values for SDK driver compatibility. * SDK driver expects cell-index 0 for HC (Host Command/PCD) port. * Mainline qoriq-fman3-0.dtsi uses cell-index 2-7, but SDK needs 0-5. @@ -373,8 +357,8 @@ }; port@83000 { - cell-index = <1>; compatible = "fsl,fman-port-oh"; + cell-index = <1>; }; port@84000 { @@ -568,4 +552,18 @@ &fsldpaa { dma-coherent; + /* CDX / DPA IPsec offline port */ + dpa-fman0-oh@2 { + compatible = "fsl,dpa-oh"; + fsl,qman-frame-queues-oh = <0x60 0x01 0x61 0x01>; + fsl,fman-oh-port = <&fman0_oh_0x3>; + dma-coherent; + }; + /* CDX / VWD WiFi offline port; optional */ + dpa-fman0-oh@3 { + compatible = "fsl,dpa-oh"; + fsl,qman-frame-queues-oh = <0x62 0x01 0x63 0x01>; + fsl,fman-oh-port = <&fman0_oh_0x4>; + dma-coherent; + }; }; diff --git a/makefile b/makefile index 064ebc9..8c7c48b 100644 --- a/makefile +++ b/makefile @@ -176,17 +176,11 @@ $(BUILD_BASE_STAMP): $(BUILD_BASE_DEPS) | $(OUT_DIR) docker tag monok8s/build-base:$(TAG) monok8s/build-base:$$iid; \ touch $@ -$(KERNEL_IMAGE): $(KERNEL_DEPS) $(DOWNLOAD_PACKAGES_STAMP) | $(OUT_DIR) - docker build \ - -f docker/kernel-build.Dockerfile \ - --build-arg DOCKER_IMAGE_ROOT=$(DOCKER_IMAGE_ROOT) \ - --build-arg TAG=$(TAG) \ - --build-arg ARCH=$(ARCH) \ - --build-arg CROSS_COMPILE=$(CROSS_COMPILE) \ - --build-arg NXP_VERSION=$(NXP_VERSION) \ - --build-arg DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \ - --output type=local,dest=./$(OUT_DIR) . - test -f $@ +$(KERNEL_IMAGE): $(KERNEL_DEPS) $(DOWNLOAD_PACKAGES_STAMP) ASK | $(OUT_DIR) + rm -f "$@" + cp $(OUT_DIR)/ASK/rootfs.tar.gz $(OUT_DIR)/rootfs.tar.gz + cp $(OUT_DIR)/ASK/kernel/* $(OUT_DIR)/ + test -f "$@" $(INITRAMFS): $(INITRAMFS_DEPS) $(DOWNLOAD_PACKAGES_STAMP) | $(OUT_DIR) docker build \ @@ -232,6 +226,7 @@ ASK: $(ASK_TAR) $(LIBNFCT_TAR) $(LIBNFNETLINK_TAR) $(TCLAP_TAR) $(LIBXML2_TAR) | --build-arg LIBCLI_TAR=$(LIBCLI_TAR) \ --build-arg LIBNFNETLINK_VERSION=$(LIBNFNETLINK_VERSION) \ --build-arg LIBNFCT_VERSION=$(LIBNFCT_VERSION) \ + --build-arg DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \ --output type=local,dest=./$(OUT_DIR)/ASK . vpp: $(BUILD_BASE_STAMP) $(VPP_TAR) $(DPDK_TAR) $(FMLIB_TAR) $(FMC_TAR) $(NXP_TAR) diff --git a/patches/ask/auto_bridge/0001-auto-bridge-adapt-timer-api-to-6.18.patch b/patches/ask/auto_bridge/0001-auto-bridge-adapt-timer-api-to-6.18.patch new file mode 100644 index 0000000..e4c6cf9 --- /dev/null +++ b/patches/ask/auto_bridge/0001-auto-bridge-adapt-timer-api-to-6.18.patch @@ -0,0 +1,62 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: builder +Date: Sun, 10 May 2026 00:00:00 +0000 +Subject: [PATCH] auto_bridge: adapt timer API names for Linux 6.18 + +Linux 6.18 uses the renamed timer helpers. Update the vendor +module to use timer_delete() and timer_container_of(). + +--- + auto_bridge/auto_bridge.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/auto_bridge/auto_bridge.c ++++ b/auto_bridge/auto_bridge.c +@@ -243,7 +243,7 @@ + list_add(&table_entry->list_msg_to_send, &l2flow_list_msg_to_send); + work_to_do = 1; + } +- if (del_timer(&table_entry->timeout) || no_timer) ++ if (timer_delete(&table_entry->timeout) || no_timer) + __abm_go_dying(table_entry); + } + } +@@ -604,7 +604,7 @@ + ****************************************************************************/ + static void abm_death_by_timeout(struct timer_list *t) + { +- struct l2flowTable *table_entry = from_timer(table_entry, t, timeout); ++ struct l2flowTable *table_entry = timer_container_of(table_entry, t, timeout); + + spin_lock_bh(&abm_lock); + __abm_go_dying(table_entry); +@@ -671,7 +671,7 @@ + /* Flow is programmed in FPP */ + table_entry->state = L2FLOW_STATE_FF; + /* If timer already expired we'll die, it's ok though... */ +- del_timer(&table_entry->timeout); ++ timer_delete(&table_entry->timeout); + } + else if(flags & L2FLOW_DENIED){ + /* Flow is not programmed in FPP */ +@@ -735,7 +735,7 @@ + } + + /* Die soon or now */ +- if(del_timer(&table_entry->timeout) || (table_entry->state == L2FLOW_STATE_FF)) ++ if(timer_delete(&table_entry->timeout) || (table_entry->state == L2FLOW_STATE_FF)) + __abm_go_dying(table_entry); + } + else{ +@@ -1093,7 +1093,7 @@ + list_for_each_safe(entry, tmp, &l2flow_table[i]){ + table_entry = container_of(entry, struct l2flowTable, list); + table_entry->flags |= L2FLOW_FL_DEAD; +- if(del_timer(&table_entry->timeout) || table_entry->state == L2FLOW_STATE_FF) ++ if(timer_delete(&table_entry->timeout) || table_entry->state == L2FLOW_STATE_FF) + __abm_go_dying(table_entry); + } + } + +-- +2.43.0 diff --git a/patches/ask/cdx/0001-cdx-do-not-start-dpa_app-from-kernel-module.patch b/patches/ask/cdx/0001-cdx-do-not-start-dpa_app-from-kernel-module.patch new file mode 100644 index 0000000..39db4b5 --- /dev/null +++ b/patches/ask/cdx/0001-cdx-do-not-start-dpa_app-from-kernel-module.patch @@ -0,0 +1,24 @@ +From c772418b42580bcf9d9b863e742df7ae3f921176 Mon Sep 17 00:00:00 2001 +From: test +Date: Sat, 9 May 2026 16:59:25 +0000 +Subject: [PATCH 1/2] cdx: do not start dpa_app from kernel module + + +diff --git a/cdx/cdx_main.c b/cdx/cdx_main.c +index 2d7b72b..ec763cb 100644 +--- a/cdx/cdx_main.c ++++ b/cdx/cdx_main.c +@@ -8,8 +8,8 @@ + * + */ + +-//uncomment to start dpa_app from cdx module +-#define START_DPA_APP 1 ++// Start dpa_app from userspace service ordering instead of kernel module init. ++// #define START_DPA_APP 1 + + #define DEFINE_GLOBALS + #include "portdefs.h" +-- +2.47.3 + diff --git a/patches/ask/cdx/0002-cdx-do-not-fail-module-init-for-absent-optional-offl.patch b/patches/ask/cdx/0002-cdx-do-not-fail-module-init-for-absent-optional-offl.patch new file mode 100644 index 0000000..fb2ba39 --- /dev/null +++ b/patches/ask/cdx/0002-cdx-do-not-fail-module-init-for-absent-optional-offl.patch @@ -0,0 +1,39 @@ +From 919ea304abf495a7142639e51555508fa1b23a30 Mon Sep 17 00:00:00 2001 +From: test +Date: Sat, 9 May 2026 16:59:28 +0000 +Subject: [PATCH 2/2] cdx: do not fail module init for absent optional offloads + + +diff --git a/cdx/cdx_main.c b/cdx/cdx_main.c +index ec763cb..641121b 100644 +--- a/cdx/cdx_main.c ++++ b/cdx/cdx_main.c +@@ -195,16 +195,17 @@ static int __init cdx_module_init(void) + #ifdef CFG_WIFI_OFFLOAD + rc = dpaa_vwd_init(); + if (rc != 0) { +- printk("%s::vwd_driver_init failed\n", __func__); +- goto exit; ++ printk(KERN_WARNING "%s::vwd_driver_init failed rc %d; continuing without wifi offload\n", ++ __func__, rc); ++ rc = 0; + } + #endif +- // initialize global fragmentation params +- if (cdx_init_frag_module()) { +- printk("%s::cdx_init_frag_module failed\n", __func__); +- rc = -EIO; +- goto exit; +- } ++ /* ++ * The vendor fragmentation path assumes its BMan pool/config exists and ++ * can crash in bman_free_pool() when this board profile does not provide ++ * it. Keep CDX usable without the optional fragmentation offload path. ++ */ ++ printk(KERN_WARNING "%s::skipping cdx_init_frag_module on this platform\n", __func__); + + #ifdef DPA_IPSEC_OFFLOAD + if (cdx_dpa_ipsec_init()) { +-- +2.47.3 + diff --git a/patches/ask/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch b/patches/ask/cdx/0003-cdx-adapt-dpa-wifi-a050385-to-6.18.patch similarity index 100% rename from patches/ask/0001-cdx-adapt-dpa-wifi-a050385-to-6.18.patch rename to patches/ask/cdx/0003-cdx-adapt-dpa-wifi-a050385-to-6.18.patch diff --git a/patches/ask/cdx/0004-cdx-add-oh-port-registration-debug.patch b/patches/ask/cdx/0004-cdx-add-oh-port-registration-debug.patch new file mode 100644 index 0000000..08833f2 --- /dev/null +++ b/patches/ask/cdx/0004-cdx-add-oh-port-registration-debug.patch @@ -0,0 +1,52 @@ +--- a/cdx/devoh.c ++++ b/cdx/devoh.c +@@ -313,6 +313,7 @@ + uint32_t port_idx; + uint8_t oh_iface_name[8]=""; + ++ printk(KERN_INFO "%s::adding OH iface name=%s\n", __func__, name); + + if (sscanf(name, "dpa-fman%d-oh@%d", &fman_idx, + &port_idx) != 2) { +@@ -331,6 +332,8 @@ + DPA_ERROR("%s::oh_port_driver_get_port_info failed\n", __func__); + return FAILURE; + } ++ printk(KERN_INFO "%s::OH port info name=%s channel=%u default_fqid=0x%x err_fqid=0x%x\n", ++ __func__, name, info.channel_id, info.default_fqid, info.err_fqid); + //ethernet/physical iface type + iface_info = (struct dpa_iface_info *) + kzalloc(sizeof(struct dpa_iface_info), GFP_KERNEL); +@@ -358,6 +361,10 @@ + __func__, name); + goto err_ret; + } ++ printk(KERN_INFO "%s::CDX OH iface config found name=%s fman=%u port_idx=%u portid=%u max_dist=%u\n", ++ __func__, name, ++ iface_info->oh_info.fman_idx, iface_info->oh_info.port_idx, ++ iface_info->oh_info.portid, iface_info->oh_info.max_dist); + if (cdx_create_dir_in_procfs(&iface_info->pcd_proc_entry, oh_iface_name, PCD_DIR)) { + DPA_ERROR("%s:: create pcd proc entry failed %s\n", + __func__, name); +@@ -581,6 +588,10 @@ + #endif + } + //add fqid information into of port list ++ printk(KERN_INFO "%s::created OH FQs name=%s fman=%u port_idx=%u rx_default_fqid=0x%x rx_err_fqid=0x%x channel=0x%x\n", ++ __func__, dpa_oh_iface_info->name, iface_info->fman_idx, ++ iface_info->port_idx, iface_info->fqinfo[RX_DEFA_FQ].fq_base, ++ iface_info->fqinfo[RX_ERR_FQ].fq_base, iface_info->channel_id); + port_info->fm_idx = iface_info->fman_idx; + port_info->ohinfo = iface_info; + port_info->channel = iface_info->channel_id; +@@ -600,6 +611,10 @@ + } + offline_port_info[iface_info->fman_idx][iface_info->port_idx].flags |= + (OF_FQID_VALID | PORT_VALID); ++ printk(KERN_INFO "%s::OH port registered name=%s fman=%u port_idx=%u flags=0x%x\n", ++ __func__, port_info->name, iface_info->fman_idx, ++ iface_info->port_idx, ++ offline_port_info[iface_info->fman_idx][iface_info->port_idx].flags); + return 0; + } + diff --git a/patches/split-kernel-patch.sh b/patches/ask/split-kernel-patch.sh similarity index 100% rename from patches/split-kernel-patch.sh rename to patches/ask/split-kernel-patch.sh diff --git a/patches/mono-ask.mk b/patches/mono-ask.mk deleted file mode 100644 index 39ddb77..0000000 --- a/patches/mono-ask.mk +++ /dev/null @@ -1,87 +0,0 @@ -# mono-ask.mk -# Custom wrapper to build the NXP ASK for the monok8s Alpine/musl ecosystem - -# Define default paths and cross-compilers -KDIR?= /src/linux -ASK_DIR?= $(CURDIR) -ARCH?= arm64 -GNU_CROSS?= aarch64-linux-gnu- -MUSL_HOST?= aarch64-linux-musl - -STAMPS_DIR := $(ASK_DIR)/sources/.stamps -FMLIB_DIR := $(ASK_DIR)/sources/fmlib -FMC_BASE := $(ASK_DIR)/sources/fmc -FMC_DIR := $(FMC_BASE)/source - -SYSROOT_PATH := /opt/aarch64-linux-musl-cross/aarch64-linux-musl - -.PHONY: prepare-kernel build-kernel modules userspace dist - -prepare-preloaded-sources: - @echo "--> Initializing dummy git repos and building preloaded fmlib/fmc..." - mkdir -p $(STAMPS_DIR) - - git config --global user.email "monok8s@localhost" - git config --global user.name "monok8s authors" - git config --global --add safe.directory '*' - - # Inject libmnl.pc into the vendor's isolated sysroot to satisfy pkg-config - mkdir -p $(ASK_DIR)/sources/sysroot/lib/pkgconfig - cp -a $(SYSROOT_PATH)/lib/pkgconfig/libmnl.pc $(ASK_DIR)/sources/sysroot/lib/pkgconfig/ - - # Handle fmlib: Initialize dummy repo, patch, and build - cd $(FMLIB_DIR) && git init -q && git add -A && git commit -q -m "base" - cd $(FMLIB_DIR) && git apply $(ASK_DIR)/patches/fmlib/01-mono-ask-extensions.patch - $(MAKE) -C $(FMLIB_DIR) CROSS_COMPILE=$(MUSL_HOST)- KERNEL_SRC=$(KDIR) libfm-arm.a - ln -sf libfm-arm.a $(FMLIB_DIR)/libfm.a - touch $(STAMPS_DIR)/fmlib - - # Handle fmc: Initialize dummy repo, patch, and build - cd $(FMC_BASE) && git init -q && git add -A && git commit -q -m "base" - cd $(FMC_BASE) && git apply $(ASK_DIR)/patches/fmc/01-mono-ask-extensions.patch - $(MAKE) -C $(FMC_DIR) CC="$(MUSL_HOST)-gcc -static" CXX="$(MUSL_HOST)-g++ -static" AR=$(MUSL_HOST)-ar \ - MACHINE=ls1046 \ - FMD_USPACE_HEADER_PATH=$(FMLIB_DIR)/include/fmd \ - FMD_USPACE_LIB_PATH=$(FMLIB_DIR) \ - LIBXML2_HEADER_PATH=$(SYSROOT_PATH)/include/libxml2 \ - TCLAP_HEADER_PATH=$(SYSROOT_PATH)/include - touch $(STAMPS_DIR)/fmc - -# 1. Patch the kernel and merge our custom Kubernetes configuration -prepare-kernel: - @echo "--> Patching the Linux kernel with NXP DPAA extensions..." - cd $(KDIR) && patch -p1 < $(ASK_DIR)/patches/kernel/002-mono-gateway-ask-kernel_linux_6_12.patch - @echo "--> Merging NXP defconfig with Kubernetes extra config..." - cp $(ASK_DIR)/config/kernel/defconfig $(KDIR)/.config - cd $(KDIR) && ./scripts/kconfig/merge_config.sh -m .config /src/kernel-extra.config - $(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(GNU_CROSS) olddefconfig - /src/ensure-kconfig.sh $(KDIR)/.config /src/kernel-extra.config - -# 2. Build the kernel tree (mandatory before out-of-tree modules can be built) -build-kernel: prepare-kernel - @echo "--> Building the Linux kernel natively..." - # Replace "dtbs" with the exact path to your target dtb - $(MAKE) -C $(KDIR) ARCH=$(ARCH) CROSS_COMPILE=$(GNU_CROSS) -j$$(nproc) \ - Image modules freescale/mono-gateway-dk-sdk.dtb - -# 3. Build the ASK out-of-tree modules using the vendor Makefile -modules: build-kernel - @echo "--> Building ASK out-of-tree modules..." - $(MAKE) -f Makefile modules KDIR=$(KDIR) CROSS_COMPILE=$(GNU_CROSS) ARCH=$(ARCH) - -# 4. Build the ASK userspace daemons using the musl cross-compiler -userspace: prepare-preloaded-sources - @echo "--> Building ASK sources and libraries..." - $(MAKE) -f Makefile sources KDIR=$(KDIR) CROSS_COMPILE=$(MUSL_HOST)- ARCH=$(ARCH) HOST=$(MUSL_HOST) - - @echo "--> Stripping -Werror from vendor Makefiles for modern GCC compatibility..." - sed -i 's/-Werror//g' $(ASK_DIR)/cmm/Makefile - sed -i 's/-Werror//g' $(ASK_DIR)/dpa_app/Makefile - - @echo "--> Building ASK userspace executables statically..." - $(MAKE) -f Makefile userspace KDIR=$(KDIR) CROSS_COMPILE=$(MUSL_HOST)- ARCH=$(ARCH) HOST=$(MUSL_HOST) CC='"$(MUSL_HOST)-gcc -static"' CXX='"$(MUSL_HOST)-g++ -static"' - -# 5. Extract artifacts -dist: - @echo "--> Staging artifacts..." - $(MAKE) -f Makefile dist KDIR=$(KDIR) CROSS_COMPILE=$(GNU_CROSS) ARCH=$(ARCH) From d308dafa4cd5d8bcefeb287123faec5c92a0fcf63e7f80bedb135157b97cc0b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 10 May 2026 04:36:48 +0800 Subject: [PATCH 04/14] Missing files --- ...module-init-for-absent-optional-offl.patch | 73 +++++++++++++++---- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/patches/ask/cdx/0002-cdx-do-not-fail-module-init-for-absent-optional-offl.patch b/patches/ask/cdx/0002-cdx-do-not-fail-module-init-for-absent-optional-offl.patch index fb2ba39..a4347b4 100644 --- a/patches/ask/cdx/0002-cdx-do-not-fail-module-init-for-absent-optional-offl.patch +++ b/patches/ask/cdx/0002-cdx-do-not-fail-module-init-for-absent-optional-offl.patch @@ -1,14 +1,28 @@ -From 919ea304abf495a7142639e51555508fa1b23a30 Mon Sep 17 00:00:00 2001 -From: test -Date: Sat, 9 May 2026 16:59:28 +0000 -Subject: [PATCH 2/2] cdx: do not fail module init for absent optional offloads +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: builder +Date: Sun, 10 May 2026 00:00:00 +0000 +Subject: [PATCH] cdx: keep optional offload init failures non-fatal +The CDX module currently treats several board-specific acceleration paths as +mandatory. On boards without VWD/WiFi OH ports, fragmentation BMan pools, or +DPA IPsec OH ports, module init either fails or can crash before returning an +error. + +Keep the CDX core loadable when those optional resources are absent: + + - warn and continue when VWD/WiFi init fails; + - skip the vendor fragmentation module on this platform, because it can + dereference a missing BMan pool; + - warn and continue when DPA IPsec init fails; + - only initialize DPA IPsec follow-up buffer pools when IPsec init succeeds. +--- + cdx/cdx_main.c | 47 +++++++++++++++++++++-------------------------- + 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/cdx/cdx_main.c b/cdx/cdx_main.c -index ec763cb..641121b 100644 --- a/cdx/cdx_main.c +++ b/cdx/cdx_main.c -@@ -195,16 +195,17 @@ static int __init cdx_module_init(void) +@@ -178,31 +178,36 @@ static int __init cdx_module_init(void) #ifdef CFG_WIFI_OFFLOAD rc = dpaa_vwd_init(); if (rc != 0) { @@ -25,15 +39,48 @@ index ec763cb..641121b 100644 - rc = -EIO; - goto exit; - } ++ + /* -+ * The vendor fragmentation path assumes its BMan pool/config exists and -+ * can crash in bman_free_pool() when this board profile does not provide -+ * it. Keep CDX usable without the optional fragmentation offload path. ++ * The vendor fragmentation path is optional for this platform and can ++ * dereference a missing BMan pool before returning an error. Do not let a ++ * missing fragmentation pool prevent the CDX core from loading. + */ -+ printk(KERN_WARNING "%s::skipping cdx_init_frag_module on this platform\n", __func__); ++ printk(KERN_WARNING "%s::skipping cdx_init_frag_module on this platform\n", ++ __func__); #ifdef DPA_IPSEC_OFFLOAD - if (cdx_dpa_ipsec_init()) { +- if (cdx_dpa_ipsec_init()) { +- printk("%s::dpa_ipsec start failed\n", __func__); +- goto exit; +- } +- +- if (cdx_init_scatter_gather_bpool()) { +- printk("%s::cdx_init_scatter_gather_bpool failed\n",__func__); +- rc = -ENOMEM; +- goto exit; +- } +- if (cdx_init_skb_2bfreed_bpool()) { +- printk("%s(%d) : cdx_init_skb_2bfreed_bpool failed\n", __func__,__LINE__); +- rc = -ENOMEM; +- goto exit; ++ rc = cdx_dpa_ipsec_init(); ++ if (rc) { ++ printk(KERN_WARNING "%s::dpa_ipsec start failed rc %d; continuing without DPA IPsec offload\n", ++ __func__, rc); ++ rc = 0; ++ } else { ++ if (cdx_init_scatter_gather_bpool()) { ++ printk("%s::cdx_init_scatter_gather_bpool failed\n", __func__); ++ rc = -ENOMEM; ++ goto exit; ++ } ++ if (cdx_init_skb_2bfreed_bpool()) { ++ printk("%s(%d) : cdx_init_skb_2bfreed_bpool failed\n", __func__, __LINE__); ++ rc = -ENOMEM; ++ goto exit; ++ } + } + #endif + -- -2.47.3 - +2.45.0 From 075efa3348f0368582954ded87cadde94000b01dd3c396b6d46cd7534449bf3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 10 May 2026 05:09:53 +0800 Subject: [PATCH 05/14] Copy requried xml files --- docker/ask.Dockerfile | 20 ++++++----- ...cdx-cfg-use-standard-offline-portids.patch | 33 +++++++++++++++++++ 2 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 patches/ask/config/0001-gateway-dk-cdx-cfg-use-standard-offline-portids.patch diff --git a/docker/ask.Dockerfile b/docker/ask.Dockerfile index 065ded2..533c26c 100644 --- a/docker/ask.Dockerfile +++ b/docker/ask.Dockerfile @@ -197,11 +197,11 @@ ARG DEVICE_TREE_TARGET RUN cd /src/linux \ && grep -q "^dtb-\\\$(CONFIG_ARCH_LAYERSCAPE) += ${DEVICE_TREE_TARGET}.dtb$" \ - arch/arm64/boot/dts/freescale/Makefile \ - || echo "dtb-\$(CONFIG_ARCH_LAYERSCAPE) += ${DEVICE_TREE_TARGET}.dtb" \ - >> arch/arm64/boot/dts/freescale/Makefile \ + arch/arm64/boot/dts/freescale/Makefile \ + || echo "dtb-\$(CONFIG_ARCH_LAYERSCAPE) += ${DEVICE_TREE_TARGET}.dtb" \ + >> arch/arm64/boot/dts/freescale/Makefile \ && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" \ - "freescale/${DEVICE_TREE_TARGET}.dtb" + "freescale/${DEVICE_TREE_TARGET}.dtb" # Patch verdor's modules RUN mkdir -p /src/patches/ask @@ -279,6 +279,11 @@ RUN KERNEL_VER=$(ls /out/rootfs/lib/modules/) && \ depmod -b /out/rootfs $KERNEL_VER && \ cd /out && tar zcf rootfs.tar.gz rootfs +RUN mkdir -p /out/rootfs-cfg/etc/dpa && \ + cp -r "${ASK_DIR}/dpa_app/files/etc/"* /out/rootfs-cfg/etc/dpa/ && \ + cp "${ASK_DIR}/config/gateway-dk/cdx_cfg.xml" /out/rootfs-cfg/etc/dpa/ && \ + cp -r /src/fmc/etc /out/rootfs-cfg/etc + FROM scratch AS export ARG DEVICE_TREE_TARGET @@ -292,8 +297,5 @@ COPY --from=build \ /src/linux/arch/arm64/boot/dts/freescale/${DEVICE_TREE_TARGET}.dtb \ /kernel/ -# Grab the proprietary Mono Gateway XML configs -COPY --from=build \ - /src/ASK/config/gateway-dk/cdx_cfg.xml \ - /src/ASK/dpa_app/files/etc/cdx_pcd.xml \ - /xml/ +# Export the configs for Gateway Development Kit +COPY --from=build /out/rootfs-cfg/ /rootfs-cfg/ diff --git a/patches/ask/config/0001-gateway-dk-cdx-cfg-use-standard-offline-portids.patch b/patches/ask/config/0001-gateway-dk-cdx-cfg-use-standard-offline-portids.patch new file mode 100644 index 0000000..35bb9a4 --- /dev/null +++ b/patches/ask/config/0001-gateway-dk-cdx-cfg-use-standard-offline-portids.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: builder +Date: Sun, 10 May 2026 00:00:00 +0000 +Subject: [PATCH] gateway-dk: use standard CDX offline port IDs + +The CDX soft-parser logic treats logical port IDs >= 9 as offline +ports, and the bundled CDX configs consistently use portid 9 and 10 +for dpa-fman0-oh@2 and dpa-fman0-oh@3. + +Keep the Gateway DK OFFLINE port numbers unchanged, because number 1 +and 2 are what dpa_app maps to dpa-fman0-oh@2 and dpa-fman0-oh@3. +Only adjust the logical port IDs. +--- + config/gateway-dk/cdx_cfg.xml | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/config/gateway-dk/cdx_cfg.xml b/config/gateway-dk/cdx_cfg.xml +index 1111111..2222222 100644 +--- a/config/gateway-dk/cdx_cfg.xml ++++ b/config/gateway-dk/cdx_cfg.xml +@@ -11,8 +11,8 @@ + + + +- +- ++ ++ + + + +-- +2.43.0 From 603313f736674a6c8f5db6c5bbefff4789a25427d61aba820df0b880bca8a7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 10 May 2026 06:12:07 +0800 Subject: [PATCH 06/14] Added mirror support to avoid hitting remote constantly --- build.env | 7 ++ devtools/dep-pkg-mirror.yaml | 101 ++++++++++++++++++ devtools/push-dep-pkg-mirror.sh | 80 +++++++++++++++ docker/download-packages.Dockerfile | 153 ++++++++++++++++++++-------- makefile | 20 +++- scripts/fetch-artifact | 40 ++++++++ 6 files changed, 357 insertions(+), 44 deletions(-) create mode 100644 devtools/dep-pkg-mirror.yaml create mode 100755 devtools/push-dep-pkg-mirror.sh create mode 100755 scripts/fetch-artifact diff --git a/build.env b/build.env index ea7f3a0..a7446f7 100644 --- a/build.env +++ b/build.env @@ -57,3 +57,10 @@ APT_PROXY= # remote image repository prefix to push to # e.g. ghcr.io/monok8s IMAGE_REPOSITORY= + +# Mirror +# You can host your local mirror by running (but you'll need to download them first) +# kubectl apply -f devtools/dep-pkg-mirror.yaml +# devtools/push-dep-pkg-mirror.sh +# e.g. http://dep-pkg-mirror.default.svc.cluster.local/monok8s +DEP_PKG_MIRROR= diff --git a/devtools/dep-pkg-mirror.yaml b/devtools/dep-pkg-mirror.yaml new file mode 100644 index 0000000..9181ae5 --- /dev/null +++ b/devtools/dep-pkg-mirror.yaml @@ -0,0 +1,101 @@ +# Hosts a mirror for dep pkg +# kubectl apply -f dep-pkg-mirror.yaml -n [namespace] +# kubectl -n [namespace] cp ./packages \ deploy/monok8s-mirror:/usr/share/nginx/html/monok8s/ +# Fetch helper contract: +# DEP_PKG_MIRROR=https://mirror.example.com/monok8s +# mirror URL = ${DEP_PKG_MIRROR}/packages/${mirror_path} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: dep-pkg-mirror-data +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: dep-pkg-mirror-nginx +data: + default.conf: | + server { + listen 8080; + server_name _; + + root /usr/share/nginx/html; + + autoindex on; + autoindex_exact_size off; + autoindex_localtime on; + + location /monok8s/packages/ { + try_files $uri =404; + } + + location = /healthz { + access_log off; + return 200 "ok\n"; + } + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dep-pkg-mirror +spec: + replicas: 1 + selector: + matchLabels: + app: dep-pkg-mirror + template: + metadata: + labels: + app: dep-pkg-mirror + spec: + containers: + - name: nginx + image: nginx:1.27-alpine + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 8080 + readinessProbe: + httpGet: + path: /healthz + port: http + livenessProbe: + httpGet: + path: /healthz + port: http + volumeMounts: + - name: data + mountPath: /usr/share/nginx/html/monok8s/packages + subPath: packages + readOnly: false + - name: nginx-conf + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + readOnly: true + volumes: + - name: data + persistentVolumeClaim: + claimName: dep-pkg-mirror-data + - name: nginx-conf + configMap: + name: dep-pkg-mirror-nginx +--- +apiVersion: v1 +kind: Service +metadata: + name: dep-pkg-mirror +spec: + type: ClusterIP + selector: + app: dep-pkg-mirror + ports: + - name: http + port: 80 + targetPort: http diff --git a/devtools/push-dep-pkg-mirror.sh b/devtools/push-dep-pkg-mirror.sh new file mode 100755 index 0000000..bbe6302 --- /dev/null +++ b/devtools/push-dep-pkg-mirror.sh @@ -0,0 +1,80 @@ +#!/bin/sh +set -eu + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +NAMESPACE="${NAMESPACE:-default}" +PACKAGES_DIR="$(realpath "$SCRIPT_DIR/../packages/")" +APP_LABEL="${APP_LABEL:-app=dep-pkg-mirror}" +CONTAINER="${CONTAINER:-nginx}" +REMOTE_DIR="${REMOTE_DIR:-/usr/share/nginx/html/monok8s/packages}" + +if [ ! -d "$PACKAGES_DIR" ]; then + echo "error: package dir not found: $PACKAGES_DIR" >&2 + exit 1 +fi + +need_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "error: missing command: $1" >&2 + exit 1 + } +} + +need_cmd kubectl +need_cmd mktemp +need_cmd tar +need_cmd cp +need_cmd find + +pod="$( + kubectl -n "$NAMESPACE" get pod \ + -l "$APP_LABEL" \ + --field-selector=status.phase=Running \ + -o jsonpath='{.items[0].metadata.name}' +)" + +if [ -z "$pod" ]; then + echo "error: no running pod found with label: $APP_LABEL in namespace: $NAMESPACE" >&2 + exit 1 +fi + +echo "using pod: $pod" +echo "remote dir: $REMOTE_DIR" + +echo "checking remote dir is writable" +kubectl -n "$NAMESPACE" exec "$pod" -c "$CONTAINER" -- sh -c " + mkdir -p '$REMOTE_DIR' && + touch '$REMOTE_DIR/.write-test' && + rm -f '$REMOTE_DIR/.write-test' +" + +stage="$(mktemp -d)" +cleanup() { + rm -rf "$stage" +} +trap cleanup EXIT INT TERM + +mkdir -p "$stage/packages" + +echo "staging $PACKAGES_DIR/ as packages/" +tar \ + --exclude='.DS_Store' \ + --exclude='.stamp-*' \ + -C "$PACKAGES_DIR" \ + -cf - . | tar -C "$stage/packages" -xf - + +echo "copying staged packages into mirror pod" +kubectl -n "$NAMESPACE" cp \ + "$stage/packages/." \ + "$pod:$REMOTE_DIR" \ + -c "$CONTAINER" + +echo "done" +echo +echo "Mirror base URL:" +echo " DEP_PKG_MIRROR=http://dep-pkg-mirror.${NAMESPACE}.svc.cluster.local/monok8s" +echo +echo "Example:" +echo " packages/kubernetes/kubelet-v1.35.3" +echo " -> http://dep-pkg-mirror.${NAMESPACE}.svc.cluster.local/monok8s/packages/kubernetes/kubelet-v1.35.3" diff --git a/docker/download-packages.Dockerfile b/docker/download-packages.Dockerfile index 94919b1..2b5242c 100644 --- a/docker/download-packages.Dockerfile +++ b/docker/download-packages.Dockerfile @@ -1,13 +1,24 @@ +ARG DEP_PKG_MIRROR= +ARG DEP_PKG_OFFLINE=0 + FROM alpine:3.23.0 AS base +ARG DEP_PKG_MIRROR +ARG DEP_PKG_OFFLINE +ENV DEP_PKG_MIRROR="${DEP_PKG_MIRROR}" +ENV DEP_PKG_OFFLINE="${DEP_PKG_OFFLINE}" RUN apk add --no-cache curl ca-certificates +COPY scripts/fetch-artifact /usr/local/bin/fetch-artifact + # ---- kubelet ---- FROM base AS kubelet ARG KUBE_VERSION ARG ARCH WORKDIR /out/kubernetes -RUN curl -fL --retry 3 -o "kubelet-${KUBE_VERSION}" \ - "https://dl.k8s.io/${KUBE_VERSION}/bin/linux/${ARCH}/kubelet" && \ +RUN fetch-artifact \ + "packages/kubernetes/kubelet-${KUBE_VERSION}" \ + "kubelet-${KUBE_VERSION}" \ + "https://dl.k8s.io/${KUBE_VERSION}/bin/linux/${ARCH}/kubelet" && \ chmod +x "kubelet-${KUBE_VERSION}" # ---- kubeadm ---- @@ -15,8 +26,10 @@ FROM base AS kubeadm ARG KUBE_VERSION ARG ARCH WORKDIR /out/kubernetes -RUN curl -fL --retry 3 -o "kubeadm-${KUBE_VERSION}" \ - "https://dl.k8s.io/${KUBE_VERSION}/bin/linux/${ARCH}/kubeadm" && \ +RUN fetch-artifact \ + "packages/kubernetes/kubeadm-${KUBE_VERSION}" \ + "kubeadm-${KUBE_VERSION}" \ + "https://dl.k8s.io/${KUBE_VERSION}/bin/linux/${ARCH}/kubeadm" && \ chmod +x "kubeadm-${KUBE_VERSION}" # ---- kubectl ---- @@ -24,136 +37,190 @@ FROM base AS kubectl ARG KUBE_VERSION ARG ARCH WORKDIR /out/kubernetes -RUN curl -fL --retry 3 -o "kubectl-${KUBE_VERSION}" \ - "https://dl.k8s.io/${KUBE_VERSION}/bin/linux/${ARCH}/kubectl" && \ +RUN fetch-artifact \ + "packages/kubernetes/kubectl-${KUBE_VERSION}" \ + "kubectl-${KUBE_VERSION}" \ + "https://dl.k8s.io/${KUBE_VERSION}/bin/linux/${ARCH}/kubectl" && \ chmod +x "kubectl-${KUBE_VERSION}" # ---- busybox ---- FROM base AS busybox ARG BUSYBOX_VERSION +ARG BUSYBOX_TAR WORKDIR /out -RUN curl -fL --retry 3 -o "busybox-${BUSYBOX_VERSION}.tar.gz" \ - "https://github.com/mirror/busybox/archive/refs/tags/${BUSYBOX_VERSION}.tar.gz" +RUN fetch-artifact \ + "${BUSYBOX_TAR}" \ + "busybox-${BUSYBOX_VERSION}.tar.gz" \ + "https://github.com/mirror/busybox/archive/refs/tags/${BUSYBOX_VERSION}.tar.gz" # ---- e2fsprogs ---- FROM base AS e2fsprogs ARG E2FSPROGS_VERSION +ARG E2FSPROGS_TAR WORKDIR /out -RUN curl -fL --retry 3 -o "e2fsprogs-v${E2FSPROGS_VERSION}.tar.gz" \ - "https://github.com/tytso/e2fsprogs/archive/refs/tags/v${E2FSPROGS_VERSION}.tar.gz" +RUN fetch-artifact \ + "${E2FSPROGS_TAR}" \ + "e2fsprogs-v${E2FSPROGS_VERSION}.tar.gz" \ + "https://github.com/tytso/e2fsprogs/archive/refs/tags/v${E2FSPROGS_VERSION}.tar.gz" # ---- dpdk ---- FROM base AS dpdk ARG DPDK_VERSION +ARG DPDK_TAR WORKDIR /out/nxp/dpdk -RUN curl -fL --retry 3 -o "${DPDK_VERSION}.tar.gz" \ - "https://github.com/nxp-qoriq/dpdk/archive/refs/tags/${DPDK_VERSION}.tar.gz" +RUN fetch-artifact \ + "${DPDK_TAR}" \ + "${DPDK_VERSION}.tar.gz" \ + "https://github.com/nxp-qoriq/dpdk/archive/refs/tags/${DPDK_VERSION}.tar.gz" # ---- fmlib ---- FROM base AS fmlib ARG FMLIB_VERSION +ARG FMLIB_TAR WORKDIR /out/nxp/fmlib -RUN curl -fL --retry 3 -o "${FMLIB_VERSION}.tar.gz" \ - "https://github.com/nxp-qoriq/fmlib/archive/refs/tags/${FMLIB_VERSION}.tar.gz" +RUN fetch-artifact \ + "${FMLIB_TAR}" \ + "${FMLIB_VERSION}.tar.gz" \ + "https://github.com/nxp-qoriq/fmlib/archive/refs/tags/${FMLIB_VERSION}.tar.gz" # ---- fmc ---- FROM base AS fmc ARG FMC_VERSION +ARG FMC_TAR WORKDIR /out/nxp/fmc -RUN curl -fL --retry 3 -o "${FMC_VERSION}.tar.gz" \ - "https://github.com/nxp-qoriq/fmc/archive/refs/tags/${FMC_VERSION}.tar.gz" +RUN fetch-artifact \ + "${FMC_TAR}" \ + "${FMC_VERSION}.tar.gz" \ + "https://github.com/nxp-qoriq/fmc/archive/refs/tags/${FMC_VERSION}.tar.gz" # ---- vpp ---- FROM base AS vpp ARG VPP_VERSION +ARG VPP_TAR WORKDIR /out/nxp/vpp -RUN curl -fL --retry 3 -o "${VPP_VERSION}.tar.gz" \ - "https://github.com/nxp-qoriq/vpp/archive/refs/tags/${VPP_VERSION}.tar.gz" +RUN fetch-artifact \ + "${VPP_TAR}" \ + "${VPP_VERSION}.tar.gz" \ + "https://github.com/nxp-qoriq/vpp/archive/refs/tags/${VPP_VERSION}.tar.gz" # ---- MUSL CC ---- FROM base AS aarch64_musl_cc WORKDIR /out -RUN curl -fL --retry 3 -o "aarch64-linux-musl-cross.tgz" \ - "https://musl.cc/aarch64-linux-musl-cross.tgz" +RUN fetch-artifact \ + "packages/aarch64-linux-musl-cross.tgz" \ + "aarch64-linux-musl-cross.tgz" \ + "https://musl.cc/aarch64-linux-musl-cross.tgz" # ---- ASK ---- FROM base AS mono_ask ARG MONO_ASK_VERSION +ARG MONO_ASK_TAR WORKDIR /out/ask -RUN curl -fL --retry 3 -o "${MONO_ASK_VERSION}.tar.gz" \ - "https://github.com/we-are-mono/ASK/archive/refs/tags/${MONO_ASK_VERSION}.tar.gz" +RUN fetch-artifact \ + "${MONO_ASK_TAR}" \ + "${MONO_ASK_VERSION}.tar.gz" \ + "https://github.com/we-are-mono/ASK/archive/refs/tags/${MONO_ASK_VERSION}.tar.gz" # ---- libnfnetlink ---- FROM base AS libnfnetlink ARG LIBNFNETLINK_VERSION +ARG LIBNFNETLINK_TAR WORKDIR /out/ask/libnfnetlink -RUN curl -fL --retry 3 -o "${LIBNFNETLINK_VERSION}.tar.bz2" \ - "https://www.netfilter.org/projects/libnfnetlink/files/libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2" +RUN fetch-artifact \ + "${LIBNFNETLINK_TAR}" \ + "${LIBNFNETLINK_VERSION}.tar.bz2" \ + "https://www.netfilter.org/projects/libnfnetlink/files/libnfnetlink-${LIBNFNETLINK_VERSION}.tar.bz2" # ---- libnfct ---- FROM base AS libnfct ARG LIBNFCT_VERSION +ARG LIBNFCT_TAR WORKDIR /out/ask/libnfct -RUN curl -fL --retry 3 -o "${LIBNFCT_VERSION}.tar.xz" \ - "https://www.netfilter.org/projects/libnetfilter_conntrack/files/libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz" +RUN fetch-artifact \ + "${LIBNFCT_VERSION_TAR}" \ + "${LIBNFCT_VERSION}.tar.xz" \ + "https://www.netfilter.org/projects/libnetfilter_conntrack/files/libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz" # ---- libmnl ---- FROM base AS libmnl ARG LIBMNL_VERSION +ARG LIBMNL_TAR WORKDIR /out/ask/libmnl -RUN curl -fL --retry 3 -o "${LIBMNL_VERSION}.tar.bz2" \ - "https://www.netfilter.org/projects/libmnl/files/libmnl-${LIBMNL_VERSION}.tar.bz2" +RUN fetch-artifact \ + "${LIBMNL_TAR}" \ + "${LIBMNL_VERSION}.tar.bz2" \ + "https://www.netfilter.org/projects/libmnl/files/libmnl-${LIBMNL_VERSION}.tar.bz2" # ---- tclap ---- FROM base AS tclap ARG TCLAP_VERSION +ARG TCLAP_TAR WORKDIR /out/ask/tclap -RUN curl -fL --retry 3 -o "${TCLAP_VERSION}.tar.gz" \ - "https://sourceforge.net/projects/tclap/files/tclap-${TCLAP_VERSION}.tar.gz" +RUN fetch-artifact \ + "${TCLAP_TAR}" \ + "${TCLAP_VERSION}.tar.gz" \ + "https://sourceforge.net/projects/tclap/files/tclap-${TCLAP_VERSION}.tar.gz" # ---- libxml2 ---- FROM base AS libxml2 ARG LIBXML2_VERSION +ARG LIBXML2_TAR WORKDIR /out/ask/libxml2 -RUN curl -fL --retry 3 -o "${LIBXML2_VERSION}.tar.xz" \ - "https://download.gnome.org/sources/libxml2/2.11/libxml2-${LIBXML2_VERSION}.tar.xz" +RUN fetch-artifact \ + "${LIBXML2_TAR}" \ + "${LIBXML2_VERSION}.tar.xz" \ + "https://download.gnome.org/sources/libxml2/2.11/libxml2-${LIBXML2_VERSION}.tar.xz" # ---- libcli ---- FROM base AS libcli ARG LIBCLI_VERSION +ARG LIBCLI_TAR WORKDIR /out/ask/libcli -RUN curl -fL --retry 3 -o "${LIBCLI_VERSION}.tar.gz" \ - "https://github.com/dparrish/libcli/archive/refs/tags/V${LIBCLI_VERSION}.tar.gz" +RUN fetch-artifact \ + "${LIBCLI_TAR}" \ + "${LIBCLI_VERSION}.tar.gz" \ + "https://github.com/dparrish/libcli/archive/refs/tags/V${LIBCLI_VERSION}.tar.gz" # ---- libpcap ---- FROM base AS libpcap ARG LIBPCAP_VERSION +ARG LIBPCAP_TAR WORKDIR /out/ask/libpcap -RUN curl -fL --retry 3 -o "${LIBPCAP_VERSION}.tar.xz" \ - "https://www.tcpdump.org/release/libpcap-${LIBPCAP_VERSION}.tar.xz" +RUN fetch-artifact \ + "${LIBPCAP_TAR}" \ + "${LIBPCAP_VERSION}.tar.xz" \ + "https://www.tcpdump.org/release/libpcap-${LIBPCAP_VERSION}.tar.xz" # ---- alpine rootfs ---- FROM base AS alpine_rootfs ARG ALPINE_SERIES ARG ALPINE_ARCH -ARG ALPINE_VER +ARG ALPINE_TAR WORKDIR /out -RUN curl -fL --retry 3 -o "alpine-minirootfs-${ALPINE_VER}-${ALPINE_ARCH}.tar.gz" \ - "https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_SERIES}/releases/${ALPINE_ARCH}/alpine-minirootfs-${ALPINE_VER}-${ALPINE_ARCH}.tar.gz" +RUN fetch-artifact \ + "${ALPINE_TAR}" \ + "alpine-minirootfs-${ALPINE_VER}-${ALPINE_ARCH}.tar.gz" \ + "https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_SERIES}/releases/${ALPINE_ARCH}/alpine-minirootfs-${ALPINE_VER}-${ALPINE_ARCH}.tar.gz" # ---- nxp linux ---- FROM base AS nxp_linux ARG NXP_VERSION +ARG NXP_TAR WORKDIR /out/nxp/kernel -RUN curl -fL --retry 3 -o "${NXP_VERSION}.tar.gz" \ - "https://github.com/nxp-qoriq/linux/archive/refs/tags/${NXP_VERSION}.tar.gz" +RUN fetch-artifact \ + "${NXP_TAR}" \ + "${NXP_VERSION}.tar.gz" \ + "https://github.com/nxp-qoriq/linux/archive/refs/tags/${NXP_VERSION}.tar.gz" # ---- crio ---- FROM base AS crio ARG CRIO_VERSION +ARG CRIO_TAR WORKDIR /out -RUN curl -fL --retry 3 -o "${CRIO_VERSION}.tar.gz" \ - "https://storage.googleapis.com/cri-o/artifacts/${CRIO_VERSION}.tar.gz" +RUN fetch-artifact \ + "${CRIO_TAR}" \ + "${CRIO_VERSION}.tar.gz" \ + "https://storage.googleapis.com/cri-o/artifacts/${CRIO_VERSION}.tar.gz" # ---- final exported artifact set ---- FROM scratch diff --git a/makefile b/makefile index 8c7c48b..a3b7995 100644 --- a/makefile +++ b/makefile @@ -7,7 +7,7 @@ TAG ?= dev PACKAGES_DIR := packages OUT_DIR := out -E2FSPROGS_TAR := $(PACKAGES_DIR)/e2fsprogs-$(E2FSPROGS_VERSION).tar.gz +E2FSPROGS_TAR := $(PACKAGES_DIR)/e2fsprogs-v$(E2FSPROGS_VERSION).tar.gz BUSYBOX_TAR := $(PACKAGES_DIR)/busybox-$(BUSYBOX_VERSION).tar.gz ALPINE_TAR := $(PACKAGES_DIR)/alpine-minirootfs-$(ALPINE_VER)-$(ALPINE_ARCH).tar.gz NXP_TAR := $(PACKAGES_DIR)/nxp/kernel/$(NXP_VERSION).tar.gz @@ -127,6 +127,7 @@ $(OUT_DIR): $(DOWNLOAD_PACKAGES_STAMP): docker/download-packages.Dockerfile build.env makefile | $(PACKAGES_DIR) docker build \ -f docker/download-packages.Dockerfile \ + --build-arg DEP_PKG_MIRROR=$(DEP_PKG_MIRROR) \ --build-arg KUBE_VERSION=$(KUBE_VERSION) \ --build-arg ARCH=$(ARCH) \ --build-arg BUSYBOX_VERSION=$(BUSYBOX_VERSION) \ @@ -149,6 +150,23 @@ $(DOWNLOAD_PACKAGES_STAMP): docker/download-packages.Dockerfile build.env makefi --build-arg ALPINE_VER=$(ALPINE_VER) \ --build-arg NXP_VERSION=$(NXP_VERSION) \ --build-arg CRIO_VERSION=$(CRIO_VERSION) \ + --build-arg BUSYBOX_TAR=$(BUSYBOX_TAR) \ + --build-arg E2FSPROGS_TAR=$(E2FSPROGS_TAR) \ + --build-arg DPDK_TAR=$(DPDK_TAR) \ + --build-arg FMLIB_TAR=$(FMLIB_TAR) \ + --build-arg FMC_TAR=$(FMC_TAR) \ + --build-arg VPP_TAR=$(VPP_TAR) \ + --build-arg MONO_ASK_TAR=$(MONO_ASK_TAR) \ + --build-arg LIBNFNETLINK_TAR=$(LIBNFNETLINK_TAR) \ + --build-arg LIBMNL_TAR=$(LIBMNL_TAR) \ + --build-arg LIBNFCT_TAR=$(LIBNFCT_TAR) \ + --build-arg LIBCLI_TAR=$(LIBCLI_TAR) \ + --build-arg LIBXML2_TAR=$(LIBXML2_TAR) \ + --build-arg LIBPCAP_TAR=$(LIBPCAP_TAR) \ + --build-arg TCLAP_TAR=$(TCLAP_TAR) \ + --build-arg ALPINE_TAR=$(ALPINE_TAR) \ + --build-arg NXP_TAR=$(NXP_TAR) \ + --build-arg CRIO_TAR=$(CRIO_TAR) \ --output type=local,dest=./$(PACKAGES_DIR) . @touch $@ diff --git a/scripts/fetch-artifact b/scripts/fetch-artifact new file mode 100755 index 0000000..a712355 --- /dev/null +++ b/scripts/fetch-artifact @@ -0,0 +1,40 @@ +#!/bin/sh +set -eu + +# Fetch helper contract: +# DEP_PKG_MIRROR=https://mirror.example.com/monok8s +# mirror URL = ${DEP_PKG_MIRROR}/${mirror_path} + +if [ "$#" -ne 3 ]; then + echo "usage: fetch-artifact " >&2 + exit 2 +fi + +mirror_path="$1" +out="$2" +upstream_url="$3" + +mkdir -p "$(dirname "$out")" +rm -f "$out" + +if [ -n "${DEP_PKG_MIRROR:-}" ]; then + mirror_url="${DEP_PKG_MIRROR%/}/${mirror_path}" + echo "fetch-artifact: trying mirror: ${mirror_url}" >&2 + if curl -fL --retry 3 -o "$out" "$mirror_url"; then + exit 0 + fi + rm -f "$out" + + if [ "${DEP_PKG_OFFLINE:-0}" = "1" ]; then + echo "fetch-artifact: mirror miss and DEP_PKG_OFFLINE=1: ${mirror_url}" >&2 + exit 1 + fi +fi + +if [ "${DEP_PKG_OFFLINE:-0}" = "1" ]; then + echo "fetch-artifact: DEP_PKG_OFFLINE=1 and no usable mirror for ${mirror_path}" >&2 + exit 1 +fi + +echo "fetch-artifact: fetching upstream: ${upstream_url}" >&2 +curl -fL --retry 3 -o "$out" "$upstream_url" From 9ecb86582867b93f65a2ba3775f5c77b7feff495834584e662327a113259d01f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 10 May 2026 06:27:56 +0800 Subject: [PATCH 07/14] Typo --- docker/download-packages.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/download-packages.Dockerfile b/docker/download-packages.Dockerfile index 2b5242c..964e10b 100644 --- a/docker/download-packages.Dockerfile +++ b/docker/download-packages.Dockerfile @@ -137,7 +137,7 @@ ARG LIBNFCT_VERSION ARG LIBNFCT_TAR WORKDIR /out/ask/libnfct RUN fetch-artifact \ - "${LIBNFCT_VERSION_TAR}" \ + "${LIBNFCT_TAR}" \ "${LIBNFCT_VERSION}.tar.xz" \ "https://www.netfilter.org/projects/libnetfilter_conntrack/files/libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz" From 8bc97370322e49f03edd46b578a81c6846e88554246c295cc02ddb8c5c406841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 10 May 2026 06:48:54 +0800 Subject: [PATCH 08/14] Export missing bin, dpa_app to support env vars --- docker/ask.Dockerfile | 12 ++-- ...-allow-xml-config-path-env-overrides.patch | 72 +++++++++++++++++++ 2 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 patches/ask/dpa/0001-dpa-app-allow-xml-config-path-env-overrides.patch diff --git a/docker/ask.Dockerfile b/docker/ask.Dockerfile index 533c26c..4e42dd8 100644 --- a/docker/ask.Dockerfile +++ b/docker/ask.Dockerfile @@ -262,11 +262,11 @@ RUN mkdir -p /out/ASK/dist && \ cp "${ASK_DIR}/cdx/cdx.ko" /out/ASK/dist && \ cp "${ASK_DIR}/fci/fci.ko" /out/ASK/dist && \ cp "${ASK_DIR}/auto_bridge/auto_bridge.ko" /out/ASK/dist && \ - mkdir -p /out/ask/bin && \ - cp /src/fmc/source/fmc /out/ASK/bin && \ - cp "${ASK_DIR}/cmm/src/cmm" /out/ASK/bin && \ - cp "${ASK_DIR}/dpa_app/dpa_app" /out/ASK/bin && \ - aarch64-linux-musl-strip /out/ASK/bin/fmc /out/ASK/bin/cmm /out/ASK/bin/dpa_app || true + mkdir -p /out/ASK/bin && \ + cp /src/fmc/source/fmc /out/ASK/bin/ && \ + cp "${ASK_DIR}/cmm/src/cmm" /out/ASK/bin/ && \ + cp "${ASK_DIR}/dpa_app/dpa_app" /out/ASK/bin/ && \ + aarch64-linux-musl-strip /out/ASK/bin/fmc /out/ASK/bin/cmm /out/ASK/bin/dpa_app # in-tree Linux kernel modules RUN mkdir -p /out/rootfs && \ @@ -297,5 +297,7 @@ COPY --from=build \ /src/linux/arch/arm64/boot/dts/freescale/${DEVICE_TREE_TARGET}.dtb \ /kernel/ +COPY --from=build /out/ASK/bin/ /bin/ + # Export the configs for Gateway Development Kit COPY --from=build /out/rootfs-cfg/ /rootfs-cfg/ diff --git a/patches/ask/dpa/0001-dpa-app-allow-xml-config-path-env-overrides.patch b/patches/ask/dpa/0001-dpa-app-allow-xml-config-path-env-overrides.patch new file mode 100644 index 0000000..4ae1766 --- /dev/null +++ b/patches/ask/dpa/0001-dpa-app-allow-xml-config-path-env-overrides.patch @@ -0,0 +1,72 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: monok8s +Date: Sun, 10 May 2026 00:00:00 +0000 +Subject: [PATCH] dpa_app: allow XML config paths to be overridden by env + +Keep the vendor default XML paths, but allow deployments to override them +without patching the binary or placing board-specific XML files directly +under /etc. + +Supported environment variables: + + CDX_CFG_FILE + CDX_PCD_FILE + CDX_PDL_FILE + CDX_SP_FILE + +This is useful for monok8s/OpenRC integration where board-specific DPA +configuration can live under a managed config directory. +--- + dpa_app/dpa.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/dpa_app/dpa.c b/dpa_app/dpa.c +index 91ca1d4..960afcd 100644 +--- a/dpa_app/dpa.c ++++ b/dpa_app/dpa.c +@@ -91,6 +91,34 @@ char *pcd_file = DEFAULT_PCD_FILE; + char *pdl_file = DEFAULT_PDL_FILE; + char *sp_file = DEFAULT_SP_FILE; + ++static void dpa_load_env_paths(void) ++{ ++ char *v; ++ ++ v = getenv("CDX_CFG_FILE"); ++ if (v && *v) ++ cfg_file = v; ++ ++ v = getenv("CDX_PCD_FILE"); ++ if (v && *v) ++ pcd_file = v; ++ ++ v = getenv("CDX_PDL_FILE"); ++ if (v && *v) ++ pdl_file = v; ++ ++ v = getenv("CDX_SP_FILE"); ++ if (v && *v) ++ sp_file = v; ++ ++#ifdef DPA_C_DEBUG ++ printf("%s::cfg_file %s\n", __func__, cfg_file); ++ printf("%s::pcd_file %s\n", __func__, pcd_file); ++ printf("%s::pdl_file %s\n", __func__, pdl_file); ++ printf("%s::sp_file %s\n", __func__, sp_file); ++#endif ++} ++ + //fmc model from xml files + static struct fmc_model_t cmodel; + +@@ -752,6 +780,8 @@ int dpa_init(void) + char devname[64]; + int retval; + ++ dpa_load_env_paths(); ++ + //open cdx control device + sprintf(devname, "/dev/%s", CDX_CTRL_CDEVNAME); + cdx_dev_handle = open(devname, O_RDWR); +-- +2.39.5 From 9ccd41bc542748ecdfbd239af847b0e1ea4ad1f1225dab3e759987156129af92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 10 May 2026 22:25:46 +0800 Subject: [PATCH 09/14] Got dpa_app working --- alpine/install-packages.sh | 4 +- docker/ask.Dockerfile | 8 +- docs/vendor-resources.md | 68 ++++++ kernel-build/dts/mono-gateway-dk-sdk.dts | 31 +-- kernel-build/dts/mono-gateway-dk.dts | 4 +- ...-allow-xml-config-path-env-overrides.patch | 2 +- .../0002-cdx-harden-fman-port-lookup.patch | 152 +++++++++++++ ...free-of-userspace-dist-info-pointers.patch | 120 ++++++++++ ...stash-userspace-fman-nested-pointers.patch | 205 ++++++++++++++++++ 9 files changed, 571 insertions(+), 23 deletions(-) create mode 100644 patches/ask/dpa/0002-cdx-harden-fman-port-lookup.patch create mode 100644 patches/ask/dpa/0003-cdx-avoid-kfree-of-userspace-dist-info-pointers.patch create mode 100644 patches/ask/dpa/0004-cdx-stash-userspace-fman-nested-pointers.patch diff --git a/alpine/install-packages.sh b/alpine/install-packages.sh index d5679c3..d924634 100755 --- a/alpine/install-packages.sh +++ b/alpine/install-packages.sh @@ -9,9 +9,9 @@ apk add alpine-base \ # For diagnotics apk add \ - iproute2 iproute2-ss curl bind-tools procps strace tcpdump lsof jq binutils \ + iproute2 iproute2-ss curl bind-tools procps strace tcpdump lsof jq gdb binutils \ openssl conntrack-tools ethtool findmnt kmod coreutils util-linux zstd libcap-utils \ - iotop sysstat + iotop sysstat dtc echo '[ -x /bin/bash ] && exec /bin/bash -l' >> "/root/.profile" # Compat layer for kubelet for now. Will look into building it myself later. If needed diff --git a/docker/ask.Dockerfile b/docker/ask.Dockerfile index 4e42dd8..5302e61 100644 --- a/docker/ask.Dockerfile +++ b/docker/ask.Dockerfile @@ -248,7 +248,7 @@ RUN make -C "${ASK_DIR}/cmm" \ PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" && \ make -C "${ASK_DIR}/dpa_app" \ CC="aarch64-linux-musl-gcc -static" \ - CFLAGS="-DDPAA_DEBUG_ENABLE -DNCSW_LINUX \ + CFLAGS="-DDPAA_DEBUG_ENABLE -DLS1043 -DNCSW_LINUX -D__STDC_LIMIT_MACROS \ -I/src/fmc/source \ -I${ASK_DIR}/cdx \ -I/src/fmlib/include/fmd \ @@ -265,8 +265,8 @@ RUN mkdir -p /out/ASK/dist && \ mkdir -p /out/ASK/bin && \ cp /src/fmc/source/fmc /out/ASK/bin/ && \ cp "${ASK_DIR}/cmm/src/cmm" /out/ASK/bin/ && \ - cp "${ASK_DIR}/dpa_app/dpa_app" /out/ASK/bin/ && \ - aarch64-linux-musl-strip /out/ASK/bin/fmc /out/ASK/bin/cmm /out/ASK/bin/dpa_app + cp "${ASK_DIR}/dpa_app/dpa_app" /out/ASK/bin/ +# aarch64-linux-musl-strip /out/ASK/bin/fmc /out/ASK/bin/cmm /out/ASK/bin/dpa_app # in-tree Linux kernel modules RUN mkdir -p /out/rootfs && \ @@ -282,7 +282,7 @@ RUN KERNEL_VER=$(ls /out/rootfs/lib/modules/) && \ RUN mkdir -p /out/rootfs-cfg/etc/dpa && \ cp -r "${ASK_DIR}/dpa_app/files/etc/"* /out/rootfs-cfg/etc/dpa/ && \ cp "${ASK_DIR}/config/gateway-dk/cdx_cfg.xml" /out/rootfs-cfg/etc/dpa/ && \ - cp -r /src/fmc/etc /out/rootfs-cfg/etc + cp -r /src/fmc/etc/* /out/rootfs-cfg/etc FROM scratch AS export diff --git a/docs/vendor-resources.md b/docs/vendor-resources.md index 41d6ee1..01bda09 100644 --- a/docs/vendor-resources.md +++ b/docs/vendor-resources.md @@ -1,3 +1,6 @@ +## ASK +The most important one is vendor's ASK. Which provides all the required resources to build the device-specific kernel + ## Updating build.env You can find the latest package versions in here * [kernel](https://github.com/nxp-qoriq/linux/archive/refs/tags/) @@ -10,3 +13,68 @@ You can find the latest package versions in here https://github.com/we-are-mono/OpenWRT-ASK/tree/mono-25.12.0-rc3/target/linux/layerscape/files/arch/arm64/boot/dts/freescale * We need both `mono-gateway-dk-sdk.dts` and `mono-gateway-dk.dts` since the sdk one includes the non-sdk one. * The actual dts being used is the `mono-gateway-dk-sdk.dts` + +## Testing dpa_app +Run this on the gateway device +```bash +while true; do nc -l -p 1234 -e sh; done +``` + +Run this script on your dev machine +```bash +#!/bin/bash +FILES=" +bin/dpa_app +rootfs-cfg/etc/dpa/cdx_cfg.xml +rootfs-cfg/etc/dpa/cdx_pcd.xml +rootfs-cfg/etc/dpa/cdx_sp.xml +rootfs-cfg/etc/dpa/cdx_cfg_ls1046_rdb.xml +rootfs-cfg/etc/fmc/config/hxs_pdl_v3.xml +rootfs-cfg/etc/fmc/config/cfgdata.xsd +rootfs-cfg/etc/fmc/config/netpcd.xsd +" + +SIZE=$( + tar -C ./out/ASK -czf - $FILES | wc -c +) + +( + echo 'set -eu' + + echo 'rm -rf /var/dpa-test' + echo 'mkdir -p /var/dpa-test/bin' + echo 'mkdir -p /etc/dpa' + echo 'mkdir -p /etc/fmc/config' + + echo 'base64 -d > /tmp/dpa-test.tar.gz <<'"'"'EOF'"'"'' + tar -C ./out/ASK -czf - $FILES | pv -s "$SIZE" | base64 + echo 'EOF' + + echo 'tar -xzf /tmp/dpa-test.tar.gz -C /var/dpa-test' + + echo 'cp /var/dpa-test/bin/dpa_app /var/dpa_app' + echo 'cp /var/dpa-test/rootfs-cfg/etc/dpa/cdx_cfg.xml /etc/dpa/cdx_cfg.xml' + echo 'cp /var/dpa-test/rootfs-cfg/etc/dpa/cdx_pcd.xml /etc/dpa/cdx_pcd.xml' + echo 'cp /var/dpa-test/rootfs-cfg/etc/dpa/cdx_sp.xml /etc/dpa/cdx_sp.xml' + echo 'cp /var/dpa-test/rootfs-cfg/etc/fmc/config/hxs_pdl_v3.xml /etc/fmc/config/hxs_pdl_v3.xml' + echo 'cp /var/dpa-test/rootfs-cfg/etc/fmc/config/cfgdata.xsd /etc/fmc/config/cfgdata.xsd' + echo 'cp /var/dpa-test/rootfs-cfg/etc/fmc/config/netpcd.xsd /etc/fmc/config/netpcd.xsd' + + echo 'chmod +x /var/dpa_app' + + echo 'export CDX_CFG_FILE=/etc/dpa/cdx_cfg.xml' + echo 'export CDX_PCD_FILE=/etc/dpa/cdx_pcd.xml' + echo 'export CDX_SP_FILE=/etc/dpa/cdx_sp.xml' + echo 'export CDX_PDL_FILE=/etc/fmc/config/hxs_pdl_v3.xml' + + echo 'echo "CDX_CFG_FILE=$CDX_CFG_FILE"' + echo 'echo "CDX_PCD_FILE=$CDX_PCD_FILE"' + echo 'echo "CDX_SP_FILE=$CDX_SP_FILE"' + echo 'echo "CDX_PDL_FILE=$CDX_PDL_FILE"' + + echo 'ls -l /var/dpa_app /etc/dpa /etc/fmc/config' + echo 'echo Running /var/dpa_app' + echo '/var/dpa_app' + echo 'echo exit=$?' +) | nc 10.0.0.10 1234 +``` diff --git a/kernel-build/dts/mono-gateway-dk-sdk.dts b/kernel-build/dts/mono-gateway-dk-sdk.dts index 8ea2c5b..0c1ac11 100644 --- a/kernel-build/dts/mono-gateway-dk-sdk.dts +++ b/kernel-build/dts/mono-gateway-dk-sdk.dts @@ -263,22 +263,23 @@ * ethernet@8 = enet6 = MAC9 (10G) */ - ethernet@8 { - compatible = "fsl,dpa-ethernet-init"; - fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; - fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>; - fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>; - }; + ethernet@8 { + compatible = "fsl,dpa-ethernet"; + /delete-property/ fsl,bman-buffer-pools; + /delete-property/ fsl,qman-frame-queues-rx; + /delete-property/ fsl,qman-frame-queues-tx; + dma-coherent; + }; /* Add MAC10 - not in qoriq-dpaa-eth.dtsi */ - ethernet@9 { - compatible = "fsl,dpa-ethernet-init"; - fsl,fman-mac = <&enet7>; - fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>; - fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>; - fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>; - dma-coherent; - }; + ethernet@9 { + compatible = "fsl,dpa-ethernet"; + fsl,fman-mac = <&enet7>; + /delete-property/ fsl,bman-buffer-pools; + /delete-property/ fsl,qman-frame-queues-rx; + /delete-property/ fsl,qman-frame-queues-tx; + dma-coherent; + }; }; &fman0 { @@ -336,12 +337,14 @@ }; ethernet@f0000 { + status = "okay"; /delete-property/ managed; fixed-link = <0 1 10000 0 0>; phy-connection-type = "xgmii"; }; ethernet@f2000 { + status = "okay"; /delete-property/ managed; fixed-link = <0 1 10000 0 0>; phy-connection-type = "xgmii"; diff --git a/kernel-build/dts/mono-gateway-dk.dts b/kernel-build/dts/mono-gateway-dk.dts index d2d7aea..df7c1ae 100644 --- a/kernel-build/dts/mono-gateway-dk.dts +++ b/kernel-build/dts/mono-gateway-dk.dts @@ -500,14 +500,14 @@ status = "okay"; }; - fm1_mac9: ethernet@f0000 { /* 10GEC1 */ + fm0_mac9: ethernet@f0000 { /* 10GEC1 */ sfp = <&sfp_xfi0>; phy-connection-type = "10gbase-r"; managed = "in-band-status"; pcs-handle-names = "xfi"; /* Match enet7 for consistency */ }; - fm1_mac10: ethernet@f2000 { /* 10GEC2 */ + fm0_mac10: ethernet@f2000 { /* 10GEC2 */ sfp = <&sfp_xfi1>; phy-connection-type = "10gbase-r"; managed = "in-band-status"; diff --git a/patches/ask/dpa/0001-dpa-app-allow-xml-config-path-env-overrides.patch b/patches/ask/dpa/0001-dpa-app-allow-xml-config-path-env-overrides.patch index 4ae1766..786f022 100644 --- a/patches/ask/dpa/0001-dpa-app-allow-xml-config-path-env-overrides.patch +++ b/patches/ask/dpa/0001-dpa-app-allow-xml-config-path-env-overrides.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: monok8s Date: Sun, 10 May 2026 00:00:00 +0000 -Subject: [PATCH] dpa_app: allow XML config paths to be overridden by env +Subject: [PATCH 1/4] dpa_app: allow XML config paths to be overridden by env Keep the vendor default XML paths, but allow deployments to override them without patching the binary or placing board-specific XML files directly diff --git a/patches/ask/dpa/0002-cdx-harden-fman-port-lookup.patch b/patches/ask/dpa/0002-cdx-harden-fman-port-lookup.patch new file mode 100644 index 0000000..9cede6a --- /dev/null +++ b/patches/ask/dpa/0002-cdx-harden-fman-port-lookup.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: monok8s +Date: Sun, 10 May 2026 00:00:00 +0000 +Subject: [PATCH 2/4] cdx: harden FMAN port lookup + +The DPA userspace loader passes FMC-derived port metadata into the CDX +ioctl. If an Ethernet netdev has a partially initialized DPAA private +structure, find_osdev_by_fman_params() can dereference a missing mac_dev +or FM wrapper pointer while trying to match the FMC port. + +Add lookup diagnostics and hard NULL guards so a mismatched board +model returns -ENODEV instead of oopsing the kernel. +--- + cdx/devman.c | 85 +++++++++++++++++++++++++++++++++++++-------------- + cdx/dpa_cfg.c | 18 ++++++++--- + 2 files changed, 76 insertions(+), 27 deletions(-) + +diff -urN a/cdx/devman.c b/cdx/devman.c +--- a/cdx/devman.c 2026-05-10 00:32:28.745375897 +0000 ++++ b/cdx/devman.c 2026-05-10 00:32:29.834300280 +0000 +@@ -396,39 +396,74 @@ + uint32_t speed) + { + struct net_device *device; +- struct dpa_priv_s *priv; +- struct mac_device *macdev; ++ ++ DPA_INFO("%s::lookup fm %u port %u speed %uG\n", ++ __func__, fm_idx, port_idx, speed); + + device = first_net_device(&init_net); +- while(1) { +- if (!device) +- break; +- if (device->type == ARPHRD_ETHER) { +- t_LnxWrpFmDev *p_LnxWrpFmDev; +- priv = netdev_priv(device); +- macdev = priv->mac_dev; +- if (macdev) { +- p_LnxWrpFmDev = (t_LnxWrpFmDev*)macdev->fm; +- if (speed == 10) { +- //10 gig interfaces upports only SUPPORTED_10000baseT_Full +- /*DGW board has 2 fixed-link interfaces +- 1 - (eth2)(xDSL)1G Fixed link interface linked to rgmii-txid +- 2 - eth5(G.fast)- 1G Fixed link interface linked to sgmii and +- connected to 10G link of the board. +- sgmii - considered as 1000baseT_Full and this has cell_index = 0*/ +- +- if ( (!macdev->fixed_link) && (macdev->if_support != SUPPORTED_10000baseT_Full) ) +- goto next_device; +- } +- if ((fm_idx == p_LnxWrpFmDev->id) && +- (port_idx == macdev->cell_index)) +- return device; +- } ++ while (device) { ++ struct dpa_priv_s *priv; ++ struct mac_device *macdev; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ ++ if (device->type != ARPHRD_ETHER) ++ goto next_device; ++ ++ priv = netdev_priv(device); ++ if (!priv) { ++ DPA_INFO("%s::skip %s: null private data\n", ++ __func__, device->name); ++ goto next_device; ++ } ++ ++ macdev = priv->mac_dev; ++ if (!macdev) { ++ DPA_INFO("%s::skip %s: null mac_dev\n", ++ __func__, device->name); ++ goto next_device; ++ } ++ ++ if (!macdev->fm) { ++ DPA_INFO("%s::skip %s: null mac_dev->fm cell_index %u max_speed %u fixed_link %u if_support 0x%x\n", ++ __func__, device->name, macdev->cell_index, ++ macdev->max_speed, macdev->fixed_link, ++ macdev->if_support); ++ goto next_device; + } ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *)macdev->fm; ++ DPA_INFO("%s::candidate %s fm %u cell_index %u max_speed %u fixed_link %u if_support 0x%x\n", ++ __func__, device->name, p_LnxWrpFmDev->id, ++ macdev->cell_index, macdev->max_speed, ++ macdev->fixed_link, macdev->if_support); ++ ++ if (speed == 10) { ++ //10 gig interfaces upports only SUPPORTED_10000baseT_Full ++ /*DGW board has 2 fixed-link interfaces ++ 1 - (eth2)(xDSL)1G Fixed link interface linked to rgmii-txid ++ 2 - eth5(G.fast)- 1G Fixed link interface linked to sgmii and ++ connected to 10G link of the board. ++ sgmii - considered as 1000baseT_Full and this has cell_index = 0*/ ++ ++ if ((!macdev->fixed_link) && ++ (macdev->if_support != SUPPORTED_10000baseT_Full)) ++ goto next_device; ++ } ++ ++ if ((fm_idx == p_LnxWrpFmDev->id) && ++ (port_idx == macdev->cell_index)) { ++ DPA_INFO("%s::matched %s for fm %u port %u speed %uG\n", ++ __func__, device->name, fm_idx, port_idx, speed); ++ return device; ++ } ++ + next_device: + device = next_net_device(device); + } +- return device; ++ ++ DPA_ERROR("%s::no OS device found for fm %u port %u speed %uG\n", ++ __func__, fm_idx, port_idx, speed); ++ return NULL; + } + + +diff -urN a/cdx/dpa_cfg.c b/cdx/dpa_cfg.c +--- a/cdx/dpa_cfg.c 2026-05-10 00:32:28.757992164 +0000 ++++ b/cdx/dpa_cfg.c 2026-05-10 00:32:51.954850425 +0000 +@@ -301,15 +301,21 @@ + struct net_device *dev; + + if (port_info->type) { ++ DPA_INFO("%s::mapping user port %s fm %u index %u portid %u type %uG\n", ++ __func__, port_info->name, port_info->fm_index, ++ port_info->index, port_info->portid, port_info->type); + dev = find_osdev_by_fman_params(port_info->fm_index, + port_info->index, port_info->type); + if (!dev) { +- DPA_ERROR("%s::could not map port %s\n", +- __func__, port_info->name); +- return -EIO; +- } else { +- strcpy(port_info->name, dev->name); ++ DPA_ERROR("%s::could not map port %s fm %u index %u portid %u type %uG\n", ++ __func__, port_info->name, ++ port_info->fm_index, port_info->index, ++ port_info->portid, port_info->type); ++ return -ENODEV; + } ++ DPA_INFO("%s::mapped user port %s to netdev %s\n", ++ __func__, port_info->name, dev->name); ++ strscpy(port_info->name, dev->name, sizeof(port_info->name)); + } + #ifdef DPA_CFG_DEBUG + DPA_INFO("%s::port %s, fmindex %d, port index %d, port id %d\n", diff --git a/patches/ask/dpa/0003-cdx-avoid-kfree-of-userspace-dist-info-pointers.patch b/patches/ask/dpa/0003-cdx-avoid-kfree-of-userspace-dist-info-pointers.patch new file mode 100644 index 0000000..c6b0f5d --- /dev/null +++ b/patches/ask/dpa/0003-cdx-avoid-kfree-of-userspace-dist-info-pointers.patch @@ -0,0 +1,120 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: monok8s +Date: Sun, 10 May 2026 00:00:00 +0000 +Subject: [PATCH 3/4] cdx: avoid kfree of userspace dist_info pointers + +get_port_info() copies an array of cdx_port_info from userspace. At that +point each cdx_port_info.dist_info field is still a userspace pointer. +However release_cfg_info() treats any non-NULL dist_info as a kernel +allocation and kfree()s it on error paths. + +If a later step fails before get_dist_info() has replaced every dist_info +with a kernel allocation, release_cfg_info() can kfree a raw userspace +pointer and oops in kfree()/virt_to_folio(). + +Stash the userspace dist_info pointers in a temporary array, clear the +kernel-side cdx_port_info.dist_info fields immediately after copy_from_user(), +and pass the saved userspace pointer explicitly to get_dist_info(). This +keeps release_cfg_info() safe on partial-initialization failures. +--- + cdx/dpa_cfg.c | 47 +++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 37 insertions(+), 10 deletions(-) + +diff -urN a/cdx/dpa_cfg.c b/cdx/dpa_cfg.c +--- a/cdx/dpa_cfg.c 2026-05-10 00:46:34.295813594 +0000 ++++ b/cdx/dpa_cfg.c 2026-05-10 00:46:35.558487337 +0000 +@@ -169,11 +169,10 @@ + } + + //allocate and copy distribution info from uspace +-static int get_dist_info(struct cdx_port_info *port_info) ++static int get_dist_info(struct cdx_port_info *port_info, void *uspace_info) + { + uint32_t mem_size; + struct cdx_dist_info *dist_info; +- void *uspace_info; + + #ifdef DPA_CFG_DEBUG + DPA_INFO("%s::port %s dist %d\n", __func__, +@@ -187,7 +186,6 @@ + return -ENOMEM; + } + memset(dist_info, 0, mem_size); +- uspace_info = port_info->dist_info; + port_info->dist_info = dist_info; + if (copy_from_user(dist_info, uspace_info, + mem_size)) { +@@ -273,6 +271,7 @@ + { + struct cdx_port_info *port_info; + void *uspace_info; ++ void **uspace_dist_info; + uint32_t mem_size; + uint32_t ii; + +@@ -289,13 +288,40 @@ + return -ENOMEM; + } + memset(port_info, 0, mem_size); ++ ++ uspace_dist_info = kcalloc(finfo->max_ports, sizeof(*uspace_dist_info), ++ GFP_KERNEL); ++ if (!uspace_dist_info) { ++ DPA_ERROR("%s::memalloc for uspace_dist_info failed\n", ++ __func__); ++ kfree(port_info); ++ return -ENOMEM; ++ } ++ + uspace_info = finfo->portinfo; + finfo->portinfo = port_info; + if (copy_from_user(port_info, uspace_info, mem_size)) { + DPA_ERROR("%s::Read port_info failed\n", + __func__); ++ finfo->portinfo = NULL; ++ kfree(uspace_dist_info); ++ kfree(port_info); + return -EIO; + } ++ ++ /* ++ * port_info has just been copied from userspace, so each dist_info ++ * member is still a userspace pointer. release_cfg_info() kfree()s ++ * non-NULL dist_info members, therefore keeping those raw userspace ++ * pointers in the kernel copy turns any later error path into an ++ * invalid kfree(). Stash the userspace pointers separately and clear ++ * the struct fields until get_dist_info() replaces them with real ++ * kernel allocations. ++ */ ++ for (ii = 0; ii < finfo->max_ports; ii++) { ++ uspace_dist_info[ii] = port_info[ii].dist_info; ++ port_info[ii].dist_info = NULL; ++ } + //put the linux name for the port + for (ii = 0; ii < finfo->max_ports; ii++) { + struct net_device *dev; +@@ -311,6 +337,7 @@ + __func__, port_info->name, + port_info->fm_index, port_info->index, + port_info->portid, port_info->type); ++ kfree(uspace_dist_info); + return -ENODEV; + } + DPA_INFO("%s::mapped user port %s to netdev %s\n", +@@ -330,11 +357,14 @@ + for (ii = 0; ii < finfo->max_ports; ii++) { + int retval; + //get dist info for this port +- retval = get_dist_info(port_info); +- if (retval) ++ retval = get_dist_info(port_info, uspace_dist_info[ii]); ++ if (retval) { ++ kfree(uspace_dist_info); + return retval; ++ } + port_info++; + } ++ kfree(uspace_dist_info); + return 0; + } + diff --git a/patches/ask/dpa/0004-cdx-stash-userspace-fman-nested-pointers.patch b/patches/ask/dpa/0004-cdx-stash-userspace-fman-nested-pointers.patch new file mode 100644 index 0000000..2344959 --- /dev/null +++ b/patches/ask/dpa/0004-cdx-stash-userspace-fman-nested-pointers.patch @@ -0,0 +1,205 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: monok8s +Date: Sun, 10 May 2026 00:00:00 +0000 +Subject: [PATCH 4/4] cdx: stash userspace fman nested pointers before cleanup + +cdx_ioc_set_dpa_params() copies struct cdx_fman_info from userspace. +The nested portinfo and tbl_info members are userspace pointers at that +point, but release_cfg_info() treats non-NULL nested pointers as +kernel-owned allocations. + +If setup fails before get_port_info() or get_cctbl_info() replaces those +members with kernel allocations, the error path can kfree a userspace +address and panic in kfree()/virt_to_folio(). + +Stash the userspace pointers in temporary arrays, clear the nested +members in fman_info immediately, and pass the stashed pointers into the +copy helpers explicitly. Also route early setup failures through the same +cleanup path so partial state is released consistently. +--- +diff --git a/cdx/dpa_cfg.c b/cdx/dpa_cfg.c +index c678d5d..55b910d 100644 +--- a/cdx/dpa_cfg.c ++++ b/cdx/dpa_cfg.c +@@ -267,10 +267,9 @@ static void *get_dist_info_by_fman_params(struct cdx_fman_info *finfo, uint32_t + #endif //CDX_RTP_RELAY + + //allocate and copy port releated info from uspace +-static int get_port_info(struct cdx_fman_info *finfo) ++static int get_port_info(struct cdx_fman_info *finfo, void *uspace_info) + { + struct cdx_port_info *port_info; +- void *uspace_info; + void **uspace_dist_info; + uint32_t mem_size; + uint32_t ii; +@@ -298,7 +297,6 @@ static int get_port_info(struct cdx_fman_info *finfo) + return -ENOMEM; + } + +- uspace_info = finfo->portinfo; + finfo->portinfo = port_info; + if (copy_from_user(port_info, uspace_info, mem_size)) { + DPA_ERROR("%s::Read port_info failed\n", +@@ -355,7 +353,7 @@ static int get_port_info(struct cdx_fman_info *finfo) + } + port_info = finfo->portinfo; + for (ii = 0; ii < finfo->max_ports; ii++) { +- int retval; ++ int retval = 0; + //get dist info for this port + retval = get_dist_info(port_info, uspace_dist_info[ii]); + if (retval) { +@@ -369,11 +367,10 @@ static int get_port_info(struct cdx_fman_info *finfo) + } + + //allocate and copy cc table infor from uspace +-static int get_cctbl_info(struct cdx_fman_info *finfo) ++static int get_cctbl_info(struct cdx_fman_info *finfo, void *uspace_info) + { + struct table_info *tbl_info; + uint32_t mem_size; +- void *uspace_info; + + //allocate table information area + mem_size = (sizeof(struct table_info) * finfo->num_tables); +@@ -384,7 +381,6 @@ static int get_cctbl_info(struct cdx_fman_info *finfo) + return -ENOMEM; + } + memset(tbl_info, 0, mem_size); +- uspace_info = finfo->tbl_info; + finfo->tbl_info = tbl_info; + //copy table related info from user space + if (copy_from_user(tbl_info, (void *)uspace_info, mem_size)) { +@@ -625,9 +621,11 @@ int cdx_ioc_set_dpa_params(unsigned long args) + { + struct cdx_ctrl_set_dpa_params params; + struct cdx_fman_info *finfo; ++ void **uspace_port_info = NULL; ++ void **uspace_tbl_info = NULL; + uint32_t ii; + uint32_t mem_size; +- int retval; ++ int retval = 0; + + if (copy_from_user(¶ms, (void *)args, + sizeof(struct cdx_ctrl_set_dpa_params))) { +@@ -655,6 +653,35 @@ int cdx_ioc_set_dpa_params(unsigned long args) + retval = -EIO; + goto err_ret; + } ++ uspace_port_info = kcalloc(num_fmans, sizeof(*uspace_port_info), ++ GFP_KERNEL); ++ uspace_tbl_info = kcalloc(num_fmans, sizeof(*uspace_tbl_info), ++ GFP_KERNEL); ++ if (!uspace_port_info || !uspace_tbl_info) { ++ DPA_ERROR("%s::unable to allocate user pointer stash\n", ++ __func__); ++ for (ii = 0; ii < num_fmans; ii++) { ++ fman_info[ii].portinfo = NULL; ++ fman_info[ii].tbl_info = NULL; ++ } ++ retval = -ENOMEM; ++ goto err_ret; ++ } ++ ++ /* ++ * fman_info is copied from userspace. Its nested portinfo and ++ * tbl_info members are userspace pointers until get_port_info() and ++ * get_cctbl_info() replace them with kernel allocations. Never leave ++ * raw userspace pointers in fman_info, because release_cfg_info() owns ++ * and frees non-NULL nested pointers on error paths. ++ */ ++ for (ii = 0; ii < num_fmans; ii++) { ++ uspace_port_info[ii] = fman_info[ii].portinfo; ++ uspace_tbl_info[ii] = fman_info[ii].tbl_info; ++ fman_info[ii].portinfo = NULL; ++ fman_info[ii].tbl_info = NULL; ++ } ++ + if (copy_from_user(&ipr_info, (void *)params.ipr_info, + sizeof(struct cdx_ipr_info))) { + DPA_ERROR("%s::Read iprv_info failed\n", +@@ -665,22 +688,26 @@ int cdx_ioc_set_dpa_params(unsigned long args) + //init the fman handles + finfo = fman_info; + for (ii = 0; ii < num_fmans; ii++) { +- if (cdxdrv_get_fman_handles(finfo)) +- return -1; ++ if (cdxdrv_get_fman_handles(finfo)) { ++ retval = -EIO; ++ goto err_ret; ++ } + finfo++; + } + finfo = fman_info; + //init interface stats module +- if (cdxdrv_init_stats(finfo->muram_handle)) +- return -1; ++ if (cdxdrv_init_stats(finfo->muram_handle)) { ++ retval = -EIO; ++ goto err_ret; ++ } + + for (ii = 0; ii < num_fmans; ii++) { + //get port info +- retval = get_port_info(finfo); ++ retval = get_port_info(finfo, uspace_port_info[ii]); + if (retval) + goto err_ret; + //get cc table info +- retval = get_cctbl_info(finfo); ++ retval = get_cctbl_info(finfo, uspace_tbl_info[ii]); + if (retval) + goto err_ret; + finfo++; +@@ -727,29 +754,43 @@ int cdx_ioc_set_dpa_params(unsigned long args) + finfo++; + } + +- if (cdx_create_port_fqs()) +- return -1; ++ if (cdx_create_port_fqs()) { ++ retval = -EIO; ++ goto err_ret; ++ } + //create cp rate limit policier profiles + if (cdxdrv_create_missaction_policer_profiles(fman_info)) { ++ retval = -EIO; + goto err_ret; + } + #ifdef ENABLE_INGRESS_QOS + if (cdxdrv_create_ingress_qos_policer_profiles(fman_info)) { ++ retval = -EIO; + goto err_ret; + } + #endif + #ifdef ENABLE_EGRESS_QOS +- if(ceetm_init_cq_plcr()) ++ if(ceetm_init_cq_plcr()) { ++ retval = -EIO; + goto err_ret; ++ } + #endif + //init the fman and its ports + for (ii = 0; ii < num_fmans; ii++) { +- if (cdxdrv_set_miss_action(ii)) ++ if (cdxdrv_set_miss_action(ii)) { ++ retval = -EIO; + goto err_ret; ++ } + } + display_dpa_cfg(); ++ kfree(uspace_port_info); ++ kfree(uspace_tbl_info); + return 0; + err_ret: ++ DPA_ERROR("%s::error path retval %d, releasing partial DPA cfg\n", ++ __func__, retval); ++ kfree(uspace_port_info); ++ kfree(uspace_tbl_info); + release_cfg_info(); + return retval; + } +-- +2.39.5 From e0bb9d72a41555c5448c48a91bb32bc89bee66032d77a6af7528e82f66ddcf4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Sun, 10 May 2026 23:20:59 +0800 Subject: [PATCH 10/14] Added ASK's cmm config --- docker/ask.Dockerfile | 5 ++++- docs/vendor-resources.md | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/docker/ask.Dockerfile b/docker/ask.Dockerfile index 5302e61..0372f4a 100644 --- a/docker/ask.Dockerfile +++ b/docker/ask.Dockerfile @@ -282,7 +282,10 @@ RUN KERNEL_VER=$(ls /out/rootfs/lib/modules/) && \ RUN mkdir -p /out/rootfs-cfg/etc/dpa && \ cp -r "${ASK_DIR}/dpa_app/files/etc/"* /out/rootfs-cfg/etc/dpa/ && \ cp "${ASK_DIR}/config/gateway-dk/cdx_cfg.xml" /out/rootfs-cfg/etc/dpa/ && \ - cp -r /src/fmc/etc/* /out/rootfs-cfg/etc + cp -r /src/fmc/etc/* /out/rootfs-cfg/etc && \ + mkdir -p /out/rootfs-cfg/etc/cmm && \ + cp "${ASK_DIR}/config/fastforward" /out/rootfs-cfg/etc/cmm/ + FROM scratch AS export diff --git a/docs/vendor-resources.md b/docs/vendor-resources.md index 01bda09..7f67794 100644 --- a/docs/vendor-resources.md +++ b/docs/vendor-resources.md @@ -78,3 +78,47 @@ SIZE=$( echo 'echo exit=$?' ) | nc 10.0.0.10 1234 ``` + +## Testing cmm +You'll need to run dpa_app first before running this + +```base +#!/bin/bash +set -eu + +FILES=" +bin/cmm +rootfs-cfg/etc/cmm/fastforward +" + +SIZE=$( + tar -C ./out/ASK -czf - $FILES | wc -c +) + +( + echo 'set -eux' + + echo 'rm -rf /var/cmm-test' + echo 'mkdir -p /var/cmm-test' + echo 'mkdir -p /var/ask/bin' + echo 'mkdir -p /var/ask/etc/cmm' + + echo 'base64 -d > /tmp/cmm-test.tar.gz <<'"'"'EOF'"'"'' + tar -C ./out/ASK -czf - $FILES | pv -s "$SIZE" | base64 + echo 'EOF' + + echo 'tar -xzf /tmp/cmm-test.tar.gz -C /var/cmm-test' + + echo 'install -m 0755 /var/cmm-test/bin/cmm /var/ask/bin/cmm' + echo 'install -m 0644 /var/cmm-test/rootfs-cfg/etc/cmm/fastforward /var/ask/etc/cmm/fastforward' + + echo 'ls -l /var/ask/bin/cmm /var/ask/etc/cmm/fastforward /dev/cdx_ctrl' + echo 'ldd /var/ask/bin/cmm || true' + + echo 'test -e /sys/class/vwd/vwd0/vwd_fast_path_enable && echo 1 > /sys/class/vwd/vwd0/vwd_fast_path_enable || true' + + echo 'echo Running cmm' + echo '/var/ask/bin/cmm -f /var/ask/etc/cmm/fastforward -n 131072' + echo 'echo exit=$?' +) | nc 10.0.0.10 1234 +``` From dca01e4abffac9f68e46de5274d0617ff0cc8ad8e58506767f432c23ed072df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Mon, 11 May 2026 02:13:10 +0800 Subject: [PATCH 11/14] Added cmm image --- ask/cmm/cmm.conf | 26 +++++++ ask/cmm/entrypoint.sh | 38 ++++++++++ docker/ask.Dockerfile | 2 +- docker/cmm.Dockerfile | 15 ++++ docs/vendor-resources.md | 6 +- makefile | 14 +++- .../cmm/0001-cmm-add-foreground-mode.patch | 75 +++++++++++++++++++ .../0002-cmm-support-stdout-log-target.patch | 36 +++++++++ 8 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 ask/cmm/cmm.conf create mode 100644 ask/cmm/entrypoint.sh create mode 100644 docker/cmm.Dockerfile create mode 100644 patches/ask/cmm/0001-cmm-add-foreground-mode.patch create mode 100644 patches/ask/cmm/0002-cmm-support-stdout-log-target.patch diff --git a/ask/cmm/cmm.conf b/ask/cmm/cmm.conf new file mode 100644 index 0000000..5951418 --- /dev/null +++ b/ask/cmm/cmm.conf @@ -0,0 +1,26 @@ +# CMM Fast Forward configuration +# This file specifies traffic that should NOT be offloaded to the fast path + +# Don't Fast Forward FTP traffic (needs ALG) +config fastforward ftp + option proto tcp + option port 21 + +# Don't Fast Forward SIP (needs ALG) +config fastforward sip + option proto udp + option port 5060 + +# Don't Fast Forward PPTP control +config fastforward pptp + option proto tcp + option port 1723 + +# Optional logging +# NOTE: "stdout" only supported in our own patched version +config logging + option file stdout + option command 0 + option error 1 + option warning 1 + option info 1 diff --git a/ask/cmm/entrypoint.sh b/ask/cmm/entrypoint.sh new file mode 100644 index 0000000..c8c91ec --- /dev/null +++ b/ask/cmm/entrypoint.sh @@ -0,0 +1,38 @@ +#!/bin/sh +set -eu + +CMM_CONFIG="${CMM_CONFIG:-/etc/cmm/cmm.conf}" + +# Vendor default from cmm.service: (131072 = 128 * 1024) max active conntrack/offload entries +CMM_MAX_CONNECTIONS="${CMM_MAX_CONNECTIONS:-131072}" + +mkdir -p /run/ask /var/log + +echo "[ask] loading auto_bridge" +modprobe auto_bridge || true + +echo "[ask] loading cdx" +modprobe cdx + +echo "[ask] waiting for /dev/cdx_ctrl" +for i in $(seq 1 40); do + if [ -e /dev/cdx_ctrl ]; then + break + fi + sleep 0.25 +done +test -e /dev/cdx_ctrl + +if [ ! -e /run/ask/dpa_app.loaded ]; then + echo "[ask] running dpa_app" + /bin/dpa_app + touch /run/ask/dpa_app.loaded +else + echo "[ask] dpa_app already loaded; skipping" +fi + +echo "[ask] loading fci" +modprobe fci + +echo "[ask] starting cmm" +exec /bin/cmm -D -f "$CMM_CONFIG" -n "$CMM_MAX_CONNECTIONS" diff --git a/docker/ask.Dockerfile b/docker/ask.Dockerfile index 0372f4a..82e6028 100644 --- a/docker/ask.Dockerfile +++ b/docker/ask.Dockerfile @@ -284,7 +284,7 @@ RUN mkdir -p /out/rootfs-cfg/etc/dpa && \ cp "${ASK_DIR}/config/gateway-dk/cdx_cfg.xml" /out/rootfs-cfg/etc/dpa/ && \ cp -r /src/fmc/etc/* /out/rootfs-cfg/etc && \ mkdir -p /out/rootfs-cfg/etc/cmm && \ - cp "${ASK_DIR}/config/fastforward" /out/rootfs-cfg/etc/cmm/ + cp "${ASK_DIR}/config/fastforward" /out/rootfs-cfg/etc/cmm/fastforward.vendor.orig FROM scratch AS export diff --git a/docker/cmm.Dockerfile b/docker/cmm.Dockerfile new file mode 100644 index 0000000..a1f877f --- /dev/null +++ b/docker/cmm.Dockerfile @@ -0,0 +1,15 @@ +ARG ALPINE_SERIES=3.23 +FROM alpine:${ALPINE_SERIES} + +RUN apk add --no-cache kmod busybox-extras + +COPY ./out/ASK/rootfs-cfg/etc /etc +COPY ./out/ASK/bin/cmm /bin/cmm +COPY ./out/ASK/bin/dpa_app /bin/dpa_app +COPY ./ask/cmm/cmm.conf /etc/cmm/cmm.conf +COPY ./ask/cmm/entrypoint.sh /entrypoint.sh + +RUN chmod +x /bin/cmm /bin/dpa_app /entrypoint.sh \ + && mkdir -p /run/ask /var/log + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/docs/vendor-resources.md b/docs/vendor-resources.md index 7f67794..be822ec 100644 --- a/docs/vendor-resources.md +++ b/docs/vendor-resources.md @@ -88,7 +88,7 @@ set -eu FILES=" bin/cmm -rootfs-cfg/etc/cmm/fastforward +rootfs-cfg/etc/cmm/fastforward.vendor.orig " SIZE=$( @@ -110,7 +110,7 @@ SIZE=$( echo 'tar -xzf /tmp/cmm-test.tar.gz -C /var/cmm-test' echo 'install -m 0755 /var/cmm-test/bin/cmm /var/ask/bin/cmm' - echo 'install -m 0644 /var/cmm-test/rootfs-cfg/etc/cmm/fastforward /var/ask/etc/cmm/fastforward' + echo 'install -m 0644 /var/cmm-test/rootfs-cfg/etc/cmm/fastforward.vendor.orig /var/ask/etc/cmm/fastforward' echo 'ls -l /var/ask/bin/cmm /var/ask/etc/cmm/fastforward /dev/cdx_ctrl' echo 'ldd /var/ask/bin/cmm || true' @@ -118,7 +118,7 @@ SIZE=$( echo 'test -e /sys/class/vwd/vwd0/vwd_fast_path_enable && echo 1 > /sys/class/vwd/vwd0/vwd_fast_path_enable || true' echo 'echo Running cmm' - echo '/var/ask/bin/cmm -f /var/ask/etc/cmm/fastforward -n 131072' + echo '/var/ask/bin/cmm -D -f /var/ask/etc/cmm/fastforward -n 131072' echo 'echo exit=$?' ) | nc 10.0.0.10 1234 ``` diff --git a/makefile b/makefile index a3b7995..f5197a5 100644 --- a/makefile +++ b/makefile @@ -247,6 +247,17 @@ ASK: $(ASK_TAR) $(LIBNFCT_TAR) $(LIBNFNETLINK_TAR) $(TCLAP_TAR) $(LIBXML2_TAR) | --build-arg DEVICE_TREE_TARGET=$(DEVICE_TREE_TARGET) \ --output type=local,dest=./$(OUT_DIR)/ASK . +cmm-image: ASK + docker buildx build \ + --platform linux/arm64 \ + -f docker/cmm.Dockerfile \ + --build-arg ALPINE_SERIES=$(ALPINE_SERIES) \ + --load \ + -t $(IMAGE_REPOSITORY)/cmm:$(KUBE_VERSION)-$(TAG) . + +push-cmm-image: cmm-image + docker push $(IMAGE_REPOSITORY)/cmm:$(KUBE_VERSION)-$(TAG) + vpp: $(BUILD_BASE_STAMP) $(VPP_TAR) $(DPDK_TAR) $(FMLIB_TAR) $(FMC_TAR) $(NXP_TAR) @build_base_tag=$$(docker image inspect \ --format '{{.Id}}' \ @@ -337,7 +348,6 @@ $(RELEASE_IMAGE): $(RELEASE_DEPS) $(DOWNLOAD_PACKAGES_STAMP) | $(OUT_DIR) test -f $@ - # ---- config targets ------------------------------------------------------------ cluster-config: $(CLUSTER_ENV_DEFAULT) $(CLUSTER_ENV_WORK) $(SCRIPTS_DIR)/merge-env.sh | $(OUT_DIR) @@ -403,5 +413,5 @@ pkgclean: rm -rf $(PACKAGES_DIR) .PHONY: release kernel initramfs itb build-base clitools clean distclean pkgclean \ - vpp ASK \ + vpp ASK cmm-image \ cluster-config cluster-defconfig cluster-print diff --git a/patches/ask/cmm/0001-cmm-add-foreground-mode.patch b/patches/ask/cmm/0001-cmm-add-foreground-mode.patch new file mode 100644 index 0000000..ab59ddd --- /dev/null +++ b/patches/ask/cmm/0001-cmm-add-foreground-mode.patch @@ -0,0 +1,75 @@ +From 7b6ff0e4a7b5e7d422c787d55225ecaa32afc8e4 Mon Sep 17 00:00:00 2001 +From: Mono +Date: Sun, 10 May 2026 15:53:21 +0000 +Subject: [PATCH] cmm: add foreground mode + +--- + cmm/src/cmm.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/cmm/src/cmm.c b/cmm/src/cmm.c +index 6452476..1bbc73e 100644 +--- a/cmm/src/cmm.c ++++ b/cmm/src/cmm.c +@@ -339,6 +339,7 @@ int main (int argc, char ** argv) + struct sigaction action; + int option,ii; + char *buf; ++ int foreground = 0; + int ret = 0; + int ch; + +@@ -402,7 +403,7 @@ int main (int argc, char ** argv) + } + + // Analyse the command line +- while ((option = getopt(argc, argv, "c:f:n:hv")) != -1) ++ while ((option = getopt(argc, argv, "c:f:n:hvD")) != -1) + { + switch (option) + { +@@ -424,6 +425,10 @@ int main (int argc, char ** argv) + } + break; + ++ case 'D': // Do not daemonize; run in foreground ++ foreground = 1; ++ break; ++ + case 'h': // Print help + cmmHelp(); + return 0; +@@ -443,9 +448,11 @@ int main (int argc, char ** argv) + goto err0; + } + +- // Daemonize the application +- if(daemon(0, 1) == -1) +- goto err0; ++ // Daemonize the application unless foreground mode was requested ++ if (!foreground) { ++ if(daemon(0, 1) == -1) ++ goto err0; ++ } + //Ensure clean termination + action.sa_handler = sig_term_hdlr; + sigemptyset(&action.sa_mask); +@@ -471,9 +478,12 @@ int main (int argc, char ** argv) + //schedParams.sched_priority = 99; + //sched_setscheduler(0, SCHED_FIFO, &schedParams); + +- //Init process does not set stdout on console +- if(freopen("/dev/console", "w", stdout) == NULL) +- goto err0; ++ // Init process does not set stdout on console. ++ // In foreground mode, keep stdout attached to the caller/container. ++ if (!foreground) { ++ if(freopen("/dev/console", "w", stdout) == NULL) ++ goto err0; ++ } + sigemptyset(&block_mask); + sigaddset(&block_mask, SIGTERM); + sigaddset(&block_mask, SIGPIPE); +-- +2.47.3 + diff --git a/patches/ask/cmm/0002-cmm-support-stdout-log-target.patch b/patches/ask/cmm/0002-cmm-support-stdout-log-target.patch new file mode 100644 index 0000000..818836b --- /dev/null +++ b/patches/ask/cmm/0002-cmm-support-stdout-log-target.patch @@ -0,0 +1,36 @@ +From 787cf734c807eecc479776ab6ac5c2c43c72e93d Mon Sep 17 00:00:00 2001 +From: Patch +Date: Sun, 10 May 2026 17:37:49 +0000 +Subject: [PATCH] cmm: support stdout log target + + +diff --git a/cmm/src/ffcontrol.c b/cmm/src/ffcontrol.c +index 4c9bdf1..b2b6b53 100644 +--- a/cmm/src/ffcontrol.c ++++ b/cmm/src/ffcontrol.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + /* bits/sockaddr.h is glibc internal, use sys/socket.h (already included) */ + #include +@@ -865,7 +866,13 @@ static int section_logging_option_hdlr(void *data, int argc, char **argv) + + if (!strcasecmp(option, "file")) + { +- globalConf.logFile = fopen(value, "a"); ++ if (!strcasecmp(value, "stdout") || !strcmp(value, "-")) ++ globalConf.logFile = fdopen(dup(STDOUT_FILENO), "a"); ++ else if (!strcasecmp(value, "stderr")) ++ globalConf.logFile = fdopen(dup(STDERR_FILENO), "a"); ++ else ++ globalConf.logFile = fopen(value, "a"); ++ + if (!globalConf.logFile) + { + cmm_print(DEBUG_CRIT, "cmmFcParser: Opening logfile %s returned error %s.\n", value, strerror(errno)); +-- +2.47.3 + From 35f2edc0b51d62fcd562c6191c1043eb3629e21b41ade118a953185bb04987f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Mon, 11 May 2026 04:48:00 +0800 Subject: [PATCH 12/14] ctl create cmm --- alpine/preload-k8s-images.sh | 1 + alpine/rootfs-extra/etc/local.d/monok8s.start | 13 ++ ask/cmm/entrypoint.sh | 31 +-- ask/cmm/init_dpa.sh | 37 +++ clitools/pkg/cmd/create/create.go | 41 ++++ clitools/pkg/render/cmm.go | 219 ++++++++++++++++++ docker/cmm.Dockerfile | 6 +- makefile | 4 +- 8 files changed, 318 insertions(+), 34 deletions(-) create mode 100755 ask/cmm/init_dpa.sh create mode 100644 clitools/pkg/render/cmm.go diff --git a/alpine/preload-k8s-images.sh b/alpine/preload-k8s-images.sh index d963384..b449780 100755 --- a/alpine/preload-k8s-images.sh +++ b/alpine/preload-k8s-images.sh @@ -27,6 +27,7 @@ FUSE_OVERLAYFS="${FUSE_OVERLAYFS:-/usr/bin/fuse-overlayfs}" EXTRA_IMAGES=( "${EXTRA_IMAGES[@]:-}" "docker-daemon:localhost/monok8s/node-control:$TAG" + "docker-daemon:localhost/monok8s/cmm:$TAG" ) # Keep archive cache version/arch scoped so downloads do not get mixed. diff --git a/alpine/rootfs-extra/etc/local.d/monok8s.start b/alpine/rootfs-extra/etc/local.d/monok8s.start index 30428c9..8d350fe 100755 --- a/alpine/rootfs-extra/etc/local.d/monok8s.start +++ b/alpine/rootfs-extra/etc/local.d/monok8s.start @@ -11,6 +11,19 @@ BOOT_STATE=/run/monok8s/boot-state.env BOOTPART_FILE="$CONFIG_DIR/.bootpart" MIGRATION_STATE_DIR="$CONFIG_DIR/migration-state" +load_module_optional() { + module="$1" + + if ! modprobe "$module"; then + echo "WARNING: failed to load optional module: $module" + fi +} + +echo "Loading optional hardware offload modules..." +load_module_optional cdx +load_module_optional fci +load_module_optional auto_bridge + mkdir -p /dev/hugepages mountpoint -q /dev/hugepages || mount -t hugetlbfs none /dev/hugepages echo 256 > /proc/sys/vm/nr_hugepages diff --git a/ask/cmm/entrypoint.sh b/ask/cmm/entrypoint.sh index c8c91ec..a9dac4e 100644 --- a/ask/cmm/entrypoint.sh +++ b/ask/cmm/entrypoint.sh @@ -3,36 +3,9 @@ set -eu CMM_CONFIG="${CMM_CONFIG:-/etc/cmm/cmm.conf}" -# Vendor default from cmm.service: (131072 = 128 * 1024) max active conntrack/offload entries +# Vendor default from cmm.service: +# 131072 = 128 * 1024 max active conntrack/offload entries. CMM_MAX_CONNECTIONS="${CMM_MAX_CONNECTIONS:-131072}" -mkdir -p /run/ask /var/log - -echo "[ask] loading auto_bridge" -modprobe auto_bridge || true - -echo "[ask] loading cdx" -modprobe cdx - -echo "[ask] waiting for /dev/cdx_ctrl" -for i in $(seq 1 40); do - if [ -e /dev/cdx_ctrl ]; then - break - fi - sleep 0.25 -done -test -e /dev/cdx_ctrl - -if [ ! -e /run/ask/dpa_app.loaded ]; then - echo "[ask] running dpa_app" - /bin/dpa_app - touch /run/ask/dpa_app.loaded -else - echo "[ask] dpa_app already loaded; skipping" -fi - -echo "[ask] loading fci" -modprobe fci - echo "[ask] starting cmm" exec /bin/cmm -D -f "$CMM_CONFIG" -n "$CMM_MAX_CONNECTIONS" diff --git a/ask/cmm/init_dpa.sh b/ask/cmm/init_dpa.sh new file mode 100755 index 0000000..e11b624 --- /dev/null +++ b/ask/cmm/init_dpa.sh @@ -0,0 +1,37 @@ +#!/bin/sh +set -eu + +STATE_DIR="${CMM_STATE_DIR:-/host/run/monok8s/cmm}" +DONE_FILE="$STATE_DIR/dpa_app.loaded" +LOCK_DIR="$STATE_DIR/dpa_app.lock" + +mkdir -p "$STATE_DIR" + +if [ -e "$DONE_FILE" ]; then + echo "[ask] dpa_app already loaded for this boot; skipping" + exit 0 +fi + +if ! mkdir "$LOCK_DIR" 2>/dev/null; then + echo "[ask] another dpa_app initialization is running; waiting" + + while [ ! -e "$DONE_FILE" ]; do + sleep 1 + done + + echo "[ask] dpa_app was loaded by another process; skipping" + exit 0 +fi + +trap 'rmdir "$LOCK_DIR" 2>/dev/null || true' EXIT + +if [ -e "$DONE_FILE" ]; then + echo "[ask] dpa_app already loaded for this boot; skipping" + exit 0 +fi + +echo "[ask] running dpa_app" +/bin/dpa_app + +date -u +"%Y-%m-%dT%H:%M:%SZ" > "$DONE_FILE" +echo "[ask] dpa_app loaded" diff --git a/clitools/pkg/cmd/create/create.go b/clitools/pkg/cmd/create/create.go index e3b5fd8..9ec1a23 100644 --- a/clitools/pkg/cmd/create/create.go +++ b/clitools/pkg/cmd/create/create.go @@ -165,6 +165,47 @@ func NewCmdCreate(flags *genericclioptions.ConfigFlags) *cobra.Command { cmd.AddCommand(&agentcmd) + cmmconf := render.CMMConf{} + cmmcmd := cobra.Command{ + Use: "cmm", + Short: "Print CMM daemonsets template", + RunE: func(cmd *cobra.Command, _ []string) error { + if len(cmmconf.ImagePullSecrets) > 0 && strings.TrimSpace(cmmconf.Image) == "" { + return fmt.Errorf("--image-pull-secret requires --image") + } + + ns, _, err := flags.ToRawKubeConfigLoader().Namespace() + if err != nil { + return err + } + + cmmconf.Namespace = ns + + out, err := render.RenderCMMDaemonSets(cmmconf) + if err != nil { + return err + } + + _, err = fmt.Fprint(cmd.OutOrStdout(), out) + return err + }, + } + + cmmcmd.Flags().StringVar( + &cmmconf.Image, + "image", + "", + "CMM image, including optional registry and tag", + ) + cmmcmd.Flags().StringSliceVar( + &cmmconf.ImagePullSecrets, + "image-pull-secret", + nil, + "Image pull secret name for the CMM image; may be specified multiple times or as a comma-separated list", + ) + + cmd.AddCommand(&cmmcmd) + return cmd } diff --git a/clitools/pkg/render/cmm.go b/clitools/pkg/render/cmm.go new file mode 100644 index 0000000..4b85275 --- /dev/null +++ b/clitools/pkg/render/cmm.go @@ -0,0 +1,219 @@ +package render + +import ( + "fmt" + "strings" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + buildinfo "example.com/monok8s/pkg/buildinfo" +) + +const cmmName = "cmm" + +type CMMConf struct { + Namespace string + Image string + ImagePullSecrets []string + Labels map[string]string +} + +func RenderCMMDaemonSets(conf CMMConf) (string, error) { + objs, err := buildCMMDaemonSetObjects(conf) + if err != nil { + return "", err + } + + return renderObjects(objs) +} + +func buildCMMDaemonSetObjects(conf CMMConf) ([]runtime.Object, error) { + if strings.TrimSpace(conf.Namespace) == "" { + return nil, fmt.Errorf("namespace is required") + } + + conf.Labels = map[string]string{ + "app.kubernetes.io/name": cmmName, + "app.kubernetes.io/component": "hardware-offload", + "app.kubernetes.io/part-of": "monok8s", + "app.kubernetes.io/managed-by": "monok8s", + } + + return []runtime.Object{ + buildCMMServiceAccount(conf), + buildCMMDaemonSet(conf), + }, nil +} + +func buildCMMServiceAccount(conf CMMConf) *corev1.ServiceAccount { + return &corev1.ServiceAccount{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "ServiceAccount", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: cmmName, + Namespace: conf.Namespace, + Labels: copyStringMap(conf.Labels), + }, + } +} + +func buildCMMDaemonSet(conf CMMConf) *appsv1.DaemonSet { + privileged := true + dsLabels := map[string]string{ + "app.kubernetes.io/name": cmmName, + "app.kubernetes.io/component": "hardware-offload", + "app.kubernetes.io/part-of": "monok8s", + "app.kubernetes.io/managed-by": "monok8s", + } + + image, pullPolicy := cmmImage(conf) + + return &appsv1.DaemonSet{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "apps/v1", + Kind: "DaemonSet", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: cmmName, + Namespace: conf.Namespace, + Labels: copyStringMap(conf.Labels), + }, + Spec: appsv1.DaemonSetSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app.kubernetes.io/name": cmmName, + }, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: dsLabels, + }, + Spec: corev1.PodSpec{ + ServiceAccountName: cmmName, + HostNetwork: true, + DNSPolicy: corev1.DNSClusterFirstWithHostNet, + ImagePullSecrets: imagePullSecrets(conf.ImagePullSecrets), + Tolerations: []corev1.Toleration{ + {Operator: corev1.TolerationOpExists}, + }, + InitContainers: []corev1.Container{ + { + Name: "dpa-app", + Image: image, + ImagePullPolicy: pullPolicy, + Command: []string{"/init_dpa.sh"}, + Env: cdxEnv(), + SecurityContext: &corev1.SecurityContext{ + Privileged: &privileged, + }, + VolumeMounts: append( + []corev1.VolumeMount{ + { + Name: "host-run-cmm", + MountPath: "/host/run/monok8s/cmm", + }, + }, + cdxVolumeMounts()..., + ), + }, + }, + Containers: []corev1.Container{ + { + Name: cmmName, + Image: image, + ImagePullPolicy: pullPolicy, + Env: cmmEnv(), + SecurityContext: &corev1.SecurityContext{ + Privileged: &privileged, + }, + VolumeMounts: cdxVolumeMounts(), + }, + }, + Volumes: cmmVolumes(), + NodeSelector: map[string]string{ + "node.kubernetes.io/instance-type": "mono-gateway", + }, + }, + }, + }, + } +} + +func cdxEnv() []corev1.EnvVar { + return []corev1.EnvVar{ + { + Name: "CDX_CFG_FILE", + Value: "/etc/dpa/cdx_cfg.xml", + }, + { + Name: "CDX_PCD_FILE", + Value: "/etc/dpa/cdx_pcd.xml", + }, + { + Name: "CDX_PDL_FILE", + Value: "/etc/fmc/config/hxs_pdl_v3.xml", + }, + { + Name: "CDX_SP_FILE", + Value: "/etc/dpa/cdx_sp.xml", + }, + } +} + +func cmmEnv() []corev1.EnvVar { + return []corev1.EnvVar{ + { + Name: "CMM_CONFIG", + Value: "/etc/cmm/cmm.conf", + }, + { + Name: "CMM_MAX_CONNECTIONS", + Value: "131072", + }, + } +} + +func cdxVolumeMounts() []corev1.VolumeMount { + return []corev1.VolumeMount{ + { + Name: "cdx-ctrl", + MountPath: "/dev/cdx_ctrl", + }, + } +} + +func cmmVolumes() []corev1.Volume { + return []corev1.Volume{ + { + Name: "cdx-ctrl", + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: "/dev/cdx_ctrl", + Type: hostPathType(corev1.HostPathCharDev), + }, + }, + }, + { + Name: "host-run-cmm", + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: "/run/monok8s/cmm", + Type: hostPathType(corev1.HostPathDirectoryOrCreate), + }, + }, + }, + } +} + +func cmmImage(conf CMMConf) (string, corev1.PullPolicy) { + if conf.Image != "" { + return conf.Image, corev1.PullIfNotPresent + } + + return fmt.Sprintf("localhost/monok8s/cmm:%s", buildinfo.Version), corev1.PullNever +} diff --git a/docker/cmm.Dockerfile b/docker/cmm.Dockerfile index a1f877f..498c094 100644 --- a/docker/cmm.Dockerfile +++ b/docker/cmm.Dockerfile @@ -1,15 +1,13 @@ ARG ALPINE_SERIES=3.23 FROM alpine:${ALPINE_SERIES} -RUN apk add --no-cache kmod busybox-extras - COPY ./out/ASK/rootfs-cfg/etc /etc COPY ./out/ASK/bin/cmm /bin/cmm COPY ./out/ASK/bin/dpa_app /bin/dpa_app COPY ./ask/cmm/cmm.conf /etc/cmm/cmm.conf COPY ./ask/cmm/entrypoint.sh /entrypoint.sh +COPY ./ask/cmm/init_dpa.sh /init_dpa.sh -RUN chmod +x /bin/cmm /bin/dpa_app /entrypoint.sh \ - && mkdir -p /run/ask /var/log +RUN chmod +x /bin/cmm /bin/dpa_app /init_dpa.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] diff --git a/makefile b/makefile index f5197a5..32500a6 100644 --- a/makefile +++ b/makefile @@ -105,6 +105,7 @@ RELEASE_DEPS := \ $(BOARD_ITB) \ $(CLITOOLS_BIN) \ docker/alpine.Dockerfile \ + cmm-image \ $(ALPINE_SRCS) \ build.env \ makefile @@ -253,9 +254,10 @@ cmm-image: ASK -f docker/cmm.Dockerfile \ --build-arg ALPINE_SERIES=$(ALPINE_SERIES) \ --load \ - -t $(IMAGE_REPOSITORY)/cmm:$(KUBE_VERSION)-$(TAG) . + -t localhost/monok8s/cmm:$(TAG) . push-cmm-image: cmm-image + docker tag -t localhost/monok8s/cmm:$(TAG) $(IMAGE_REPOSITORY)/cmm:$(KUBE_VERSION)-$(TAG) . docker push $(IMAGE_REPOSITORY)/cmm:$(KUBE_VERSION)-$(TAG) vpp: $(BUILD_BASE_STAMP) $(VPP_TAR) $(DPDK_TAR) $(FMLIB_TAR) $(FMC_TAR) $(NXP_TAR) From 7411e1994b5571eb1c5dd8f2a532ba076626a397d00a7537500ca273241b5916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Mon, 11 May 2026 07:01:39 +0800 Subject: [PATCH 13/14] Got cmm working --- ask/cmm/cmm.conf | 5 +- docker/ask.Dockerfile | 80 ++++++++-------- ...3-cmm-ignore-non-fastpath-conntracks.patch | 74 +++++++++++++++ patches/ask/upstream/README.md | 1 + ...net__freescale__sdk_dpaa__dpaa_eth.h.patch | 0 ...__freescale__sdk_dpaa__dpaa_eth_sg.c.patch | 0 ...062-drivers__net__ppp__ppp_generic.c.patch | 0 ...ers__staging__fsl_qbman__qman_high.c.patch | 0 .../0071-include__linux__if_bridge.h.patch | 0 .../kernel/0078-include__net__xfrm.h.patch | 0 ...ux__netfilter__nfnetlink_conntrack.h.patch | 0 .../0100-net__bridge__br_private.h.patch | 0 .../kernel/0103-net__core__dev.c.patch | 0 .../kernel/0108-net__ipv4__ip_output.c.patch | 0 .../kernel/0112-net__ipv6__ip6_output.c.patch | 0 .../0115-net__ipv6__output_core.c.patch | 0 .../kernel/0119-net__key__af_key.c.patch | 0 ...t__netfilter__nf_conntrack_netlink.c.patch | 0 .../kernel/0129-net__wireless__Kconfig.patch | 0 .../kernel/0131-net__xfrm__Makefile.patch | 0 .../0136-net__xfrm__xfrm_policy.c.patch | 0 .../kernel/0137-net__xfrm__xfrm_state.c.patch | 0 ...o-not-abort-on-unusable-nxp-attrs-v3.patch | 93 +++++++++++++++++++ 23 files changed, 213 insertions(+), 40 deletions(-) create mode 100644 patches/ask/cmm/0003-cmm-ignore-non-fastpath-conntracks.patch create mode 100644 patches/ask/upstream/README.md rename patches/ask/{ => upstream}/kernel/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch (100%) rename patches/ask/{ => upstream}/kernel/0009-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth_sg.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0062-drivers__net__ppp__ppp_generic.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0068-drivers__staging__fsl_qbman__qman_high.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0071-include__linux__if_bridge.h.patch (100%) rename patches/ask/{ => upstream}/kernel/0078-include__net__xfrm.h.patch (100%) rename patches/ask/{ => upstream}/kernel/0086-include__uapi__linux__netfilter__nfnetlink_conntrack.h.patch (100%) rename patches/ask/{ => upstream}/kernel/0100-net__bridge__br_private.h.patch (100%) rename patches/ask/{ => upstream}/kernel/0103-net__core__dev.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0108-net__ipv4__ip_output.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0112-net__ipv6__ip6_output.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0115-net__ipv6__output_core.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0119-net__key__af_key.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0124-net__netfilter__nf_conntrack_netlink.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0129-net__wireless__Kconfig.patch (100%) rename patches/ask/{ => upstream}/kernel/0131-net__xfrm__Makefile.patch (100%) rename patches/ask/{ => upstream}/kernel/0136-net__xfrm__xfrm_policy.c.patch (100%) rename patches/ask/{ => upstream}/kernel/0137-net__xfrm__xfrm_state.c.patch (100%) create mode 100644 patches/ask/upstream/libnetfilter-conntrack/02-libnetfilter-conntrack-do-not-abort-on-unusable-nxp-attrs-v3.patch diff --git a/ask/cmm/cmm.conf b/ask/cmm/cmm.conf index 5951418..0e2977a 100644 --- a/ask/cmm/cmm.conf +++ b/ask/cmm/cmm.conf @@ -17,10 +17,11 @@ config fastforward pptp option port 1723 # Optional logging -# NOTE: "stdout" only supported in our own patched version +# NOTE: "stdout" only supported in our own patched version. +# Keep info disabled by default; CMM receives the whole conntrack stream. config logging option file stdout option command 0 option error 1 option warning 1 - option info 1 + option info 0 diff --git a/docker/ask.Dockerfile b/docker/ask.Dockerfile index 82e6028..896620a 100644 --- a/docker/ask.Dockerfile +++ b/docker/ask.Dockerfile @@ -51,8 +51,16 @@ COPY "${LIBNFCT_TAR}" ./libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz # Provision the musl cross-compiler from musl.cc RUN tar zxf "aarch64_musl_cc.tar.gz" -C /opt -# Expose the musl compiler to the PATH -ENV PATH="/opt/aarch64-linux-musl-cross/bin:${PATH}" +# Common paths / flags for the remaining ASK build. +# Keep userspace fully static against the musl sysroot. +ENV PATH="/opt/aarch64-linux-musl-cross/bin:${PATH}" \ + ASK_DIR=/src/ASK \ + KERNEL_DIR=/src/linux \ + SYSROOT=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ + HOST=aarch64-linux-musl \ + CROSS_COMPILE=aarch64-linux-musl- \ + ARCH=arm64 \ + PLATFORM=LS1043A # Extract and build the dependency libraries RUN mkdir -p ASK/sources/tarballs && \ @@ -65,7 +73,7 @@ RUN mkdir linux && tar zxf "kernel.tar.gz" -C "linux" --strip-components=1 && \ # ASK's Kernel patches COPY patches/ask/split-kernel-patch.sh /src/split-kernel-patch.sh -COPY patches/ask/kernel/*.patch /src/ASK/patches/kernel/updated-patch/ +COPY patches/ask/upstream/kernel/*.patch /src/ASK/patches/kernel/updated-patch/ RUN chmod +x /src/split-kernel-patch.sh && \ PATCH_FILE="/src/ASK/patches/kernel/002-mono-gateway-ask-kernel_linux_6_12.patch" \ @@ -74,6 +82,17 @@ RUN chmod +x /src/split-kernel-patch.sh && \ /src/split-kernel-patch.sh split && \ /src/split-kernel-patch.sh apply +# Build the kernel first, without the custom DTS +COPY kernel-extra.config /src/kernel-extra.config +COPY kernel-build/ensure-kconfig.sh /src/ + +RUN cd /src/linux \ + && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" defconfig lsdk.config \ + && ./scripts/kconfig/merge_config.sh -m .config "${ASK_DIR}/config/kernel/defconfig" /src/kernel-extra.config \ + && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" olddefconfig \ + && /src/ensure-kconfig.sh .config /src/kernel-extra.config \ + && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" -j"$(nproc)" + # tclap RUN mkdir -p tclap && tar zxf "tclap.tar.gz" -C "tclap" --strip-components=1 && \ cp -r tclap/include/tclap /opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/ && \ @@ -135,15 +154,18 @@ RUN mkdir fmlib && \ LIBXML2_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include/libxml2 \ TCLAP_HEADER_PATH=/opt/aarch64-linux-musl-cross/aarch64-linux-musl/include -# Common paths / flags for the remaining ASK build. -# Keep userspace fully static against the musl sysroot. -ENV ASK_DIR=/src/ASK \ - KERNEL_DIR=/src/linux \ - SYSROOT=/opt/aarch64-linux-musl-cross/aarch64-linux-musl \ - HOST=aarch64-linux-musl \ - CROSS_COMPILE=aarch64-linux-musl- \ - ARCH=arm64 \ - PLATFORM=LS1043A +# Patch verdor's modules +RUN mkdir -p /src/patches/ask +COPY patches/ask/ /src/patches/ask/ + +RUN cd /src/ASK && \ + git init -q && git add -A && git commit -q -m "base" && \ + find /src/patches/ask \ + -path /src/patches/ask/upstream -prune -o \ + -name '*.patch' -print \ + | sort > /tmp/ask-module-patches.list && \ + test ! -s /tmp/ask-module-patches.list || xargs -a /tmp/ask-module-patches.list git apply --check && \ + test ! -s /tmp/ask-module-patches.list || xargs -a /tmp/ask-module-patches.list git apply # Build patched libnfnetlink + libnetfilter_conntrack into the musl sysroot. # These are needed by cmm through pkg-config. @@ -163,8 +185,15 @@ RUN mkdir -p "${ASK_DIR}/sources" && \ tar xf "${ASK_DIR}/sources/tarballs/libnetfilter_conntrack-${LIBNFCT_VERSION}.tar.xz" \ -C libnetfilter_conntrack --strip-components=1 && \ cd libnetfilter_conntrack && \ + cp /src/patches/ask/upstream/libnetfilter-conntrack/* "${ASK_DIR}/patches/libnetfilter-conntrack/" && \ git init -q && git add -A && git commit -q -m "upstream" && \ - git apply "${ASK_DIR}/patches/libnetfilter-conntrack/01-nxp-ask-comcerto-fp-extensions.patch" && \ + find "${ASK_DIR}/patches/libnetfilter-conntrack/" \ + -name '*.patch' -exec sha256sum {} \; && \ + find "${ASK_DIR}/patches/libnetfilter-conntrack/" \ + -name '*.patch' -print \ + | sort > /tmp/libnfct-patches.list && \ + test ! -s /tmp/libnfct-patches.list || xargs -a /tmp/libnfct-patches.list git apply --check && \ + test ! -s /tmp/libnfct-patches.list || xargs -a /tmp/libnfct-patches.list git apply && \ PKG_CONFIG_PATH="${SYSROOT}/lib/pkgconfig" \ CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar RANLIB=aarch64-linux-musl-ranlib \ ./configure --host="${HOST}" --prefix="${SYSROOT}" \ @@ -179,17 +208,6 @@ RUN make -C "${ASK_DIR}/fci/lib" \ CC=aarch64-linux-musl-gcc \ AR=aarch64-linux-musl-ar -# Build the kernel first, without the custom DTS -COPY kernel-extra.config /src/kernel-extra.config -COPY kernel-build/ensure-kconfig.sh /src/ - -RUN cd /src/linux \ - && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" defconfig lsdk.config \ - && ./scripts/kconfig/merge_config.sh -m .config "${ASK_DIR}/config/kernel/defconfig" /src/kernel-extra.config \ - && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" olddefconfig \ - && /src/ensure-kconfig.sh .config /src/kernel-extra.config \ - && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" -j"$(nproc)" - # DTS changes happen after the expensive kernel build layer COPY kernel-build/dts/*.dts /src/linux/arch/arm64/boot/dts/freescale/ @@ -203,19 +221,6 @@ RUN cd /src/linux \ && make ARCH="${ARCH}" CROSS_COMPILE="${CROSS_COMPILE}" \ "freescale/${DEVICE_TREE_TARGET}.dtb" -# Patch verdor's modules -RUN mkdir -p /src/patches/ask -COPY patches/ask/ /src/patches/ask/ - -RUN cd /src/ASK && \ - git init -q && git add -A && git commit -q -m "base" && \ - find /src/patches/ask \ - -path /src/patches/ask/kernel -prune -o \ - -name '*.patch' -print \ - | sort > /tmp/ask-module-patches.list && \ - test ! -s /tmp/ask-module-patches.list || xargs -a /tmp/ask-module-patches.list git apply --check && \ - test ! -s /tmp/ask-module-patches.list || xargs -a /tmp/ask-module-patches.list git apply - # Build out-of-tree ASK kernel modules: cdx -> fci, plus auto_bridge. RUN make -C "${ASK_DIR}/cdx" \ CROSS_COMPILE="${CROSS_COMPILE}" \ @@ -286,7 +291,6 @@ RUN mkdir -p /out/rootfs-cfg/etc/dpa && \ mkdir -p /out/rootfs-cfg/etc/cmm && \ cp "${ASK_DIR}/config/fastforward" /out/rootfs-cfg/etc/cmm/fastforward.vendor.orig - FROM scratch AS export ARG DEVICE_TREE_TARGET diff --git a/patches/ask/cmm/0003-cmm-ignore-non-fastpath-conntracks.patch b/patches/ask/cmm/0003-cmm-ignore-non-fastpath-conntracks.patch new file mode 100644 index 0000000..65f478c --- /dev/null +++ b/patches/ask/cmm/0003-cmm-ignore-non-fastpath-conntracks.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: monok8s authors +Date: Mon, 11 May 2026 00:00:00 +0000 +Subject: [PATCH] cmm: ignore conntracks without fastpath metadata + +CMM receives conntrack notifications for the whole system conntrack table. +On a Kubernetes node, many entries are unrelated to Comcerto/NXP fastpath: +loopback traffic, local control-plane traffic, Cilium traffic, broadcast, +multicast, and ordinary slow-path flows. + +Those entries do not necessarily carry the private fastpath attributes CMM +expects. Treat them as non-fastpathable instead of trying to process them. + +--- + cmm/src/ffcontrol.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/cmm/src/ffcontrol.c b/cmm/src/ffcontrol.c +--- a/cmm/src/ffcontrol.c ++++ b/cmm/src/ffcontrol.c +@@ -75,6 +75,25 @@ + return 1; + } + ++/***************************************************************** ++* cmmFcHasFastpathAttrs() ++* ++* CMM receives all conntrack notifications, including entries that ++* never passed through the Comcerto/NXP fastpath hooks. Those entries ++* do not have the private fastpath attributes needed below. Treat them ++* as ordinary slow-path conntracks and ignore them. ++******************************************************************/ ++static int cmmFcHasFastpathAttrs(struct nf_conntrack *ct) ++{ ++ if (!nfct_attr_is_set(ct, ATTR_ORIG_COMCERTO_FP_IIF)) ++ return 0; ++ ++ if (!nfct_attr_is_set(ct, ATTR_ORIG_COMCERTO_FP_IFINDEX)) ++ return 0; ++ ++ return 1; ++} ++ + /***************************************************************** + * cmmIsConntrack4Allowed() + * +@@ -92,6 +111,12 @@ + sAddr = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); + dAddr = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC); + ++ if (!cmmFcHasFastpathAttrs(ct)) { ++ cmm_print(DEBUG_INFO, "%s: conntrack has no fastpath metadata, ignored\n", ++ __func__); ++ goto refused; ++ } ++ + /* Multicast connections are not forwarded */ + if (MULTICAST(dAddr)) { + cmm_print(DEBUG_WARNING, "%s: conntrack multicast dst:%s:%x src:%s:%x\n", __func__, +@@ -197,6 +222,12 @@ + Saddr = nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC); + SaddrReply = nfct_get_attr(ct, ATTR_REPL_IPV6_SRC); + ++ if (!Saddr || !SaddrReply || !cmmFcHasFastpathAttrs(ct)) { ++ cmm_print(DEBUG_INFO, "%s: conntrack has no fastpath metadata, ignored\n", ++ __func__); ++ goto refused; ++ } ++ + if ((SaddrReply[0] & ntohl(0xff000000)) == ntohl(0xff000000)) + { + goto refused; +-- +2.45.0 \ No newline at end of file diff --git a/patches/ask/upstream/README.md b/patches/ask/upstream/README.md new file mode 100644 index 0000000..4d534d0 --- /dev/null +++ b/patches/ask/upstream/README.md @@ -0,0 +1 @@ +This is for when vendor is already patching upstream source. And we are patching on top of it. diff --git a/patches/ask/kernel/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch b/patches/ask/upstream/kernel/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch similarity index 100% rename from patches/ask/kernel/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch rename to patches/ask/upstream/kernel/0005-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth.h.patch diff --git a/patches/ask/kernel/0009-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth_sg.c.patch b/patches/ask/upstream/kernel/0009-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth_sg.c.patch similarity index 100% rename from patches/ask/kernel/0009-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth_sg.c.patch rename to patches/ask/upstream/kernel/0009-drivers__net__ethernet__freescale__sdk_dpaa__dpaa_eth_sg.c.patch diff --git a/patches/ask/kernel/0062-drivers__net__ppp__ppp_generic.c.patch b/patches/ask/upstream/kernel/0062-drivers__net__ppp__ppp_generic.c.patch similarity index 100% rename from patches/ask/kernel/0062-drivers__net__ppp__ppp_generic.c.patch rename to patches/ask/upstream/kernel/0062-drivers__net__ppp__ppp_generic.c.patch diff --git a/patches/ask/kernel/0068-drivers__staging__fsl_qbman__qman_high.c.patch b/patches/ask/upstream/kernel/0068-drivers__staging__fsl_qbman__qman_high.c.patch similarity index 100% rename from patches/ask/kernel/0068-drivers__staging__fsl_qbman__qman_high.c.patch rename to patches/ask/upstream/kernel/0068-drivers__staging__fsl_qbman__qman_high.c.patch diff --git a/patches/ask/kernel/0071-include__linux__if_bridge.h.patch b/patches/ask/upstream/kernel/0071-include__linux__if_bridge.h.patch similarity index 100% rename from patches/ask/kernel/0071-include__linux__if_bridge.h.patch rename to patches/ask/upstream/kernel/0071-include__linux__if_bridge.h.patch diff --git a/patches/ask/kernel/0078-include__net__xfrm.h.patch b/patches/ask/upstream/kernel/0078-include__net__xfrm.h.patch similarity index 100% rename from patches/ask/kernel/0078-include__net__xfrm.h.patch rename to patches/ask/upstream/kernel/0078-include__net__xfrm.h.patch diff --git a/patches/ask/kernel/0086-include__uapi__linux__netfilter__nfnetlink_conntrack.h.patch b/patches/ask/upstream/kernel/0086-include__uapi__linux__netfilter__nfnetlink_conntrack.h.patch similarity index 100% rename from patches/ask/kernel/0086-include__uapi__linux__netfilter__nfnetlink_conntrack.h.patch rename to patches/ask/upstream/kernel/0086-include__uapi__linux__netfilter__nfnetlink_conntrack.h.patch diff --git a/patches/ask/kernel/0100-net__bridge__br_private.h.patch b/patches/ask/upstream/kernel/0100-net__bridge__br_private.h.patch similarity index 100% rename from patches/ask/kernel/0100-net__bridge__br_private.h.patch rename to patches/ask/upstream/kernel/0100-net__bridge__br_private.h.patch diff --git a/patches/ask/kernel/0103-net__core__dev.c.patch b/patches/ask/upstream/kernel/0103-net__core__dev.c.patch similarity index 100% rename from patches/ask/kernel/0103-net__core__dev.c.patch rename to patches/ask/upstream/kernel/0103-net__core__dev.c.patch diff --git a/patches/ask/kernel/0108-net__ipv4__ip_output.c.patch b/patches/ask/upstream/kernel/0108-net__ipv4__ip_output.c.patch similarity index 100% rename from patches/ask/kernel/0108-net__ipv4__ip_output.c.patch rename to patches/ask/upstream/kernel/0108-net__ipv4__ip_output.c.patch diff --git a/patches/ask/kernel/0112-net__ipv6__ip6_output.c.patch b/patches/ask/upstream/kernel/0112-net__ipv6__ip6_output.c.patch similarity index 100% rename from patches/ask/kernel/0112-net__ipv6__ip6_output.c.patch rename to patches/ask/upstream/kernel/0112-net__ipv6__ip6_output.c.patch diff --git a/patches/ask/kernel/0115-net__ipv6__output_core.c.patch b/patches/ask/upstream/kernel/0115-net__ipv6__output_core.c.patch similarity index 100% rename from patches/ask/kernel/0115-net__ipv6__output_core.c.patch rename to patches/ask/upstream/kernel/0115-net__ipv6__output_core.c.patch diff --git a/patches/ask/kernel/0119-net__key__af_key.c.patch b/patches/ask/upstream/kernel/0119-net__key__af_key.c.patch similarity index 100% rename from patches/ask/kernel/0119-net__key__af_key.c.patch rename to patches/ask/upstream/kernel/0119-net__key__af_key.c.patch diff --git a/patches/ask/kernel/0124-net__netfilter__nf_conntrack_netlink.c.patch b/patches/ask/upstream/kernel/0124-net__netfilter__nf_conntrack_netlink.c.patch similarity index 100% rename from patches/ask/kernel/0124-net__netfilter__nf_conntrack_netlink.c.patch rename to patches/ask/upstream/kernel/0124-net__netfilter__nf_conntrack_netlink.c.patch diff --git a/patches/ask/kernel/0129-net__wireless__Kconfig.patch b/patches/ask/upstream/kernel/0129-net__wireless__Kconfig.patch similarity index 100% rename from patches/ask/kernel/0129-net__wireless__Kconfig.patch rename to patches/ask/upstream/kernel/0129-net__wireless__Kconfig.patch diff --git a/patches/ask/kernel/0131-net__xfrm__Makefile.patch b/patches/ask/upstream/kernel/0131-net__xfrm__Makefile.patch similarity index 100% rename from patches/ask/kernel/0131-net__xfrm__Makefile.patch rename to patches/ask/upstream/kernel/0131-net__xfrm__Makefile.patch diff --git a/patches/ask/kernel/0136-net__xfrm__xfrm_policy.c.patch b/patches/ask/upstream/kernel/0136-net__xfrm__xfrm_policy.c.patch similarity index 100% rename from patches/ask/kernel/0136-net__xfrm__xfrm_policy.c.patch rename to patches/ask/upstream/kernel/0136-net__xfrm__xfrm_policy.c.patch diff --git a/patches/ask/kernel/0137-net__xfrm__xfrm_state.c.patch b/patches/ask/upstream/kernel/0137-net__xfrm__xfrm_state.c.patch similarity index 100% rename from patches/ask/kernel/0137-net__xfrm__xfrm_state.c.patch rename to patches/ask/upstream/kernel/0137-net__xfrm__xfrm_state.c.patch diff --git a/patches/ask/upstream/libnetfilter-conntrack/02-libnetfilter-conntrack-do-not-abort-on-unusable-nxp-attrs-v3.patch b/patches/ask/upstream/libnetfilter-conntrack/02-libnetfilter-conntrack-do-not-abort-on-unusable-nxp-attrs-v3.patch new file mode 100644 index 0000000..80e842a --- /dev/null +++ b/patches/ask/upstream/libnetfilter-conntrack/02-libnetfilter-conntrack-do-not-abort-on-unusable-nxp-attrs-v3.patch @@ -0,0 +1,93 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Mono +Date: Mon, 11 May 2026 00:00:00 +0900 +Subject: [PATCH] libnetfilter_conntrack: do not abort on unusable NXP attrs + +The NXP ASK extension patch teaches libnetfilter_conntrack about +Comcerto/Layerscape fast-path and QoS conntrack attributes, but it also +uses abi_breakage() when those attributes are present with a shape this +userspace does not expect. + +That is too fragile for CMM. CMM dumps the global conntrack table, which +can contain ordinary Kubernetes/Cilium conntrack entries alongside entries +that are relevant to the NXP fast path. A single unexpected or +unrepresentable vendor attribute must not abort the entire dump before CMM +has a chance to ignore the entry. + +Keep unsupported attribute IDs ignored as before. For NXP fast-path/QoS +attributes that fail validation or nested parsing, skip only that attribute +or fast-path block and continue parsing the rest of the conntrack object. + +Signed-off-by: Mono +--- + src/conntrack/parse_mnl.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/src/conntrack/parse_mnl.c b/src/conntrack/parse_mnl.c +index 33f7824..0000000 100644 +--- a/src/conntrack/parse_mnl.c ++++ b/src/conntrack/parse_mnl.c +@@ -873,16 +873,16 @@ nfct_parse_comcerto_fp_attr_cb(const struct nlattr *attr, void *data) + case CTA_COMCERTO_FP_IIF: + case CTA_COMCERTO_FP_UNDERLYING_IIF: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) +- abi_breakage(); ++ return MNL_CB_OK; + break; + case CTA_COMCERTO_FP_UNDERLYING_VID: + if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) +- abi_breakage(); ++ return MNL_CB_OK; + break; + case CTA_COMCERTO_FP_XFRM_HANDLE: + /* 4 x u32 = 16 bytes */ + if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC, 16) < 0) +- abi_breakage(); ++ return MNL_CB_OK; + break; + } + tb[type] = attr; +@@ -1024,11 +1024,11 @@ nfct_parse_conntrack_attr_cb(const struct nlattr *attr, void *data) + case CTA_LAYERSCAPE_FP_ORIG: + case CTA_LAYERSCAPE_FP_REPLY: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) +- abi_breakage(); ++ return MNL_CB_OK; + break; + case CTA_QOSCONNMARK: + if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) +- abi_breakage(); ++ return MNL_CB_OK; + break; + } + tb[type] = attr; +@@ -1164,18 +1164,21 @@ nfct_payload_parse(const void *payload, size_t payload_len, + + /* NXP ASK: Comcerto fast path and QoS */ + if (tb[CTA_LAYERSCAPE_FP_ORIG]) { +- if (nfct_parse_comcerto_fp(tb[CTA_LAYERSCAPE_FP_ORIG], ct, +- __DIR_ORIG) < 0) +- return -1; ++ /* ++ * Do not abort the entire conntrack dump if one fast-path ++ * extension block cannot be represented by this userspace. ++ */ ++ nfct_parse_comcerto_fp(tb[CTA_LAYERSCAPE_FP_ORIG], ct, ++ __DIR_ORIG); + } + + if (tb[CTA_LAYERSCAPE_FP_REPLY]) { +- if (nfct_parse_comcerto_fp(tb[CTA_LAYERSCAPE_FP_REPLY], ct, +- __DIR_REPL) < 0) +- return -1; ++ /* See CTA_LAYERSCAPE_FP_ORIG handling above. */ ++ nfct_parse_comcerto_fp(tb[CTA_LAYERSCAPE_FP_REPLY], ct, ++ __DIR_REPL); + } + + if (tb[CTA_QOSCONNMARK]) { + ct->qosconnmark = be64toh(mnl_attr_get_u64(tb[CTA_QOSCONNMARK])); + set_bit(ATTR_QOSCONNMARK, ct->head.set); + } +-- +2.47.3 From 222235fa1c8052829cacc3f706f1517f57ba23bec78519ce0c103b627882bc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Mon, 11 May 2026 07:56:55 +0800 Subject: [PATCH 14/14] Added cmm docs --- README.md | 8 ++ docs/cmm.md | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 328 insertions(+) create mode 100644 docs/cmm.md diff --git a/README.md b/README.md index b27373b..46b3834 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,14 @@ Tested worker node upgrade chain: --- +## CMM + +Based on vendor's ASK + +See: + +- [Running cmm](docs/cmm.md) + ## Current status This project is usable for experimenting with a single control-plane device image, but it is still a development project. diff --git a/docs/cmm.md b/docs/cmm.md new file mode 100644 index 0000000..7596d49 --- /dev/null +++ b/docs/cmm.md @@ -0,0 +1,320 @@ +# CMM integration for monok8s + +This document describes how monok8s runs the vendor Connection Manager daemon (`cmm`) from [ASK](https://github.com/we-are-mono/ASK/) on Kubernetes nodes. + +`cmm` is part of the NXP/ASK hardware-offload stack. In the vendor layout it is normally started as a boot-time service, together with the `cdx` kernel module and `dpa_app`. monok8s intentionally does **not** follow that model. Kubernetes has priority: the node should boot, kubelet should come up, CNI should configure networking, and only then should the CMM stack start from a DaemonSet. + +## Startup model + +The intended startup order is: + +1. The node boots. +2. `kubelet` starts. +3. CNI is configured. +4. The `cmm` DaemonSet starts on the node. +5. The DaemonSet prepares the DPA/CDX runtime and starts `cmm` in the foreground. + +This is different from the vendor flow, where CMM-related components are treated as host services started early during boot. That flow is a poor fit for monok8s because CNI and Kubernetes-owned networking must win any ordering conflict. + +## Local changes from vendor ASK + +monok8s carries a small set of patches so the ASK CMM stack behaves correctly inside a Kubernetes pod. + +### `cmm` + +The `cmm` daemon is patched to: + +- run in the foreground, so it can be supervised directly by Kubernetes; +- log to stdout/stderr, so logs are visible through `kubectl logs`; +- avoid exiting when it sees CNI-managed conntrack entries it does not understand. + +The last item is important. On a Kubernetes node, conntrack is not exclusively owned by CMM. CNI, kubelet, host networking, and ordinary pods can all create conntrack entries. CMM must tolerate that environment. + +### `cdx` kernel module + +The `cdx` module is patched so loading the module does **not** automatically start `dpa_app`. + +In monok8s, module loading and DPA configuration are separate steps. This avoids doing device configuration too early, before Kubernetes networking is ready. + +### `dpa_app` + +`dpa_app` is patched so the XML config paths can be supplied through environment variables: + +- `CDX_CFG_FILE` +- `CDX_PCD_FILE` +- `CDX_PDL_FILE` +- `CDX_SP_FILE` + +This lets the DaemonSet select different XML files per node, board, or port layout without rebuilding the image. + +## Patch locations + +The relevant patch sets are under: + +```text +patches/ask/upstream/libnetfilter-conntrack +patches/ask/cmm +patches/ask/cdx +patches/ask/dpa +``` + +Other ASK patches in the tree are mostly kernel-porting work for the target NXP LSDK kernel, including the 6.18-based kernel used by monok8s. + +## Installation + +CMM is **not installed by default**. Install it explicitly after the node-control components are available. + +With `MKS_ENABLE_NODE_CONTROL` enabled, generate and apply the CMM manifests with: + +```sh +kubectl -n mono-system exec -it ds/node-agent -- ctl create cmm | kubectl apply -f - +``` + +This creates the CMM DaemonSet and the supporting objects required to run it on each matching node. + +Check that the pod is running: + +```sh +kubectl -n mono-system get pods -l app.kubernetes.io/name=cmm -owide +``` + +View logs with: + +```sh +kubectl -n mono-system logs ds/cmm -f +``` + +If the DaemonSet name or labels change, inspect the generated YAML from `ctl create cmm` and use the actual object names. + +## Accessing the CMM CLI + +The CMM CLI is exposed from the pod for debugging and manual inspection. The DaemonSet uses `hostNetwork: true`, but the safest access method is still `kubectl port-forward`; it avoids exposing the CLI beyond your local machine. + +First find a CMM pod: + +```sh +kubectl -n mono-system get pods -l app.kubernetes.io/name=cmm +``` + +Then forward a local port to the CMM CLI port inside the pod. Kubernetes port-forward syntax is `LOCAL_PORT:REMOTE_PORT`. + +For example, if CMM listens on port `12345` in the pod: + +```sh +kubectl -n mono-system port-forward pod/cmm-xxxxx 12345:2103 +``` + +In another terminal, connect to the local forwarded port: + +```sh +telnet 127.0.0.1 12345 +``` + +Use `telnet` for this CLI. Plain `ncat` can show leading garbage characters or behave badly with the login prompt because the CMM CLI behaves like a telnet-style interactive console rather than a clean raw TCP protocol. + +Default login, if unchanged by the generated config, is usually: + +```text +Username: admin +Password: admin +``` + +Do not expose this port through a Service or LoadBalancer unless you have added proper access control. Treat the CMM CLI as an operator/debug interface. + +## Configuration + +`ctl create cmm` emits a default configuration suitable for the expected monok8s hardware layout. You can override the generated YAML before applying it. + +The vendor's original `fastforward` config is preserved in the image as a reference file, but monok8s uses its own runtime config. Keep those roles separate: + +- vendor reference config: useful for comparison and debugging; +- monok8s runtime config: the config actually consumed by the DaemonSet. + +A clear filename for the preserved vendor file is: + +```text +fastforward.vendor.orig +``` + +That name is less project-specific than `fastforward.ask.orig` and makes the intent obvious: it is the original vendor-provided config, not the active config. + +## Multi-node configuration + +If all nodes have the same board and port layout, one shared CMM/DPA config is enough. + +If nodes have different port layouts, use node-specific XML config. The recommended pattern is: + +1. Mount all supported configs into the CMM pod. +2. Pass the Kubernetes node name into the pod. +3. Run a small wrapper script before `dpa_app`. +4. The wrapper selects the XML files for the current node and exports the corresponding `CDX_*` environment variables. +5. The wrapper then execs the normal DPA initialization script. + +Example DaemonSet fragment: + +```yaml +spec: + template: + spec: + initContainers: + - name: dpa-app + image: localhost/monok8s/cmm:dev + imagePullPolicy: Never + command: + - /node-config/select-dpa-config.sh + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: node-config + mountPath: /node-config + readOnly: true + - name: dpa-configs + mountPath: /etc/monok8s/dpa-configs + readOnly: true + volumes: + - name: node-config + configMap: + name: cmm-node-config-wrapper + defaultMode: 0755 + - name: dpa-configs + configMap: + name: cmm-dpa-configs +``` + +Example wrapper: + +```sh +#!/bin/sh +set -eu + +CONFIG_DIR="/etc/monok8s/dpa-configs/${NODE_NAME}" + +if [ ! -d "${CONFIG_DIR}" ]; then + echo "missing DPA config directory for node ${NODE_NAME}: ${CONFIG_DIR}" >&2 + exit 1 +fi + +export CDX_CFG_FILE="${CONFIG_DIR}/cdx_cfg.xml" +export CDX_PCD_FILE="${CONFIG_DIR}/cdx_pcd.xml" +export CDX_PDL_FILE="${CONFIG_DIR}/hxs_pdl_v3.xml" +export CDX_SP_FILE="${CONFIG_DIR}/cdx_sp.xml" + +exec /bin/init_dpa.sh +``` + +The ConfigMap layout should then look like this conceptually: + +```text +/etc/monok8s/dpa-configs/ + node-a/ + cdx_cfg.xml + cdx_pcd.xml + hxs_pdl_v3.xml + cdx_sp.xml + node-b/ + cdx_cfg.xml + cdx_pcd.xml + hxs_pdl_v3.xml + cdx_sp.xml +``` + +For production, prefer a naming scheme based on stable node labels or hardware profiles rather than raw node names if multiple nodes share the same layout. Raw node names are fine for early bring-up, but they do not scale well. + +## Operational notes + +### CMM and Kubernetes conntrack + +Do not assume CMM owns the full conntrack table. Kubernetes nodes contain conntrack entries from: + +- CNI traffic; +- kubelet; +- host-network pods; +- service routing; +- node-local traffic; +- ordinary workloads. + +CMM must tolerate unknown entries. If it exits because it encountered a CNI or Kubernetes conntrack entry, that is a bug in the integration layer, not an operator error. + +### `hostNetwork: true` + +The CMM pod uses `hostNetwork: true` because it needs to interact with host networking and hardware-offload state. This also means any port bound by the pod may be bound in the host network namespace. + +For the CLI, prefer `kubectl port-forward` anyway. It gives you a controlled local tunnel and avoids accidentally publishing the CLI on the node network. + +### `CMM_MAX_CONNECTIONS` + +The default value: + +```sh +CMM_MAX_CONNECTIONS="${CMM_MAX_CONNECTIONS:-131072}" +``` + +uses `131072`, which is `128 * 1024`. It is a power-of-two-sized default commonly used for connection-table limits. Treat it as a capacity default, not a magic correctness value. + +Lower it if memory pressure is a concern. Raise it only if the hardware, memory budget, and expected traffic justify it. + +## Troubleshooting + +### The CMM pod is not running + +Check the DaemonSet and pod events: + +```sh +kubectl -n mono-system get ds cmm -oyaml +kubectl -n mono-system describe pod -l app.kubernetes.io/name=cmm +``` + +Then check logs: + +```sh +kubectl -n mono-system logs ds/cmm --all-containers=true --tail=200 +``` + +### The CLI shows strange characters with `ncat` + +Use `telnet` instead: + +```sh +telnet 127.0.0.1 2103 +``` + +The CMM CLI behaves like a telnet-style console. `ncat --telnet` may still not behave exactly like traditional telnet for this CLI. + +### Port-forward connects to the wrong port + +Remember the syntax: + +```text +LOCAL_PORT:REMOTE_PORT +``` + +So this command: + +```sh +kubectl -n mono-system port-forward pod/cmm-xxxxx 12345:2103 +``` + +means: + +```text +127.0.0.1:12345 on your workstation -> port 2103 inside the pod +``` + +Connect to `127.0.0.1:12345`, not `127.0.0.1:2103`. + +### `dpa_app` uses the wrong XML files + +Confirm the environment seen by the init container or wrapper: + +```sh +kubectl -n mono-system logs pod/cmm-xxxxx -c dpa-app +``` + +The wrapper should print enough information to identify the selected config directory and XML paths. If it does not, add explicit logging before `exec /bin/init_dpa.sh`. + +## Recommended policy + +Keep CMM optional. It is hardware-specific, operationally sharp, and not required for a generic Kubernetes node. The base monok8s node should boot and join the cluster without CMM. Enable CMM only on hardware profiles where the ASK offload stack is expected and tested.