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