diff --git a/CHANGELOG.md b/CHANGELOG.md index f087148..4c5f6cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,14 @@ ## v1 (active) -The v1 release supports Cisco IOS-XR release versions 7.7.1 and 7.8.1. +The v1 release supports Cisco IOS-XR release versions from 7.7.1 to 7.9.1. + +### v1.1.9 (2023-05-15) + +Changes corresponding to the release of XR version 7.9.1. + +- Add check to ensure real-time group scheduling is disabled on the host for XRd vRouter. + ### v1.1.8 (2023-03-08) diff --git a/docs/version-compatibility.md b/docs/version-compatibility.md index 3810e78..30ae828 100644 --- a/docs/version-compatibility.md +++ b/docs/version-compatibility.md @@ -3,10 +3,17 @@ This file documents compatibility between versions of this project with XR releases. In some cases extra arguments will be required to continue using older XR releases, and those cases will be documented here. - ## v1.1 -Supports XR 7.7.1 and 7.8.1 (the first and most recent released versions of XRd). +Supports all XR versions between 7.7.1 and 7.9.1 (all released versions of XRd). + +See the v1.1 section below for compatibility with XR 7.7.1. + + +### XR 7.8.1 + +- The real-time scheduling host check can be ignored before XR version 7.9.1. + ### XR 7.7.1 @@ -24,6 +31,7 @@ Supports XR 7.7.1 and 7.8.1 (the first and most recent released versions of XRd) - Does not support running with `--cgroupns=private`. - Requires `/sys/fs/cgroup/systemd/` to be mounted read-write on the host. - Does not support cgroups v2. +- The real-time scheduling host check can be ignored before XR version 7.9.1. ## v1.0 diff --git a/scripts/host-check b/scripts/host-check index 220fdcd..85445f4 100755 --- a/scripts/host-check +++ b/scripts/host-check @@ -635,6 +635,50 @@ def check_linux_security_modules() -> CheckFuncReturn: return ch_state, "\n".join(msgs) +def check_realtime_group_sched() -> CheckFuncReturn: + """Check that real-time group scheduling is disabled""" + recommendation = ( + "Running with real-time group scheduling enabled is not supported.\n" + "If real-time group scheduling (RT_GROUP_SCHED) is configured in the kernel,\n" + "it is required that this feature is disabled at runtime by adding\n" + "'kernel.sched_rt_runtime_us=-1' to /etc/sysctl.conf or in a dedicated conf\n" + "file under /etc/sysctl.d/.\n" + "For a temporary fix, run:\n" + " sysctl -w kernel.sched_rt_runtime_us=-1" + ) + + # We've specified a dependency on the Cgroup check, so can assume this will succeed. + cgroup_version = _get_cgroup_version() + + if cgroup_version == 1: + rt_runtime_us_path = "/sys/fs/cgroup/cpu/cpu.rt_runtime_us" + else: + rt_runtime_us_path = "/sys/fs/cgroup/cpu.rt_runtime_us" + + if os.path.exists(rt_runtime_us_path): + kernel_sched_rt_path = "/proc/sys/kernel/sched_rt_runtime_us" + try: + with open(kernel_sched_rt_path, "r", encoding="utf-8") as f: + val = int(f.read().strip()) + if val != -1: + return ( + CheckState.FAILED, + f"The kernel parameter kernel.sched_rt_runtime_us is set to {val}\n" + f"but must be disabled by setting it to '-1'.\n" + + recommendation, + ) + else: + return CheckState.SUCCESS, "disabled at runtime" + except Exception: + return ( + CheckState.WARNING, + f"Failed to read {kernel_sched_rt_path}, unable to check if\n" + f"real-time group scheduling is disabled.\n" + recommendation, + ) + + return CheckState.SUCCESS, "disabled in kernel config" + + def check_socket_parameters() -> CheckFuncReturn: """Check that socket kernel parameters are set high enough""" required_params = { @@ -1360,6 +1404,7 @@ VROUTER_CHECKS = [ Check("Interface kernel driver", check_interface_kernel_driver, []), Check("IOMMU", check_iommu, ["Interface kernel driver"]), Check("Shared memory pages max size", check_shmem_pages_max_size, []), + Check("Real-time Group Scheduling", check_realtime_group_sched, []), ] DOCKER_CHECKS = [ diff --git a/tests/test_host_check.py b/tests/test_host_check.py index 297b6e7..7490d6d 100644 --- a/tests/test_host_check.py +++ b/tests/test_host_check.py @@ -222,7 +222,7 @@ def test_no_args(self, capsys): xrd-vrouter checks ----------------------- -Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size +Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size, Real-time Group Scheduling ================================================================== XR platforms supported: xrd-control-plane, xrd-vrouter @@ -371,7 +371,7 @@ def test_extra_check_docker(self, capsys): xrd-vrouter checks ----------------------- -Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size +Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size, Real-time Group Scheduling ============================== Extra checks @@ -408,7 +408,7 @@ def test_extra_check_xr_compose(self, capsys): xrd-vrouter checks ----------------------- -Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size +Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size, Real-time Group Scheduling ============================== Extra checks @@ -447,7 +447,7 @@ def test_all_extra_checks(self, capsys): xrd-vrouter checks ----------------------- -Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size +Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size, Real-time Group Scheduling ============================== Extra checks @@ -510,7 +510,7 @@ def test_no_plats_supported(self, capsys): xrd-vrouter checks ----------------------- -Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size +Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size, Real-time Group Scheduling ================================================================== !! Host NOT set up correctly for any XR platforms !! @@ -539,7 +539,7 @@ def test_one_plat_supported(self, capsys): xrd-vrouter checks ----------------------- -Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size +Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size, Real-time Group Scheduling ================================================================== XR platforms supported: xrd-control-plane @@ -569,7 +569,7 @@ def test_extra_check_not_supported(self, capsys): xrd-vrouter checks ----------------------- -Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size +Checks: CPU extensions, RAM, Hugepages, Interface kernel driver, IOMMU, Shared memory pages max size, Real-time Group Scheduling ============================== Extra checks @@ -1436,6 +1436,130 @@ def test_both_enabled(self, capsys): assert not success +class TestRealtimeGroupSched(_CheckTestBase): + """Tests for Real-time Group Scheduling disabled check""" + + check_group = "xrd-vrouter" + check_name = "Real-time Group Scheduling" + files = ["/proc/sys/kernel/sched_rt_runtime_us"] + + def test_v1_disabled_in_kernel_config(self, capsys): + """Test the v1 case where disabled in kernel config""" + with mock.patch( + "host_check._get_cgroup_version", return_value=1 + ), mock.patch("os.path.exists", return_value=False): + success, output = self.perform_check(capsys, read_effects=None) + assert ( + output + == "PASS -- Real-time Group Scheduling (disabled in kernel config)\n" + ) + assert success + + def test_v1_disabled_at_runtime(self, capsys): + """Test the v1 case where disabled at runtime""" + with mock.patch( + "host_check._get_cgroup_version", return_value=1 + ), mock.patch("os.path.exists", return_value=True): + success, output = self.perform_check(capsys, read_effects="-1") + assert ( + output + == "PASS -- Real-time Group Scheduling (disabled at runtime)\n" + ) + assert success + + def test_v1_read_error(self, capsys): + """Test the limit being too low.""" + with mock.patch( + "host_check._get_cgroup_version", return_value=1 + ), mock.patch("os.path.exists", return_value=True): + success, output = self.perform_check( + capsys, read_effects=Exception + ) + assert output == textwrap.dedent( + """\ + WARN -- Real-time Group Scheduling + Failed to read /proc/sys/kernel/sched_rt_runtime_us, unable to check if + real-time group scheduling is disabled. + Running with real-time group scheduling enabled is not supported. + If real-time group scheduling (RT_GROUP_SCHED) is configured in the kernel, + it is required that this feature is disabled at runtime by adding + 'kernel.sched_rt_runtime_us=-1' to /etc/sysctl.conf or in a dedicated conf + file under /etc/sysctl.d/. + For a temporary fix, run: + sysctl -w kernel.sched_rt_runtime_us=-1 + """ + ) + assert not success + + def test_v1_failure_enabled_at_runtime(self, capsys): + """Test the check fails in the v1 case where enabled at runtime""" + with mock.patch( + "host_check._get_cgroup_version", return_value=1 + ), mock.patch("os.path.exists", return_value=True): + success, output = self.perform_check(capsys, read_effects="950000") + assert output == textwrap.dedent( + """\ + FAIL -- Real-time Group Scheduling + The kernel parameter kernel.sched_rt_runtime_us is set to 950000 + but must be disabled by setting it to '-1'. + Running with real-time group scheduling enabled is not supported. + If real-time group scheduling (RT_GROUP_SCHED) is configured in the kernel, + it is required that this feature is disabled at runtime by adding + 'kernel.sched_rt_runtime_us=-1' to /etc/sysctl.conf or in a dedicated conf + file under /etc/sysctl.d/. + For a temporary fix, run: + sysctl -w kernel.sched_rt_runtime_us=-1 + """ + ) + assert not success + + def test_v2_disabled_in_kernel_config(self, capsys): + """Test the v2 case where disabled in kernel config""" + with mock.patch( + "host_check._get_cgroup_version", return_value=2 + ), mock.patch("os.path.exists", return_value=False): + success, output = self.perform_check(capsys, read_effects=None) + assert ( + output + == "PASS -- Real-time Group Scheduling (disabled in kernel config)\n" + ) + assert success + + def test_v2_disabled_at_runtime(self, capsys): + """Test the v2 case where disabled at runtime""" + with mock.patch( + "host_check._get_cgroup_version", return_value=2 + ), mock.patch("os.path.exists", return_value=True): + success, output = self.perform_check(capsys, read_effects="-1") + assert ( + output + == "PASS -- Real-time Group Scheduling (disabled at runtime)\n" + ) + assert success + + def test_v2_failure_enabled_at_runtime(self, capsys): + """Test the check fails in the v2 case where enabled at runtime""" + with mock.patch( + "host_check._get_cgroup_version", return_value=2 + ), mock.patch("os.path.exists", return_value=True): + success, output = self.perform_check(capsys, read_effects="950000") + assert output == textwrap.dedent( + """\ + FAIL -- Real-time Group Scheduling + The kernel parameter kernel.sched_rt_runtime_us is set to 950000 + but must be disabled by setting it to '-1'. + Running with real-time group scheduling enabled is not supported. + If real-time group scheduling (RT_GROUP_SCHED) is configured in the kernel, + it is required that this feature is disabled at runtime by adding + 'kernel.sched_rt_runtime_us=-1' to /etc/sysctl.conf or in a dedicated conf + file under /etc/sysctl.d/. + For a temporary fix, run: + sysctl -w kernel.sched_rt_runtime_us=-1 + """ + ) + assert not success + + class TestSocketParameters(_CheckTestBase): """Tests for Socket Kernel Parameters check."""