The device had no pause method, so it went on receiving and sending
while a snapshot was taken. The memory of the guest is saved before the
state of the device: a receive descriptor filled in between is not in
the saved memory, but the saved RDH counts it. After the restore the
guest finds no completed descriptor and never moves RDT, while the
device waits for free descriptors: the restored guest receives nothing
any more. The snapshot also recorded what the transmit thread was doing
(esc_tx_active); restored as 1, it kept e82545_tx_start() from waking
the thread, and the guest could not send either.
Add pause and resume methods. A pause stops the receive events of the
backend and waits until the receive callback and the transmit thread are
idle; the resume starts both again and wakes the transmit thread for the
packets the guest has queued.
While here, check the receive descriptor ring against its own length in
e82545_snapshot(), not that of the transmit ring.
Signed-off-by: Wanpeng Qian <wanpengqian@gmail.com>
Sponsored by: keelos.dev