mirror of
				https://github.com/community-scripts/ProxmoxVE.git
				synced 2025-11-04 10:22:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			244 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
#!/usr/bin/env bash
 | 
						||
 | 
						||
# Creates a systemd service to disable NIC offloading features for Intel e1000e and e1000 interfaces
 | 
						||
# Author: rcastley
 | 
						||
# License: MIT
 | 
						||
 | 
						||
YW=$(echo "\033[33m")
 | 
						||
YWB=$'\e[93m'
 | 
						||
BL=$(echo "\033[36m")
 | 
						||
RD=$(echo "\033[01;31m")
 | 
						||
BGN=$(echo "\033[4;92m")
 | 
						||
GN=$(echo "\033[1;92m")
 | 
						||
DGN=$(echo "\033[32m")
 | 
						||
CL=$(echo "\033[m")
 | 
						||
TAB="  "
 | 
						||
CM="${TAB}✔️${TAB}"
 | 
						||
CROSS="${TAB}✖️${TAB}"
 | 
						||
INFO="${TAB}ℹ️${TAB}${CL}"
 | 
						||
WARN="${TAB}⚠️${TAB}${CL}"
 | 
						||
 | 
						||
function header_info {
 | 
						||
clear
 | 
						||
cat <<"EOF"
 | 
						||
 | 
						||
    _   ____________   ____  __________                ___                ____  _            __    __
 | 
						||
   / | / /  _/ ____/  / __ \/ __/ __/ /___  ____ _____/ (_)___  ____ _   / __ \(_)________ _/ /_  / /__  _____
 | 
						||
  /  |/ // // /      / / / / /_/ /_/ / __ \/ __ `/ __  / / __ \/ __ `/  / / / / / ___/ __ `/ __ \/ / _ \/ ___/
 | 
						||
 / /|  // // /___   / /_/ / __/ __/ / /_/ / /_/ / /_/ / / / / / /_/ /  / /_/ / (__  ) /_/ / /_/ / /  __/ /
 | 
						||
/_/ |_/___/\____/   \____/_/ /_/ /_/\____/\__,_/\__,_/_/_/ /_/\__, /  /_____/_/____/\__,_/_.___/_/\___/_/
 | 
						||
                                                             /____/
 | 
						||
Enhanced version supporting both e1000e and e1000 drivers
 | 
						||
 | 
						||
EOF
 | 
						||
}
 | 
						||
 | 
						||
header_info
 | 
						||
 | 
						||
function msg_info() { echo -e "${INFO} ${YW}${1}...${CL}"; }
 | 
						||
function msg_ok() { echo -e "${CM} ${GN}${1}${CL}"; }
 | 
						||
function msg_error() { echo -e "${CROSS} ${RD}${1}${CL}"; }
 | 
						||
function msg_warn() { echo -e "${WARN} ${YWB}${1}"; }
 | 
						||
 | 
						||
# Check for root privileges
 | 
						||
if [ "$(id -u)" -ne 0 ]; then
 | 
						||
    msg_error "Error: This script must be run as root."
 | 
						||
    exit 1
 | 
						||
fi
 | 
						||
 | 
						||
if ! command -v ethtool >/dev/null 2>&1; then
 | 
						||
    msg_info "Installing ethtool"
 | 
						||
    apt-get update &>/dev/null
 | 
						||
    apt-get install -y ethtool &>/dev/null || { msg_error "Failed to install ethtool. Exiting."; exit 1; }
 | 
						||
    msg_ok "ethtool installed successfully"
 | 
						||
fi
 | 
						||
 | 
						||
# Get list of network interfaces using Intel e1000e or e1000 drivers
 | 
						||
INTERFACES=()
 | 
						||
COUNT=0
 | 
						||
 | 
						||
msg_info "Searching for Intel e1000e and e1000 interfaces"
 | 
						||
 | 
						||
for device in /sys/class/net/*; do
 | 
						||
    interface="$(basename "$device")"  # or adjust the rest of the usages below, as mostly you'll use the path anyway
 | 
						||
    # Skip loopback interface and virtual interfaces
 | 
						||
    if [[ "$interface" != "lo" ]] && [[ ! "$interface" =~ ^(tap|fwbr|veth|vmbr|bonding_masters) ]]; then
 | 
						||
        # Check if the interface uses the e1000e or e1000 driver
 | 
						||
        driver=$(basename $(readlink -f /sys/class/net/$interface/device/driver 2>/dev/null) 2>/dev/null)
 | 
						||
        
 | 
						||
        if [[ "$driver" == "e1000e" ]] || [[ "$driver" == "e1000" ]]; then
 | 
						||
            # Get MAC address for additional identification
 | 
						||
            mac=$(cat /sys/class/net/$interface/address 2>/dev/null)
 | 
						||
            INTERFACES+=("$interface" "Intel $driver NIC ($mac)")
 | 
						||
            ((COUNT++))
 | 
						||
        fi
 | 
						||
    fi
 | 
						||
done
 | 
						||
 | 
						||
# Check if any Intel e1000e/e1000 interfaces were found
 | 
						||
if [ ${#INTERFACES[@]} -eq 0 ]; then
 | 
						||
    whiptail --title "Error" --msgbox "No Intel e1000e or e1000 network interfaces found!" 10 60
 | 
						||
    msg_error "No Intel e1000e or e1000 network interfaces found! Exiting."
 | 
						||
    exit 1
 | 
						||
fi
 | 
						||
 | 
						||
msg_ok "Found ${BL}$COUNT${GN} Intel e1000e/e1000 interfaces"
 | 
						||
 | 
						||
# Create a checklist for interface selection with all interfaces initially checked
 | 
						||
INTERFACES_CHECKLIST=()
 | 
						||
for ((i=0; i<${#INTERFACES[@]}; i+=2)); do
 | 
						||
    INTERFACES_CHECKLIST+=("${INTERFACES[i]}" "${INTERFACES[i+1]}" "ON")
 | 
						||
done
 | 
						||
 | 
						||
# Show interface selection checklist
 | 
						||
SELECTED_INTERFACES=$(whiptail --backtitle "Intel e1000e/e1000 NIC Offloading Disabler" --title "Network Interfaces" \
 | 
						||
    --separate-output --checklist "Select Intel e1000e/e1000 network interfaces\n(Space to toggle, Enter to confirm):" 15 80 6 \
 | 
						||
    "${INTERFACES_CHECKLIST[@]}" 3>&1 1>&2 2>&3)
 | 
						||
 | 
						||
exitstatus=$?
 | 
						||
if [ $exitstatus != 0 ]; then
 | 
						||
    msg_info "User canceled. Exiting."
 | 
						||
    exit 0
 | 
						||
fi
 | 
						||
 | 
						||
# Check if any interfaces were selected
 | 
						||
if [ -z "$SELECTED_INTERFACES" ]; then
 | 
						||
    msg_error "No interfaces selected. Exiting."
 | 
						||
    exit 0
 | 
						||
fi
 | 
						||
 | 
						||
# Convert the selected interfaces into an array
 | 
						||
readarray -t INTERFACE_ARRAY <<< "$SELECTED_INTERFACES"
 | 
						||
 | 
						||
# Show the number of selected interfaces
 | 
						||
INTERFACE_COUNT=${#INTERFACE_ARRAY[@]}
 | 
						||
 | 
						||
# Print selected interfaces with their driver types
 | 
						||
for iface in "${INTERFACE_ARRAY[@]}"; do
 | 
						||
    driver=$(basename $(readlink -f /sys/class/net/$iface/device/driver 2>/dev/null) 2>/dev/null)
 | 
						||
    msg_ok "Selected interface: ${BL}$iface${GN} (${BL}$driver${GN})"
 | 
						||
done
 | 
						||
 | 
						||
# Ask for confirmation with the list of selected interfaces
 | 
						||
CONFIRMATION_MSG="You have selected the following interface(s):\n\n"
 | 
						||
for iface in "${INTERFACE_ARRAY[@]}"; do
 | 
						||
    SPEED=$(cat /sys/class/net/$iface/speed 2>/dev/null || echo "Unknown")
 | 
						||
    MAC=$(cat /sys/class/net/$iface/address 2>/dev/null)
 | 
						||
    DRIVER=$(basename $(readlink -f /sys/class/net/$iface/device/driver 2>/dev/null) 2>/dev/null)
 | 
						||
    CONFIRMATION_MSG+="- $iface (Driver: $DRIVER, MAC: $MAC, Speed: ${SPEED}Mbps)\n"
 | 
						||
done
 | 
						||
CONFIRMATION_MSG+="\nThis will create systemd service(s) to disable offloading features.\n\nProceed?"
 | 
						||
 | 
						||
if ! whiptail --backtitle "Intel e1000e/e1000 NIC Offloading Disabler" --title "Confirmation" \
 | 
						||
    --yesno "$CONFIRMATION_MSG" 20 80; then
 | 
						||
    msg_info "User canceled. Exiting."
 | 
						||
    exit 0
 | 
						||
fi
 | 
						||
 | 
						||
# Loop through all selected interfaces and create services for each
 | 
						||
for SELECTED_INTERFACE in "${INTERFACE_ARRAY[@]}"; do
 | 
						||
    # Get the driver type for this specific interface
 | 
						||
    DRIVER=$(basename $(readlink -f /sys/class/net/$SELECTED_INTERFACE/device/driver 2>/dev/null) 2>/dev/null)
 | 
						||
    
 | 
						||
    # Create service name for this interface
 | 
						||
    SERVICE_NAME="disable-nic-offload-$SELECTED_INTERFACE.service"
 | 
						||
    SERVICE_PATH="/etc/systemd/system/$SERVICE_NAME"
 | 
						||
    
 | 
						||
    # Create the service file with driver-specific optimizations
 | 
						||
    msg_info "Creating systemd service for interface: ${BL}$SELECTED_INTERFACE${YW} (${BL}$DRIVER${YW})"
 | 
						||
    
 | 
						||
    # Start with the common part of the service file
 | 
						||
    cat > "$SERVICE_PATH" << EOF
 | 
						||
[Unit]
 | 
						||
Description=Disable NIC offloading for Intel $DRIVER interface $SELECTED_INTERFACE
 | 
						||
After=network.target
 | 
						||
 | 
						||
[Service]
 | 
						||
Type=oneshot
 | 
						||
# Disable all offloading features for Intel $DRIVER
 | 
						||
ExecStart=/sbin/ethtool -K $SELECTED_INTERFACE gso off gro off tso off tx off rx off rxvlan off txvlan off sg off
 | 
						||
RemainAfterExit=true
 | 
						||
 | 
						||
[Install]
 | 
						||
WantedBy=multi-user.target
 | 
						||
EOF
 | 
						||
 | 
						||
    # Check if service file was created successfully
 | 
						||
    if [ ! -f "$SERVICE_PATH" ]; then
 | 
						||
        whiptail --title "Error" --msgbox "Failed to create service file for $SELECTED_INTERFACE!" 10 50
 | 
						||
        msg_error "Failed to create service file for $SELECTED_INTERFACE! Skipping to next interface."
 | 
						||
        continue
 | 
						||
    fi
 | 
						||
 | 
						||
    # Configure this service
 | 
						||
    {
 | 
						||
        echo "25"; sleep 0.2
 | 
						||
        # Reload systemd to recognize the new service
 | 
						||
        systemctl daemon-reload
 | 
						||
        echo "50"; sleep 0.2
 | 
						||
        # Start the service
 | 
						||
        systemctl start "$SERVICE_NAME"
 | 
						||
        echo "75"; sleep 0.2
 | 
						||
        # Enable the service to start on boot
 | 
						||
        systemctl enable "$SERVICE_NAME"
 | 
						||
        echo "100"; sleep 0.2
 | 
						||
    } | whiptail --backtitle "Intel e1000e/e1000 NIC Offloading Disabler" --gauge "Configuring service for $SELECTED_INTERFACE..." 10 80 0
 | 
						||
 | 
						||
    # Individual service status
 | 
						||
    if systemctl is-active --quiet "$SERVICE_NAME"; then
 | 
						||
        SERVICE_STATUS="Active"
 | 
						||
    else
 | 
						||
        SERVICE_STATUS="Inactive"
 | 
						||
    fi
 | 
						||
 | 
						||
    if systemctl is-enabled --quiet "$SERVICE_NAME"; then
 | 
						||
        BOOT_STATUS="Enabled"
 | 
						||
    else
 | 
						||
        BOOT_STATUS="Disabled"
 | 
						||
    fi
 | 
						||
 | 
						||
    # Show individual service results
 | 
						||
    msg_ok "Service for ${BL}$SELECTED_INTERFACE${GN} (${BL}$DRIVER${GN}) created and enabled!"
 | 
						||
    msg_info "${TAB}Service: ${BL}$SERVICE_NAME${YW}"
 | 
						||
    msg_info "${TAB}Status: ${BL}$SERVICE_STATUS${YW}"
 | 
						||
    msg_info "${TAB}Start on boot: ${BL}$BOOT_STATUS${YW}"
 | 
						||
done
 | 
						||
 | 
						||
# Prepare summary of all interfaces
 | 
						||
SUMMARY_MSG="Services created successfully!\n\n"
 | 
						||
SUMMARY_MSG+="Configured Interfaces:\n"
 | 
						||
 | 
						||
for iface in "${INTERFACE_ARRAY[@]}"; do
 | 
						||
    SERVICE_NAME="disable-nic-offload-$iface.service"
 | 
						||
    DRIVER=$(basename $(readlink -f /sys/class/net/$iface/device/driver 2>/dev/null) 2>/dev/null)
 | 
						||
    
 | 
						||
    if systemctl is-active --quiet "$SERVICE_NAME"; then
 | 
						||
        SVC_STATUS="Active"
 | 
						||
    else
 | 
						||
        SVC_STATUS="Inactive"
 | 
						||
    fi
 | 
						||
 | 
						||
    if systemctl is-enabled --quiet "$SERVICE_NAME"; then
 | 
						||
        BOOT_SVC_STATUS="Enabled"
 | 
						||
    else
 | 
						||
        BOOT_SVC_STATUS="Disabled"
 | 
						||
    fi
 | 
						||
 | 
						||
    SUMMARY_MSG+="- $iface ($DRIVER): $SVC_STATUS, Boot: $BOOT_SVC_STATUS\n"
 | 
						||
done
 | 
						||
 | 
						||
# Show summary results
 | 
						||
whiptail --backtitle "Intel e1000e/e1000 NIC Offloading Disabler" --title "Success" --msgbox "$SUMMARY_MSG" 22 80
 | 
						||
 | 
						||
msg_ok "Intel e1000e/e1000 optimization complete for ${#INTERFACE_ARRAY[@]} interface(s)!"
 | 
						||
 | 
						||
# Show verification commands
 | 
						||
echo ""
 | 
						||
msg_info "Verification commands:"
 | 
						||
for iface in "${INTERFACE_ARRAY[@]}"; do
 | 
						||
    echo -e "${TAB}${BL}ethtool -k $iface${CL} ${YW}# Check offloading status${CL}"
 | 
						||
    echo -e "${TAB}${BL}systemctl status disable-nic-offload-$iface.service${CL} ${YW}# Check service status${CL}"
 | 
						||
done
 | 
						||
 | 
						||
exit 0
 |