`EthernetIf.remove()` snapshotted `Section.sub_interfaces()` once and then removed every entry of that list. For Q-in-Q setups the list contains both the vif-s (eth0.10) and its vif-c children (eth0.10.20), as `Section.sub_interfaces()` matches every configured interface whose name starts with "<ifname>.".
Removing eth0.10 cascades in the Kernel and also deletes eth0.10.20. Once the loop reached eth0.10.20, `Interface.__init__()` no longer found it and - as "create" defaults to True, re-created it via a bare `ip link add dev eth0.10.20` without any type. This failed and left a stranded interface behind which in turn broke all subsequent smoketests.
The same cascade silently killed DHCP clients running on sub-interfaces of any other interface type, as only the interface itself got its addresses flushed:
* deletion of a bond or bridge interface carrying vif/vif-s/vif-c
* deletion of an entire vif-s, as `get_removed_vlans()` only populates "vif_c_remove" for a vif-s which still exists in the new configuration