diff mbox

[4/4] lib/test_crc: Add test cases for crc calculation

Message ID 20180716165507.23100-5-colyli@suse.de (mailing list archive)
State New, archived
Headers show

Commit Message

Coly Li July 16, 2018, 4:55 p.m. UTC
This patch adds a kernel module to test the consistency of multiple crc
calculation in Linux kernel. It is enabled with CONFIG_TEST_CRC enabled.

The test results are printed into kernel message, which look like,

test_crc: crc64_le: PASSED (0x4e6b1ff972fa8c55, expval 0x4e6b1ff972fa8c55)
test_crc: crc64_le_bch: PASSED (0x0e4f1391d7a4a62e, expval 0x0e4f1391d7a4a62e)
test_crc: crc64_le_update: FAILED (0x03d4d0d85685d9a1, expval 0x3d4d0d85685d9a1f)

kernel 0day system has framework to check kernel message, then the above
result can be handled by 0day system. If crc calculation inconsistency
happens, it can be detected quite soon.

lib/test_crc.c can is a testing frame work for all crc consistency
testings. For now, there are only test caes for 3 crc routines,
- crc64_le()
- crc64_le_bch()
- crc64_le_update()

Signed-off-by: Coly Li <colyli@suse.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Luis R. Rodriguez <mcgrof@suse.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Kate Stewart <kstewart@linuxfoundation.org>
---
 lib/Kconfig.debug |  11 ++++
 lib/Makefile      |   1 +
 lib/test_crc.c    | 136 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 148 insertions(+)
 create mode 100644 lib/test_crc.c

Comments

Randy Dunlap July 16, 2018, 6:05 p.m. UTC | #1
On 07/16/2018 09:55 AM, Coly Li wrote:
> This patch adds a kernel module to test the consistency of multiple crc
> calculation in Linux kernel. It is enabled with CONFIG_TEST_CRC enabled.
> 
> The test results are printed into kernel message, which look like,
> 
> test_crc: crc64_le: PASSED (0x4e6b1ff972fa8c55, expval 0x4e6b1ff972fa8c55)
> test_crc: crc64_le_bch: PASSED (0x0e4f1391d7a4a62e, expval 0x0e4f1391d7a4a62e)
> test_crc: crc64_le_update: FAILED (0x03d4d0d85685d9a1, expval 0x3d4d0d85685d9a1f)
> 
> kernel 0day system has framework to check kernel message, then the above
> result can be handled by 0day system. If crc calculation inconsistency
> happens, it can be detected quite soon.
> 
> lib/test_crc.c can is a testing frame work for all crc consistency

            drop ^^^ "can"

Well, we already have (from lib/Makefile):
obj-$(CONFIG_CRC32_SELFTEST)	+= crc32test.o

so lib/test_crc.c isn't exactly "for all crc".


> testings. For now, there are only test caes for 3 crc routines,
> - crc64_le()
> - crc64_le_bch()
> - crc64_le_update()
> 
> Signed-off-by: Coly Li <colyli@suse.de>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Luis R. Rodriguez <mcgrof@suse.com>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Kate Stewart <kstewart@linuxfoundation.org>
> ---
>  lib/Kconfig.debug |  11 ++++
>  lib/Makefile      |   1 +
>  lib/test_crc.c    | 136 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 148 insertions(+)
>  create mode 100644 lib/test_crc.c


> diff --git a/lib/test_crc.c b/lib/test_crc.c
> new file mode 100644
> index 000000000000..3a9442252de5
> --- /dev/null
> +++ b/lib/test_crc.c
> @@ -0,0 +1,136 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * CRC test driver
> + *
> + * Copyright (C) 2018 Coly Li <colyli@suse.de>
> + *
> + * This module provides an simple framework to check the consistency of
> + * Linux kernel crc calculation routines in lib/crc*.c. This driver

                   CRC

> + * requires CONFIG_CRC* items to be enabled if the associated routines are
> + * tested here. The test results will be printed to kernel message
> + * when this test driver is loaded.
> + *
> + * Current test routines are,
> + * - crc64_le()
> + * - crc64_le_bch()
> + * - crc64_le_update()
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/printk.h>
> +#include <linux/fs.h>
> +#include <linux/miscdevice.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +#include <linux/async.h>
> +#include <linux/delay.h>
> +#include <linux/vmalloc.h>
> +#include <linux/crc64.h>
> +
> +struct crc_test_record {
> +
> +	char	*name;
> +	__le64	data[4];
> +	__le64	initval;
> +	__le64	expval;
> +	int	(*handler)(struct crc_test_record *rec);
> +};
> +
> +static int chk_and_msg(const char *name, __le64 crc, __le64 expval)
> +{
> +	int ret = 0;
> +
> +	if (crc == expval) {
> +		pr_info("test_crc: %s: PASSED:(0x%016llx, expval 0x%016llx)",
> +			name, crc, expval);
> +	} else {
> +		pr_err("test_crc: %s: FAILED:(0x%016llx, expval 0x%016llx)",
> +			name, crc, expval);

For both pr_err() lines, please print "expected" instead of "expval".

> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +/* Add your crc test caese here */

               CRC test cases

> +static int test_crc64_le(struct crc_test_record *rec)
> +{
> +	__le64 crc;
> +
> +	crc = crc64_le(rec->data, sizeof(rec->data));
> +	return chk_and_msg(rec->name, crc, rec->expval);
> +
> +}
> +
> +static int test_crc64_le_bch(struct crc_test_record *rec)
> +{
> +	__le64 crc;
> +
> +	crc = crc64_le_bch(rec->data, sizeof(rec->data));
> +	return chk_and_msg(rec->name, crc, rec->expval);
> +}
> +
> +static int test_crc64_le_update(struct crc_test_record *rec)
> +{
> +	__le64 crc = rec->initval;
> +
> +	crc = crc64_le_update(crc, rec->data, sizeof(rec->data));
> +	return chk_and_msg(rec->name, crc, rec->expval);
> +}
> +
> +/*
> + * Set up your crc test initial data here.
> + * Do not change the existing items, they are hard coded with
> + * pre-calculated values.
> + */
> +static struct crc_test_record test_data[] = {
> +	{ .name		= "crc64_le",
> +	  .data		= { 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
> +			    0xC711223CFA3E5BB5, 0x493366450E42ECDF },
> +	  .initval	= 0,
> +	  .expval	= 0xe2b9911e7b997201,
> +	  .handler	= test_crc64_le,
> +	},
> +	{ .name		= "crc64_le_bch",
> +	  .data		= { 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
> +			    0xC711223CFA3E5BB5, 0x493366450E42ECDF },
> +	  .initval	= 0,
> +	  .expval	= 0xd2753a20fd862892,
> +	  .handler	= test_crc64_le_bch,
> +	},
> +	{ .name		= "crc64_le_update",
> +	  .data		= { 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
> +			    0xC711223CFA3E5BB5, 0x493366450E42ECDF },
> +	  .initval	= 0x61C8864680B583EB,
> +	  .expval	= 0xb2c863673f4292bf,
> +	  .handler	= test_crc64_le_update,
> +	},
> +	{ .name = NULL, }
> +};
> +
> +
> +static int __init test_crc_init(void)
> +{
> +	int i;
> +	int v, ret = 0;
> +
> +	pr_info("Kernel crc consitency testing:");

	                CRC consistency

> +	for (i = 0; test_data[i].name; i++) {
> +		v = test_data[i].handler(&test_data[i]);
> +		if (v < 0 && ret == 0)
> +			ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +late_initcall(test_crc_init);
> +
> +static void __exit test_crc_exit(void) { }
> +module_exit(test_crc_exit);
> +
> +MODULE_DESCRIPTION("CRC consistency testing driver");
> +MODULE_AUTHOR("Coly Li <colyli@suse.de>");
> +MODULE_LICENSE("GPL");
> 


thanks,
Andy Shevchenko July 16, 2018, 8:47 p.m. UTC | #2
On Mon, Jul 16, 2018 at 7:55 PM, Coly Li <colyli@suse.de> wrote:
> This patch adds a kernel module to test the consistency of multiple crc
> calculation in Linux kernel. It is enabled with CONFIG_TEST_CRC enabled.
>
> The test results are printed into kernel message, which look like,
>
> test_crc: crc64_le: PASSED (0x4e6b> +
1ff972fa8c55, expval 0x4e6b1ff972fa8c55)
> test_crc: crc64_le_bch: PASSED (0x0e4f1391d7a4a62e, expval 0x0e4f1391d7a4a62e)
> test_crc: crc64_le_update: FAILED (0x03d4d0d85685d9a1, expval 0x3d4d0d85685d9a1f)
>
> kernel 0day system has framework to check kernel message, then the above
> result can be handled by 0day system. If crc calculation inconsistency
> happens, it can be detected quite soon.
>
> lib/test_crc.c can is a testing frame work for all crc consistency
> testings. For now, there are only test caes for 3 crc routines,
> - crc64_le()
> - crc64_le_bch()
> - crc64_le_update()

> +config TEST_CRC
> +       tristate "CRC calculation test driver"

> +       default n

Default default is n.

> +       depends on CRC64

> +#include <linux/init.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/printk.h>
> +#include <linux/fs.h>
> +#include <linux/miscdevice.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +#include <linux/async.h>
> +#include <linux/delay.h>
> +#include <linux/vmalloc.h>
> +#include <linux/crc64.h>

Perhaps in order?

Moreover, either init.h or module.h depending on the Kconfig (here
seems module.h is a right choice).

> +struct crc_test_record {

> +

Redundant.

> +       char    *name;
> +       __le64  data[4];
> +       __le64  initval;
> +       __le64  expval;
> +       int     (*handler)(struct crc_test_record *rec);
> +};
> +
> +static int chk_and_msg(const char *name, __le64 crc, __le64 expval)
> +{
> +       int ret = 0;
> +
> +       if (crc == expval) {
> +               pr_info("test_crc: %s: PASSED:(0x%016llx, expval 0x%016llx)",
> +                       name, crc, expval);
> +       } else {
> +               pr_err("test_crc: %s: FAILED:(0x%016llx, expval 0x%016llx)",
> +                       name, crc, expval);
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;

Perhaps collect statistics instead how it's done in many other tests?

> +}
> +
> +/* Add your crc test caese here */

caese ?

> +static int test_crc64_le(struct crc_test_record *rec)
> +{
> +       __le64 crc;
> +
> +       crc = crc64_le(rec->data, sizeof(rec->data));
> +       return chk_and_msg(rec->name, crc, rec->expval);

> +

Redundant.

> +}

> +       { .name = NULL, }

Simple {} would work.

> +static int __init test_crc_init(void)
> +{
> +       int i;
> +       int v, ret = 0;
> +
> +       pr_info("Kernel crc consitency testing:");
> +       for (i = 0; test_data[i].name; i++) {

> +               v = test_data[i].handler(&test_data[i]);
> +               if (v < 0 && ret == 0)
> +                       ret = -EINVAL;

A bit strange. Anyway, better to collect statistics and print it at
the end with corresponding return code.

> +       }
> +
> +       return ret;
> +}

> +late_initcall(test_crc_init);

Why?

> +static void __exit test_crc_exit(void) { }
> +module_exit(test_crc_exit);

> +MODULE_LICENSE("GPL");

It's not the same as in SPDX.
Coly Li July 17, 2018, 3:37 a.m. UTC | #3
On 2018/7/17 2:05 AM, Randy Dunlap wrote:
> On 07/16/2018 09:55 AM, Coly Li wrote:
>> This patch adds a kernel module to test the consistency of multiple crc
>> calculation in Linux kernel. It is enabled with CONFIG_TEST_CRC enabled.
>>
>> The test results are printed into kernel message, which look like,
>>
>> test_crc: crc64_le: PASSED (0x4e6b1ff972fa8c55, expval 0x4e6b1ff972fa8c55)
>> test_crc: crc64_le_bch: PASSED (0x0e4f1391d7a4a62e, expval 0x0e4f1391d7a4a62e)
>> test_crc: crc64_le_update: FAILED (0x03d4d0d85685d9a1, expval 0x3d4d0d85685d9a1f)
>>
>> kernel 0day system has framework to check kernel message, then the above
>> result can be handled by 0day system. If crc calculation inconsistency
>> happens, it can be detected quite soon.
>>

Hi Randy,

>> lib/test_crc.c can is a testing frame work for all crc consistency
> 
>             drop ^^^ "can"
> 

All the following issues are fixed in v2 series, thank you for the review.

> Well, we already have (from lib/Makefile):
> obj-$(CONFIG_CRC32_SELFTEST)	+= crc32test.o
> 
> so lib/test_crc.c isn't exactly "for all crc".
> 

My plan is to add extra consistency test cases for crc32/crc32c for
consistency testing. Consistency testing case is much simpler than the
code in crc32test.c, the results of test_crc.c are in unified format so
0day testing can handle them in a simple way.

I agree with you that 'for all crc' is inaccurate before the
crc32/crc32c test cases added into test_crc. So in v2 series, it will be
modified to 'for many crc consistency testings'.

Thanks.

Coly Li

> 
>> testings. For now, there are only test caes for 3 crc routines,
>> - crc64_le()
>> - crc64_le_bch()
>> - crc64_le_update()
>>
>> Signed-off-by: Coly Li <colyli@suse.de>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Cc: Luis R. Rodriguez <mcgrof@suse.com>
>> Cc: Linus Torvalds <torvalds@linux-foundation.org>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Kate Stewart <kstewart@linuxfoundation.org>
>> ---
>>  lib/Kconfig.debug |  11 ++++
>>  lib/Makefile      |   1 +
>>  lib/test_crc.c    | 136 ++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 148 insertions(+)
>>  create mode 100644 lib/test_crc.c
> 
> 
>> diff --git a/lib/test_crc.c b/lib/test_crc.c
>> new file mode 100644
>> index 000000000000..3a9442252de5
>> --- /dev/null
>> +++ b/lib/test_crc.c
>> @@ -0,0 +1,136 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * CRC test driver
>> + *
>> + * Copyright (C) 2018 Coly Li <colyli@suse.de>
>> + *
>> + * This module provides an simple framework to check the consistency of
>> + * Linux kernel crc calculation routines in lib/crc*.c. This driver
> 
>                    CRC
> 
>> + * requires CONFIG_CRC* items to be enabled if the associated routines are
>> + * tested here. The test results will be printed to kernel message
>> + * when this test driver is loaded.
>> + *
>> + * Current test routines are,
>> + * - crc64_le()
>> + * - crc64_le_bch()
>> + * - crc64_le_update()
>> + *
>> + */
>> +
>> +#include <linux/init.h>
>> +#include <linux/list.h>
>> +#include <linux/module.h>
>> +#include <linux/printk.h>
>> +#include <linux/fs.h>
>> +#include <linux/miscdevice.h>
>> +#include <linux/slab.h>
>> +#include <linux/uaccess.h>
>> +#include <linux/async.h>
>> +#include <linux/delay.h>
>> +#include <linux/vmalloc.h>
>> +#include <linux/crc64.h>
>> +
>> +struct crc_test_record {
>> +
>> +	char	*name;
>> +	__le64	data[4];
>> +	__le64	initval;
>> +	__le64	expval;
>> +	int	(*handler)(struct crc_test_record *rec);
>> +};
>> +
>> +static int chk_and_msg(const char *name, __le64 crc, __le64 expval)
>> +{
>> +	int ret = 0;
>> +
>> +	if (crc == expval) {
>> +		pr_info("test_crc: %s: PASSED:(0x%016llx, expval 0x%016llx)",
>> +			name, crc, expval);
>> +	} else {
>> +		pr_err("test_crc: %s: FAILED:(0x%016llx, expval 0x%016llx)",
>> +			name, crc, expval);
> 
> For both pr_err() lines, please print "expected" instead of "expval".
> 
>> +		ret = -EINVAL;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +/* Add your crc test caese here */
> 
>                CRC test cases
> 
>> +static int test_crc64_le(struct crc_test_record *rec)
>> +{
>> +	__le64 crc;
>> +
>> +	crc = crc64_le(rec->data, sizeof(rec->data));
>> +	return chk_and_msg(rec->name, crc, rec->expval);
>> +
>> +}
>> +
>> +static int test_crc64_le_bch(struct crc_test_record *rec)
>> +{
>> +	__le64 crc;
>> +
>> +	crc = crc64_le_bch(rec->data, sizeof(rec->data));
>> +	return chk_and_msg(rec->name, crc, rec->expval);
>> +}
>> +
>> +static int test_crc64_le_update(struct crc_test_record *rec)
>> +{
>> +	__le64 crc = rec->initval;
>> +
>> +	crc = crc64_le_update(crc, rec->data, sizeof(rec->data));
>> +	return chk_and_msg(rec->name, crc, rec->expval);
>> +}
>> +
>> +/*
>> + * Set up your crc test initial data here.
>> + * Do not change the existing items, they are hard coded with
>> + * pre-calculated values.
>> + */
>> +static struct crc_test_record test_data[] = {
>> +	{ .name		= "crc64_le",
>> +	  .data		= { 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
>> +			    0xC711223CFA3E5BB5, 0x493366450E42ECDF },
>> +	  .initval	= 0,
>> +	  .expval	= 0xe2b9911e7b997201,
>> +	  .handler	= test_crc64_le,
>> +	},
>> +	{ .name		= "crc64_le_bch",
>> +	  .data		= { 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
>> +			    0xC711223CFA3E5BB5, 0x493366450E42ECDF },
>> +	  .initval	= 0,
>> +	  .expval	= 0xd2753a20fd862892,
>> +	  .handler	= test_crc64_le_bch,
>> +	},
>> +	{ .name		= "crc64_le_update",
>> +	  .data		= { 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
>> +			    0xC711223CFA3E5BB5, 0x493366450E42ECDF },
>> +	  .initval	= 0x61C8864680B583EB,
>> +	  .expval	= 0xb2c863673f4292bf,
>> +	  .handler	= test_crc64_le_update,
>> +	},
>> +	{ .name = NULL, }
>> +};
>> +
>> +
>> +static int __init test_crc_init(void)
>> +{
>> +	int i;
>> +	int v, ret = 0;
>> +
>> +	pr_info("Kernel crc consitency testing:");
> 
> 	                CRC consistency
> 
>> +	for (i = 0; test_data[i].name; i++) {
>> +		v = test_data[i].handler(&test_data[i]);
>> +		if (v < 0 && ret == 0)
>> +			ret = -EINVAL;
>> +	}
>> +
>> +	return ret;
>> +}
>> +late_initcall(test_crc_init);
>> +
>> +static void __exit test_crc_exit(void) { }
>> +module_exit(test_crc_exit);
>> +
>> +MODULE_DESCRIPTION("CRC consistency testing driver");
>> +MODULE_AUTHOR("Coly Li <colyli@suse.de>");
>> +MODULE_LICENSE("GPL");
>>
> 
> 
> thanks,
>
Coly Li July 17, 2018, 4:38 a.m. UTC | #4
On 2018/7/17 4:47 AM, Andy Shevchenko wrote:
> On Mon, Jul 16, 2018 at 7:55 PM, Coly Li <colyli@suse.de> wrote:
>> This patch adds a kernel module to test the consistency of multiple crc
>> calculation in Linux kernel. It is enabled with CONFIG_TEST_CRC enabled.
>>
>> The test results are printed into kernel message, which look like,
>>
>> test_crc: crc64_le: PASSED (0x4e6b> +
> 1ff972fa8c55, expval 0x4e6b1ff972fa8c55)
>> test_crc: crc64_le_bch: PASSED (0x0e4f1391d7a4a62e, expval 0x0e4f1391d7a4a62e)
>> test_crc: crc64_le_update: FAILED (0x03d4d0d85685d9a1, expval 0x3d4d0d85685d9a1f)
>>
>> kernel 0day system has framework to check kernel message, then the above
>> result can be handled by 0day system. If crc calculation inconsistency
>> happens, it can be detected quite soon.
>>
>> lib/test_crc.c can is a testing frame work for all crc consistency
>> testings. For now, there are only test caes for 3 crc routines,
>> - crc64_le()
>> - crc64_le_bch()
>> - crc64_le_update()
> 
>> +config TEST_CRC
>> +       tristate "CRC calculation test driver"
> 

Hi Andy,

>> +       default n
> 
> Default default is n.
> 

I see TEST_FIRMWARE, TEST_SYSCTL, TEST_UDELAY, TEST_STATIC_KEYS arround
TEST_CRC all have 'default n', then I think to follow the style it might
be better to have 'default n' here too.


>> +       depends on CRC64
> 
>> +#include <linux/init.h>
>> +#include <linux/list.h>
>> +#include <linux/module.h>
>> +#include <linux/printk.h>
>> +#include <linux/fs.h>
>> +#include <linux/miscdevice.h>
>> +#include <linux/slab.h>
>> +#include <linux/uaccess.h>
>> +#include <linux/async.h>
>> +#include <linux/delay.h>
>> +#include <linux/vmalloc.h>
>> +#include <linux/crc64.h>
> 
> Perhaps in order?

Do you mean in alphabet order of header file names ? I will do it in v2
series.

> 
> Moreover, either init.h or module.h depending on the Kconfig (here
> seems module.h is a right choice).
> 

Sure I will keep module.h in v2 series.

>> +struct crc_test_record {
> 
>> +
> 
> Redundant.

Removed.

> 
>> +       char    *name;
>> +       __le64  data[4];
>> +       __le64  initval;
>> +       __le64  expval;
>> +       int     (*handler)(struct crc_test_record *rec);
>> +};
>> +
>> +static int chk_and_msg(const char *name, __le64 crc, __le64 expval)
>> +{
>> +       int ret = 0;
>> +
>> +       if (crc == expval) {
>> +               pr_info("test_crc: %s: PASSED:(0x%016llx, expval 0x%016llx)",
>> +                       name, crc, expval);
>> +       } else {
>> +               pr_err("test_crc: %s: FAILED:(0x%016llx, expval 0x%016llx)",
>> +                       name, crc, expval);
>> +               ret = -EINVAL;
>> +       }
>> +
>> +       return ret;
> 
> Perhaps collect statistics instead how it's done in many other tests?
> 

Good idea. I will add this in v2 series.

>> +}
>> +
>> +/* Add your crc test caese here */
> 
> caese ?

Fixed.

> 
>> +static int test_crc64_le(struct crc_test_record *rec)
>> +{
>> +       __le64 crc;
>> +
>> +       crc = crc64_le(rec->data, sizeof(rec->data));
>> +       return chk_and_msg(rec->name, crc, rec->expval);
> 
>> +
> 
> Redundant.
> 

Fixed.

>> +}
> 
>> +       { .name = NULL, }
> 
> Simple {} would work.
> 

Fixed.

>> +static int __init test_crc_init(void)
>> +{
>> +       int i;
>> +       int v, ret = 0;
>> +
>> +       pr_info("Kernel crc consitency testing:");
>> +       for (i = 0; test_data[i].name; i++) {
> 
>> +               v = test_data[i].handler(&test_data[i]);
>> +               if (v < 0 && ret == 0)
>> +                       ret = -EINVAL;
> 
> A bit strange. Anyway, better to collect statistics and print it at
> the end with corresponding return code.
> 

Sure, I will add this :-)

>> +       }
>> +
>> +       return ret;
>> +}
> 
>> +late_initcall(test_crc_init);
> 
> Why?

Oh, IMHO this is a test module, we don't need to occupy boot time and it
should be good to invoke it after other modules loaded. As I see many
other test modules do this.

> 
>> +static void __exit test_crc_exit(void) { }
>> +module_exit(test_crc_exit);
> 
>> +MODULE_LICENSE("GPL");
> 
> It's not the same as in SPDX.
> 

Nice catch, I will change it to MODULE_LICENSE("GPL v2").

Thanks for all your review !

Coly Li
diff mbox

Patch

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 8838d1158d19..c7deb4e2e4eb 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1911,6 +1911,17 @@  config TEST_SYSCTL
 
 	  If unsure, say N.
 
+config TEST_CRC
+	tristate "CRC calculation test driver"
+	default n
+	depends on CRC64
+	help
+	  This builds the "test_crc" module. This driver enables to test the
+	  CRC calculation consistency to make sure new modification does not
+	  break existing checksum calculation.
+
+	  if unsure, say N.
+
 config TEST_UDELAY
 	tristate "udelay test driver"
 	default n
diff --git a/lib/Makefile b/lib/Makefile
index 40c215181687..224d047d026a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -49,6 +49,7 @@  obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o
 obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
 obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
+obj-$(CONFIG_TEST_CRC) += test_crc.o
 obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o
 obj-$(CONFIG_TEST_KASAN) += test_kasan.o
 CFLAGS_test_kasan.o += -fno-builtin
diff --git a/lib/test_crc.c b/lib/test_crc.c
new file mode 100644
index 000000000000..3a9442252de5
--- /dev/null
+++ b/lib/test_crc.c
@@ -0,0 +1,136 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CRC test driver
+ *
+ * Copyright (C) 2018 Coly Li <colyli@suse.de>
+ *
+ * This module provides an simple framework to check the consistency of
+ * Linux kernel crc calculation routines in lib/crc*.c. This driver
+ * requires CONFIG_CRC* items to be enabled if the associated routines are
+ * tested here. The test results will be printed to kernel message
+ * when this test driver is loaded.
+ *
+ * Current test routines are,
+ * - crc64_le()
+ * - crc64_le_bch()
+ * - crc64_le_update()
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/async.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/crc64.h>
+
+struct crc_test_record {
+
+	char	*name;
+	__le64	data[4];
+	__le64	initval;
+	__le64	expval;
+	int	(*handler)(struct crc_test_record *rec);
+};
+
+static int chk_and_msg(const char *name, __le64 crc, __le64 expval)
+{
+	int ret = 0;
+
+	if (crc == expval) {
+		pr_info("test_crc: %s: PASSED:(0x%016llx, expval 0x%016llx)",
+			name, crc, expval);
+	} else {
+		pr_err("test_crc: %s: FAILED:(0x%016llx, expval 0x%016llx)",
+			name, crc, expval);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/* Add your crc test caese here */
+static int test_crc64_le(struct crc_test_record *rec)
+{
+	__le64 crc;
+
+	crc = crc64_le(rec->data, sizeof(rec->data));
+	return chk_and_msg(rec->name, crc, rec->expval);
+
+}
+
+static int test_crc64_le_bch(struct crc_test_record *rec)
+{
+	__le64 crc;
+
+	crc = crc64_le_bch(rec->data, sizeof(rec->data));
+	return chk_and_msg(rec->name, crc, rec->expval);
+}
+
+static int test_crc64_le_update(struct crc_test_record *rec)
+{
+	__le64 crc = rec->initval;
+
+	crc = crc64_le_update(crc, rec->data, sizeof(rec->data));
+	return chk_and_msg(rec->name, crc, rec->expval);
+}
+
+/*
+ * Set up your crc test initial data here.
+ * Do not change the existing items, they are hard coded with
+ * pre-calculated values.
+ */
+static struct crc_test_record test_data[] = {
+	{ .name		= "crc64_le",
+	  .data		= { 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
+			    0xC711223CFA3E5BB5, 0x493366450E42ECDF },
+	  .initval	= 0,
+	  .expval	= 0xe2b9911e7b997201,
+	  .handler	= test_crc64_le,
+	},
+	{ .name		= "crc64_le_bch",
+	  .data		= { 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
+			    0xC711223CFA3E5BB5, 0x493366450E42ECDF },
+	  .initval	= 0,
+	  .expval	= 0xd2753a20fd862892,
+	  .handler	= test_crc64_le_bch,
+	},
+	{ .name		= "crc64_le_update",
+	  .data		= { 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26,
+			    0xC711223CFA3E5BB5, 0x493366450E42ECDF },
+	  .initval	= 0x61C8864680B583EB,
+	  .expval	= 0xb2c863673f4292bf,
+	  .handler	= test_crc64_le_update,
+	},
+	{ .name = NULL, }
+};
+
+
+static int __init test_crc_init(void)
+{
+	int i;
+	int v, ret = 0;
+
+	pr_info("Kernel crc consitency testing:");
+	for (i = 0; test_data[i].name; i++) {
+		v = test_data[i].handler(&test_data[i]);
+		if (v < 0 && ret == 0)
+			ret = -EINVAL;
+	}
+
+	return ret;
+}
+late_initcall(test_crc_init);
+
+static void __exit test_crc_exit(void) { }
+module_exit(test_crc_exit);
+
+MODULE_DESCRIPTION("CRC consistency testing driver");
+MODULE_AUTHOR("Coly Li <colyli@suse.de>");
+MODULE_LICENSE("GPL");