1 // SPDX-License-Identifier: GPL-2.0 2 #include <kunit/test.h> 3 4 #include "hsr_main.h" 5 #include "hsr_framereg.h" 6 7 struct prp_test_data { 8 struct hsr_port port; 9 struct hsr_port port_rcv; 10 struct hsr_frame_info frame; 11 struct hsr_node node; 12 }; 13 14 static struct prp_test_data *build_prp_test_data(struct kunit *test) 15 { 16 struct prp_test_data *data = kunit_kzalloc(test, 17 sizeof(struct prp_test_data), GFP_USER); 18 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, data); 19 20 data->frame.node_src = &data->node; 21 data->frame.port_rcv = &data->port_rcv; 22 data->port_rcv.type = HSR_PT_SLAVE_A; 23 data->node.seq_start[HSR_PT_SLAVE_A] = 1; 24 data->node.seq_expected[HSR_PT_SLAVE_A] = 1; 25 data->node.seq_start[HSR_PT_SLAVE_B] = 1; 26 data->node.seq_expected[HSR_PT_SLAVE_B] = 1; 27 data->node.seq_out[HSR_PT_MASTER] = 0; 28 data->node.time_out[HSR_PT_MASTER] = jiffies; 29 data->port.type = HSR_PT_MASTER; 30 31 return data; 32 } 33 34 static void check_prp_counters(struct kunit *test, 35 struct prp_test_data *data, 36 u16 seq_start_a, u16 seq_expected_a, 37 u16 seq_start_b, u16 seq_expected_b) 38 { 39 KUNIT_EXPECT_EQ(test, data->node.seq_start[HSR_PT_SLAVE_A], 40 seq_start_a); 41 KUNIT_EXPECT_EQ(test, data->node.seq_start[HSR_PT_SLAVE_B], 42 seq_start_b); 43 KUNIT_EXPECT_EQ(test, data->node.seq_expected[HSR_PT_SLAVE_A], 44 seq_expected_a); 45 KUNIT_EXPECT_EQ(test, data->node.seq_expected[HSR_PT_SLAVE_B], 46 seq_expected_b); 47 } 48 49 static void prp_dup_discard_forward(struct kunit *test) 50 { 51 /* Normal situation, both LANs in sync. Next frame is forwarded */ 52 struct prp_test_data *data = build_prp_test_data(test); 53 54 data->frame.sequence_nr = 2; 55 KUNIT_EXPECT_EQ(test, 0, 56 prp_register_frame_out(&data->port, &data->frame)); 57 KUNIT_EXPECT_EQ(test, data->frame.sequence_nr, 58 data->node.seq_out[HSR_PT_MASTER]); 59 KUNIT_EXPECT_EQ(test, jiffies, data->node.time_out[HSR_PT_MASTER]); 60 check_prp_counters(test, data, data->frame.sequence_nr, 61 data->frame.sequence_nr + 1, 1, 1); 62 } 63 64 static void prp_dup_discard_inside_dropwindow(struct kunit *test) 65 { 66 /* Normal situation, other LAN ahead by one. Frame is dropped */ 67 struct prp_test_data *data = build_prp_test_data(test); 68 unsigned long time = jiffies - 10; 69 70 data->frame.sequence_nr = 1; 71 data->node.seq_expected[HSR_PT_SLAVE_B] = 3; 72 data->node.seq_out[HSR_PT_MASTER] = 2; 73 data->node.time_out[HSR_PT_MASTER] = time; 74 75 KUNIT_EXPECT_EQ(test, 1, 76 prp_register_frame_out(&data->port, &data->frame)); 77 KUNIT_EXPECT_EQ(test, 2, data->node.seq_out[HSR_PT_MASTER]); 78 KUNIT_EXPECT_EQ(test, time, data->node.time_out[HSR_PT_MASTER]); 79 check_prp_counters(test, data, 2, 2, 2, 3); 80 } 81 82 static void prp_dup_discard_node_timeout(struct kunit *test) 83 { 84 /* Timeout situation, node hasn't sent anything for a while */ 85 struct prp_test_data *data = build_prp_test_data(test); 86 87 data->frame.sequence_nr = 7; 88 data->node.seq_start[HSR_PT_SLAVE_A] = 1234; 89 data->node.seq_expected[HSR_PT_SLAVE_A] = 1235; 90 data->node.seq_start[HSR_PT_SLAVE_B] = 1234; 91 data->node.seq_expected[HSR_PT_SLAVE_B] = 1234; 92 data->node.seq_out[HSR_PT_MASTER] = 1234; 93 data->node.time_out[HSR_PT_MASTER] = 94 jiffies - msecs_to_jiffies(HSR_ENTRY_FORGET_TIME) - 1; 95 96 KUNIT_EXPECT_EQ(test, 0, 97 prp_register_frame_out(&data->port, &data->frame)); 98 KUNIT_EXPECT_EQ(test, data->frame.sequence_nr, 99 data->node.seq_out[HSR_PT_MASTER]); 100 KUNIT_EXPECT_EQ(test, jiffies, data->node.time_out[HSR_PT_MASTER]); 101 check_prp_counters(test, data, data->frame.sequence_nr, 102 data->frame.sequence_nr + 1, 1234, 1234); 103 } 104 105 static void prp_dup_discard_out_of_sequence(struct kunit *test) 106 { 107 /* One frame is received out of sequence on both LANs */ 108 struct prp_test_data *data = build_prp_test_data(test); 109 110 data->node.seq_start[HSR_PT_SLAVE_A] = 10; 111 data->node.seq_expected[HSR_PT_SLAVE_A] = 10; 112 data->node.seq_start[HSR_PT_SLAVE_B] = 10; 113 data->node.seq_expected[HSR_PT_SLAVE_B] = 10; 114 data->node.seq_out[HSR_PT_MASTER] = 9; 115 116 /* 1st old frame, should be accepted */ 117 data->frame.sequence_nr = 8; 118 KUNIT_EXPECT_EQ(test, 0, 119 prp_register_frame_out(&data->port, &data->frame)); 120 KUNIT_EXPECT_EQ(test, data->frame.sequence_nr, 121 data->node.seq_out[HSR_PT_MASTER]); 122 check_prp_counters(test, data, data->frame.sequence_nr, 123 data->frame.sequence_nr + 1, 10, 10); 124 125 /* 2nd frame should be dropped */ 126 data->frame.sequence_nr = 8; 127 data->port_rcv.type = HSR_PT_SLAVE_B; 128 KUNIT_EXPECT_EQ(test, 1, 129 prp_register_frame_out(&data->port, &data->frame)); 130 check_prp_counters(test, data, data->frame.sequence_nr + 1, 131 data->frame.sequence_nr + 1, 132 data->frame.sequence_nr + 1, 133 data->frame.sequence_nr + 1); 134 135 /* Next frame, this is forwarded */ 136 data->frame.sequence_nr = 10; 137 data->port_rcv.type = HSR_PT_SLAVE_A; 138 KUNIT_EXPECT_EQ(test, 0, 139 prp_register_frame_out(&data->port, &data->frame)); 140 KUNIT_EXPECT_EQ(test, data->frame.sequence_nr, 141 data->node.seq_out[HSR_PT_MASTER]); 142 check_prp_counters(test, data, data->frame.sequence_nr, 143 data->frame.sequence_nr + 1, 9, 9); 144 145 /* and next one is dropped */ 146 data->frame.sequence_nr = 10; 147 data->port_rcv.type = HSR_PT_SLAVE_B; 148 KUNIT_EXPECT_EQ(test, 1, 149 prp_register_frame_out(&data->port, &data->frame)); 150 check_prp_counters(test, data, data->frame.sequence_nr + 1, 151 data->frame.sequence_nr + 1, 152 data->frame.sequence_nr + 1, 153 data->frame.sequence_nr + 1); 154 } 155 156 static void prp_dup_discard_lan_b_late(struct kunit *test) 157 { 158 /* LAN B is behind */ 159 struct prp_test_data *data = build_prp_test_data(test); 160 161 data->node.seq_start[HSR_PT_SLAVE_A] = 9; 162 data->node.seq_expected[HSR_PT_SLAVE_A] = 9; 163 data->node.seq_start[HSR_PT_SLAVE_B] = 9; 164 data->node.seq_expected[HSR_PT_SLAVE_B] = 9; 165 data->node.seq_out[HSR_PT_MASTER] = 8; 166 167 data->frame.sequence_nr = 9; 168 KUNIT_EXPECT_EQ(test, 0, 169 prp_register_frame_out(&data->port, &data->frame)); 170 KUNIT_EXPECT_EQ(test, data->frame.sequence_nr, 171 data->node.seq_out[HSR_PT_MASTER]); 172 check_prp_counters(test, data, 9, 10, 9, 9); 173 174 data->frame.sequence_nr = 10; 175 KUNIT_EXPECT_EQ(test, 0, 176 prp_register_frame_out(&data->port, &data->frame)); 177 KUNIT_EXPECT_EQ(test, data->frame.sequence_nr, 178 data->node.seq_out[HSR_PT_MASTER]); 179 check_prp_counters(test, data, 9, 11, 9, 9); 180 181 data->frame.sequence_nr = 9; 182 data->port_rcv.type = HSR_PT_SLAVE_B; 183 KUNIT_EXPECT_EQ(test, 1, 184 prp_register_frame_out(&data->port, &data->frame)); 185 check_prp_counters(test, data, 10, 11, 10, 10); 186 187 data->frame.sequence_nr = 10; 188 data->port_rcv.type = HSR_PT_SLAVE_B; 189 KUNIT_EXPECT_EQ(test, 1, 190 prp_register_frame_out(&data->port, &data->frame)); 191 check_prp_counters(test, data, 11, 11, 11, 11); 192 } 193 194 static struct kunit_case prp_dup_discard_test_cases[] = { 195 KUNIT_CASE(prp_dup_discard_forward), 196 KUNIT_CASE(prp_dup_discard_inside_dropwindow), 197 KUNIT_CASE(prp_dup_discard_node_timeout), 198 KUNIT_CASE(prp_dup_discard_out_of_sequence), 199 KUNIT_CASE(prp_dup_discard_lan_b_late), 200 {} 201 }; 202 203 static struct kunit_suite prp_dup_discard_suite = { 204 .name = "prp_duplicate_discard", 205 .test_cases = prp_dup_discard_test_cases, 206 }; 207 208 kunit_test_suite(prp_dup_discard_suite); 209 210 MODULE_LICENSE("GPL"); 211 MODULE_DESCRIPTION("KUnit tests for PRP duplicate discard"); 212 MODULE_AUTHOR("Jaakko Karrenpalo <jkarrenpalo@gmail.com>"); 213