---
name: openshift-cni
title: Selecting a container network interface
description: Review the following information for selecting a container network interface (CNI).
last-updated: 2026-08-11
---

> ## Documentation Index
> The table of contents for this documentation set is at https://cloud.ibm.com/docs/openshift?format=markdown
> The index for all IBM Cloud docs is at: https://cloud.ibm.com/docs/llms.txt
> Use these files to discover more information as needed.

# Selecting a container network interface
{: #cni}

[Virtual Private Cloud]{: tag-vpc}

Review the following information for selecting a container network interface (CNI).
{: shortdesc}

In Red Hat OpenShift on IBM Cloud version 4.20 and later, Calico is the default CNI, but VPC clusters that use RHCOS worker nodes have the option of selecting Open Virtual Network (OVN) as their cluster CNI.

Calico [Default]{: tag-teal}
:   Calico is a single platform for networking, network security, and observability for any Kubernetes distribution in the cloud, on-premises, or at the edge. Whether you're just starting with Kubernetes or operating at scale, Calico's open source, enterprise, and cloud editions provide the networking, security, and observability you need. For more information, see [Calico documentation](https://docs.tigera.io/calico/latest/about/){: external}.

OVN-Kubernetes (OVN) [4.20 and later]{: tag-red} [RHCOS worker nodes only]{: tag-magenta}
:   OVN-Kubernetes is based on Open Virtual Network (OVN) and provides an overlay-based networking implementation. A cluster that uses the OVN-Kubernetes plugin also runs Open vSwitch (OVS) on each node. OVN configures OVS on each node to implement the declared network configuration.  For more information, see the [Red Hat documentation](https://docs.redhat.com/en/documentation/openshift_container_platform/4.21/html-single/ovn-kubernetes_network_plugin/index){: external}

## Comparing Calico and OVN
{: #cni-compare}

Review the following table to compare the features and functionality of Calico and OVN.

When using OVN, you must ensure that your VPC subnets don't overlap with the additional subnets specified in the following table. If there is a subnet overlap, pod to pod networking will fail.
{: important}

Layer2 and layer3 user defined networks (UDN) are not supported with workloads that use DHCP, such as OpenShift Virtualization VMs.
{: important}

| Component | Calico | OVN-Kubernetes |
| --- | --- | --- |
| Encapsulation | - IP in IP Protocol (not UDP or TCP)  \n - Encapsulates only pod to pod traffic from pods running on nodes that are in different subnets. | - Geneve: UDP Protocol on port 6081  \n - Encapsulates all pod to pod traffic |
| Default Cluster Network / Pod MTU | 1480 bytes (20 byte IPinIP header) by default. This can be changed. | 1400 bytes (100 byte Geneve header) by default. This can be changed. Daemonset needs to create NetworkManager file instead of just running `ip link set dev ens3 mtu`. You must also restart new worker nodes. |
| Pod IPAM | Calico initially allocates each new node a /26 subnet (64 IPs, at least one typically used as tunl0 IP, rest are available for pods). If all pod IPs in a /26 are used, then Calico assigns a second /26 subnet to the node, and more if/when needed. You can use the `calicoctl ipam check` to see subnets assigned to each node. | OVN initially allocates /24 pod subnet (256 IPs) to each new cluster node. There is no option to add any more pod subnets. It also allocates a join subnet IP to each new node, which is used internally by OVN |
| Pod to pod routing | - Uses linux routes.  \n - Uses BGP to distribute routes.  \n - `tunl0` interface on each node for encapsulation. | - Open vSwitch (OVS) runs on each node and routes pod to pod traffic.  \n - OVN configures OVS flows to define pod to pod routing.  \n - Many other interfaces are created on each node such as: `ovs-system`, `genev_sys_6081`, `ovn-k8s-mp0`, `br-int`, `br-ex` and are used by OVN and OVS |
| Kubernetes network policies | - Implemented by `calico-node` adding iptables rules.  \n - Logging of traffics blocked by network policies is possible, but complicated.  It requires extra Calico policies that use a "Log" action and some thought and planning on where/when to put these Log actions.  \n - Logs to `syslog` on the worker node, which can difficult to retrieve.  \n - Logs do not include what policy allowed or blocked the traffic. | - Implemented by OVS using ACLs on logical ports (not iptables).  \n - Logging network policy drops and/or allowed traffic is much easier by using annotations.  \n - Annotate the namespace(s) where you want to log policy activity, and if you want to log allows, denies, or both.  \n - Logs are sent to file `/var/log/ovn/acl-audit-log.log` in the `ovnkube-node` pod.  \n - Configuration options exist to send these logs to other log targets.  \n - Logs include which policy allowed the traffic, but not which traffic denied it, because policies are allow-only.  \n - There must be at least one policy in place for allowed traffic to be logged. |
| Host network policies | Calico GlobalNetworkPolicies | None |
| Additional subnets | None | - **Join Subnet**: `100.64.0.0/16` (OpenShift default).  \n - **Masquerade subnet**: `169.254.64.0/18`. This is different from the OpenShift default of `169.254.0.0/17`. This difference is to avoid conflicting with the `169.254.2.0/24` IPs that are used for local registry haproxy.  \n - **Transit subnet**:`100.88.0.0/16` (OpenShift default). |
| APIserver watches | - `calico-typha` registers resource watches and acts as a proxy to `calico-node` pods to notify of changes.  \n - `calico-node` connects to one of the `calico-typha` pods and registers for notification of resource changes. | - The `ovnkube-cluster-manager` container in control plane watches for new nodes.  \n - The `ovnkube-controller` container on each cluster node watches for resources and translates them into OVN logical entries in the nbdb. |
| CNI | The `calico` and `calico-ipam` CNI binaries are copied to each node by the `install-cni` initContainer on the `calico-node` pod. | The `ovnkube-node` pod’s `ovnkube-controller` container executes the CNI binary for add and delete calls. |
| Resources created | - `calico-apiserver` namespace  \n - `calico-apiserver` (deployment, 2 pods)  \n - `calico-system` namespace  \n - `calico-node` (each node)  \n - `calico-typha` (deployment, from 2 - 10 pods).  \n - `calico-kube-controllers` (1 node).  \n - `openshift-kube-proxy` namespace.  \n - `openshift-kube-proxy` (each node).  \n - `tigera-operator` namespace.  \n - `tigera-operator` (deployment, 1 pod).  \n - The `calico` CNI binary, `calico-ipam` CNI binary, and various other CNI binaries are copied to each node by `install-cni` initContainer on `calico-node`. | - `openshift-ovn-kubernetes` namespace, `ovnkube-node` on each node with 8 containers, `ovnkube-controller` watches resources, allocates pod IPs, and translates resources into OVN logical entries in `nbdb`. Also handles CNI add and delete.  \n - `nbdb` stores logical entries.  \n - `northd` converts logical entries from `nbdb` to logical flows in `sbdb`.  \n - `sbdb` stores logical flows.  \n - `ovn-controller` converts logical flows in `sbdb` and programs OVS switch.  \n - `ovn-acl-logging`.  \n - `kube-rbac-proxy-node` protects node metrics so only authorized users can scrape them.  \n - `kube-rbac-proxy-ovn-metrics` protects OVN metrics so only authorized users can scrape them. |
| Connections between pods | - The `calico-node` pod initially connects to the kube apiserver via local haproxy in proxy pod listening on TCP 172.20.0.1:2040 to get `calico-typha` pod list.  \n - The `calico-node` pod connects to one of the `calico-typha` pods on TCP port 5473 to listen for cluster resource updates.  \n - The `calico-node` pod runs bird BGP daemon that connects in a full mesh to all other `calico-node` bird BGP daemons on TCP port 179.  \n - Pod to pod traffic happens directly for pods on nodes in the same subnet.  \n - Pod to pod traffic between pods on nodes in different subnets is encapsulated using IPinIP encapsulation (or VxLAN for Satellite clusters). | - The `ovnkube-controller` container on each node connects to kube apiserver via local haproxy in proxy pod listening on TCP `172.20.0.1:2040` for resource watches.  \n - All pod to pod traffic is encapsulated using Geneve and is sent via UDP port 6081.  \n - For more information, see [Configuring your firewall](https://docs.redhat.com/en/documentation/openshift_container_platform/4.21/html/installation_configuration/configuring-firewall){: external}. |
{: caption="Calico and OVN comparison table" caption-side="bottom"}