blob: 354b9900d102be053c88fb1effb401ec6aea3124 [file] [log] [blame]
Dave Wallace543852a2017-08-03 02:11:34 -04001/*
2 * Copyright (c) 2017 Cisco and/or its affiliates.
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 <unistd.h>
17#include <errno.h>
18#include <sys/types.h>
19#include <sys/socket.h>
20#include <stdio.h>
21#include <string.h>
22#include <time.h>
23#include <ctype.h>
Dave Wallace5c7cf1c2017-10-24 04:12:18 -040024#include <vcl/sock_test.h>
Dave Wallace35830af2017-10-09 01:43:42 -040025#include <sys/stat.h>
26#include <fcntl.h>
Florin Coras0e88e852018-09-17 22:09:02 -070027#include <sys/ioctl.h>
Dave Wallace543852a2017-08-03 02:11:34 -040028
Dave Wallacef7f809c2017-10-03 01:48:42 -040029#define SOCK_SERVER_USE_EPOLL 1
Dave Wallace35830af2017-10-09 01:43:42 -040030#define VPPCOM_SESSION_ATTR_UNIT_TEST 0
Dave Wallacef7f809c2017-10-03 01:48:42 -040031
32#if SOCK_SERVER_USE_EPOLL
33#include <sys/epoll.h>
Dave Wallace3ee1fe12018-02-23 01:09:11 -050034#if !defined(VCL_TEST)
35#include <sys/un.h>
36#endif
Dave Wallacef7f809c2017-10-03 01:48:42 -040037#endif
38
Dave Wallace35830af2017-10-09 01:43:42 -040039#ifdef VCL_TEST
40#if VPPCOM_SESSION_ATTR_UNIT_TEST
41#define BUFLEN sizeof (uint64_t) * 16
42uint64_t buffer[16];
43uint32_t buflen = BUFLEN;
44uint32_t *flags = (uint32_t *) buffer;
45#endif
46#endif
47
Dave Wallace543852a2017-08-03 02:11:34 -040048typedef struct
49{
50 uint8_t is_alloc;
51 int fd;
52 uint8_t *buf;
53 uint32_t buf_size;
Florin Coras1502fc32018-10-05 00:50:30 -070054 vcl_test_cfg_t cfg;
55 vcl_test_stats_t stats;
Dave Wallace543852a2017-08-03 02:11:34 -040056#ifdef VCL_TEST
57 vppcom_endpt_t endpt;
58 uint8_t ip[16];
59#endif
60} sock_server_conn_t;
61
Dave Wallacede910062018-03-20 09:22:13 -040062typedef struct
63{
64 uint32_t port;
65 uint32_t address_ip6;
66 uint32_t transport_udp;
67} sock_server_cfg_t;
68
Dave Wallace543852a2017-08-03 02:11:34 -040069#define SOCK_SERVER_MAX_TEST_CONN 10
Dave Wallacef7f809c2017-10-03 01:48:42 -040070#define SOCK_SERVER_MAX_EPOLL_EVENTS 10
Dave Wallace543852a2017-08-03 02:11:34 -040071typedef struct
72{
73 int listen_fd;
Dave Wallacede910062018-03-20 09:22:13 -040074 sock_server_cfg_t cfg;
Dave Wallacef7f809c2017-10-03 01:48:42 -040075#if SOCK_SERVER_USE_EPOLL
76 int epfd;
77 struct epoll_event listen_ev;
78 struct epoll_event wait_events[SOCK_SERVER_MAX_EPOLL_EVENTS];
Dave Wallace3ee1fe12018-02-23 01:09:11 -050079#if !defined (VCL_TEST)
80 int af_unix_listen_fd;
81 int af_unix_fd;
82 struct epoll_event af_unix_listen_ev;
83 struct sockaddr_un serveraddr;
84 uint32_t af_unix_xacts;
85#endif
Dave Wallacef7f809c2017-10-03 01:48:42 -040086#endif
Dave Wallace543852a2017-08-03 02:11:34 -040087 size_t num_conn;
88 size_t conn_pool_size;
89 sock_server_conn_t *conn_pool;
90 int nfds;
91 fd_set rd_fdset;
92 fd_set wr_fdset;
93 struct timeval timeout;
94} sock_server_main_t;
95
96sock_server_main_t sock_server_main;
97
Dave Wallacef7f809c2017-10-03 01:48:42 -040098#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -040099static inline int
100get_nfds (void)
101{
102 sock_server_main_t *ssm = &sock_server_main;
103 int i, nfds;
104
105 for (nfds = i = 0; i < FD_SETSIZE; i++)
106 {
107 if (FD_ISSET (i, &ssm->rd_fdset) || FD_ISSET (i, &ssm->wr_fdset))
108 nfds = i + 1;
109 }
110 return nfds;
111}
112
113static inline void
114conn_fdset_set (sock_server_conn_t * conn, fd_set * fdset)
115{
116 sock_server_main_t *ssm = &sock_server_main;
117
118 FD_SET (conn->fd, fdset);
119 ssm->nfds = get_nfds ();
120}
121
122static inline void
123conn_fdset_clr (sock_server_conn_t * conn, fd_set * fdset)
124{
125 sock_server_main_t *ssm = &sock_server_main;
126
127 FD_CLR (conn->fd, fdset);
128 ssm->nfds = get_nfds ();
129}
Dave Wallacef7f809c2017-10-03 01:48:42 -0400130#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400131
132static inline void
133conn_pool_expand (size_t expand_size)
134{
135 sock_server_main_t *ssm = &sock_server_main;
136 sock_server_conn_t *conn_pool;
137 size_t new_size = ssm->conn_pool_size + expand_size;
138 int i;
139
140 conn_pool = realloc (ssm->conn_pool, new_size * sizeof (*ssm->conn_pool));
141 if (conn_pool)
142 {
143 for (i = ssm->conn_pool_size; i < new_size; i++)
144 {
145 sock_server_conn_t *conn = &conn_pool[i];
146 memset (conn, 0, sizeof (*conn));
Florin Coras1502fc32018-10-05 00:50:30 -0700147 vcl_test_cfg_init (&conn->cfg);
148 vcl_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ ,
149 &conn->buf, &conn->buf_size);
Dave Wallace543852a2017-08-03 02:11:34 -0400150 conn->cfg.txbuf_size = conn->cfg.rxbuf_size;
151 }
152
153 ssm->conn_pool = conn_pool;
154 ssm->conn_pool_size = new_size;
155 }
156 else
157 {
158 int errno_val = errno;
159 perror ("ERROR in conn_pool_expand()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500160 fprintf (stderr, "SERVER: ERROR: Memory allocation "
161 "failed (errno = %d)!\n", errno_val);
Dave Wallace543852a2017-08-03 02:11:34 -0400162 }
163}
164
165static inline sock_server_conn_t *
166conn_pool_alloc (void)
167{
168 sock_server_main_t *ssm = &sock_server_main;
169 int i;
170
171 for (i = 0; i < ssm->conn_pool_size; i++)
172 {
173 if (!ssm->conn_pool[i].is_alloc)
174 {
175#ifdef VCL_TEST
176 ssm->conn_pool[i].endpt.ip = ssm->conn_pool[i].ip;
177#endif
178 ssm->conn_pool[i].is_alloc = 1;
179 return (&ssm->conn_pool[i]);
180 }
181 }
182
183 return 0;
184}
185
186static inline void
187conn_pool_free (sock_server_conn_t * conn)
188{
Dave Wallacef7f809c2017-10-03 01:48:42 -0400189#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400190 sock_server_main_t *ssm = &sock_server_main;
191
192 conn_fdset_clr (conn, &ssm->rd_fdset);
193 conn_fdset_clr (conn, &ssm->wr_fdset);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400194#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400195 conn->fd = 0;
196 conn->is_alloc = 0;
197}
198
199static inline void
Florin Coras1502fc32018-10-05 00:50:30 -0700200sync_config_and_reply (sock_server_conn_t * conn, vcl_test_cfg_t * rx_cfg)
Dave Wallace543852a2017-08-03 02:11:34 -0400201{
202 conn->cfg = *rx_cfg;
Florin Coras1502fc32018-10-05 00:50:30 -0700203 vcl_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ ,
204 &conn->buf, &conn->buf_size);
Dave Wallace543852a2017-08-03 02:11:34 -0400205 conn->cfg.txbuf_size = conn->cfg.rxbuf_size;
206
207 if (conn->cfg.verbose)
208 {
209 printf ("\nSERVER (fd %d): Replying to cfg message!\n", conn->fd);
Florin Coras1502fc32018-10-05 00:50:30 -0700210 vcl_test_cfg_dump (&conn->cfg, 0 /* is_client */ );
Dave Wallace543852a2017-08-03 02:11:34 -0400211 }
212 (void) sock_test_write (conn->fd, (uint8_t *) & conn->cfg,
213 sizeof (conn->cfg), NULL, conn->cfg.verbose);
214}
215
216static void
217stream_test_server_start_stop (sock_server_conn_t * conn,
Florin Coras1502fc32018-10-05 00:50:30 -0700218 vcl_test_cfg_t * rx_cfg)
Dave Wallace543852a2017-08-03 02:11:34 -0400219{
220 sock_server_main_t *ssm = &sock_server_main;
221 int client_fd = conn->fd;
Florin Coras1502fc32018-10-05 00:50:30 -0700222 vcl_test_t test = rx_cfg->test;
Dave Wallace543852a2017-08-03 02:11:34 -0400223
224 if (rx_cfg->ctrl_handle == conn->fd)
225 {
226 int i;
227 clock_gettime (CLOCK_REALTIME, &conn->stats.stop);
228
229 for (i = 0; i < ssm->conn_pool_size; i++)
230 {
231 sock_server_conn_t *tc = &ssm->conn_pool[i];
232
233 if (tc->cfg.ctrl_handle == conn->fd)
234 {
Florin Coras1502fc32018-10-05 00:50:30 -0700235 vcl_test_stats_accumulate (&conn->stats, &tc->stats);
Dave Wallace543852a2017-08-03 02:11:34 -0400236
237 if (conn->cfg.verbose)
238 {
239 static char buf[64];
240
241 sprintf (buf, "SERVER (fd %d) RESULTS", tc->fd);
Florin Coras1502fc32018-10-05 00:50:30 -0700242 vcl_test_stats_dump (buf, &tc->stats, 1 /* show_rx */ ,
243 test == VCL_TEST_TYPE_BI
244 /* show tx */ ,
245 conn->cfg.verbose);
Dave Wallace543852a2017-08-03 02:11:34 -0400246 }
247 }
248 }
249
Florin Coras1502fc32018-10-05 00:50:30 -0700250 vcl_test_stats_dump ("SERVER RESULTS", &conn->stats, 1 /* show_rx */ ,
251 (test == VCL_TEST_TYPE_BI) /* show_tx */ ,
252 conn->cfg.verbose);
253 vcl_test_cfg_dump (&conn->cfg, 0 /* is_client */ );
Dave Wallace543852a2017-08-03 02:11:34 -0400254 if (conn->cfg.verbose)
255 {
256 printf (" sock server main\n"
Florin Coras1502fc32018-10-05 00:50:30 -0700257 VCL_TEST_SEPARATOR_STRING
Dave Wallace543852a2017-08-03 02:11:34 -0400258 " buf: %p\n"
259 " buf size: %u (0x%08x)\n"
Florin Coras1502fc32018-10-05 00:50:30 -0700260 VCL_TEST_SEPARATOR_STRING,
Dave Wallace543852a2017-08-03 02:11:34 -0400261 conn->buf, conn->buf_size, conn->buf_size);
262 }
263
264 sync_config_and_reply (conn, rx_cfg);
265 printf ("\nSERVER (fd %d): %s-directional Stream Test Complete!\n"
266 SOCK_TEST_BANNER_STRING "\n", conn->fd,
Florin Coras1502fc32018-10-05 00:50:30 -0700267 test == VCL_TEST_TYPE_BI ? "Bi" : "Uni");
Dave Wallace543852a2017-08-03 02:11:34 -0400268 }
269 else
270 {
271 printf ("\n" SOCK_TEST_BANNER_STRING
272 "SERVER (fd %d): %s-directional Stream Test!\n"
273 " Sending client the test cfg to start streaming data...\n",
Florin Coras1502fc32018-10-05 00:50:30 -0700274 client_fd, test == VCL_TEST_TYPE_BI ? "Bi" : "Uni");
Dave Wallace543852a2017-08-03 02:11:34 -0400275
276 rx_cfg->ctrl_handle = (rx_cfg->ctrl_handle == ~0) ? conn->fd :
277 rx_cfg->ctrl_handle;
278
279 sync_config_and_reply (conn, rx_cfg);
280
281 /* read the 1st chunk, record start time */
282 memset (&conn->stats, 0, sizeof (conn->stats));
283 clock_gettime (CLOCK_REALTIME, &conn->stats.start);
284 }
285}
286
287
288static inline void
289stream_test_server (sock_server_conn_t * conn, int rx_bytes)
290{
291 int client_fd = conn->fd;
Florin Coras1502fc32018-10-05 00:50:30 -0700292 vcl_test_t test = conn->cfg.test;
Dave Wallace543852a2017-08-03 02:11:34 -0400293
Florin Coras1502fc32018-10-05 00:50:30 -0700294 if (test == VCL_TEST_TYPE_BI)
Dave Wallace543852a2017-08-03 02:11:34 -0400295 (void) sock_test_write (client_fd, conn->buf, rx_bytes, &conn->stats,
296 conn->cfg.verbose);
297
298 if (conn->stats.rx_bytes >= conn->cfg.total_bytes)
299 {
300 clock_gettime (CLOCK_REALTIME, &conn->stats.stop);
301 }
302}
303
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500304#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST)
305static inline void
306af_unix_echo (void)
307{
308 sock_server_main_t *ssm = &sock_server_main;
309 int af_unix_client_fd;
310 int rv;
311 int errno_val;
312 uint8_t buffer[256];
313 size_t nbytes = strlen (SOCK_TEST_MIXED_EPOLL_DATA) + 1;
314
315#if HAVE_ACCEPT4
316 af_unix_client_fd = accept4 (ssm->af_unix_listen_fd,
317 (struct sockaddr *) NULL, NULL, NULL);
318#else
319 af_unix_client_fd = accept (ssm->af_unix_listen_fd,
320 (struct sockaddr *) NULL, NULL);
321#endif
322 if (af_unix_client_fd < 0)
323 {
324 errno_val = errno;
325 perror ("ERROR in af_unix_accept()");
326 fprintf (stderr, "SERVER: ERROR: accept failed "
327 "(errno = %d)!\n", errno_val);
328 return;
329 }
330
331 printf ("SERVER: Got an AF_UNIX connection -- fd = %d (0x%08x)!\n",
332 af_unix_client_fd, af_unix_client_fd);
333
334 memset (buffer, 0, sizeof (buffer));
335
336 rv = read (af_unix_client_fd, buffer, nbytes);
337 if (rv < 0)
338 {
339 errno_val = errno;
340 perror ("ERROR in af_unix_echo(): read() failed");
341 fprintf (stderr, "SERVER: ERROR: read(af_unix_client_fd %d (0x%x), "
342 "\"%s\", nbytes %lu) failed (errno = %d)!\n",
343 af_unix_client_fd, af_unix_client_fd, buffer, nbytes,
344 errno_val);
345 goto done;
346 }
347
348 printf ("SERVER (AF_UNIX): RX (%d bytes) - '%s'\n", rv, buffer);
349
350 if (!strncmp (SOCK_TEST_MIXED_EPOLL_DATA, (const char *) buffer, nbytes))
351 {
352 rv = write (af_unix_client_fd, buffer, nbytes);
353 if (rv < 0)
354 {
355 errno_val = errno;
356 perror ("ERROR in af_unix_echo(): write() failed");
357 fprintf (stderr,
358 "SERVER: ERROR: write(af_unix_client_fd %d (0x%x), "
359 "\"%s\", nbytes %ld) failed (errno = %d)!\n",
360 af_unix_client_fd, af_unix_client_fd, buffer, nbytes,
361 errno_val);
362 goto done;
363 }
364 printf ("SERVER (AF_UNIX): TX (%d bytes) - '%s'\n", rv, buffer);
365 ssm->af_unix_xacts++;
366 }
367done:
368 close (af_unix_client_fd);
369}
370
371#endif
372
Dave Wallace543852a2017-08-03 02:11:34 -0400373static inline void
374new_client (void)
375{
376 sock_server_main_t *ssm = &sock_server_main;
377 int client_fd;
378 sock_server_conn_t *conn;
379
380 if (ssm->conn_pool_size < (ssm->num_conn + SOCK_SERVER_MAX_TEST_CONN + 1))
381 conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1);
382
383 conn = conn_pool_alloc ();
384 if (!conn)
385 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500386 fprintf (stderr, "\nSERVER: ERROR: No free connections!\n");
Dave Wallace543852a2017-08-03 02:11:34 -0400387 return;
388 }
389
390#ifdef VCL_TEST
Dave Wallace048b1d62018-01-03 22:24:41 -0500391 client_fd = vppcom_session_accept (ssm->listen_fd, &conn->endpt, 0);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400392 if (client_fd < 0)
393 errno = -client_fd;
Dave Wallace59179392017-11-07 02:20:07 -0500394#elif HAVE_ACCEPT4
395 client_fd = accept4 (ssm->listen_fd, (struct sockaddr *) NULL, NULL, NULL);
Dave Wallace543852a2017-08-03 02:11:34 -0400396#else
397 client_fd = accept (ssm->listen_fd, (struct sockaddr *) NULL, NULL);
398#endif
399 if (client_fd < 0)
400 {
401 int errno_val;
402 errno_val = errno;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400403 perror ("ERROR in new_client()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500404 fprintf (stderr, "SERVER: ERROR: accept failed "
405 "(errno = %d)!\n", errno_val);
Dave Wallaceee45d412017-11-24 21:44:06 -0500406 return;
Dave Wallace543852a2017-08-03 02:11:34 -0400407 }
408
409 printf ("SERVER: Got a connection -- fd = %d (0x%08x)!\n",
410 client_fd, client_fd);
411
412 conn->fd = client_fd;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400413
414#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400415 conn_fdset_set (conn, &ssm->rd_fdset);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400416 ssm->nfds++;
417#else
418 {
419 struct epoll_event ev;
420 int rv;
421
422 ev.events = EPOLLIN;
423 ev.data.u64 = conn - ssm->conn_pool;
424#ifdef VCL_TEST
425 rv = vppcom_epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, client_fd, &ev);
426 if (rv)
427 errno = -rv;
428#else
429 rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, client_fd, &ev);
430#endif
431 if (rv < 0)
432 {
433 int errno_val;
434 errno_val = errno;
435 perror ("ERROR in new_client()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500436 fprintf (stderr, "SERVER: ERROR: epoll_ctl failed (errno = %d)!\n",
Dave Wallacef7f809c2017-10-03 01:48:42 -0400437 errno_val);
438 }
439 else
440 ssm->nfds++;
441 }
442#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400443}
444
Dave Wallacede910062018-03-20 09:22:13 -0400445void
446print_usage_and_exit (void)
447{
448 fprintf (stderr,
449 "sock_test_server [OPTIONS] <port>\n"
450 " OPTIONS\n"
451 " -h Print this message and exit.\n"
452 " -6 Use IPv6\n"
453 " -u Use UDP transport layer\n");
454 exit (1);
455}
456
Dave Wallace543852a2017-08-03 02:11:34 -0400457int
458main (int argc, char **argv)
459{
460 sock_server_main_t *ssm = &sock_server_main;
461 int client_fd, rv, main_rv = 0;
462 int tx_bytes, rx_bytes, nbytes;
463 sock_server_conn_t *conn;
Florin Coras1502fc32018-10-05 00:50:30 -0700464 vcl_test_cfg_t *rx_cfg;
Dave Wallace543852a2017-08-03 02:11:34 -0400465 uint32_t xtra = 0;
466 uint64_t xtra_bytes = 0;
Dave Wallacede910062018-03-20 09:22:13 -0400467 struct sockaddr_storage servaddr;
Dave Wallace543852a2017-08-03 02:11:34 -0400468 int errno_val;
Dave Wallacede910062018-03-20 09:22:13 -0400469 int c, v, i;
Florin Coras1502fc32018-10-05 00:50:30 -0700470 uint16_t port = VCL_TEST_SERVER_PORT;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400471#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400472 fd_set _rfdset, *rfdset = &_rfdset;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400473#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400474#ifdef VCL_TEST
475 vppcom_endpt_t endpt;
476#else
Dave Wallacede910062018-03-20 09:22:13 -0400477 uint32_t servaddr_size;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400478#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400479 fd_set _wfdset, *wfdset = &_wfdset;
480#endif
Dave Wallacef7f809c2017-10-03 01:48:42 -0400481#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400482
Dave Wallacede910062018-03-20 09:22:13 -0400483 opterr = 0;
484 while ((c = getopt (argc, argv, "6D")) != -1)
485 switch (c)
486 {
487 case '6':
488 ssm->cfg.address_ip6 = 1;
489 break;
490
491 case 'D':
492 ssm->cfg.transport_udp = 1;
493 break;
494
495 case '?':
496 switch (optopt)
497 {
498 default:
499 if (isprint (optopt))
500 fprintf (stderr, "SERVER: ERROR: Unknown "
501 "option `-%c'.\n", optopt);
502 else
503 fprintf (stderr, "SERVER: ERROR: Unknown "
504 "option character `\\x%x'.\n", optopt);
505 }
506 /* fall thru */
507 case 'h':
508 default:
509 print_usage_and_exit ();
510 }
511
512 if (argc < (optind + 1))
513 {
514 fprintf (stderr, "SERVER: ERROR: Insufficient number of arguments!\n");
515 print_usage_and_exit ();
516 }
517
518 if (sscanf (argv[optind], "%d", &v) == 1)
Dave Wallace543852a2017-08-03 02:11:34 -0400519 port = (uint16_t) v;
Dave Wallacede910062018-03-20 09:22:13 -0400520 else
521 {
522 fprintf (stderr, "SERVER: ERROR: Invalid port (%s)!\n", argv[optind]);
523 print_usage_and_exit ();
524 }
Dave Wallace543852a2017-08-03 02:11:34 -0400525
526 conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1);
527
528#ifdef VCL_TEST
529 rv = vppcom_app_create ("vcl_test_server");
530 if (rv)
531 {
532 errno = -rv;
533 ssm->listen_fd = -1;
534 }
535 else
536 {
Dave Wallacede910062018-03-20 09:22:13 -0400537 ssm->listen_fd = vppcom_session_create (ssm->cfg.transport_udp ?
538 VPPCOM_PROTO_UDP :
539 VPPCOM_PROTO_TCP,
540 0 /* is_nonblocking */ );
Dave Wallace543852a2017-08-03 02:11:34 -0400541 }
542#else
Dave Wallacede910062018-03-20 09:22:13 -0400543 ssm->listen_fd = socket (ssm->cfg.address_ip6 ? AF_INET6 : AF_INET,
544 ssm->cfg.transport_udp ? SOCK_DGRAM : SOCK_STREAM,
545 0);
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500546#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST)
547 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
548 ssm->af_unix_listen_fd = socket (AF_UNIX, SOCK_STREAM, 0);
549 if (ssm->af_unix_listen_fd < 0)
550 {
551 errno_val = errno;
552 perror ("ERROR in main(): socket(AF_UNIX) failed");
553 fprintf (stderr,
554 "SERVER: ERROR: socket(AF_UNIX, SOCK_STREAM, 0) failed "
555 "(errno = %d)!\n", errno_val);
556 return ssm->af_unix_listen_fd;
557 }
558
559 memset (&ssm->serveraddr, 0, sizeof (ssm->serveraddr));
560 ssm->serveraddr.sun_family = AF_UNIX;
561 strcpy (ssm->serveraddr.sun_path, SOCK_TEST_AF_UNIX_FILENAME);
562
563 rv = bind (ssm->af_unix_listen_fd, (struct sockaddr *) &ssm->serveraddr,
564 SUN_LEN (&ssm->serveraddr));
565 if (rv < 0)
566 {
567 errno_val = errno;
568 perror ("ERROR in main(): bind(SOCK_TEST_AF_UNIX_FILENAME) failed");
569 fprintf (stderr, "SERVER: ERROR: bind() fd %d, \"%s\": "
570 "failed (errno = %d)!\n", ssm->af_unix_listen_fd,
571 SOCK_TEST_AF_UNIX_FILENAME, errno_val);
572 close (ssm->af_unix_listen_fd);
573 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
574 return rv;
575 }
576
577 rv = listen (ssm->af_unix_listen_fd, 10);
578 if (rv < 0)
579 {
580 errno_val = errno;
581 perror ("ERROR in main(): listen(AF_UNIX) failed");
582 fprintf (stderr, "SERVER: ERROR: listen() fd %d, \"%s\": "
583 "failed (errno = %d)!\n", ssm->af_unix_listen_fd,
584 SOCK_TEST_AF_UNIX_FILENAME, errno_val);
585 close (ssm->af_unix_listen_fd);
586 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
587 return rv;
588 }
589#endif /* SOCK_SERVER_USE_EPOLL */
Dave Wallace543852a2017-08-03 02:11:34 -0400590#endif
591 if (ssm->listen_fd < 0)
592 {
593 errno_val = errno;
594 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500595 fprintf (stderr, "SERVER: ERROR: socket() failed "
596 "(errno = %d)!\n", errno_val);
Dave Wallace543852a2017-08-03 02:11:34 -0400597 return ssm->listen_fd;
598 }
599
600 memset (&servaddr, 0, sizeof (servaddr));
601
Dave Wallacede910062018-03-20 09:22:13 -0400602 if (ssm->cfg.address_ip6)
603 {
604 struct sockaddr_in6 *server_addr = (struct sockaddr_in6 *) &servaddr;
605#ifndef VCL_TEST
606 servaddr_size = sizeof (*server_addr);
607#endif
608 server_addr->sin6_family = AF_INET6;
609 server_addr->sin6_addr = in6addr_any;
610 server_addr->sin6_port = htons (port);
611 }
612 else
613 {
614 struct sockaddr_in *server_addr = (struct sockaddr_in *) &servaddr;
615#ifndef VCL_TEST
616 servaddr_size = sizeof (*server_addr);
617#endif
618 server_addr->sin_family = AF_INET;
619 server_addr->sin_addr.s_addr = htonl (INADDR_ANY);
620 server_addr->sin_port = htons (port);
621 }
Dave Wallace543852a2017-08-03 02:11:34 -0400622
623#ifdef VCL_TEST
Dave Wallacede910062018-03-20 09:22:13 -0400624 if (ssm->cfg.address_ip6)
625 {
626 struct sockaddr_in6 *server_addr = (struct sockaddr_in6 *) &servaddr;
627 endpt.is_ip4 = 0;
628 endpt.ip = (uint8_t *) & server_addr->sin6_addr;
629 endpt.port = (uint16_t) server_addr->sin6_port;
630 }
631 else
632 {
633 struct sockaddr_in *server_addr = (struct sockaddr_in *) &servaddr;
634 endpt.is_ip4 = 1;
635 endpt.ip = (uint8_t *) & server_addr->sin_addr;
636 endpt.port = (uint16_t) server_addr->sin_port;
637 }
Dave Wallace543852a2017-08-03 02:11:34 -0400638
639 rv = vppcom_session_bind (ssm->listen_fd, &endpt);
640 if (rv)
641 {
642 errno = -rv;
643 rv = -1;
644 }
645#else
Dave Wallacede910062018-03-20 09:22:13 -0400646 rv = bind (ssm->listen_fd, (struct sockaddr *) &servaddr, servaddr_size);
Dave Wallace543852a2017-08-03 02:11:34 -0400647#endif
648 if (rv < 0)
649 {
650 errno_val = errno;
651 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500652 fprintf (stderr, "SERVER: ERROR: bind failed (errno = %d)!\n",
653 errno_val);
Dave Wallace543852a2017-08-03 02:11:34 -0400654 return rv;
655 }
Florin Corasc227e492018-12-21 19:28:34 -0800656 if (fcntl (ssm->listen_fd, F_SETFL, O_NONBLOCK) < 0)
657 {
658 errno_val = errno;
659 perror ("ERROR in main()");
660 fprintf (stderr, "SERVER: ERROR: fcntl failed (errno = %d)!\n",
661 errno_val);
662 return rv;
663 }
Dave Wallace543852a2017-08-03 02:11:34 -0400664
665#ifdef VCL_TEST
666 rv = vppcom_session_listen (ssm->listen_fd, 10);
667 if (rv)
668 {
669 errno = -rv;
670 rv = -1;
671 }
672#else
673 rv = listen (ssm->listen_fd, 10);
674#endif
675 if (rv < 0)
676 {
677 errno_val = errno;
678 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500679 fprintf (stderr, "SERVER: ERROR: listen failed "
680 "(errno = %d)!\n", errno_val);
Dave Wallace543852a2017-08-03 02:11:34 -0400681 return rv;
682 }
683
Dave Wallacef7f809c2017-10-03 01:48:42 -0400684#if ! SOCK_SERVER_USE_EPOLL
685
Dave Wallace543852a2017-08-03 02:11:34 -0400686 FD_ZERO (&ssm->wr_fdset);
687 FD_ZERO (&ssm->rd_fdset);
688
689 FD_SET (ssm->listen_fd, &ssm->rd_fdset);
690 ssm->nfds = ssm->listen_fd + 1;
691
Dave Wallacef7f809c2017-10-03 01:48:42 -0400692#else
693#ifdef VCL_TEST
694 ssm->epfd = vppcom_epoll_create ();
695 if (ssm->epfd < 0)
696 errno = -ssm->epfd;
697#else
698 ssm->epfd = epoll_create (1);
699#endif
700 if (ssm->epfd < 0)
701 {
702 errno_val = errno;
703 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500704 fprintf (stderr, "SERVER: ERROR: epoll_create failed (errno = %d)!\n",
Dave Wallacef7f809c2017-10-03 01:48:42 -0400705 errno_val);
706 return ssm->epfd;
707 }
708
709 ssm->listen_ev.events = EPOLLIN;
710 ssm->listen_ev.data.u32 = ~0;
711#ifdef VCL_TEST
712 rv = vppcom_epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->listen_fd,
713 &ssm->listen_ev);
714 if (rv < 0)
715 errno = -rv;
716#else
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500717 ssm->af_unix_listen_ev.events = EPOLLIN;
718 ssm->af_unix_listen_ev.data.u32 = SOCK_TEST_AF_UNIX_ACCEPT_DATA;
719 rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->af_unix_listen_fd,
720 &ssm->af_unix_listen_ev);
721 if (rv < 0)
722 {
723 errno_val = errno;
724 perror ("ERROR in main(): mixed epoll_ctl(EPOLL_CTL_ADD)");
725 fprintf (stderr, "SERVER: ERROR: mixed epoll_ctl(epfd %d (0x%x), "
726 "EPOLL_CTL_ADD, af_unix_listen_fd %d (0x%x), EPOLLIN) failed "
727 "(errno = %d)!\n", ssm->epfd, ssm->epfd,
728 ssm->af_unix_listen_fd, ssm->af_unix_listen_fd, errno_val);
729 close (ssm->af_unix_listen_fd);
730 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
731 return rv;
732 }
733
Dave Wallacef7f809c2017-10-03 01:48:42 -0400734 rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->listen_fd, &ssm->listen_ev);
735#endif
736 if (rv < 0)
737 {
738 errno_val = errno;
739 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500740 fprintf (stderr, "SERVER: ERROR: epoll_ctl failed "
741 "(errno = %d)!\n", errno_val);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400742 return rv;
743 }
744#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400745
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500746 printf ("\nSERVER: Waiting for a client to connect on port %d...\n", port);
747
Dave Wallace543852a2017-08-03 02:11:34 -0400748 while (1)
749 {
Dave Wallacef7f809c2017-10-03 01:48:42 -0400750#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400751 _rfdset = ssm->rd_fdset;
752
753#ifdef VCL_TEST
754 rv = vppcom_select (ssm->nfds, (uint64_t *) rfdset, NULL, NULL, 0);
755#else
756 {
757 struct timeval timeout;
758 timeout = ssm->timeout;
759 _wfdset = ssm->wr_fdset;
760 rv = select (ssm->nfds, rfdset, wfdset, NULL, &timeout);
761 }
762#endif
763 if (rv < 0)
764 {
765 perror ("select()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500766 fprintf (stderr, "\nSERVER: ERROR: select() failed -- aborting!\n");
Dave Wallace543852a2017-08-03 02:11:34 -0400767 main_rv = -1;
768 goto done;
769 }
770 else if (rv == 0)
771 continue;
772
773 if (FD_ISSET (ssm->listen_fd, rfdset))
774 new_client ();
775
776 for (i = 0; i < ssm->conn_pool_size; i++)
777 {
778 if (!ssm->conn_pool[i].is_alloc)
779 continue;
780
781 conn = &ssm->conn_pool[i];
Dave Wallacef7f809c2017-10-03 01:48:42 -0400782#else
783 int num_ev;
784#ifdef VCL_TEST
785 num_ev = vppcom_epoll_wait (ssm->epfd, ssm->wait_events,
786 SOCK_SERVER_MAX_EPOLL_EVENTS, 60.0);
Dave Wallace0fd6ad62017-10-20 13:23:40 -0400787 if (num_ev < 0)
788 errno = -num_ev;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400789#else
790 num_ev = epoll_wait (ssm->epfd, ssm->wait_events,
791 SOCK_SERVER_MAX_EPOLL_EVENTS, 60000);
792#endif
793 if (num_ev < 0)
794 {
795 perror ("epoll_wait()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500796 fprintf (stderr, "\nSERVER: ERROR: epoll_wait() "
797 "failed -- aborting!\n");
Dave Wallacef7f809c2017-10-03 01:48:42 -0400798 main_rv = -1;
799 goto done;
800 }
801 if (num_ev == 0)
802 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500803 fprintf (stderr, "\nSERVER: epoll_wait() timeout!\n");
Dave Wallacef7f809c2017-10-03 01:48:42 -0400804 continue;
805 }
806 for (i = 0; i < num_ev; i++)
807 {
Dave Wallace63f18592018-03-13 19:37:54 -0400808 conn = &ssm->conn_pool[ssm->wait_events[i].data.u32];
809 if (ssm->wait_events[i].events & (EPOLLHUP | EPOLLRDHUP))
810 {
811#ifdef VCL_TEST
812 vppcom_session_close (conn->fd);
813#else
814 close (conn->fd);
815#endif
816 continue;
817 }
Dave Wallacef7f809c2017-10-03 01:48:42 -0400818 if (ssm->wait_events[i].data.u32 == ~0)
819 {
820 new_client ();
821 continue;
822 }
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500823#if !defined (VCL_TEST)
824 else if (ssm->wait_events[i].data.u32 ==
825 SOCK_TEST_AF_UNIX_ACCEPT_DATA)
826 {
827 af_unix_echo ();
828 continue;
829 }
830#endif
Dave Wallacef7f809c2017-10-03 01:48:42 -0400831#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400832 client_fd = conn->fd;
833
Dave Wallacef7f809c2017-10-03 01:48:42 -0400834#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400835 if (FD_ISSET (client_fd, rfdset))
Dave Wallacef7f809c2017-10-03 01:48:42 -0400836#else
837 if (EPOLLIN & ssm->wait_events[i].events)
838#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400839 {
Florin Coras0e88e852018-09-17 22:09:02 -0700840 read_again:
Dave Wallace543852a2017-08-03 02:11:34 -0400841 rx_bytes = sock_test_read (client_fd, conn->buf,
842 conn->buf_size, &conn->stats);
843 if (rx_bytes > 0)
844 {
Florin Coras1502fc32018-10-05 00:50:30 -0700845 rx_cfg = (vcl_test_cfg_t *) conn->buf;
846 if (rx_cfg->magic == VCL_TEST_CFG_CTRL_MAGIC)
Dave Wallace543852a2017-08-03 02:11:34 -0400847 {
848 if (rx_cfg->verbose)
849 {
850 printf ("SERVER (fd %d): Received a cfg message!\n",
851 client_fd);
Florin Coras1502fc32018-10-05 00:50:30 -0700852 vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ );
Dave Wallace543852a2017-08-03 02:11:34 -0400853 }
854
855 if (rx_bytes != sizeof (*rx_cfg))
856 {
857 printf ("SERVER (fd %d): Invalid cfg message "
858 "size (%d)!\n Should be %lu bytes.\n",
859 client_fd, rx_bytes, sizeof (*rx_cfg));
860 conn->cfg.rxbuf_size = 0;
861 conn->cfg.num_writes = 0;
862 if (conn->cfg.verbose)
863 {
864 printf ("SERVER (fd %d): Replying to "
865 "cfg message!\n", client_fd);
Florin Coras1502fc32018-10-05 00:50:30 -0700866 vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ );
Dave Wallace543852a2017-08-03 02:11:34 -0400867 }
868 sock_test_write (client_fd, (uint8_t *) & conn->cfg,
869 sizeof (conn->cfg), NULL,
870 conn->cfg.verbose);
871 continue;
872 }
873
874 switch (rx_cfg->test)
875 {
Florin Coras1502fc32018-10-05 00:50:30 -0700876 case VCL_TEST_TYPE_NONE:
877 case VCL_TEST_TYPE_ECHO:
Dave Wallace543852a2017-08-03 02:11:34 -0400878 sync_config_and_reply (conn, rx_cfg);
879 break;
880
Florin Coras1502fc32018-10-05 00:50:30 -0700881 case VCL_TEST_TYPE_BI:
882 case VCL_TEST_TYPE_UNI:
Dave Wallace543852a2017-08-03 02:11:34 -0400883 stream_test_server_start_stop (conn, rx_cfg);
884 break;
885
Florin Coras1502fc32018-10-05 00:50:30 -0700886 case VCL_TEST_TYPE_EXIT:
Dave Wallace543852a2017-08-03 02:11:34 -0400887 printf ("SERVER: Have a great day, "
888 "connection %d!\n", client_fd);
889#ifdef VCL_TEST
890 vppcom_session_close (client_fd);
891#else
892 close (client_fd);
893#endif
894 conn_pool_free (conn);
Dave Wallaceee45d412017-11-24 21:44:06 -0500895 printf ("SERVER: Closed client fd %d\n", client_fd);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400896#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400897 if (ssm->nfds == (ssm->listen_fd + 1))
Dave Wallacef7f809c2017-10-03 01:48:42 -0400898#else
899 ssm->nfds--;
900 if (!ssm->nfds)
901#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400902 {
903 printf ("SERVER: All client connections "
904 "closed.\n\nSERVER: "
905 "May the force be with you!\n\n");
906 goto done;
907 }
908 break;
909
910 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500911 fprintf (stderr,
912 "SERVER: ERROR: Unknown test type!\n");
Florin Coras1502fc32018-10-05 00:50:30 -0700913 vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ );
Dave Wallace543852a2017-08-03 02:11:34 -0400914 break;
915 }
916 continue;
917 }
918
Florin Coras1502fc32018-10-05 00:50:30 -0700919 else if ((conn->cfg.test == VCL_TEST_TYPE_UNI) ||
920 (conn->cfg.test == VCL_TEST_TYPE_BI))
Dave Wallace543852a2017-08-03 02:11:34 -0400921 {
922 stream_test_server (conn, rx_bytes);
Florin Coras0e88e852018-09-17 22:09:02 -0700923 if (ioctl (conn->fd, FIONREAD))
924 goto read_again;
Dave Wallace543852a2017-08-03 02:11:34 -0400925 continue;
926 }
927
Chris Luke879ace32017-09-26 13:15:16 -0400928 else if (isascii (conn->buf[0]))
Chris Lukeab7b8d92017-09-07 07:40:13 -0400929 {
930 // If it looks vaguely like a string, make sure it's terminated
931 ((char *) conn->buf)[rx_bytes <
932 conn->buf_size ? rx_bytes :
933 conn->buf_size - 1] = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400934 printf ("SERVER (fd %d): RX (%d bytes) - '%s'\n",
Chris Lukeab7b8d92017-09-07 07:40:13 -0400935 conn->fd, rx_bytes, conn->buf);
936 }
Dave Wallace543852a2017-08-03 02:11:34 -0400937 }
938 else // rx_bytes < 0
939 {
940 if (errno == ECONNRESET)
941 {
942 printf ("\nSERVER: Connection reset by remote peer.\n"
943 " Y'all have a great day now!\n\n");
944 break;
945 }
946 else
947 continue;
948 }
949
Chris Luke879ace32017-09-26 13:15:16 -0400950 if (isascii (conn->buf[0]))
Dave Wallace543852a2017-08-03 02:11:34 -0400951 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500952 /* If it looks vaguely like a string,
953 * make sure it's terminated
954 */
Chris Luke879ace32017-09-26 13:15:16 -0400955 ((char *) conn->buf)[rx_bytes <
956 conn->buf_size ? rx_bytes :
957 conn->buf_size - 1] = 0;
Dave Wallace543852a2017-08-03 02:11:34 -0400958 if (xtra)
Dave Wallace048b1d62018-01-03 22:24:41 -0500959 fprintf (stderr, "SERVER: ERROR: "
960 "FIFO not drained in previous test!\n"
Dave Wallace543852a2017-08-03 02:11:34 -0400961 " extra chunks %u (0x%x)\n"
962 " extra bytes %lu (0x%lx)\n",
963 xtra, xtra, xtra_bytes, xtra_bytes);
964
965 xtra = 0;
966 xtra_bytes = 0;
967
968 if (conn->cfg.verbose)
969 printf ("SERVER (fd %d): Echoing back\n", client_fd);
970
971 nbytes = strlen ((const char *) conn->buf) + 1;
972
973 tx_bytes = sock_test_write (client_fd, conn->buf,
974 nbytes, &conn->stats,
975 conn->cfg.verbose);
976 if (tx_bytes >= 0)
977 printf ("SERVER (fd %d): TX (%d bytes) - '%s'\n",
978 conn->fd, tx_bytes, conn->buf);
979 }
980
981 else // Extraneous read data from non-echo tests???
982 {
983 xtra++;
984 xtra_bytes += rx_bytes;
985 }
986 }
987 }
988 }
989
990done:
991#ifdef VCL_TEST
992 vppcom_session_close (ssm->listen_fd);
993 vppcom_app_destroy ();
994#else
995 close (ssm->listen_fd);
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500996
997#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST)
998 close (ssm->af_unix_listen_fd);
999 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
1000#endif /* SOCK_SERVER_USE_EPOLL */
1001
Dave Wallace543852a2017-08-03 02:11:34 -04001002#endif
1003 if (ssm->conn_pool)
1004 free (ssm->conn_pool);
1005
1006 return main_rv;
1007}
1008
1009/*
1010 * fd.io coding-style-patch-verification: ON
1011 *
1012 * Local Variables:
1013 * eval: (c-set-style "gnu")
1014 * End:
1015 */