Let's say my network interface is receiving too many packets and I have a single-core processor.
What stops it (if anything) to keep interrupting the kernel and essentially monopolize the CPU (top-half after top-half)?
If there was too much work in a bottom half, in the form of a softirq: ksoftirqd, which runs as a kernel thread, and hence receives only its "fair" allocation of the CPU v.s. other processes. With a recent fix around 2016, specifically because of the networking case you mention.
https://lwn.net/Articles/687617/
I think the top half doesn't need to be re-enabled until the softirq has processed all known packets. However, this might be specific to NAPI. You can look e.g. at earlier articles about NAPI from LWN.net.
https://lwn.net/Articles/30107/
https://lwn.net/Articles/214457/
https://lwn.net/Articles/244640/
A driver MAY continue using the old 2.4 technique for interfacing to the network stack and not benefit from the NAPI changes. NAPI additions to the kernel do not break backward compatibility. NAPI, however, requires the following features to be available:
A) DMA ring or enough RAM to store packets in software devices.
B) Ability to turn off interrupts or maybe events that send packets up the stack.