#!/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 } # Telemetry source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "nic-offloading-fix" "pve" 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 104 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 237 } 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 236 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" </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