Skip to content

OVS Bridge / TAP Port Issues

Symptom: VMs are running but have no network connectivity. OVS bridge inspection shows missing ports, duplicate ports, or ports in the wrong bridge.


Terminal window
# Show the full OVS topology
sudo ovs-vsctl show
# List all ports on br-provision
sudo ovs-vsctl list-ports br-provision
# Check current OVS flows
sudo ovs-ofctl dump-flows br-provision
# Show all TAP interfaces on the host
ip link show type tun

Root Cause A — TAP device not added to br-provision

Section titled “Root Cause A — TAP device not added to br-provision”

The most critical issue encountered in the July 2026 provisioning. All Talos VMs (talos-cp-0, talos-worker-2/3/4) use the Hades config format (devices.networkinterfaces) which was not handled by prepareVMNetworks. TAP devices were created but never added to the OVS bridge.

Fixed in commit: fix(pivirtd): handle Hades-format NIs in prepareVMNetworks

How to check if a VM’s TAP is in the bridge

Section titled “How to check if a VM’s TAP is in the bridge”
Terminal window
VM=talos-worker-4
UUID=$(sudo python3 -c "import yaml; d=yaml.safe_load(open('/var/lib/pivirt/vms/$VM/config.yaml')); print(d['uuid'])")
TAP="tap${UUID//-/}"
TAP="${TAP:0:11}" # first 8 hex chars of UUID + "tap" prefix
echo "Expected TAP: $TAP"
sudo ovs-vsctl list-ports br-provision | grep "$TAP" || echo "NOT IN BRIDGE"

Or use the OVS output directly:

Terminal window
sudo ovs-vsctl list-ports br-provision
# Expected:
# pivirt-gw
# tapd558f558 ← talos-cp-0
# tap04a7851e ← talos-worker-2
# tapd2d99fa2 ← talos-worker-3
# tapF994C870 ← talos-worker-4

Manual fix (temporary — until pivirtd restart re-attaches)

Section titled “Manual fix (temporary — until pivirtd restart re-attaches)”
Terminal window
TAP=tapF994C870
sudo ovs-vsctl --may-exist add-port br-provision "$TAP"
sudo ip link set "$TAP" up

Deploy the fixed pivirtd binary (see Talos Linux Installation Guide) and restart:

Terminal window
sudo systemctl restart pivirtd

On restart, pivirtd re-runs prepareVMNetworks for all running VMs and adds missing TAPs.


Root Cause B — Duplicate port error on OVS

Section titled “Root Cause B — Duplicate port error on OVS”

pivirtd logs show:

WRN OVS port add failed error="exit status 1" tap=tapF994C870
INF OVS port added bridge=br-provision port=tapF994C870

The WRN line is not an error — the port already exists (from a previous pivirtd run or a manual ovs-vsctl add-port). The INF line immediately after confirms it’s in the bridge. This is idempotent by design.

You can safely ignore this warning.


Root Cause C — br-provision does not exist

Section titled “Root Cause C — br-provision does not exist”

If the host was rebooted and Open vSwitch was not restored, br-provision may be missing.

Terminal window
sudo ovs-vsctl show
# If no bridge named br-provision appears, it needs to be recreated
Terminal window
# Recreate the bridge
sudo ovs-vsctl add-br br-provision
# Assign gateway IP
sudo ip addr add 10.0.0.1/24 dev br-provision
sudo ip link set br-provision up
# Re-add the gateway port (pivirt-gw) if it was registered before
sudo ovs-vsctl --may-exist add-port br-provision pivirt-gw
# Enable IP forwarding (for outbound NAT)
sudo sysctl -w net.ipv4.ip_forward=1
# NAT for VMs to reach the internet
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j MASQUERADE
# Metadata DNAT
sudo iptables -t nat -A PREROUTING \
-d 169.254.169.254 -p tcp --dport 80 \
-j DNAT --to-destination 10.0.0.1:8080
# Restart pivirtd — it will re-attach all TAPs to the bridge
sudo systemctl restart pivirtd

Root Cause D — VLAN / OpenFlow flow misconfiguration

Section titled “Root Cause D — VLAN / OpenFlow flow misconfiguration”

If OVS flows are blocking traffic between VMs or between VMs and the gateway, VMs get IPs but cannot reach the gateway or each other.

Terminal window
# Look for flows that might be dropping traffic
sudo ovs-ofctl dump-flows br-provision
# Check if ARP is flowing (expect replies)
# From the host — send an ARP for a VM IP
sudo arping -I br-provision -c 3 10.0.0.19
Terminal window
# Remove all custom flows (falls back to OVS default: normal switching)
sudo ovs-ofctl del-flows br-provision
# Verify VMs can ping each other through the bridge
ping -c 2 10.0.0.19

Full OVS State Dump (Useful for Bug Reports)

Section titled “Full OVS State Dump (Useful for Bug Reports)”
Terminal window
echo "=== OVS version ===" && sudo ovs-vsctl --version
echo "=== Topology ===" && sudo ovs-vsctl show
echo "=== Ports ===" && sudo ovs-vsctl list-ports br-provision
echo "=== Flows ===" && sudo ovs-ofctl dump-flows br-provision
echo "=== Interfaces ===" && ip link show type tun
echo "=== Bridge IP ===" && ip addr show br-provision