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