1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2020-2023. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <netdb.h>
17 #include <netinet/in.h>
18 #include <sys/socket.h>
19 #include <arpa/inet.h>
20 #include <unistd.h>
21 #include <pthread.h>
22 #include "util.h"
23
24 constexpr int PORT = 1500; // port
25 constexpr int PIPE_FD_COUNT = 2;
26 constexpr int BUFFER_SIZE = 100;
27 constexpr int MSG_COUNT = 10;
28
Bm_function_socket_server(benchmark::State & state)29 static void Bm_function_socket_server(benchmark::State &state)
30 {
31 struct sockaddr_in serverAddr;
32 memset(&serverAddr, 0, sizeof(serverAddr));
33 serverAddr.sin_family = AF_INET;
34 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Any IP address of this host
35 serverAddr.sin_port = htons(PORT);
36 int eight = 8;
37 bzero(&(serverAddr.sin_zero), eight); // Set other attributes to 0
38 for (auto _ : state) {
39 int serverFd = socket(AF_INET, SOCK_STREAM, 0);
40 if (serverFd == -1) {
41 printf("socket failed:%d", errno);
42 break;
43 }
44 close(serverFd);
45 }
46 state.SetBytesProcessed(state.iterations());
47 }
48
Bm_function_socketpair_sendmsg_recvmsg(benchmark::State & state)49 static void Bm_function_socketpair_sendmsg_recvmsg(benchmark::State &state)
50 {
51 int ret;
52 int socks[2];
53 struct msghdr msg;
54 struct iovec iov[1];
55 char sendBuf[BUFFER_SIZE] = "it is a test";
56 struct msghdr msgr;
57 struct iovec iovr[1];
58 char recvBuf[BUFFER_SIZE];
59
60 for (auto _ : state) {
61 ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, socks);
62 if (ret == -1) {
63 printf("socketpair sendmsg err\n");
64 break;
65 }
66
67 bzero(&msg, sizeof(msg));
68 msg.msg_name = nullptr;
69 msg.msg_namelen = 0;
70 iov[0].iov_base = sendBuf;
71 iov[0].iov_len = sizeof(sendBuf);
72 msg.msg_iov = iov;
73 msg.msg_iovlen = 1;
74
75 ret = sendmsg(socks[1], &msg, 0);
76 if (ret == -1) {
77 printf("sendmsg err\n");
78 close(socks[0]);
79 close(socks[1]);
80 break;
81 }
82
83 bzero(&msgr, sizeof(msgr));
84 msgr.msg_name = nullptr;
85 msgr.msg_namelen = 0;
86 iovr[0].iov_base = &recvBuf;
87 iovr[0].iov_len = sizeof(recvBuf);
88 msgr.msg_iov = iovr;
89 msgr.msg_iovlen = 1;
90 ret = recvmsg(socks[0], &msgr, 0);
91 if (ret == -1) {
92 printf("recvmsg err\n");
93 }
94 close(socks[0]);
95 close(socks[1]);
96 }
97 state.SetBytesProcessed(state.iterations());
98 }
99
Bm_function_socketpair_sendmmsg_recvmmsg(benchmark::State & state)100 static void Bm_function_socketpair_sendmmsg_recvmmsg(benchmark::State &state)
101 {
102 int ret;
103 int socks[2];
104 struct mmsghdr msgs[MSG_COUNT];
105 struct iovec iovs[MSG_COUNT][1];
106 char sendBuf[BUFFER_SIZE] = "it is a test";
107 struct mmsghdr msgsr[MSG_COUNT];
108 struct iovec iovsr[MSG_COUNT][1];
109 char recvBuf[BUFFER_SIZE];
110
111 for (auto _ : state) {
112 ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, socks);
113 if (ret == -1) {
114 printf("socketpair sendmsg err\n");
115 break;
116 }
117
118 for (int i = 0; i < MSG_COUNT; i++) {
119 bzero(&msgs[i], sizeof(msgs[i]));
120 msgs[i].msg_hdr.msg_name = nullptr;
121 msgs[i].msg_hdr.msg_namelen = 0;
122 iovs[i][0].iov_base = sendBuf;
123 iovs[i][0].iov_len = sizeof(sendBuf);
124 msgs[i].msg_hdr.msg_iov = iovs[i];
125 msgs[i].msg_hdr.msg_iovlen = 1;
126 }
127
128 ret = sendmmsg(socks[1], msgs, MSG_COUNT, 0);
129 if (ret == -1) {
130 printf("sendmmsg err\n");
131 close(socks[0]);
132 close(socks[1]);
133 break;
134 }
135
136 for (int i = 0; i < MSG_COUNT; i++) {
137 bzero(&msgsr[i], sizeof(msgsr[i]));
138 msgsr[i].msg_hdr.msg_name = nullptr;
139 msgsr[i].msg_hdr.msg_namelen = 0;
140 iovsr[i][0].iov_base = &recvBuf;
141 iovsr[i][0].iov_len = sizeof(recvBuf);
142 msgsr[i].msg_hdr.msg_iov = iovsr[i];
143 msgsr[i].msg_hdr.msg_iovlen = 1;
144 }
145 ret = recvmmsg(socks[0], msgsr, MSG_COUNT, 0, nullptr);
146 if (ret == -1) {
147 printf("recvmmsg err\n");
148 }
149 close(socks[0]);
150 close(socks[1]);
151 }
152 state.SetBytesProcessed(state.iterations());
153 }
154
Bm_function_socketpair_sendto_recvfrom(benchmark::State & state)155 static void Bm_function_socketpair_sendto_recvfrom(benchmark::State &state)
156 {
157 int ret;
158 int socks[2];
159 char sendBuf[BUFFER_SIZE] = "it is a test";
160 char recvBuf[BUFFER_SIZE];
161
162 for (auto _ : state) {
163 ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, socks);
164 if (ret == -1) {
165 printf("socketpair sendto err\n");
166 break;
167 }
168
169 ret = sendto(socks[1], sendBuf, sizeof(sendBuf), 0, nullptr, 0);
170 if (ret == -1) {
171 printf("sendto err\n");
172 close(socks[0]);
173 close(socks[1]);
174 break;
175 }
176
177 ret = recvfrom(socks[0], recvBuf, sizeof(recvBuf), 0, nullptr, 0);
178 if (ret == -1) {
179 printf("recvfrom err\n");
180 }
181 close(socks[0]);
182 close(socks[1]);
183 }
184 state.SetBytesProcessed(state.iterations());
185 }
186
Bm_function_getsockopt(benchmark::State & state)187 static void Bm_function_getsockopt(benchmark::State &state)
188 {
189 int optVal;
190 socklen_t optLen = sizeof(optVal);
191
192 for (auto _ : state) {
193 int sockFd = socket(AF_INET, SOCK_STREAM, 0);
194 if (getsockopt(sockFd, SOL_SOCKET, SO_SNDBUF, &optVal, &optLen) < 0) {
195 printf("fail to getsockopt");
196 }
197 close(sockFd);
198 }
199 state.SetBytesProcessed(state.iterations());
200 }
201
Bm_function_setsockopt(benchmark::State & state)202 static void Bm_function_setsockopt(benchmark::State &state)
203 {
204 for (auto _ : state) {
205 int nRecvBuf = 32*1024; // Set to 32K
206 int sockFd = socket(AF_INET, SOCK_STREAM, 0);
207 if (setsockopt(sockFd, SOL_SOCKET, SO_RCVBUF, (const char*)&nRecvBuf, sizeof(int)) < 0) {
208 printf("fail to setsockopt");
209 }
210 close(sockFd);
211 }
212 state.SetBytesProcessed(state.iterations());
213 }
214
Bm_function_sockpair(benchmark::State & state)215 static void Bm_function_sockpair(benchmark::State &state)
216 {
217 for (auto _ : state) {
218 int fd[PIPE_FD_COUNT] = {-1, -1};
219 benchmark::DoNotOptimize(socketpair(0, SOCK_STREAM, 0, fd));
220 state.PauseTiming();
221 for (size_t i = 0; i < PIPE_FD_COUNT; i++) {
222 if (fd[i] >= 0) {
223 close(fd[i]);
224 }
225 }
226 state.ResumeTiming();
227 }
228 }
229
Bm_function_pipe(benchmark::State & state)230 static void Bm_function_pipe(benchmark::State &state)
231 {
232 for (auto _ : state) {
233 int fd[PIPE_FD_COUNT] = {-1, -1};
234 benchmark::DoNotOptimize(pipe(fd));
235 state.PauseTiming();
236 for (size_t i = 0; i < PIPE_FD_COUNT; i++) {
237 if (fd[i] >= 0) {
238 close(fd[i]);
239 }
240 }
241 state.ResumeTiming();
242 }
243 }
244
ConnectTo(const char * host,const char * port,int socktype,struct addrinfo * addr)245 static int ConnectTo(const char *host, const char *port, int socktype, struct addrinfo *addr)
246 {
247 struct addrinfo hint;
248 struct addrinfo *res;
249 bzero(&hint, sizeof(struct addrinfo));
250 hint.ai_flags = 0;
251 hint.ai_family = AF_UNSPEC;
252 hint.ai_protocol = 0;
253 hint.ai_socktype = socktype;
254
255 int n = getaddrinfo(host, port, &hint, &res);
256 if (n != 0) {
257 perror("getaddrinfo");
258 return -1;
259 }
260
261 int sfd = -1;
262 for (struct addrinfo *rp = res; rp != nullptr; rp = rp->ai_next) {
263 sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
264 if (sfd == -1) {
265 continue;
266 }
267
268 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) {
269 if (addr != nullptr) {
270 struct sockaddr *aiAddr = addr->ai_addr;
271 *addr = *rp;
272 *aiAddr = *rp->ai_addr;
273 addr->ai_addr = aiAddr;
274 }
275 break;
276 }
277
278 close(sfd);
279 sfd = -1;
280 }
281
282 freeaddrinfo(res);
283
284 if (sfd == -1) {
285 perror("connect");
286 }
287
288 return sfd;
289 }
290
BindAt(const char * port)291 static int BindAt(const char *port)
292 {
293 struct addrinfo hint;
294 struct addrinfo *res;
295 bzero(&hint, sizeof(struct addrinfo));
296 hint.ai_flags = AI_PASSIVE;
297 hint.ai_family = AF_UNSPEC;
298 hint.ai_protocol = 0;
299 hint.ai_socktype = SOCK_STREAM;
300
301 int n = getaddrinfo("127.0.0.1", port, &hint, &res);
302 if (n != 0) {
303 perror("getaddrinfo");
304 return -1;
305 }
306
307 int sfd = -1;
308 for (struct addrinfo *rp = res; rp != nullptr; rp = rp->ai_next) {
309 sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
310 if (sfd == -1) {
311 continue;
312 }
313
314 int reuse = 1;
315 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
316 close(sfd);
317 continue;
318 }
319
320 if (bind(sfd, rp->ai_addr, rp->ai_addrlen) != -1) {
321 break;
322 }
323
324 close(sfd);
325 sfd = -1;
326 }
327
328 freeaddrinfo(res);
329
330 if (sfd == -1) {
331 perror("bind");
332 }
333
334 return sfd;
335 }
336
Bm_function_getpeername_client_local(benchmark::State & state)337 static void Bm_function_getpeername_client_local(benchmark::State &state)
338 {
339 int sfd = ConnectTo("127.0.0.1", "80", SOCK_DGRAM, nullptr);
340 if (sfd == -1) {
341 }
342
343 struct sockaddr_in peerAddr;
344 socklen_t peerLen = sizeof(peerAddr);
345 for (auto _ : state) {
346 if (getpeername(sfd, (struct sockaddr *)&peerAddr, &peerLen) == -1) {
347 perror("getpeername");
348 printf("peer addr: %s:%d\n", inet_ntoa(peerAddr.sin_addr), ntohs(peerAddr.sin_port));
349 }
350 }
351
352 close(sfd);
353 }
354
Bm_function_getpeername_client_external(benchmark::State & state)355 static void Bm_function_getpeername_client_external(benchmark::State &state)
356 {
357 int sfd = ConnectTo("www.baidu.com", "80", SOCK_DGRAM, nullptr);
358 if (sfd == -1) {
359 }
360
361 struct sockaddr_in peerAddr;
362 socklen_t peerLen = sizeof(peerAddr);
363 for (auto _ : state) {
364 if (getpeername(sfd, (struct sockaddr *)&peerAddr, &peerLen) == -1) {
365 perror("getpeername");
366 printf("peer addr: %s:%d\n", inet_ntoa(peerAddr.sin_addr), ntohs(peerAddr.sin_port));
367 }
368 }
369
370 close(sfd);
371 }
372
ThreadTaskClient(void * arg)373 void* ThreadTaskClient(void* arg)
374 {
375 int sfd = ConnectTo("127.0.0.1", "1500", SOCK_STREAM, nullptr);
376 if (sfd == -1) {
377 return (void*)-1;
378 }
379
380 close(sfd);
381 return nullptr;
382 }
383
StartServer(int * connfd)384 static int StartServer(int *connfd)
385 {
386 int sfd = BindAt("1500");
387 if (sfd == -1) {
388 return -1;
389 }
390
391 if (listen(sfd, 1) < 0) {
392 perror("listen");
393 return -1;
394 }
395
396 pthread_t thread;
397 void *res;
398 pthread_create(&thread, nullptr, ThreadTaskClient, nullptr);
399 pthread_join(thread, &res);
400 if (res == (void*)-1) {
401 return -1;
402 }
403
404 *connfd = accept(sfd, nullptr, nullptr);
405 if (*connfd < 0) {
406 perror("accept");
407 return -1;
408 }
409
410 return sfd;
411 }
412
Bm_function_getpeername_server(benchmark::State & state)413 static void Bm_function_getpeername_server(benchmark::State &state)
414 {
415 int connfd;
416 int sfd = StartServer(&connfd);
417 if (sfd < 0) {
418 }
419
420 struct sockaddr_in peerAddr;
421 socklen_t peerLen = sizeof(peerAddr);
422 for (auto _ : state) {
423 if (getpeername(connfd, (struct sockaddr *)&peerAddr, &peerLen) == -1) {
424 perror("getpeername");
425 printf("peer addr: %s:%d\n", inet_ntoa(peerAddr.sin_addr), ntohs(peerAddr.sin_port));
426 }
427 }
428
429 close(sfd);
430 }
431
Bm_function_getsockname_client_local(benchmark::State & state)432 static void Bm_function_getsockname_client_local(benchmark::State &state)
433 {
434 int sfd = ConnectTo("127.0.0.1", "80", SOCK_DGRAM, nullptr);
435 if (sfd == -1) {
436 }
437
438 struct sockaddr_in addr;
439 socklen_t len = sizeof(addr);
440 for (auto _ : state) {
441 if (getsockname(sfd, (struct sockaddr *)&addr, &len) == -1) {
442 perror("getsockname");
443 printf("sock addr: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
444 }
445 }
446
447 close(sfd);
448 }
449
Bm_function_getsockname_client_external(benchmark::State & state)450 static void Bm_function_getsockname_client_external(benchmark::State &state)
451 {
452 int sfd = ConnectTo("www.baidu.com", "80", SOCK_DGRAM, nullptr);
453 if (sfd == -1) {
454 }
455
456 struct sockaddr_in addr;
457 socklen_t len = sizeof(addr);
458 for (auto _ : state) {
459 if (getsockname(sfd, (struct sockaddr *)&addr, &len) == -1) {
460 perror("getsockname");
461 printf("sock addr: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
462 }
463 }
464
465 close(sfd);
466 }
467
Bm_function_getsockname_server(benchmark::State & state)468 static void Bm_function_getsockname_server(benchmark::State &state)
469 {
470 int connfd;
471 int sfd = StartServer(&connfd);
472 if (sfd < 0) {
473 }
474
475 struct sockaddr_in addr;
476 socklen_t len = sizeof(addr);
477 for (auto _ : state) {
478 if (getsockname(connfd, (struct sockaddr *)&addr, &len) == -1) {
479 perror("getsockname");
480 printf("sock addr: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
481 }
482 }
483
484 close(sfd);
485 }
486
Bm_function_connect_local_dgram(benchmark::State & state)487 static void Bm_function_connect_local_dgram(benchmark::State &state)
488 {
489 struct addrinfo addr;
490 struct sockaddr_in aiAddr;
491 addr.ai_addr = (struct sockaddr*)&aiAddr;
492 int sfd = ConnectTo("127.0.0.1", "80", SOCK_DGRAM, &addr);
493 if (sfd < 0) {
494 }
495
496 for (auto _ : state) {
497 if (connect(sfd, addr.ai_addr, addr.ai_addrlen) == -1) {
498 perror("connect");
499 }
500 }
501
502 close(sfd);
503 }
504
Bm_function_connect_accept(benchmark::State & state)505 static void Bm_function_connect_accept(benchmark::State &state)
506 {
507 int sfd = BindAt("1500");
508 if (sfd == -1) {
509 }
510
511 if (listen(sfd, 1) < 0) {
512 perror("listen");
513 }
514
515 struct addrinfo addr;
516 struct sockaddr_in aiAddr;
517 addr.ai_addr = (struct sockaddr*)&aiAddr;
518 int sfd2 = ConnectTo("127.0.0.1", "1500", SOCK_STREAM, &addr);
519 if (sfd2 == -1) {
520 }
521
522 for (auto _ : state) {
523 int connfd = accept(sfd, nullptr, nullptr);
524 if (connfd < 0) {
525 perror("accept");
526 }
527
528 state.PauseTiming();
529 close(connfd);
530 close(sfd2);
531 sfd2 = socket(addr.ai_family, addr.ai_socktype, addr.ai_protocol);
532 if (sfd == -1) {
533 perror("socket");
534 }
535 if (connect(sfd2, addr.ai_addr, addr.ai_addrlen) == -1) {
536 perror("connect2");
537 }
538 state.ResumeTiming();
539 }
540
541 close(sfd);
542 }
543
Bm_function_bind(benchmark::State & state)544 static void Bm_function_bind(benchmark::State &state)
545 {
546 struct sockaddr_in addr;
547 memset(&addr, 0, sizeof(addr));
548 addr.sin_family = AF_INET;
549 addr.sin_addr.s_addr = htonl(INADDR_ANY);
550 addr.sin_port = htons(PORT);
551
552 for (auto _ : state) {
553 state.PauseTiming();
554 int sfd = socket(AF_INET, SOCK_STREAM, 0);
555 if (sfd == -1) {
556 perror("socket");
557 }
558
559 int reuse = 1;
560 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
561 perror("setsockopt");
562 close(sfd);
563 }
564
565 state.ResumeTiming();
566
567 if (bind(sfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
568 perror("bind");
569 }
570
571 state.PauseTiming();
572 close(sfd);
573 state.ResumeTiming();
574 }
575 }
576
577 MUSL_BENCHMARK(Bm_function_socket_server);
578 MUSL_BENCHMARK(Bm_function_socketpair_sendmsg_recvmsg);
579 MUSL_BENCHMARK(Bm_function_socketpair_sendmmsg_recvmmsg);
580 MUSL_BENCHMARK(Bm_function_socketpair_sendto_recvfrom);
581 MUSL_BENCHMARK(Bm_function_getsockopt);
582 MUSL_BENCHMARK(Bm_function_setsockopt);
583 MUSL_BENCHMARK(Bm_function_sockpair);
584 MUSL_BENCHMARK(Bm_function_pipe);
585 MUSL_BENCHMARK(Bm_function_getpeername_client_local);
586 MUSL_BENCHMARK(Bm_function_getpeername_client_external);
587 MUSL_BENCHMARK(Bm_function_getpeername_server);
588 MUSL_BENCHMARK(Bm_function_getsockname_client_local);
589 MUSL_BENCHMARK(Bm_function_getsockname_client_external);
590 MUSL_BENCHMARK(Bm_function_getsockname_server);
591 MUSL_BENCHMARK(Bm_function_connect_local_dgram);
592 MUSL_BENCHMARK(Bm_function_connect_accept);
593 MUSL_BENCHMARK(Bm_function_bind);
594