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
build_prp_test_data(struct kunit * test)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
check_prp_counters(struct kunit * test,struct prp_test_data * data,u16 seq_start_a,u16 seq_expected_a,u16 seq_start_b,u16 seq_expected_b)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
prp_dup_discard_forward(struct kunit * test)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
prp_dup_discard_inside_dropwindow(struct kunit * test)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
prp_dup_discard_node_timeout(struct kunit * test)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
prp_dup_discard_out_of_sequence(struct kunit * test)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
prp_dup_discard_lan_b_late(struct kunit * test)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