forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
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(uint16_t))] = {0};
218
+ struct msghdr msg = {0};
219
+ struct iovec iov = {0};
220
+ struct cmsghdr *cmsg;
221
+ uint16_t *gsosizeptr;
222
+ int ret;
223
+
224
+ iov.iov_base = buf;
225
+ iov.iov_len = len;
226
+
227
+ msg.msg_iov = &iov;
228
+ msg.msg_iovlen = 1;
229
+
230
+ msg.msg_control = control;
231
+ msg.msg_controllen = sizeof(control);
232
+
233
+ *gso_size = -1;
234
+ ret = recvmsg(fd, &msg, MSG_TRUNC | MSG_DONTWAIT);
235
+ if (ret != -1) {
236
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
237
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
238
+ if (cmsg->cmsg_level == SOL_UDP
239
+ && cmsg->cmsg_type == UDP_GRO) {
240
+ gsosizeptr = (uint16_t *) CMSG_DATA(cmsg);
241
+ *gso_size = *gsosizeptr;
242
+ break;
243
+ }
244
+ }
245
+ }
246
+ return ret;
247
+}
248
+
167249 /* Flush all outstanding datagrams. Verify first few bytes of each. */
168250 static void do_flush_udp(int fd)
169251 {
170
- static char rbuf[ETH_DATA_LEN];
171
- int ret, len, budget = 256;
252
+ static char rbuf[ETH_MAX_MTU];
253
+ int ret, len, gso_size, budget = 256;
172254
173
- len = cfg_verify ? sizeof(rbuf) : 0;
255
+ len = cfg_read_all ? sizeof(rbuf) : 0;
174256 while (budget--) {
175257 /* MSG_TRUNC will make return value full datagram length */
176
- ret = recv(fd, rbuf, len, MSG_TRUNC | MSG_DONTWAIT);
258
+ if (!cfg_expected_gso_size)
259
+ ret = recv(fd, rbuf, len, MSG_TRUNC | MSG_DONTWAIT);
260
+ else
261
+ ret = recv_msg(fd, rbuf, len, &gso_size);
177262 if (ret == -1 && errno == EAGAIN)
178
- return;
263
+ break;
179264 if (ret == -1)
180265 error(1, errno, "recv");
181
- if (len) {
266
+ if (cfg_expected_pkt_len && ret != cfg_expected_pkt_len)
267
+ error(1, 0, "recv: bad packet len, got %d,"
268
+ " expected %d\n", ret, cfg_expected_pkt_len);
269
+ if (len && cfg_verify) {
182270 if (ret == 0)
183271 error(1, errno, "recv: 0 byte datagram\n");
184272
185273 do_verify_udp(rbuf, ret);
186274 }
275
+ if (cfg_expected_gso_size && cfg_expected_gso_size != gso_size)
276
+ error(1, 0, "recv: bad gso size, got %d, expected %d "
277
+ "(-1 == no gso cmsg))\n", gso_size,
278
+ cfg_expected_gso_size);
187279
188280 packets++;
189281 bytes += ret;
282
+ if (cfg_expected_pkt_nr && packets >= cfg_expected_pkt_nr)
283
+ break;
190284 }
191285 }
192286
193287 static void usage(const char *filepath)
194288 {
195
- error(1, 0, "Usage: %s [-tv] [-p port]", filepath);
289
+ error(1, 0, "Usage: %s [-C connect_timeout] [-Grtv] [-b addr] [-p port]"
290
+ " [-l pktlen] [-n packetnr] [-R rcv_timeout] [-S gsosize]",
291
+ filepath);
196292 }
197293
198294 static void parse_opts(int argc, char **argv)
199295 {
296
+ const char *bind_addr = NULL;
200297 int c;
201298
202
- while ((c = getopt(argc, argv, "ptv")) != -1) {
299
+ while ((c = getopt(argc, argv, "4b:C:Gl:n:p:rR:S:tv")) != -1) {
203300 switch (c) {
301
+ case '4':
302
+ cfg_family = PF_INET;
303
+ cfg_alen = sizeof(struct sockaddr_in);
304
+ break;
305
+ case 'b':
306
+ bind_addr = optarg;
307
+ break;
308
+ case 'C':
309
+ cfg_connect_timeout_ms = strtoul(optarg, NULL, 0);
310
+ break;
311
+ case 'G':
312
+ cfg_gro_segment = true;
313
+ break;
314
+ case 'l':
315
+ cfg_expected_pkt_len = strtoul(optarg, NULL, 0);
316
+ break;
317
+ case 'n':
318
+ cfg_expected_pkt_nr = strtoul(optarg, NULL, 0);
319
+ break;
204320 case 'p':
205
- cfg_port = htons(strtoul(optarg, NULL, 0));
321
+ cfg_port = strtoul(optarg, NULL, 0);
322
+ break;
323
+ case 'r':
324
+ cfg_read_all = true;
325
+ break;
326
+ case 'R':
327
+ cfg_rcv_timeout_ms = strtoul(optarg, NULL, 0);
328
+ break;
329
+ case 'S':
330
+ cfg_expected_gso_size = strtol(optarg, NULL, 0);
206331 break;
207332 case 't':
208333 cfg_tcp = true;
209334 break;
210335 case 'v':
211336 cfg_verify = true;
337
+ cfg_read_all = true;
212338 break;
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 }