diff --git a/bindata/network/ovn-kubernetes/common/008-script-lib.yaml b/bindata/network/ovn-kubernetes/common/008-script-lib.yaml index c22fca3126..1885ba99a2 100644 --- a/bindata/network/ovn-kubernetes/common/008-script-lib.yaml +++ b/bindata/network/ovn-kubernetes/common/008-script-lib.yaml @@ -490,6 +490,9 @@ data: local metrics_port=$2 local ovn_metrics_port=$3 + # Ensure ovn_advertised_udn_isolation_mode_flag is always defined + ovn_advertised_udn_isolation_mode_flag= + if [[ $# -ne 3 ]]; then echo "Expected three arguments but got $#" exit 1 @@ -610,6 +613,10 @@ data: sysctl -w net.ipv6.conf.all.forwarding=0 fi + if [[ "{{.AdvertisedUDNIsolationMode}}" != "" ]]; then + ovn_advertised_udn_isolation_mode_flag="--advertised-udn-isolation-mode={{.AdvertisedUDNIsolationMode}}" + fi + NETWORK_NODE_IDENTITY_ENABLE= if [[ "{{.NETWORK_NODE_IDENTITY_ENABLE}}" == "true" ]]; then NETWORK_NODE_IDENTITY_ENABLE=" @@ -679,6 +686,7 @@ data: --acl-logging-rate-limit "{{.OVNPolicyAuditRateLimit}}" \ ${gw_interface_flag} \ ${ip_forwarding_flag} \ + ${ovn_advertised_udn_isolation_mode_flag} \ ${NETWORK_NODE_IDENTITY_ENABLE} \ ${ovn_v4_join_subnet_opt} \ ${ovn_v6_join_subnet_opt} \ diff --git a/pkg/bootstrap/types.go b/pkg/bootstrap/types.go index 8ed4331330..dcc43e457a 100644 --- a/pkg/bootstrap/types.go +++ b/pkg/bootstrap/types.go @@ -33,6 +33,11 @@ type OVNConfigBoostrapResult struct { SmartNicModeLabel string SmartNicModeNodes []string MgmtPortResourceName string + // ConfigOverrides contains the overrides for the OVN Kubernetes configuration + // This is used to set the hidden OVN Kubernetes configuration in the cluster + // It is a map of key-value pairs where the key is the configuration option and the + // value is the configuration value. + ConfigOverrides map[string]string } // OVNUpdateStatus contains the status of existing daemonset diff --git a/pkg/network/ovn_kubernetes.go b/pkg/network/ovn_kubernetes.go index b8640eb4bd..69e5578e2a 100644 --- a/pkg/network/ovn_kubernetes.go +++ b/pkg/network/ovn_kubernetes.go @@ -68,7 +68,9 @@ const OVN_NODE_IDENTITY_CERT_DURATION = "24h" const OVN_EGRESSIP_HEALTHCHECK_PORT = "9107" const ( - OVSFlowsConfigMapName = "ovs-flows-config" + OVSFlowsConfigMapName = "ovs-flows-config" + OVNKubernetesConfigOverridesCMName = "ovn-kubernetes-config-overrides" + OVSFlowsConfigNamespace = names.APPLIED_NAMESPACE defaultV4InternalSubnet = "100.64.0.0/16" defaultV6InternalSubnet = "fd98::/64" @@ -180,6 +182,7 @@ func renderOVNKubernetes(conf *operv1.NetworkSpec, bootstrapResult *bootstrap.Bo data.Data["NETWORK_NODE_IDENTITY_ENABLE"] = bootstrapResult.Infra.NetworkNodeIdentityEnabled data.Data["NodeIdentityCertDuration"] = OVN_NODE_IDENTITY_CERT_DURATION data.Data["IsNetworkTypeLiveMigration"] = false + data.Data["AdvertisedUDNIsolationMode"] = bootstrapResult.OVN.OVNKubernetesConfig.ConfigOverrides["advertised-udn-isolation-mode"] if conf.Migration != nil { if conf.Migration.MTU != nil && conf.Migration.Mode != operv1.LiveNetworkMigrationMode { @@ -869,6 +872,11 @@ func bootstrapOVNConfig(conf *operv1.Network, kubeClient cnoclient.Client, hc *h return nil, fmt.Errorf("Node %s has multiple hardware offload labels.", nodeName) } + ovnConfigResult.ConfigOverrides, err = getOVNKubernetesConfigOverrides(kubeClient) + if err != nil { + return nil, fmt.Errorf("Could not get OVN Kubernetes config overrides: %w", err) + } + klog.Infof("OVN configuration is now %+v", ovnConfigResult) ovnConfigResult.DisableUDPAggregation = getDisableUDPAggregation(kubeClient.ClientFor("").CRClient()) @@ -1975,3 +1983,21 @@ func GetMasqueradeSubnet(conf *operv1.OVNKubernetesConfig) (v4Subnet, v6Subnet s } return } + +// getOVNKubernetesConfigOverrides retrieves OVN Kubernetes configuration overrides from the +// openshift-network-operator/ovn-kubernetes-config-overrides configmap. +// If the configmap exists, it returns the data as a map. +// If the configmap does not exist, it returns nil, indicating that no overrides are set +// and no error. +// If there is an error retrieving the configmap, it returns an error. +func getOVNKubernetesConfigOverrides(client cnoclient.Client) (map[string]string, error) { + configMap := &corev1.ConfigMap{} + if err := client.Default().CRClient().Get(context.TODO(), + types.NamespacedName{Name: OVNKubernetesConfigOverridesCMName, Namespace: names.APPLIED_NAMESPACE}, configMap); err != nil { + if apierrors.IsNotFound(err) { + return nil, nil + } + return nil, fmt.Errorf("unable to retrieve config from configmap %v: %s", OVNKubernetesConfigOverridesCMName, err) + } + return configMap.Data, nil +} diff --git a/pkg/network/ovn_kubernetes_test.go b/pkg/network/ovn_kubernetes_test.go index 4434244a67..8287ba8aeb 100644 --- a/pkg/network/ovn_kubernetes_test.go +++ b/pkg/network/ovn_kubernetes_test.go @@ -3977,6 +3977,18 @@ func extractOVNKubeConfig(g *WithT, objs []*uns.Unstructured) string { return "" } +func extractOVNScriptLib(g *WithT, objs []*uns.Unstructured) string { + for _, obj := range objs { + if obj.GetKind() == "ConfigMap" && obj.GetName() == "ovnkube-script-lib" { + val, ok, err := uns.NestedString(obj.Object, "data", "ovnkube-lib.sh") + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(ok).To(BeTrue()) + return val + } + } + return "" +} + // checkDaemonsetAnnotation check that all the daemonset have the annotation with the // same key and value func checkDaemonsetAnnotation(g *WithT, objs []*uns.Unstructured, key, value string) bool { @@ -4192,3 +4204,44 @@ func Test_renderOVNKubernetes(t *testing.T) { }) } } + +func TestRenderOVNKubernetes_AdvertisedUDNIsolationModeOverride(t *testing.T) { + g := NewGomegaWithT(t) + + crd := OVNKubernetesConfig.DeepCopy() + config := &crd.Spec + fillDefaults(config, nil) + + renderWithOverrides := func(overrides map[string]string) string { + bootstrapResult := fakeBootstrapResult() + bootstrapResult.OVN = bootstrap.OVNBootstrapResult{ + ControlPlaneReplicaCount: 3, + OVNKubernetesConfig: &bootstrap.OVNConfigBoostrapResult{ + DpuHostModeLabel: OVN_NODE_SELECTOR_DEFAULT_DPU_HOST, + DpuModeLabel: OVN_NODE_SELECTOR_DEFAULT_DPU, + SmartNicModeLabel: OVN_NODE_SELECTOR_DEFAULT_SMART_NIC, + MgmtPortResourceName: "", + HyperShiftConfig: &bootstrap.OVNHyperShiftBootstrapResult{ + Enabled: false, + }, + ConfigOverrides: overrides, + }, + } + featureGatesCNO := getDefaultFeatureGates() + fakeClient := cnofake.NewFakeClient() + + objs, _, err := renderOVNKubernetes(config, bootstrapResult, manifestDirOvn, fakeClient, featureGatesCNO) + g.Expect(err).NotTo(HaveOccurred()) + return extractOVNScriptLib(g, objs) + } + + t.Run("with advertised-udn-isolation-mode override", func(t *testing.T) { + ovnkubeScriptLib := renderWithOverrides(map[string]string{"advertised-udn-isolation-mode": "loose"}) + g.Expect(ovnkubeScriptLib).To(ContainSubstring(`--advertised-udn-isolation-mode=loose"`)) + }) + + t.Run("without advertised-udn-isolation-mode override", func(t *testing.T) { + ovnkubeScriptLib := renderWithOverrides(nil) + g.Expect(ovnkubeScriptLib).To(ContainSubstring(`--advertised-udn-isolation-mode="`)) + }) +}