Remove leftover `vmtap-*` interfaces from previous driver runs. Called once at driver startup for interfaces that were not torn down (e.g. the launcher was `SIGKILL`-ed before teardown), so stale interfaces cannot cause subnet routing conflicts with newly allocated TAPs.
()
| 353 | /// (e.g. the launcher was `SIGKILL`-ed before teardown), so stale |
| 354 | /// interfaces cannot cause subnet routing conflicts with newly allocated TAPs. |
| 355 | pub fn cleanup_stale_tap_interfaces() { |
| 356 | let Ok(entries) = std::fs::read_dir("/sys/class/net") else { |
| 357 | return; |
| 358 | }; |
| 359 | for entry in entries.flatten() { |
| 360 | let name = entry.file_name(); |
| 361 | let Some(name) = name.to_str() else { |
| 362 | continue; |
| 363 | }; |
| 364 | if !name.starts_with("vmtap-") { |
| 365 | continue; |
| 366 | } |
| 367 | // Read the IP address so we can clean up iptables rules too. |
| 368 | // Port 0 tells teardown we don't know the original gateway port; |
| 369 | // the blanket legacy rule is still cleaned up best-effort. |
| 370 | let ip = read_tap_host_ip(name); |
| 371 | if let Some(ref host_ip) = ip { |
| 372 | teardown_tap_networking(name, host_ip, 0); |
| 373 | } else { |
| 374 | let _ = run_cmd("ip", &["link", "set", name, "down"]); |
| 375 | let _ = run_cmd("ip", &["tuntap", "del", "dev", name, "mode", "tap"]); |
| 376 | } |
| 377 | tracing::warn!(interface = %name, "removed stale TAP interface from previous run"); |
| 378 | } |
| 379 | } |
| 380 | |
| 381 | /// Read the first IPv4 address assigned to a network interface. |
| 382 | fn read_tap_host_ip(device: &str) -> Option<String> { |
nothing calls this directly
no test coverage detected