22 KiB
OVN Deep-Dive: Incus Cluster Networking Internals
How Incus translates its network abstractions into OVN logical objects, OVS physical flows, and Geneve tunnels. Based on a live 3-node IncusOS cluster running OVS 3.6.1 with an OVN overlay network.
Lab Topology
flowchart TD
lan(("LAN<br/>192.168.100.0/22"))
n1["oc-node-01 · .140<br/>Geneve endpoint"]
n2["oc-node-02 · .141<br/>Geneve endpoint"]
n3["oc-node-03 · .142<br/>Geneve + gateway"]
uplink("UPLINK<br/>OVN range .103.200-210")
netprod("net-prod<br/>10.10.10.0/24")
lan --- n1 & n2 & n3
lan --- uplink --> netprod
classDef node fill:#009E73,color:#fff,stroke:#007a5e
classDef network fill:#0072B2,color:#fff,stroke:#005a8e
class n1,n2,n3 node
class lan,uplink,netprod network
Instances on net-prod:
| Instance | IP | Node | Role |
|---|---|---|---|
| ffsdn-haproxy-52-01 | 10.10.10.50 | oc-node-01 | HAProxy LB |
| ffsdn-haproxy-52-02 | 10.10.10.51 | oc-node-02 | HAProxy LB |
| nginx-lb-01 | 10.10.10.60 | oc-node-01 | Nginx backend |
| nginx-lb-02 | 10.10.10.61 | oc-node-02 | Nginx backend |
| nginx-lb-03 | 10.10.10.62 | oc-node-03 | Nginx backend |
| test-app-manual-web-tier-app-1 | 10.10.10.4 | oc-node-03 | App server |
| test-app-manual-web-tier-web-1 | 10.10.10.2 | oc-node-01 | Web server |
| test-app-manual-web-tier-web-2 | 10.10.10.3 | oc-node-02 | Web server |
OVN Northbound Database (Logical Layer)
The NB database describes the desired network topology. Incus creates and manages all objects here — users never touch OVN directly.
Incus → OVN Naming Convention
Incus uses a consistent naming scheme. For a network named net-prod
with internal ID net8:
| Incus Concept | OVN Object | OVN Name |
|---|---|---|
| OVN network | Logical Switch (internal) | incus-net8-ls-int |
| OVN uplink | Logical Switch (external) | incus-net8-ls-ext |
| OVN gateway | Logical Router | incus-net8-lr |
| Instance NIC | Logical Switch Port | incus-net8-instance-<UUID>-eth0 |
| Router↔int switch | Router Port + Switch Port | incus-net8-lr-lrp-int / incus-net8-ls-int-lsp-router |
| Router↔ext switch | Router Port + Switch Port | incus-net8-lr-lrp-ext / incus-net8-ls-ext-lsp-router |
| Provider connection | Localnet Port | incus-net8-ls-ext-lsp-provider |
| Network forward LB | Load Balancer | incus-net8-lb-<VIP>-<proto> |
The numeric net8 suffix is an internal Incus identifier for the network.
It increments as networks are created.
Logical Switches
Internal switch (incus-net8-ls-int): The overlay network where all
instances connect. Subnet 10.10.10.0/24, IPv6 fd42:842b:1e5f:b27::/64.
incus-net8-ls-int
├── 8 instance ports (one per container on net-prod)
├── 1 router port (incus-net8-ls-int-lsp-router)
├── 1 load balancer attached (VIP 192.168.103.200:80)
├── 15 ACL rules (Incus baseline security)
├── 8 DNS records (forward + reverse per instance)
└── DHCP options (IPv4 lease=3600, MTU=1442, DNS=192.168.100.1)
Key config in other_config:
subnet=10.10.10.0/24— Incus IPAM rangeexclude_ips=10.10.10.1 10.10.10.254 ...— reserved IPs (gateway, broadcast, static assignments)ipv6_prefix=fd42:842b:1e5f:b27::/64— SLAAC prefix
External switch (incus-net8-ls-ext): Bridges the logical router to
the physical UPLINK network.
incus-net8-ls-ext
├── 1 localnet port (incus-net8-ls-ext-lsp-provider)
│ └── options: network_name=UPLINK
└── 1 router port (incus-net8-ls-ext-lsp-router)
└── nat_addresses: 10:66:6a:d4:30:c7 192.168.103.200
is_chassis_resident("cr-incus-net8-lr-lrp-ext")
The localnet port type is special — it tells OVN to bridge this logical
switch to a physical network via ovn-bridge-mappings on each chassis.
The mapping UPLINK:incusovn7 connects it to the OVS provider bridge.
Logical Router
Router (incus-net8-lr): Connects internal overlay to external UPLINK.
incus-net8-lr
├── lrp-int: 10.10.10.1/24, fd42:842b:1e5f:b27::1/64
│ MAC: 10:66:6a:d4:30:c7, MTU: 1442
│ IPv6 RA: periodic, DHCPv6 stateless, DNSSL=incus
│
├── lrp-ext: 192.168.103.200/22
│ MAC: 10:66:6a:d4:30:c7, MTU: 1442
│ HA Chassis Group: incus-net8 (gateway on oc-node-03)
│
├── NAT:
│ └── SNAT: 10.10.10.0/24 → 192.168.103.200 (stateful)
│
├── Static Routes:
│ ├── 0.0.0.0/0 → 192.168.100.1 via lrp-ext (default gateway)
│ └── 192.168.103.200/32 → 10.10.10.1 (hairpin VIP route)
│
├── Load Balancer: (same LB as on ls-int)
│ └── 192.168.103.200:80 → 10.10.10.50:80, 10.10.10.51:80
│
├── Policies:
│ ├── priority 600: allow ip4.src == $incus_net8_routes_ip4
│ ├── priority 600: allow ip6.src == $incus_net8_routes_ip6
│ └── priority 500: drop (inport == lrp-int) ← deny-by-default
│
└── Options:
├── always_learn_from_arp_request=false
└── dynamic_neigh_routers=true
Router policies explained: The priority-500 drop rule blocks all traffic from the internal network by default. The priority-600 allow rules create exceptions for the network's own IP ranges. This prevents instances from spoofing source IPs outside their assigned ranges.
Hairpin VIP route: The 192.168.103.200/32 → 10.10.10.1 route
handles the case where an instance on net-prod accesses the VIP from
inside the overlay. Without this, the router would try to route the VIP
out the external port, but the packet originated internally.
Load Balancer
Name: incus-net8-lb-192.168.103.200-tcp
Protocol: tcp
VIPs: 192.168.103.200:80 → 10.10.10.50:80, 10.10.10.51:80
Incus creates this LB from incus network forward or from Aether's
HAProxy deployment. The LB is attached to both the logical switch
(ls-int) and the logical router (lr). This dual attachment ensures
the LB intercepts traffic regardless of where it enters:
- On the router: Catches external traffic (LAN → VIP)
- On the switch: Catches internal traffic (instance → VIP)
DHCP and DNS
DHCP Options (IPv4):
- Server: 10.10.10.1, MAC: 10:66:6a:d4:30:c7
- Lease time: 3600s, MTU: 1442 (Geneve overhead: 1500 - 58 = 1442)
- DNS: 192.168.100.1 (upstream resolver from UPLINK config)
- Domain: incus, search list: incus
DHCP Options (IPv6):
- Stateless DHCPv6 (SLAAC for addresses, DHCPv6 for DNS)
- DNS: fd42:842b:1e5f:b27::1
DNS Records: Incus creates forward and reverse DNS entries for every instance. The DNS server runs inside the OVN router (lrp-int port).
ffsdn-haproxy-52-01.incus → 10.10.10.50, fd42:842b:1e5f:b27:1266:6aff:fe67:3482
ffsdn-haproxy-52-02.incus → 10.10.10.51, fd42:842b:1e5f:b27:1266:6aff:fe5f:418f
nginx-lb-01.incus → 10.10.10.60, fd42:842b:1e5f:b27:1266:6aff:fe2a:da10
nginx-lb-02.incus → 10.10.10.61, fd42:842b:1e5f:b27:1266:6aff:fe69:888e
nginx-lb-03.incus → 10.10.10.62, fd42:842b:1e5f:b27:1266:6aff:fe90:4ab8
ACLs (Baseline Security)
Incus creates a default ACL set on the internal switch. These are not user-configurable — they form the baseline security policy:
| Priority | Direction | Match | Action | Purpose |
|---|---|---|---|---|
| 200 | to-lport | arp || nd |
allow | ARP/ND always allowed |
| 200 | to-lport | icmp4.type == {3,11,12} && ip.ttl == 255 |
allow | ICMP errors |
| 200 | to-lport | igmp && ip.ttl == 1 && ip4.mcast |
allow | IGMP |
| 200 | to-lport | Router port ping echo reply | allow | Router ping |
| 200 | to-lport | DHCP to router port | allow | DHCP relay |
| 200 | to-lport | DNS to router port | allow | DNS queries |
| 200 | to-lport | nd_ra from router |
allow | IPv6 RA |
| 200 | to-lport | nd_rs to router |
allow | IPv6 RS |
| 200 | to-lport | tcp.flags == 0x014 |
allow | TCP RST+ACK |
All ACLs are to-lport (ingress to the logical port), which means they
filter traffic arriving at a port. There are no explicit from-lport
rules — the default for egress is allow.
OVN Southbound Database (Physical Layer)
The SB database maps logical topology to physical infrastructure. It's
computed by ovn-northd from the NB database and consumed by
ovn-controller on each chassis.
Chassis
Each Incus cluster member registers as a chassis:
| Chassis | Hostname | Geneve IP | OVS UUID |
|---|---|---|---|
| b840b5b2-... | oc-node-01 | 192.168.102.140 | 298b76a9-... |
| 4652b51f-... | oc-node-02 | 192.168.102.141 | 5ee7906c-... |
| 3f7400f9-... | oc-node-03 | 192.168.102.142 | fd0c3d36-... |
All chassis use Geneve encapsulation with checksum enabled (csum=true).
Each chassis advertises ovn-bridge-mappings=UPLINK:incusovn7.
Key other_config values:
datapath-type=system— kernel datapath (not DPDK)ovn-bridge-mappings=UPLINK:incusovn7— maps logical "UPLINK" network to OVS bridgeovn-monitor-all=false— each chassis only gets flows relevant to its local portsct-commit-nat-v2=true,ct-next-zone=true— modern conntrack features
Datapath Bindings (Tunnel Keys)
Each logical switch/router gets a unique tunnel key used inside Geneve:
| Tunnel Key | Datapath | OVN Object |
|---|---|---|
| 1 | incus-net8-lr | Logical Router |
| 2 | incus-net8-ls-ext | External Switch |
| 3 | incus-net8-ls-int | Internal Switch |
When a packet traverses a Geneve tunnel, the tunnel key (VNI) identifies which datapath it belongs to.
Port Bindings
Port bindings map logical ports to physical chassis:
| Logical Port | Type | Chassis | Tunnel Key |
|---|---|---|---|
| Instance ports (8 total) | VIF | Respective chassis | 2-10 |
| cr-incus-net8-lr-lrp-ext | chassisredirect | oc-node-03 | 2 |
| incus-net8-lr-lrp-ext | patch | (distributed) | 1 |
| incus-net8-lr-lrp-int | patch | (distributed) | 3 |
| incus-net8-ls-ext-lsp-provider | localnet | (all chassis) | 2 |
| incus-net8-ls-ext-lsp-router | patch | (distributed) | 1 |
Key port types:
- VIF (Virtual Interface): Regular instance ports, bound to a specific chassis. Each has a MAC+IP pair for the instance.
- patch: Connects two OVN datapaths (switch↔router). Distributed — processed locally on every chassis.
- chassisredirect: The gateway port. Centralizes external-facing traffic on a single chassis for SNAT/DNAT. Bound to oc-node-03.
- localnet: Maps to a physical network. Present on every chassis
via
ovn-bridge-mappings.
HA Chassis Group (Gateway Failover)
The gateway port uses an HA chassis group for failover:
HA Chassis Group: incus-net8
├── oc-node-03 priority 22372 ← active gateway
├── oc-node-02 priority 18011 ← first failover
└── oc-node-01 priority 12213 ← second failover
Incus assigns random-looking priorities (likely based on a hash). If
oc-node-03 goes down, the cr-incus-net8-lr-lrp-ext binding migrates
to oc-node-02, then oc-node-01 if needed. BFD (Bidirectional Forwarding
Detection) between chassis enables fast failure detection.
Logical Flows (Compiled Pipeline)
The lflow pipeline is the compiled form of all NB rules. For ls-int ingress:
| Table | Name | Key Rules |
|---|---|---|
| 0 | ls_in_check_port_sec | Drop multicast src, VLAN tagged |
| 1 | ls_in_apply_port_sec | Enforce port security |
| 4 | ls_in_pre_acl | Skip ACL for router port traffic |
| 5 | ls_in_pre_lb | Pre-process for LB (set reg0[2] for CT) |
| 6 | ls_in_pre_stateful | LB intercept: dst=192.168.103.200:80 → ct_lb_mark |
| 7 | ls_in_acl_hint | Compute ACL hints from conntrack state |
| 8 | ls_in_acl | Apply ACLs, track connections |
The critical LB flow in table 6:
priority=120, match=(reg0[2] == 1 && ip4.dst == 192.168.103.200 && tcp.dst == 80)
action=(reg1 = 192.168.103.200; reg2[0..15] = 80; ct_lb_mark;)
This intercepts packets to the VIP and sends them through conntrack load balancing, which selects a backend and rewrites the destination.
OVS Physical Layer
Each IncusOS node runs OVS 3.6.1 with two bridges.
Bridge Architecture
flowchart LR
subgraph provider["incusovn7 · provider bridge"]
nic["physical NIC"]
intport["internal port"]
patch1["patch to br-int"]
end
subgraph integration["br-int · integration bridge"]
veth["instance veth ports"]
ovntun["Geneve tunnels"]
patch2["patch to incusovn7"]
end
patch1 <-->|"patch port"| patch2
classDef prov fill:#0072B2,color:#fff,stroke:#005a8e
classDef integ fill:#009E73,color:#fff,stroke:#007a5e
class nic,intport,patch1 prov
class veth,ovntun,patch2 integ
style provider fill:#e0eef8,stroke:#0072B2
style integration fill:#e6f5f0,stroke:#009E73
br-int (integration bridge):
fail_mode: secure— drops all traffic if OVN controller disconnects- Contains all instance veth ports, Geneve tunnel ports, and the patch port to the provider bridge
- All OVN logical processing (ACLs, NAT, LB, routing) happens here via
OpenFlow rules installed by
ovn-controller
incusovn7 (provider bridge):
- Named after the Incus-managed OVS bridge (
incusovn+ network ID) - Contains the physical NIC port, an internal port, and a patch port to br-int
- Single OpenFlow rule:
priority=0 actions=NORMAL(standard L2 switching) - This bridge is the on-ramp/off-ramp between OVN and the physical network
Geneve Tunnels (Full Mesh)
Every pair of chassis has a Geneve tunnel with BFD health monitoring:
graph LR
n1(("oc-node-01<br/>.140"))
n2(("oc-node-02<br/>.141"))
n3(("oc-node-03<br/>.142"))
n1 <-->|"Geneve 6081"| n2
n2 <-->|"Geneve 6081"| n3
n1 <-->|"Geneve 6081"| n3
classDef chassis fill:#009E73,color:#fff,stroke:#007a5e
class n1,n2,n3 chassis
| Source | Destination | OVS Port Name | BFD State |
|---|---|---|---|
| .140 (node-01) | .141 (node-02) | ovn-4652b5-0 | forwarding=true |
| .140 (node-01) | .142 (node-03) | ovn-3f7400-0 | forwarding=true |
| .141 (node-02) | .140 (node-01) | ovn-b840b5-0 | forwarding=true |
| .141 (node-02) | .142 (node-03) | ovn-3f7400-0 | forwarding=true |
| .142 (node-03) | .140 (node-01) | ovn-b840b5-0 | forwarding=true |
| .142 (node-03) | .141 (node-02) | ovn-4652b5-0 | forwarding=true |
Tunnel port names use the first 6 hex chars of the remote chassis name.
Options: key=flow (tunnel key set per-packet from OVN datapath), csum=true.
Veth Port Mapping
Each instance on net-prod gets a veth pair: one end in the container's
network namespace, the other plugged into br-int. The OVS external_ids
field links the veth to its OVN logical port.
oc-node-01:
| veth | OVN Port (iface-id) | Instance | OVS ofport |
|---|---|---|---|
| veth8bd9abf3 | ...c446bd6a...-eth0 | nginx-lb-01 (10.10.10.60) | 8 |
| vethfc99b1ec | ...b90abddd...-eth0 | test-web-tier-web-1 (10.10.10.2) | 5 |
| veth07cf17cf | ...0880f911...-eth0 | ffsdn-haproxy-52-01 (10.10.10.50) | 9 |
oc-node-02:
| veth | OVN Port (iface-id) | Instance |
|---|---|---|
| veth3352cb4f | ...a2cad635...-eth0 | ffsdn-haproxy-52-02 (10.10.10.51) |
| vethc0b4d30a | ...07270515...-eth0 | nginx-lb-02 (10.10.10.61) |
| vethd2307cca | ...b2cbf869...-eth0 | test-web-tier-web-2 (10.10.10.3) |
oc-node-03:
| veth | OVN Port (iface-id) | Instance |
|---|---|---|
| veth9306f6ef | ...292ce9ce...-eth0 | nginx-lb-03 (10.10.10.62) |
| veth4701597a | ...1f056d1a...-eth0 | test-web-tier-app-1 (10.10.10.4) |
Packet Trace: LAN → VIP → HAProxy → Nginx → Return
Complete path for an HTTP request from a LAN client to
http://192.168.103.200/ (the HAProxy VIP).
1. Client → Gateway Chassis
Client (192.168.1.x) sends TCP SYN to 192.168.103.200:80
→ LAN switch forwards to oc-node-03 (gateway chassis)
192.168.103.200 is announced by oc-node-03 via the
cr-incus-net8-lr-lrp-ext chassisredirect port
→ Packet enters physical NIC → incusovn7 bridge
→ OVS NORMAL action → patch port → br-int
Why oc-node-03? The external router port (lrp-ext) uses HA chassis
scheduling, and oc-node-03 has the highest priority (22372). OVN makes
oc-node-03's OVS respond to ARP for 192.168.103.200, directing all
external traffic to this node.
2. br-int → OVN Router (External Processing)
br-int receives packet on patch port
→ OpenFlow table 0: classify as localnet traffic (metadata=0x2, ls-ext)
→ Pipeline: ls-ext ingress → router pipeline
→ Router receives on lrp-ext (192.168.103.200/22)
3. OVN Load Balancer DNAT
Router detects dst=192.168.103.200:80 matches LB
→ ct_lb_mark: conntrack creates new entry
→ DNAT: rewrite dst to 10.10.10.50:80 or 10.10.10.51:80
(round-robin selection, conntrack-aware)
→ Packet now has dst=10.10.10.50:80 (say, haproxy-01)
The LB is processed in the router pipeline because it's attached to both the router and the internal switch. For external traffic, the router processes it first.
4. Router → Internal Switch
Router forwards via lrp-int (10.10.10.1)
→ Enters ls-int pipeline
→ ACL check (baseline allows established connections)
→ Destination lookup: 10.10.10.50 → ffsdn-haproxy-52-01
→ Port binding: haproxy-01 is on oc-node-01
5. Geneve Tunnel (Cross-Chassis)
Since the gateway is on oc-node-03 but the destination (haproxy-01) is on oc-node-01:
br-int on oc-node-03:
→ Output action: tunnel to oc-node-01
→ Geneve encapsulate:
- Outer: src=192.168.102.142, dst=192.168.102.140, UDP:6081
- VNI (tunnel key): 3 (ls-int datapath)
- TUN_METADATA0: encodes reg14 (destination port) + reg15
→ Physical NIC sends to LAN
oc-node-01 receives Geneve packet:
→ br-int decapsulates
→ Restores metadata from tunnel headers
→ Delivers to veth07cf17cf (haproxy-01's veth, ofport 9)
→ Packet enters container's network namespace
6. HAProxy Processing
HAProxy receives HTTP request on 10.10.10.50:80
→ HAProxy selects backend: nginx-lb-01 (10.10.10.60)
→ Opens new TCP connection to 10.10.10.60:80
→ Proxies request
7. HAProxy → Nginx (Same or Different Chassis)
If nginx-lb-01 is on the same node (oc-node-01):
→ br-int local delivery (no tunnel needed)
→ veth8bd9abf3 (nginx-lb-01, ofport 8)
If HAProxy chose nginx-lb-02 (oc-node-02) or nginx-lb-03 (oc-node-03):
→ Geneve tunnel to remote node
→ Same encap/decap as step 5
8. Return Path
Nginx response → HAProxy (reverse of step 7)
→ HAProxy response → OVN (enters ls-int as src=10.10.10.50)
→ ls-int → router (dst is LAN client, matches default route)
→ Router SNAT: src 10.10.10.50 → 192.168.103.200
→ lrp-ext → ls-ext → provider bridge → physical NIC → LAN
→ Client receives response from 192.168.103.200
Important: The return path from HAProxy to the LAN client goes through the gateway chassis (oc-node-03) because SNAT is centralized there. If HAProxy is on oc-node-01, the reply tunnels to oc-node-03 for SNAT, then exits to the LAN.
MTU: Why 1442?
Standard Ethernet MTU is 1500 bytes. Geneve adds 58 bytes of overhead:
Outer Ethernet: 14 bytes
Outer IP: 20 bytes
Outer UDP: 8 bytes
Geneve header: 16 bytes (8 base + 8 metadata)
─────────
Total overhead: 58 bytes
Inner MTU: 1442 bytes (1500 - 58)
Incus sets bridge.mtu=1442 on net-prod and propagates this via:
- DHCP option:
mtu=1442 - Router port option:
gateway_mtu=1442 - IPv6 RA:
mtu=1442
Inspection Tools
Using ovn-inspect
The incusos/helpers/ovn-inspect script provides structured inspection:
# NB database (logical topology)
incusos/helpers/ovn-inspect --nb
# SB database (physical bindings)
incusos/helpers/ovn-inspect --sb
# OVS on each node (deploys temp containers, cleans up after)
incusos/helpers/ovn-inspect --ovs
# Everything
incusos/helpers/ovn-inspect --full
# Trace a VIP's packet path
incusos/helpers/ovn-inspect --trace 192.168.103.200
# Dry run (show commands without executing)
incusos/helpers/ovn-inspect --nb --dry-run
Manual Commands
All NB/SB commands go through the ovn-central container:
# NB: Logical topology
incus exec oc-node-01:ovn-central -- ovn-nbctl ls-list
incus exec oc-node-01:ovn-central -- ovn-nbctl lr-list
incus exec oc-node-01:ovn-central -- ovn-nbctl lsp-list incus-net8-ls-int
incus exec oc-node-01:ovn-central -- ovn-nbctl lr-nat-list incus-net8-lr
incus exec oc-node-01:ovn-central -- ovn-nbctl lb-list
incus exec oc-node-01:ovn-central -- ovn-nbctl acl-list incus-net8-ls-int
# SB: Physical bindings
incus exec oc-node-01:ovn-central -- ovn-sbctl show
incus exec oc-node-01:ovn-central -- ovn-sbctl list Chassis
incus exec oc-node-01:ovn-central -- ovn-sbctl list Port_Binding
incus exec oc-node-01:ovn-central -- ovn-sbctl lflow-list incus-net8-ls-int
# OVS: Physical layer (requires privileged container with /run/openvswitch)
ovs-vsctl show
ovs-ofctl dump-flows br-int
ovs-vsctl get Interface <veth> external_ids
Incus CLI Cross-Reference
# See OVN network config
incus network show oc-node-01:net-prod --target oc-node-01
# See UPLINK config
incus network show oc-node-01:UPLINK --target oc-node-01
# See which instances use net-prod
incus list oc-node-01: -f csv -c n4l | grep "10.10.10"
# Network forwards (LB VIPs managed via Incus)
incus network forward list oc-node-01:net-prod
Key Architectural Insights
-
Incus fully manages OVN: Users never interact with OVN directly.
incus network create,incus network forward, and instance NIC configs translate to OVN objects automatically. -
Single gateway chassis: All external traffic (SNAT, DNAT, LB for external VIPs) is centralized on one node. This is a potential bottleneck but simplifies state management. HA failover handles node failures.
-
Distributed routing for internal traffic: East-west traffic between instances on the same switch is fully distributed. No traffic goes through the gateway unless it needs SNAT/DNAT.
-
LB is in OVN, not HAProxy: The VIP load balancing between HAProxy instances is done by OVN's built-in L4 LB (conntrack-based). HAProxy then does L7 load balancing to nginx backends. This is a two-tier LB architecture.
-
BFD for fast failover: All Geneve tunnels have BFD enabled, which detects chassis failures in ~3×detection-interval (typically <1s), much faster than relying on OVN cluster heartbeats.
-
MTU must be consistent: The 1442 byte MTU is critical. If any path (physical switch, hypervisor NIC) has MTU < 1500, Geneve encapsulated packets will be fragmented or dropped.