forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/tools/testing/selftests/net/udpgso_bench_rx.c
....@@ -31,9 +31,23 @@
3131 #include <sys/wait.h>
3232 #include <unistd.h>
3333
34
+#ifndef UDP_GRO
35
+#define UDP_GRO 104
36
+#endif
37
+
3438 static int cfg_port = 8000;
3539 static bool cfg_tcp;
3640 static bool cfg_verify;
41
+static bool cfg_read_all;
42
+static bool cfg_gro_segment;
43
+static int cfg_family = PF_INET6;
44
+static int cfg_alen = sizeof(struct sockaddr_in6);
45
+static int cfg_expected_pkt_nr;
46
+static int cfg_expected_pkt_len;
47
+static int cfg_expected_gso_size;
48
+static int cfg_connect_timeout_ms;
49
+static int cfg_rcv_timeout_ms;
50
+static struct sockaddr_storage cfg_bind_addr;
3751
3852 static bool interrupted;
3953 static unsigned long packets, bytes;
....@@ -44,6 +58,29 @@
4458 interrupted = true;
4559 }
4660
61
+static void setup_sockaddr(int domain, const char *str_addr, void *sockaddr)
62
+{
63
+ struct sockaddr_in6 *addr6 = (void *) sockaddr;
64
+ struct sockaddr_in *addr4 = (void *) sockaddr;
65
+
66
+ switch (domain) {
67
+ case PF_INET:
68
+ addr4->sin_family = AF_INET;
69
+ addr4->sin_port = htons(cfg_port);
70
+ if (inet_pton(AF_INET, str_addr, &(addr4->sin_addr)) != 1)
71
+ error(1, 0, "ipv4 parse error: %s", str_addr);
72
+ break;
73
+ case PF_INET6:
74
+ addr6->sin6_family = AF_INET6;
75
+ addr6->sin6_port = htons(cfg_port);
76
+ if (inet_pton(AF_INET6, str_addr, &(addr6->sin6_addr)) != 1)
77
+ error(1, 0, "ipv6 parse error: %s", str_addr);
78
+ break;
79
+ default:
80
+ error(1, 0, "illegal domain");
81
+ }
82
+}
83
+
4784 static unsigned long gettimeofday_ms(void)
4885 {
4986 struct timeval tv;
....@@ -52,7 +89,7 @@
5289 return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
5390 }
5491
55
-static void do_poll(int fd)
92
+static void do_poll(int fd, int timeout_ms)
5693 {
5794 struct pollfd pfd;
5895 int ret;
....@@ -63,22 +100,34 @@
63100
64101 do {
65102 ret = poll(&pfd, 1, 10);
103
+ if (interrupted)
104
+ break;
66105 if (ret == -1)
67106 error(1, errno, "poll");
68
- if (ret == 0)
107
+ if (ret == 0) {
108
+ if (!timeout_ms)
109
+ continue;
110
+
111
+ timeout_ms -= 10;
112
+ if (timeout_ms <= 0) {
113
+ interrupted = true;
114
+ break;
115
+ }
116
+
117
+ /* no events and more time to wait, do poll again */
69118 continue;
119
+ }
70120 if (pfd.revents != POLLIN)
71121 error(1, errno, "poll: 0x%x expected 0x%x\n",
72122 pfd.revents, POLLIN);
73
- } while (!ret && !interrupted);
123
+ } while (!ret);
74124 }
75125
76126 static int do_socket(bool do_tcp)
77127 {
78
- struct sockaddr_in6 addr = {0};
79128 int fd, val;
80129
81
- fd = socket(PF_INET6, cfg_tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
130
+ fd = socket(cfg_family, cfg_tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
82131 if (fd == -1)
83132 error(1, errno, "socket");
84133
....@@ -89,10 +138,7 @@
89138 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)))
90139 error(1, errno, "setsockopt reuseport");
91140
92
- addr.sin6_family = PF_INET6;
93
- addr.sin6_port = htons(cfg_port);
94
- addr.sin6_addr = in6addr_any;
95
- if (bind(fd, (void *) &addr, sizeof(addr)))
141
+ if (bind(fd, (void *)&cfg_bind_addr, cfg_alen))
96142 error(1, errno, "bind");
97143
98144 if (do_tcp) {
....@@ -101,7 +147,9 @@
101147 if (listen(accept_fd, 1))
102148 error(1, errno, "listen");
103149
104
- do_poll(accept_fd);
150
+ do_poll(accept_fd, cfg_connect_timeout_ms);
151
+ if (interrupted)
152
+ exit(0);
105153
106154 fd = accept(accept_fd, NULL, NULL);
107155 if (fd == -1)
....@@ -164,54 +212,137 @@
164212 }
165213 }
166214
215
+static int recv_msg(int fd, char *buf, int len, int *gso_size)
216
+{
217
+ char control[CMSG_SPACE(sizeof(int))] = {0};
218
+ struct msghdr msg = {0};
219
+ struct iovec iov = {0};
220
+ struct cmsghdr *cmsg;
221
+ int ret;
222
+
223
+ iov.iov_base = buf;
224
+ iov.iov_len = len;
225
+
226
+ msg.msg_iov = &iov;
227
+ msg.msg_iovlen = 1;
228
+
229
+ msg.msg_control = control;
230
+ msg.msg_controllen = sizeof(control);
231
+
232
+ *gso_size = -1;
233
+ ret = recvmsg(fd, &msg, MSG_TRUNC | MSG_DONTWAIT);
234
+ if (ret != -1) {
235
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
236
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
237
+ if (cmsg->cmsg_level == SOL_UDP
238
+ && cmsg->cmsg_type == UDP_GRO) {
239
+ *gso_size = *(int *)CMSG_DATA(cmsg);
240
+ break;
241
+ }
242
+ }
243
+ }
244
+ return ret;
245
+}
246
+
167247 /* Flush all outstanding datagrams. Verify first few bytes of each. */
168248 static void do_flush_udp(int fd)
169249 {
170
- static char rbuf[ETH_DATA_LEN];
171
- int ret, len, budget = 256;
250
+ static char rbuf[ETH_MAX_MTU];
251
+ int ret, len, gso_size = 0, budget = 256;
172252
173
- len = cfg_verify ? sizeof(rbuf) : 0;
253
+ len = cfg_read_all ? sizeof(rbuf) : 0;
174254 while (budget--) {
175255 /* MSG_TRUNC will make return value full datagram length */
176
- ret = recv(fd, rbuf, len, MSG_TRUNC | MSG_DONTWAIT);
256
+ if (!cfg_expected_gso_size)
257
+ ret = recv(fd, rbuf, len, MSG_TRUNC | MSG_DONTWAIT);
258
+ else
259
+ ret = recv_msg(fd, rbuf, len, &gso_size);
177260 if (ret == -1 && errno == EAGAIN)
178
- return;
261
+ break;
179262 if (ret == -1)
180263 error(1, errno, "recv");
181
- if (len) {
264
+ if (cfg_expected_pkt_len && ret != cfg_expected_pkt_len)
265
+ error(1, 0, "recv: bad packet len, got %d,"
266
+ " expected %d\n", ret, cfg_expected_pkt_len);
267
+ if (len && cfg_verify) {
182268 if (ret == 0)
183269 error(1, errno, "recv: 0 byte datagram\n");
184270
185271 do_verify_udp(rbuf, ret);
186272 }
273
+ if (cfg_expected_gso_size && cfg_expected_gso_size != gso_size)
274
+ error(1, 0, "recv: bad gso size, got %d, expected %d "
275
+ "(-1 == no gso cmsg))\n", gso_size,
276
+ cfg_expected_gso_size);
187277
188278 packets++;
189279 bytes += ret;
280
+ if (cfg_expected_pkt_nr && packets >= cfg_expected_pkt_nr)
281
+ break;
190282 }
191283 }
192284
193285 static void usage(const char *filepath)
194286 {
195
- error(1, 0, "Usage: %s [-tv] [-p port]", filepath);
287
+ error(1, 0, "Usage: %s [-C connect_timeout] [-Grtv] [-b addr] [-p port]"
288
+ " [-l pktlen] [-n packetnr] [-R rcv_timeout] [-S gsosize]",
289
+ filepath);
196290 }
197291
198292 static void parse_opts(int argc, char **argv)
199293 {
294
+ const char *bind_addr = NULL;
200295 int c;
201296
202
- while ((c = getopt(argc, argv, "ptv")) != -1) {
297
+ while ((c = getopt(argc, argv, "4b:C:Gl:n:p:rR:S:tv")) != -1) {
203298 switch (c) {
299
+ case '4':
300
+ cfg_family = PF_INET;
301
+ cfg_alen = sizeof(struct sockaddr_in);
302
+ break;
303
+ case 'b':
304
+ bind_addr = optarg;
305
+ break;
306
+ case 'C':
307
+ cfg_connect_timeout_ms = strtoul(optarg, NULL, 0);
308
+ break;
309
+ case 'G':
310
+ cfg_gro_segment = true;
311
+ break;
312
+ case 'l':
313
+ cfg_expected_pkt_len = strtoul(optarg, NULL, 0);
314
+ break;
315
+ case 'n':
316
+ cfg_expected_pkt_nr = strtoul(optarg, NULL, 0);
317
+ break;
204318 case 'p':
205
- cfg_port = htons(strtoul(optarg, NULL, 0));
319
+ cfg_port = strtoul(optarg, NULL, 0);
320
+ break;
321
+ case 'r':
322
+ cfg_read_all = true;
323
+ break;
324
+ case 'R':
325
+ cfg_rcv_timeout_ms = strtoul(optarg, NULL, 0);
326
+ break;
327
+ case 'S':
328
+ cfg_expected_gso_size = strtol(optarg, NULL, 0);
206329 break;
207330 case 't':
208331 cfg_tcp = true;
209332 break;
210333 case 'v':
211334 cfg_verify = true;
335
+ cfg_read_all = true;
212336 break;
337
+ default:
338
+ exit(1);
213339 }
214340 }
341
+
342
+ if (!bind_addr)
343
+ bind_addr = cfg_family == PF_INET6 ? "::" : "0.0.0.0";
344
+
345
+ setup_sockaddr(cfg_family, bind_addr, &cfg_bind_addr);
215346
216347 if (optind != argc)
217348 usage(argv[0]);
....@@ -222,14 +353,21 @@
222353
223354 static void do_recv(void)
224355 {
356
+ int timeout_ms = cfg_tcp ? cfg_rcv_timeout_ms : cfg_connect_timeout_ms;
225357 unsigned long tnow, treport;
226358 int fd;
227359
228360 fd = do_socket(cfg_tcp);
229361
362
+ if (cfg_gro_segment && !cfg_tcp) {
363
+ int val = 1;
364
+ if (setsockopt(fd, IPPROTO_UDP, UDP_GRO, &val, sizeof(val)))
365
+ error(1, errno, "setsockopt UDP_GRO");
366
+ }
367
+
230368 treport = gettimeofday_ms() + 1000;
231369 do {
232
- do_poll(fd);
370
+ do_poll(fd, timeout_ms);
233371
234372 if (cfg_tcp)
235373 do_flush_tcp(fd);
....@@ -247,8 +385,14 @@
247385 treport = tnow + 1000;
248386 }
249387
388
+ timeout_ms = cfg_rcv_timeout_ms;
389
+
250390 } while (!interrupted);
251391
392
+ if (cfg_expected_pkt_nr && (packets != cfg_expected_pkt_nr))
393
+ error(1, 0, "wrong packet number! got %ld, expected %d\n",
394
+ packets, cfg_expected_pkt_nr);
395
+
252396 if (close(fd))
253397 error(1, errno, "close");
254398 }