• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "tst_minmax.h"
14 
15 static int s, t;
16 
test_sockets(canid_t can_id,int expect_rxs,int expect_rxt)17 static void test_sockets(canid_t can_id, int expect_rxs, int expect_rxt)
18 {
19 	fd_set rdfs;
20 	struct timeval tv;
21 	int m = MAX(s, t) + 1;
22 	int have_rx = 1;
23 	struct can_frame frame;
24 	int rxs = 0, rxt = 0;
25 
26 	frame.can_id = can_id;
27 	frame.can_dlc = 0;
28 	SAFE_WRITE(SAFE_WRITE_ALL, s, &frame, sizeof(frame));
29 
30 	while (have_rx) {
31 
32 		FD_ZERO(&rdfs);
33 		FD_SET(s, &rdfs);
34 		FD_SET(t, &rdfs);
35 		tv.tv_sec = 0;
36 		tv.tv_usec = 50000;	/* 50ms timeout */
37 		have_rx = 0;
38 
39 		if (select(m, &rdfs, NULL, NULL, &tv) < 0)
40 			tst_brk(TBROK | TERRNO, "select");
41 
42 		if (FD_ISSET(s, &rdfs)) {
43 
44 			have_rx = 1;
45 			SAFE_READ(1, s, &frame, sizeof(struct can_frame));
46 
47 			if (frame.can_id != can_id)
48 				tst_res(TFAIL, "received wrong can_id!");
49 
50 			rxs++;
51 		}
52 
53 		if (FD_ISSET(t, &rdfs)) {
54 
55 			have_rx = 1;
56 			SAFE_READ(1, t, &frame, sizeof(struct can_frame));
57 
58 			if (frame.can_id != can_id)
59 				tst_res(TFAIL, "received wrong can_id!");
60 
61 			rxt++;
62 		}
63 	}
64 
65 	/* timeout */
66 
67 	tst_res(rxs == expect_rxs && rxt == expect_rxt ? TPASS : TFAIL,
68 		"s received %d of %d, t received %d of %d",
69 		rxs, expect_rxs, rxt, expect_rxt);
70 }
71 
setopts(int loopback,int recv_own_msgs)72 static void setopts(int loopback, int recv_own_msgs)
73 {
74 	SAFE_SETSOCKOPT(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback,
75 			sizeof(loopback));
76 	SAFE_SETSOCKOPT(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs,
77 			sizeof(recv_own_msgs));
78 
79 	tst_res(TINFO, "set loopback = %d, recv_own_msgs = %d",
80 		loopback, recv_own_msgs);
81 }
82 
setup(void)83 static void setup(void)
84 {
85 	struct sockaddr_can addr;
86 	struct ifreq ifr;
87 
88 	can_setup_vcan();
89 
90 	s = SAFE_SOCKET(PF_CAN, SOCK_RAW, CAN_RAW);
91 	t = SAFE_SOCKET(PF_CAN, SOCK_RAW, CAN_RAW);
92 
93 	strcpy(ifr.ifr_name, can_dev_name);
94 	SAFE_IOCTL(s, SIOCGIFINDEX, &ifr);
95 
96 	addr.can_ifindex = ifr.ifr_ifindex;
97 	addr.can_family = AF_CAN;
98 
99 	SAFE_BIND(s, (struct sockaddr *)&addr, sizeof(addr));
100 	SAFE_BIND(t, (struct sockaddr *)&addr, sizeof(addr));
101 }
102 
cleanup(void)103 static void cleanup(void)
104 {
105 	if (s)
106 		SAFE_CLOSE(s);
107 	if (t)
108 		SAFE_CLOSE(t);
109 
110 	can_cleanup_vcan();
111 }
112 
run(void)113 static void run(void)
114 {
115 	tst_res(TINFO, "Starting PF_CAN frame flow test.");
116 	tst_res(TINFO, "checking socket default settings");
117 	test_sockets(0x340, 0, 1);
118 
119 	setopts(0, 0);
120 	test_sockets(0x341, 0, 0);
121 
122 	setopts(0, 1);
123 	test_sockets(0x342, 0, 0);
124 
125 	setopts(1, 0);
126 	test_sockets(0x343, 0, 1);
127 
128 	setopts(1, 1);
129 	test_sockets(0x344, 1, 1);
130 
131 	/* Return to defaults for when -i is used */
132 	setopts(1, 0);
133 }
134 
135 static struct tst_test test = {
136 	.options = (struct tst_option[]) {
137 		{"D:", &can_dev_name, "CAN device name"},
138 		{}
139 	},
140 	.setup = setup,
141 	.cleanup = cleanup,
142 	.test_all = run,
143 	.caps = (struct tst_cap []) {
144 		TST_CAP(TST_CAP_REQ, CAP_NET_RAW),
145 		TST_CAP(TST_CAP_DROP, CAP_SYS_ADMIN),
146 		{}
147 	},
148 	.needs_drivers = (const char *const[]) {
149 		"vcan",
150 		"can-raw",
151 		NULL
152 	}
153 };
154 
155 #else
156 
157 TST_TEST_TCONF("The linux/can.h was missing upon compilation");
158 
159 #endif /* HAVE_LINUX_CAN_H */
160