blob: d76e9395a7575e5e91f7ad89fd9090e929429f7e [file] [log] [blame]
Dave Barach68b0fb02017-02-28 15:15:56 -05001/*
2 * Copyright (c) 2016 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 <stdio.h>
17#include <signal.h>
Florin Coras90a63982017-12-19 04:50:01 -080018
19#include <vnet/session/application_interface.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050020#include <svm/svm_fifo_segment.h>
21#include <vlibmemory/api.h>
Florin Coras90a63982017-12-19 04:50:01 -080022
Dave Barach68b0fb02017-02-28 15:15:56 -050023#include <vpp/api/vpe_msg_enum.h>
24
Florin Corase04c2992017-03-01 08:17:34 -080025#define vl_typedefs /* define message structures */
Dave Barach68b0fb02017-02-28 15:15:56 -050026#include <vpp/api/vpe_all_api_h.h>
27#undef vl_typedefs
28
29/* declare message handlers for each api */
30
Florin Corase04c2992017-03-01 08:17:34 -080031#define vl_endianfun /* define message structures */
Dave Barach68b0fb02017-02-28 15:15:56 -050032#include <vpp/api/vpe_all_api_h.h>
33#undef vl_endianfun
34
35/* instantiate all the print functions we know about */
36#define vl_print(handle, ...)
37#define vl_printfun
38#include <vpp/api/vpe_all_api_h.h>
39#undef vl_printfun
40
Florin Corasa849b7b2018-05-18 00:41:55 -070041#define TCP_ECHO_DBG 0
42#define DBG(_fmt,_args...) \
43 if (TCP_ECHO_DBG) \
44 clib_warning (_fmt, _args)
45
Dave Barach68b0fb02017-02-28 15:15:56 -050046typedef struct
47{
Florin Coras9e47ac52019-01-24 23:22:37 -080048 CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
49#define _(type, name) type name;
50 foreach_app_session_field
51#undef _
Florin Corasa5464812017-04-19 13:00:05 -070052 u64 vpp_session_handle;
Florin Corasa849b7b2018-05-18 00:41:55 -070053 u64 bytes_sent;
54 u64 bytes_to_send;
55 volatile u64 bytes_received;
56 volatile u64 bytes_to_receive;
Florin Corasf03a59a2017-06-09 21:07:32 -070057 f64 start;
Florin Coras9e47ac52019-01-24 23:22:37 -080058} echo_session_t;
Dave Barach68b0fb02017-02-28 15:15:56 -050059
60typedef enum
61{
62 STATE_START,
Florin Corasa5464812017-04-19 13:00:05 -070063 STATE_ATTACHED,
Florin Coras52207f12018-07-12 14:48:06 -070064 STATE_LISTEN,
Dave Barach68b0fb02017-02-28 15:15:56 -050065 STATE_READY,
66 STATE_DISCONNECTING,
Florin Corasa849b7b2018-05-18 00:41:55 -070067 STATE_FAILED,
68 STATE_DETACHED
Dave Barach68b0fb02017-02-28 15:15:56 -050069} connection_state_t;
70
71typedef struct
72{
73 /* vpe input queue */
Florin Corase86a8ed2018-01-05 03:20:25 -080074 svm_queue_t *vl_input_queue;
Dave Barach68b0fb02017-02-28 15:15:56 -050075
76 /* API client handle */
77 u32 my_client_index;
78
79 /* The URI we're playing with */
Florin Corase04c2992017-03-01 08:17:34 -080080 u8 *uri;
Dave Barach68b0fb02017-02-28 15:15:56 -050081
82 /* Session pool */
Florin Coras9e47ac52019-01-24 23:22:37 -080083 echo_session_t *sessions;
Dave Barach68b0fb02017-02-28 15:15:56 -050084
85 /* Hash table for disconnect processing */
Florin Corase04c2992017-03-01 08:17:34 -080086 uword *session_index_by_vpp_handles;
Dave Barach68b0fb02017-02-28 15:15:56 -050087
88 /* intermediate rx buffer */
Florin Corase04c2992017-03-01 08:17:34 -080089 u8 *rx_buf;
Dave Barach68b0fb02017-02-28 15:15:56 -050090
91 /* URI for slave's connect */
Florin Corase04c2992017-03-01 08:17:34 -080092 u8 *connect_uri;
Dave Barach68b0fb02017-02-28 15:15:56 -050093
94 u32 connected_session_index;
95
96 int i_am_master;
97
98 /* drop all packets */
Florin Coras8e43d042018-05-04 15:46:57 -070099 int no_return;
Dave Barach68b0fb02017-02-28 15:15:56 -0500100
101 /* Our event queue */
Florin Coras3c2fed52018-07-04 04:15:05 -0700102 svm_msg_q_t *our_event_queue;
Dave Barach68b0fb02017-02-28 15:15:56 -0500103
Florin Coras90a63982017-12-19 04:50:01 -0800104 u8 *socket_name;
105
Dave Barach68b0fb02017-02-28 15:15:56 -0500106 pid_t my_pid;
107
108 /* For deadman timers */
109 clib_time_t clib_time;
110
111 /* State of the connection, shared between msg RX thread and main thread */
112 volatile connection_state_t state;
113
114 /* Signal variables */
115 volatile int time_to_stop;
116 volatile int time_to_print_stats;
117
118 u32 configured_segment_size;
119
120 /* VNET_API_ERROR_FOO -> "Foo" hash table */
Florin Corase04c2992017-03-01 08:17:34 -0800121 uword *error_string_by_error_number;
Dave Barach68b0fb02017-02-28 15:15:56 -0500122
123 u8 *connect_test_data;
Florin Corasa849b7b2018-05-18 00:41:55 -0700124 pthread_t *client_thread_handles;
125 u32 *thread_args;
Florin Corase04c2992017-03-01 08:17:34 -0800126 u32 client_bytes_received;
127 u8 test_return_packets;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700128 u64 bytes_to_send;
Florin Coras8e43d042018-05-04 15:46:57 -0700129 u32 fifo_size;
Florin Corase04c2992017-03-01 08:17:34 -0800130
Florin Corasa849b7b2018-05-18 00:41:55 -0700131 u32 n_clients;
132 u64 tx_total;
133 u64 rx_total;
134
135 volatile u32 n_clients_connected;
136 volatile u32 n_active_clients;
137
138
Florin Coras90a63982017-12-19 04:50:01 -0800139 /** Flag that decides if socket, instead of svm, api is used to connect to
140 * vpp. If sock api is used, shm binary api is subsequently bootstrapped
141 * and all other messages are exchanged using shm IPC. */
142 u8 use_sock_api;
143
Florin Corasadc74d72018-12-02 13:36:00 -0800144 svm_fifo_segment_main_t segment_main;
Florin Corasb384b542018-01-15 01:08:33 -0800145} echo_main_t;
Dave Barach68b0fb02017-02-28 15:15:56 -0500146
Florin Corasb384b542018-01-15 01:08:33 -0800147echo_main_t echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500148
149#if CLIB_DEBUG > 0
150#define NITER 10000
151#else
152#define NITER 4000000
153#endif
154
Florin Corasa5464812017-04-19 13:00:05 -0700155static u8 *
156format_api_error (u8 * s, va_list * args)
157{
Florin Corasb384b542018-01-15 01:08:33 -0800158 echo_main_t *em = &echo_main;
Florin Corasa5464812017-04-19 13:00:05 -0700159 i32 error = va_arg (*args, u32);
160 uword *p;
161
Florin Corasb384b542018-01-15 01:08:33 -0800162 p = hash_get (em->error_string_by_error_number, -error);
Florin Corasa5464812017-04-19 13:00:05 -0700163
164 if (p)
165 s = format (s, "%s", p[0]);
166 else
167 s = format (s, "%d", error);
168 return s;
169}
170
171static void
Florin Corasb384b542018-01-15 01:08:33 -0800172init_error_string_table (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -0700173{
Florin Corasb384b542018-01-15 01:08:33 -0800174 em->error_string_by_error_number = hash_create (0, sizeof (uword));
Florin Corasa5464812017-04-19 13:00:05 -0700175
Florin Corasb384b542018-01-15 01:08:33 -0800176#define _(n,v,s) hash_set (em->error_string_by_error_number, -v, s);
Florin Corasa5464812017-04-19 13:00:05 -0700177 foreach_vnet_api_error;
178#undef _
179
Florin Corasb384b542018-01-15 01:08:33 -0800180 hash_set (em->error_string_by_error_number, 99, "Misc");
Florin Corasa5464812017-04-19 13:00:05 -0700181}
182
Florin Coras52207f12018-07-12 14:48:06 -0700183static void handle_mq_event (session_event_t * e);
184
185static int
Florin Corasb384b542018-01-15 01:08:33 -0800186wait_for_state_change (echo_main_t * em, connection_state_t state)
Dave Barach68b0fb02017-02-28 15:15:56 -0500187{
Florin Coras52207f12018-07-12 14:48:06 -0700188 svm_msg_q_msg_t msg;
189 session_event_t *e;
190 f64 timeout;
191
Dave Barach68b0fb02017-02-28 15:15:56 -0500192#if CLIB_DEBUG > 0
193#define TIMEOUT 600.0
194#else
195#define TIMEOUT 600.0
196#endif
197
Florin Coras52207f12018-07-12 14:48:06 -0700198 timeout = clib_time_now (&em->clib_time) + TIMEOUT;
Dave Barach68b0fb02017-02-28 15:15:56 -0500199
Florin Corasb384b542018-01-15 01:08:33 -0800200 while (clib_time_now (&em->clib_time) < timeout)
Dave Barach68b0fb02017-02-28 15:15:56 -0500201 {
Florin Corasb384b542018-01-15 01:08:33 -0800202 if (em->state == state)
Florin Corase04c2992017-03-01 08:17:34 -0800203 return 0;
Florin Corasb384b542018-01-15 01:08:33 -0800204 if (em->state == STATE_FAILED)
Dave Barach68b0fb02017-02-28 15:15:56 -0500205 return -1;
Florin Corasb384b542018-01-15 01:08:33 -0800206 if (em->time_to_stop == 1)
Florin Corasf03a59a2017-06-09 21:07:32 -0700207 return 0;
Florin Coras99368312018-08-02 10:45:44 -0700208 if (!em->our_event_queue || em->state < STATE_ATTACHED)
Florin Coras52207f12018-07-12 14:48:06 -0700209 continue;
210
211 if (svm_msg_q_sub (em->our_event_queue, &msg, SVM_Q_NOWAIT, 0))
212 continue;
213 e = svm_msg_q_msg_data (em->our_event_queue, &msg);
214 handle_mq_event (e);
215 svm_msg_q_free_msg (em->our_event_queue, &msg);
Dave Barach68b0fb02017-02-28 15:15:56 -0500216 }
Florin Corasa849b7b2018-05-18 00:41:55 -0700217 clib_warning ("timeout waiting for state %d", state);
Dave Barach68b0fb02017-02-28 15:15:56 -0500218 return -1;
219}
220
Florin Coras6cf30ad2017-04-04 23:08:23 -0700221void
Florin Corasb384b542018-01-15 01:08:33 -0800222application_send_attach (echo_main_t * em)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700223{
224 vl_api_application_attach_t *bmp;
Florin Corase3e2f072018-03-04 07:24:30 -0800225 vl_api_application_tls_cert_add_t *cert_mp;
226 vl_api_application_tls_key_add_t *key_mp;
227
Florin Coras6cf30ad2017-04-04 23:08:23 -0700228 bmp = vl_msg_api_alloc (sizeof (*bmp));
Dave Barachb7b92992018-10-17 10:38:51 -0400229 clib_memset (bmp, 0, sizeof (*bmp));
Florin Coras6cf30ad2017-04-04 23:08:23 -0700230
231 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
Florin Corasb384b542018-01-15 01:08:33 -0800232 bmp->client_index = em->my_client_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700233 bmp->context = ntohl (0xfeedface);
Florin Coras52207f12018-07-12 14:48:06 -0700234 bmp->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
235 bmp->options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ADD_SEGMENT;
Dave Barach10d8cc62017-05-30 09:30:07 -0400236 bmp->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = 16;
Florin Coras8e43d042018-05-04 15:46:57 -0700237 bmp->options[APP_OPTIONS_RX_FIFO_SIZE] = em->fifo_size;
238 bmp->options[APP_OPTIONS_TX_FIFO_SIZE] = em->fifo_size;
Florin Corasff6e7692017-12-11 04:59:01 -0800239 bmp->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = 128 << 20;
240 bmp->options[APP_OPTIONS_SEGMENT_SIZE] = 256 << 20;
Florin Corasa849b7b2018-05-18 00:41:55 -0700241 bmp->options[APP_OPTIONS_EVT_QUEUE_SIZE] = 256;
Florin Corasb384b542018-01-15 01:08:33 -0800242 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
Florin Corase3e2f072018-03-04 07:24:30 -0800243
244 cert_mp = vl_msg_api_alloc (sizeof (*cert_mp) + test_srv_crt_rsa_len);
Dave Barachb7b92992018-10-17 10:38:51 -0400245 clib_memset (cert_mp, 0, sizeof (*cert_mp));
Florin Corase3e2f072018-03-04 07:24:30 -0800246 cert_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_CERT_ADD);
247 cert_mp->client_index = em->my_client_index;
248 cert_mp->context = ntohl (0xfeedface);
249 cert_mp->cert_len = clib_host_to_net_u16 (test_srv_crt_rsa_len);
Dave Barach178cf492018-11-13 16:34:13 -0500250 clib_memcpy_fast (cert_mp->cert, test_srv_crt_rsa, test_srv_crt_rsa_len);
Florin Corase3e2f072018-03-04 07:24:30 -0800251 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & cert_mp);
252
253 key_mp = vl_msg_api_alloc (sizeof (*key_mp) + test_srv_key_rsa_len);
Dave Barachb7b92992018-10-17 10:38:51 -0400254 clib_memset (key_mp, 0, sizeof (*key_mp) + test_srv_key_rsa_len);
Florin Corase3e2f072018-03-04 07:24:30 -0800255 key_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_KEY_ADD);
256 key_mp->client_index = em->my_client_index;
257 key_mp->context = ntohl (0xfeedface);
258 key_mp->key_len = clib_host_to_net_u16 (test_srv_key_rsa_len);
Dave Barach178cf492018-11-13 16:34:13 -0500259 clib_memcpy_fast (key_mp->key, test_srv_key_rsa, test_srv_key_rsa_len);
Florin Corase3e2f072018-03-04 07:24:30 -0800260 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & key_mp);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700261}
262
Florin Coras52207f12018-07-12 14:48:06 -0700263static int
Florin Corasb384b542018-01-15 01:08:33 -0800264application_attach (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -0700265{
Florin Corasb384b542018-01-15 01:08:33 -0800266 application_send_attach (em);
267 if (wait_for_state_change (em, STATE_ATTACHED))
Florin Corasa5464812017-04-19 13:00:05 -0700268 {
269 clib_warning ("timeout waiting for STATE_ATTACHED");
270 return -1;
271 }
272 return 0;
273}
274
Florin Coras6cf30ad2017-04-04 23:08:23 -0700275void
Florin Corasb384b542018-01-15 01:08:33 -0800276application_detach (echo_main_t * em)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700277{
278 vl_api_application_detach_t *bmp;
279 bmp = vl_msg_api_alloc (sizeof (*bmp));
Dave Barachb7b92992018-10-17 10:38:51 -0400280 clib_memset (bmp, 0, sizeof (*bmp));
Florin Coras6cf30ad2017-04-04 23:08:23 -0700281
282 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
Florin Corasb384b542018-01-15 01:08:33 -0800283 bmp->client_index = em->my_client_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700284 bmp->context = ntohl (0xfeedface);
Florin Corasb384b542018-01-15 01:08:33 -0800285 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
286
Florin Corasa849b7b2018-05-18 00:41:55 -0700287 DBG ("%s", "Sent detach");
Florin Corasb384b542018-01-15 01:08:33 -0800288}
289
290static int
Florin Coras99368312018-08-02 10:45:44 -0700291ssvm_segment_attach (char *name, ssvm_segment_type_t type, int fd)
Florin Corasb384b542018-01-15 01:08:33 -0800292{
293 svm_fifo_segment_create_args_t _a, *a = &_a;
Florin Corasadc74d72018-12-02 13:36:00 -0800294 svm_fifo_segment_main_t *sm = &echo_main.segment_main;
Florin Corasb384b542018-01-15 01:08:33 -0800295 int rv;
296
Dave Barachb7b92992018-10-17 10:38:51 -0400297 clib_memset (a, 0, sizeof (*a));
Florin Corasb384b542018-01-15 01:08:33 -0800298 a->segment_name = (char *) name;
Florin Corasb384b542018-01-15 01:08:33 -0800299 a->segment_type = type;
300
301 if (type == SSVM_SEGMENT_MEMFD)
Florin Coras99368312018-08-02 10:45:44 -0700302 a->memfd_fd = fd;
Florin Corasb384b542018-01-15 01:08:33 -0800303
Florin Corasadc74d72018-12-02 13:36:00 -0800304 if ((rv = svm_fifo_segment_attach (sm, a)))
Florin Corasb384b542018-01-15 01:08:33 -0800305 {
306 clib_warning ("svm_fifo_segment_attach ('%s') failed", name);
307 return rv;
308 }
309
Florin Coras99368312018-08-02 10:45:44 -0700310 vec_reset_length (a->new_segment_indices);
Florin Corasb384b542018-01-15 01:08:33 -0800311 return 0;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700312}
313
314static void
315vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t *
316 mp)
317{
Florin Corasb384b542018-01-15 01:08:33 -0800318 echo_main_t *em = &echo_main;
Florin Coras99368312018-08-02 10:45:44 -0700319 int *fds = 0;
320 u32 n_fds = 0;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700321
322 if (mp->retval)
323 {
Florin Corasa5464812017-04-19 13:00:05 -0700324 clib_warning ("attach failed: %U", format_api_error,
325 clib_net_to_host_u32 (mp->retval));
Florin Coras99368312018-08-02 10:45:44 -0700326 goto failed;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700327 }
328
329 if (mp->segment_name_length == 0)
330 {
331 clib_warning ("segment_name_length zero");
Florin Coras99368312018-08-02 10:45:44 -0700332 goto failed;
Florin Corasb384b542018-01-15 01:08:33 -0800333 }
334
335 ASSERT (mp->app_event_queue_address);
336 em->our_event_queue = uword_to_pointer (mp->app_event_queue_address,
Florin Coras3c2fed52018-07-04 04:15:05 -0700337 svm_msg_q_t *);
Florin Coras99368312018-08-02 10:45:44 -0700338
339 if (mp->n_fds)
340 {
341 vec_validate (fds, mp->n_fds);
342 vl_socket_client_recv_fd_msg (fds, mp->n_fds, 5);
343
344 if (mp->fd_flags & SESSION_FD_F_VPP_MQ_SEGMENT)
345 if (ssvm_segment_attach (0, SSVM_SEGMENT_MEMFD, fds[n_fds++]))
346 goto failed;
347
348 if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
349 if (ssvm_segment_attach ((char *) mp->segment_name,
350 SSVM_SEGMENT_MEMFD, fds[n_fds++]))
351 goto failed;
352
353 if (mp->fd_flags & SESSION_FD_F_MQ_EVENTFD)
354 svm_msg_q_set_consumer_eventfd (em->our_event_queue, fds[n_fds++]);
355
356 vec_free (fds);
357 }
358 else
359 {
360 if (ssvm_segment_attach ((char *) mp->segment_name, SSVM_SEGMENT_SHM,
361 -1))
362 goto failed;
363 }
364
Florin Corasb384b542018-01-15 01:08:33 -0800365 em->state = STATE_ATTACHED;
Florin Coras99368312018-08-02 10:45:44 -0700366 return;
367failed:
368 em->state = STATE_FAILED;
369 return;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700370}
371
372static void
373vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t *
374 mp)
375{
376 if (mp->retval)
377 clib_warning ("detach returned with err: %d", mp->retval);
Florin Corasa849b7b2018-05-18 00:41:55 -0700378 echo_main.state = STATE_DETACHED;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700379}
380
Dave Barach68b0fb02017-02-28 15:15:56 -0500381static void
Dave Barach68b0fb02017-02-28 15:15:56 -0500382stop_signal (int signum)
383{
Florin Corasb384b542018-01-15 01:08:33 -0800384 echo_main_t *um = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500385
386 um->time_to_stop = 1;
387}
388
389static void
390stats_signal (int signum)
391{
Florin Corasb384b542018-01-15 01:08:33 -0800392 echo_main_t *um = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500393
394 um->time_to_print_stats = 1;
395}
396
397static clib_error_t *
398setup_signal_handlers (void)
399{
400 signal (SIGINT, stats_signal);
401 signal (SIGQUIT, stop_signal);
402 signal (SIGTERM, stop_signal);
403
404 return 0;
405}
406
407void
408vlib_cli_output (struct vlib_main_t *vm, char *fmt, ...)
409{
410 clib_warning ("BUG");
411}
412
413int
414connect_to_vpp (char *name)
415{
Florin Corasb384b542018-01-15 01:08:33 -0800416 echo_main_t *em = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500417 api_main_t *am = &api_main;
418
Florin Corasb384b542018-01-15 01:08:33 -0800419 if (em->use_sock_api)
Florin Coras90a63982017-12-19 04:50:01 -0800420 {
Florin Corasb384b542018-01-15 01:08:33 -0800421 if (vl_socket_client_connect ((char *) em->socket_name, name,
Florin Coras90a63982017-12-19 04:50:01 -0800422 0 /* default rx, tx buffer */ ))
Florin Corasb384b542018-01-15 01:08:33 -0800423 {
424 clib_warning ("socket connect failed");
425 return -1;
426 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500427
Tomasz Kulasek97dcf5b2019-01-31 18:26:32 +0100428 if (vl_socket_client_init_shm (0, 1 /* want_pthread */ ))
Florin Corasb384b542018-01-15 01:08:33 -0800429 {
430 clib_warning ("init shm api failed");
431 return -1;
432 }
Florin Coras90a63982017-12-19 04:50:01 -0800433 }
434 else
435 {
436 if (vl_client_connect_to_vlib ("/vpe-api", name, 32) < 0)
Florin Corasb384b542018-01-15 01:08:33 -0800437 {
438 clib_warning ("shmem connect failed");
439 return -1;
440 }
Florin Coras90a63982017-12-19 04:50:01 -0800441 }
Florin Corasb384b542018-01-15 01:08:33 -0800442 em->vl_input_queue = am->shmem_hdr->vl_input_queue;
443 em->my_client_index = am->my_client_index;
Dave Barach68b0fb02017-02-28 15:15:56 -0500444 return 0;
445}
446
Florin Coras90a63982017-12-19 04:50:01 -0800447void
Florin Corasb384b542018-01-15 01:08:33 -0800448disconnect_from_vpp (echo_main_t * em)
Florin Coras90a63982017-12-19 04:50:01 -0800449{
Florin Corasb384b542018-01-15 01:08:33 -0800450 if (em->use_sock_api)
Florin Coras90a63982017-12-19 04:50:01 -0800451 vl_socket_client_disconnect ();
452 else
453 vl_client_disconnect_from_vlib ();
454}
455
Dave Barach68b0fb02017-02-28 15:15:56 -0500456static void
Florin Corase04c2992017-03-01 08:17:34 -0800457vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
Dave Barach68b0fb02017-02-28 15:15:56 -0500458{
Florin Corasadc74d72018-12-02 13:36:00 -0800459 svm_fifo_segment_main_t *sm = &echo_main.segment_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500460 svm_fifo_segment_create_args_t _a, *a = &_a;
461 int rv;
462
Dave Barachb7b92992018-10-17 10:38:51 -0400463 clib_memset (a, 0, sizeof (*a));
Dave Barach68b0fb02017-02-28 15:15:56 -0500464 a->segment_name = (char *) mp->segment_name;
465 a->segment_size = mp->segment_size;
466 /* Attach to the segment vpp created */
Florin Corasadc74d72018-12-02 13:36:00 -0800467 rv = svm_fifo_segment_attach (sm, a);
Dave Barach68b0fb02017-02-28 15:15:56 -0500468 if (rv)
469 {
470 clib_warning ("svm_fifo_segment_attach ('%s') failed",
Florin Corase04c2992017-03-01 08:17:34 -0800471 mp->segment_name);
Dave Barach68b0fb02017-02-28 15:15:56 -0500472 return;
473 }
474 clib_warning ("Mapped new segment '%s' size %d", mp->segment_name,
Florin Corase04c2992017-03-01 08:17:34 -0800475 mp->segment_size);
Dave Barach68b0fb02017-02-28 15:15:56 -0500476}
477
478static void
Florin Coras9e47ac52019-01-24 23:22:37 -0800479session_print_stats (echo_main_t * em, echo_session_t * session)
Florin Corasf03a59a2017-06-09 21:07:32 -0700480{
481 f64 deltat;
482 u64 bytes;
483
Florin Corasb384b542018-01-15 01:08:33 -0800484 deltat = clib_time_now (&em->clib_time) - session->start;
485 bytes = em->i_am_master ? session->bytes_received : em->bytes_to_send;
Florin Corasf03a59a2017-06-09 21:07:32 -0700486 fformat (stdout, "Finished in %.6f\n", deltat);
487 fformat (stdout, "%.4f Gbit/second\n", (bytes * 8.0) / deltat / 1e9);
488}
489
490static void
Florin Coras9e47ac52019-01-24 23:22:37 -0800491test_recv_bytes (echo_session_t * s, u8 * rx_buf, u32 n_read)
Dave Barach68b0fb02017-02-28 15:15:56 -0500492{
Florin Corasa849b7b2018-05-18 00:41:55 -0700493 int i;
494 for (i = 0; i < n_read; i++)
495 {
496 if (rx_buf[i] != ((s->bytes_received + i) & 0xff))
497 {
498 clib_warning ("error at byte %lld, 0x%x not 0x%x",
499 s->bytes_received + i, rx_buf[i],
500 ((s->bytes_received + i) & 0xff));
501 }
502 }
503}
Dave Barach68b0fb02017-02-28 15:15:56 -0500504
Florin Corasa849b7b2018-05-18 00:41:55 -0700505static void
Florin Coras9e47ac52019-01-24 23:22:37 -0800506recv_data_chunk (echo_main_t * em, echo_session_t * s, u8 * rx_buf)
Florin Corasa849b7b2018-05-18 00:41:55 -0700507{
Florin Coras9e47ac52019-01-24 23:22:37 -0800508 int n_to_read, n_read;
Dave Barach68b0fb02017-02-28 15:15:56 -0500509
Florin Coras9e47ac52019-01-24 23:22:37 -0800510 n_to_read = svm_fifo_max_dequeue (s->rx_fifo);
511 if (!n_to_read)
512 return;
Florin Coras6792ec02017-03-13 03:49:51 -0700513
Dave Barach68b0fb02017-02-28 15:15:56 -0500514 do
515 {
Florin Coras9e47ac52019-01-24 23:22:37 -0800516 n_read = app_recv_stream ((app_session_t *) s, rx_buf,
517 vec_len (rx_buf));
518
519 if (n_read > 0)
520 {
521 if (em->test_return_packets)
522 test_recv_bytes (s, rx_buf, n_read);
523
524 n_to_read -= n_read;
525
526 s->bytes_received += n_read;
527 s->bytes_to_receive -= n_read;
528 }
529 else
Florin Corasa849b7b2018-05-18 00:41:55 -0700530 break;
Dave Barach68b0fb02017-02-28 15:15:56 -0500531 }
Florin Corasa849b7b2018-05-18 00:41:55 -0700532 while (n_to_read > 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500533}
534
Florin Corasa849b7b2018-05-18 00:41:55 -0700535static void
Florin Coras9e47ac52019-01-24 23:22:37 -0800536send_data_chunk (echo_main_t * em, echo_session_t * s)
Florin Corasa849b7b2018-05-18 00:41:55 -0700537{
538 u64 test_buf_len, bytes_this_chunk, test_buf_offset;
Florin Corasa849b7b2018-05-18 00:41:55 -0700539 u8 *test_data = em->connect_test_data;
Florin Coras9e47ac52019-01-24 23:22:37 -0800540 int n_sent;
Florin Corasa849b7b2018-05-18 00:41:55 -0700541
542 test_buf_len = vec_len (test_data);
543 test_buf_offset = s->bytes_sent % test_buf_len;
544 bytes_this_chunk = clib_min (test_buf_len - test_buf_offset,
545 s->bytes_to_send);
Florin Corasa849b7b2018-05-18 00:41:55 -0700546
Florin Coras9e47ac52019-01-24 23:22:37 -0800547 n_sent = app_send_stream ((app_session_t *) s, test_data + test_buf_offset,
548 bytes_this_chunk, 0);
Florin Corasa849b7b2018-05-18 00:41:55 -0700549
Florin Coras9e47ac52019-01-24 23:22:37 -0800550 if (n_sent > 0)
Dave Barach68b0fb02017-02-28 15:15:56 -0500551 {
Florin Coras9e47ac52019-01-24 23:22:37 -0800552 s->bytes_to_send -= n_sent;
553 s->bytes_sent += n_sent;
Dave Barach68b0fb02017-02-28 15:15:56 -0500554 }
555}
556
Florin Corasa849b7b2018-05-18 00:41:55 -0700557/*
558 * Rx/Tx polling thread per connection
559 */
Florin Corase04c2992017-03-01 08:17:34 -0800560static void *
Florin Corasa849b7b2018-05-18 00:41:55 -0700561client_thread_fn (void *arg)
562{
563 echo_main_t *em = &echo_main;
564 static u8 *rx_buf = 0;
565 u32 session_index = *(u32 *) arg;
Florin Coras9e47ac52019-01-24 23:22:37 -0800566 echo_session_t *s;
Florin Corasa849b7b2018-05-18 00:41:55 -0700567
568 vec_validate (rx_buf, 1 << 20);
569
570 while (!em->time_to_stop && em->state != STATE_READY)
571 ;
572
573 s = pool_elt_at_index (em->sessions, session_index);
574 while (!em->time_to_stop)
575 {
Florin Coras9e47ac52019-01-24 23:22:37 -0800576 send_data_chunk (em, s);
577 recv_data_chunk (em, s, rx_buf);
Florin Corasa849b7b2018-05-18 00:41:55 -0700578 if (!s->bytes_to_send && !s->bytes_to_receive)
579 break;
580 }
581
582 DBG ("session %d done", session_index);
583 em->tx_total += s->bytes_sent;
584 em->rx_total += s->bytes_received;
585 em->n_active_clients--;
586
587 pthread_exit (0);
588}
589
Florin Coras52207f12018-07-12 14:48:06 -0700590void
591client_send_connect (echo_main_t * em)
592{
593 vl_api_connect_uri_t *cmp;
594 cmp = vl_msg_api_alloc (sizeof (*cmp));
Dave Barachb7b92992018-10-17 10:38:51 -0400595 clib_memset (cmp, 0, sizeof (*cmp));
Florin Coras52207f12018-07-12 14:48:06 -0700596
597 cmp->_vl_msg_id = ntohs (VL_API_CONNECT_URI);
598 cmp->client_index = em->my_client_index;
599 cmp->context = ntohl (0xfeedface);
600 memcpy (cmp->uri, em->connect_uri, vec_len (em->connect_uri));
601 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & cmp);
602}
603
604void
Florin Coras9e47ac52019-01-24 23:22:37 -0800605client_send_disconnect (echo_main_t * em, echo_session_t * s)
Florin Coras52207f12018-07-12 14:48:06 -0700606{
607 vl_api_disconnect_session_t *dmp;
608 dmp = vl_msg_api_alloc (sizeof (*dmp));
Dave Barachb7b92992018-10-17 10:38:51 -0400609 clib_memset (dmp, 0, sizeof (*dmp));
Florin Coras52207f12018-07-12 14:48:06 -0700610 dmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION);
611 dmp->client_index = em->my_client_index;
612 dmp->handle = s->vpp_session_handle;
613 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & dmp);
614}
615
616int
Florin Coras9e47ac52019-01-24 23:22:37 -0800617client_disconnect (echo_main_t * em, echo_session_t * s)
Florin Coras52207f12018-07-12 14:48:06 -0700618{
619 client_send_disconnect (em, s);
620 pool_put (em->sessions, s);
Dave Barachb7b92992018-10-17 10:38:51 -0400621 clib_memset (s, 0xfe, sizeof (*s));
Florin Coras52207f12018-07-12 14:48:06 -0700622 return 0;
623}
624
Dave Barach68b0fb02017-02-28 15:15:56 -0500625static void
Florin Coras9e47ac52019-01-24 23:22:37 -0800626session_bound_handler (session_bound_msg_t * mp)
627{
628 echo_main_t *em = &echo_main;
629
630 if (mp->retval)
631 {
632 clib_warning ("bind failed: %U", format_api_error,
633 clib_net_to_host_u32 (mp->retval));
634 em->state = STATE_FAILED;
635 return;
636 }
637
638 clib_warning ("listening on %U:%u", format_ip46_address, mp->lcl_ip,
639 mp->lcl_is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6, mp->lcl_port);
640 em->state = STATE_READY;
641}
642
643static void
Florin Coras52207f12018-07-12 14:48:06 -0700644session_accepted_handler (session_accepted_msg_t * mp)
645{
646 app_session_evt_t _app_evt, *app_evt = &_app_evt;
647 session_accepted_reply_msg_t *rmp;
648 svm_fifo_t *rx_fifo, *tx_fifo;
649 echo_main_t *em = &echo_main;
Florin Coras9e47ac52019-01-24 23:22:37 -0800650 echo_session_t *session;
Florin Coras52207f12018-07-12 14:48:06 -0700651 static f64 start_time;
652 u32 session_index;
653 u8 *ip_str;
654
655 if (start_time == 0.0)
656 start_time = clib_time_now (&em->clib_time);
657
658 ip_str = format (0, "%U", format_ip46_address, &mp->ip, mp->is_ip4);
659 clib_warning ("Accepted session from: %s:%d", ip_str,
660 clib_net_to_host_u16 (mp->port));
661
662 /* Allocate local session and set it up */
663 pool_get (em->sessions, session);
664 session_index = session - em->sessions;
665
666 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
667 rx_fifo->client_session_index = session_index;
668 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
669 tx_fifo->client_session_index = session_index;
670
Florin Coras9e47ac52019-01-24 23:22:37 -0800671 session->rx_fifo = rx_fifo;
672 session->tx_fifo = tx_fifo;
Florin Coras52207f12018-07-12 14:48:06 -0700673 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
674 svm_msg_q_t *);
675
676 /* Add it to lookup table */
677 hash_set (em->session_index_by_vpp_handles, mp->handle, session_index);
678
679 em->state = STATE_READY;
680
681 /* Stats printing */
682 if (pool_elts (em->sessions) && (pool_elts (em->sessions) % 20000) == 0)
683 {
684 f64 now = clib_time_now (&em->clib_time);
685 fformat (stdout, "%d active sessions in %.2f seconds, %.2f/sec...\n",
686 pool_elts (em->sessions), now - start_time,
687 (f64) pool_elts (em->sessions) / (now - start_time));
688 }
689
690 /*
691 * Send accept reply to vpp
692 */
693 app_alloc_ctrl_evt_to_vpp (session->vpp_evt_q, app_evt,
694 SESSION_CTRL_EVT_ACCEPTED_REPLY);
695 rmp = (session_accepted_reply_msg_t *) app_evt->evt->data;
696 rmp->handle = mp->handle;
697 rmp->context = mp->context;
698 app_send_ctrl_evt_to_vpp (session->vpp_evt_q, app_evt);
699
700 session->bytes_received = 0;
701 session->start = clib_time_now (&em->clib_time);
702}
703
704static void
705session_connected_handler (session_connected_msg_t * mp)
Dave Barach68b0fb02017-02-28 15:15:56 -0500706{
Florin Corasb384b542018-01-15 01:08:33 -0800707 echo_main_t *em = &echo_main;
Florin Coras9e47ac52019-01-24 23:22:37 -0800708 echo_session_t *session;
Dave Barach68b0fb02017-02-28 15:15:56 -0500709 u32 session_index;
710 svm_fifo_t *rx_fifo, *tx_fifo;
711 int rv;
712
713 if (mp->retval)
714 {
Florin Corasa5464812017-04-19 13:00:05 -0700715 clib_warning ("connection failed with code: %U", format_api_error,
716 clib_net_to_host_u32 (mp->retval));
Florin Corasb384b542018-01-15 01:08:33 -0800717 em->state = STATE_FAILED;
Dave Barach68b0fb02017-02-28 15:15:56 -0500718 return;
719 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500720
721 /*
722 * Setup session
723 */
724
Florin Corasb384b542018-01-15 01:08:33 -0800725 pool_get (em->sessions, session);
Dave Barachb7b92992018-10-17 10:38:51 -0400726 clib_memset (session, 0, sizeof (*session));
Florin Corasb384b542018-01-15 01:08:33 -0800727 session_index = session - em->sessions;
Dave Barach68b0fb02017-02-28 15:15:56 -0500728
Damjan Marion7bee80c2017-04-26 15:32:12 +0200729 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500730 rx_fifo->client_session_index = session_index;
Damjan Marion7bee80c2017-04-26 15:32:12 +0200731 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500732 tx_fifo->client_session_index = session_index;
733
Florin Coras9e47ac52019-01-24 23:22:37 -0800734 session->rx_fifo = rx_fifo;
735 session->tx_fifo = tx_fifo;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700736 session->vpp_session_handle = mp->handle;
Florin Corasb384b542018-01-15 01:08:33 -0800737 session->start = clib_time_now (&em->clib_time);
Florin Corasa849b7b2018-05-18 00:41:55 -0700738 session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
Florin Coras3c2fed52018-07-04 04:15:05 -0700739 svm_msg_q_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500740
Florin Corasb384b542018-01-15 01:08:33 -0800741 hash_set (em->session_index_by_vpp_handles, mp->handle, session_index);
Florin Corase04c2992017-03-01 08:17:34 -0800742
Florin Corasa849b7b2018-05-18 00:41:55 -0700743 /*
744 * Start RX thread
745 */
746 em->thread_args[em->n_clients_connected] = session_index;
747 rv = pthread_create (&em->client_thread_handles[em->n_clients_connected],
748 NULL /*attr */ , client_thread_fn,
749 (void *) &em->thread_args[em->n_clients_connected]);
Florin Corase04c2992017-03-01 08:17:34 -0800750 if (rv)
751 {
752 clib_warning ("pthread_create returned %d", rv);
Florin Corasa849b7b2018-05-18 00:41:55 -0700753 return;
Florin Coras6792ec02017-03-13 03:49:51 -0700754 }
755
Florin Corasa849b7b2018-05-18 00:41:55 -0700756 em->n_clients_connected += 1;
757 clib_warning ("session %u (0x%llx) connected with local ip %U port %d",
758 session_index, mp->handle, format_ip46_address, mp->lcl_ip,
759 mp->is_ip4, clib_net_to_host_u16 (mp->lcl_port));
Florin Corase04c2992017-03-01 08:17:34 -0800760}
761
Florin Coras52207f12018-07-12 14:48:06 -0700762static void
763session_disconnected_handler (session_disconnected_msg_t * mp)
Florin Corase04c2992017-03-01 08:17:34 -0800764{
Florin Coras52207f12018-07-12 14:48:06 -0700765 app_session_evt_t _app_evt, *app_evt = &_app_evt;
766 session_disconnected_reply_msg_t *rmp;
767 echo_main_t *em = &echo_main;
Florin Coras9e47ac52019-01-24 23:22:37 -0800768 echo_session_t *session = 0;
Florin Coras52207f12018-07-12 14:48:06 -0700769 uword *p;
770 int rv = 0;
Florin Corase04c2992017-03-01 08:17:34 -0800771
Florin Coras52207f12018-07-12 14:48:06 -0700772 p = hash_get (em->session_index_by_vpp_handles, mp->handle);
Florin Coras3d0fadc2018-07-17 05:35:47 -0700773 if (!p)
Florin Coras52207f12018-07-12 14:48:06 -0700774 {
775 clib_warning ("couldn't find session key %llx", mp->handle);
Florin Coras3d0fadc2018-07-17 05:35:47 -0700776 return;
Florin Coras52207f12018-07-12 14:48:06 -0700777 }
778
Florin Coras3d0fadc2018-07-17 05:35:47 -0700779 session = pool_elt_at_index (em->sessions, p[0]);
780 hash_unset (em->session_index_by_vpp_handles, mp->handle);
781 pool_put (em->sessions, session);
782
Florin Coras52207f12018-07-12 14:48:06 -0700783 app_alloc_ctrl_evt_to_vpp (session->vpp_evt_q, app_evt,
784 SESSION_CTRL_EVT_DISCONNECTED_REPLY);
785 rmp = (session_disconnected_reply_msg_t *) app_evt->evt->data;
786 rmp->retval = rv;
787 rmp->handle = mp->handle;
788 rmp->context = mp->context;
789 app_send_ctrl_evt_to_vpp (session->vpp_evt_q, app_evt);
790
Florin Coras3d0fadc2018-07-17 05:35:47 -0700791 session_print_stats (em, session);
Florin Corase04c2992017-03-01 08:17:34 -0800792}
793
Florin Coras52207f12018-07-12 14:48:06 -0700794static void
795session_reset_handler (session_reset_msg_t * mp)
Florin Corase04c2992017-03-01 08:17:34 -0800796{
Florin Coras52207f12018-07-12 14:48:06 -0700797 app_session_evt_t _app_evt, *app_evt = &_app_evt;
798 echo_main_t *em = &echo_main;
799 session_reset_reply_msg_t *rmp;
Florin Coras9e47ac52019-01-24 23:22:37 -0800800 echo_session_t *session = 0;
Florin Coras52207f12018-07-12 14:48:06 -0700801 uword *p;
802 int rv = 0;
803
804 p = hash_get (em->session_index_by_vpp_handles, mp->handle);
805
806 if (p)
807 {
808 session = pool_elt_at_index (em->sessions, p[0]);
809 clib_warning ("got reset");
810 /* Cleanup later */
811 em->time_to_stop = 1;
812 }
813 else
814 {
815 clib_warning ("couldn't find session key %llx", mp->handle);
816 return;
817 }
818
819 app_alloc_ctrl_evt_to_vpp (session->vpp_evt_q, app_evt,
820 SESSION_CTRL_EVT_RESET_REPLY);
821 rmp = (session_reset_reply_msg_t *) app_evt->evt->data;
822 rmp->retval = rv;
823 rmp->handle = mp->handle;
824 app_send_ctrl_evt_to_vpp (session->vpp_evt_q, app_evt);
Florin Corase04c2992017-03-01 08:17:34 -0800825}
826
Florin Coras52207f12018-07-12 14:48:06 -0700827static void
828handle_mq_event (session_event_t * e)
Florin Corasa5464812017-04-19 13:00:05 -0700829{
Florin Coras52207f12018-07-12 14:48:06 -0700830 switch (e->event_type)
831 {
Florin Coras9e47ac52019-01-24 23:22:37 -0800832 case SESSION_CTRL_EVT_BOUND:
833 session_bound_handler ((session_bound_msg_t *) e->data);
834 break;
Florin Coras52207f12018-07-12 14:48:06 -0700835 case SESSION_CTRL_EVT_ACCEPTED:
836 session_accepted_handler ((session_accepted_msg_t *) e->data);
837 break;
838 case SESSION_CTRL_EVT_CONNECTED:
839 session_connected_handler ((session_connected_msg_t *) e->data);
840 break;
841 case SESSION_CTRL_EVT_DISCONNECTED:
842 session_disconnected_handler ((session_disconnected_msg_t *) e->data);
843 break;
844 case SESSION_CTRL_EVT_RESET:
845 session_reset_handler ((session_reset_msg_t *) e->data);
846 break;
847 default:
848 clib_warning ("unhandled %u", e->event_type);
849 }
Florin Corasa5464812017-04-19 13:00:05 -0700850}
851
Florin Corase04c2992017-03-01 08:17:34 -0800852static void
Florin Corasa849b7b2018-05-18 00:41:55 -0700853clients_run (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -0800854{
Florin Corasa849b7b2018-05-18 00:41:55 -0700855 f64 start_time, deltat, timeout = 100.0;
Florin Coras3c2fed52018-07-04 04:15:05 -0700856 svm_msg_q_msg_t msg;
Florin Coras52207f12018-07-12 14:48:06 -0700857 session_event_t *e;
Florin Coras9e47ac52019-01-24 23:22:37 -0800858 echo_session_t *s;
Florin Corase04c2992017-03-01 08:17:34 -0800859 int i;
860
Florin Corase04c2992017-03-01 08:17:34 -0800861 /* Init test data */
Florin Coras8e43d042018-05-04 15:46:57 -0700862 vec_validate (em->connect_test_data, 1024 * 1024 - 1);
Florin Corasb384b542018-01-15 01:08:33 -0800863 for (i = 0; i < vec_len (em->connect_test_data); i++)
864 em->connect_test_data[i] = i & 0xff;
Florin Corase04c2992017-03-01 08:17:34 -0800865
Florin Corasa849b7b2018-05-18 00:41:55 -0700866 /*
867 * Attach and connect the clients
868 */
869 if (application_attach (em))
870 return;
Florin Corase04c2992017-03-01 08:17:34 -0800871
Florin Corasa849b7b2018-05-18 00:41:55 -0700872 for (i = 0; i < em->n_clients; i++)
873 client_send_connect (em);
874
875 start_time = clib_time_now (&em->clib_time);
876 while (em->n_clients_connected < em->n_clients
877 && (clib_time_now (&em->clib_time) - start_time < timeout)
878 && em->state != STATE_FAILED)
Florin Coras52207f12018-07-12 14:48:06 -0700879
880 {
881 svm_msg_q_sub (em->our_event_queue, &msg, SVM_Q_WAIT, 0);
882 e = svm_msg_q_msg_data (em->our_event_queue, &msg);
883 handle_mq_event (e);
884 svm_msg_q_free_msg (em->our_event_queue, &msg);
885 }
Florin Corasa849b7b2018-05-18 00:41:55 -0700886
887 if (em->n_clients_connected != em->n_clients)
888 {
889 clib_warning ("failed to initialize all connections");
890 return;
891 }
892
893 /*
894 * Initialize connections
895 */
896 for (i = 0; i < em->n_clients; i++)
897 {
898 s = pool_elt_at_index (em->sessions, i);
899 s->bytes_to_send = em->bytes_to_send;
900 if (!em->no_return)
901 s->bytes_to_receive = em->bytes_to_send;
902 }
903 em->n_active_clients = em->n_clients_connected;
904
905 /*
906 * Wait for client threads to send the data
907 */
908 start_time = clib_time_now (&em->clib_time);
909 em->state = STATE_READY;
910 while (em->n_active_clients)
Florin Coras3c2fed52018-07-04 04:15:05 -0700911 if (!svm_msg_q_is_empty (em->our_event_queue))
912 {
913 if (svm_msg_q_sub (em->our_event_queue, &msg, SVM_Q_WAIT, 0))
914 {
915 clib_warning ("svm msg q returned");
Florin Coras52207f12018-07-12 14:48:06 -0700916 continue;
Florin Coras3c2fed52018-07-04 04:15:05 -0700917 }
Florin Coras52207f12018-07-12 14:48:06 -0700918 e = svm_msg_q_msg_data (em->our_event_queue, &msg);
Florin Corasfe97da32019-03-06 10:09:04 -0800919 if (e->event_type != SESSION_IO_EVT_RX)
Florin Coras52207f12018-07-12 14:48:06 -0700920 handle_mq_event (e);
921 svm_msg_q_free_msg (em->our_event_queue, &msg);
Florin Coras3c2fed52018-07-04 04:15:05 -0700922 }
Florin Corasa849b7b2018-05-18 00:41:55 -0700923
924 for (i = 0; i < em->n_clients; i++)
925 {
926 s = pool_elt_at_index (em->sessions, i);
927 client_disconnect (em, s);
928 }
929
930 /*
931 * Stats and detach
932 */
933 deltat = clib_time_now (&em->clib_time) - start_time;
934 fformat (stdout, "%lld bytes (%lld mbytes, %lld gbytes) in %.2f seconds\n",
935 em->tx_total, em->tx_total / (1ULL << 20),
936 em->tx_total / (1ULL << 30), deltat);
937 fformat (stdout, "%.4f Gbit/second\n", (em->tx_total * 8.0) / deltat / 1e9);
938
Florin Corasb384b542018-01-15 01:08:33 -0800939 application_detach (em);
Florin Corase04c2992017-03-01 08:17:34 -0800940}
941
942static void
943vl_api_bind_uri_reply_t_handler (vl_api_bind_uri_reply_t * mp)
944{
Florin Corasb384b542018-01-15 01:08:33 -0800945 echo_main_t *em = &echo_main;
Florin Corase04c2992017-03-01 08:17:34 -0800946
947 if (mp->retval)
948 {
flyingeagle23a07779f2017-04-26 20:22:04 +0800949 clib_warning ("bind failed: %U", format_api_error,
Florin Corasa5464812017-04-19 13:00:05 -0700950 clib_net_to_host_u32 (mp->retval));
Florin Corasb384b542018-01-15 01:08:33 -0800951 em->state = STATE_FAILED;
Florin Corase04c2992017-03-01 08:17:34 -0800952 return;
953 }
954
Florin Corasb384b542018-01-15 01:08:33 -0800955 em->state = STATE_READY;
Dave Barach68b0fb02017-02-28 15:15:56 -0500956}
957
Dave Barach68b0fb02017-02-28 15:15:56 -0500958static void
Florin Corase04c2992017-03-01 08:17:34 -0800959vl_api_unbind_uri_reply_t_handler (vl_api_unbind_uri_reply_t * mp)
Dave Barach68b0fb02017-02-28 15:15:56 -0500960{
Florin Corasb384b542018-01-15 01:08:33 -0800961 echo_main_t *em = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500962
963 if (mp->retval != 0)
Florin Corase04c2992017-03-01 08:17:34 -0800964 clib_warning ("returned %d", ntohl (mp->retval));
Dave Barach68b0fb02017-02-28 15:15:56 -0500965
Florin Corasb384b542018-01-15 01:08:33 -0800966 em->state = STATE_START;
Dave Barach68b0fb02017-02-28 15:15:56 -0500967}
968
Florin Coras6cf30ad2017-04-04 23:08:23 -0700969u8 *
970format_ip4_address (u8 * s, va_list * args)
971{
972 u8 *a = va_arg (*args, u8 *);
973 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
974}
975
976u8 *
977format_ip6_address (u8 * s, va_list * args)
978{
979 ip6_address_t *a = va_arg (*args, ip6_address_t *);
980 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
981
982 i_max_n_zero = ARRAY_LEN (a->as_u16);
983 max_n_zeros = 0;
984 i_first_zero = i_max_n_zero;
985 n_zeros = 0;
986 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
987 {
988 u32 is_zero = a->as_u16[i] == 0;
989 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
990 {
991 i_first_zero = i;
992 n_zeros = 0;
993 }
994 n_zeros += is_zero;
995 if ((!is_zero && n_zeros > max_n_zeros)
996 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
997 {
998 i_max_n_zero = i_first_zero;
999 max_n_zeros = n_zeros;
1000 i_first_zero = ARRAY_LEN (a->as_u16);
1001 n_zeros = 0;
1002 }
1003 }
1004
1005 last_double_colon = 0;
1006 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
1007 {
1008 if (i == i_max_n_zero && max_n_zeros > 1)
1009 {
1010 s = format (s, "::");
1011 i += max_n_zeros - 1;
1012 last_double_colon = 1;
1013 }
1014 else
1015 {
1016 s = format (s, "%s%x",
1017 (last_double_colon || i == 0) ? "" : ":",
1018 clib_net_to_host_u16 (a->as_u16[i]));
1019 last_double_colon = 0;
1020 }
1021 }
1022
1023 return s;
1024}
1025
1026/* Format an IP46 address. */
1027u8 *
1028format_ip46_address (u8 * s, va_list * args)
1029{
1030 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
1031 ip46_type_t type = va_arg (*args, ip46_type_t);
1032 int is_ip4 = 1;
1033
1034 switch (type)
1035 {
1036 case IP46_TYPE_ANY:
1037 is_ip4 = ip46_address_is_ip4 (ip46);
1038 break;
1039 case IP46_TYPE_IP4:
1040 is_ip4 = 1;
1041 break;
1042 case IP46_TYPE_IP6:
1043 is_ip4 = 0;
1044 break;
1045 }
1046
1047 return is_ip4 ?
1048 format (s, "%U", format_ip4_address, &ip46->ip4) :
1049 format (s, "%U", format_ip6_address, &ip46->ip6);
1050}
1051
Dave Barach68b0fb02017-02-28 15:15:56 -05001052static void
Florin Coras9e47ac52019-01-24 23:22:37 -08001053server_handle_rx (echo_main_t * em, session_event_t * e)
Dave Barach68b0fb02017-02-28 15:15:56 -05001054{
Florin Coras9e47ac52019-01-24 23:22:37 -08001055 int n_read, max_dequeue, n_sent;
1056 u32 offset, to_dequeue;
1057 echo_session_t *s;
Florin Corase04c2992017-03-01 08:17:34 -08001058
Florin Corasc0737e92019-03-04 14:19:39 -08001059 s = pool_elt_at_index (em->sessions, e->session_index);
Florin Corase04c2992017-03-01 08:17:34 -08001060
Florin Coras9e47ac52019-01-24 23:22:37 -08001061 /* Clear event only once. Otherwise, if we do it in the loop by calling
1062 * app_recv_stream, we may end up with a lot of unhandled rx events on the
1063 * message queue */
1064 svm_fifo_unset_event (s->rx_fifo);
Florin Coras6792ec02017-03-13 03:49:51 -07001065
Florin Coras9e47ac52019-01-24 23:22:37 -08001066 max_dequeue = svm_fifo_max_dequeue (s->rx_fifo);
Florin Corasa849b7b2018-05-18 00:41:55 -07001067 if (PREDICT_FALSE (!max_dequeue))
1068 return;
Florin Coras6792ec02017-03-13 03:49:51 -07001069
Florin Corase04c2992017-03-01 08:17:34 -08001070 do
1071 {
Florin Coras9e47ac52019-01-24 23:22:37 -08001072 /* The options here are to limit ourselves to max_dequeue or read
1073 * even the data that was enqueued while we were dequeueing and which
1074 * now has an rx event in the mq. Either of the two work. */
1075 to_dequeue = clib_min (max_dequeue, vec_len (em->rx_buf));
1076 n_read = app_recv_stream_raw (s->rx_fifo, em->rx_buf, to_dequeue,
1077 0 /* clear evt */ , 0 /* peek */ );
Florin Coras6792ec02017-03-13 03:49:51 -07001078 if (n_read > 0)
Florin Corase04c2992017-03-01 08:17:34 -08001079 {
Florin Corasf03a59a2017-06-09 21:07:32 -07001080 max_dequeue -= n_read;
Florin Coras9e47ac52019-01-24 23:22:37 -08001081 s->bytes_received += n_read;
Florin Corasf03a59a2017-06-09 21:07:32 -07001082 }
Florin Coras9e47ac52019-01-24 23:22:37 -08001083 else
1084 break;
Florin Corasf03a59a2017-06-09 21:07:32 -07001085
1086 /* Reflect if a non-drop session */
Florin Coras8e43d042018-05-04 15:46:57 -07001087 if (!em->no_return && n_read > 0)
Florin Corasf03a59a2017-06-09 21:07:32 -07001088 {
1089 offset = 0;
Florin Corase04c2992017-03-01 08:17:34 -08001090 do
1091 {
Florin Coras9e47ac52019-01-24 23:22:37 -08001092 n_sent = app_send_stream ((app_session_t *) s,
1093 &em->rx_buf[offset],
1094 n_read, SVM_Q_WAIT);
1095 if (n_sent > 0)
Florin Corasf03a59a2017-06-09 21:07:32 -07001096 {
Florin Coras9e47ac52019-01-24 23:22:37 -08001097 n_read -= n_sent;
1098 offset += n_sent;
Florin Corasf03a59a2017-06-09 21:07:32 -07001099 }
Florin Corase04c2992017-03-01 08:17:34 -08001100 }
Florin Coras9e47ac52019-01-24 23:22:37 -08001101 while ((n_sent <= 0 || n_read > 0) && !em->time_to_stop);
Florin Corase04c2992017-03-01 08:17:34 -08001102 }
Florin Corase04c2992017-03-01 08:17:34 -08001103 }
Florin Coras9e47ac52019-01-24 23:22:37 -08001104 while (max_dequeue > 0 && !em->time_to_stop);
Florin Corase04c2992017-03-01 08:17:34 -08001105}
1106
Florin Coras52207f12018-07-12 14:48:06 -07001107static void
Florin Coras9e47ac52019-01-24 23:22:37 -08001108server_handle_mq (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -08001109{
Florin Coras3c2fed52018-07-04 04:15:05 -07001110 svm_msg_q_msg_t msg;
Florin Coras52207f12018-07-12 14:48:06 -07001111 session_event_t *e;
Florin Corase04c2992017-03-01 08:17:34 -08001112
1113 while (1)
1114 {
Florin Coras3c2fed52018-07-04 04:15:05 -07001115 svm_msg_q_sub (em->our_event_queue, &msg, SVM_Q_WAIT, 0);
1116 e = svm_msg_q_msg_data (em->our_event_queue, &msg);
Florin Corase04c2992017-03-01 08:17:34 -08001117 switch (e->event_type)
1118 {
Florin Corasc0737e92019-03-04 14:19:39 -08001119 case SESSION_IO_EVT_RX:
Florin Coras9e47ac52019-01-24 23:22:37 -08001120 server_handle_rx (em, e);
Florin Corase04c2992017-03-01 08:17:34 -08001121 break;
Florin Corase04c2992017-03-01 08:17:34 -08001122 default:
Florin Coras52207f12018-07-12 14:48:06 -07001123 handle_mq_event (e);
Florin Corase04c2992017-03-01 08:17:34 -08001124 break;
1125 }
Florin Corasb384b542018-01-15 01:08:33 -08001126 if (PREDICT_FALSE (em->time_to_stop == 1))
Florin Corase04c2992017-03-01 08:17:34 -08001127 break;
Florin Corasb384b542018-01-15 01:08:33 -08001128 if (PREDICT_FALSE (em->time_to_print_stats == 1))
Florin Corase04c2992017-03-01 08:17:34 -08001129 {
Florin Corasb384b542018-01-15 01:08:33 -08001130 em->time_to_print_stats = 0;
1131 fformat (stdout, "%d connections\n", pool_elts (em->sessions));
Florin Corase04c2992017-03-01 08:17:34 -08001132 }
Florin Coras3c2fed52018-07-04 04:15:05 -07001133 svm_msg_q_free_msg (em->our_event_queue, &msg);
Florin Corase04c2992017-03-01 08:17:34 -08001134 }
1135}
1136
1137void
Florin Corasb384b542018-01-15 01:08:33 -08001138server_send_listen (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -08001139{
1140 vl_api_bind_uri_t *bmp;
Florin Corase04c2992017-03-01 08:17:34 -08001141 bmp = vl_msg_api_alloc (sizeof (*bmp));
Dave Barachb7b92992018-10-17 10:38:51 -04001142 clib_memset (bmp, 0, sizeof (*bmp));
Florin Corase04c2992017-03-01 08:17:34 -08001143
1144 bmp->_vl_msg_id = ntohs (VL_API_BIND_URI);
Florin Corasb384b542018-01-15 01:08:33 -08001145 bmp->client_index = em->my_client_index;
Florin Corase04c2992017-03-01 08:17:34 -08001146 bmp->context = ntohl (0xfeedface);
Florin Corasb384b542018-01-15 01:08:33 -08001147 memcpy (bmp->uri, em->uri, vec_len (em->uri));
1148 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
Florin Corase04c2992017-03-01 08:17:34 -08001149}
1150
Florin Corasa5464812017-04-19 13:00:05 -07001151int
Florin Corasb384b542018-01-15 01:08:33 -08001152server_listen (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -07001153{
Florin Corasb384b542018-01-15 01:08:33 -08001154 server_send_listen (em);
1155 if (wait_for_state_change (em, STATE_READY))
Florin Corasa5464812017-04-19 13:00:05 -07001156 {
1157 clib_warning ("timeout waiting for STATE_READY");
1158 return -1;
1159 }
1160 return 0;
1161}
1162
Florin Corase04c2992017-03-01 08:17:34 -08001163void
Florin Corasb384b542018-01-15 01:08:33 -08001164server_send_unbind (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -08001165{
1166 vl_api_unbind_uri_t *ump;
1167
1168 ump = vl_msg_api_alloc (sizeof (*ump));
Dave Barachb7b92992018-10-17 10:38:51 -04001169 clib_memset (ump, 0, sizeof (*ump));
Florin Corase04c2992017-03-01 08:17:34 -08001170
1171 ump->_vl_msg_id = ntohs (VL_API_UNBIND_URI);
Florin Corasb384b542018-01-15 01:08:33 -08001172 ump->client_index = em->my_client_index;
1173 memcpy (ump->uri, em->uri, vec_len (em->uri));
1174 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & ump);
Florin Corase04c2992017-03-01 08:17:34 -08001175}
1176
Florin Corasa5464812017-04-19 13:00:05 -07001177int
Florin Corasb384b542018-01-15 01:08:33 -08001178server_unbind (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -07001179{
Florin Corasb384b542018-01-15 01:08:33 -08001180 server_send_unbind (em);
1181 if (wait_for_state_change (em, STATE_START))
Florin Corasa5464812017-04-19 13:00:05 -07001182 {
1183 clib_warning ("timeout waiting for STATE_START");
1184 return -1;
1185 }
1186 return 0;
1187}
1188
Florin Corase04c2992017-03-01 08:17:34 -08001189void
Florin Corasb384b542018-01-15 01:08:33 -08001190server_run (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -08001191{
Florin Coras9e47ac52019-01-24 23:22:37 -08001192 echo_session_t *session;
Florin Coras90a63982017-12-19 04:50:01 -08001193 int i;
1194
1195 /* $$$$ hack preallocation */
1196 for (i = 0; i < 200000; i++)
1197 {
Florin Corasb384b542018-01-15 01:08:33 -08001198 pool_get (em->sessions, session);
Dave Barachb7b92992018-10-17 10:38:51 -04001199 clib_memset (session, 0, sizeof (*session));
Florin Coras90a63982017-12-19 04:50:01 -08001200 }
1201 for (i = 0; i < 200000; i++)
Florin Corasb384b542018-01-15 01:08:33 -08001202 pool_put_index (em->sessions, i);
Florin Coras90a63982017-12-19 04:50:01 -08001203
Florin Corasb384b542018-01-15 01:08:33 -08001204 if (application_attach (em))
Florin Corasa5464812017-04-19 13:00:05 -07001205 return;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001206
Dave Barach68b0fb02017-02-28 15:15:56 -05001207 /* Bind to uri */
Florin Corasb384b542018-01-15 01:08:33 -08001208 if (server_listen (em))
Florin Corasa5464812017-04-19 13:00:05 -07001209 return;
Dave Barach68b0fb02017-02-28 15:15:56 -05001210
1211 /* Enter handle event loop */
Florin Coras9e47ac52019-01-24 23:22:37 -08001212 server_handle_mq (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001213
1214 /* Cleanup */
Florin Corasb384b542018-01-15 01:08:33 -08001215 server_send_unbind (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001216
Florin Corasb384b542018-01-15 01:08:33 -08001217 application_detach (em);
Florin Coras6cf30ad2017-04-04 23:08:23 -07001218
Dave Barach68b0fb02017-02-28 15:15:56 -05001219 fformat (stdout, "Test complete...\n");
1220}
1221
Florin Corase69f4952017-03-07 10:06:24 -08001222static void
1223vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t *
1224 mp)
1225{
Florin Corasb384b542018-01-15 01:08:33 -08001226 echo_main_t *em = &echo_main;
Florin Corasa849b7b2018-05-18 00:41:55 -07001227 uword *p;
Florin Coras6792ec02017-03-13 03:49:51 -07001228
Florin Corasf03a59a2017-06-09 21:07:32 -07001229 if (mp->retval)
1230 {
1231 clib_warning ("vpp complained about disconnect: %d",
1232 ntohl (mp->retval));
Florin Corasa849b7b2018-05-18 00:41:55 -07001233 return;
Florin Corasf03a59a2017-06-09 21:07:32 -07001234 }
1235
Florin Corasb384b542018-01-15 01:08:33 -08001236 em->state = STATE_START;
Florin Corasa849b7b2018-05-18 00:41:55 -07001237
1238 p = hash_get (em->session_index_by_vpp_handles, mp->handle);
1239 if (p)
1240 {
1241 hash_unset (em->session_index_by_vpp_handles, mp->handle);
1242 }
1243 else
1244 {
1245 clib_warning ("couldn't find session key %llx", mp->handle);
1246 }
Florin Corase69f4952017-03-07 10:06:24 -08001247}
1248
Florin Corase3e2f072018-03-04 07:24:30 -08001249static void
1250 vl_api_application_tls_cert_add_reply_t_handler
1251 (vl_api_application_tls_cert_add_reply_t * mp)
1252{
1253 if (mp->retval)
1254 clib_warning ("failed to add tls cert");
1255}
1256
1257static void
1258 vl_api_application_tls_key_add_reply_t_handler
1259 (vl_api_application_tls_key_add_reply_t * mp)
1260{
1261 if (mp->retval)
1262 clib_warning ("failed to add tls key");
1263}
1264
1265#define foreach_tcp_echo_msg \
1266_(BIND_URI_REPLY, bind_uri_reply) \
1267_(UNBIND_URI_REPLY, unbind_uri_reply) \
Florin Corase3e2f072018-03-04 07:24:30 -08001268_(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \
Florin Corase3e2f072018-03-04 07:24:30 -08001269_(APPLICATION_ATTACH_REPLY, application_attach_reply) \
1270_(APPLICATION_DETACH_REPLY, application_detach_reply) \
1271_(MAP_ANOTHER_SEGMENT, map_another_segment) \
1272_(APPLICATION_TLS_CERT_ADD_REPLY, application_tls_cert_add_reply) \
1273_(APPLICATION_TLS_KEY_ADD_REPLY, application_tls_key_add_reply) \
Dave Barach68b0fb02017-02-28 15:15:56 -05001274
1275void
Florin Corasb384b542018-01-15 01:08:33 -08001276tcp_echo_api_hookup (echo_main_t * em)
Dave Barach68b0fb02017-02-28 15:15:56 -05001277{
1278#define _(N,n) \
1279 vl_msg_api_set_handlers(VL_API_##N, #n, \
1280 vl_api_##n##_t_handler, \
1281 vl_noop_handler, \
1282 vl_api_##n##_t_endian, \
1283 vl_api_##n##_t_print, \
1284 sizeof(vl_api_##n##_t), 1);
Florin Corasb384b542018-01-15 01:08:33 -08001285 foreach_tcp_echo_msg;
Dave Barach68b0fb02017-02-28 15:15:56 -05001286#undef _
1287}
1288
1289int
1290main (int argc, char **argv)
1291{
Florin Coras8e43d042018-05-04 15:46:57 -07001292 int i_am_server = 1, test_return_packets = 0;
Florin Corasb384b542018-01-15 01:08:33 -08001293 echo_main_t *em = &echo_main;
Florin Corasadc74d72018-12-02 13:36:00 -08001294 svm_fifo_segment_main_t *sm = &em->segment_main;
Dave Barach68b0fb02017-02-28 15:15:56 -05001295 unformat_input_t _argv, *a = &_argv;
1296 u8 *chroot_prefix;
Dave Barach6a5adc32018-07-04 10:56:23 -04001297 u8 *uri = 0;
Florin Corase69f4952017-03-07 10:06:24 -08001298 u8 *bind_uri = (u8 *) "tcp://0.0.0.0/1234";
Florin Coras8e43d042018-05-04 15:46:57 -07001299 u8 *connect_uri = (u8 *) "tcp://6.0.1.1/1234";
Florin Coras6cf30ad2017-04-04 23:08:23 -07001300 u64 bytes_to_send = 64 << 10, mbytes;
Florin Corasb384b542018-01-15 01:08:33 -08001301 char *app_name;
Dave Barach68b0fb02017-02-28 15:15:56 -05001302 u32 tmp;
Dave Barach68b0fb02017-02-28 15:15:56 -05001303
Dave Barach6a5adc32018-07-04 10:56:23 -04001304 clib_mem_init_thread_safe (0, 256 << 20);
Dave Barach68b0fb02017-02-28 15:15:56 -05001305
Dave Barachb7b92992018-10-17 10:38:51 -04001306 clib_memset (em, 0, sizeof (*em));
Florin Corasb384b542018-01-15 01:08:33 -08001307 em->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
Florin Corasb384b542018-01-15 01:08:33 -08001308 em->my_pid = getpid ();
1309 em->configured_segment_size = 1 << 20;
1310 em->socket_name = 0;
1311 em->use_sock_api = 1;
Florin Coras8e43d042018-05-04 15:46:57 -07001312 em->fifo_size = 64 << 10;
Florin Corasa849b7b2018-05-18 00:41:55 -07001313 em->n_clients = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -05001314
Florin Corasb384b542018-01-15 01:08:33 -08001315 clib_time_init (&em->clib_time);
1316 init_error_string_table (em);
David Johnsond9818dd2018-12-14 14:53:41 -05001317 svm_fifo_segment_main_init (sm, HIGH_SEGMENT_BASEVA, 20);
Dave Barach68b0fb02017-02-28 15:15:56 -05001318 unformat_init_command_line (a, argv);
1319
1320 while (unformat_check_input (a) != UNFORMAT_END_OF_INPUT)
1321 {
1322 if (unformat (a, "chroot prefix %s", &chroot_prefix))
Florin Corase04c2992017-03-01 08:17:34 -08001323 {
1324 vl_set_memory_root_path ((char *) chroot_prefix);
1325 }
Florin Corase69f4952017-03-07 10:06:24 -08001326 else if (unformat (a, "uri %s", &uri))
Florin Corase04c2992017-03-01 08:17:34 -08001327 ;
Dave Barach68b0fb02017-02-28 15:15:56 -05001328 else if (unformat (a, "segment-size %dM", &tmp))
Florin Corasb384b542018-01-15 01:08:33 -08001329 em->configured_segment_size = tmp << 20;
Dave Barach68b0fb02017-02-28 15:15:56 -05001330 else if (unformat (a, "segment-size %dG", &tmp))
Florin Corasb384b542018-01-15 01:08:33 -08001331 em->configured_segment_size = tmp << 30;
Florin Coras8e43d042018-05-04 15:46:57 -07001332 else if (unformat (a, "server"))
1333 i_am_server = 1;
1334 else if (unformat (a, "client"))
1335 i_am_server = 0;
1336 else if (unformat (a, "no-return"))
1337 em->no_return = 1;
Florin Corase04c2992017-03-01 08:17:34 -08001338 else if (unformat (a, "test"))
1339 test_return_packets = 1;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001340 else if (unformat (a, "mbytes %lld", &mbytes))
Florin Coras6792ec02017-03-13 03:49:51 -07001341 {
1342 bytes_to_send = mbytes << 20;
1343 }
Florin Coras6cf30ad2017-04-04 23:08:23 -07001344 else if (unformat (a, "gbytes %lld", &mbytes))
1345 {
1346 bytes_to_send = mbytes << 30;
1347 }
Florin Corasb384b542018-01-15 01:08:33 -08001348 else if (unformat (a, "socket-name %s", &em->socket_name))
Florin Coras90a63982017-12-19 04:50:01 -08001349 ;
1350 else if (unformat (a, "use-svm-api"))
Florin Corasb384b542018-01-15 01:08:33 -08001351 em->use_sock_api = 0;
Florin Coras8e43d042018-05-04 15:46:57 -07001352 else if (unformat (a, "fifo-size %d", &tmp))
1353 em->fifo_size = tmp << 10;
Florin Corasa849b7b2018-05-18 00:41:55 -07001354 else if (unformat (a, "nclients %d", &em->n_clients))
1355 ;
Dave Barach68b0fb02017-02-28 15:15:56 -05001356 else
Florin Corase04c2992017-03-01 08:17:34 -08001357 {
Jerome Tollet61f79122018-06-04 08:31:33 +01001358 fformat (stderr, "%s: usage [master|slave]\n", argv[0]);
Florin Corase04c2992017-03-01 08:17:34 -08001359 exit (1);
1360 }
Dave Barach68b0fb02017-02-28 15:15:56 -05001361 }
1362
Florin Corasb384b542018-01-15 01:08:33 -08001363 if (!em->socket_name)
1364 em->socket_name = format (0, "%s%c", API_SOCKET_FILE, 0);
Florin Coras90a63982017-12-19 04:50:01 -08001365
Florin Corase69f4952017-03-07 10:06:24 -08001366 if (uri)
1367 {
Florin Corasb384b542018-01-15 01:08:33 -08001368 em->uri = format (0, "%s%c", uri, 0);
1369 em->connect_uri = format (0, "%s%c", uri, 0);
Florin Corase69f4952017-03-07 10:06:24 -08001370 }
1371 else
1372 {
Florin Corasb384b542018-01-15 01:08:33 -08001373 em->uri = format (0, "%s%c", bind_uri, 0);
1374 em->connect_uri = format (0, "%s%c", connect_uri, 0);
Florin Corase69f4952017-03-07 10:06:24 -08001375 }
1376
Florin Coras8e43d042018-05-04 15:46:57 -07001377 em->i_am_master = i_am_server;
Florin Corasb384b542018-01-15 01:08:33 -08001378 em->test_return_packets = test_return_packets;
1379 em->bytes_to_send = bytes_to_send;
1380 em->time_to_stop = 0;
Florin Coras9e47ac52019-01-24 23:22:37 -08001381 vec_validate (em->rx_buf, 4 << 20);
Florin Corasa849b7b2018-05-18 00:41:55 -07001382 vec_validate (em->client_thread_handles, em->n_clients - 1);
1383 vec_validate (em->thread_args, em->n_clients - 1);
Dave Barach68b0fb02017-02-28 15:15:56 -05001384
Florin Corase04c2992017-03-01 08:17:34 -08001385 setup_signal_handlers ();
Florin Corasb384b542018-01-15 01:08:33 -08001386 tcp_echo_api_hookup (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001387
Florin Coras8e43d042018-05-04 15:46:57 -07001388 app_name = i_am_server ? "tcp_echo_server" : "tcp_echo_client";
Florin Corasb384b542018-01-15 01:08:33 -08001389 if (connect_to_vpp (app_name) < 0)
Dave Barach68b0fb02017-02-28 15:15:56 -05001390 {
1391 svm_region_exit ();
1392 fformat (stderr, "Couldn't connect to vpe, exiting...\n");
1393 exit (1);
1394 }
1395
Florin Coras8e43d042018-05-04 15:46:57 -07001396 if (i_am_server == 0)
Florin Corasa849b7b2018-05-18 00:41:55 -07001397 clients_run (em);
Florin Coras90a63982017-12-19 04:50:01 -08001398 else
Florin Corasb384b542018-01-15 01:08:33 -08001399 server_run (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001400
Florin Corasa849b7b2018-05-18 00:41:55 -07001401 /* Make sure detach finishes */
1402 wait_for_state_change (em, STATE_DETACHED);
1403
Florin Corasb384b542018-01-15 01:08:33 -08001404 disconnect_from_vpp (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001405 exit (0);
1406}
Florin Corase04c2992017-03-01 08:17:34 -08001407
1408/*
1409 * fd.io coding-style-patch-verification: ON
1410 *
1411 * Local Variables:
1412 * eval: (c-set-style "gnu")
1413 * End:
1414 */