Modern datacenters and beyond

Networking -- Quick Reference

Key Numbers

Parameter Value Notes
GENEVE overhead 50 bytes (14 Eth + 20 IP + 8 UDP + 8 GENEVE) OVN-Kubernetes default overlay
VXLAN overhead 50 bytes Same as GENEVE
MTU (standard) 1500 Physical NIC default
MTU (jumbo frames) 9000 Recommended for storage + overlay
Effective MTU (overlay, std) 1450 (1500 - 50 overhead) Pod/VM sees this MTU
Effective MTU (overlay, jumbo) 8950 (9000 - 50 overhead) Pod/VM sees this MTU
GENEVE UDP port 6081 Must be open between all nodes
OVN Northbound DB port 6641 Control plane
OVN Southbound DB port 6642 Control plane
Kubernetes API port 6443 Must be reachable from all nodes
NodePort range 30000-32767 Default; configurable
Pod CIDR (OpenShift default) 10.128.0.0/14 ~262k IPs; /23 per node = 512 pods/node
Service CIDR (OpenShift default) 172.30.0.0/16 ~65k ClusterIPs
MetalLB L2 failover time 10-30 s Depends on gratuitous ARP propagation
MetalLB BGP convergence 1-3 s Depends on BGP timers (hold/keepalive)
SR-IOV max VFs per PF 64-128 (NIC-dependent) Intel E810: 128 VFs; Mellanox CX-6: 127
SR-IOV latency vs virtio ~3-5 us vs ~15-30 us (one-way) SR-IOV = near-native
SR-IOV throughput Line rate (25/100 Gbps) Bypasses software stack entirely
virtio-net throughput 10-20 Gbps typical With vhost-net acceleration
DPDK throughput Line rate Userspace networking, high CPU cost
OVN-K Services implementation OVN load balancers (no kube-proxy) Native in OVN Southbound DB

Decision Matrix

Scenario Recommended Approach Notes
Primary VM NIC (default) masquerade mode on pod network Simple, works with any CNI, live-migratable
VM needs pod IP directly bridge mode on pod network No NAT; pod IP = VM IP; sidecar containers cannot share IP
High-throughput VM (>10 Gbps) SR-IOV (sriov mode via Multus) Near-native perf; blocks live migration
Low-latency trading/HFT SR-IOV + DPDK inside guest Requires SR-IOV NIC + DPDK-capable guest driver
VLAN-attached VM Multus + bridge CNI + VLAN ID NetworkAttachmentDefinition with VLAN tag
Multiple NICs per VM Multus secondary interfaces Each additional NIC = separate NAD
External L4 service (stable IP) MetalLB LoadBalancer Service L2 for simple; BGP for redundancy
External L7 service (HTTP/S) OpenShift Route / Ingress HAProxy-based; TLS termination built-in
Internal L4 load balancing ClusterIP Service kube-proxy/OVN handles DNAT to backends
East-west micro-segmentation NetworkPolicy Per-namespace; default-deny recommended
Cluster-wide default deny AdminNetworkPolicy Cluster-scoped, admin-only
MetalLB L2 vs BGP L2 = simple (no router config); BGP = production (multi-speaker, fast failover) BGP needs ToR router peering
Dedicated migration network Multus NAD for KubeVirt migration Separate VLAN + NICs for migration traffic
Dedicated storage network Multus NAD or separate physical NIC ODF cluster network on dedicated interface

Essential Commands

Task VMware/NSX OVE (OVN-Kubernetes) Azure Local (SDN)
List VM IPs govc vm.ip my-vm oc get vmi my-vm -o jsonpath='{.status.interfaces}' Get-VMNetworkAdapter -VMName my-vm
List pod network N/A oc get pods -o wide N/A
Show node network config esxcfg-nics -l oc get nncp (NodeNetworkConfigurationPolicy) Get-NetAdapter -CimSession $node
Show network state N/A oc get nnce (NodeNetworkConfigurationEnactment) Get-NetIPConfiguration
List network attachments Port groups oc get net-attach-def -A Get-VMSwitch
Create VLAN network Add port group oc apply -f nad-vlan100.yaml Add-VMSwitch -NetAdapterName
Show OVN topology N/A oc exec -n openshift-ovn-kubernetes ovnkube-node-xxx -- ovn-nbctl show N/A
Show OVS flows N/A oc exec -n openshift-ovn-kubernetes ovnkube-node-xxx -- ovs-ofctl dump-flows br-int N/A
List Services N/A oc get svc -A N/A
Show Service endpoints N/A oc get endpoints my-svc N/A
Show NetworkPolicies NSX DFW rules oc get networkpolicy -A Get-NetworkControllerAccessControlList
MetalLB status N/A oc get ipaddresspool -n metallb-system N/A
MetalLB speaker logs N/A oc logs -n metallb-system -l component=speaker N/A
SR-IOV VF status N/A oc get sriovnetworknodestates -n openshift-sriov-network-operator N/A
SR-IOV policy N/A oc get sriovnetworknodepolicy -n openshift-sriov-network-operator N/A
DNS lookup (in-cluster) N/A oc exec debug-pod -- nslookup my-svc.my-ns.svc.cluster.local N/A
Trace packet path net-dvs -l oc exec ovnkube-node-xxx -- ovn-trace <datapath> '<flow>' Test-NetConnection
Check connectivity vmkping oc exec debug-pod -- curl -v http://my-svc:8080 Test-NetConnection -Port 443
Debug node network esxcli network oc debug node/<node> -- chroot /host ip a Get-NetAdapter -CimSession $node
NMState bond/VLAN config N/A oc apply -f nncp-bond0-vlan100.yaml New-NetLbfoTeam

Architecture at a Glance (OVE/OVN-Kubernetes)

+===============================================================================+
| VM Guest OS                                                                   |
|   eth0: 10.0.2.2/24 (masquerade, mgmt)    eth1: 192.168.100.5/24 (SR-IOV)   |
|         virtio-net                               VFIO passthrough             |
+===============================================================================+
| virt-launcher Pod                                                             |
|   tap0 ---> linux bridge ---> NAT (iptables DNAT/SNAT) ---> eth0 (pod iface) |
|   [no software path for SR-IOV -- direct hardware access via VFIO]            |
+===============================================================================+
| Node Network Stack                                                            |
|   veth pair: pod eth0 <---> br-int (Open vSwitch)                             |
|   OVS bridge br-int handles:                                                  |
|     - Pod-to-pod switching (local)                                            |
|     - GENEVE encap/decap (remote pods)                                        |
|     - Service DNAT (OVN load balancer, replaces kube-proxy)                   |
|     - NetworkPolicy ACLs                                                      |
+===============================================================================+
| OVN Control Plane                                                             |
|   Northbound DB (6641): logical switches, routers, ACLs, LBs                 |
|   Southbound DB (6642): compiled flows, chassis bindings                      |
|   ovn-controller (per node): translates SB DB -> OVS OpenFlow rules           |
+===============================================================================+
| Physical NIC                                                                  |
|   eno1: GENEVE overlay (pod traffic, UDP 6081)     MTU 9000 recommended       |
|   eno2: SR-IOV PF (VFs allocated to VMs)           VLAN trunk to ToR switch   |
|   Bond0: optional LACP bond for overlay NICs                                  |
+===============================================================================+
| Physical Network (Spine-Leaf)                                                 |
|   ToR Switch: VLAN trunks, GENEVE transport, BGP peering (MetalLB)            |
+===============================================================================+

Network Troubleshooting Quick Checks

1. VM has no network connectivity

# Check pod network interface inside the virt-launcher pod
oc exec virt-launcher-my-vm-xxxxx -- ip a
# Check if OVN port binding exists for this pod
oc exec -n openshift-ovn-kubernetes ovnkube-node-xxx -- ovn-nbctl list Logical_Switch_Port | grep my-vm
# Check CNI events on the pod
oc describe pod virt-launcher-my-vm-xxxxx | grep -A5 Events

2. Service not reachable (ClusterIP or LoadBalancer)

# Check service endpoints are populated (empty = selector mismatch or pods not ready)
oc get endpoints my-svc -n my-ns
# Check OVN load balancer for this service
oc exec -n openshift-ovn-kubernetes ovnkube-node-xxx -- ovn-nbctl list Load_Balancer | grep <cluster-ip>
# Test from inside cluster
oc run debug --rm -it --image=nicolaka/netshoot -- curl -v http://my-svc.my-ns:8080

3. MetalLB external IP not reachable

# Check IPAddressPool has available IPs
oc get ipaddresspool -n metallb-system -o yaml
# Check which speaker owns the IP (L2 mode: only one speaker answers ARP)
oc logs -n metallb-system -l component=speaker | grep "announcing"
# Check ARP on the physical network (from a host on the same L2 segment)
# arping -I eth0 <external-ip>

4. SR-IOV VF not available / VM stuck pending

# Check SriovNetworkNodeState for available VFs on the node
oc get sriovnetworknodestates -n openshift-sriov-network-operator <node> -o yaml
# Check SriovNetworkNodePolicy is applied and VFs are created
oc get sriovnetworknodepolicy -n openshift-sriov-network-operator
# Check node for VF allocation (device plugin)
oc describe node <node> | grep -A5 "openshift.io/sriov"

5. DNS resolution failing inside VM/Pod

# Check CoreDNS pods are running
oc get pods -n openshift-dns
# Test DNS from inside a debug pod
oc run dns-test --rm -it --image=busybox -- nslookup kubernetes.default.svc.cluster.local
# Check CoreDNS logs for errors
oc logs -n openshift-dns -l dns.operator.openshift.io/daemonset-dns=default --tail=30

NetworkAttachmentDefinition Examples

VLAN bridge (L2 access to physical VLAN):

apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: vlan100-prod
  namespace: production
spec:
  config: |
    {
      "cniVersion": "0.3.1",
      "type": "bridge",
      "bridge": "br-vlan100",
      "vlan": 100,
      "ipam": { "type": "static" }
    }

SR-IOV network:

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: sriov-storage-net
  namespace: openshift-sriov-network-operator
spec:
  ipam: '{ "type": "static" }'
  networkNamespace: production
  resourceName: sriov_storage_vf
  vlan: 200

VM using both default + secondary network:

spec:
  template:
    spec:
      networks:
        - name: default
          pod: {}                        # Pod network (masquerade)
        - name: storage-net
          multus:
            networkName: sriov-storage-net  # SR-IOV secondary
      domain:
        devices:
          interfaces:
            - name: default
              masquerade: {}
            - name: storage-net
              sriov: {}