This commit is contained in:
2022-02-21 16:45:30 -05:00
parent 820d56232e
commit bd8a102b4d
3 changed files with 258 additions and 236 deletions

5
.vscode/launch.json vendored
View File

@@ -12,10 +12,7 @@
"program": "${file}", "program": "${file}",
"args": [ "args": [
"-d", "-d",
"-p", "-p", "r4s"
"r4s",
"--ssh-backup",
"root@router.lan"
] ]
} }
] ]

View File

@@ -1,11 +1,12 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# #
# Copyright 2022 Bryan C. Roessler
#
# Build and flash/upgrade OpenWRT devices # Build and flash/upgrade OpenWRT devices
# #
# Apache 2.0 License # Apache 2.0 License
printHelpAndExit() { printHelp() {
debug "${FUNCNAME[0]}" debug "${FUNCNAME[0]}"
cat <<-'EOF' cat <<-'EOF'
@@ -27,17 +28,14 @@ OPTIONS
--flash, -f DEVICE --flash, -f DEVICE
Example: /dev/sdX Example: /dev/sdX
--reset --reset
CLeanup all source and output files Cleanup all source and output files
--debug, -d --debug, -d
--help, -h --help, -h
EOF EOF
# Exit using passed exit code
[[ -z $1 ]] && exit 0 || exit "$1"
} }
input() { readInput() {
debug "${FUNCNAME[0]}" debug "${FUNCNAME[0]}"
unset RESET unset RESET
@@ -53,9 +51,9 @@ input() {
shift && PROFILE="$1" shift && PROFILE="$1"
;; ;;
--info|-i) --info|-i)
shift && profileInfo "$1" && exit $? shift && PROFILE="$1" && PROFILE_INFO=1 && exit $?
;; ;;
--list-profile|-l) --list-profiles|-l)
listProfiles && exit $? listProfiles && exit $?
;; ;;
--builddir|-b) --builddir|-b)
@@ -71,14 +69,14 @@ input() {
shift && FLASH_DEV="$1" shift && FLASH_DEV="$1"
;; ;;
--reset) --reset)
RESET=true RESET=1
;; ;;
--debug|-d) --debug|-d)
echo "Debugging on" echo "Debugging on"
DEBUG=true DEBUG=1
;; ;;
--help|-h) --help|-h)
printHelpAndExit 0 printHelp && exit 0
;; ;;
--) --)
shift shift
@@ -89,182 +87,18 @@ input() {
done done
else else
echo "Incorrect options provided" echo "Incorrect options provided"
printHelpAndExit 1 printHelp && exit 1
fi fi
} }
profiles() {
debug "${FUNCNAME[0]}"
# Additional packages to install for all profiles
default_packages="\
luci \
luci-ssl \
nano \
htop \
tcpdump \
diffutils \
tar \
iperf \
bash \
rsync " # Leave trailing whitespace
# Set the default release
[[ -z $RELEASE ]] && RELEASE="21.02.1"
# Use these tools to add and parse profiles
declare -ag PROFILES
add_profile() {
declare -Ag "$1"
PROFILES+=("$1")
}
add_profile archer
archer['profile']="tplink_archer-c7-v2"
archer['target']="ath79/generic"
archer['filesystem']="squashfs"
# shellcheck disable=SC2034 # Indirect
archer['packages']="\
$default_packages \
-dnsmasq \
-odhcpd \
-iptables \
-ath10k-firmware-qca988x-ct \
ath10k-firmware-qca988x-ct-full-htt"
add_profile linksys
linksys['profile']="linksys_ea8300"
linksys['target']="ipq40xx/generic"
linksys['filesystem']="squashfs"
# shellcheck disable=SC2034 # Indirect
linksys['packages']="\
$default_packages \
-dnsmasq \
-odhcpd \
-iptables"
add_profile rpi4
rpi4['profile']="rpi-4"
rpi4['target']="bcm27xx/bcm2711"
rpi4['filesystem']="ext4"
# shellcheck disable=SC2034 # Indirect
rpi4['packages']="\
$default_packages \
kmod-usb-net-asix-ax88179 \
kmod-usb-net-rtl8152 \
luci-app-upnp \
luci-app-wireguard \
luci-app-vpn-policy-routing \
-dnsmasq \
dnsmasq-full \
luci-app-ddns \
luci-app-sqm"
add_profile r2s
r2s['profile']="friendlyarm_nanopi-r2s"
r2s['target']="rockchip/armv8"
r2s['filesystem']="ext4"
# shellcheck disable=SC2034 # Indirect
r2s['packages']="\
$default_packages \
luci-app-upnp \
luci-app-wireguard \
luci-app-vpn-policy-routing \
-dnsmasq \
dnsmasq-full \
luci-app-ddns \
luci-app-sqm \
luci-app-statistics \
collectd-mod-sensors \
collectd-mod-thermal \
collectd-mod-conntrack \
smcroute \
curl \
ethtool"
add_profile r4s
r4s['release']="snapshot"
r4s['profile']="friendlyarm_nanopi-r4s"
r4s['target']="rockchip/armv8"
r4s['filesystem']="ext4"
# shellcheck disable=SC2034 # Indirect
r4s['packages']="\
$default_packages \
luci-app-upnp \
luci-app-wireguard \
luci-app-vpn-policy-routing \
-dnsmasq \
dnsmasq-full \
luci-app-ddns \
luci-app-sqm \
luci-app-statistics \
collectd-mod-sensors \
collectd-mod-thermal \
collectd-mod-conntrack \
smcroute \
curl \
ethtool \
kmod-ipt-nat6"
for PNAME in "${PROFILES[@]}"; do
declare -n ARR="$PNAME"
local _out_prefix
[[ ! -v ARR['release'] ]] && ARR['release']="$RELEASE"
ARR['source_archive']="$BUILDDIR/sources/${ARR[profile]}-${ARR[release]}.tar.xz"
ARR['source_dir']="${ARR[source_archive]%.tar.xz}"
ARR['out_bin_dir']="$BUILDDIR/bin/${ARR[profile]}-${ARR[release]}"
#_patches_dir="$BUILDDIR/patches/"
#_files_dir="$BUILDDIR/files/"
if [[ "${ARR[release]}" == "snapshot" ]]; then
_out_prefix="${ARR[out_bin_dir]}/openwrt-${ARR[target]//\//-}-${ARR[profile]}"
else
_out_prefix="${ARR[out_bin_dir]}/openwrt-${ARR[release]}-${ARR[target]//\//-}-${ARR[profile]}"
fi
ARR['factory_img']="$_out_prefix-${ARR[filesystem]}-factory.img"
ARR['factory_img_gz']="${ARR[factory_img]}.gz"
ARR['sysupgrade_img']="$_out_prefix-${ARR[filesystem]}-sysupgrade.img"
ARR['sysupgrade_img_gz']="${ARR[sysupgrade_img]}.gz"
ARR['sysupgrade_bin']="$_out_prefix-${ARR[filesystem]}-sysupgrade.bin"
ARR['sysupgrade_bin_fname']="${ARR[sysupgrade_bin]##*/}"
ARR['sysupgrade_bin_gz']="${ARR[sysupgrade_bin]}.gz"
ARR['sysupgrade_bin_gz_fname']="${ARR[sysupgrade_bin_gz]##*/}"
done
}
listProfiles() { listProfiles() {
debug "${FUNCNAME[0]}" debug "${FUNCNAME[0]}"
[[ ! -v PROFILES ]] && profiles grep "declare -Ag" "$PFILE" | cut -d" " -f3
echo "Available profiles:"
for PNAME in "${PROFILES[@]}"; do
declare -n ARR2="$PNAME"
echo "$PNAME: ${ARR2[profile]}"
done
} }
profileInfo() { installHostDependencies() {
debug "${FUNCNAME[0]}"
local _profile
_profile="$1"
[[ ! -v PROFILES ]] && profiles
declare -n ARR3="$_profile"
for i in "${!ARR3[@]}"; do
echo "$i: ${ARR3[i]}"
done
}
prerequisites() {
debug "${FUNCNAME[0]}" debug "${FUNCNAME[0]}"
local -a _pkg_list local -a _pkg_list
@@ -318,80 +152,87 @@ prerequisites() {
getImageBuilder() { getImageBuilder() {
debug "${FUNCNAME[0]}" debug "${FUNCNAME[0]}"
declare -n ARR4="$PROFILE"
local _url _filename local _url _filename
if [[ "${ARR4[release]}" == "snapshot" ]]; then if [[ "${P_ARR[release]}" == "snapshot" ]]; then
_filename="openwrt-imagebuilder-${ARR4[target]//\//-}.Linux-x86_64.tar.xz" _filename="openwrt-imagebuilder-${P_ARR[target]//\//-}.Linux-x86_64.tar.xz"
_url="https://downloads.openwrt.org/snapshots/targets/${ARR4[target]}/$_filename" _url="https://downloads.openwrt.org/snapshots/targets/${P_ARR[target]}/$_filename"
if [[ -f "${ARR4[source_archive]}" ]]; then if [[ -f "${P_ARR[source_archive]}" ]]; then
if askOk "Update ImageBuilder snapshot?"; then if askOk "Update ImageBuilder snapshot?"; then
rm -f "${ARR4[source_archive]}" rm -f "${P_ARR[source_archive]}"
else else
return 0 return 0
fi fi
fi fi
else else
_filename="openwrt-imagebuilder-${ARR4[release]}-${ARR4[target]//\//-}.Linux-x86_64.tar.xz" _filename="openwrt-imagebuilder-${P_ARR[release]}-${P_ARR[target]//\//-}.Linux-x86_64.tar.xz"
_url="https://downloads.openwrt.org/releases/${ARR4[release]}/targets/${ARR4[target]}/$_filename" _url="https://downloads.openwrt.org/releases/${P_ARR[release]}/targets/${P_ARR[target]}/$_filename"
[[ -f "${ARR4[source_archive]}" ]] && return 0 # Reuse existing ImageBuilders [[ -f "${P_ARR[source_archive]}" ]] && return 0 # Reuse existing ImageBuilders
fi fi
# Make sources directory if it does not exist # Make sources directory if it does not exist
[[ ! -d "$BUILDDIR/sources" ]] && mkdir -p "$BUILDDIR/sources" [[ ! -d "$BUILDDIR/sources" ]] && mkdir -p "$BUILDDIR/sources"
echo "Downloading imagebuilder archive" echo "Downloading imagebuilder archive"
debug "axel -o ${ARR4[source_archive]} $_url" debug "axel -o ${P_ARR[source_archive]} $_url"
if ! axel -o "${ARR4[source_archive]}" "$_url" > /dev/null 2>&1; then if ! axel -o "${P_ARR[source_archive]}" "$_url" > /dev/null 2>&1; then
echo "Could not download imagebuilder archive" echo "Could not download imagebuilder archive"
exit 1 exit 1
fi fi
if [[ ! -f "${ARR4[source_archive]}" ]]; then if [[ ! -f "${P_ARR[source_archive]}" ]]; then
echo "Archive missing" echo "Archive missing"
exit 1 exit 1
fi fi
echo "Extracting image archive" echo "Extracting image archive"
debug "tar -xf ${ARR4[source_archive]} -C ${ARR4[source_dir]} --strip-components 1" [[ ! -d "${P_ARR[source_dir]}" ]] && mkdir -p "${P_ARR[source_dir]}"
if ! tar -xf "${ARR4[source_archive]}" -C "${ARR4[source_dir]}" --strip-components 1; then debug "tar -xf ${P_ARR[source_archive]} -C ${P_ARR[source_dir]} --strip-components 1"
if ! tar -xf "${P_ARR[source_archive]}" -C "${P_ARR[source_dir]}" --strip-components 1; then
echo "Extraction failed" echo "Extraction failed"
exit 1 exit 1
fi fi
} }
makeImage() { addRepos() {
debug "${FUNCNAME[0]}" debug "${FUNCNAME[0]}"
declare -n ARR5="$PROFILE" if [[ -v P_ARR[repo] ]]; then
if ! grep -q "${P_ARR[repo]}" "${P_ARR[source_dir]}/repositories.conf"; then
echo "${P_ARR[repo]}" >> "${P_ARR[source_dir]}/repositories.conf"
fi
sed -i '/option check_signature/d' "${P_ARR[source_dir]}/repositories.conf"
fi
}
makeImage() {
debug "${FUNCNAME[0]}"
# Reuse the existing output # Reuse the existing output
if [[ -d "${ARR5[out_bin_dir]}" ]]; then if [[ -d "${P_ARR[out_bin_dir]}" ]]; then
if askOk "${ARR5[out_bin_dir]} exists. Rebuild?"; then if askOk "${P_ARR[out_bin_dir]} exists. Rebuild?"; then
rm -rf "${ARR5[out_bin_dir]}" rm -rf "${P_ARR[out_bin_dir]}"
else else
return 0 return 0
fi fi
fi fi
[[ ! -d "${ARR5[out_bin_dir]}" ]] && mkdir -p "${ARR5[out_bin_dir]}" [[ ! -d "${P_ARR[out_bin_dir]}" ]] && mkdir -p "${P_ARR[out_bin_dir]}"
# build image # build image
debug "make -j4 image BIN_DIR=${ARR5[out_bin_dir]} PROFILE=${ARR5[profile]} PACKAGES=${ARR5[packages]} FILES=$FILESDIR --directory=${ARR5[source_dir]} > make.log" debug "make -j4 image BIN_DIR=${P_ARR[out_bin_dir]} PROFILE=${P_ARR[profile]} PACKAGES=${P_ARR[packages]} FILES=$FILESDIR --directory=${P_ARR[source_dir]} > make.log"
if ! make image BIN_DIR="${ARR5[out_bin_dir]}" PROFILE="${ARR5[profile]}" PACKAGES="${ARR5[packages]}" FILES="$FILESDIR" --directory="${ARR5[source_dir]}" > make.log; then if ! make image BIN_DIR="${P_ARR[out_bin_dir]}" PROFILE="${P_ARR[profile]}" PACKAGES="${P_ARR[packages]}" FILES="$FILESDIR" --directory="${P_ARR[source_dir]}" > make.log; then
echo "Make image failed!" echo "Make image failed!"
exit 1 exit 1
fi fi
} }
sshBackup() {
sshBackup() {
debug "${FUNCNAME[0]}" debug "${FUNCNAME[0]}"
local _date _hostname _backup_fname local _date _hostname _backup_fname
@@ -428,11 +269,8 @@ sshBackup() {
flashImage() { flashImage() {
debug "${FUNCNAME[0]}" debug "${FUNCNAME[0]}"
declare -n ARR6="$PROFILE"
local _umount local _umount
if [[ ! -e "$FLASH_DEV" ]]; then if [[ ! -e "$FLASH_DEV" ]]; then
@@ -441,12 +279,12 @@ flashImage() {
fi fi
# TODO Roughly chooses the correct image # TODO Roughly chooses the correct image
if [[ -f "${ARR6[factory_img_gz]}" ]]; then if [[ -f "${P_ARR[factory_img_gz]}" ]]; then
img_gz="${ARR6[factory_img_gz]}" img_gz="${P_ARR[factory_img_gz]}"
img="${ARR6[factory_img]}" img="${P_ARR[factory_img]}"
elif [[ -f "${ARR6[sysupgrade_img_gz]}" ]]; then elif [[ -f "${P_ARR[sysupgrade_img_gz]}" ]]; then
img_gz="${ARR6[sysupgrade_img_gz]}" img_gz="${P_ARR[sysupgrade_img_gz]}"
img="${ARR6[sysupgrade_img]}" img="${P_ARR[sysupgrade_img]}"
else else
return 1 return 1
fi fi
@@ -473,27 +311,24 @@ flashImage() {
sshUpgrade() { sshUpgrade() {
debug "${FUNCNAME[0]}" debug "${FUNCNAME[0]}"
declare -n ARR7="$PROFILE" echo "Copying \"${P_ARR[sysupgrade_bin_gz]}\" to $SSH_UPGRADE_PATH/tmp/"
debug "scp \"${P_ARR[sysupgrade_bin_gz]}\" \"$SSH_UPGRADE_PATH\":\"/tmp/${P_ARR[sysupgrade_bin_gz_fname]}\""
echo "Copying \"${ARR7[sysupgrade_bin_gz]}\" to $SSH_UPGRADE_PATH/tmp/"
debug "scp \"${ARR7[sysupgrade_bin_gz]}\" \"$SSH_UPGRADE_PATH\":\"/tmp/${ARR7[sysupgrade_bin_gz_fname]}\""
# shellcheck disable=SC2140 # shellcheck disable=SC2140
if ! scp "${ARR7[sysupgrade_bin_gz]}" "$SSH_UPGRADE_PATH":"/tmp/${ARR7[sysupgrade_bin_gz_fname]}"; then if ! scp "${P_ARR[sysupgrade_bin_gz]}" "$SSH_UPGRADE_PATH":"/tmp/${P_ARR[sysupgrade_bin_gz_fname]}"; then
echo "Could not access the --ssh-upgrade PATH" echo "Could not access the --ssh-upgrade PATH"
exit 1 exit 1
fi fi
echo "Executing remote sysupgrade" echo "Executing remote sysupgrade"
debug "ssh \"$SSH_UPGRADE_PATH\" \"sysupgrade -F /tmp/${ARR7[sysupgrade_bin_gz_fname]}\"" debug "ssh \"$SSH_UPGRADE_PATH\" \"sysupgrade -F /tmp/${P_ARR[sysupgrade_bin_gz_fname]}\""
# shellcheck disable=SC2029 # shellcheck disable=SC2029
ssh "$SSH_UPGRADE_PATH" "sysupgrade -F /tmp/${ARR7[sysupgrade_bin_gz_fname]}" ssh "$SSH_UPGRADE_PATH" "sysupgrade -F /tmp/${P_ARR[sysupgrade_bin_gz_fname]}"
} }
debug() { "$DEBUG" && echo "Running: " "$@" ; } debug() { (( DEBUG )) && echo "Running: " "$@" ; }
askOk() { askOk() {
@@ -506,26 +341,73 @@ askOk() {
reset() { reset() {
debug "${FUNCNAME[0]}"
askOk "Remove $FILESDIR $BUILDDIR/sources $BUILDDIR/bin?" || exit $? askOk "Remove $FILESDIR $BUILDDIR/sources $BUILDDIR/bin?" || exit $?
debug "rm -rf $FILESDIR $BUILDDIR/sources $BUILDDIR/bin" debug "rm -rf $FILESDIR $BUILDDIR/sources $BUILDDIR/bin"
rm -rf "$FILESDIR" "${BUILDDIR:?}/sources" "${BUILDDIR:?}/bin" rm -rf "$FILESDIR" "${BUILDDIR:?}/sources" "${BUILDDIR:?}/bin"
} }
loadProfiles() {
debug "${FUNCNAME[0]}"
declare -g SCRIPTDIR PFILE
# https://stackoverflow.com/a/4774063
SCRIPTDIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 || exit $? ; pwd -P )"
PFILE="$SCRIPTDIR/profiles"
# shellcheck source=./profiles
! source "$PFILE" && echo "profiles file missing!" && return 1
}
main() { main() {
debug "${FUNCNAME[0]}"
: "${DEBUG:=false}" # Set to true to enable debugging by default loadProfiles
scriptdir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 || exit $? ; pwd -P )" # https://stackoverflow.com/a/4774063
# scriptdir="$PWD" readInput "$@"
: "${BUILDDIR:=$scriptdir}"
[[ ! -v "$PROFILE"[@] ]] && echo "Profile does not exist" && return 1
declare -gn P_ARR="$PROFILE"
declare _out_prefix
: "${BUILDDIR:=$SCRIPTDIR}"
: "${FILESDIR:=$BUILDDIR/files}" : "${FILESDIR:=$BUILDDIR/files}"
: "${RELEASE:="21.02.1"}"
: "${P_ARR[release]:=$RELEASE}"
: "${P_ARR[source_archive]:=$BUILDDIR/sources/${P_ARR[profile]}-${P_ARR[release]}.tar.xz}"
: "${P_ARR[source_dir]:=${P_ARR[source_archive]%.tar.xz}}"
: "${P_ARR[out_bin_dir]:=$BUILDDIR/bin/${P_ARR[profile]}-${P_ARR[release]}}"
if [[ "${P_ARR[release]}" == "snapshot" ]]; then
_out_prefix="${P_ARR[out_bin_dir]}/openwrt-${P_ARR[target]//\//-}-${P_ARR[profile]}"
else
_out_prefix="${P_ARR[out_bin_dir]}/openwrt-${P_ARR[release]}-${P_ARR[target]//\//-}-${P_ARR[profile]}"
fi
: "${P_ARR[factory_img]:=$_out_prefix-${P_ARR[filesystem]}-factory.img}"
: "${P_ARR[factory_img_gz]:=${P_ARR[factory_img]}.gz}"
: "${P_ARR[sysupgrade_img]:=$_out_prefix-${P_ARR[filesystem]}-sysupgrade.img}"
: "${P_ARR[sysupgrade_img_gz]:=${P_ARR[sysupgrade_img]}.gz}"
: "${P_ARR[sysupgrade_bin]:=$_out_prefix-${P_ARR[filesystem]}-sysupgrade.img}"
: "${P_ARR[sysupgrade_bin_fname]:=${P_ARR[sysupgrade_bin]##*/}}"
: "${P_ARR[sysupgrade_bin_gz]:=${P_ARR[sysupgrade_bin]}.gz}"
: "${P_ARR[sysupgrade_bin_gz_fname]:=${P_ARR[sysupgrade_bin_gz]##*/}}"
(( RESET )) && reset
if (( DEBUG )) || (( PROFILE_INFO )); then
for x in "${!P_ARR[@]}"; do printf "[%s]=%s\n" "$x" "${P_ARR[$x]}"; done
fi
installHostDependencies
input "$@"
profiles
[[ -v RESET ]] && reset
prerequisites
getImageBuilder getImageBuilder
addRepos
#copyFiles #copyFiles
[[ -v SSH_BACKUP_PATH ]] && sshBackup [[ -v SSH_BACKUP_PATH ]] && sshBackup
if makeImage; then if makeImage; then
[[ -v SSH_UPGRADE_PATH ]] && sshUpgrade [[ -v SSH_UPGRADE_PATH ]] && sshUpgrade
@@ -534,4 +416,4 @@ main() {
} }
main "$@" main "$@"
exit $? exit

143
profiles Normal file
View File

@@ -0,0 +1,143 @@
#!/usr/bin/env bash
# shellcheck disable=SC2034
# This file contains a set of device profiles for openwrtbuilder
# Packages to install for all profiles
default_packages="\
luci \
luci-ssl \
nano \
htop \
tcpdump \
diffutils \
tar \
iperf \
bash \
rsync " # Leave trailing whitespace
declare -Ag archer
archer['profile']="tplink_archer-c7-v2"
archer['target']="ath79/generic"
archer['filesystem']="squashfs"
archer['packages']="\
$default_packages \
-dnsmasq \
-odhcpd \
-iptables \
-ath10k-firmware-qca988x-ct \
ath10k-firmware-qca988x-ct-full-htt"
declare -Ag linksys
linksys['profile']="linksys_ea8300"
linksys['target']="ipq40xx/generic"
linksys['filesystem']="squashfs"
linksys['packages']="\
$default_packages \
-dnsmasq \
-odhcpd \
-iptables"
declare -Ag rpi4
rpi4['profile']="rpi-4"
rpi4['target']="bcm27xx/bcm2711"
rpi4['filesystem']="ext4"
rpi4['packages']="\
$default_packages \
kmod-usb-net-asix-ax88179 \
kmod-usb-net-rtl8152 \
luci-app-upnp \
luci-app-wireguard \
luci-app-vpn-policy-routing \
-dnsmasq \
dnsmasq-full \
luci-app-ddns \
luci-app-sqm"
declare -Ag r2s
r2s['profile']="friendlyarm_nanopi-r2s"
r2s['target']="rockchip/armv8"
r2s['filesystem']="ext4"
r2s['packages']="\
$default_packages \
luci-app-upnp \
luci-app-wireguard \
luci-app-vpn-policy-routing \
-dnsmasq \
dnsmasq-full \
luci-app-ddns \
luci-app-sqm \
luci-app-statistics \
collectd-mod-sensors \
collectd-mod-thermal \
collectd-mod-conntrack \
smcroute \
curl \
ethtool"
declare -Ag r4s
r4s['release']="snapshot"
r4s['profile']="friendlyarm_nanopi-r4s"
r4s['target']="rockchip/armv8"
r4s['filesystem']="ext4"
r4s['repo']="src/gz stangri_repo https://repo.openwrt.melmac.net"
# r4s['packages']="\
# $default_packages \
# luci-app-upnp \
# luci-app-wireguard \
# luci-app-vpn-policy-routing \
# vpn-policy-routing \
# -dnsmasq \
# dnsmasq-full \
# luci-app-ddns \
# luci-app-sqm \
# luci-app-statistics \
# collectd-mod-sensors \
# collectd-mod-thermal \
# collectd-mod-conntrack \
# smcroute \
# curl \
# ethtool \
# kmod-ipt-nat6 \
# -firewall4 \
# -nftables \
# -kmod-nft-offload \
# firewall \
# ip6tables \
# iptables \
# kmod-ipt-offload"
r4s['packages']="\
$default_packages \
luci-app-upnp \
luci-app-wireguard \
luci-app-pbr \
pbr-ipt \
-dnsmasq \
dnsmasq-full \
luci-app-ddns \
luci-app-sqm \
luci-app-statistics \
collectd-mod-sensors \
collectd-mod-thermal \
collectd-mod-conntrack \
smcroute \
curl \
ethtool \
kmod-ipt-nat6 \
-firewall4 \
-nftables \
-kmod-nft-offload \
firewall \
ip6tables \
iptables \
kmod-ipt-offload"
declare -Ag x5000r
x5000r['profile']="totolink_x5000r"
x5000r['target']="ramips/mt7621"
x5000r['filesystem']="squashfs"
x5000r['packages']="\
$default_packages \
-dnsmasq \
-odhcpd \
-iptables"