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