From bb29ccf718461e0c861039fe8e5fd20bc491e39c Mon Sep 17 00:00:00 2001 From: Yuvarani Shankar Date: Mon, 22 Jun 2026 21:51:07 -0700 Subject: [PATCH] fix: set InTreeModulesToRemove on OpenShift only to unload in-tree ionic driver (NETOP-176) (#333) On OpenShift (RHEL CoreOS), the in-tree ionic kernel module loads at boot and binds to the PCI device before KMM can intervene. This causes KMM's out-of-tree module loading to fail with "could not insert ionic_rdma: Unknown symbol in module". Set InTreeModulesToRemove to ["ionic"] in the KMM Module CR's KernelMapping only on OpenShift, so KMM unloads the in-tree driver before loading the out-of-tree module stack. On Kubernetes (Ubuntu), the in-tree ionic driver is not present, so InTreeModulesToRemove is left empty to avoid triggering unnecessary module reload cycles. Co-authored-by: Yuva Shankar <11082310+yuva29@users.noreply.github.com> Co-authored-by: Claude Opus 4 (1M context) (cherry picked from commit 40990d1a846e691e29098f01008f94095162fe03) --- internal/kmmmodule/kmmmodule.go | 22 ++++++++++------- internal/kmmmodule/kmmmodule_test.go | 36 +++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/internal/kmmmodule/kmmmodule.go b/internal/kmmmodule/kmmmodule.go index 6f27c68a..df04f657 100644 --- a/internal/kmmmodule/kmmmodule.go +++ b/internal/kmmmodule/kmmmodule.go @@ -328,6 +328,9 @@ func (km *kmmModule) setKMMModuleLoader(ctx context.Context, mod *kmmv1beta1.Mod func getKernelMappings(nwConfig *amdv1alpha1.NetworkConfig, isOpenshift bool, nodes *v1.NodeList) ([]kmmv1beta1.KernelMapping, string, error) { inTreeModuleToRemove := "" + if isOpenshift { + inTreeModuleToRemove = ionicModuleName + } if nodes == nil || len(nodes.Items) == 0 { return nil, "", fmt.Errorf("No nodes found for the label selector %s", MapToLabelSelector(nwConfig.Spec.Selector)) @@ -495,14 +498,17 @@ func getKM(nwConfig *amdv1alpha1.NetworkConfig, node v1.Node, inTreeModuleToRemo } } - return kmmv1beta1.KernelMapping{ - Literal: node.Status.NodeInfo.KernelVersion, - ContainerImage: driversImage, - InTreeModuleToRemove: inTreeModuleToRemove, - Build: kmmBuild, - Sign: kmmSign, - RegistryTLS: registryTLS, - }, driversVersion, nil + km := kmmv1beta1.KernelMapping{ + Literal: node.Status.NodeInfo.KernelVersion, + ContainerImage: driversImage, + Build: kmmBuild, + Sign: kmmSign, + RegistryTLS: registryTLS, + } + if inTreeModuleToRemove != "" { + km.InTreeModulesToRemove = []string{inTreeModuleToRemove} + } + return km, driversVersion, nil } func addNodeInfoSuffixToImageTag(imgStr string, osName, driversVersion string) string { diff --git a/internal/kmmmodule/kmmmodule_test.go b/internal/kmmmodule/kmmmodule_test.go index 93fa9d64..c1301155 100644 --- a/internal/kmmmodule/kmmmodule_test.go +++ b/internal/kmmmodule/kmmmodule_test.go @@ -213,7 +213,7 @@ var _ = Describe("BaseImageRegistry and BaseImageRegistryTLS", func() { }, } - km, _, err := getKM(nwConfig, node, "", true) // isOpenShift = true + km, _, err := getKM(nwConfig, node, "ionic", true) // isOpenShift = true Expect(err).To(BeNil()) Expect(km.Build).NotTo(BeNil()) @@ -231,6 +231,40 @@ var _ = Describe("BaseImageRegistry and BaseImageRegistryTLS", func() { }) }) +var _ = Describe("getKernelMappings", func() { + newNetworkConfig := func() *amdv1alpha1.NetworkConfig { + return &amdv1alpha1.NetworkConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-config", + Namespace: "test-ns", + }, + Spec: amdv1alpha1.NetworkConfigSpec{ + Driver: amdv1alpha1.DriverSpec{ + Version: "6.2.2", + }, + }, + } + } + + It("should set InTreeModulesToRemove to ionic on OpenShift", func() { + kms, _, err := getKernelMappings(newNetworkConfig(), true, testNodeList) + Expect(err).To(BeNil()) + Expect(kms).NotTo(BeEmpty()) + for _, km := range kms { + Expect(km.InTreeModulesToRemove).To(Equal([]string{"ionic"})) + } + }) + + It("should not set InTreeModulesToRemove on Kubernetes", func() { + kms, _, err := getKernelMappings(newNetworkConfig(), false, testNodeList) + Expect(err).To(BeNil()) + Expect(kms).NotTo(BeEmpty()) + for _, km := range kms { + Expect(km.InTreeModulesToRemove).To(BeNil()) + } + }) +}) + var _ = PDescribe("setKMMModuleLoader", func() { It("KMM module creation - default input values", func() { mod := kmmv1beta1.Module{