xref: /linux/net/hsr/prp_dup_discard_test.c (revision 1a9239bb4253f9076b5b4b2a1a4e8d7defd77a95)
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