Last active
May 15, 2026 23:37
-
-
Save nfl0/189222c24b61c75f4aa23e67490ff54b to your computer and use it in GitHub Desktop.
Fix for Intel I219-LM "e1000e Detected Hardware Unit Hang" — NIC randomly drops link on Linux/Proxmox until power-cycle. Idempotent, reboot-persistent script that disables the offload + EEE/LPI triggers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Intel I219-LM / e1000e "Detected Hardware Unit Hang" mitigation. | |
| # | |
| # Symptom: NIC TX engine hangs after hours/days of uptime, link drops, | |
| # only a physical power-cycle recovers it (warm reboot does not). | |
| # Cause: I219 silicon errata exercised by (a) hardware offloads and | |
| # (b) EEE/LPI low-power-idle transitions. We disable BOTH triggers. | |
| # | |
| # Run as root after a fresh Proxmox install. Idempotent + reboot-persistent | |
| # via a systemd oneshot (interface-name independent, survives renames). | |
| # | |
| set -euo pipefail | |
| ETHTOOL=/usr/sbin/ethtool | |
| OFFLOADS="gso off gro off tso off tx off rx off sg off rxvlan off txvlan off" | |
| UNIT=/etc/systemd/system/e1000e-no-offload.service | |
| [[ $EUID -eq 0 ]] || { echo "Run as root." >&2; exit 1; } | |
| command -v "$ETHTOOL" >/dev/null || { apt-get update -qq && apt-get install -y ethtool; } | |
| # Find every NIC bound to the e1000e driver. | |
| mapfile -t NICS < <( | |
| for d in /sys/class/net/*; do | |
| [[ -e "$d/device/driver" ]] || continue | |
| [[ "$(basename "$(readlink -f "$d/device/driver")")" == e1000e ]] && basename "$d" | |
| done | |
| ) | |
| [[ ${#NICS[@]} -gt 0 ]] || { echo "No e1000e NIC found — nothing to do."; exit 0; } | |
| echo "e1000e NIC(s): ${NICS[*]}" | |
| # 1. Apply now (safe, no link drop). | |
| for n in "${NICS[@]}"; do | |
| echo "Disabling offloads + EEE on $n ..." | |
| $ETHTOOL -K "$n" $OFFLOADS || true | |
| $ETHTOOL --set-eee "$n" eee off || true | |
| done | |
| # 2. Persist across reboots, independent of /etc/network/interfaces layout. | |
| cat > "$UNIT" <<EOF | |
| [Unit] | |
| Description=Disable e1000e hardware offloads (I219 hang workaround) | |
| Wants=network-pre.target | |
| Before=network-pre.target | |
| DefaultDependencies=no | |
| [Service] | |
| Type=oneshot | |
| RemainAfterExit=yes | |
| ExecStart=/bin/sh -c 'for d in /sys/class/net/*; do [ -e "\$d/device/driver" ] || continue; [ "\$(basename \$(readlink -f \$d/device/driver))" = e1000e ] || continue; n=\$(basename \$d); $ETHTOOL -K \$n $OFFLOADS || true; $ETHTOOL --set-eee \$n eee off || true; done' | |
| [Install] | |
| WantedBy=multi-user.target | |
| EOF | |
| systemctl daemon-reload | |
| systemctl enable --now e1000e-no-offload.service >/dev/null 2>&1 || systemctl enable e1000e-no-offload.service | |
| # 3. Verify. | |
| echo "--- verification ---" | |
| for n in "${NICS[@]}"; do | |
| echo "[$n]" | |
| $ETHTOOL -k "$n" | grep -E '^(tx-checksumming|rx-checksumming|scatter-gather|tcp-segmentation-offload|generic-segmentation-offload|generic-receive-offload):' | |
| $ETHTOOL --show-eee "$n" 2>/dev/null | grep -E 'EEE status:' || true | |
| done | |
| echo "Done. Persistent via $UNIT" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment