0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenWrt 最適化 ネットワーク パフォーマンス チューニング

Last updated at Posted at 2025-07-20

:flag_jp: Japanese article
OpenWrt_icon.png

はじめに

おススメ管理インターフェース

ネットワークパフォーマンスチューニング

ツール

仕様
  • メモリ・バッファ設定
    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"

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?