[Devel] [PATCH vz10] tests: add ve_printk selftest

Aleksei Oladko aleksey.oladko at virtuozzo.com
Wed Dec 3 03:48:04 MSK 2025


On 12/2/25 11:32 AM, Konstantin Khorenko wrote:
> On 11/26/25 21:04, Aleksei Oladko wrote:
>> Add selftests for the printk virtualization feature. The new tests cover
>> ve_printk, ve_printk_ratelimited, net_ve_ratelimited, and log buffer
>> overflow handling.
>>
>> https://virtuozzo.atlassian.net/browse/VSTOR-114252
>>
>> Signed-off-by: Aleksei Oladko <aleksey.oladko at virtuozzo.com>
>> ---
>>   tools/testing/selftests/Makefile              |   1 +
>>   tools/testing/selftests/ve_printk/.gitignore  |   3 +
>>   tools/testing/selftests/ve_printk/Makefile    |   8 +
>>   tools/testing/selftests/ve_printk/test_segf.c |  12 +
>>   tools/testing/selftests/ve_printk/test_trap.c |   5 +
>>   .../selftests/ve_printk/ve_printk_test.c      | 593 ++++++++++++++++++
>>   6 files changed, 622 insertions(+)
>>   create mode 100644 tools/testing/selftests/ve_printk/.gitignore
>>   create mode 100644 tools/testing/selftests/ve_printk/Makefile
>>   create mode 100644 tools/testing/selftests/ve_printk/test_segf.c
>>   create mode 100644 tools/testing/selftests/ve_printk/test_trap.c
>>   create mode 100644 tools/testing/selftests/ve_printk/ve_printk_test.c
>>
>> diff --git a/tools/testing/selftests/Makefile 
>> b/tools/testing/selftests/Makefile
>> index 363d031a16f7..7334fb207676 100644
>> --- a/tools/testing/selftests/Makefile
>> +++ b/tools/testing/selftests/Makefile
>> @@ -113,6 +113,7 @@ TARGETS += tty
>>   TARGETS += uevent
>>   TARGETS += user_events
>>   TARGETS += vDSO
>> +TARGETS += ve_printk
>>   TARGETS += mm
>>   TARGETS += x86
>>   TARGETS += zram
>> diff --git a/tools/testing/selftests/ve_printk/.gitignore 
>> b/tools/testing/selftests/ve_printk/.gitignore
>> new file mode 100644
>> index 000000000000..a4ad6620b803
>> --- /dev/null
>> +++ b/tools/testing/selftests/ve_printk/.gitignore
>> @@ -0,0 +1,3 @@
>> +ve_printk_test
>> +test_segf
>> +test_trap
>> diff --git a/tools/testing/selftests/ve_printk/Makefile 
>> b/tools/testing/selftests/ve_printk/Makefile
>> new file mode 100644
>> index 000000000000..e3edcbacda1e
>> --- /dev/null
>> +++ b/tools/testing/selftests/ve_printk/Makefile
>> @@ -0,0 +1,8 @@
>> +# SPDX-License-Identifier: GPL-2.0
>> +# Makefile for ve_printk selftests.
>> +CFLAGS = -g -I../../../../usr/include/ -Wall -O2
>> +
>> +TEST_GEN_PROGS += ve_printk_test
>> +TEST_GEN_FILES += test_segf test_trap
>> +
>> +include ../lib.mk
>> diff --git a/tools/testing/selftests/ve_printk/test_segf.c 
>> b/tools/testing/selftests/ve_printk/test_segf.c
>> new file mode 100644
>> index 000000000000..cdc89068ca06
>> --- /dev/null
>> +++ b/tools/testing/selftests/ve_printk/test_segf.c
>> @@ -0,0 +1,12 @@
>> +#include <stdio.h>
>> +#include <unistd.h>
>> +
>> +int main(void)
>> +{
>> +    int *p = (int *)0xffffffffffffff00;
>> +
>> +    printf("%d\n", getpid());
>> +    fflush(stdout);
>> +    *p = 1;
>> +    return 0;
>> +}
>> diff --git a/tools/testing/selftests/ve_printk/test_trap.c 
>> b/tools/testing/selftests/ve_printk/test_trap.c
>> new file mode 100644
>> index 000000000000..b774e2b9484c
>> --- /dev/null
>> +++ b/tools/testing/selftests/ve_printk/test_trap.c
>> @@ -0,0 +1,5 @@
>> +int main(void)
>> +{
>> +    __asm__("int3");
>> +    return 0;
>> +}
>> diff --git a/tools/testing/selftests/ve_printk/ve_printk_test.c 
>> b/tools/testing/selftests/ve_printk/ve_printk_test.c
>> new file mode 100644
>> index 000000000000..78475ff71faa
>> --- /dev/null
>> +++ b/tools/testing/selftests/ve_printk/ve_printk_test.c
>> @@ -0,0 +1,593 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +#define _GNU_SOURCE
>> +#include <linux/sched.h>
>> +#include <time.h>
>> +#include <sched.h>
>> +#include <sys/wait.h>
>> +#include <unistd.h>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <fcntl.h>
>> +#include <string.h>
>> +#include <sys/stat.h>
>> +#include <sys/mount.h>
>> +#include <linux/limits.h>
>> +#include <errno.h>
>> +
>> +#include "../kselftest_harness.h"
>> +
>> +#define __STACK_SIZE (8 * 1024 * 1024)
>> +#define CTID_MIN 108
>> +#define CTID_MAX 200
>> +#define SEGFAULT_PROG "test_segf"
>> +#define TRAP_PROG "test_trap"
>> +#define TEST_RATELIMIT_BURST 10
>> +#define TEST_RATELIMIT 5
>> +
>> +static int has_substr(char *buf, const char *str)
>> +{
>> +    char *token;
>> +    char *str_ptr = buf;
>> +
>> +    while ((token = strsep(&str_ptr, ",")) != NULL) {
>> +        if (!strcmp(token, str))
>> +            return 1;
>> +    }
>> +    return 0;
>> +}
>> +
>> +static int get_mount_path(const char *fstype, const char *subsys, 
>> char *out, int size)
>> +{
>> +    FILE *fp;
>> +    int n;
>> +    char buf[PATH_MAX];
>> +    char target[4096];
>> +    char ops[4096];
>> +    char format[4096];
>> +    int ret = 1;
>> +
>> +    snprintf(format, sizeof(format), "%%*s %%4095s %s %%4095s", 
>> fstype);
>> +
>> +    fp = fopen("/proc/mounts", "r");
>> +    if (fp == NULL)
>> +        return -1;
>> +
>> +    while (fgets(buf, sizeof(buf), fp)) {
>> +        n = sscanf(buf, format, target, ops);
>> +        if (n != 2)
>> +            continue;
>> +        if (subsys == NULL || has_substr(ops, subsys)) {
>> +            strncpy(out, target, size);
>> +            out[size-1] = '\0';
>> +            ret = 0;
>> +            break;
>> +        }
>> +    }
>> +    fclose(fp);
>> +
>> +    return ret;
>> +}
>> +
>> +FIXTURE(ve_printk)
>> +{
>> +    char cgv2_path[PATH_MAX];
>> +    char cgve_path[PATH_MAX];
>> +    int ctid;
>> +};
>> +
>> +FIXTURE_SETUP(ve_printk)
>> +{
>> +    char path[PATH_MAX * 2];
>> +
>> +    ASSERT_EQ(get_mount_path("cgroup2", NULL, self->cgv2_path, 
>> sizeof(self->cgv2_path)), 0);
>> +    ASSERT_EQ(get_mount_path("cgroup", "ve", self->cgve_path, 
>> sizeof(self->cgve_path)), 0);
>> +
>> +    self->ctid = CTID_MIN;
>> +    while (self->ctid < CTID_MAX) {
>> +        snprintf(path, sizeof(path), "%s/%d", self->cgve_path, 
>> self->ctid);
>> +        if (access(path, F_OK) && errno == ENOENT) {
>> +            snprintf(path, sizeof(path), "%s/%d", self->cgv2_path, 
>> self->ctid);
>> +            if (access(path, F_OK)) {
>> +                break;
>> +            }
>> +        }
>> +        self->ctid++;
>> +    }
>> +    ASSERT_LT(self->ctid, CTID_MAX);
>> +
>> +    snprintf(path, sizeof(path), "%s/%d", self->cgv2_path, self->ctid);
>> +    ASSERT_EQ(mkdir(path, 0755), 0);
>> +    snprintf(path, sizeof(path), "%s/%d", self->cgve_path, self->ctid);
>> +    ASSERT_EQ(mkdir(path, 0755), 0);
>> +    snprintf(path, sizeof(path), "echo %d > %s/%d/ve.veid",
>> +            self->ctid, self->cgve_path, self->ctid);
>> +    ASSERT_EQ(system(path), 0);
>> +};
>> +
>> +FIXTURE_TEARDOWN(ve_printk)
>> +{
>> +    char path[PATH_MAX * 2];
>> +
>> +    snprintf(path, sizeof(path), "%s/%d/vz.slice", self->cgv2_path, 
>> self->ctid);
>> +    rmdir(path);
>> +    snprintf(path, sizeof(path), "%s/%d", self->cgv2_path, self->ctid);
>> +    rmdir(path);
>> +    snprintf(path, sizeof(path), "%s/%d", self->cgve_path, self->ctid);
>> +    rmdir(path);
>> +}
>> +
>> +int setup_timens(void)
>> +{
>> +    int ret, fd;
>> +
>> +    if (access("/proc/self/timens_offsets", F_OK))
>> +        return 0;
>> +
>> +    if (unshare(CLONE_NEWTIME)) {
>> +        return -1;
>> +    }
>> +
>> +    fd = open("/proc/self/ns/time_for_children", O_RDONLY);
>> +    if (fd < 0) {
>> +        return -1;
>> +    }
>> +
>> +    ret = setns(fd, CLONE_NEWTIME);
>> +
>> +    close(fd);
>> +    return ret;
>> +}
>> +
>> +struct fargs {
>> +    char *cgve;
>> +    int ctid;
>> +    int test;
>> +};
>> +
>> +enum {
>> +    TEST_LOG,
>> +    TEST_LOGV0,
>> +    TEST_LOGBOTH,
>> +    TEST_PR_RATELIMIT,
>> +    TEST_OVERFLOW,
>> +};
>> +
>> +int ve_printk_test_logct(void)
>> +{
>> +    FILE *pdmesg;
>> +    char buf[1024];
>> +    char str[256];
>> +    FILE *f;
>> +    int pid;
>> +    int ret = 2;
>> +
>> +    f = popen("./" SEGFAULT_PROG, "r");
>> +    if (!f)
>> +        return -1;
>> +
>> +    if (fscanf(f, "%d", &pid) != 1) {
>> +        pclose(f);
>> +        return -1;
>> +    }
>> +    pclose(f);
>> +
>> +    pdmesg = popen("dmesg", "r");
>> +    if (!pdmesg)
>> +        return -1;
>> +
>> +    snprintf(str, sizeof(str), "%s[%d]: segfault at", SEGFAULT_PROG, 
>> pid);
>> +    while (fgets(buf, sizeof(buf), pdmesg)) {
>> +        if (ret == 2 && strstr(buf, str)) {
>> +            ret = 1;
>> +        }
>> +        if (ret == 1 && strstr(buf, "Code: ")) {
>> +            ret = 0;
>> +            break;
>> +        }
>> +    }
>> +    pclose(pdmesg);
>> +    return ret;
>> +}
>> +
>> +int ve_printk_test_logve0(void)
>> +{
>> +    FILE *pdmesg;
>> +    char buf[1024];
>> +        int ret = 0;
>> +
>> +    /* do_trap -> show_signal -> print_vma_addr -> 
>> ve_print_vma_addr(VE0_LOG, ... */
>> +    system("./" TRAP_PROG);
>> +
>> +    pdmesg = popen("dmesg", "r");
>> +    if (!pdmesg)
>> +        return -1;
>> +
>> +    while (fgets(buf, sizeof(buf), pdmesg)) {
>> +        if (strstr(buf, "traps: test_trap[") &&
>> +            strstr(buf, " in test_trap[")) {
>> +            ret = 1;
>> +            break;
>> +        }
>> +    }
>> +    pclose(pdmesg);
>> +    return ret;
>> +}
>> +
>> +int ve_printk_test_logboth(void)
>> +{
>> +    FILE *pdmesg;
>> +    char buf[1024];
>> +        int ret = TEST_RATELIMIT_BURST;
>> +
>> +    system("ip link set up dev lo");
>> +    /*
>> +     * Reduce the connection tracking table size to 2. After two 
>> ping calls the
>> +     * table will be full, and all new packets will trigger
>> +     * net_veboth_ratelimited
>> +     */
>> +    system("echo 2 > /proc/sys/net/nf_conntrack_max");
>
> Restore nf_conntrack_max after the test.
This parameter is modified inside the container.
>
>> +    system("iptables -A INPUT -m conntrack --ctstate 
>> RELATED,ESTABLISHED -j ACCEPT");
>
> Please cleanup those rules after the test.
This rule is added inside the container.
>
>> +    system("ping -q -c 1 -w 1 127.0.0.1 > /dev/null");
>> +    system("ping -q -c 1 -w 1 127.0.0.1 > /dev/null");
>> +    /* net_veboth_ratelimited */
>> +    system("ping -q -c 100 -w 1 -i 0.0001 127.0.0.1 > /dev/null");
>> +
>> +    pdmesg = popen("dmesg", "r");
>> +    if (!pdmesg)
>> +        return -1;
>> +
>> +    while (fgets(buf, sizeof(buf), pdmesg)) {
>> +        if (strstr(buf, "nf_conntrack table full, dropping packet")) {
>> +            ret--;
>> +        }
>> +    }
>> +    pclose(pdmesg);
>> +    return ret;
>> +}
>> +
>> +int ve_printk_test_ratelimit(void)
>> +{
>> +    FILE *pdmesg;
>> +    char buf[1024];
>> +        int ret = TEST_RATELIMIT_BURST + 1;
>> +    int supressed = 1;
>> +    int i;
>> +
>> +    /* reject_tg_check -> ve_printk_ratelimited(VE_LOG, ... */
>> +    for (i = 0; i < 2 * TEST_RATELIMIT_BURST; i++) {
>> +        system("iptables -A INPUT -s 10.20.30.40 -j REJECT 
>> --reject-with tcp-reset &> /dev/null");
>
> Please cleanup those rules after the test.
All attempts to add rules will fail
>
>> +    }
>> +    sleep(TEST_RATELIMIT + 1);
>> +    system("iptables -A INPUT -s 10.20.30.40 -j REJECT --reject-with 
>> tcp-reset &> /dev/null");
>
> Please cleanup those rules after the test.
>
> BTW, here we have many "system" calls and none ret checks.
> In the meanwhile even iptables may be easily missing.
>
> i think need to add a wrapper which checks err code after system().
>
>> +
>> +    pdmesg = popen("dmesg", "r");
>> +    if (!pdmesg)
>> +        return -1;
>> +
>> +    while (fgets(buf, sizeof(buf), pdmesg)) {
>> +        if (strstr(buf, "TCP_RESET invalid for non-tcp")) {
>> +            ret--;
>> +        }
>> +        if (strstr(buf, "reject_tg_check") && strstr(buf, "callbacks 
>> suppressed"))
>> +            supressed--;
>> +    }
>> +    pclose(pdmesg);
>> +
>> +    return ret + supressed;
>> +}
>> +
>> +int ve_printk_test_overflow(void)
>> +{
>> +    int i;
>> +
>> +    /*
>> +     * Ten program segfaults are enough to overflow the container's 
>> log buffer
>> +     * Run 15 to ensure the buffer is actually overflowed.
>> +     */
>> +    for (i = 0; i < 15; i++) {
>> +        system("./" SEGFAULT_PROG " > /dev/null");
>> +        /* bypass printk_ratelimit */
>> +        if (i == 9)
>> +            sleep(5);
>> +    }
>> +    return ve_printk_test_logct();
>> +}
>> +
>> +int child_func(void *arg)
>> +{
>> +    int ret;
>> +    int fd;
>> +    struct fargs *args = (struct fargs *)arg;
>> +    char cg_state[PATH_MAX];
>> +
>> +    ret = setup_timens();
>> +    if (ret)
>> +        return ret;
>> +
>> +    snprintf(cg_state, sizeof(cg_state), "%s/%d/ve.state", 
>> args->cgve, args->ctid);
>> +
>> +    (void)umount2("/proc", MNT_DETACH);
>> +    ret = mount("proc", "/proc", "proc", 0, NULL);
>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    fd = open("/proc/self/uid_map", O_WRONLY);
>> +    if (fd < 0)
>> +        return -1;
>> +    write(fd, "0 0 1\n", 6);
>
> ret/num of bytes check?
>
>> +    close(fd);
>> +
>> +    fd = open("/proc/self/gid_map", O_WRONLY);
>> +    if (fd < 0)
>> +        return -1;
>> +    write(fd, "0 0 1\n", 6);
>
> ret/num of bytes check?
>
>> +    close(fd);
>> +
>> +    fd = open(cg_state, O_WRONLY);
>> +    if (fd < 0) {
>> +        return -1;
>> +    }
>> +
>> +    if (write(fd, "START", strlen("START")) < 0) {
>
> ret/num of bytes check?
>
>> +        close(fd);
>> +        return -1;
>> +    }
>> +
>> +    close(fd);
>> +
>> +    switch(args->test) {
>> +    case TEST_LOG:
>> +        ret = ve_printk_test_logct();
>> +        break;
>> +    case TEST_LOGV0:
>> +        ret = ve_printk_test_logve0();
>> +        break;
>> +    case TEST_LOGBOTH:
>> +        ret = ve_printk_test_logboth();
>> +        break;
>> +    case TEST_PR_RATELIMIT:
>> +        ret = ve_printk_test_ratelimit();
>> +        break;
>> +    case TEST_OVERFLOW:
>> +        ret = ve_printk_test_overflow();
>> +        break;
>> +    default:
>> +        ret = -1;
>> +    }
>> +    return ret;
>> +}
>> +
>> +int enter_cgroup(const char *cgroup, int ctid)
>> +{
>> +    char cg_path[PATH_MAX];
>> +    char pid_str[64];
>> +    int fd;
>> +    int ret = 0;
>> +
>> +    if (ctid)
>> +        snprintf(cg_path, sizeof(cg_path), "%s/%d/cgroup.procs", 
>> cgroup, ctid);
>> +    else
>> +        snprintf(cg_path, sizeof(cg_path), "%s/cgroup.procs", cgroup);
>> +    snprintf(pid_str, sizeof(pid_str), "%d", getpid());
>> +    fd = open(cg_path, O_WRONLY);
>> +    if (fd < 0) {
>> +        return -1;
>> +    }
>> +
>> +    if (write(fd, pid_str, strlen(pid_str)) < 0) {
>
> There could be a partial write, need to check the amount of written 
> bytes.
>
>> +        ret = -1;
>> +    }
>> +
>> +    close(fd);
>> +    return ret;
>> +}
>> +
>> +int run_vzct(char *cgv2, char *cgve, int ctid, int testid)
>> +{
>> +    char *stack;
>> +    char *stack_top;
>> +    pid_t pid;
>> +    int flags = CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
>> +            CLONE_NEWPID | CLONE_NEWUSER | CLONE_NEWNET |
>> +            CLONE_NEWCGROUP | SIGCHLD;
>> +    struct fargs args = {
>> +        .cgve = cgve,
>> +        .ctid = ctid,
>> +        .test = testid,
>> +    };
>> +    int status;
>> +    int ret;
>> +
>> +    stack = malloc(__STACK_SIZE);
>
> Missing free() for it?
>
>> +    if (!stack)
>> +        return -1;
>> +
>> +    ret = enter_cgroup(cgv2, ctid);
>> +    if (ret < 0)
>> +        return -1;
>> +    ret = enter_cgroup(cgve, ctid);
>> +    if (ret < 0)
>> +        return -1;
>> +
>> +    stack_top = stack + __STACK_SIZE;
>> +    pid = clone(child_func, stack_top, flags, &args);
>> +    if (pid < 0) {
>> +        return -1;
>> +    }
>> +
>> +    ret = waitpid(pid, &status, 0);
>> +    if (ret < 0)
>> +        return -1;
>> +    ret = -1;
>> +    if (WIFEXITED(status)) {
>> +        ret = WEXITSTATUS(status);
>> +    }
>> +    enter_cgroup(cgv2, 0);
>> +    enter_cgroup(cgve, 0);
>> +
>> +    return ret;
>> +}
>> +
>> +FILE *open_dmesg(void)
>> +{
>> +    int fd;
>> +    FILE *fdmesg;
>> +    char buf[1024];
>> +
>> +    fd = open("/dev/kmsg", O_RDONLY | O_NONBLOCK);
>> +    if (fd < 0)
>> +        return NULL;
>> +    fdmesg = fdopen(fd, "r");
>> +    if (!fdmesg)
>> +        return NULL;
>> +
>> +    while (fgets(buf, sizeof(buf), fdmesg)) ;
>
> If fgets returns an error, "while" cycle will continue.
fgets returns NULL on error.
>
>> +    return fdmesg;
>> +}
>> +
>> +int restore_param(const char *path, int val)
>> +{
>> +    int fd;
>> +    char str[16];
>> +
>> +    fd = open(path, O_WRONLY);
>> +    if (fd < 0)
>> +        return -1;
>> +    snprintf(str, sizeof(str), "%d", val);
>> +    write(fd, str, strlen(str));
>
> To check the error code here?
>
>> +    close(fd);
>> +
>> +    return 0;
>> +}
>> +
>> +int set_param(const char *path, int val, int *old)
>> +{
>> +    FILE *f;
>> +
>> +    f = fopen(path, "r");
>> +    if (!f)
>> +        return -1;
>> +    if (fscanf(f, "%u", old) != 1) {
>> +        fclose(f);
>> +        return -1;
>> +    }
>> +    fclose(f);
>> +    if (*old == val)
>> +        return 0;
>> +    return restore_param(path, val);
>> +}
>> +
>> +TEST_F(ve_printk, ve_log)
>> +{
>> +    int ret;
>> +    FILE *fdmesg;
>> +    char buf[1024];
>> +    int old;
>> +
>> +    ASSERT_EQ(set_param("/proc/sys/debug/exception-trace", 1, &old), 
>> 0);
>> +    fdmesg = open_dmesg();
>> +    ASSERT_NE(fdmesg, NULL);
>> +
>> +    ret = run_vzct(self->cgv2_path, self->cgve_path, self->ctid, 
>> TEST_LOG);
>> +    ASSERT_EQ(ret, 0);
>> +
>> +    while (fgets(buf, sizeof(buf), fdmesg)) {
>> +        ASSERT_EQ(strstr(buf, SEGFAULT_PROG) && strstr(buf, 
>> "segfault at"), false);
>> +        EXPECT_EQ(strstr(buf, "Code: "), NULL);
>> +    }
>> +    fclose(fdmesg);
>> +    restore_param("/proc/sys/debug/exception-trace", old);
>> +}
>> +
>> +TEST_F(ve_printk, ve0_log)
>> +{
>> +    int ret;
>> +    FILE *fdmesg;
>> +    char buf[1024];
>> +    int ex_trace;
>> +
>> +    ASSERT_EQ(set_param("/proc/sys/debug/exception-trace", 1, 
>> &ex_trace), 0);
>> +    fdmesg = open_dmesg();
>> +    ASSERT_NE(fdmesg, NULL);
>> +
>> +    ret = run_vzct(self->cgv2_path, self->cgve_path, self->ctid, 
>> TEST_LOGV0);
>> +    ASSERT_EQ(ret, 0);
>> +
>> +    while (fgets(buf, sizeof(buf), fdmesg)) {
>> +        if (strstr(buf, "traps: test_trap[") &&
>> +            strstr(buf, " in test_trap[")) {
>> +            ret = 1;
>> +            break;
>> +        }
>> +    }
>> +    fclose(fdmesg);
>> +    restore_param("/proc/sys/debug/exception-trace", ex_trace);
>> +    ASSERT_EQ(ret, 1);
>> +}
>> +
>> +TEST_F(ve_printk, ve_log_both)
>> +{
>> +    int ret;
>> +    FILE *fdmesg;
>> +    char buf[1024];
>> +    int old_ratelimit;
>> +
>> +    ASSERT_EQ(set_param("/proc/sys/net/core/message_burst",
>> +                TEST_RATELIMIT_BURST, &old_ratelimit), 0);
>
> You change /proc/sys/net/core/message_burst
>
>> +    fdmesg = open_dmesg();
>> +    ASSERT_NE(fdmesg, NULL);
>> +
>> +    ret = run_vzct(self->cgv2_path, self->cgve_path, self->ctid, 
>> TEST_LOGBOTH);
>> +    ASSERT_EQ(ret, 0);
>> +
>> +    while (fgets(buf, sizeof(buf), fdmesg)) {
>> +        if (strstr(buf, "nf_conntrack table full, dropping packet")) {
>> +            ret++;
>> +        }
>> +    }
>> +    fclose(fdmesg);
>> +    restore_param("/proc/sys/kernel/printk_ratelimit_burst", 
>> old_ratelimit);
>
> but restore /proc/sys/kernel/printk_ratelimit_burst ?
> Should it be the same as above?
>
>> +    ASSERT_EQ(ret, TEST_RATELIMIT_BURST);
>> +}
>> +
>> +TEST_F(ve_printk, ve_printk_ratelimited)
>> +{
>> +    int ret;
>> +    FILE *fdmesg;
>> +    char buf[1024];
>> +    int old_ratelimit_burst;
>> +    int old_ratelimit;
>> +
>> +    ASSERT_EQ(set_param("/proc/sys/net/core/message_burst",
>> +                TEST_RATELIMIT_BURST, &old_ratelimit_burst), 0);
>
> You change /proc/sys/net/core/message_burst
>
>> + ASSERT_EQ(set_param("/proc/sys/net/core/message_cost",
>> +                TEST_RATELIMIT, &old_ratelimit), 0);
>> +    fdmesg = open_dmesg();
>> +    ASSERT_NE(fdmesg, NULL);
>> +
>> +    ret = run_vzct(self->cgv2_path, self->cgve_path, self->ctid, 
>> TEST_PR_RATELIMIT);
>> +    ASSERT_EQ(ret, 0);
>> +
>> +    while (fgets(buf, sizeof(buf), fdmesg)) {
>> +        ASSERT_EQ(strstr(buf, "reject_tg_check") && strstr(buf, 
>> "callbacks suppressed"), false);
>> +        ASSERT_EQ(strstr(buf, "TCP_RESET invalid for non-tcp"), NULL);
>> +    }
>> +    fclose(fdmesg);
>> +    restore_param("/proc/sys/kernel/printk_ratelimit_burst", 
>> old_ratelimit_burst);
>
> but restore /proc/sys/kernel/printk_ratelimit_burst ?
> Should it be the same as above?
>
>> + restore_param("/proc/sys/net/core/message_cost", old_ratelimit);
>> +}
>> +
>> +TEST_F(ve_printk, ve_printk_overflow)
>> +{
>> +    int ret;
>> +    int ex_trace;
>> +
>> +    ASSERT_EQ(set_param("/proc/sys/debug/exception-trace", 1, 
>> &ex_trace), 0);
>> +
>> +    ret = run_vzct(self->cgv2_path, self->cgve_path, self->ctid, 
>> TEST_OVERFLOW);
>> +    ASSERT_EQ(ret, 0);
>> +    restore_param("/proc/sys/debug/exception-trace", ex_trace);
>> +
>> +}
>> +
>> +TEST_HARNESS_MAIN
>


More information about the Devel mailing list