Skip to content

Build fails on CentOS Stream 9 with kernel 5.14.0-655 (RHEL 9.8 equivalent) - timer_container_of redefinition #93

Description

@dante-gomez

Summary

The ovpn-dco kernel module (v0.2.20251017) fails to compile on CentOS Stream 9 with kernel 5.14.0-655.el9.x86_64 due to timer_container_of macro redefinition. This is caused by Red Hat's aggressive backporting of kernel 6.16+ timer APIs into the 5.14 kernel baseline, which the current DCO compatibility code does not detect.

Environment

Operating System:

NAME="CentOS Stream"
VERSION="9"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="9"
PLATFORM_ID="platform:el9"
CPE_NAME="cpe:/o:centos:centos:9"

Kernel Version:

uname -r
5.14.0-655.el9.x86_64

RHEL Release Code:

grep RHEL_RELEASE /usr/src/kernels/5.14.0-655.el9.x86_64/include/generated/uapi/linux/version.h
#define RHEL_RELEASE_VERSION(a,b) (((a) << 8) + (b))
#define RHEL_RELEASE_CODE 2312
#define RHEL_RELEASE "655"

Decoded: RHEL_RELEASE_CODE 2312 = RHEL 9.8 equivalent (9 << 8 + 8 = 2312)

DCO Version:

rpm -qa | grep ovpn-dco
kmod-ovpn-dco-0.2.20251017-2.el9.noarch

DCO Git Commit: Latest from October 17, 2025 (commit 5c595d5)

Build Error

Command

cd /usr/src/ovpn-dco-0.2.20251017.2.el9
make

Error Output

In file included from <command-line>:
/usr/src/ovpn-dco-0.2.20251017.2.el9/linux-compat.h:85: warning: "timer_container_of" redefined
   85 | #define timer_container_of from_timer
      |
In file included from ./include/linux/workqueue.h:9,
                 from ./include/linux/timer.h:139:
./include/linux/timer.h:139: note: this is the location of the previous definition
  139 | #define timer_container_of(var, callback_timer, timer_fieldname)        \
      |

/usr/src/ovpn-dco-0.2.20251017.2.el9/drivers/net/ovpn-dco/peer.c: In function 'ovpn_peer_ping':
/usr/src/ovpn-dco-0.2.20251017.2.el9/linux-compat.h:85:28: error: implicit declaration of function 'from_timer'; did you mean 'mod_timer'? [-Werror=implicit-function-declaration]
   85 | #define timer_container_of from_timer
      |                            ^~~~~~~~~~
/usr/src/ovpn-dco-0.2.20251017.2.el9/drivers/net/ovpn-dco/peer.c:25:34: note: in expansion of macro 'timer_container_of'
   25 |         struct ovpn_peer *peer = timer_container_of(peer, t, keepalive_xmit);
      |                                  ^~~~~~~~~~~~~~~~~~

/usr/src/ovpn-dco-0.2.20251017.2.el9/drivers/net/ovpn-dco/peer.c:25:62: error: 'keepalive_xmit' undeclared (first use in this function)
   25 |         struct ovpn_peer *peer = timer_container_of(peer, t, keepalive_xmit);
      |                                                              ^~~~~~~~~~~~~~

cc1: some warnings being treated as errors
make[3]: *** [scripts/Makefile.build:250: /usr/src/ovpn-dco-0.2.20251017.2.el9/drivers/net/ovpn-dco/peer.o] Error 1

Full error shows compilation fails in drivers/net/ovpn-dco/peer.c at lines 25 and 33 where timer_container_of is used.

Root Cause Analysis

The Aggressive Backporting Problem

Red Hat/CentOS Stream backports features from newer kernels into their 5.14 baseline while keeping the version number as "5.14". This breaks version-based feature detection.

Timeline of timer API changes:

  • Kernel < 6.16: Uses from_timer() function
  • Kernel 6.16+: Uses timer_container_of() macro
  • CentOS Stream 5.14.0-655 (RHEL 9.8): Has timer_container_of backported from 6.16+

Current DCO Compatibility Code

File: linux-compat.h (lines 76-108)

#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0)

#ifndef UDP_ENCAP_OVPNINUDP
#define UDP_ENCAP_OVPNINUDP 100
#endif

#define timer_container_of from_timer    // ← LINE 85: THE PROBLEM

enum ovpn_ifla_attrs {
    // ...
};

#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0) */

What happens:

  1. DCO checks: LINUX_VERSION_CODE < KERNEL_VERSION(6, 16, 0)
  2. CentOS Stream kernel reports: 5.14.0-655 ✅ (passes check)
  3. DCO defines: timer_container_of as alias to from_timer
  4. But kernel already has timer_container_of (backported from 6.16+)
  5. Compiler error: macro redefinition + undefined from_timer function

Missing RHEL Version Check

Unlike other compatibility fixes in the same file (lines 130, 140, 148, 156, 160), the timer_container_of block at line 76 does not check RHEL_RELEASE_CODE.

Examples of correct RHEL detection elsewhere in the code:

// Line 130: Correct pattern with RHEL check
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 12, 0) && \
    RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9, 6)
    // ... compat code
#endif

// Line 160: Another correct pattern
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) && \
    SUSE_PRODUCT_CODE < SUSE_PRODUCT(1, 15, 5, 0) && \
    RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9, 6)
    // ... compat code
#endif

Evidence: RHEL Version Detection Works

CentOS Stream properly defines RHEL macros that DCO can use:

grep -r "RHEL_RELEASE" /usr/src/kernels/5.14.0-655.el9.x86_64/include/ | head -3

Output confirms:

#define RHEL_RELEASE_VERSION(a,b) (((a) << 8) + (b))
#define RHEL_RELEASE_CODE 2312
#define RHEL_RELEASE "655"

This means the fix is straightforward - add RHEL version detection like other compat blocks.

Comparison to Previous Similar Issues

This follows the exact same pattern as previously fixed RHEL backporting issues:

Issue #83: RHEL 9.6 Build Failure (Fixed May 2025)

  • Kernel: 5.14.0-570.16.1.el9_6
  • Error: NETIF_F_LLTX undeclared, duplicate struct members
  • Fix: Commit ed8e85b added RHEL_RELEASE_VERSION(9, 6) checks
  • Result: Fixed in v0.2.20250520

Issue #64: CentOS Stream 9 skb_gso_segment (Fixed May 2024)

  • Kernel: 5.14.0-437.el9.x86_64
  • Error: Backported net/gso.h header
  • Fix: Commit c4c4f80 added RHEL-specific exception checks
  • Result: Working in RHEL 9.4

Issue #74: CentOS Stream 9 Build Failure (Closed Feb 2025)

  • Kernel: 5.14.0-536 through 5.14.0-547
  • Error: Similar macro/struct conflicts
  • Maintainer (ordex) confirmed: "Red Hat is backporting new features to older kernels and breaking version checks. This needs explicit fixing."
  • User resolution: Migrated to CentOS Stream 10

Current Issue: timer_container_of (NEW - Unreported)

  • Kernel: 5.14.0-655.el9.x86_64 (RHEL 9.8 equivalent)
  • Error: timer_container_of redefinition
  • Cause: Backported timer API from kernel 6.16+
  • Status: ❌ Not yet fixed

Verified Workaround ✅

Status: Successfully tested on CentOS Stream 9 with kernel 5.14.0-655.el9.x86_64

Users can manually patch the source code before building by adding RHEL version check to line 85:

cd /usr/src/ovpn-dco-0.2.20251017.2.el9

# Backup original file
cp linux-compat.h linux-compat.h.ORIGINAL

# Apply patch: wrap timer_container_of definition with RHEL version check
sed -i '85i\
  /* Only define timer_container_of for kernels without the backport */\
  #if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9, 8)' linux-compat.h

sed -i '87a\
  #endif' linux-compat.h

# Verify patch (should see nested #if for RHEL check)
sed -n '83,90p' linux-compat.h

# Build and install
make clean && make
make install

# Load module
modprobe -r ovpn-dco-v2
modprobe ovpn-dco-v2

# Verify module loaded
lsmod | grep ovpn
modinfo ovpn-dco-v2

# Restart OpenVPN
systemctl restart openvpnas

Results from testing:

# Successful build
Exit code: 0
-rw-r--r-- 1 root root 5.2M Feb  4 08:49 drivers/net/ovpn-dco/ovpn-dco-v2.ko

# Module loaded successfully
ovpn_dco_v2            98304  0
ip6_udp_tunnel         16384  1 ovpn_dco_v2
udp_tunnel             36864  1 ovpn_dco_v2

# OpenVPN Access Server working
● openvpnas.service - OpenVPN Access Server
     Loaded: loaded (/usr/lib/systemd/system/openvpnas.service; enabled)
     Active: active (running)

Patched code structure:

#endif

  /* Only define timer_container_of for kernels without the backport */
  #if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9, 8)
#define timer_container_of from_timer
  #endif

enum ovpn_ifla_attrs {

This workaround follows the same pattern used in other parts of the file (lines 130, 140, 148, 156, 160) and successfully prevents the macro redefinition error.

Related Commits

Timer API Compatibility (July 2025):

  • Commit 98a25de: "ovpn-dco: compat hack for 6.15 timer_* API renaming"
  • This fixed timer_delete vs del_timer naming changes
  • Did NOT address timer_container_of for RHEL backports

6.16 Port (July 2025):

  • Commit b1b490e: "ovpn-dco: port to 6.16 and add compat hacks"
  • Changed code from from_timer() to timer_container_of()
  • Added compat layer for kernels < 6.16
  • Did NOT add RHEL version checks

Previous RHEL Fixes:

  • Commit 5c595d5 (Oct 17, 2025): "fix 5.15 compat hack for RHEL9.6"
  • Commit ed8e85b (May 20, 2025): "add compat support for RHEL 9.6"
  • Commit 2b17b01 (Jun 18, 2024): "fix gso.h compat code for RHEL 9.4"

Impact

Affected Systems:

  • CentOS Stream 9 with kernel 5.14.0-655+
  • RHEL 9.8+ (when released)
  • Potentially RHEL 9.7 (needs verification)

Repository Information

Related Issues

Similar RHEL backporting issues previously fixed:

  • #83 - RHEL 9.6 build failure
  • #74 - CentOS Stream 9 build failure
  • #64 - CentOS Stream 9 skb_gso_segment issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions