1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 /*
3 * Copyright (c) 2011 Volkswagen Group Electronic Research
4 * All rights reserved.
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <string.h>
11
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/ioctl.h>
15 #include <sys/time.h>
16 #include <net/if.h>
17 #include <linux/if.h>
18
19 #include <linux/can.h>
20 #include <linux/can/raw.h>
21
22 #include "kselftest_harness.h"
23
24 #define ID 0x123
25
26 char CANIF[IFNAMSIZ];
27
send_can_frames(int sock,int testcase)28 static int send_can_frames(int sock, int testcase)
29 {
30 struct can_frame frame;
31
32 frame.can_dlc = 1;
33 frame.data[0] = testcase;
34
35 frame.can_id = ID;
36 if (write(sock, &frame, sizeof(frame)) < 0)
37 goto write_err;
38
39 frame.can_id = (ID | CAN_RTR_FLAG);
40 if (write(sock, &frame, sizeof(frame)) < 0)
41 goto write_err;
42
43 frame.can_id = (ID | CAN_EFF_FLAG);
44 if (write(sock, &frame, sizeof(frame)) < 0)
45 goto write_err;
46
47 frame.can_id = (ID | CAN_EFF_FLAG | CAN_RTR_FLAG);
48 if (write(sock, &frame, sizeof(frame)) < 0)
49 goto write_err;
50
51 return 0;
52
53 write_err:
54 perror("write");
55 return 1;
56 }
57
FIXTURE(can_filters)58 FIXTURE(can_filters) {
59 int sock;
60 };
61
FIXTURE_SETUP(can_filters)62 FIXTURE_SETUP(can_filters)
63 {
64 struct sockaddr_can addr;
65 struct ifreq ifr;
66 int recv_own_msgs = 1;
67 int s, ret;
68
69 s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
70 ASSERT_GE(s, 0)
71 TH_LOG("failed to create CAN_RAW socket: %d", errno);
72
73 strncpy(ifr.ifr_name, CANIF, sizeof(ifr.ifr_name));
74 ret = ioctl(s, SIOCGIFINDEX, &ifr);
75 ASSERT_GE(ret, 0)
76 TH_LOG("failed SIOCGIFINDEX: %d", errno);
77
78 addr.can_family = AF_CAN;
79 addr.can_ifindex = ifr.ifr_ifindex;
80
81 setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
82 &recv_own_msgs, sizeof(recv_own_msgs));
83
84 ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
85 ASSERT_EQ(ret, 0)
86 TH_LOG("failed bind socket: %d", errno);
87
88 self->sock = s;
89 }
90
FIXTURE_TEARDOWN(can_filters)91 FIXTURE_TEARDOWN(can_filters)
92 {
93 close(self->sock);
94 }
95
FIXTURE_VARIANT(can_filters)96 FIXTURE_VARIANT(can_filters) {
97 int testcase;
98 canid_t id;
99 canid_t mask;
100 int exp_num_rx;
101 canid_t exp_flags[];
102 };
103
104 /* Receive all frames when filtering for the ID in standard frame format */
FIXTURE_VARIANT_ADD(can_filters,base)105 FIXTURE_VARIANT_ADD(can_filters, base) {
106 .testcase = 1,
107 .id = ID,
108 .mask = CAN_SFF_MASK,
109 .exp_num_rx = 4,
110 .exp_flags = {
111 0,
112 CAN_RTR_FLAG,
113 CAN_EFF_FLAG,
114 CAN_EFF_FLAG | CAN_RTR_FLAG,
115 },
116 };
117
118 /* Ignore EFF flag in filter ID if not covered by filter mask */
FIXTURE_VARIANT_ADD(can_filters,base_eff)119 FIXTURE_VARIANT_ADD(can_filters, base_eff) {
120 .testcase = 2,
121 .id = ID | CAN_EFF_FLAG,
122 .mask = CAN_SFF_MASK,
123 .exp_num_rx = 4,
124 .exp_flags = {
125 0,
126 CAN_RTR_FLAG,
127 CAN_EFF_FLAG,
128 CAN_EFF_FLAG | CAN_RTR_FLAG,
129 },
130 };
131
132 /* Ignore RTR flag in filter ID if not covered by filter mask */
FIXTURE_VARIANT_ADD(can_filters,base_rtr)133 FIXTURE_VARIANT_ADD(can_filters, base_rtr) {
134 .testcase = 3,
135 .id = ID | CAN_RTR_FLAG,
136 .mask = CAN_SFF_MASK,
137 .exp_num_rx = 4,
138 .exp_flags = {
139 0,
140 CAN_RTR_FLAG,
141 CAN_EFF_FLAG,
142 CAN_EFF_FLAG | CAN_RTR_FLAG,
143 },
144 };
145
146 /* Ignore EFF and RTR flags in filter ID if not covered by filter mask */
FIXTURE_VARIANT_ADD(can_filters,base_effrtr)147 FIXTURE_VARIANT_ADD(can_filters, base_effrtr) {
148 .testcase = 4,
149 .id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
150 .mask = CAN_SFF_MASK,
151 .exp_num_rx = 4,
152 .exp_flags = {
153 0,
154 CAN_RTR_FLAG,
155 CAN_EFF_FLAG,
156 CAN_EFF_FLAG | CAN_RTR_FLAG,
157 },
158 };
159
160 /* Receive only SFF frames when expecting no EFF flag */
FIXTURE_VARIANT_ADD(can_filters,filter_eff)161 FIXTURE_VARIANT_ADD(can_filters, filter_eff) {
162 .testcase = 5,
163 .id = ID,
164 .mask = CAN_SFF_MASK | CAN_EFF_FLAG,
165 .exp_num_rx = 2,
166 .exp_flags = {
167 0,
168 CAN_RTR_FLAG,
169 },
170 };
171
172 /* Receive only EFF frames when filter id and filter mask include EFF flag */
FIXTURE_VARIANT_ADD(can_filters,filter_eff_eff)173 FIXTURE_VARIANT_ADD(can_filters, filter_eff_eff) {
174 .testcase = 6,
175 .id = ID | CAN_EFF_FLAG,
176 .mask = CAN_SFF_MASK | CAN_EFF_FLAG,
177 .exp_num_rx = 2,
178 .exp_flags = {
179 CAN_EFF_FLAG,
180 CAN_EFF_FLAG | CAN_RTR_FLAG,
181 },
182 };
183
184 /* Receive only SFF frames when expecting no EFF flag, ignoring RTR flag */
FIXTURE_VARIANT_ADD(can_filters,filter_eff_rtr)185 FIXTURE_VARIANT_ADD(can_filters, filter_eff_rtr) {
186 .testcase = 7,
187 .id = ID | CAN_RTR_FLAG,
188 .mask = CAN_SFF_MASK | CAN_EFF_FLAG,
189 .exp_num_rx = 2,
190 .exp_flags = {
191 0,
192 CAN_RTR_FLAG,
193 },
194 };
195
196 /* Receive only EFF frames when filter id and filter mask include EFF flag,
197 * ignoring RTR flag
198 */
FIXTURE_VARIANT_ADD(can_filters,filter_eff_effrtr)199 FIXTURE_VARIANT_ADD(can_filters, filter_eff_effrtr) {
200 .testcase = 8,
201 .id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
202 .mask = CAN_SFF_MASK | CAN_EFF_FLAG,
203 .exp_num_rx = 2,
204 .exp_flags = {
205 CAN_EFF_FLAG,
206 CAN_EFF_FLAG | CAN_RTR_FLAG,
207 },
208 };
209
210 /* Receive no remote frames when filtering for no RTR flag */
FIXTURE_VARIANT_ADD(can_filters,filter_rtr)211 FIXTURE_VARIANT_ADD(can_filters, filter_rtr) {
212 .testcase = 9,
213 .id = ID,
214 .mask = CAN_SFF_MASK | CAN_RTR_FLAG,
215 .exp_num_rx = 2,
216 .exp_flags = {
217 0,
218 CAN_EFF_FLAG,
219 },
220 };
221
222 /* Receive no remote frames when filtering for no RTR flag, ignoring EFF flag */
FIXTURE_VARIANT_ADD(can_filters,filter_rtr_eff)223 FIXTURE_VARIANT_ADD(can_filters, filter_rtr_eff) {
224 .testcase = 10,
225 .id = ID | CAN_EFF_FLAG,
226 .mask = CAN_SFF_MASK | CAN_RTR_FLAG,
227 .exp_num_rx = 2,
228 .exp_flags = {
229 0,
230 CAN_EFF_FLAG,
231 },
232 };
233
234 /* Receive only remote frames when filter includes RTR flag */
FIXTURE_VARIANT_ADD(can_filters,filter_rtr_rtr)235 FIXTURE_VARIANT_ADD(can_filters, filter_rtr_rtr) {
236 .testcase = 11,
237 .id = ID | CAN_RTR_FLAG,
238 .mask = CAN_SFF_MASK | CAN_RTR_FLAG,
239 .exp_num_rx = 2,
240 .exp_flags = {
241 CAN_RTR_FLAG,
242 CAN_EFF_FLAG | CAN_RTR_FLAG,
243 },
244 };
245
246 /* Receive only remote frames when filter includes RTR flag, ignoring EFF
247 * flag
248 */
FIXTURE_VARIANT_ADD(can_filters,filter_rtr_effrtr)249 FIXTURE_VARIANT_ADD(can_filters, filter_rtr_effrtr) {
250 .testcase = 12,
251 .id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
252 .mask = CAN_SFF_MASK | CAN_RTR_FLAG,
253 .exp_num_rx = 2,
254 .exp_flags = {
255 CAN_RTR_FLAG,
256 CAN_EFF_FLAG | CAN_RTR_FLAG,
257 },
258 };
259
260 /* Receive only SFF data frame when filtering for no flags */
FIXTURE_VARIANT_ADD(can_filters,filter_effrtr)261 FIXTURE_VARIANT_ADD(can_filters, filter_effrtr) {
262 .testcase = 13,
263 .id = ID,
264 .mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
265 .exp_num_rx = 1,
266 .exp_flags = {
267 0,
268 },
269 };
270
271 /* Receive only EFF data frame when filtering for EFF but no RTR flag */
FIXTURE_VARIANT_ADD(can_filters,filter_effrtr_eff)272 FIXTURE_VARIANT_ADD(can_filters, filter_effrtr_eff) {
273 .testcase = 14,
274 .id = ID | CAN_EFF_FLAG,
275 .mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
276 .exp_num_rx = 1,
277 .exp_flags = {
278 CAN_EFF_FLAG,
279 },
280 };
281
282 /* Receive only SFF remote frame when filtering for RTR but no EFF flag */
FIXTURE_VARIANT_ADD(can_filters,filter_effrtr_rtr)283 FIXTURE_VARIANT_ADD(can_filters, filter_effrtr_rtr) {
284 .testcase = 15,
285 .id = ID | CAN_RTR_FLAG,
286 .mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
287 .exp_num_rx = 1,
288 .exp_flags = {
289 CAN_RTR_FLAG,
290 },
291 };
292
293 /* Receive only EFF remote frame when filtering for EFF and RTR flag */
FIXTURE_VARIANT_ADD(can_filters,filter_effrtr_effrtr)294 FIXTURE_VARIANT_ADD(can_filters, filter_effrtr_effrtr) {
295 .testcase = 16,
296 .id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
297 .mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
298 .exp_num_rx = 1,
299 .exp_flags = {
300 CAN_EFF_FLAG | CAN_RTR_FLAG,
301 },
302 };
303
304 /* Receive only SFF data frame when filtering for no EFF flag and no RTR flag
305 * but based on EFF mask
306 */
FIXTURE_VARIANT_ADD(can_filters,eff)307 FIXTURE_VARIANT_ADD(can_filters, eff) {
308 .testcase = 17,
309 .id = ID,
310 .mask = CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
311 .exp_num_rx = 1,
312 .exp_flags = {
313 0,
314 },
315 };
316
317 /* Receive only EFF data frame when filtering for EFF flag and no RTR flag but
318 * based on EFF mask
319 */
FIXTURE_VARIANT_ADD(can_filters,eff_eff)320 FIXTURE_VARIANT_ADD(can_filters, eff_eff) {
321 .testcase = 18,
322 .id = ID | CAN_EFF_FLAG,
323 .mask = CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
324 .exp_num_rx = 1,
325 .exp_flags = {
326 CAN_EFF_FLAG,
327 },
328 };
329
330 /* This test verifies that the raw CAN filters work, by checking if only frames
331 * with the expected set of flags are received. For each test case, the given
332 * filter (id and mask) is added and four CAN frames are sent with every
333 * combination of set/unset EFF/RTR flags.
334 */
TEST_F(can_filters,test_filter)335 TEST_F(can_filters, test_filter)
336 {
337 struct can_filter rfilter;
338 int ret;
339
340 rfilter.can_id = variant->id;
341 rfilter.can_mask = variant->mask;
342 setsockopt(self->sock, SOL_CAN_RAW, CAN_RAW_FILTER,
343 &rfilter, sizeof(rfilter));
344
345 TH_LOG("filters: can_id = 0x%08X can_mask = 0x%08X",
346 rfilter.can_id, rfilter.can_mask);
347
348 ret = send_can_frames(self->sock, variant->testcase);
349 ASSERT_EQ(ret, 0)
350 TH_LOG("failed to send CAN frames");
351
352 for (int i = 0; i <= variant->exp_num_rx; i++) {
353 struct can_frame frame;
354 struct timeval tv = {
355 .tv_sec = 0,
356 .tv_usec = 50000, /* 50ms timeout */
357 };
358 fd_set rdfs;
359
360 FD_ZERO(&rdfs);
361 FD_SET(self->sock, &rdfs);
362
363 ret = select(self->sock + 1, &rdfs, NULL, NULL, &tv);
364 ASSERT_GE(ret, 0)
365 TH_LOG("failed select for frame %d, err: %d)", i, errno);
366
367 ret = FD_ISSET(self->sock, &rdfs);
368 if (i == variant->exp_num_rx) {
369 ASSERT_EQ(ret, 0)
370 TH_LOG("too many frames received");
371 } else {
372 ASSERT_NE(ret, 0)
373 TH_LOG("too few frames received");
374
375 ret = read(self->sock, &frame, sizeof(frame));
376 ASSERT_GE(ret, 0)
377 TH_LOG("failed to read frame %d, err: %d", i, errno);
378
379 TH_LOG("rx: can_id = 0x%08X rx = %d", frame.can_id, i);
380
381 ASSERT_EQ(ID, frame.can_id & CAN_SFF_MASK)
382 TH_LOG("received wrong can_id");
383 ASSERT_EQ(variant->testcase, frame.data[0])
384 TH_LOG("received wrong test case");
385
386 ASSERT_EQ(frame.can_id & ~CAN_ERR_MASK,
387 variant->exp_flags[i])
388 TH_LOG("received unexpected flags");
389 }
390 }
391 }
392
main(int argc,char ** argv)393 int main(int argc, char **argv)
394 {
395 char *ifname = getenv("CANIF");
396
397 if (!ifname) {
398 printf("CANIF environment variable must contain the test interface\n");
399 return KSFT_FAIL;
400 }
401
402 strncpy(CANIF, ifname, sizeof(CANIF) - 1);
403
404 return test_harness_run(argc, argv);
405 }
406