Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,18 @@ OVNKubernetes supports the following configuration options, all of which are opt
* `egressIPConfig`: holds the configuration for EgressIP options.
* `reachabilityTotalTimeoutSeconds`: Set EgressIP node reachability total timeout in seconds, 0 means disable reachability check and the default is 1 second.

#### DPU Host Mode Support

OVN-Kubernetes supports specialized hardware deployments such as DPU (Data Processing Unit) hosts through the `OVN_NODE_MODE` environment variable. In `dpu-host` mode, certain features are automatically disabled on those nodes regardless of cluster-wide configuration:

- Egress IP and related features (egress firewall, egress QoS, egress service)
- Multicast support
- Multi-external gateway support
- Multi-network policies and admin network policies
- Network segmentation features

This per-node feature enforcement is implemented through conditional logic in the startup scripts, allowing the same cluster configuration to work across heterogeneous node types. For detailed information about node modes and the technical implementation, see `docs/ovn_node_mode.md`.

These configuration flags are only in the Operator configuration object.

Example from the `manifests/cluster-network-03-config.yml` file:
Expand Down
61 changes: 59 additions & 2 deletions bindata/network/ovn-kubernetes/common/008-script-lib.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,16 @@ data:

echo "I$(date "+%m%d %H:%M:%S.%N") - starting ovnkube-node"

# enable egress ip, egress firewall, egress qos, egress service
egress_features_enable_flag="--enable-egress-ip=true --enable-egress-firewall=true --enable-egress-qos=true --enable-egress-service=true"
init_ovnkube_controller="--init-ovnkube-controller ${K8S_NODE}"
gateway_interface="br-ex"
multi_external_gateway_enable_flag="--enable-multi-external-gateway=true"
gateway_interface=br-ex

# enable multicast
enable_multicast_flag="--enable-multicast"

Comment on lines +548 to +550

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

DPU-host multicast disable is bypassed by an unconditional CLI arg.

enable_multicast_flag is cleared for dpu-host (Lines 563-565), but Line 769 still always passes --enable-multicast, so the mode-specific disable never takes effect.

Suggested fix
       exec /usr/bin/ovnkube \
         ${init_ovnkube_controller} \
         --init-node "${K8S_NODE}" \
@@
         ${dns_name_resolver_enabled_flag} \
         ${network_observability_enabled_flag} \
         ${enable_multicast_flag} \
         --zone ${K8S_NODE} \
         ${enable_interconnect_flag} \
-        --enable-multicast \
         --acl-logging-rate-limit "{{.OVNPolicyAuditRateLimit}}" \

Also applies to: 563-565, 766-770

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bindata/network/ovn-kubernetes/common/008-script-lib.yaml` around lines 548 -
550, The enable_multicast_flag variable is conditionally cleared for dpu-host
mode (lines 563-565), but this control is bypassed because line 769
unconditionally passes the --enable-multicast argument directly instead of using
the enable_multicast_flag variable. Fix this by replacing the hardcoded
--enable-multicast argument at line 769 with a reference to the
enable_multicast_flag variable, ensuring that the mode-specific disable for
dpu-host actually takes effect.

# Use OVN_NODE_MODE environment variable, default to "full" if not set
OVN_NODE_MODE=${OVN_NODE_MODE:-full}
# We check only dpu-host mode and not smart-nic mode here as currently we do not support it yet
# Once we support it, we will need to check for it here and add relevant code.
Expand All @@ -549,10 +557,17 @@ data:
# https://github.com/ovn-kubernetes/ovn-kubernetes/pull/5327/files
gateway_interface="derive-from-mgmt-port"
ovnkube_node_mode="--ovnkube-node-mode dpu-host"
# disable egress ip for dpu-host mode as it is not supported
egress_features_enable_flag=""

# disable multicast for dpu-host mode as it is not supported
enable_multicast_flag=""

# disable init-ovnkube-controller for dpu-host mode as it is not supported
init_ovnkube_controller=""

# disable multi-external-gateway for dpu-host mode as it is not supported
multi_external_gateway_enable_flag=""
fi

if [[ -n "${OVNKUBE_NODE_LEASE_RENEW_INTERVAL}" ]]; then
Expand Down Expand Up @@ -604,6 +619,17 @@ data:
node_mgmt_port_netdev_flags="$node_mgmt_port_netdev_flags --ovnkube-node-mgmt-port-dp-resource-name ${OVNKUBE_NODE_MGMT_PORT_DP_RESOURCE_NAME}"
fi

multi_network_enabled_flag=
if [[ "{{.OVN_MULTI_NETWORK_ENABLE}}" == "true" && "${OVN_NODE_MODE}" != "dpu-host" ]]; then
multi_network_enabled_flag="--enable-multi-network"
fi

network_segmentation_enabled_flag=
if [[ "${OVN_NODE_MODE}" != "dpu-host" ]]; then
multi_network_enabled_flag="--enable-multi-network"
network_segmentation_enabled_flag="--enable-network-segmentation"
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.

route_advertisements_enable_flag=
if [[ "{{.OVN_ROUTE_ADVERTISEMENTS_ENABLE}}" == "true" ]]; then
route_advertisements_enable_flag="--enable-route-advertisements"
Expand All @@ -613,12 +639,34 @@ data:
if [[ "{{.OVN_EVPN_ENABLE}}" == "true" ]]; then
evpn_enable_flag="--enable-evpn"
fi

preconfigured_udn_addresses_enable_flag="--enable-preconfigured-udn-addresses"

network_connect_enabled_flag=
if [[ "{{.OVN_NETWORK_CONNECT_ENABLE}}" == "true" ]]; then
network_connect_enabled_flag="--enable-network-connect"
fi

network_observability_enabled_flag=
if [[ "{{.OVN_OBSERVABILITY_ENABLE}}" == "true" ]]; then
network_observability_enabled_flag="--enable-observability"
fi

multi_network_policy_enabled_flag=
if [[ "{{.OVN_MULTI_NETWORK_POLICY_ENABLE}}" == "true"&& "${OVN_NODE_MODE}" != "dpu-host" ]]; then
multi_network_policy_enabled_flag="--enable-multi-networkpolicy"
fi

admin_network_policy_enabled_flag=
if [[ "${OVN_NODE_MODE}" != "dpu-host" ]]; then
admin_network_policy_enabled_flag="--enable-admin-network-policy"
fi

dns_name_resolver_enabled_flag=
if [[ "{{.DNS_NAME_RESOLVER_ENABLE}}" == "true" ]]; then
dns_name_resolver_enabled_flag="--enable-dns-name-resolver"
fi

# If IP Forwarding mode is global set it in the host here. IPv6 IP Forwarding shuld be
# enabled for all interfaces at all times if cluster is configured as single stack IPv6
# or dual stack. This will be taken care by ovn-kubernetes(ovn-org/ovn-kubernetes#4376).
Expand Down Expand Up @@ -705,9 +753,17 @@ data:
--export-ovs-metrics \
--disable-snat-multiple-gws \
${export_network_flows_flags} \
${multi_network_enabled_flag} \
${network_segmentation_enabled_flag} \
${network_connect_enabled_flag} \
${route_advertisements_enable_flag} \
${evpn_enable_flag} \
${preconfigured_udn_addresses_enable_flag} \
${multi_network_policy_enabled_flag} \
${admin_network_policy_enabled_flag} \
${dns_name_resolver_enabled_flag} \
${network_observability_enabled_flag} \
${enable_multicast_flag} \
--zone ${K8S_NODE} \
${enable_interconnect_flag} \
--enable-multicast \
Expand All @@ -724,5 +780,6 @@ data:
${ovn_v6_masquerade_subnet_opt} \
${ovn_v4_transit_switch_subnet_opt} \
${ovn_v6_transit_switch_subnet_opt} \
${dpu_lease_flags}
${egress_features_enable_flag} \
${multi_external_gateway_enable_flag}
}
13 changes: 9 additions & 4 deletions bindata/network/ovn-kubernetes/managed/004-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,12 @@ data:
dns-service-name="dns-default"

[ovnkubernetesfeature]
enable-egress-ip=true
enable-egress-firewall=true
enable-egress-qos=true
enable-egress-service=true
{{- if .ReachabilityNodePort }}
egressip-node-healthcheck-port={{.ReachabilityNodePort}}
{{- end }}
{{- if not .OVN_MULTI_NETWORK_ENABLE }}
enable-multi-network=true
{{- end }}
Comment on lines +39 to +41

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

enable-multi-network rendering currently defeats the disable override

These template branches render enable-multi-network=true when .OVN_MULTI_NETWORK_ENABLE is false (and in hostedcluster, effectively in both branches), so DisableMultiNetwork=true does not actually disable the feature.

Suggested fix
-    {{- if not .OVN_MULTI_NETWORK_ENABLE }}
-    enable-multi-network=true
-    {{- end }}
+    enable-multi-network={{.OVN_MULTI_NETWORK_ENABLE}}
...
-{{- if .OVN_MULTI_NETWORK_ENABLE }}
-    enable-multi-network=true
-{{- end }}
-    {{- if not .OVN_MULTI_NETWORK_ENABLE }}
-    enable-multi-network=true
-    {{- end }}
+    enable-multi-network={{.OVN_MULTI_NETWORK_ENABLE}}

Also applies to: 133-138

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bindata/network/ovn-kubernetes/managed/004-config.yaml` around lines 43 - 45,
The conditional logic for enable-multi-network is inverted, causing the feature
to be enabled when it should be disabled. In the template section at lines 43-45
and the similar section at lines 133-138, remove the `not` operator from the
condition `{{- if not .OVN_MULTI_NETWORK_ENABLE }}` so it becomes `{{- if
.OVN_MULTI_NETWORK_ENABLE }}`. This ensures that `enable-multi-network=true` is
only rendered when the feature is actually intended to be enabled, allowing
DisableMultiNetwork to properly override the setting.

enable-network-segmentation=true
enable-preconfigured-udn-addresses=true

Expand All @@ -49,6 +47,7 @@ data:
{{- end }}
enable-admin-network-policy=true
enable-multi-external-gateway=true
enable-multicast=true
{{- if .DNS_NAME_RESOLVER_ENABLE }}
enable-dns-name-resolver=true
{{- end }}
Expand Down Expand Up @@ -128,14 +127,20 @@ data:
{{- if .ReachabilityNodePort }}
egressip-node-healthcheck-port={{.ReachabilityNodePort}}
{{- end }}
{{- if .OVN_MULTI_NETWORK_ENABLE }}
enable-multi-network=true
{{- end }}
{{- if not .OVN_MULTI_NETWORK_ENABLE }}
enable-multi-network=true
{{- end }}
enable-network-segmentation=true
enable-preconfigured-udn-addresses=true
{{- if .OVN_MULTI_NETWORK_POLICY_ENABLE }}
enable-multi-networkpolicy=true
{{- end }}
enable-admin-network-policy=true
enable-multi-external-gateway=true
enable-multicast=true
{{- if .DNS_NAME_RESOLVER_ENABLE }}
enable-dns-name-resolver=true
{{- end }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,19 @@ spec:
ovn_v6_masquerade_subnet_opt="--gateway-v6-masquerade-subnet {{.V6MasqueradeSubnet}}"
fi

dns_name_resolver_enabled_flag=
if [[ "{{.DNS_NAME_RESOLVER_ENABLE}}" == "true" ]]; then
dns_name_resolver_enabled_flag="--enable-dns-name-resolver"
fi

persistent_ips_enabled_flag="--enable-persistent-ips"

# This is needed so that converting clusters from GA to TP
# will rollout control plane pods as well
network_segmentation_enabled_flag=
multi_network_enabled_flag="--enable-multi-network"
network_segmentation_enabled_flag="--enable-network-segmentation"

route_advertisements_enable_flag=
if [[ "{{.OVN_ROUTE_ADVERTISEMENTS_ENABLE}}" == "true" ]]; then
route_advertisements_enable_flag="--enable-route-advertisements"
Expand All @@ -195,6 +206,22 @@ spec:
evpn_enable_flag="--enable-evpn"
fi

preconfigured_udn_addresses_enable_flag="--enable-preconfigured-udn-addresses"

# Enable multi-network policy if configured (control-plane always full mode)
multi_network_policy_enabled_flag=
if [[ "{{.OVN_MULTI_NETWORK_POLICY_ENABLE}}" == "true" ]]; then
multi_network_policy_enabled_flag="--enable-multi-networkpolicy"
fi

# Enable admin network policy if configured (control-plane always full mode)
admin_network_policy_enabled_flag="--enable-admin-network-policy"

network_connect_enabled_flag=
if [[ "{{.OVN_NETWORK_CONNECT_ENABLE}}" == "true" ]]; then
network_connect_enabled_flag="--enable-network-connect"
fi

# DROP: remove when older OVN-K images that require --enable-interconnect are no longer supported
enable_interconnect_flag=
if /usr/bin/ovnkube --help 2>&1 | grep -q -- '--enable-interconnect'; then
Expand All @@ -220,9 +247,22 @@ spec:
${ovn_v6_transit_switch_subnet_opt} \
${ovn_v4_masquerade_subnet_opt} \
${ovn_v6_masquerade_subnet_opt} \
${dns_name_resolver_enabled_flag} \
${persistent_ips_enabled_flag} \
${multi_network_enabled_flag} \
${network_segmentation_enabled_flag} \
${network_connect_enabled_flag} \
${route_advertisements_enable_flag} \
${evpn_enable_flag}
${evpn_enable_flag} \
${preconfigured_udn_addresses_enable_flag} \
--enable-egress-ip=true \
--enable-egress-firewall=true \
--enable-egress-qos=true \
--enable-egress-service=true \
--enable-multicast \
--enable-multi-external-gateway=true \
${multi_network_policy_enabled_flag} \
${admin_network_policy_enabled_flag}
volumeMounts:
- mountPath: /run/ovnkube-config/
name: ovnkube-config
Expand Down
8 changes: 4 additions & 4 deletions bindata/network/ovn-kubernetes/self-hosted/004-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,24 @@ data:
dns-service-name="dns-default"

[ovnkubernetesfeature]
enable-egress-ip=true
enable-egress-firewall=true
enable-egress-qos=true
enable-egress-service=true

{{- if .ReachabilityTotalTimeoutSeconds }}
egressip-reachability-total-timeout={{.ReachabilityTotalTimeoutSeconds}}
{{- end }}
{{- if .ReachabilityNodePort }}
egressip-node-healthcheck-port={{.ReachabilityNodePort}}
{{- end }}
{{- if not .OVN_MULTI_NETWORK_ENABLE }}
enable-multi-network=true
{{- end }}
Comment on lines +46 to +48

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Conditional is inverted for multi-network enablement

enable-multi-network=true is emitted only when .OVN_MULTI_NETWORK_ENABLE is false, which inverts the intended behavior and breaks DisableMultiNetwork.

Suggested fix
-    {{- if not .OVN_MULTI_NETWORK_ENABLE }}
-    enable-multi-network=true
-    {{- end }}
+    enable-multi-network={{.OVN_MULTI_NETWORK_ENABLE}}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{{- if not .OVN_MULTI_NETWORK_ENABLE }}
enable-multi-network=true
{{- end }}
enable-multi-network={{.OVN_MULTI_NETWORK_ENABLE}}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bindata/network/ovn-kubernetes/self-hosted/004-config.yaml` around lines 49 -
51, The conditional logic is inverted in the template around the
enable-multi-network configuration. The current condition `{{- if not
.OVN_MULTI_NETWORK_ENABLE }}` causes enable-multi-network=true to be set only
when the feature flag is false, which breaks the intended behavior. Remove the
`not` operator from the if statement so that enable-multi-network=true is
applied when .OVN_MULTI_NETWORK_ENABLE is true.

enable-network-segmentation=true
enable-preconfigured-udn-addresses=true
{{- if .OVN_MULTI_NETWORK_POLICY_ENABLE }}
enable-multi-networkpolicy=true
{{- end }}
enable-admin-network-policy=true
enable-multi-external-gateway=true
enable-multicast=true
{{- if .DNS_NAME_RESOLVER_ENABLE }}
enable-dns-name-resolver=true
{{- end }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,19 @@ spec:
ovn_v6_masquerade_subnet_opt="--gateway-v6-masquerade-subnet {{.V6MasqueradeSubnet}}"
fi

dns_name_resolver_enabled_flag=
if [[ "{{.DNS_NAME_RESOLVER_ENABLE}}" == "true" ]]; then
dns_name_resolver_enabled_flag="--enable-dns-name-resolver"
fi

persistent_ips_enabled_flag="--enable-persistent-ips"

# This is needed so that converting clusters from GA to TP
# will rollout control plane pods as well
network_segmentation_enabled_flag=
multi_network_enabled_flag="--enable-multi-network"
network_segmentation_enabled_flag="--enable-network-segmentation"

route_advertisements_enable_flag=
if [[ "{{.OVN_ROUTE_ADVERTISEMENTS_ENABLE}}" == "true" ]]; then
route_advertisements_enable_flag="--enable-route-advertisements"
Expand All @@ -141,6 +152,22 @@ spec:
if [[ "{{.OVN_EVPN_ENABLE}}" == "true" ]]; then
evpn_enable_flag="--enable-evpn"
fi

preconfigured_udn_addresses_enable_flag="--enable-preconfigured-udn-addresses"

# Enable multi-network policy if configured (control-plane always full mode)
multi_network_policy_enabled_flag=
if [[ "{{.OVN_MULTI_NETWORK_POLICY_ENABLE}}" == "true" ]]; then
multi_network_policy_enabled_flag="--enable-multi-networkpolicy"
fi

# Enable admin network policy if configured (control-plane always full mode)
admin_network_policy_enabled_flag="--enable-admin-network-policy"

network_connect_enabled_flag=
if [[ "{{.OVN_NETWORK_CONNECT_ENABLE}}" == "true" ]]; then
network_connect_enabled_flag="--enable-network-connect"
fi

if [ "{{.OVN_GATEWAY_MODE}}" == "shared" ]; then
gateway_mode_flags="--gateway-mode shared"
Expand Down Expand Up @@ -173,10 +200,23 @@ spec:
${ovn_v6_transit_switch_subnet_opt} \
${ovn_v4_masquerade_subnet_opt} \
${ovn_v6_masquerade_subnet_opt} \
${dns_name_resolver_enabled_flag} \
${persistent_ips_enabled_flag} \
${multi_network_enabled_flag} \
${network_segmentation_enabled_flag} \
${gateway_mode_flags} \
${network_connect_enabled_flag} \
${route_advertisements_enable_flag} \
${evpn_enable_flag}
${evpn_enable_flag} \
${preconfigured_udn_addresses_enable_flag} \
--enable-egress-ip=true \
--enable-egress-firewall=true \
--enable-egress-qos=true \
--enable-egress-service=true \
--enable-multicast \
--enable-multi-external-gateway=true \
${multi_network_policy_enabled_flag} \
${admin_network_policy_enabled_flag}
volumeMounts:
- mountPath: /run/ovnkube-config/
name: ovnkube-config
Expand Down
6 changes: 6 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ The Network operator needs to make sure that the input configuration doesn't cha

The persisted configuration must **make all defaults explicit**. This protects against inadvertent code changes that could destabilize an existing cluster.

### Per-Node Configuration

For certain specialized deployments (e.g., DPU host nodes), some features need to be disabled on a per-node basis even when enabled cluster-wide. Since ConfigMap values cannot be reliably overridden per-node, the CNO implements per-node feature enforcement through conditional logic in the startup scripts.

The `OVN_NODE_MODE` environment variable is injected into `ovnkube-node` pods and consumed by the startup script (`008-script-lib.yaml`) to conditionally enable or disable features based on the node's operational mode. This ensures that unsupported features are deterministically disabled on specialized hardware regardless of cluster-wide configuration.

## Egress Router

**Input:** `EgressRouter.network.operator.openshift.io`
Expand Down
20 changes: 20 additions & 0 deletions docs/operands.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,26 @@ configuration object (which in turn is copied there from the
configuration) is "`OVNKubernetes`". If the specified network type is
not "`OVNKubernetes`", the CNO will not render any network plugin.

### OVN-Kubernetes Node Modes

OVN-Kubernetes supports different node operational modes through the `OVN_NODE_MODE`
environment variable. This allows per-node feature enforcement, particularly for
specialized hardware like DPU (Data Processing Unit) hosts where certain features
must be disabled.

The startup script (`008-script-lib.yaml`) contains conditional logic that adjusts
feature enablement based on the node mode:

- **`full` mode (default)**: All features enabled as configured
- **`dpu-host` mode**: Certain features like egress IP, multicast, multi-network
policies, and admin network policies are automatically disabled regardless of
cluster-wide configuration

This approach was necessary because ConfigMap values (`004-config.yaml`) cannot be
reliably overridden on a per-node basis, but startup script logic can be conditional.

For detailed information, see `docs/ovn_node_mode.md`.

## Multus

Multus is deployed as long as `.spec.disableMultiNetwork` is not set.
Expand Down
Loading