I sat down to do some work on one of my lab hosts and found I could no longer ssh to it. I went to the console and the system was up and responsive, but I could not ping anything: not the gateway, not another host on the same subnet, nothing. On top of that, the console was scrolling a steady stream of kernel messages that kept repeating every couple of seconds.
A host that is alive but completely cut off from the network turns into guesswork very quickly. Is it the switch port, the cable, the DHCP lease, or the host itself? In this case it turned out to be the network card driver, and the fix was a one line change. Let's walk through what I saw, what the messages mean, and how to make the fix survive a reboot.
The Error Messages
This is what was streaming across the console. The host is named asus2, the interface is eno1, and the messages repeat roughly every two seconds:
Oct 22 15:38:24 asus2 kernel: e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:#012 TDH <da>#012 TDT <5>#012 next_to_use <5>#012 next_to_clean <d9>#012buffer_info[next_to_clean]:#012 time_stamp <1d38993a8>#012 next_to_watch <da>#012 jiffies <1d3a2b4c0>#012 next_to_watch.status <0>#012MAC Status <80083>#012PHY Status <796d>#012PHY 1000BASE-T Status <3800>#012PHY Extended Status <3000>#012PCI Status <10>
Oct 22 15:38:26 asus2 kernel: e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:#012 TDH <da>#012 TDT <5>#012 next_to_use <5>#012 next_to_clean <d9>#012buffer_info[next_to_clean]:#012 time_stamp <1d38993a8>#012 next_to_watch <da>#012 jiffies <1d3a2bcc0>#012 next_to_watch.status <0>#012MAC Status <80083>#012PHY Status <796d>#012PHY 1000BASE-T Status <3800>#012PHY Extended Status <3000>#012PCI Status <10>
Oct 22 15:38:28 asus2 kernel: e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:#012 TDH <da>#012 TDT <5>#012 next_to_use <5>#012 next_to_clean <d9>#012buffer_info[next_to_clean]:#012 time_stamp <1d38993a8>#012 next_to_watch <da>#012 jiffies <1d3a2c480>#012 next_to_watch.status <0>#012MAC Status <80083>#012PHY Status <796d>#012PHY 1000BASE-T Status <3800>#012PHY Extended Status <3000>#012PCI Status <10>
Oct 22 15:38:30 asus2 kernel: e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:#012 TDH <da>#012 TDT <5>#012 next_to_use <5>#012 next_to_clean <d9>#012buffer_info[next_to_clean]:#012 time_stamp <1d38993a8>#012 next_to_watch <da>#012 jiffies <1d3a2cc40>#012 next_to_watch.status <0>#012MAC Status <80083>#012PHY Status <796d>#012PHY 1000BASE-T Status <3800>#012PHY Extended Status <3000>#012PCI Status <10>
Oct 22 15:38:32 asus2 kernel: e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:#012 TDH <da>#012 TDT <5>#012 next_to_use <5>#012 next_to_clean <d9>#012buffer_info[next_to_clean]:#012 time_stamp <1d38993a8>#012 next_to_watch <da>#012 jiffies <1d3a2d401>#012 next_to_watch.status <0>#012MAC Status <80083>#012PHY Status <796d>#012PHY 1000BASE-T Status <3800>#012PHY Extended Status <3000>#012PCI Status <10>
Oct 22 15:38:34 asus2 kernel: e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:#012 TDH <da>#012 TDT <5>#012 next_to_use <5>#012 next_to_clean <d9>#012buffer_info[next_to_clean]:#012 time_stamp <1d38993a8>#012 next_to_watch <da>#012 jiffies <1d3a2dc00>#012 next_to_watch.status <0>#012MAC Status <80083>#012PHY Status <796d>#012PHY 1000BASE-T Status <3800>#012PHY Extended Status <3000>#012PCI Status <10>
Oct 22 15:38:36 asus2 kernel: e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:#012 TDH <da>#012 TDT <5>#012 next_to_use <5>#012 next_to_clean <d9>#012buffer_info[next_to_clean]:#012 time_stamp <1d38993a8>#012 next_to_watch <da>#012 jiffies <1d3a2e3c0>#012 next_to_watch.status <0>#012MAC Status <80083>#012PHY Status <796d>#012PHY 1000BASE-T Status <3800>#012PHY Extended Status <3000>#012PCI Status <10>
Oct 22 15:38:38 asus2 kernel: e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:#012 TDH <da>#012 TDT <5>#012 next_to_use <5>#012 next_to_clean <d9>#012buffer_info[next_to_clean]:#012 time_stamp <1d38993a8>#012 next_to_watch <da>#012 jiffies <1d3a2eb80>#012 next_to_watch.status <0>#012MAC Status <80083>#012PHY Status <796d>#012PHY 1000BASE-T Status <3800>#012PHY Extended Status <3000>#012PCI Status <10>
Oct 22 15:38:40 asus2 kernel: e1000e 0000:00:1f.6 eno1: Detected Hardware Unit Hang:#012 TDH <da>#012 TDT <5>#012 next_to_use <5>#012 next_to_clean <d9>#012buffer_info[next_to_clean]:#012 time_stamp <1d38993a8>#012 next_to_watch <da>#012 jiffies <1d3a2f340>#012 next_to_watch.status <0>#012MAC Status <80083>#012PHY Status <796d>#012PHY 1000BASE-T Status <3800>#012PHY Extended Status <3000>#012PCI Status <10>
The Error Messages Meaning
The first thing to pull out of those lines is the device. e1000e 0000:00:1f.6 eno1 is the Intel network controller built into the motherboard, handled by the e1000e driver, and eno1 is the interface name the system gave it. The messages come from the kernel, so this is the driver talking, not an application.
"Detected Hardware Unit Hang" is the driver telling us it queued packets for transmit and the network card never finished sending them. The transmit descriptor ring has a head and a tail. The tail (TDT, here <5>) is where the driver is adding new work and the head (TDH, here <da>) is where the hardware has gotten to. Healthy hardware keeps chasing the tail. Here the head never moves: next_to_clean is <d9>, next_to_watch is <da>, and the time_stamp stays at <1d38993a8> in every message while jiffies keeps counting up. In other words, the same descriptor has been sitting there for a long time.
The other detail that matters is that the link itself looks healthy. The MAC Status of <80083> and the PHY Status of <796d> along with PHY 1000BASE-T Status tell us the link is up at gigabit speed. Only the transmit path is wedged. That fits my symptoms: the host was up and the console was alive, but nothing I tried to send ever left the machine, which is why ssh to the host failed and ping got no replies. The driver repeats the message every two seconds until it manages to reset the adapter, and on this host that was not enough to recover.
Note: I cannot prove a root cause from this log alone. What I can say is that this pattern is a well documented e1000e problem, and the next section covers what usually causes it.
Common Triggers
There is no single cause, but these are the ones that come up most often with the e1000e driver on Intel onboard controllers:
- TCP segmentation offload settings (TSO, GSO and GRO). Bugs in how the driver handles offloaded segmentation are one of the most commonly reported triggers.
- Power management on the card or the PCIe link, such as Energy Efficient Ethernet (EEE) or Active State Power Management (ASPM). EEE lets the card and the switch port drop into a low power idle state, and on some controllers the transmit path does not wake back up cleanly.
- Less often, an old driver, kernel or BIOS and Intel Management Engine firmware, or a failing card or cable.
It is also worth thinking about what else depends on the port. On a host that runs virtual machines, a hung port stalls the networking of everything behind it, not just the host. This particular setup does host multiple virtual machines across a bridge port.
Resolution
Before changing anything it helps to see what is currently enabled. We can check the driver details and the current offload and EEE settings with:
ethtool -i eno1
ethtool -k eno1 | grep -E 'tcp-segmentation|generic-segmentation|generic-receive'
ethtool --show-eee eno1
The usual first suspect is the offload settings, which can be turned off on the running system with:
sudo ethtool -K eno1 tso off gso off gro off
In my case I did not need that. Turning off Energy Efficient Ethernet is what made my errors go away:
sudo ethtool --set-eee eno1 eee off
The moment I ran it, the stream of messages stopped. That identifies the culprit: with EEE on, the card and the switch port negotiate low power idle and this Intel controller sometimes fails to wake its transmit path, which is the stall the log was describing. Since EEE was the trigger, there was no reason to change the TSO, GSO or GRO settings, so I left them alone.
We can verify the change took effect by asking for the EEE state again and looking at the kernel log:
ethtool --show-eee eno1
sudo journalctl -k -b | grep -i 'e1000e'
The EEE status should now read disabled, and no new "Detected Hardware Unit Hang" lines should show up. At this point the console should be quiet again, and the host should be able to reach the network.
Persistent The Fix
There is one catch. ethtool --set-eee only changes the running state of the card, so the setting is lost on reboot and the hangs would come right back. Since I did not want to find myself at the console again, let's make the fix apply automatically. There are two ways to do it.
Option 1: A systemd link file
The first method is a systemd .link file. It is declarative, and the setting is applied when udev configures the interface. The EnergyEfficientEthernet= option needs systemd 248 or newer. Ubuntu 24.04 ships systemd 255, and we can check what a host has with systemctl --version.
sudo tee /etc/systemd/network/10-eno1-eee.link <<'EOF'
[Match]
OriginalName=eno1
[Link]
EnergyEfficientEthernet=false
EOF
sudo update-initramfs -u
The update-initramfs -u step makes sure the link file is also present in the initramfs so it is picked up early in the boot. Then reboot the host and check the result:
ethtool --show-eee eno1
If EEE reports disabled after the reboot, the link file did its job. If it shows enabled again, move on to the second option.
Option 2: A oneshot systemd service
While the link file is the cleaner choice in my opinion, a small service that runs the same ethtool command at boot works everywhere and is easy to reason about. It waits for the interface to exist and then turns EEE off:
sudo tee /etc/systemd/system/eno1-eee-off.service <<'EOF'
[Unit]
Description=Disable EEE on eno1
After=network-pre.target sys-subsystem-net-devices-eno1.device
Wants=sys-subsystem-net-devices-eno1.device
[Service]
Type=oneshot
ExecStart=/usr/sbin/ethtool --set-eee eno1 eee off
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now eno1-eee-off.service
If the service reports that it cannot find the binary, confirm where ethtool lives with command -v ethtool and adjust the path in ExecStart. Either way, the check afterward is the same.
Validating After a Reboot
With either option in place, reboot the host and confirm the setting was applied without any manual help. We can verify this by checking the EEE state and then watching the kernel log for any stray hangs:
ethtool --show-eee eno1
sudo journalctl -k -b | grep -i 'e1000e'
If everything looks good the EEE status will read disabled and there will be no "Detected Hardware Unit Hang" lines in the log for the current boot. At this point I would feel pretty confident the node can be rebooted at any time and come back up with a working network.
Keep in mind EEE only saves a few watts of idle power, so leaving it off is essentially free on a lab host. If the hangs ever return with EEE disabled, the next things I would try are the TSO, GSO and GRO offload settings from earlier, the kernel parameter pcie_aspm=off, and a kernel or BIOS and Intel Management Engine firmware update. As a last resort a different network card, such as a USB or add-in adapter, takes the onboard controller out of the picture entirely.
Hopefully this write-up saves someone a trip to the console the next time an Intel e1000e interface hangs and the host drops off the network.

