1*63603515SShashank Mohan Jain // SPDX-License-Identifier: GPL-2.0
2*63603515SShashank Mohan Jain /*
3*63603515SShashank Mohan Jain * KUnit tests for the Dynamic Interrupt Moderation library
4*63603515SShashank Mohan Jain */
5*63603515SShashank Mohan Jain
6*63603515SShashank Mohan Jain #include <kunit/test.h>
7*63603515SShashank Mohan Jain #include <linux/dim.h>
8*63603515SShashank Mohan Jain #include <linux/ktime.h>
9*63603515SShashank Mohan Jain #include <linux/module.h>
10*63603515SShashank Mohan Jain
11*63603515SShashank Mohan Jain struct dim_calc_stats_case {
12*63603515SShashank Mohan Jain const char *name;
13*63603515SShashank Mohan Jain u32 delta_us;
14*63603515SShashank Mohan Jain u32 start_pkts, end_pkts;
15*63603515SShashank Mohan Jain u32 start_bytes, end_bytes;
16*63603515SShashank Mohan Jain u32 start_comps, end_comps;
17*63603515SShashank Mohan Jain int ppms, bpms, cpms;
18*63603515SShashank Mohan Jain };
19*63603515SShashank Mohan Jain
20*63603515SShashank Mohan Jain static const struct dim_calc_stats_case dim_calc_stats_cases[] = {
21*63603515SShashank Mohan Jain {
22*63603515SShashank Mohan Jain .name = "small",
23*63603515SShashank Mohan Jain .delta_us = 1000,
24*63603515SShashank Mohan Jain .end_pkts = 640, .end_bytes = 640 * 1500, .end_comps = 64,
25*63603515SShashank Mohan Jain .ppms = 640, .bpms = 960000, .cpms = 64,
26*63603515SShashank Mohan Jain },
27*63603515SShashank Mohan Jain {
28*63603515SShashank Mohan Jain .name = "round_up",
29*63603515SShashank Mohan Jain .delta_us = 3000,
30*63603515SShashank Mohan Jain .end_pkts = 10, .end_bytes = 10, .end_comps = 1,
31*63603515SShashank Mohan Jain .ppms = 4, .bpms = 4, .cpms = 1,
32*63603515SShashank Mohan Jain },
33*63603515SShashank Mohan Jain {
34*63603515SShashank Mohan Jain .name = "counter_wrap",
35*63603515SShashank Mohan Jain .delta_us = 1000,
36*63603515SShashank Mohan Jain .start_pkts = 0xffffff00, .end_pkts = 0x100,
37*63603515SShashank Mohan Jain .start_bytes = 0xfffff000, .end_bytes = 0x1000,
38*63603515SShashank Mohan Jain .start_comps = 0xfffffff0, .end_comps = 0x10,
39*63603515SShashank Mohan Jain .ppms = 0x200, .bpms = 0x2000, .cpms = 0x20,
40*63603515SShashank Mohan Jain },
41*63603515SShashank Mohan Jain {
42*63603515SShashank Mohan Jain /* 30 MB in 10 ms (24 Gbit/s): nbytes * 1000 exceeds 32 bits */
43*63603515SShashank Mohan Jain .name = "many_bytes",
44*63603515SShashank Mohan Jain .delta_us = 10000,
45*63603515SShashank Mohan Jain .end_pkts = 20000, .end_bytes = 30000000, .end_comps = 64,
46*63603515SShashank Mohan Jain .ppms = 2000, .bpms = 3000000, .cpms = 7,
47*63603515SShashank Mohan Jain },
48*63603515SShashank Mohan Jain {
49*63603515SShashank Mohan Jain /* 4.3 MB in 16 ms (2.15 Gbit/s), just above the 32-bit limit */
50*63603515SShashank Mohan Jain .name = "bytes_32bit_limit",
51*63603515SShashank Mohan Jain .delta_us = 16000,
52*63603515SShashank Mohan Jain .end_pkts = 2900, .end_bytes = 4300000, .end_comps = 64,
53*63603515SShashank Mohan Jain .ppms = 182, .bpms = 268750, .cpms = 4,
54*63603515SShashank Mohan Jain },
55*63603515SShashank Mohan Jain {
56*63603515SShashank Mohan Jain /* 5 MB in 40 ms: a 1 Gbit/s link at line rate */
57*63603515SShashank Mohan Jain .name = "gigabit",
58*63603515SShashank Mohan Jain .delta_us = 40000,
59*63603515SShashank Mohan Jain .end_pkts = 3300, .end_bytes = 5000000, .end_comps = 64,
60*63603515SShashank Mohan Jain .ppms = 83, .bpms = 125000, .cpms = 2,
61*63603515SShashank Mohan Jain },
62*63603515SShashank Mohan Jain {
63*63603515SShashank Mohan Jain /* 5 million packets and completions in 2 s */
64*63603515SShashank Mohan Jain .name = "many_packets",
65*63603515SShashank Mohan Jain .delta_us = 2000000,
66*63603515SShashank Mohan Jain .end_pkts = 5000000, .end_bytes = 5000000, .end_comps = 5000000,
67*63603515SShashank Mohan Jain .ppms = 2500, .bpms = 2500, .cpms = 2500,
68*63603515SShashank Mohan Jain },
69*63603515SShashank Mohan Jain };
70*63603515SShashank Mohan Jain
dim_calc_stats_case_desc(const struct dim_calc_stats_case * t,char * desc)71*63603515SShashank Mohan Jain static void dim_calc_stats_case_desc(const struct dim_calc_stats_case *t,
72*63603515SShashank Mohan Jain char *desc)
73*63603515SShashank Mohan Jain {
74*63603515SShashank Mohan Jain strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
75*63603515SShashank Mohan Jain }
76*63603515SShashank Mohan Jain
77*63603515SShashank Mohan Jain KUNIT_ARRAY_PARAM(dim_calc_stats, dim_calc_stats_cases,
78*63603515SShashank Mohan Jain dim_calc_stats_case_desc);
79*63603515SShashank Mohan Jain
dim_calc_stats_test(struct kunit * test)80*63603515SShashank Mohan Jain static void dim_calc_stats_test(struct kunit *test)
81*63603515SShashank Mohan Jain {
82*63603515SShashank Mohan Jain const struct dim_calc_stats_case *t = test->param_value;
83*63603515SShashank Mohan Jain struct dim_sample start = {}, end = {};
84*63603515SShashank Mohan Jain struct dim_stats stats = {};
85*63603515SShashank Mohan Jain
86*63603515SShashank Mohan Jain dim_update_sample_with_comps(0, t->start_pkts, t->start_bytes,
87*63603515SShashank Mohan Jain t->start_comps, &start);
88*63603515SShashank Mohan Jain dim_update_sample_with_comps(DIM_NEVENTS, t->end_pkts, t->end_bytes,
89*63603515SShashank Mohan Jain t->end_comps, &end);
90*63603515SShashank Mohan Jain /* dim_update_sample() stamps ktime_get(); use fixed times instead */
91*63603515SShashank Mohan Jain start.time = ktime_set(1000, 0);
92*63603515SShashank Mohan Jain end.time = ktime_add_us(start.time, t->delta_us);
93*63603515SShashank Mohan Jain
94*63603515SShashank Mohan Jain KUNIT_ASSERT_TRUE(test, dim_calc_stats(&start, &end, &stats));
95*63603515SShashank Mohan Jain KUNIT_EXPECT_EQ(test, stats.ppms, t->ppms);
96*63603515SShashank Mohan Jain KUNIT_EXPECT_EQ(test, stats.bpms, t->bpms);
97*63603515SShashank Mohan Jain KUNIT_EXPECT_EQ(test, stats.cpms, t->cpms);
98*63603515SShashank Mohan Jain KUNIT_EXPECT_EQ(test, stats.epms,
99*63603515SShashank Mohan Jain (int)DIV_ROUND_UP(DIM_NEVENTS * USEC_PER_MSEC,
100*63603515SShashank Mohan Jain t->delta_us));
101*63603515SShashank Mohan Jain }
102*63603515SShashank Mohan Jain
dim_calc_stats_no_time_test(struct kunit * test)103*63603515SShashank Mohan Jain static void dim_calc_stats_no_time_test(struct kunit *test)
104*63603515SShashank Mohan Jain {
105*63603515SShashank Mohan Jain struct dim_sample sample = {};
106*63603515SShashank Mohan Jain struct dim_stats stats = {};
107*63603515SShashank Mohan Jain
108*63603515SShashank Mohan Jain dim_update_sample_with_comps(0, 100, 1000, 10, &sample);
109*63603515SShashank Mohan Jain KUNIT_EXPECT_FALSE(test, dim_calc_stats(&sample, &sample, &stats));
110*63603515SShashank Mohan Jain }
111*63603515SShashank Mohan Jain
112*63603515SShashank Mohan Jain static struct kunit_case dim_test_cases[] = {
113*63603515SShashank Mohan Jain KUNIT_CASE_PARAM(dim_calc_stats_test, dim_calc_stats_gen_params),
114*63603515SShashank Mohan Jain KUNIT_CASE(dim_calc_stats_no_time_test),
115*63603515SShashank Mohan Jain {}
116*63603515SShashank Mohan Jain };
117*63603515SShashank Mohan Jain
118*63603515SShashank Mohan Jain static struct kunit_suite dim_test_suite = {
119*63603515SShashank Mohan Jain .name = "dim",
120*63603515SShashank Mohan Jain .test_cases = dim_test_cases,
121*63603515SShashank Mohan Jain };
122*63603515SShashank Mohan Jain
123*63603515SShashank Mohan Jain kunit_test_suite(dim_test_suite);
124*63603515SShashank Mohan Jain
125*63603515SShashank Mohan Jain MODULE_DESCRIPTION("KUnit tests for the DIM library");
126*63603515SShashank Mohan Jain MODULE_LICENSE("GPL");
127