xref: /aosp_15_r20/external/ltp/testcases/network/can/filter-tests/can_filter.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 /*
3  * Copyright (c) 2011 Volkswagen Group Electronic Research
4  * Copyright (c) 2021 SUSE LLC
5  */
6 
7 #include "config.h"
8 #include "tst_test.h"
9 
10 #ifdef HAVE_LINUX_CAN_H
11 
12 #include "can_common.h"
13 
14 #define ID 0x123
15 #define TC 18			/* # of testcases */
16 
17 const int rx_res[TC] = { 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 };
18 const int rxbits_res[TC] = { 4369, 4369, 4369, 4369, 17, 4352, 17, 4352, 257,
19 			     257, 4112, 4112, 1, 256, 16, 4096, 1, 256 };
20 
21 static int s;
22 
calc_id(int testcase)23 static canid_t calc_id(int testcase)
24 {
25 	canid_t id = ID;
26 
27 	if (testcase & 1)
28 		id |= CAN_EFF_FLAG;
29 	if (testcase & 2)
30 		id |= CAN_RTR_FLAG;
31 
32 	return id;
33 }
34 
calc_mask(int testcase)35 static canid_t calc_mask(int testcase)
36 {
37 	canid_t mask = CAN_SFF_MASK;
38 
39 	if (testcase > 15)
40 		return CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG;
41 
42 	if (testcase & 4)
43 		mask |= CAN_EFF_FLAG;
44 	if (testcase & 8)
45 		mask |= CAN_RTR_FLAG;
46 
47 	return mask;
48 }
49 
setup(void)50 static void setup(void)
51 {
52 	struct sockaddr_can addr;
53 	struct ifreq ifr;
54 	int recv_own_msgs = 1;
55 
56 	can_setup_vcan();
57 
58 	s = SAFE_SOCKET(PF_CAN, SOCK_RAW, CAN_RAW);
59 
60 	strcpy(ifr.ifr_name, can_dev_name);
61 	SAFE_IOCTL(s, SIOCGIFINDEX, &ifr);
62 
63 	addr.can_family = AF_CAN;
64 	addr.can_ifindex = ifr.ifr_ifindex;
65 
66 	SAFE_SETSOCKOPT(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
67 			&recv_own_msgs, sizeof(recv_own_msgs));
68 
69 	SAFE_BIND(s, (struct sockaddr *)&addr, sizeof(addr));
70 }
71 
cleanup(void)72 static void cleanup(void)
73 {
74 	if (s)
75 		SAFE_CLOSE(s);
76 
77 	can_cleanup_vcan();
78 }
79 
run(unsigned int n)80 static void run(unsigned int n)
81 {
82 	fd_set rdfs;
83 	struct timeval tv;
84 	struct can_frame frame;
85 	static struct can_filter rfilter;
86 	int testcase = n;
87 	int have_rx = 1;
88 	int rx = 0;
89 	int rxbits = 0, rxbitval;
90 
91 	rfilter.can_id = calc_id(testcase);
92 	rfilter.can_mask = calc_mask(testcase);
93 	SAFE_SETSOCKOPT(s, SOL_CAN_RAW, CAN_RAW_FILTER,
94 			&rfilter, sizeof(rfilter));
95 
96 	tst_res(TINFO, "testcase %2d filters : can_id = 0x%08X can_mask = "
97 	       "0x%08X", testcase, rfilter.can_id, rfilter.can_mask);
98 
99 	tst_res(TINFO, "testcase %2d sending patterns ... ", testcase);
100 
101 	frame.can_dlc = 1;
102 	frame.data[0] = testcase;
103 
104 	frame.can_id = ID;
105 	SAFE_WRITE(SAFE_WRITE_ALL, s, &frame, sizeof(frame));
106 
107 	frame.can_id = (ID | CAN_RTR_FLAG);
108 	SAFE_WRITE(SAFE_WRITE_ALL, s, &frame, sizeof(frame));
109 
110 	frame.can_id = (ID | CAN_EFF_FLAG);
111 	SAFE_WRITE(SAFE_WRITE_ALL, s, &frame, sizeof(frame));
112 
113 	frame.can_id = (ID | CAN_EFF_FLAG | CAN_RTR_FLAG);
114 	SAFE_WRITE(SAFE_WRITE_ALL, s, &frame, sizeof(frame));
115 
116 	tst_res(TPASS, "testcase %2d Sent patterns", testcase);
117 
118 	while (have_rx) {
119 
120 		have_rx = 0;
121 		FD_ZERO(&rdfs);
122 		FD_SET(s, &rdfs);
123 		tv.tv_sec = 0;
124 		tv.tv_usec = 50000;	/* 50ms timeout */
125 
126 		if (select(s + 1, &rdfs, NULL, NULL, &tv) < 0)
127 			tst_brk(TBROK | TERRNO, "select");
128 
129 		if (FD_ISSET(s, &rdfs)) {
130 			have_rx = 1;
131 			SAFE_READ(1, s, &frame, sizeof(struct can_frame));
132 
133 			if ((frame.can_id & CAN_SFF_MASK) != ID)
134 				tst_res(TFAIL, "received wrong can_id!");
135 
136 			if (frame.data[0] != testcase)
137 				tst_res(TFAIL, "received wrong testcase!");
138 
139 			/* test & calc rxbits */
140 			rxbitval = 1 << ((frame.can_id &
141 					  (CAN_EFF_FLAG | CAN_RTR_FLAG |
142 					   CAN_ERR_FLAG)) >> 28);
143 
144 			/* only receive a rxbitval once */
145 			if ((rxbits & rxbitval) == rxbitval) {
146 				tst_res(TFAIL, "received rxbitval %d twice!",
147 					rxbitval);
148 			}
149 			rxbits |= rxbitval;
150 			rx++;
151 
152 			tst_res(TINFO, "testcase %2d rx : can_id = 0x%08X rx = "
153 			       "%d rxbits = %d", testcase,
154 			       frame.can_id, rx, rxbits);
155 		}
156 	}
157 	/* rx timed out -> check the received results */
158 	if (rx_res[testcase] != rx) {
159 		tst_brk(TBROK,
160 			"wrong rx value in testcase %d : %d (expected "
161 			"%d)", testcase, rx, rx_res[testcase]);
162 	}
163 	if (rxbits_res[testcase] != rxbits) {
164 		tst_brk(TBROK,
165 			"wrong rxbits value in testcase %d : %d "
166 			"(expected %d)", testcase, rxbits,
167 			rxbits_res[testcase]);
168 	}
169 	tst_res(TPASS, "testcase %2d ok", testcase);
170 }
171 
172 static struct tst_test test = {
173 	.tcnt = TC,
174 	.options = (struct tst_option[]) {
175 		{"d:", &can_dev_name, "CAN device name"},
176 		{}
177 	},
178 	.setup = setup,
179 	.cleanup = cleanup,
180 	.test = run,
181 	.caps = (struct tst_cap []) {
182 		TST_CAP(TST_CAP_REQ, CAP_NET_RAW),
183 		TST_CAP(TST_CAP_DROP, CAP_SYS_ADMIN),
184 		{}
185 	},
186 	.needs_drivers = (const char *const[]) {
187 		"vcan",
188 		"can-raw",
189 		NULL
190 	}
191 };
192 
193 #else
194 
195 TST_TEST_TCONF("The linux/can.h was missing upon compilation");
196 
197 #endif /* HAVE_LINUX_CAN_H */
198