はじめに
OpenWrt搭載Wi-Fi7デバイス比較
Wi-Fi7デバイス
-
SinoVoip Banana Pi BPI-R4
用途: オープンソースルーター開発向け
CPU: MediaTek MT7988A (Filogic 880)
メモリ: 4GB or 8GB DDR4
ストレージ: MicroSD(TF) card or 8GB eMMC
WAN: 1G ×1
LAN: 1G ×3
SFP: 10G ×2
USB: USB 3.2 Type-A
OS: OpenWrt -
Linksys Velop WRT Pro 7
用途: ホーム&ビジネス向け
CPU: Qualcomm IPQ9554
メモリ: 1GB DDR4
ストレージ: 8GB eMMC
WAN: 2.5G ×1
LAN: 1G ×4
OS: QSDK 19.07/カーネル 5.4.213(公式OpenWrtインストール不可)
MLO: サポート -
GL.iNet Flint 3 GL-BE9300
https://www.gl-inet.com/campaign/gl-be9300-jp/
用途: 家庭や小規模オフィス向け
CPU: Qualcomm IPQ9554?
メモリ: 1GB DDR4
ストレージ: 8GB eMMC
WAN: 2.5G ×1
WAN/LAN: 2.5G ×1
LAN: 2.5G ×4
USB: USB 3.0 Type-A
OS: QSDK 23.05/カーネル 5.4.213 (公式OpenWrtインストール不可?)
MLO: サポート
OpenWrt
ファームウェア
ダウンロード
公式ファームウェア
デバイス用のOpenWrtカスタムファームウェアをダウンロード
※ビルダーは非公式
SDカード利用の場合:
- イメージのダウンロード >> SDCARD.IMG.GZ をダウンロード
SDカードサイズ拡張
SDカード初期化
- コマンドプロンプト
※管理者として実行
diskpart
list disk
select disk
clean
create partition primary
select partition 1
format fs=fat32 quick
assign
exit
SDカード拡張
- 用意するもの:
SDカード ×2枚 ※サイズが異なっても可
SDカードリーダー - 作業工程
両方のSDカードに同じイメージを書き込み
サブのSDカードでデバイス起動
メインのSDカードをリーダーに差してUSB接続
fdiskでパーティション7を容量拡張
SDカードを入れ替え (完了)
Type UUID: CAE9BE83-B15F-49CC-863F-081B744A2D93
Partition UUID: 5452574F-2211-4433-5566-778899AABB07
- 手順
PKGS="f2fs-tools fdisk gdisk kmod-usb-storage kmod-usb-storage-uas parted"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
partprobe /dev/sda
fdisk /dev/sda
d
7
n
7
未入力
未入力
t
7
CAE9BE83-B15F-49CC-863F-081B744A2D93
x
u
7
5452574F-2211-4433-5566-778899AABB07
n
7
production
r
w
- 断電しメインのSDカードをデバイスに入替挿入 ※USBカードリーダーを抜く
ビルドツール
Linuxライブディストリビューション (設定永続化仕様)
Live Linux
Ubuntu
- Ubuntu Desktop 24.04.2 LTS
-
Ubuntu Desktop 日本語 Remix
Ubuntu 22.04 LTS: ubuntu-ja-22.04-desktop-amd64.iso
RAMディスク作成
- クライアント確認
free -h
df -h
- RAMディスク自動マウント設定
/etc/fstab 自動追記(要8GB以上: 動的サイズ)
※推奨メモリ: 16GB以上
#!/bin/bash
sudo cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d%H%M%S)
free -m | awk '
/^Mem:/ {
total_mb = $2
if (total_mb <= 8000) exit 0
size_gb = int(total_mb / 2 / 1024)
if (size_gb > 32) size_gb = 32
if (size_gb < 1) size_gb = 1
print "tmpfs /mnt/ramdisk tmpfs defaults,size=" size_gb "G 0 0"
}
' > /tmp/ramdisk_fstab
sudo sed -i '/^tmpfs \/mnt\/ramdisk tmpfs /d' /etc/fstab
if [ -s /tmp/ramdisk_fstab ]; then
sudo tee -a /etc/fstab < /tmp/ramdisk_fstab
fi
rm -f /tmp/ramdisk_fstab
sudo mkdir -p /mnt/ramdisk
sudo umount /mnt/ramdisk 2>/dev/null
sudo mount -a
df -h /mnt/ramdisk
grep '/mnt/ramdisk' /etc/fstab
echo "RAMディスク設定完了"
- Windowsの時刻がUTCになる問題対応
sudo timedatectl set-local-rtc 1
timedatectl
# RTC in local TZ: yes
チューニング
ネットワークパフォーマンス
ツール
-
メモリ・バッファ設定
net.core.rmem_max/wmem_max: ソケット受信/送信バッファの最大サイズ
tcp_rmem/tcp_wmem: TCP受信/送信バッファサイズ(最小/デフォルト/最大)
初期値: rmem_max/wmem_max = 212KB (212,992 bytes)
推奨値: 12MB以上(4GBメモリなら16MB推奨)
設定値: 16MB (16,777,216 bytes) -
TCP最適化
tcp_fastopen: TCP Fast Open(接続高速化)
tcp_keepalive_probes: 接続維持のプローブ回数
初期値: tcp_wmem最大値 = 4MB (4,194,304), tcp_rmem最大値 = 6MB (6,291,456)
推奨値: 16MB以上
設定値: 16MB (16,777,216) -
TCP設定
tcp_congestion_control: 輻輳制御アルゴリズム
初期値: cubic, fastopen=1, keepalive_probes=9
推奨値: westwood, fastopen=3, keepalive_probes=3
設定値: cubic, fastopen=3, keepalive_probes=3(westwoodは利用不可) -
コネクション追跡
nf_conntrack_max: 同時接続数の上限
netdev_max_backlog: ネットワークデバイスのキューサイズ
somaxconn: リスニングキューの最大サイズ
初期値: nf_conntrack_max=65,536, netdev_max_backlog=1,000, somaxconn=4,096
推奨値: 131,072接続以上
設定値: nf_conntrack_max=262,144, netdev_max_backlog=5,000, somaxconn=16,384 -
設定
#!/bin/sh
TMP=/tmp/aios
mkdir -p "$TMP"
cat > "$TMP/dynamic-network-optimizer.sh" << 'SCRIPT_END'
#!/bin/sh
set -e
CONFIG_FILE="/etc/sysctl.d/99-network-optimization-auto.conf"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m'
log_info() { printf "${BLUE}[INFO]${NC} %s\n" "$1"; }
log_success() { printf "${GREEN}[OK]${NC} %s\n" "$1"; }
log_warning() { printf "${YELLOW}[WARN]${NC} %s\n" "$1"; }
log_error() { printf "${RED}[ERROR]${NC} %s\n" "$1"; }
log_highlight() { printf "${CYAN}[HIGHLIGHT]${NC} %s\n" "$1"; }
detect_memory() {
local mem_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
printf '%s\n' "$((mem_kb / 1024))"
}
detect_cpu_cores() {
grep -c ^processor /proc/cpuinfo
}
get_current_connections() {
if [ -f /proc/sys/net/netfilter/nf_conntrack_count ]; then
cat /proc/sys/net/netfilter/nf_conntrack_count
else
printf '%s\n' "0"
fi
}
get_best_congestion_control() {
local available
available=$(cat /proc/sys/net/ipv4/tcp_available_congestion_control)
for algo in bbr cubic reno; do
if printf '%s\n' "$available" | grep -q "$algo"; then
printf '%s\n' "$algo"
return
fi
done
printf '%s\n' "$(printf '%s\n' "$available" | awk '{print $1}')"
}
# Get current value dynamically - this is the key fix
get_current_value() {
local setting="$1"
case "$setting" in
"rmem_max")
cat /proc/sys/net/core/rmem_max 2>/dev/null || printf "%s" "unknown"
;;
"wmem_max")
cat /proc/sys/net/core/wmem_max 2>/dev/null || printf "%s" "unknown"
;;
"tcp_rmem")
cat /proc/sys/net/ipv4/tcp_rmem 2>/dev/null | tr -s '\t' ' ' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//' || printf "%s" "unknown"
;;
"tcp_wmem")
cat /proc/sys/net/ipv4/tcp_wmem 2>/dev/null | tr -s '\t' ' ' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//' || printf "%s" "unknown"
;;
"tcp_congestion_control")
cat /proc/sys/net/ipv4/tcp_congestion_control 2>/dev/null || printf "%s" "unknown"
;;
"nf_conntrack_max")
cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null || printf "%s" "unknown"
;;
"netdev_max_backlog")
cat /proc/sys/net/core/netdev_max_backlog 2>/dev/null || printf "%s" "unknown"
;;
"somaxconn")
cat /proc/sys/net/core/somaxconn 2>/dev/null || printf "%s" "unknown"
;;
"active_connections")
get_current_connections
;;
*)
printf "%s" "unknown"
;;
esac
}
calculate_buffer_sizes() {
local mem_mb=$1
local cores=$2
if [ "$mem_mb" -ge 3072 ]; then
rmem_max=16777216; wmem_max=16777216
tcp_rmem="4096 262144 16777216"; tcp_wmem="4096 262144 16777216"
conntrack_max=262144; netdev_backlog=5000; somaxconn=16384
elif [ "$mem_mb" -ge 1536 ]; then
rmem_max=8388608; wmem_max=8388608
tcp_rmem="4096 131072 8388608"; tcp_wmem="4096 131072 8388608"
conntrack_max=131072; netdev_backlog=2500; somaxconn=8192
elif [ "$mem_mb" -ge 512 ]; then
rmem_max=4194304; wmem_max=4194304
tcp_rmem="4096 65536 4194304"; tcp_wmem="4096 65536 4194304"
conntrack_max=65536; netdev_backlog=1000; somaxconn=4096
else
rmem_max=1048576; wmem_max=1048576
tcp_rmem="4096 32768 1048576"; tcp_wmem="4096 32768 1048576"
conntrack_max=32768; netdev_backlog=500; somaxconn=2048
fi
if [ "$cores" -gt 4 ]; then
netdev_backlog=$((netdev_backlog * 2))
somaxconn=$((somaxconn * 2))
elif [ "$cores" -gt 2 ]; then
netdev_backlog=$((netdev_backlog + netdev_backlog / 2))
somaxconn=$((somaxconn + somaxconn / 2))
fi
}
format_bytes() {
local bytes=$1
if [ "$bytes" = "unknown" ]; then
printf '%s' "unknown"
return
fi
if [ "$bytes" -ge 1048576 ]; then
printf '%s' "$((bytes / 1048576))MB"
elif [ "$bytes" -ge 1024 ]; then
printf '%s' "$((bytes / 1024))KB"
else
printf '%s' "${bytes}B"
fi
}
values_equal() {
local current="$1"
local new="$2"
if [ "$current" = "unknown" ] || [ "$new" = "unknown" ]; then
return 1
fi
local norm_current=$(printf '%s\n' "$current" | tr -s ' \t' ' ' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')
local norm_new=$(printf '%s\n' "$new" | tr -s ' \t' ' ' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')
[ "$norm_current" = "$norm_new" ]
}
show_comparison() {
printf '\n'
printf "BEFORE vs AFTER COMPARISON\n"
printf '\n'
local max_setting=7
local max_value=6
local status_width=11
local single_settings="rmem_max wmem_max tcp_congestion_control nf_conntrack_max netdev_max_backlog somaxconn"
for setting in $single_settings; do
[ ${#setting} -gt $max_setting ] && max_setting=${#setting}
done
local tcp_items="tcp_rmem (min) tcp_rmem (default) tcp_rmem (max) tcp_wmem (min) tcp_wmem (default) tcp_wmem (max)"
for item in $tcp_items; do
[ ${#item} -gt $max_setting ] && max_setting=${#item}
done
for setting in $single_settings; do
local current_value=$(get_current_value "$setting")
local new_value
case "$setting" in
"rmem_max") new_value="$rmem_max" ;;
"wmem_max") new_value="$wmem_max" ;;
"tcp_congestion_control") new_value="$best_congestion" ;;
"nf_conntrack_max") new_value="$conntrack_max" ;;
"netdev_max_backlog") new_value="$netdev_backlog" ;;
"somaxconn") new_value="$somaxconn" ;;
esac
local display_current display_new
case "$setting" in
"rmem_max"|"wmem_max")
display_current="$(format_bytes "$current_value")"
display_new="$(format_bytes "$new_value")"
;;
*)
display_current="$current_value"
display_new="$new_value"
;;
esac
[ ${#display_current} -gt $max_value ] && max_value=${#display_current}
[ ${#display_new} -gt $max_value ] && max_value=${#display_new}
done
for proto in rmem tcp_wmem; do
local cur=$(get_current_value "${proto/tcp_/tcp_}")
local new=$(eval echo "\$tcp_${proto/tcp_}")
if [ "$cur" != "unknown" ]; then
for val in $(echo "$cur") $(echo "$new"); do
[ ${#val} -gt $max_value ] && max_value=${#val}
done
fi
done
max_setting=$((max_setting + 1))
max_value=$((max_value + 1))
local sep_setting sep_value sep_status
sep_setting=$(printf '%*s' "$max_setting" '' | tr ' ' '-')
sep_value=$(printf '%*s' "$max_value" '' | tr ' ' '-')
sep_status=$(printf '%*s' "$status_width" '' | tr ' ' '-')
printf "%-${max_setting}s| %-${max_value}s| %-${max_value}s| %-${status_width}s\n" "Setting" "Before" "After" "Status"
printf "%s+-%s+-%s+-%s\n" "$sep_setting" "$sep_value" "$sep_value" "$sep_status"
print_row() {
local setting="$1" current_val="$2" new_val="$3" status="$4"
printf "%-${max_setting}s| %-${max_value}s| %-${max_value}s| %s\n" "$setting" "$current_val" "$new_val" "$status"
}
for setting in $single_settings; do
local current_value=$(get_current_value "$setting")
local new_value status
case "$setting" in
"rmem_max") new_value="$rmem_max" ;;
"wmem_max") new_value="$wmem_max" ;;
"tcp_congestion_control") new_value="$best_congestion" ;;
"nf_conntrack_max") new_value="$conntrack_max" ;;
"netdev_max_backlog") new_value="$netdev_backlog" ;;
"somaxconn") new_value="$somaxconn" ;;
esac
local display_current display_new
case "$setting" in
"rmem_max"|"wmem_max")
display_current="$(format_bytes "$current_value")"
display_new="$(format_bytes "$new_value")"
;;
*)
display_current="$current_value"
display_new="$new_value"
;;
esac
if values_equal "$current_value" "$new_value"; then
status="Same"
else
status="Changed"
if [ "$current_value" != "unknown" ] && [ "$new_value" != "unknown" ]; then
case "$setting" in
"rmem_max"|"wmem_max"|"netdev_max_backlog"|"somaxconn"|"nf_conntrack_max")
if [ "$new_value" -gt "$current_value" ] 2>/dev/null; then
status="↑ Increased"
elif [ "$new_value" -lt "$current_value" ] 2>/dev/null; then
status="↓ Optimized"
fi
;;
esac
fi
fi
print_row "$setting" "$display_current" "$display_new" "$status"
done
print_tcp_rows() {
local name="$1" cur="$2" new="$3"
if [ "$cur" = "unknown" ]; then
print_row "${name} (min)" "unknown" "$(echo "$new" | awk '{print $1}')" "Unknown"
print_row "${name} (default)" "unknown" "$(echo "$new" | awk '{print $2}')" "Unknown"
print_row "${name} (max)" "unknown" "$(echo "$new" | awk '{print $3}')" "Unknown"
return
fi
local c1 c2 c3 n1 n2 n3 s1 s2 s3
c1=$(echo "$cur" | awk '{print $1}'); n1=$(echo "$new" | awk '{print $1}')
c2=$(echo "$cur" | awk '{print $2}'); n2=$(echo "$new" | awk '{print $2}')
c3=$(echo "$cur" | awk '{print $3}'); n3=$(echo "$new" | awk '{print $3}')
s1="Same"; s2="Same"; s3="Same"
[ "$c1" != "$n1" ] && s1="Changed"
[ "$c2" != "$n2" ] && s2="Changed"
[ "$c3" != "$n3" ] && s3="Changed"
[ "$n1" -gt "$c1" ] 2>/dev/null && s1="↑ Increased"
[ "$n1" -lt "$c1" ] 2>/dev/null && s1="↓ Decreased"
[ "$n2" -gt "$c2" ] 2>/dev/null && s2="↑ Increased"
[ "$n2" -lt "$c2" ] 2>/dev/null && s2="↓ Decreased"
[ "$n3" -gt "$c3" ] 2>/dev/null && s3="↑ Increased"
[ "$n3" -lt "$c3" ] 2>/dev/null && s3="↓ Decreased"
print_row "${name} (min)" "$c1" "$n1" "$s1"
print_row "${name} (default)" "$c2" "$n2" "$s2"
print_row "${name} (max)" "$c3" "$n3" "$s3"
}
print_tcp_rows "tcp_rmem" "$(get_current_value tcp_rmem)" "$tcp_rmem"
print_tcp_rows "tcp_wmem" "$(get_current_value tcp_wmem)" "$tcp_wmem"
printf "%s+-%s+-%s+-%s\n" "$sep_setting" "$sep_value" "$sep_value" "$sep_status"
print_row "active_connections" "$(get_current_connections)" "$(get_current_connections)" "Same"
printf '\n'
printf "Legend:\n"
printf " Same - No change needed\n"
printf " ↑ Increased - Value will be increased for better performance\n"
printf " ↓ Optimized - Value will be reduced for memory optimization\n"
printf " Changed - Value will be modified\n"
printf '\n'
}
verify_applied_settings() {
printf '\n'
log_info "=== Post-Application Verification ==="
local verification_failed=0
verify_setting() {
local setting_name="$1"
local expected_value="$2"
local actual_value="$3"
local display_name="$4"
if values_equal "$actual_value" "$expected_value"; then
log_success "$display_name: $(format_bytes "$actual_value" 2>/dev/null || printf "%s" "$actual_value")"
else
log_warning "$display_name: $actual_value (expected: $expected_value)"
verification_failed=1
fi
}
# Verify each setting using the same dynamic fetch method
verify_setting "rmem_max" "$rmem_max" "$(get_current_value "rmem_max")" "rmem_max"
verify_setting "wmem_max" "$wmem_max" "$(get_current_value "wmem_max")" "wmem_max"
verify_setting "netdev_max_backlog" "$netdev_backlog" "$(get_current_value "netdev_max_backlog")" "netdev_max_backlog"
verify_setting "somaxconn" "$somaxconn" "$(get_current_value "somaxconn")" "somaxconn"
verify_setting "tcp_rmem" "$tcp_rmem" "$(get_current_value "tcp_rmem")" "tcp_rmem"
verify_setting "tcp_wmem" "$tcp_wmem" "$(get_current_value "tcp_wmem")" "tcp_wmem"
# Overall result
if [ "$verification_failed" -eq 0 ]; then
log_success "All settings verified successfully!"
else
log_warning "Some settings may not have been applied correctly"
printf '\n'
log_info "This may be due to:"
printf " - Kernel module not loaded (e.g., nf_conntrack)\n"
printf " - Insufficient permissions\n"
printf " - Kernel version compatibility\n"
printf " - Hardware limitations\n"
printf '\n'
log_info "Running 'dmesg | tail' might provide more information"
fi
}
show_performance_impact() {
printf "Performance Impact Summary\n"
printf '\n'
mem_mb=$(detect_memory)
cores=$(detect_cpu_cores)
printf "System Profile: %dMB RAM, %d CPU cores\n" "$mem_mb" "$cores"
printf '\n'
changes_found=0
improvements=""
# Check for actual improvements by comparing current vs new values
current_rmem=$(get_current_value rmem_max)
current_wmem=$(get_current_value wmem_max)
current_backlog=$(get_current_value netdev_max_backlog)
current_somaxconn=$(get_current_value somaxconn)
if ! values_equal "$current_rmem" "$rmem_max" && [ "$current_rmem" != unknown ] && [ "$current_rmem" -gt 0 ] 2>/dev/null; then
rmem_impr=$(( (rmem_max - current_rmem) * 100 / current_rmem ))
if [ "$rmem_impr" -gt 0 ]; then
improvements="${improvements}Receive buffer: +${rmem_impr}% increase -> Better download performance\n"
changes_found=1
elif [ "$rmem_impr" -lt 0 ]; then
improvements="${improvements}Receive buffer: ${rmem_impr}% decrease -> Memory optimized\n"
changes_found=1
fi
fi
if ! values_equal "$current_wmem" "$wmem_max" && [ "$current_wmem" != unknown ] && [ "$current_wmem" -gt 0 ] 2>/dev/null; then
wmem_impr=$(( (wmem_max - current_wmem) * 100 / current_wmem ))
if [ "$wmem_impr" -gt 0 ]; then
improvements="${improvements}Send buffer: +${wmem_impr}% increase -> Better upload performance\n"
changes_found=1
elif [ "$wmem_impr" -lt 0 ]; then
improvements="${improvements}Send buffer: ${wmem_impr}% decrease -> Memory optimized\n"
changes_found=1
fi
fi
if ! values_equal "$current_backlog" "$netdev_backlog" && [ "$current_backlog" != unknown ] && [ "$current_backlog" -gt 0 ] 2>/dev/null; then
backlog_impr=$(( (netdev_backlog - current_backlog) * 100 / current_backlog ))
if [ "$backlog_impr" -gt 0 ]; then
improvements="${improvements}Network backlog: +${backlog_impr}% increase -> Better packet processing\n"
changes_found=1
fi
fi
if ! values_equal "$current_somaxconn" "$somaxconn" && [ "$current_somaxconn" != unknown ] && [ "$current_somaxconn" -gt 0 ] 2>/dev/null; then
connq_impr=$(( (somaxconn - current_somaxconn) * 100 / current_somaxconn ))
if [ "$connq_impr" -gt 0 ]; then
improvements="${improvements}Connection queue: +${connq_impr}% increase -> More concurrent connections\n"
changes_found=1
fi
fi
if [ "$changes_found" -eq 1 ]; then
printf "Performance Improvements:\n"
printf "%b" "$improvements"
else
printf "System is already optimally configured for your hardware\n"
printf "No significant changes needed\n"
fi
printf '\n'
printf "Expected Benefits:\n"
printf " - Reduced packet drops under high load\n"
printf " - Better throughput for large file transfers\n"
printf " - Improved responsiveness for multiple connections\n"
printf " - Optimized memory usage for your hardware\n"
printf '\n'
}
remove_optimizer() {
printf "Network Optimizer Removal Tool\n"
printf "==============================\n"
if [ ! -f "$CONFIG_FILE" ]; then
log_info "No optimization config found"
return 0
fi
printf "Do you want to remove the existing optimization config? (y/N): "
read -r confirm_remove
if [ "$confirm_remove" != "y" ] && [ "$confirm_remove" != "Y" ]; then
log_info "Removal cancelled by user"
return 0
fi
local backup_file=""
for backup in "${CONFIG_FILE}.backup."*; do
[ -f "$backup" ] && { backup_file="$backup"; break; }
done
if [ -n "$backup_file" ]; then
log_info "Restoring from backup: $backup_file"
cp "$backup_file" "$CONFIG_FILE"
sysctl -p "$CONFIG_FILE" >/dev/null 2>&1
log_success "Original settings restored"
else
log_info "No backup found – removing config file"
rm "$CONFIG_FILE"
log_success "Config file removed"
log_highlight "Reboot required to return to system defaults"
fi
}
optimizer_main() {
printf "Dynamic Network Performance Optimizer\n"
printf "=====================================\n"
if [ -f "$CONFIG_FILE" ]; then
log_warning "Existing config detected: $CONFIG_FILE"
remove_optimizer
exit 0
fi
printf '\n'
log_info "=== System Analysis ==="
local mem_mb=$(detect_memory)
local cores=$(detect_cpu_cores)
local best_congestion=$(get_best_congestion_control)
log_info "Detected RAM: ${mem_mb}MB"
log_info "Detected CPU cores: $cores"
log_info "Best congestion control: $best_congestion"
calculate_buffer_sizes "$mem_mb" "$cores"
show_comparison
show_performance_impact
printf "Do you want to apply these changes? (y/N): "
read -r confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
log_info "Operation cancelled by user"
exit 0
fi
if [ -f "$CONFIG_FILE" ]; then
local backup_file="${CONFIG_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
cp "$CONFIG_FILE" "$backup_file"
log_info "Backed up existing config to: $backup_file"
fi
log_info "Creating configuration: $CONFIG_FILE"
cat > "$CONFIG_FILE" << CONFIG_EOF
net.core.rmem_max = $rmem_max
net.core.wmem_max = $wmem_max
net.ipv4.tcp_rmem = $tcp_rmem
net.ipv4.tcp_wmem = $tcp_wmem
net.ipv4.tcp_congestion_control = $best_congestion
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_keepalive_probes = 3
net.netfilter.nf_conntrack_max = $conntrack_max
net.core.netdev_max_backlog = $netdev_backlog
net.core.somaxconn = $somaxconn
CONFIG_EOF
printf '\n'
log_info "Applying configuration"
if sysctl -p "$CONFIG_FILE" >/dev/null 2>&1; then
log_success "Configuration applied successfully"
else
log_warning "Some settings may have failed (check kernel support)"
fi
verify_applied_settings
printf '\n'
log_success "Network optimization completed!"
log_highlight "Reboot recommended for full effect and persistent changes"
printf '\n'
log_info "Current memory usage:"
free -h
}
if [ "$0" = "${0#*/}" ] || [ "${0##*/}" = "$(basename "$0")" ]; then
optimizer_main "$@"
fi
SCRIPT_END
chmod +x "$TMP/dynamic-network-optimizer.sh"
sh "$TMP/dynamic-network-optimizer.sh"
Wi-Fi
ドライバー
- ドライバー
firmware/mt7996
-
mt7996_eeprom_233_2i5i6i.bin
/lib/firmware/mediatek/mt7996
OpenWrt24.10ファームウェアでの無線周波数のパフォーマンスを向上
wget -O /tmp/mt7996_eeprom_233_2i5i6i.bin 'https://github.com/openwrt/mt76/raw/refs/heads/master/firmware/mt7996/mt7996_eeprom_233_2i5i6i.bin'
FW_DIR="/lib/firmware/mediatek/mt7996"
if [ -f "$FW_DIR/mt7996_eeprom_233_2i5i6i.bin" ]; then
mv "$FW_DIR/mt7996_eeprom_233_2i5i6i.bin" "$FW_DIR/mt7996_eeprom_233_2i5i6i.bin.bak"
fi
mv /tmp/mt7996_eeprom_233_2i5i6i.bin "$FW_DIR/"
-
mt7996_eeprom_233.bin
/lib/firmware/mediatek/mt7996
wget -O /tmp/mt7996_eeprom_233.bin 'https://github.com/openwrt/mt76/raw/refs/heads/master/firmware/mt7996/mt7996_eeprom_233.bin'
FW_DIR="/lib/firmware/mediatek/mt7996"
if [ -f "$FW_DIR/mt7996_eeprom_233.bin" ]; then
mv "$FW_DIR/mt7996_eeprom_233.bin" "$FW_DIR/mt7996_eeprom_233.bin.bak"
fi
mv /tmp/mt7996_eeprom_233.bin "$FW_DIR/"
バックグラウンドレーダー
uci set wireless.default_radio1.background_radar=1
# uci set wireless.default_radio2.background_radar=1
uci commit wireless
wifi reload
ワイヤレスオフロード
WED ( Wireless Ethernet D ispatch )
25.12.0-rc5ではRAM制限不要
RAMを2GBに制限した後(上記の注記を参照、一時的な回避策)、WOファームウェアの読み込みを有効にします。
WOファームウェア有効化
map-eは非推奨(アップロードがドロップする)
echo 'options mt7996e wed_enable=Y sr_scene_detect=Y' >> /etc/modules.conf
確認
cat /sys/module/mt7996e/parameters/sr_scene_detect
cat /sys/module/mt7996e/parameters/wed_enable
削除
sed -i '/^options mt7996e /d' /etc/modules.conf
# reboot
SN比改善
#!/bin/sh
grep -q 'pcie_aspm/parameters/policy' /etc/rc.local || \
sed -i '/^exit 0/i \
# Set CPU governor to "ondemand" to reduce power consumption and heat generation\
for CPUFREQ in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do\
echo ondemand > "$CPUFREQ"\
done\
\
# Adjust parameters for the "ondemand" governor to further optimize power consumption\
for ONDEMAND_DIR in /sys/devices/system/cpu/cpu*/cpufreq/ondemand; do\
echo 70 > "$ONDEMAND_DIR/up_threshold"\
echo 60000 > "$ONDEMAND_DIR/sampling_rate"\
echo 1 > "$ONDEMAND_DIR/io_is_busy"\
done\
\
# Enable ASPM with "powersupersave" policy to improve WiFi signal-to-noise ratio\
echo powersupersave > /sys/module/pcie_aspm/parameters/policy\
' /etc/rc.local
# reboot
設定確認
cat /sys/module/pcie_aspm/parameters/policy
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
Wi-Fi 7
MLO (Multi Link Operation)
MLO設定
動作確認:25.12.0-rc4

wireless-mlo-openwrt
- /etc/config/wireless
#!/bin/sh
# MLO Configuration for BPI-R4
# Based on: github.com/danpawlik/openwrt-builder/blob/master/settings-configs/BPI-R4/wireless-mlo-openwrt
SSID='ばなな'
WPA_KEY='password'
COUNTRY='JP'
# バックアップ作成
cp /etc/config/wireless /etc/config/wireless.mlo.bak
# UCI batch設定
uci -q batch << EOF
# 既存の個別インターフェース削除
delete wireless.default_radio0
delete wireless.default_radio1
delete wireless.default_radio2
# radio0: 2.4GHz
set wireless.radio0.disabled='0'
set wireless.radio0.band='2g'
set wireless.radio0.channel='1'
set wireless.radio0.htmode='EHT20'
set wireless.radio0.country='${COUNTRY}'
set wireless.radio0.rnr='1'
# radio1: 5GHz
set wireless.radio1.disabled='0'
set wireless.radio1.band='5g'
set wireless.radio1.channel='36'
set wireless.radio1.htmode='EHT80'
set wireless.radio1.country='${COUNTRY}'
set wireless.radio1.rnr='1'
set wireless.radio1.background_radar='1'
# radio2: 6GHz
set wireless.radio2.disabled='0'
set wireless.radio2.band='6g'
set wireless.radio2.channel='auto'
set wireless.radio2.htmode='EHT160'
set wireless.radio2.country='${COUNTRY}'
set wireless.radio2.rnr='1'
# MLO統合インターフェース
set wireless.wifinet0='wifi-iface'
add_list wireless.wifinet0.device='radio0'
add_list wireless.wifinet0.device='radio1'
add_list wireless.wifinet0.device='radio2'
set wireless.wifinet0.mlo='1'
set wireless.wifinet0.network='lan'
set wireless.wifinet0.mode='ap'
set wireless.wifinet0.ssid='${SSID}'
set wireless.wifinet0.encryption='sae'
set wireless.wifinet0.key='${WPA_KEY}'
set wireless.wifinet0.ieee80211w='2'
commit wireless
EOF
wifi reload
echo "MLO設定完了"
- 2.4GHz除外設定
#!/bin/sh
# MLO Configuration for BPI-R4 (5GHz + 6GHz)
# Tested on: OpenWrt 25.12.0-rc5, r32673-482ba7230a
# Note: 2.4GHz is excluded from MLO (disabled)
SSID='ばなな'
WPA_KEY='password'
COUNTRY='JP'
# バックアップ作成
cp /etc/config/wireless /etc/config/wireless.mlo.bak
# UCI batch設定
uci -q batch << EOF
# 既存の個別インターフェース削除
delete wireless.default_radio0
delete wireless.default_radio1
delete wireless.default_radio2
# radio0: 2.4GHz (MLO非対応のため無効化)
set wireless.radio0.disabled='1'
set wireless.radio0.country='${COUNTRY}'
# radio1: 5GHz (MLO link ID 1)
set wireless.radio1.disabled='0'
set wireless.radio1.band='5g'
set wireless.radio1.channel='36'
set wireless.radio1.htmode='EHT80'
set wireless.radio1.country='${COUNTRY}'
set wireless.radio1.rnr='1'
set wireless.radio1.background_radar='1'
# radio2: 6GHz (MLO link ID 2)
set wireless.radio2.disabled='0'
set wireless.radio2.band='6g'
set wireless.radio2.channel='5'
set wireless.radio2.htmode='EHT320'
set wireless.radio2.country='${COUNTRY}'
set wireless.radio2.rnr='1'
# MLO統合インターフェース (5GHz + 6GHz)
set wireless.mlo='wifi-iface'
add_list wireless.mlo.device='radio1'
add_list wireless.mlo.device='radio2'
set wireless.mlo.mlo='1'
set wireless.mlo.network='lan'
set wireless.mlo.mode='ap'
set wireless.mlo.ssid='${SSID}'
set wireless.mlo.encryption='sae'
set wireless.mlo.key='${WPA_KEY}'
set wireless.mlo.ieee80211w='2'
commit wireless
EOF
wifi up
echo "MLO設定完了"
# 確認
echo "--- 設定確認 ---"
uci show wireless
echo "--- インターフェース確認 ---"
iw dev
echo "--- station dump確認 ---"
iw dev ap-mld0 station dump
- 復元
cp /etc/config/wireless.mlo.bak /etc/config/wireless
uci commit wireless
wifi reload
echo "復元完了"
Wi-Fi 6
高速ローミング構成 (usteer + 802.11r/k/v)
#!/bin/sh
I18N="ja"
SSID='ばなな'
WIFI_KEY='password'
COUNTRY='JP'
MOBILITY_DOMAIN='1234'
BANDS="2g 5g 6g"
HTMODES="HE20 HE80 HE160"
TXPOWERS="10 15"
CHANNELS="1 auto auto"
NASIDS="ap1-2g ap1-5g ap1-6g"
SNR="30 20 15"
PKGS="luci-i18n-usteer-${I18N}"
command -v opkg && { opkg list-installed | grep -q "$PKGS" || { opkg update && opkg install $PKGS; }; }
command -v apk && { apk list -I 2>/dev/null | grep -q "$PKGS" || { apk update && apk add $PKGS; }; }
cp /etc/config/wireless /etc/config/wireless.usteer.bak
rm /etc/config/wireless
wifi config
NUM_IFACES=$(grep -c "^config wifi-device" /etc/config/wireless)
i=0
while [ $i -lt $NUM_IFACES ]; do
iface="default_radio${i}"
radio="radio${i}"
band=$(echo $BANDS | awk -v n=$((i+1)) '{print $n}')
htmode=$(echo $HTMODES | awk -v n=$((i+1)) '{print $n}')
txpower=$(echo $TXPOWERS | awk -v n=$((i+1)) '{print $n}')
nasid=$(echo $NASIDS | awk -v n=$((i+1)) '{print $n}')
min_snr=$(echo $SNR | awk -v n=$((i+1)) '{print $n}')
channel=$(echo $CHANNELS | awk -v n=$((i+1)) '{print $n}')
uci -q batch << EOF
set wireless.${radio}.band=${band}
set wireless.${radio}.channel=${channel}
set wireless.${radio}.htmode=${htmode}
set wireless.${radio}.country=${COUNTRY}
set wireless.${radio}.disabled=0
set wireless.${iface}.device=${radio}
set wireless.${iface}.network=lan
set wireless.${iface}.mode=ap
set wireless.${iface}.ssid=${SSID}
set wireless.${iface}.encryption=sae
set wireless.${iface}.key=${WIFI_KEY}
set wireless.${iface}.isolate=1
set wireless.${iface}.ocv=1
set wireless.${iface}.ieee80211r=1
set wireless.${iface}.mobility_domain=${MOBILITY_DOMAIN}
set wireless.${iface}.ft_over_ds=1
set wireless.${iface}.nasid=${nasid}
set wireless.${iface}.usteer_min_snr=${min_snr}
set wireless.${iface}.ieee80211k=1
set wireless.${iface}.ieee80211v=1
set wireless.${iface}.disabled=0
EOF
[ -n "$txpower" ] && uci set wireless.$radio.txpower="$txpower"
[ "$band" = "5g" ] && uci set wireless.$radio.background_radar='1' && uci set wireless.$iface.ft_psk_generate_local='1'
i=$((i+1))
done
uci -q batch << EOF
set usteer.@usteer[0].roam_scan_snr=-65
set usteer.@usteer[0].signal_diff_threshold=8
commit
EOF
/etc/init.d/usteer enable
/etc/init.d/usteer start
wifi reload
- 復元
#!/bin/sh
/etc/init.d/usteer stop
/etc/init.d/usteer disable
cp /etc/config/wireless.usteer.bak /etc/config/wireless
rm -f /etc/config/usteer
opkg remove luci-app-usteer usteer
uci commit wireless
wifi reload
PCIe2
PCIeモード無効化(USBモード化)
#!/bin/sh
PKG="u-boot-envtools"
if command -v opkg >/dev/null 2>&1; then
opkg update
opkg install $PKG
elif command -v apk >/dev/null 2>&1; then
apk update
apk add $PKG
else
echo "パッケージマネージャが見つかりません。"
exit 1
fi
cat <<'EOF' > /etc/init.d/bootconf
#!/bin/sh /etc/rc.common
START=10
boot() {
fw_setenv bootconf_extra 'mt7988a-bananapi-bpi-r4-disable-pcie2'
}
EOF
chmod +x /etc/init.d/bootconf
/etc/init.d/bootconf enable
echo "rebootしてください。次回起動時に反映されます。"
パーツ
ACアダプター
UCB Type-C PD 20V
-
純正ACアダプター:
12V/5.2A or 19V 3.2A -
PD 20V: 65Wアダプター
PC-VP-BP143:20V/3.25A,15V/3A,9V/3A,5V/3A
EC-AC8565BK:20V/3.25A,15V/3A,12V/3A,9V/3A,5V/3A
ファン
BPI-R4用ファン確認
- ハードウェアモニタ(hwmon)デバイス一覧
ls -l /sys/class/hwmon/
- ファンPWM値の現在値確認
cat /sys/class/hwmon/hwmon1/pwm1
- ファンPWM制御の状態確認
cat /sys/class/hwmon/hwmon1/pwm1_enable
- サーマルゾーン(温度トリップポイント)の種類確認
cat /sys/class/thermal/thermal_zone0/trip_point_0_type # クリティカル: 100%
cat /sys/class/thermal/thermal_zone0/trip_point_1_type # ホット
cat /sys/class/thermal/thermal_zone0/trip_point_2_type # アクティブ: 50%
cat /sys/class/thermal/thermal_zone0/trip_point_3_type # アクティブ: 30%
cat /sys/class/thermal/thermal_zone0/trip_point_4_type # アクティブ: 0%
- サーマルゾーン(温度トリップポイント)の温度設定確認
cat /sys/class/thermal/thermal_zone0/trip_point_0_temp # 臨界: 125℃
cat /sys/class/thermal/thermal_zone0/trip_point_1_temp # 高: 120℃
cat /sys/class/thermal/thermal_zone0/trip_point_2_temp # 高: 115℃
cat /sys/class/thermal/thermal_zone0/trip_point_3_temp # 中: 85℃
cat /sys/class/thermal/thermal_zone0/trip_point_4_temp # 低: 40℃
BPI-R4用ファンスクリプト
- pwmfan
# /etc/init.d/pwmfan
cat <<'EOF' > /etc/init.d/pwmfan
#!/bin/sh /etc/rc.common
START=99
PIDFILE=/var/run/pwmfan.pid
start() {
if [ -f $PIDFILE ]; then
PID=$(cat $PIDFILE 2>/dev/null)
if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
echo "Already running"
return 1
else
rm -f $PIDFILE
fi
fi
/usr/bin/pwmfan-loop &
echo $! > $PIDFILE
}
stop() {
if [ -f $PIDFILE ]; then
PID=$(cat $PIDFILE 2>/dev/null)
if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
kill $PID
fi
rm -f $PIDFILE
fi
}
restart() {
stop
sleep 1
start
}
EOF
chmod 755 /etc/init.d/pwmfan
# /usr/bin/pwmfan-loop
cat <<'EOF' > /usr/bin/pwmfan-loop
#!/bin/sh
CONFIG=pwmfan
SECTION="pwmfan"
get_temp() {
local temp
temp=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null)
[ -z "$temp" ] && temp=0
echo $((temp / 1000))
}
set_pwm() {
local pwm="$1"
echo 1 > /sys/class/hwmon/hwmon1/pwm1_enable
echo $pwm > /sys/class/hwmon/hwmon1/pwm1
}
read_config() {
INTERVAL=$(uci get ${CONFIG}.@${SECTION}[0].interval 2>/dev/null)
[ -z "$INTERVAL" ] && INTERVAL=30
TRIP_TEMP=$(uci get ${CONFIG}.@${SECTION}[0].trip_temp 2>/dev/null)
TRIP_PWM=$(uci get ${CONFIG}.@${SECTION}[0].trip_pwm 2>/dev/null)
MINPWM=$(uci get ${CONFIG}.@${SECTION}[0].minpwm 2>/dev/null)
[ -z "$MINPWM" ] && MINPWM=100
MAXPWM=$(uci get ${CONFIG}.@${SECTION}[0].maxpwm 2>/dev/null)
[ -z "$MAXPWM" ] && MAXPWM=255
if [ -z "$TRIP_TEMP" ] || [ -z "$TRIP_PWM" ]; then
exit 1
fi
case "$INTERVAL" in
''|*[!0-9]*) INTERVAL=30 ;;
esac
}
main_loop() {
read_config
local temp pwm i t p last_pwm=0
set -- $TRIP_TEMP
local trip_count=$#
while true; do
temp=$(get_temp)
pwm=$MINPWM
set -- $TRIP_TEMP
local j=1
for t in $@; do
set -- $TRIP_PWM
p=$(eval "echo \$$j")
[ -z "$p" ] && p=$MINPWM
[ "$temp" -ge "$t" ] && pwm=$p
j=$((j+1))
done
[ "$pwm" -lt "$MINPWM" ] && pwm=$MINPWM
[ "$pwm" -gt "$MAXPWM" ] && pwm=$MAXPWM
if [ "$pwm" != "$last_pwm" ]; then
set_pwm "$pwm"
last_pwm=$pwm
fi
sleep "$INTERVAL"
done
}
main_loop
EOF
chmod 755 /usr/bin/pwmfan-loop
touch /etc/config/pwmfan
uci -q delete pwmfan.@pwmfan[0]
uci -q commit pwmfan
uci -q add pwmfan pwmfan
uci -q set pwmfan.@pwmfan[-1].interval='20'
uci -q set pwmfan.@pwmfan[-1].minpwm='80'
uci -q set pwmfan.@pwmfan[-1].maxpwm='255'
uci -q set pwmfan.@pwmfan[-1].trip_temp='60 70'
uci -q set pwmfan.@pwmfan[-1].trip_pwm='128 255'
uci -q commit pwmfan
/etc/init.d/pwmfan enable
/etc/init.d/pwmfan restart
# /usr/bin/fan-status
cat <<'EOF' > /usr/bin/fan-status
#!/bin/sh
TEMP_RAW=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null)
TEMP_C=$(awk "BEGIN {printf \"%.1f\", $TEMP_RAW/1000}")
PWM=$(cat /sys/class/hwmon/hwmon1/pwm1 2>/dev/null)
PWM_PERCENT=$((PWM * 100 / 255))
echo "========================="
echo " Fan & Temperature Status"
echo "-------------------------"
echo " Temperature : ${TEMP_C} °C"
echo " Fan PWM : ${PWM} (${PWM_PERCENT} %)"
echo "========================="
EOF
chmod 755 /usr/bin/fan-status
fan-status
- 監視
while true; do
fan-status
sleep 20
done
- リムーブ
/etc/init.d/pwmfan stop
/etc/init.d/pwmfan disable
rm -f /etc/init.d/pwmfan
rm -f /usr/bin/pwmfan-loop
rm -f /usr/bin/fan-status
uci -q delete pwmfan.@pwmfan[0]
uci -q commit pwmfan
[ ! -s /etc/config/pwmfan ] && rm -f /etc/config/pwmfan
モデム
Fibocom FM350-GL (14c3:4d75)
-
動作環境
Revision: 1.1
OpenWrt: 24.10.2
ModemManager: 1.22.0
kmod-mtk-t7xx: 6.6.93-r1
14C3:4D75: 81600.0000.00.29.18.16_DO
モード: PCIe
SIMスロット: SIM1
キャリア: docomo -
MHF4コネクタ (アンテナ端子)

M: プライマリ/送信 (全利用)
M1: 4×4 MIMO
M2: 4×4 MIMO
D/G: ダイバーシティ/受信 (全利用) -
既知の問題
モデムデバイスは、ルーター本体を完全に断電してから通電させないと、認識しない
※M.2スロットの3.3 V電源ラインはカーネルから制御できず、PCIeリセットピンも露出していない
PCIeモードでは、ATコマンドは送信出来ない
SIM1の青色LEDは、通信が確立しないと点灯しない
SIMトレイがスムースに挿入出来ない場合、SIMが認識しない事がある (ケースネジを緩め要調整) -
モデム設定
#!/bin/sh
WWAN="wwan"
APN="spmode.ne.jp"
ALLOWEDAUTH="chap"
ALLOWEDMODE="5G" # SPモードの場合必須
METRIC="100"
IPTYPE="ipv4v6"
LOGLEVEL="ERR"
IP6ASSIGN="64"
MTU="1500"
SIGNALRATE="120"
INIT_EPSBEARER="default" # SPモードの場合必須
AUTO="0"
cp /etc/config/network /etc/config/network.wwan.bak
cp /etc/config/firewall /etc/config/firewall.wwan.bak
PKGS="kmod-mtk-t7xx modemmanager-rpcd luci-proto-modemmanager pciutils mbim-utils ubus"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
WWAN_IDX=$(uci show network | grep "name='wwan0'" | sed -n "s/network.@device
\[\([0-9]\+\)\]
.*/\1/p")
if [ -n "$WWAN_IDX" ]; then
uci set network.@device[$WWAN_IDX].ipv6='1'
[ -n "$MTU" ] && uci set network.@device[$WWAN_IDX].mtu="${MTU}"
[ -n "$MTU" ] && uci set network.@device[$WWAN_IDX].mtu6="${MTU}"
else
uci add network device
uci set network.@device[-1].name='wwan0'
uci set network.@device[-1].ipv6='1'
[ -n "$MTU" ] && uci set network.@device[-1].mtu="${MTU}"
[ -n "$MTU" ] && uci set network.@device[-1].mtu6="${MTU}"
fi
uci set network.${WWAN}=interface
uci set network.${WWAN}.proto='modemmanager'
uci set network.${WWAN}.apn="${APN}"
uci set network.${WWAN}.allowedauth="${ALLOWEDAUTH}"
uci set network.${WWAN}.allowedmode="${ALLOWEDMODE}"
uci set network.${WWAN}.iptype="${IPTYPE}"
uci set network.${WWAN}.loglevel="${LOGLEVEL}"
uci set network.${WWAN}.metric="${METRIC}"
uci set network.${WWAN}.force_link='1'
uci set network.${WWAN}.ip6assign="${IP6ASSIGN}"
[ -n "$MTU" ] && uci set network.${WWAN}.mtu="${MTU}"
[ -n "$SIGNALRATE" ] && uci set network.${WWAN}.signalrate="${SIGNALRATE}"
uci set network.${WWAN}.auto="${AUTO}"
uci set network.${WWAN}.init_epsbearer="${INIT_EPSBEARER}"
[ -z "$(uci get firewall.@zone[1].network 2>/dev/null | grep -w 'wwan')" ] && uci add_list firewall.@zone[1].network='wwan'
uci commit network
uci commit firewall
/etc/init.d/modemmanager stop
sleep 2
/etc/init.d/modemmanager start
sleep 3
ubus call network reload
sleep 2
ifup wwan
- 復元
cp /etc/config/network.wwan.bak /etc/config/network
cp /etc/config/firewall.wwan.bak /etc/config/firewall
uci commit network
uci commit firewall
# reboot
- デバイス確認
lspci
ls -la /dev/ | grep -E "(cdc|wwan)"
- ネットワークインターフェース確認
ip link show
- ベンダーID、プロダクトID確認
ls /sys/class/net/wwan0/device/
cat /sys/class/net/wwan0/device/../../../modalias
cat /sys/class/net/wwan0/device/../../../uevent
- モデム確認
ubus call modemmanager info
ubus call modemmanager dump
mmcli -L
mmcli -m 0
- 使用可能なすべてのオプション
mbimcli --help-all
- バージョン確認
mbimcli --version
- FCCロック確認
mbimcli -d /dev/wwan0mbim0 --intel-query-fcc-lock
mbimcli -d /dev/wwan0mbim0 --set-radio-state=on
- FCCロック解除(必要な場合)
mbimcli -d /dev/wwan0mbim0 --intel-set-fcc-unlock
/etc/ModemManager/fcc.unlock/
dispatcher-fcc-unlock
MODEM="14c3" # 例
mkdir -p /etc/ModemManager/fcc.unlock/
chmod 644 /etc/ModemManager/fcc.unlock/$MODEM
cat <<'EOF' > /etc/ModemManager/fcc.unlock/$MODEM
# <ここにdispatcher-fcc-unlockの該当ソースを貼る>
EOF
/etc/init.d/modemmanager restart
- モデム有効化(enable)
mmcli -m 0 -e
- ラジオ有効化
mbimcli -d /dev/wwan0mbim0 --set-radio-state=on
- ラジオ状態確認
mbimcli -d /dev/wwan0mbim0 --query-radio-state
- デバイス機能確認
mbimcli -d /dev/wwan0mbim0 --query-device-caps
- SIM状態確認
mbimcli -d /dev/wwan0mbim0 --query-subscriber-ready-status
- ネットワーク登録状態確認
mbimcli -d /dev/wwan0mbim0 --query-registration-state
- 信号強度確認
mmcli -m 0 --signal-get
mbimcli -d /dev/wwan0mbim0 --query-signal-state
- APN設定確認
mbimcli -d /dev/wwan0mbim0 --query-provisioned-contexts
- 接続IP情報
mbimcli -d /dev/wwan0mbim0 -p --query-ip-configuration=0
- モデムの詳細状態確認
mmcli -m 0 --output-keyvalue
- モデムの詳細情報
root@bpi-r4:~# mmcli -m 0
-----------------------------------
General | path: /org/freedesktop/ModemManager1/Modem/0
| device id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----------------------------------
Hardware | manufacturer: generic
| model: MBIM [14C3:4D75]
| firmware revision: 81600.0000.00.29.18.16_DO
| C43
| h/w revision: V1.0.6
| supported: gsm-umts, lte, 5gnr
| current: gsm-umts, lte, 5gnr
| equipment id: XXXXXXXXXXXXXXXX
-----------------------------------
System | device: /sys/devices/platform/soc/11280000.pcie/pci0003:00/0003:00:00.0/0003:01:00.0
| physdev: /sys/devices/platform/soc/11280000.pcie/pci0003:00/0003:00:00.0/0003:01:00.0
| drivers: mtk_t7xx
| plugin: generic
| primary port: wwan0mbim0
| ports: wwan0 (net), wwan0at0 (at), wwan0mbim0 (mbim)
-----------------------------------
Numbers | own: XXXXXXXXXXXX
-----------------------------------
Status | lock: sim-pin2
| unlock retries: sim-pin2 (3)
| state: connected
| power state: on
| access tech: lte, 5gnr
| signal quality: 48% (cached)
-----------------------------------
Modes | supported: allowed: 3g; preferred: none
| allowed: 4g; preferred: none
| allowed: 3g, 4g; preferred: none
| allowed: 5g; preferred: none
| allowed: 3g, 5g; preferred: none
| allowed: 4g, 5g; preferred: none
| allowed: 3g, 4g, 5g; preferred: none
| current: allowed: 5g; preferred: none
-----------------------------------
IP | supported: ipv4, ipv6, ipv4v6
-----------------------------------
3GPP | imei: XXXXXXXXXXXXXXXX
| enabled locks: fixed-dialing
| operator id: 44010
| operator name: NTT DOCOMO
| registration: home
| packet service state: attached
-----------------------------------
3GPP EPS | ue mode of operation: csps-2
| initial bearer path: /org/freedesktop/ModemManager1/Bearer/4
| initial bearer apn: spmode.ne.jp
| initial bearer ip type: ipv4v6
-----------------------------------
3GPP 5GNR | mico mode: disabled
-----------------------------------
SIM | primary sim path: /org/freedesktop/ModemManager1/SIM/0
| sim slot paths: slot 1: /org/freedesktop/ModemManager1/SIM/0 (active)
| slot 2: /org/freedesktop/ModemManager1/SIM/1
-----------------------------------
Bearer | paths: /org/freedesktop/ModemManager1/Bearer/5
root@bpi-r4:~#

Telit LN940 よりは速いが、5Gの速度にしては遅すぎる
モデムリセット(検証専用)
- 動作不安定(セーフモードに入るリスク有)
cat > /etc/modem_power.sh << 'EOF'
#!/bin/sh
pci_reset() {
local pci_path="/sys/bus/pci/devices/0003:01:00.0"
if [ -f "$pci_path/reset" ]; then
echo 1 > "$pci_path/reset"
return 0
else
return 1
fi
}
driver_reset() {
echo "0003:01:00.0" > /sys/bus/pci/drivers/mtk_t7xx/unbind 2>/dev/null
sleep 2
echo "0003:01:00.0" > /sys/bus/pci/drivers/mtk_t7xx/bind 2>/dev/null
sleep 3
}
modem_reset() {
/etc/init.d/modemmanager stop
sleep 2
if ! pci_reset; then
driver_reset
fi
sleep 3
/etc/init.d/modemmanager start
sleep 5
}
check_status() {
lspci | grep -i mediatek | grep 4d75
ls -la /dev/wwan0* 2>/dev/null || echo "なし"
mmcli -L 2>/dev/null || echo "モデムなし"
if mmcli -L 2>/dev/null | grep -q "Modem"; then
mmcli -m 0 2>/dev/null | grep -E "(状態|State|オペレータ|Operator|信号|Signal)" || true
fi
dmesg | grep -i -E "(t7xx|mtk|modem)" | tail -5
}
case "$1" in
reset)
modem_reset
;;
status)
check_status
;;
*)
echo "使用法: $0 {reset|status}"
;;
esac
EOF
chmod +x /etc/modem_power.sh
# モデムリセット
sh /etc/modem_power.sh reset
RTC
RTC有効化
-
バナナパイR4 RTCが動作しない#15766
LIR2032 (充電式電池)
RTCバッテリーボックス (1.25mm: JST)
PKGS="i2c-tools"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
fw_setenv bootconf_extra mt7988a-bananapi-bpi-r4-rtc
Mini PCI Express
AW7916-NPD
#!/bin/sh
command -v opkg && opkg update
command -v apk && apk update
# 不要
REMOVE="kmod-mt7996-firmware kmod-mt7996-233-firmware mt7988-wo-firmware"
command -v opkg && opkg list $REMOVE
command -v apk && apk search $REMOVE
# 必要
REQUIRED="kmod-mt7915e kmod-mt7916-firmware"
command -v opkg && opkg list $REQUIRED
command -v apk && apk search $REQUIRED
フラッシュ&インストールシステム
デバイスアクセス
デバイスアクセス(UCI)
パワーシェルでアクセス
PowerShellの開始
-
パワーシェル起動:キー入力:
Win+x>a>はい -
コンソールログイン (パワーシェル)
※192.168.1.1以外の場合、以下の形式で入力後にワンライナーを入力下さい
$ip="192.168.*.*"
- コンソールログイン (192.168.1.1用)
万能型ワンライナー
if(!$ip){$ip="192.168.1.1"}; ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL -o GlobalKnownHostsFile=NUL -o HostKeyAlgorithms=+ssh-rsa -tt root@$ip
LuCi
初期設定
パスワード
初期値から変更
passwd
Changing password for root
New password:
任意のパスワード
Retype password:
再入力
passwd: password for root changed by root
exit
ホストネーム
ホストネーム(openwrt)を変更
#!/bin/sh
HOSTNAME='openwrt' # デバイス名
uci set system.@system[0].hostname=${HOSTNAME}
uci commit system
/etc/init.d/system reload
NTP
NTPサーバーを変更
#!/bin/sh
POOL='jp'
uci delete system.ntp.server
uci add_list system.ntp.server=0.${POOL}.pool.ntp.org
uci add_list system.ntp.server=1.${POOL}.ppl.ntp.org
uci add_list system.ntp.server=2.${POOL}.pool.ntp.org
uci add_list system.ntp.server=3.${POOL}.pool.ntp.org
uci set system.ntp.enable_server='1'
uci set system.ntp.use_dhcp='0'
uci set system.ntp.interface='lan'
uci commit system
/etc/init.d/sysntpd restart
SSH
WANからのアクセスを遮断
uci set dropbear.@dropbear[0].Interface='lan'
uci commit dropbear
LED
ネットワークアクセスで点灯点滅
#! /bin/sh
uci add system led
uci set system.@led[-1].name='wan'
uci set system.@led[-1].sysfs='green:status'
uci set system.@led[-1].trigger='netdev'
uci set system.@led[-1].dev='br-wan'
uci add_list system.@led[-1].mode='link'
uci add_list system.@led[-1].mode='tx'
uci add_list system.@led[-1].mode='rx'
uci add system led
uci set system.@led[-1].name='br-lan'
uci set system.@led[-1].sysfs='blue:wps'
uci set system.@led[-1].trigger='netdev'
uci set system.@led[-1].dev='br-lan'
uci add_list system.@led[-1].mode='link'
uci add_list system.@led[-1].mode='tx'
uci add_list system.@led[-1].mode='rx'
uci commit system
/etc/init.d/led reload
cronで点灯消灯を時間制御
cat >> /etc/crontabs/root << 'EOF'
# 0時にbr-wan・br-lanのLEDを消灯
0 0 * * * uci set system.@led[0].trigger='none' && uci set system.@led[1].trigger='none' && uci commit system && /etc/init.d/led restart
# 8時にbr-wan・br-lanのLEDを点灯(netdev連動に戻す)
0 8 * * * uci set system.@led[0].trigger='netdev' && uci set system.@led[1].trigger='netdev' && uci commit system && /etc/init.d/led restart
EOF
/etc/init.d/cron restart
パッケージ
母国語サポート
LuCiの言語パッケージをインストール
- 対応言語検索
#! /bin/sh
PATTERN="luci-i18n-base*"
command -v opkg && opkg update && opkg list $PATTERN
command -v apk && apk update && apk search $PATTERN
- 設定
#! /bin/sh
I18N="ja"
PKGS="luci-i18n-base-${I18N} luci-i18n-firewall-${I18N}"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
UCI(TTYD)
ブラウザーでUCIにアクセス
#! /bin/sh
I18N="ja"
PKGS="luci-i18n-ttyd-${I18N}"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
uci set ttyd.@ttyd[0].ipv6='1'
uci set ttyd.@ttyd[0].command='/bin/login -f root' #自動ログイン
uci commit ttyd
/etc/init.d/rpcd restart
ファイラー (filebrowser)
ブラウザでファイルにアクセス
mkdir -p /tmp && wget --no-check-certificate -O /tmp/filebrowser.sh "https://site-u.pages.dev/www/custom-scripts/filebrowser.sh" && chmod +x /tmp/filebrowser.sh && sh /tmp/filebrowser.sh -i
- 管理画面 (初期値)
Web Interface: http://192.168.0.1:8080/
Username:admin
Password:admin12345678
※/etc/config/filebrowserのパスワードは12文字以上必須
ファイラー (openssh-sftp-server)
WinSCPでファイルにアクセス
#! /bin/sh
PKGS="openssh-sftp-server"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
クライアント設定(Windows)
- 手動インストール
- ダウンロード:WinSCP
- 自動インストール
- キー入力:
Win+x>a>はい - 最新版ソフトウェアのインストール
- キー入力:
$psVersion = $PSVersionTable.PSVersion.Major
$LINKS = Invoke-WebRequest "https://winscp.net/eng/download.php"
$LINKS_VERSION = $LINKS.Links | Where-Object {$_.href -like "*WinSCP-*-Setup.exe*"} | Select-Object -ExpandProperty href
$VERSION = ($LINKS_VERSION -split '/')[-2] -replace "WinSCP-([0-9]+\.[0-9]+\.[0-9]+).*", '$1'
Write-Host "Version to install: $VERSION"
$downloadUrl = "https://jaist.dl.sourceforge.net/project/winscp/WinSCP/$VERSION/WinSCP-$VERSION-Setup.exe?viasf=1"
Write-Host "Downloading from: $downloadUrl"
$ONAMAE = (whoami).Split('\')[1]
$destinationPath = "C:\Users\$ONAMAE\Downloads\WinSCP-$VERSION-Setup.exe"
Invoke-WebRequest -Uri $downloadUrl -OutFile $destinationPath
Write-Host "Installing WinSCP..."
Start-Process -FilePath $destinationPath -ArgumentList "/VERYSILENT /NORESTART" -Wait
Invoke-Expression "C:\Users\$ONAMAE\AppData\Local\Programs\WinSCP\WinSCP.exe"
-
警告>強制的に貼り付け -
WinSCP設定
- セッション
- ホスト名:
192.168.1.1 - ユーザー名:
root - パスワード:
設定したパスワード -
ログインをクリック
- ホスト名:
- セッション
CPU負荷分散
インストール
#! /bin/sh
PKGS="irqbalance"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
uci set irqbalance.irqbalance=irqbalance
uci set irqbalance.irqbalance.enabled='1'
uci commit irqbalance
/etc/init.d/irqbalance start
ネットワーク統計インターフェイス
インストール
#! /bin/sh
I18N="ja"
PKGS="luci-i18n-statistics-${I18N}"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
/etc/init.d/collectd enable
/etc/init.d/rpcd restart
- プラグイン検索
#! /bin/sh
PATTERN="collectd-mod\*"
command -v opkg && opkg update && opkg list $PATTERN
command -v apk && apk update && apk search $PATTERN
追加テーマ
インストール
#! /bin/sh
PKGS="luci-theme-openwrt luci-theme-material"
command -v opkg && opkg update && opkg install $PKGS
command -v apk && apk update && apk add $PKGS
AdGuard Home
インストール
- インストール及びリムーブ
mkdir -p /tmp && wget --no-check-certificate -O /tmp/adguardhome.sh "https://site-u.pages.dev/www/custom-scripts/adguardhome.sh" && chmod +x /tmp/adguardhome.sh && sh /tmp/adguardhome.sh
- 管理画面ログイン
http://192.168.1.1:8000/
Webmin
インストール
- webminインストール
#!/bin/sh
set -e
## 1. 変数定義
INSTALL_DIR=/usr/libexec/webmin # Webmin 本体設置先
CONFIG_DIR=/etc/webmin # 設定ディレクトリ
LOG_DIR=/lib/webmin # ログ出力先
PID_DIR=/var/run/webmin # pid 保存先
USER=admin # 管理ユーザー名
PASS=$(tr -dc A-Za-z0-9 </dev/urandom | head -c12) # ランダムパスワード
PORT=10000 # リッスンポート
## 2. 依存パッケージのインストール(SSL 有効化に perl-net-ssleay)
opkg update
BASE_PKGS="
tar gzip unzip shared-mime-info openssl-util
coreutils coreutils-install coreutils-stty coreutils-df
make gawk fdisk patch diffutils binutils-objdump
perl perlbase perlbase-bignum perlbase-commons perlbase-time
perl-test-warn perl-test-harness
"
PERLBASE_PKGS="$(opkg list | awk '/^perlbase-/{print $1}')"
opkg install $BASE_PKGS $PERLBASE_PKGS --force-overwrite
echo "依存パッケージのインストールが完了しました。"
## 3. グループ「bin」の確認/追加
grep -q '^bin:' /etc/group || echo 'bin:x:2:' >> /etc/group
## 4. ディレクトリ作成
mkdir -p ${INSTALL_DIR} ${CONFIG_DIR} ${LOG_DIR} ${PID_DIR}
## 5. Webmin ダウンロード&展開
wget --no-check-certificate -O /tmp/webmin.tar.gz https://www.webmin.com/download/webmin-current.tar.gz
tar xzf /tmp/webmin.tar.gz -C ${INSTALL_DIR} --strip-components=1
## 6. setup.sh の無人化パッチ
# atboot=1 → 0(xinetd 非依存化)
# makeboot=1 行削除
sed -i -e 's/^atboot=1/atboot=0/' -e '/^makeboot=1/d' ${INSTALL_DIR}/setup.sh
## 7. setup.sh を非対話で実行
perl_bin=$(which perl || echo /usr/bin/perl)
os_name="Generic Linux"
os_ver=$(uname -r)
/usr/bin/env bash <<EOF | ${INSTALL_DIR}/setup.sh ${INSTALL_DIR}
${LOG_DIR}
${perl_bin}
${os_name}
${os_ver}
${PORT}
${USER}
${PASS}
${PASS}
n
EOF
## 8. SSL 無効化(SSLeay ライブラリなしでも動くように)
sed -i -e 's/^ssl=1/ssl=0/' ${CONFIG_DIR}/miniserv.conf
## 9. procd/rc.common ベースの init スクリプト作成
cat << 'EOI' > /etc/init.d/webmin
#!/bin/sh /etc/rc.common
START=90
STOP=10
USE_PROCD=1
PIDFILE=/var/run/webmin/miniserv.pid
COMMAND=/etc/webmin/.start-init
start_service() {
procd_open_instance
procd_set_param command ${COMMAND}
procd_set_param pidfile ${PIDFILE}
procd_set_param respawn
procd_close_instance
}
stop_service() {
/etc/webmin/.stop-init
}
reload_service() {
/etc/webmin/.reload-init
}
EOI
chmod +x /etc/init.d/webmin
## 10. サービス有効化&起動
/etc/init.d/webmin enable
/etc/init.d/webmin start
## 完了メッセージ
echo "-------------------------------------------------"
echo "Webmin Installed!"
echo "URL: http://$(ip addr show dev br-lan | grep -Po 'inet \K[\d.]+'):${PORT}/"
echo "User: ${USER}"
echo "Pass: ${PASS}"
echo "Log: ${LOG_DIR}/miniserv.log"
echo "-------------------------------------------------"
- 管理画面ログイン
http://192.168.1.1:10000/
- リムーブ
service webmin stop
rm -rf /etc/init.d/webmin
rm -rf /etc/init.d/webmin.old
sed -i "/bin:x:2:/d" /etc/group
sed -i "/webmin/d" /etc/services
/etc/webmin/uninstall.sh
テスト
iperf3
インストール
#!/bin/sh
TMP=/tmp/aios
mkdir -p "$TMP"
cat > "$TMP"/iperf3_setup.sh << 'SCRIPT_END'
#!/bin/sh
# Usage: ./iperf3_setup.sh [start|stop|restart|enable|disable|status|interactive]
SERVICE_FILE="/etc/init.d/iperf3"
PIDFILE="/var/run/iperf3.pid"
LAN="br-lan"
RED='\033[1;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
BLUE='\033[1;34m'
CYAN='\033[1;36m'
NC='\033[0m'
print_msg() { printf "${1}${2}${NC}\n"; }
get_iface_addrs() {
local flag=0
if ip -4 -o addr show dev "$LAN" scope global 2>/dev/null | grep -q 'inet '; then
NET_ADDR=$(ip -4 -o addr show dev "$LAN" scope global | awk 'NR==1{sub(/\/.*/,"",$4); print $4}')
flag=$((flag | 1))
else
printf "\033[1;33mWarning: No IPv4 address on %s\033[0m\n" "$LAN"
fi
if ip -6 -o addr show dev "$LAN" scope global 2>/dev/null | grep -q 'inet6 '; then
NET_ADDR6_LIST=$(ip -6 -o addr show dev "$LAN" scope global | grep -v temporary | awk 'match($4,/^(2|fd|fc)/){sub(/\/.*/,"",$4); print $4;}')
flag=$((flag | 2))
else
printf "\033[1;33mWarning: No IPv6 address on %s\033[0m\n" "$LAN"
fi
case $flag in
3) FAMILY_TYPE=any ;;
1) FAMILY_TYPE=ipv4 ;;
2) FAMILY_TYPE=ipv6 ;;
*) FAMILY_TYPE="" ;;
esac
}
get_lan_ip() {
get_iface_addrs
if [ -n "$NET_ADDR" ]; then
printf "${NET_ADDR}"
else
printf "192.168.1.1"
fi
}
check_package() {
command -v iperf3 >/dev/null 2>&1 || {
command -v apk >/dev/null 2>&1 && apk info iperf3 >/dev/null 2>&1
} || {
command -v opkg >/dev/null 2>&1 && opkg list-installed | grep -q "^iperf3 "
}
}
check_service() { [ -f "$SERVICE_FILE" ]; }
install_package(){
PKGS="iperf3"
print_msg "$BLUE" "Installing $PKGS package"
command -v opkg >/dev/null 2>&1 && opkg update >/dev/null 2>&1 && opkg install $PKGS && return 0
command -v apk >/dev/null 2>&1 && apk update >/dev/null 2>&1 && apk add $PKGS && return 0
print_msg "$RED" "No supported package manager found (opkg/apk)"
return 1
}
create_service() {
local ip
ip=$(get_lan_ip)
print_msg "$BLUE" "Creating iperf3 service for $ip:5201"
cat > "$SERVICE_FILE" << 'SERVICEEOF'
#!/bin/sh /etc/rc.common
START=95
STOP=01
USE_PROCD=1
PROG=/usr/bin/iperf3
pidfile=/var/run/iperf3.pid
start_service() {
local ip
ip=$(ip -4 -o addr show dev br-lan scope global 2>/dev/null | awk 'NR==1{sub(/\/.*/,"",$4); print $4}')
[ -z "$ip" ] && ip="192.168.1.1"
printf "Starting iperf3 server on %s:5201\n" "$ip"
procd_open_instance
procd_set_param command "$PROG" --server --daemon --pidfile "$pidfile" --bind "$ip"
procd_set_param pidfile "$pidfile"
procd_set_param respawn
procd_close_instance
}
stop_service() {
printf "Stopping iperf3 server\n"
[ -f "$pidfile" ] && {
pid=$(cat "$pidfile" 2>/dev/null)
[ -n "$pid" ] && kill -0 "$pid" 2>/dev/null && {
kill "$pid" 2>/dev/null && printf "iperf3 server stopped\n" || {
printf "Failed to stop iperf3 server (PID: %s)\n" "$pid"; return 1
}
}
rm -f "$pidfile"
}
}
status() {
local ip pid
ip=$(ip -4 -o addr show dev br-lan scope global 2>/dev/null | awk 'NR==1{sub(/\/.*/,"",$4); print $4}')
[ -z "$ip" ] && ip="192.168.1.1"
[ -f "$pidfile" ] && {
pid=$(cat "$pidfile" 2>/dev/null)
[ -n "$pid" ] && kill -0 "$pid" 2>/dev/null && {
printf "iperf3 server is running (PID: %s) on %s:5201\n" "$pid" "$ip"; return 0
}
printf "iperf3 server is not running (stale pidfile)\n"; rm -f "$pidfile"; return 1
} || { printf "iperf3 server is not running\n"; return 1; }
}
SERVICEEOF
chmod +x "$SERVICE_FILE"
print_msg "$GREEN" "Service configured for $ip:5201"
}
install_iperf3() {
print_msg "$BLUE" "Installing iperf3"
command -v iperf3 >/dev/null 2>&1 || install_package iperf3 || { print_msg "$RED" "Package installation failed"; return 1; }
[ -f "$SERVICE_FILE" ] || create_service || { print_msg "$RED" "Service creation failed"; return 1; }
print_msg "$GREEN" "Installation completed"
printf "${CYAN}service iperf3 [enable|start|stop|status]${NC}\n"
printf "${CYAN}Test: iperf3 -c $(get_lan_ip) -t 10${NC}\n"
}
remove_iperf3() {
local auto="$1"
print_msg "$BLUE" "Removing iperf3"
local pkg=false svc=false
check_package && pkg=true
check_service && svc=true
[ "$pkg" = "false" ] && [ "$svc" = "false" ] && { print_msg "$RED" "iperf3 not found"; return 1; }
[ "$auto" != "auto" ] && {
printf "Remove iperf3? (y/N): "
read -r confirm
case "$confirm" in
[yY]*) ;;
*) print_msg "$YELLOW" "Cancelled"; return 0;;
esac
}
[ "$svc" = "true" ] && {
print_msg "$BLUE" "Removing service"
service iperf3 stop 2>/dev/null || true
service iperf3 disable 2>/dev/null || true
rm -f "$SERVICE_FILE" "$PIDFILE"
print_msg "$GREEN" "Service removed"
}
[ "$pkg" = "true" ] && {
print_msg "$BLUE" "Removing package"
if command -v apk >/dev/null 2>&1; then
apk del iperf3 && print_msg "$GREEN" "Package removed" || { print_msg "$RED" "Remove failed"; return 1; }
elif command -v opkg >/dev/null 2>&1; then
opkg remove iperf3 && print_msg "$GREEN" "Package removed" || { print_msg "$RED" "Remove failed"; return 1; }
else
print_msg "$YELLOW" "Cannot remove package - no package manager"
fi
}
print_msg "$GREEN" "Removal completed"
}
show_usage() {
printf "Usage: %s [command]\n\n" "$0"
printf "Commands:\n"
printf " start - Start iperf3 service\n"
printf " stop - Stop iperf3 service\n"
printf " restart - Restart iperf3 service\n"
printf " enable - Enable service at boot\n"
printf " disable - Disable service at boot\n"
printf " status - Show service status\n"
printf " interactive - Interactive mode (default)\n"
printf " help - Show this help\n\n"
printf "Note: Install/Uninstall is determined automatically\n"
}
interactive_mode() {
while true; do
printf "\n${BLUE}iperf3 Management${NC}\n"
check_package && pkg=true || pkg=false
check_service && svc=true || svc=false
if [ "$svc" = "true" ]; then
service iperf3 status >/dev/null 2>&1 && running=true || running=false
else
running=false
fi
if [ "$pkg" = "false" ] || [ "$svc" = "false" ]; then
printf "[1] Install iperf3\n"
printf "[2] Exit\n"
printf "Please select (1-2): "
read -r choice
case "$choice" in
1)
install_iperf3
;;
2)
print_msg "$GREEN" "Goodbye"
break
;;
*)
printf "${RED}Invalid selection: %s${NC}\n" "$choice"
;;
esac
else
printf "[1] Start service [5] Disable service\n"
printf "[2] Stop service [6] Show status\n"
printf "[3] Restart service [7] Remove iperf3\n"
printf "[4] Enable service [8] Exit\n"
printf "Please select (1-8): "
read -r choice
case "$choice" in
1) service iperf3 start;;
2) service iperf3 stop;;
3) service iperf3 restart;;
4)
service iperf3 enable
print_msg "$GREEN" "Enabled at boot"
;;
5)
service iperf3 disable
print_msg "$GREEN" "Disabled at boot"
;;
6)
service iperf3 status
;;
7)
remove_iperf3
;;
8)
print_msg "$GREEN" "Goodbye"
break
;;
*)
printf "${RED}Invalid selection: %s${NC}\n" "$choice"
;;
esac
fi
if [ "$choice" != "2" ] && [ "$choice" != "8" ]; then
printf "\n${CYAN}Press Enter to continue${NC}"
read -r dummy 2>/dev/null || true
fi
done
}
iperf3_main() {
case "${1:-interactive}" in
start|stop|restart)
check_service || {
print_msg "$RED" "Service not configured. Run script to install."
exit 1
}
service iperf3 "$1"
;;
enable|disable)
check_service || {
print_msg "$RED" "Service not configured. Run script to install."
exit 1
}
service iperf3 "$1"
print_msg "$GREEN" "Service ${1}d at boot"
;;
status)
check_service || {
print_msg "$RED" "Service not configured"
exit 1
}
service iperf3 status
printf "\n${CYAN}Server: $(get_lan_ip):5201${NC}\n"
printf "${CYAN}Test: iperf3 -c $(get_lan_ip) -t 10${NC}\n"
;;
interactive)
interactive_mode
;;
auto-toggle)
if check_package || check_service; then
remove_iperf3
else
install_iperf3
fi
;;
help|-h|--help)
show_usage
;;
*)
print_msg "$RED" "Unknown command: $1"
show_usage
exit 1
;;
esac
}
[ "${0##*/}" = "iperf3_setup.sh" ] && iperf3_main "$@"
SCRIPT_END
chmod +x "$TMP"/iperf3_setup.sh
printf "\n${GREEN}=== iperf3 Setup Script Created ===${NC}\n"
printf "${CYAN}Location: $TMP/iperf3_setup.sh${NC}\n"
printf "${YELLOW}Usage: $TMP/iperf3_setup.sh [start|stop|status|help]${NC}\n"
printf "${YELLOW}Interactive: $TMP/iperf3_setup.sh${NC}\n"
printf "\n${BLUE}Running script in interactive mode${NC}\n"
sh "$TMP"/iperf3_setup.sh
- サーバー起動 (2回目以降)
/etc/init.d/iperf3 start
- クライアントで実行
$iperf3 = Get-Command iperf3.exe -ErrorAction SilentlyContinue
if (-not $iperf3) {
$iperf3 = Get-ChildItem -Path $PWD -Filter iperf3.exe -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if ($iperf3) { $iperf3 = $iperf3.FullName }
else {
Write-Host "iperf3.exe が見つかりません。" -ForegroundColor Red
exit 1
}
} else {
$iperf3 = $iperf3.Source
}
$server = (Get-DnsClientServerAddress -AddressFamily IPv4 | Select-Object -ExpandProperty ServerAddresses)[0]
& "$iperf3" -c $server -t 10
- 追加テスト
& "$iperf3" -c $server -t 60 -P 16 -w 2M
- リムーブ
sh /tmp/aios/iperf3_setup.sh auto-toggle
トラブル
初期化
ファクトリーリセット(初期化)
リセット
# 要注意
firstboot && reboot now
This will erase all settings and remove any installed packages. Are you sure? [N/y]
y
デバイスリセットボタン
デバイスのリセットボタンを10秒押し続ける
あとがき
-
BPI-R3より、色々進化している
-
ハードウェアアクセレーターは有効
-
Wi-Fi7はまだまだ成熟していないが、逆にどんどん良くなるのが面白いかな
-
購入について、AliExpressが一番安いが、アフターサービスを考えると、Amazonやエレファインの方が安心かもしれない
-
モデム動かすのに、丸1日掛かった。。。
-
Wi-Fi BEはまだ不安定だが、AXの完成度は高い
※BPI-R3より早いね (アップロードはWANチューニングの問題)

-
BPI-BE1900 なんだか値が張りそうな気がするが
-
AdGuardHomeとWebminのメンテついでに掲載した
-
AW7916-NPDを換装してみた
BPI-R4-NIC-BE14より気持ちSNRが良い程度
ボード側の方に問題がありそうだ
このBPI-R4は文字通り机上の検証用だね -
2026年1月31日
mloが動いた!
が、しかし、、、(6GHz + 2.4GHz)

もとい、、、 (6GHz + 5GHz)

DFSで2Ghz掴んじゃうと、なんかおかしい?











