summaryrefslogtreecommitdiff
path: root/scripts/package-build/linux-kernel
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2024-09-08 08:13:39 +0200
committerGitHub <noreply@github.com>2024-09-08 08:13:39 +0200
commit917325fafc9365a722235222f8635653079a5854 (patch)
tree26d03e228ca55acc5fc29d4ad18e8331b79e8605 /scripts/package-build/linux-kernel
parent70122746469e930a6775e0c42c4d1fd30bc6d514 (diff)
parentc9a5a93834fce33f1e999dd50381cb7ff9e5fabb (diff)
downloadvyos-build-917325fafc9365a722235222f8635653079a5854.tar.gz
vyos-build-917325fafc9365a722235222f8635653079a5854.zip
Merge pull request #756 from sever-sever/T6674-circ
T6674: Add build-scrips for packages without Jenkins
Diffstat (limited to 'scripts/package-build/linux-kernel')
-rw-r--r--scripts/package-build/linux-kernel/.gitignore32
-rw-r--r--scripts/package-build/linux-kernel/README.md41
l---------scripts/package-build/linux-kernel/arch1
-rwxr-xr-xscripts/package-build/linux-kernel/build-accel-ppp.sh42
-rwxr-xr-xscripts/package-build/linux-kernel/build-intel-ixgbe.sh107
-rwxr-xr-xscripts/package-build/linux-kernel/build-intel-ixgbevf.sh100
-rwxr-xr-xscripts/package-build/linux-kernel/build-intel-qat.sh111
-rwxr-xr-xscripts/package-build/linux-kernel/build-jool.py98
-rwxr-xr-xscripts/package-build/linux-kernel/build-kernel.sh56
-rwxr-xr-xscripts/package-build/linux-kernel/build-linux-firmware.sh98
-rwxr-xr-xscripts/package-build/linux-kernel/build-nat-rtsp.sh38
-rwxr-xr-xscripts/package-build/linux-kernel/build-openvpn-dco.sh33
-rwxr-xr-xscripts/package-build/linux-kernel/build.py239
-rw-r--r--scripts/package-build/linux-kernel/package.toml62
l---------scripts/package-build/linux-kernel/patches1
15 files changed, 1059 insertions, 0 deletions
diff --git a/scripts/package-build/linux-kernel/.gitignore b/scripts/package-build/linux-kernel/.gitignore
new file mode 100644
index 00000000..0a18ea8c
--- /dev/null
+++ b/scripts/package-build/linux-kernel/.gitignore
@@ -0,0 +1,32 @@
+/linux*
+/wireguard
+/wireguard-linux-compat
+/accel-ppp
+/intel-qat
+/linux-firmware
+/vyos-drivers-intel*
+/vyos-drivers-realtek*
+/ovpn-dco
+/nat-rtsp*
+/jool*
+/qat*
+/QAT*
+*.tar.gz
+*.tar.xz
+/*.postinst
+
+# Intel Driver source
+i40e-*/
+igb-*/
+ixgbe-*/
+ixgbevf-*/
+vyos-intel-*/
+vyos-linux-firmware*/
+kernel-vars
+r8152-*.tar.bz2
+
+*.buildinfo
+*.build
+*.changes
+*.deb
+*.dsc
diff --git a/scripts/package-build/linux-kernel/README.md b/scripts/package-build/linux-kernel/README.md
new file mode 100644
index 00000000..56954e5a
--- /dev/null
+++ b/scripts/package-build/linux-kernel/README.md
@@ -0,0 +1,41 @@
+# Build
+```
+./build.py --config package.toml --packages linux-kernel accel-ppp xxx
+```
+
+# About
+
+VyOS runs on a custom Linux Kernel (which is 4.19) at the time of this writing.
+This repository holds a Jenkins Pipeline which is used to build the Custom
+Kernel (x86_64/amd64 at the moment) and all required out-of tree modules.
+
+VyOS does not utilize the build in Intel Kernel drivers for its NICs as those
+Kernels sometimes lack features e.g. configurable receive-side-scaling queues.
+On the other hand we ship additional not mainlined features as WireGuard VPN.
+
+## Kernel
+
+The Kernel is build from the vanilla repositories hosted at https://git.kernel.org.
+VyOS requires two additional patches to work which are stored in the patches/kernel
+folder.
+
+### Config
+
+The Kernel configuration used is [x86_64_vyos_defconfig](x86_64_vyos_defconfig)
+which will be copied on demand during the Pipeline run into the `arch/x86/configs`i
+direcotry of the Kernel source tree.
+
+Other configurations can be added in the future easily.
+
+### Modules
+
+VyOS utilizes several Out-of-Tree modules (e.g. WireGuard, Accel-PPP and Intel
+network interface card drivers). Module source code is retrieved from the
+upstream repository and - when needed - patched so it can be build using this
+pipeline.
+
+In the past VyOS maintainers had a fork of the Linux Kernel, WireGuard and
+Accel-PPP. This is fine but increases maintenance effort. By utilizing vanilla
+repositories upgrading to new versions is very easy - only the branch/commit/tag
+used when cloning the repository via [Jenkinsfile](Jenkinsfile) needs to be
+adjusted.
diff --git a/scripts/package-build/linux-kernel/arch b/scripts/package-build/linux-kernel/arch
new file mode 120000
index 00000000..f5f81fdc
--- /dev/null
+++ b/scripts/package-build/linux-kernel/arch
@@ -0,0 +1 @@
+../../../packages/linux-kernel/arch \ No newline at end of file
diff --git a/scripts/package-build/linux-kernel/build-accel-ppp.sh b/scripts/package-build/linux-kernel/build-accel-ppp.sh
new file mode 100755
index 00000000..1685ff8d
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build-accel-ppp.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+CWD=$(pwd)
+KERNEL_VAR_FILE=${CWD}/kernel-vars
+
+ACCEL_SRC=${CWD}/accel-ppp
+if [ ! -d ${ACCEL_SRC} ]; then
+ echo "Accel-PPP source not found"
+ exit 1
+fi
+
+if [ ! -f ${KERNEL_VAR_FILE} ]; then
+ echo "Kernel variable file '${KERNEL_VAR_FILE}' does not exist, run ./build_kernel.sh first"
+ exit 1
+fi
+
+PATCH_DIR=${CWD}/patches/accel-ppp
+if [ -d $PATCH_DIR ]; then
+ cd ${ACCEL_SRC}
+ for patch in $(ls ${PATCH_DIR})
+ do
+ echo "I: Apply patch: ${PATCH_DIR}/${patch}"
+ patch -p1 < ${PATCH_DIR}/${patch}
+ done
+fi
+
+. ${KERNEL_VAR_FILE}
+mkdir -p ${ACCEL_SRC}/build
+cd ${ACCEL_SRC}/build
+
+echo "I: Build Accel-PPP Debian package"
+cmake -DBUILD_IPOE_DRIVER=TRUE \
+ -DBUILD_VLAN_MON_DRIVER=TRUE \
+ -DCMAKE_INSTALL_PREFIX=/usr \
+ -DKDIR=${KERNEL_DIR} \
+ -DLUA=5.3 \
+ -DMODULES_KDIR=${KERNEL_VERSION}${KERNEL_SUFFIX} \
+ -DCPACK_TYPE=Debian12 ..
+make
+cpack -G DEB
+
+# rename resulting Debian package according git description
+mv accel-ppp*.deb ${CWD}/accel-ppp_$(git describe --always --tags)_$(dpkg --print-architecture).deb
diff --git a/scripts/package-build/linux-kernel/build-intel-ixgbe.sh b/scripts/package-build/linux-kernel/build-intel-ixgbe.sh
new file mode 100755
index 00000000..5f45c62a
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build-intel-ixgbe.sh
@@ -0,0 +1,107 @@
+#!/bin/sh
+CWD=$(pwd)
+KERNEL_VAR_FILE=${CWD}/kernel-vars
+
+if ! dpkg-architecture -iamd64; then
+ echo "Intel ixgbe is only buildable on amd64 platforms"
+ exit 0
+fi
+
+if [ ! -f ${KERNEL_VAR_FILE} ]; then
+ echo "Kernel variable file '${KERNEL_VAR_FILE}' does not exist, run ./build_kernel.sh first"
+ exit 1
+fi
+
+. ${KERNEL_VAR_FILE}
+
+url="https://sourceforge.net/projects/e1000/files/ixgbe%20stable/5.20.3/ixgbe-5.20.3.tar.gz"
+
+cd ${CWD}
+
+DRIVER_FILE=$(basename ${url} | sed -e s/tar_0/tar/)
+DRIVER_DIR="${DRIVER_FILE%.tar.gz}"
+DRIVER_NAME="ixgbe"
+DRIVER_VERSION=$(echo ${DRIVER_DIR} | awk -F${DRIVER_NAME} '{print $2}' | sed 's/^-//')
+DRIVER_VERSION_EXTRA=""
+
+# Build up Debian related variables required for packaging
+DEBIAN_ARCH=$(dpkg --print-architecture)
+DEBIAN_DIR="${CWD}/vyos-intel-${DRIVER_NAME}_${DRIVER_VERSION}_${DEBIAN_ARCH}"
+DEBIAN_CONTROL="${DEBIAN_DIR}/DEBIAN/control"
+DEBIAN_POSTINST="${CWD}/vyos-intel-ixgbe.postinst"
+
+# Fetch Intel driver source from SourceForge
+if [ -e ${DRIVER_FILE} ]; then
+ rm -f ${DRIVER_FILE}
+fi
+curl -L -o ${DRIVER_FILE} ${url}
+if [ "$?" -ne "0" ]; then
+ exit 1
+fi
+
+# Unpack archive
+if [ -d ${DRIVER_DIR} ]; then
+ rm -rf ${DRIVER_DIR}
+fi
+mkdir -p ${DRIVER_DIR}
+tar -C ${DRIVER_DIR} --strip-components=1 -xf ${DRIVER_FILE}
+
+cd ${DRIVER_DIR}/src
+if [ -z $KERNEL_DIR ]; then
+ echo "KERNEL_DIR not defined"
+ exit 1
+fi
+
+# See https://lore.kernel.org/lkml/f90837d0-810e-5772-7841-28d47c44d260@intel.com/
+echo "I: remove pci_enable_pcie_error_reporting() code no longer present in Kernel"
+sed -i '/.*pci_disable_pcie_error_reporting(pdev);/d' ixgbe_main.c
+sed -i '/.*pci_enable_pcie_error_reporting(pdev);/d' ixgbe_main.c
+
+# See https://vyos.dev/T6155
+echo "I: always enable allow_unsupported_sfp for all NICs by default"
+patch -l -p1 < ../../patches/ixgbe/allow_unsupported_sfp.patch
+
+# See https://vyos.dev/T6162
+echo "I: add 1000BASE-BX support"
+patch -l -p1 < ../../patches/ixgbe/add_1000base-bx_support.patch
+
+echo "I: Compile Kernel module for Intel ${DRIVER_NAME} driver"
+make KSRC=${KERNEL_DIR} INSTALL_MOD_PATH=${DEBIAN_DIR} INSTALL_FW_PATH=${DEBIAN_DIR} -j $(getconf _NPROCESSORS_ONLN) install
+
+if [ "x$?" != "x0" ]; then
+ exit 1
+fi
+
+if [ -f ${DEBIAN_DIR}.deb ]; then
+ rm ${DEBIAN_DIR}.deb
+fi
+
+# build Debian package
+echo "I: Building Debian package vyos-intel-${DRIVER_NAME}"
+cd ${CWD}
+
+# delete non required files which are also present in the kernel package
+# und thus lead to duplicated files
+find ${DEBIAN_DIR} -name "modules.*" | xargs rm -f
+
+echo "#!/bin/sh" > ${DEBIAN_POSTINST}
+echo "/sbin/depmod -a ${KERNEL_VERSION}${KERNEL_SUFFIX}" >> ${DEBIAN_POSTINST}
+
+fpm --input-type dir --output-type deb --name vyos-intel-${DRIVER_NAME} \
+ --version ${DRIVER_VERSION} --deb-compression gz \
+ --maintainer "VyOS Package Maintainers <maintainers@vyos.net>" \
+ --description "Vendor based driver for Intel ${DRIVER_NAME}" \
+ --depends linux-image-${KERNEL_VERSION}${KERNEL_SUFFIX} \
+ --license "GPL2" -C ${DEBIAN_DIR} --after-install ${DEBIAN_POSTINST}
+
+echo "I: Cleanup ${DRIVER_NAME} source"
+cd ${CWD}
+if [ -e ${DRIVER_FILE} ]; then
+ rm -f ${DRIVER_FILE}
+fi
+if [ -d ${DRIVER_DIR} ]; then
+ rm -rf ${DRIVER_DIR}
+fi
+if [ -d ${DEBIAN_DIR} ]; then
+ rm -rf ${DEBIAN_DIR}
+fi
diff --git a/scripts/package-build/linux-kernel/build-intel-ixgbevf.sh b/scripts/package-build/linux-kernel/build-intel-ixgbevf.sh
new file mode 100755
index 00000000..a965e0de
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build-intel-ixgbevf.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+CWD=$(pwd)
+KERNEL_VAR_FILE=${CWD}/kernel-vars
+
+if ! dpkg-architecture -iamd64; then
+ echo "Intel ixgbevf is only buildable on amd64 platforms"
+ exit 0
+fi
+
+if [ ! -f ${KERNEL_VAR_FILE} ]; then
+ echo "Kernel variable file '${KERNEL_VAR_FILE}' does not exist, run ./build_kernel.sh first"
+ exit 1
+fi
+
+. ${KERNEL_VAR_FILE}
+
+url="https://sourceforge.net/projects/e1000/files/ixgbevf%20stable/4.18.9/ixgbevf-4.18.9.tar.gz"
+
+cd ${CWD}
+
+DRIVER_FILE=$(basename ${url} | sed -e s/tar_0/tar/)
+DRIVER_DIR="${DRIVER_FILE%.tar.gz}"
+DRIVER_NAME="ixgbevf"
+DRIVER_VERSION=$(echo ${DRIVER_DIR} | awk -F${DRIVER_NAME} '{print $2}' | sed 's/^-//')
+DRIVER_VERSION_EXTRA=""
+
+# Build up Debian related variables required for packaging
+DEBIAN_ARCH=$(dpkg --print-architecture)
+DEBIAN_DIR="${CWD}/vyos-intel-${DRIVER_NAME}_${DRIVER_VERSION}_${DEBIAN_ARCH}"
+DEBIAN_CONTROL="${DEBIAN_DIR}/DEBIAN/control"
+DEBIAN_POSTINST="${CWD}/vyos-intel-ixgbevf.postinst"
+
+# Fetch Intel driver source from SourceForge
+if [ -e ${DRIVER_FILE} ]; then
+ rm -f ${DRIVER_FILE}
+fi
+curl -L -o ${DRIVER_FILE} ${url}
+if [ "$?" -ne "0" ]; then
+ exit 1
+fi
+
+# Unpack archive
+if [ -d ${DRIVER_DIR} ]; then
+ rm -rf ${DRIVER_DIR}
+fi
+mkdir -p ${DRIVER_DIR}
+tar -C ${DRIVER_DIR} --strip-components=1 -xf ${DRIVER_FILE}
+
+cd ${DRIVER_DIR}/src
+if [ -z $KERNEL_DIR ]; then
+ echo "KERNEL_DIR not defined"
+ exit 1
+fi
+
+# See https://lore.kernel.org/lkml/f90837d0-810e-5772-7841-28d47c44d260@intel.com/
+echo "I: remove pci_enable_pcie_error_reporting() code no longer present in Kernel"
+sed -i '/.*pci_disable_pcie_error_reporting(pdev);/d' ixgbevf_main.c
+sed -i '/.*pci_enable_pcie_error_reporting(pdev);/d' ixgbevf_main.c
+
+echo "I: Compile Kernel module for Intel ${DRIVER_NAME} driver"
+make KSRC=${KERNEL_DIR} INSTALL_MOD_PATH=${DEBIAN_DIR} INSTALL_FW_PATH=${DEBIAN_DIR} -j $(getconf _NPROCESSORS_ONLN) install
+
+if [ "x$?" != "x0" ]; then
+ exit 1
+fi
+
+if [ -f ${DEBIAN_DIR}.deb ]; then
+ rm ${DEBIAN_DIR}.deb
+fi
+
+# build Debian package
+echo "I: Building Debian package vyos-intel-${DRIVER_NAME}"
+cd ${CWD}
+
+# delete non required files which are also present in the kernel package
+# und thus lead to duplicated files
+find ${DEBIAN_DIR} -name "modules.*" | xargs rm -f
+
+echo "#!/bin/sh" > ${DEBIAN_POSTINST}
+echo "/sbin/depmod -a ${KERNEL_VERSION}${KERNEL_SUFFIX}" >> ${DEBIAN_POSTINST}
+
+fpm --input-type dir --output-type deb --name vyos-intel-${DRIVER_NAME} \
+ --version ${DRIVER_VERSION} --deb-compression gz \
+ --maintainer "VyOS Package Maintainers <maintainers@vyos.net>" \
+ --description "Vendor based driver for Intel ${DRIVER_NAME}" \
+ --depends linux-image-${KERNEL_VERSION}${KERNEL_SUFFIX} \
+ --license "GPL2" -C ${DEBIAN_DIR} --after-install ${DEBIAN_POSTINST}
+
+echo "I: Cleanup ${DRIVER_NAME} source"
+cd ${CWD}
+if [ -e ${DRIVER_FILE} ]; then
+ rm -f ${DRIVER_FILE}
+fi
+if [ -d ${DRIVER_DIR} ]; then
+ rm -rf ${DRIVER_DIR}
+fi
+if [ -d ${DEBIAN_DIR} ]; then
+ rm -rf ${DEBIAN_DIR}
+fi
+
diff --git a/scripts/package-build/linux-kernel/build-intel-qat.sh b/scripts/package-build/linux-kernel/build-intel-qat.sh
new file mode 100755
index 00000000..765cea3f
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build-intel-qat.sh
@@ -0,0 +1,111 @@
+#!/bin/sh
+CWD=$(pwd)
+KERNEL_VAR_FILE=${CWD}/kernel-vars
+
+if ! dpkg-architecture -iamd64; then
+ echo "Intel-QAT is only buildable on amd64 platforms"
+ exit 0
+fi
+
+if [ ! -f ${KERNEL_VAR_FILE} ]; then
+ echo "Kernel variable file '${KERNEL_VAR_FILE}' does not exist, run ./build_kernel.sh first"
+ exit 1
+fi
+
+. ${KERNEL_VAR_FILE}
+
+url="https://dev.packages.vyos.net/source-mirror/QAT.L.4.24.0-00005.tar.gz"
+
+cd ${CWD}
+
+DRIVER_FILE=$(basename ${url} | sed -e s/tar_0/tar/)
+DRIVER_DIR="${DRIVER_FILE%.tar.gz}"
+DRIVER_NAME="QAT"
+DRIVER_NAME_EXTRA="L."
+DRIVER_VERSION=$(echo ${DRIVER_DIR} | awk -F${DRIVER_NAME} '{print $2}' | awk -F${DRIVER_NAME_EXTRA} '{print $2}')
+DRIVER_VERSION_EXTRA="-0"
+
+# Build up Debian related variables required for packaging
+DEBIAN_ARCH=$(dpkg --print-architecture)
+DEBIAN_DIR="${CWD}/vyos-intel-${DRIVER_NAME}_${DRIVER_VERSION}${DRIVER_VERSION_EXTRA}_${DEBIAN_ARCH}"
+DEBIAN_CONTROL="${DEBIAN_DIR}/DEBIAN/control"
+DEBIAN_POSTINST="${CWD}/vyos-intel-qat.postinst"
+
+# Fetch Intel driver source from SourceForge
+if [ -e ${DRIVER_FILE} ]; then
+ rm -f ${DRIVER_FILE}
+fi
+curl -L -o ${DRIVER_FILE} ${url}
+if [ "$?" -ne "0" ]; then
+ exit 1
+fi
+
+# Unpack archive
+if [ -d ${DRIVER_DIR} ]; then
+ rm -rf ${DRIVER_DIR}
+fi
+mkdir -p ${DRIVER_DIR}
+tar -C ${DRIVER_DIR} -xf ${DRIVER_FILE}
+
+cd ${DRIVER_DIR}
+if [ -z $KERNEL_DIR ]; then
+ echo "KERNEL_DIR not defined"
+ exit 1
+fi
+
+echo "I: Compile Kernel module for Intel ${DRIVER_NAME} driver"
+mkdir -p \
+ ${DEBIAN_DIR}/lib/firmware \
+ ${DEBIAN_DIR}/usr/sbin \
+ ${DEBIAN_DIR}/usr/lib/x86_64-linux-gnu \
+ ${DEBIAN_DIR}/etc/init.d
+KERNEL_SOURCE_ROOT=${KERNEL_DIR} ./configure --enable-kapi --enable-qat-lkcf
+make -j $(getconf _NPROCESSORS_ONLN) all
+make INSTALL_MOD_PATH=${DEBIAN_DIR} INSTALL_FW_PATH=${DEBIAN_DIR} \
+ qat-driver-install adf-ctl-all
+
+if [ "x$?" != "x0" ]; then
+ exit 1
+fi
+
+cp quickassist/qat/fw/*.bin ${DEBIAN_DIR}/lib/firmware
+cp build/*.so ${DEBIAN_DIR}/usr/lib/x86_64-linux-gnu
+cp build/adf_ctl ${DEBIAN_DIR}/usr/sbin
+cp quickassist/build_system/build_files/qat_service ${DEBIAN_DIR}/etc/init.d
+cp build/usdm_drv.ko ${DEBIAN_DIR}/lib/modules/${KERNEL_VERSION}${KERNEL_SUFFIX}/updates/drivers
+chmod 644 ${DEBIAN_DIR}/lib/firmware/*
+chmod 755 ${DEBIAN_DIR}/etc/init.d/* ${DEBIAN_DIR}/usr/local/bin/*
+
+if [ -f ${DEBIAN_DIR}.deb ]; then
+ rm ${DEBIAN_DIR}.deb
+fi
+
+# build Debian package
+echo "I: Building Debian package vyos-intel-${DRIVER_NAME}"
+cd ${CWD}
+
+# delete non required files which are also present in the kernel package
+# und thus lead to duplicated files
+find ${DEBIAN_DIR} -name "modules.*" | xargs rm -f
+
+echo "#!/bin/sh" > ${DEBIAN_POSTINST}
+echo "/sbin/depmod -a ${KERNEL_VERSION}${KERNEL_SUFFIX}" >> ${DEBIAN_POSTINST}
+
+fpm --input-type dir --output-type deb --name vyos-intel-${DRIVER_NAME} \
+ --version ${DRIVER_VERSION}${DRIVER_VERSION_EXTRA} --deb-compression gz \
+ --maintainer "VyOS Package Maintainers <maintainers@vyos.net>" \
+ --description "Vendor based driver for Intel ${DRIVER_NAME}" \
+ --depends linux-image-${KERNEL_VERSION}${KERNEL_SUFFIX} \
+ --license "GPL2" -C ${DEBIAN_DIR} --after-install ${DEBIAN_POSTINST}
+
+echo "I: Cleanup ${DRIVER_NAME} source"
+cd ${CWD}
+if [ -e ${DRIVER_FILE} ]; then
+ rm -f ${DRIVER_FILE}
+fi
+if [ -d ${DRIVER_DIR} ]; then
+ rm -rf ${DRIVER_DIR}
+fi
+if [ -d ${DEBIAN_DIR} ]; then
+ rm -rf ${DEBIAN_DIR}
+fi
diff --git a/scripts/package-build/linux-kernel/build-jool.py b/scripts/package-build/linux-kernel/build-jool.py
new file mode 100755
index 00000000..570293f5
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build-jool.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+
+from tomllib import loads as toml_loads
+from requests import get
+from pathlib import Path
+from subprocess import run
+
+def find_arch() -> str:
+ tmp=run(['dpkg-architecture', '-q', 'DEB_HOST_ARCH'], capture_output=True)
+ return tmp.stdout.decode().strip()
+
+# dependency modifier
+def add_depends(package_dir: str, package_name: str,
+ depends: list[str]) -> None:
+ """Add dependencies to a package
+
+ Args:
+ package_dir (str): a directory where package sources are located
+ package_name (str): a name of package
+ depends (list[str]): a list of dependencies to add
+ """
+ depends_list: str = ', '.join(depends)
+ depends_line: str = f'misc:Depends={depends_list}\n'
+
+ substvars_file = Path(f'{package_dir}/debian/{package_name}.substvars')
+ substvars_file.write_text(depends_line)
+
+
+# find kernel version and source path
+arch: str = find_arch()
+defaults_file: str = Path('../../../data/defaults.toml').read_text()
+architecture_file: str = Path(f'../../../data/architectures/{arch}.toml').read_text()
+KERNEL_VER: str = toml_loads(defaults_file).get('kernel_version')
+KERNEL_FLAVOR: str = toml_loads(architecture_file).get('kernel_flavor')
+KERNEL_SRC: str = Path.cwd().as_posix() + '/linux'
+
+# define variables
+PACKAGE_NAME: str = 'jool'
+PACKAGE_VERSION: str = '4.1.9+bf4c7e3669'
+PACKAGE_DIR: str = f'{PACKAGE_NAME}-{PACKAGE_VERSION}'
+SOURCES_ARCHIVE: str = 'jool-4.1.9+bf4c7e3669.tar.gz'
+SOURCES_URL: str = f'https://github.com/NICMx/Jool/archive/7f08c42c615ed63cf0fdc1522d91aa0809f6d990.tar.gz'
+
+# download sources
+sources_archive = Path(SOURCES_ARCHIVE)
+sources_archive.write_bytes(get(SOURCES_URL).content)
+
+# prepare sources
+debmake_cmd: list[str] = [
+ 'debmake', '-e', 'support@vyos.io', '-f', 'VyOS Support', '-p',
+ PACKAGE_NAME, '-u', PACKAGE_VERSION, '-a', SOURCES_ARCHIVE
+]
+run(debmake_cmd)
+
+# add kernel to dependencies
+add_depends(PACKAGE_DIR, PACKAGE_NAME,
+ [f'linux-image-{KERNEL_VER}-{KERNEL_FLAVOR}'])
+
+# configure build rules
+build_rules_text: str = f'''#!/usr/bin/make -f
+# config
+export KERNEL_DIR := {KERNEL_SRC}
+PACKAGE_BUILD_DIR := debian/{PACKAGE_NAME}
+KVER := {KERNEL_VER}-{KERNEL_FLAVOR}
+MODULES_DIR := extra
+
+# main packaging script based on dh7 syntax
+%:
+ dh $@
+
+override_dh_clean:
+ dh_clean --exclude=debian/{PACKAGE_NAME}.substvars
+
+override_dh_prep:
+ dh_prep --exclude=debian/{PACKAGE_NAME}.substvars
+
+# override_dh_auto_clean:
+# make -C src/mod clean
+
+override_dh_auto_build:
+ dh_auto_build $@
+ make -C ${{KERNEL_DIR}} M=$$PWD/src/mod/common modules
+ make -C ${{KERNEL_DIR}} M=$$PWD/src/mod/nat64 modules
+ make -C ${{KERNEL_DIR}} M=$$PWD/src/mod/siit modules
+
+override_dh_auto_install:
+ dh_auto_install $@
+ install -D -m 644 src/mod/common/jool_common.ko ${{PACKAGE_BUILD_DIR}}/lib/modules/${{KVER}}/${{MODULES_DIR}}/jool_common.ko
+ install -D -m 644 src/mod/nat64/jool.ko ${{PACKAGE_BUILD_DIR}}/lib/modules/${{KVER}}/${{MODULES_DIR}}/jool.ko
+ install -D -m 644 src/mod/siit/jool_siit.ko ${{PACKAGE_BUILD_DIR}}/lib/modules/${{KVER}}/${{MODULES_DIR}}/jool_siit.ko
+
+'''
+bild_rules = Path(f'{PACKAGE_DIR}/debian/rules')
+bild_rules.write_text(build_rules_text)
+
+# build a package
+debuild_cmd: list[str] = ['debuild']
+run(debuild_cmd, cwd=PACKAGE_DIR)
diff --git a/scripts/package-build/linux-kernel/build-kernel.sh b/scripts/package-build/linux-kernel/build-kernel.sh
new file mode 100755
index 00000000..2c02f5c3
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build-kernel.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+CWD=$(pwd)
+KERNEL_SRC=linux
+
+set -e
+
+if [ ! -d ${KERNEL_SRC} ]; then
+ echo "Linux Kernel source directory does not exists, please 'git clone'"
+ exit 1
+fi
+
+echo "I: Copy Kernel config (x86_64_vyos_defconfig) to Kernel Source"
+cp -rv arch/ ${KERNEL_SRC}/
+
+cd ${KERNEL_SRC}
+
+echo "I: clean modified files"
+git reset --hard HEAD
+
+KERNEL_VERSION=$(make kernelversion)
+KERNEL_SUFFIX=-$(dpkg --print-architecture)-vyos
+
+# VyOS requires some small Kernel Patches - apply them here
+# It's easier to habe them here and make use of the upstream
+# repository instead of maintaining a full Kernel Fork.
+# Saving time/resources is essential :-)
+PATCH_DIR=${CWD}/patches/kernel
+for patch in $(ls ${PATCH_DIR})
+do
+ echo "I: Apply Kernel patch: ${PATCH_DIR}/${patch}"
+ patch -p1 < ${PATCH_DIR}/${patch}
+done
+
+echo "I: make vyos_defconfig"
+# Select Kernel configuration - currently there is only one
+make vyos_defconfig
+
+echo "I: Generate environment file containing Kernel variable"
+cat << EOF >${CWD}/kernel-vars
+#!/bin/sh
+export KERNEL_VERSION=${KERNEL_VERSION}
+export KERNEL_SUFFIX=${KERNEL_SUFFIX}
+export KERNEL_DIR=${CWD}/${KERNEL_SRC}
+EOF
+
+echo "I: Build Debian Kernel package"
+touch .scmversion
+make bindeb-pkg BUILD_TOOLS=1 LOCALVERSION=${KERNEL_SUFFIX} KDEB_PKGVERSION=${KERNEL_VERSION}-1 -j $(getconf _NPROCESSORS_ONLN)
+
+cd $CWD
+if [[ $? == 0 ]]; then
+ for package in $(ls linux-*.deb)
+ do
+ ln -sf linux-kernel/$package ..
+ done
+fi
diff --git a/scripts/package-build/linux-kernel/build-linux-firmware.sh b/scripts/package-build/linux-kernel/build-linux-firmware.sh
new file mode 100755
index 00000000..2b1fa7b7
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build-linux-firmware.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+
+# All selected drivers are then precomfiled "make drivers/foo/bar.i" and we grep for
+# the magic word "UNIQUE_ID_firmware" which identifies firmware files.
+
+CWD=$(pwd)
+LINUX_SRC="linux"
+LINUX_FIRMWARE="linux-firmware"
+KERNEL_VAR_FILE=${CWD}/kernel-vars
+
+if [ ! -d ${LINUX_SRC} ]; then
+ echo "Kernel source missing"
+ exit 1
+fi
+
+if [ ! -d ${LINUX_FIRMWARE} ]; then
+ echo "Linux firmware repository missing"
+ exit 1
+fi
+
+. ${KERNEL_VAR_FILE}
+
+result=()
+# Retrieve firmware blobs from source files
+FW_FILES=$(find ${LINUX_SRC}/debian/linux-image/lib/modules/${KERNEL_VERSION}${KERNEL_SUFFIX}/kernel/drivers/net -name *.ko | xargs modinfo | grep "^firmware:" | awk '{print $2}')
+
+# Debian package will use the descriptive Git commit as version
+GIT_COMMIT=$(cd ${CWD}/${LINUX_FIRMWARE}; git describe --always)
+VYOS_FIRMWARE_NAME="vyos-linux-firmware"
+VYOS_FIRMWARE_DIR="${VYOS_FIRMWARE_NAME}_${GIT_COMMIT}-0_all"
+if [ -d ${VYOS_FIRMWARE_DIR} ]; then
+ # remove Debian package folder and deb file from previous runs
+ rm -rf ${VYOS_FIRMWARE_DIR}*
+fi
+mkdir -p ${VYOS_FIRMWARE_DIR}
+
+# Install firmware files to build directory
+LINUX_FIRMWARE_BUILD_DIR="${LINUX_FIRMWARE}_${GIT_COMMIT}"
+
+if [ -d ${LINUX_FIRMWARE_BUILD_DIR} ]; then
+ rm -rf "${LINUX_FIRMWARE_BUILD_DIR}"
+fi
+
+mkdir -p "${LINUX_FIRMWARE_BUILD_DIR}"
+
+(
+ cd ${LINUX_FIRMWARE}
+ ./copy-firmware.sh "${CWD}/${LINUX_FIRMWARE_BUILD_DIR}"
+)
+
+# Copy firmware file from linux firmware build directory into
+# assembly folder for the vyos-firmware package
+SED_REPLACE="s@${CWD}/${LINUX_FIRMWARE}/@@"
+for FILE_PATTERN in ${FW_FILES}; do
+ find "${LINUX_FIRMWARE_BUILD_DIR}" -path "*/${FILE_PATTERN}" -print0 | while IFS= read -r -d $'\0' FILE; do
+ TARGET="$(echo "${FILE}" | sed "s/${LINUX_FIRMWARE_BUILD_DIR}\///g")"
+ TARGET_DIR="${VYOS_FIRMWARE_DIR}/lib/firmware/$(dirname "${TARGET}")"
+ # If file is a symlink install the symlink target as well
+ if [ -h "${FILE}" ]; then
+ if [ ! -f "${TARGET_DIR}/$(basename "${TARGET}")" ]; then
+ if [ -f "${LINUX_FIRMWARE_BUILD_DIR}/${TARGET}" ]; then
+ mkdir -p "${TARGET_DIR}"
+
+ echo "I: install firmware: ${TARGET}"
+ cp "${CWD}/${LINUX_FIRMWARE_BUILD_DIR}/${TARGET}" "${TARGET_DIR}"
+ # If file links to other folder which this script not cover. Create folder and copy together.
+ if [ -L "${LINUX_FIRMWARE_BUILD_DIR}/${TARGET}" ]; then
+ REALPATH_TARGET=$(realpath --relative-to="${CWD}/${LINUX_FIRMWARE_BUILD_DIR}" "${CWD}/${LINUX_FIRMWARE_BUILD_DIR}/${TARGET}")
+ REALPATH_TARGET_DIR="${VYOS_FIRMWARE_DIR}/lib/firmware/$(dirname "${REALPATH_TARGET}")"
+ mkdir -p "${REALPATH_TARGET_DIR}"
+ echo "I: install firmware: ${REALPATH_TARGET}"
+ cp "${CWD}/${LINUX_FIRMWARE_BUILD_DIR}/${REALPATH_TARGET}" "${REALPATH_TARGET_DIR}"
+ fi
+ else
+ echo "I: firmware file not found: ${TARGET}"
+ fi
+ fi
+ fi
+
+ if [ -f "${FILE}" ]; then
+ mkdir -p "${TARGET_DIR}"
+ echo "I: install firmware: ${TARGET}"
+ cp -P "${CWD}/${LINUX_FIRMWARE_BUILD_DIR}/${TARGET}" "${TARGET_DIR}"
+ else
+ echo "I: firmware file not found: ${TARGET}"
+ fi
+ done
+done
+
+echo "I: Create linux-firmware package"
+rm -f ${VYOS_FIRMWARE_NAME}_*.deb
+fpm --input-type dir --output-type deb --name ${VYOS_FIRMWARE_NAME} \
+ --maintainer "VyOS Package Maintainers <maintainers@vyos.net>" \
+ --description "Binary firmware for various drivers in the Linux kernel" \
+ --architecture all --version ${GIT_COMMIT} --deb-compression gz -C ${VYOS_FIRMWARE_DIR}
+
+rm -rf "${LINUX_FIRMWARE_BUILD_DIR}"
+rm -rf ${VYOS_FIRMWARE_DIR}
diff --git a/scripts/package-build/linux-kernel/build-nat-rtsp.sh b/scripts/package-build/linux-kernel/build-nat-rtsp.sh
new file mode 100755
index 00000000..ec7d19a6
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build-nat-rtsp.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+CWD=$(pwd)
+KERNEL_VAR_FILE=${CWD}/kernel-vars
+
+SRC=${CWD}/nat-rtsp
+if [ ! -d ${SRC} ]; then
+ echo "nat-rtsp source not found"
+ exit 1
+fi
+
+if [ ! -f ${KERNEL_VAR_FILE} ]; then
+ echo "Kernel variable file '${KERNEL_VAR_FILE}' does not exist, run ./build_kernel.sh first"
+ exit 1
+fi
+
+. ${KERNEL_VAR_FILE}
+
+cd ${SRC} && make KERNELDIR=$KERNEL_DIR
+
+# Copy binary to package directory
+DEBIAN_DIR=tmp/lib/modules/${KERNEL_VERSION}${KERNEL_SUFFIX}/extra
+mkdir -p ${DEBIAN_DIR}
+cp nf_conntrack_rtsp.ko nf_nat_rtsp.ko ${DEBIAN_DIR}
+
+DEBIAN_POSTINST="${CWD}/vyos-nat-rtsp.postinst"
+echo "#!/bin/sh" > ${DEBIAN_POSTINST}
+echo "/sbin/depmod -a ${KERNEL_VERSION}${KERNEL_SUFFIX}" >> ${DEBIAN_POSTINST}
+
+# Build Debian Package
+fpm --input-type dir --output-type deb --name nat-rtsp \
+ --version $(git describe --tags --always) --deb-compression gz \
+ --maintainer "VyOS Package Maintainers <maintainers@vyos.net>" \
+ --description "Connection tracking and NAT support for RTSP" \
+ --depends linux-image-${KERNEL_VERSION}${KERNEL_SUFFIX} \
+ --after-install ${DEBIAN_POSTINST} \
+ --license "GPL2" --chdir tmp
+
+mv *.deb ..
diff --git a/scripts/package-build/linux-kernel/build-openvpn-dco.sh b/scripts/package-build/linux-kernel/build-openvpn-dco.sh
new file mode 100755
index 00000000..fd427825
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build-openvpn-dco.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+CWD=$(pwd)
+KERNEL_VAR_FILE=${CWD}/kernel-vars
+
+SRC=${CWD}/ovpn-dco
+if [ ! -d ${SRC} ]; then
+ echo "OpenVPN DCO source not found"
+ exit 1
+fi
+
+if [ ! -f ${KERNEL_VAR_FILE} ]; then
+ echo "Kernel variable file '${KERNEL_VAR_FILE}' does not exist, run ./build_kernel.sh first"
+ exit 1
+fi
+
+. ${KERNEL_VAR_FILE}
+
+cd ${SRC} && make KERNEL_SRC=$KERNEL_DIR
+
+# Copy binary to package directory
+DEBIAN_DIR=tmp/lib/modules/${KERNEL_VERSION}${KERNEL_SUFFIX}/extra
+mkdir -p ${DEBIAN_DIR}
+cp drivers/net/ovpn-dco/ovpn-dco-v2.ko ${DEBIAN_DIR}
+
+# Build Debian Package
+fpm --input-type dir --output-type deb --name openvpn-dco \
+ --version $(git describe | sed s/^v//) --deb-compression gz \
+ --maintainer "VyOS Package Maintainers <maintainers@vyos.net>" \
+ --description "OpenVPN Data Channel Offload" \
+ --depends linux-image-${KERNEL_VERSION}${KERNEL_SUFFIX} \
+ --license "GPL2" --chdir tmp
+
+mv *.deb ..
diff --git a/scripts/package-build/linux-kernel/build.py b/scripts/package-build/linux-kernel/build.py
new file mode 100755
index 00000000..1bcab686
--- /dev/null
+++ b/scripts/package-build/linux-kernel/build.py
@@ -0,0 +1,239 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import datetime
+import glob
+import shutil
+import toml
+import os
+import subprocess
+
+from argparse import ArgumentParser
+from pathlib import Path
+from subprocess import run, CalledProcessError
+
+# Relative path to defaults.toml
+defaults_path = "../../../data/defaults.toml"
+
+
+def ensure_dependencies(dependencies: list) -> None:
+ """Ensure Debian build dependencies are met"""
+ if not dependencies:
+ print("I: No additional dependencies to install")
+ return
+
+ print("I: Ensure Debian build dependencies are met")
+ run(['sudo', 'apt-get', 'install', '-y'] + dependencies, check=True)
+
+
+def prepare_package(repo_dir: Path, install_data: str) -> None:
+ """Prepare a package"""
+ if not install_data:
+ print("I: No install data provided, skipping package preparation")
+ return
+
+ install_file = repo_dir / 'debian/install'
+ install_file.parent.mkdir(parents=True, exist_ok=True)
+ install_file.write_text(install_data)
+ print("I: Prepared package")
+
+
+def clone_or_update_repo(repo_dir: Path, scm_url: str, commit_id: str) -> None:
+ """Clone the repository if it does not exist, otherwise update it"""
+ if repo_dir.exists():
+ #run(['git', 'fetch'], cwd=repo_dir, check=True)
+ run(['git', 'checkout', commit_id], cwd=repo_dir, check=True)
+ #run(['git', 'pull'], cwd=repo_dir, check=True)
+ else:
+ run(['git', 'clone', scm_url, str(repo_dir)], check=True)
+ run(['git', 'checkout', commit_id], cwd=repo_dir, check=True)
+
+
+def build_package(package: dict, dependencies: list) -> None:
+ """Build a package from the repository
+
+ Args:
+ package (dict): Package information
+ dependencies (list): List of additional dependencies
+ """
+ timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
+ repo_name = package['name']
+ repo_dir = Path(repo_name)
+
+ try:
+ # Clone or update the repository
+ #clone_or_update_repo(repo_dir, package['scm_url'], package['commit_id'])
+
+ # Ensure dependencies
+ #ensure_dependencies(dependencies)
+
+ # Prepare the package if required
+ #if package.get('prepare_package', False):
+ # prepare_package(repo_dir, package.get('install_data', ''))
+
+ # Execute the build command
+ if package['build_cmd'] == 'build_kernel':
+ build_kernel(package['kernel_version'])
+ elif package['build_cmd'] == 'build_linux_firmware':
+ build_linux_firmware(package['commit_id'], package['scm_url'])
+ elif package['build_cmd'] == 'build_accel_ppp':
+ build_accel_ppp(package['commit_id'], package['scm_url'])
+ elif package['build_cmd'] == 'build_intel_qat':
+ build_intel_qat()
+ elif package['build_cmd'] == 'build_intel_ixgbe':
+ build_intel_ixgbe()
+ elif package['build_cmd'] == 'build_intel_ixgbevf':
+ build_intel_ixgbevf()
+ elif package['build_cmd'] == 'build_jool':
+ build_jool()
+ elif package['build_cmd'] == 'build_openvpn_dco':
+ build_openvpn_dco(package['commit_id'], package['scm_url'])
+ elif package['build_cmd'] == 'build_nat_rtsp':
+ build_nat_rtsp(package['commit_id'], package['scm_url'])
+ else:
+ run(package['build_cmd'], cwd=repo_dir, check=True, shell=True)
+
+ except CalledProcessError as e:
+ print(f"Failed to build package {repo_name}: {e}")
+ finally:
+ # Clean up repository directory
+ # shutil.rmtree(repo_dir, ignore_errors=True)
+ pass
+
+
+def cleanup_build_deps(repo_dir: Path) -> None:
+ """Clean up build dependency packages"""
+ try:
+ if repo_dir.exists():
+ for file in glob.glob(str(repo_dir / '*build-deps*.deb')):
+ os.remove(file)
+ print("Cleaned up build dependency packages")
+ except Exception as e:
+ print(f"Error cleaning up build dependencies: {e}")
+
+
+def copy_packages(repo_dir: Path) -> None:
+ """Copy generated .deb packages to the parent directory"""
+ try:
+ deb_files = glob.glob(str(repo_dir / '*.deb'))
+ for deb_file in deb_files:
+ shutil.copy(deb_file, repo_dir.parent)
+ print("Copied generated .deb packages")
+ except Exception as e:
+ print(f"Error copying packages: {e}")
+
+
+def merge_dicts(defaults, package):
+ return {**defaults, **package}
+
+
+def build_kernel(kernel_version):
+ """Build the Linux kernel"""
+ run(['gpg2', '--locate-keys', 'torvalds@kernel.org', 'gregkh@kernel.org'], check=True)
+ run(['curl', '-OL', f'https://www.kernel.org/pub/linux/kernel/v6.x/linux-{kernel_version}.tar.xz'], check=True)
+ run(['curl', '-OL', f'https://www.kernel.org/pub/linux/kernel/v6.x/linux-{kernel_version}.tar.sign'], check=True)
+ # Using pipes to handle decompression and verification
+ with subprocess.Popen(['xz', '-cd', f'linux-{kernel_version}.tar.xz'], stdout=subprocess.PIPE) as proc_xz:
+ run(['gpg2', '--verify', f'linux-{kernel_version}.tar.sign', '-'], stdin=proc_xz.stdout, check=True)
+ run(['tar', 'xf', f'linux-{kernel_version}.tar.xz'], check=True)
+ os.symlink(f'linux-{kernel_version}', 'linux')
+ run(['./build-kernel.sh'], check=True)
+
+
+def build_linux_firmware(commit_id, scm_url):
+ """Build Linux firmware"""
+ repo_dir = Path('linux-firmware')
+ clone_or_update_repo(repo_dir, scm_url, commit_id)
+ run(['./build-linux-firmware.sh'], check=True)
+
+
+def build_accel_ppp(commit_id, scm_url):
+ """Build accel-ppp"""
+ repo_dir = Path('accel-ppp')
+ clone_or_update_repo(repo_dir, scm_url, commit_id)
+ run(['./build-accel-ppp.sh'], check=True)
+
+
+def build_intel_qat():
+ """Build Intel QAT"""
+ run(['./build-intel-qat.sh'], check=True)
+
+
+def build_intel_ixgbe():
+ """Build Intel IXGBE"""
+ run(['./build-intel-ixgbe.sh'], check=True)
+
+
+def build_intel_ixgbevf():
+ """Build Intel IXGBEVF"""
+ run(['./build-intel-ixgbevf.sh'], check=True)
+
+
+def build_jool():
+ """Build Jool"""
+ run(['echo y | ./build-jool.py'], check=True, shell=True)
+
+
+def build_openvpn_dco(commit_id, scm_url):
+ """Build OpenVPN DCO"""
+ repo_dir = Path('ovpn-dco')
+ clone_or_update_repo(repo_dir, scm_url, commit_id)
+ run(['./build-openvpn-dco.sh'], check=True)
+
+
+def build_nat_rtsp(commit_id, scm_url):
+ """Build RTSP netfilter helper"""
+ repo_dir = Path('nat-rtsp')
+ clone_or_update_repo(repo_dir, scm_url, commit_id)
+ run(['./build-nat-rtsp.sh'], check=True)
+
+
+if __name__ == '__main__':
+ # Prepare argument parser
+ arg_parser = ArgumentParser()
+ arg_parser.add_argument('--config', default='package.toml', help='Path to the package configuration file')
+ arg_parser.add_argument('--packages', nargs='+', help='Names of packages to build (default: all)', default=[])
+ args = arg_parser.parse_args()
+
+ # Load package configuration
+ with open(args.config, 'r') as file:
+ config = toml.load(file)
+
+ # Extract defaults and packages
+ with open(defaults_path, 'r') as file:
+ defaults = toml.load(file)
+
+ packages = config['packages']
+
+ # Filter packages if specific packages are specified in the arguments
+ if args.packages:
+ packages = [pkg for pkg in packages if pkg['name'] in args.packages]
+
+ # Merge defaults into each package
+ packages = [merge_dicts(defaults, pkg) for pkg in packages]
+
+ for package in packages:
+ dependencies = package.get('dependencies', {}).get('packages', [])
+
+ # Build the package
+ build_package(package, dependencies)
+
+ # Clean up build dependency packages after build
+ cleanup_build_deps(Path(package['name']))
+
+ # Copy generated .deb packages to parent directory
+ copy_packages(Path(package['name']))
diff --git a/scripts/package-build/linux-kernel/package.toml b/scripts/package-build/linux-kernel/package.toml
new file mode 100644
index 00000000..8b030da0
--- /dev/null
+++ b/scripts/package-build/linux-kernel/package.toml
@@ -0,0 +1,62 @@
+# [defaults]
+# We get the kernel_version from vyos-build/data/defaults.toml
+# kernel_version = "6.6.47"
+# kernel_flavor = "amd64-vyos"
+
+
+[[packages]]
+name = "linux-kernel"
+commit_id = "" # Uses defaults.kernel_version
+scm_url = ""
+build_cmd = "build_kernel"
+
+[[packages]]
+name = "linux-firmware"
+commit_id = "20240610"
+scm_url = "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git"
+build_cmd = "build_linux_firmware"
+
+[[packages]]
+name = "accel-ppp"
+commit_id = "1.13.0"
+scm_url = "https://github.com/accel-ppp/accel-ppp.git"
+build_cmd = "build_accel_ppp"
+
+
+[[packages]]
+name = "ovpn-dco"
+commit_id = "v0.2.20231117"
+scm_url = "https://github.com/OpenVPN/ovpn-dco"
+build_cmd = "build_openvpn_dco"
+
+[[packages]]
+name = "nat-rtsp"
+commit_id = "475af0a"
+scm_url = "https://github.com/maru-sama/rtsp-linux.git"
+build_cmd = "build_nat_rtsp"
+
+
+[[packages]]
+name = "qat"
+commit_id = ""
+scm_url = ""
+build_cmd = "build_intel_qat"
+
+[[packages]]
+name = "ixgbe"
+commit_id = ""
+scm_url = ""
+build_cmd = "build_intel_ixgbe"
+
+[[packages]]
+name = "ixgbevf"
+commit_id = ""
+scm_url = ""
+build_cmd = "build_intel_ixgbevf"
+
+[[packages]]
+name = "jool"
+commit_id = ""
+scm_url = ""
+build_cmd = "build_jool"
+
diff --git a/scripts/package-build/linux-kernel/patches b/scripts/package-build/linux-kernel/patches
new file mode 120000
index 00000000..fd016d35
--- /dev/null
+++ b/scripts/package-build/linux-kernel/patches
@@ -0,0 +1 @@
+../../../packages/linux-kernel/patches \ No newline at end of file