blob: 30eb54dcddab55957a4596dc47fd8a115c15c284 [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
Dave Barach68b0fb02017-02-28 15:15:56 -050041typedef struct
42{
Florin Corase04c2992017-03-01 08:17:34 -080043 svm_fifo_t *server_rx_fifo;
44 svm_fifo_t *server_tx_fifo;
Dave Barach68b0fb02017-02-28 15:15:56 -050045
Florin Corasa5464812017-04-19 13:00:05 -070046 u64 vpp_session_handle;
Florin Corasf03a59a2017-06-09 21:07:32 -070047 u64 bytes_received;
48 f64 start;
Dave Barach68b0fb02017-02-28 15:15:56 -050049} session_t;
50
51typedef enum
52{
53 STATE_START,
Florin Corasa5464812017-04-19 13:00:05 -070054 STATE_ATTACHED,
Dave Barach68b0fb02017-02-28 15:15:56 -050055 STATE_READY,
56 STATE_DISCONNECTING,
57 STATE_FAILED
58} connection_state_t;
59
60typedef struct
61{
62 /* vpe input queue */
63 unix_shared_memory_queue_t *vl_input_queue;
64
65 /* API client handle */
66 u32 my_client_index;
67
68 /* The URI we're playing with */
Florin Corase04c2992017-03-01 08:17:34 -080069 u8 *uri;
Dave Barach68b0fb02017-02-28 15:15:56 -050070
71 /* Session pool */
Florin Corase04c2992017-03-01 08:17:34 -080072 session_t *sessions;
Dave Barach68b0fb02017-02-28 15:15:56 -050073
74 /* Hash table for disconnect processing */
Florin Corase04c2992017-03-01 08:17:34 -080075 uword *session_index_by_vpp_handles;
Dave Barach68b0fb02017-02-28 15:15:56 -050076
77 /* intermediate rx buffer */
Florin Corase04c2992017-03-01 08:17:34 -080078 u8 *rx_buf;
Dave Barach68b0fb02017-02-28 15:15:56 -050079
80 /* URI for slave's connect */
Florin Corase04c2992017-03-01 08:17:34 -080081 u8 *connect_uri;
Dave Barach68b0fb02017-02-28 15:15:56 -050082
83 u32 connected_session_index;
84
85 int i_am_master;
86
87 /* drop all packets */
88 int drop_packets;
89
90 /* Our event queue */
Florin Corase04c2992017-03-01 08:17:34 -080091 unix_shared_memory_queue_t *our_event_queue;
Dave Barach68b0fb02017-02-28 15:15:56 -050092
93 /* $$$ single thread only for the moment */
Florin Corase04c2992017-03-01 08:17:34 -080094 unix_shared_memory_queue_t *vpp_event_queue;
Dave Barach68b0fb02017-02-28 15:15:56 -050095
Florin Coras90a63982017-12-19 04:50:01 -080096 u8 *socket_name;
97
Dave Barach68b0fb02017-02-28 15:15:56 -050098 pid_t my_pid;
99
100 /* For deadman timers */
101 clib_time_t clib_time;
102
103 /* State of the connection, shared between msg RX thread and main thread */
104 volatile connection_state_t state;
105
106 /* Signal variables */
107 volatile int time_to_stop;
108 volatile int time_to_print_stats;
109
110 u32 configured_segment_size;
111
112 /* VNET_API_ERROR_FOO -> "Foo" hash table */
Florin Corase04c2992017-03-01 08:17:34 -0800113 uword *error_string_by_error_number;
Dave Barach68b0fb02017-02-28 15:15:56 -0500114
115 u8 *connect_test_data;
Florin Corase04c2992017-03-01 08:17:34 -0800116 pthread_t client_rx_thread_handle;
117 u32 client_bytes_received;
118 u8 test_return_packets;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700119 u64 bytes_to_send;
Florin Corase04c2992017-03-01 08:17:34 -0800120
Florin Coras90a63982017-12-19 04:50:01 -0800121 /** Flag that decides if socket, instead of svm, api is used to connect to
122 * vpp. If sock api is used, shm binary api is subsequently bootstrapped
123 * and all other messages are exchanged using shm IPC. */
124 u8 use_sock_api;
125
Florin Corase04c2992017-03-01 08:17:34 -0800126 /* convenience */
127 svm_fifo_segment_main_t *segment_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500128} uri_tcp_test_main_t;
129
130uri_tcp_test_main_t uri_tcp_test_main;
131
132#if CLIB_DEBUG > 0
133#define NITER 10000
134#else
135#define NITER 4000000
136#endif
137
Florin Corasa5464812017-04-19 13:00:05 -0700138static u8 *
139format_api_error (u8 * s, va_list * args)
140{
141 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
142 i32 error = va_arg (*args, u32);
143 uword *p;
144
145 p = hash_get (utm->error_string_by_error_number, -error);
146
147 if (p)
148 s = format (s, "%s", p[0]);
149 else
150 s = format (s, "%d", error);
151 return s;
152}
153
154static void
155init_error_string_table (uri_tcp_test_main_t * utm)
156{
157 utm->error_string_by_error_number = hash_create (0, sizeof (uword));
158
159#define _(n,v,s) hash_set (utm->error_string_by_error_number, -v, s);
160 foreach_vnet_api_error;
161#undef _
162
163 hash_set (utm->error_string_by_error_number, 99, "Misc");
164}
165
Dave Barach68b0fb02017-02-28 15:15:56 -0500166int
167wait_for_state_change (uri_tcp_test_main_t * utm, connection_state_t state)
168{
169#if CLIB_DEBUG > 0
170#define TIMEOUT 600.0
171#else
172#define TIMEOUT 600.0
173#endif
174
175 f64 timeout = clib_time_now (&utm->clib_time) + TIMEOUT;
176
177 while (clib_time_now (&utm->clib_time) < timeout)
178 {
179 if (utm->state == state)
Florin Corase04c2992017-03-01 08:17:34 -0800180 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500181 if (utm->state == STATE_FAILED)
182 return -1;
flyingeagle23a07779f2017-04-26 20:22:04 +0800183 if (utm->time_to_stop == 1)
Florin Corasf03a59a2017-06-09 21:07:32 -0700184 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500185 }
186 clib_warning ("timeout waiting for STATE_READY");
187 return -1;
188}
189
Florin Coras6cf30ad2017-04-04 23:08:23 -0700190void
Florin Corasa5464812017-04-19 13:00:05 -0700191application_send_attach (uri_tcp_test_main_t * utm)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700192{
193 vl_api_application_attach_t *bmp;
Florin Corasf03a59a2017-06-09 21:07:32 -0700194 u32 fifo_size = 4 << 20;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700195 bmp = vl_msg_api_alloc (sizeof (*bmp));
196 memset (bmp, 0, sizeof (*bmp));
197
198 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
199 bmp->client_index = utm->my_client_index;
200 bmp->context = ntohl (0xfeedface);
Florin Corasa5464812017-04-19 13:00:05 -0700201 bmp->options[APP_OPTIONS_FLAGS] =
Florin Corascea194d2017-10-02 00:18:51 -0700202 APP_OPTIONS_FLAGS_ACCEPT_REDIRECT | APP_OPTIONS_FLAGS_ADD_SEGMENT;
Dave Barach10d8cc62017-05-30 09:30:07 -0400203 bmp->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = 16;
Florin Corasff6e7692017-12-11 04:59:01 -0800204 bmp->options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
205 bmp->options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
206 bmp->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = 128 << 20;
207 bmp->options[APP_OPTIONS_SEGMENT_SIZE] = 256 << 20;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700208 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & bmp);
209}
210
Florin Corasa5464812017-04-19 13:00:05 -0700211int
212application_attach (uri_tcp_test_main_t * utm)
213{
214 application_send_attach (utm);
215 if (wait_for_state_change (utm, STATE_ATTACHED))
216 {
217 clib_warning ("timeout waiting for STATE_ATTACHED");
218 return -1;
219 }
220 return 0;
221}
222
Florin Coras6cf30ad2017-04-04 23:08:23 -0700223void
224application_detach (uri_tcp_test_main_t * utm)
225{
226 vl_api_application_detach_t *bmp;
227 bmp = vl_msg_api_alloc (sizeof (*bmp));
228 memset (bmp, 0, sizeof (*bmp));
229
230 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
231 bmp->client_index = utm->my_client_index;
232 bmp->context = ntohl (0xfeedface);
233 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & bmp);
234}
235
236static void
237vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t *
238 mp)
239{
240 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
241 svm_fifo_segment_create_args_t _a, *a = &_a;
242 int rv;
243
244 if (mp->retval)
245 {
Florin Corasa5464812017-04-19 13:00:05 -0700246 clib_warning ("attach failed: %U", format_api_error,
247 clib_net_to_host_u32 (mp->retval));
Florin Coras6cf30ad2017-04-04 23:08:23 -0700248 utm->state = STATE_FAILED;
249 return;
250 }
251
252 if (mp->segment_name_length == 0)
253 {
254 clib_warning ("segment_name_length zero");
255 return;
256 }
257
Florin Corasff6e7692017-12-11 04:59:01 -0800258 memset (a, 0, sizeof (*a));
Florin Coras6cf30ad2017-04-04 23:08:23 -0700259 a->segment_name = (char *) mp->segment_name;
260 a->segment_size = mp->segment_size;
261
262 ASSERT (mp->app_event_queue_address);
263
264 /* Attach to the segment vpp created */
265 rv = svm_fifo_segment_attach (a);
266 if (rv)
267 {
268 clib_warning ("svm_fifo_segment_attach ('%s') failed",
269 mp->segment_name);
270 return;
271 }
272
273 utm->our_event_queue =
Damjan Marion7bee80c2017-04-26 15:32:12 +0200274 uword_to_pointer (mp->app_event_queue_address,
275 unix_shared_memory_queue_t *);
Florin Corasa5464812017-04-19 13:00:05 -0700276 utm->state = STATE_ATTACHED;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700277}
278
279static void
280vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t *
281 mp)
282{
283 if (mp->retval)
284 clib_warning ("detach returned with err: %d", mp->retval);
285}
286
Dave Barach68b0fb02017-02-28 15:15:56 -0500287static void
Dave Barach68b0fb02017-02-28 15:15:56 -0500288stop_signal (int signum)
289{
290 uri_tcp_test_main_t *um = &uri_tcp_test_main;
291
292 um->time_to_stop = 1;
293}
294
295static void
296stats_signal (int signum)
297{
298 uri_tcp_test_main_t *um = &uri_tcp_test_main;
299
300 um->time_to_print_stats = 1;
301}
302
303static clib_error_t *
304setup_signal_handlers (void)
305{
306 signal (SIGINT, stats_signal);
307 signal (SIGQUIT, stop_signal);
308 signal (SIGTERM, stop_signal);
309
310 return 0;
311}
312
313void
314vlib_cli_output (struct vlib_main_t *vm, char *fmt, ...)
315{
316 clib_warning ("BUG");
317}
318
319int
320connect_to_vpp (char *name)
321{
322 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
323 api_main_t *am = &api_main;
324
Florin Coras90a63982017-12-19 04:50:01 -0800325 if (utm->use_sock_api)
326 {
327 if (vl_socket_client_connect ((char *) utm->socket_name, name,
328 0 /* default rx, tx buffer */ ))
329 return -1;
Dave Barach68b0fb02017-02-28 15:15:56 -0500330
Florin Coras90a63982017-12-19 04:50:01 -0800331 return vl_socket_client_init_shm (0);
332 }
333 else
334 {
335 if (vl_client_connect_to_vlib ("/vpe-api", name, 32) < 0)
336 return -1;
337 utm->vl_input_queue = am->shmem_hdr->vl_input_queue;
338 utm->my_client_index = am->my_client_index;
339 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500340 return 0;
341}
342
Florin Coras90a63982017-12-19 04:50:01 -0800343void
344disconnect_from_vpp (uri_tcp_test_main_t * utm)
345{
346 if (utm->use_sock_api)
347 vl_socket_client_disconnect ();
348 else
349 vl_client_disconnect_from_vlib ();
350}
351
Dave Barach68b0fb02017-02-28 15:15:56 -0500352static void
Florin Corase04c2992017-03-01 08:17:34 -0800353vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
Dave Barach68b0fb02017-02-28 15:15:56 -0500354{
355 svm_fifo_segment_create_args_t _a, *a = &_a;
356 int rv;
357
Florin Coras3cbc04b2017-10-02 00:18:51 -0700358 memset (a, 0, sizeof (*a));
Dave Barach68b0fb02017-02-28 15:15:56 -0500359 a->segment_name = (char *) mp->segment_name;
360 a->segment_size = mp->segment_size;
361 /* Attach to the segment vpp created */
362 rv = svm_fifo_segment_attach (a);
363 if (rv)
364 {
365 clib_warning ("svm_fifo_segment_attach ('%s') failed",
Florin Corase04c2992017-03-01 08:17:34 -0800366 mp->segment_name);
Dave Barach68b0fb02017-02-28 15:15:56 -0500367 return;
368 }
369 clib_warning ("Mapped new segment '%s' size %d", mp->segment_name,
Florin Corase04c2992017-03-01 08:17:34 -0800370 mp->segment_size);
Dave Barach68b0fb02017-02-28 15:15:56 -0500371}
372
373static void
Florin Corasf03a59a2017-06-09 21:07:32 -0700374session_print_stats (uri_tcp_test_main_t * utm, session_t * session)
375{
376 f64 deltat;
377 u64 bytes;
378
379 deltat = clib_time_now (&utm->clib_time) - session->start;
380 bytes = utm->i_am_master ? session->bytes_received : utm->bytes_to_send;
381 fformat (stdout, "Finished in %.6f\n", deltat);
382 fformat (stdout, "%.4f Gbit/second\n", (bytes * 8.0) / deltat / 1e9);
383}
384
385static void
Dave Barach68b0fb02017-02-28 15:15:56 -0500386vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp)
387{
388 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
Florin Corasf03a59a2017-06-09 21:07:32 -0700389 session_t *session = 0;
Florin Corase04c2992017-03-01 08:17:34 -0800390 vl_api_disconnect_session_reply_t *rmp;
391 uword *p;
Dave Barach68b0fb02017-02-28 15:15:56 -0500392 int rv = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500393
Florin Coras6cf30ad2017-04-04 23:08:23 -0700394 p = hash_get (utm->session_index_by_vpp_handles, mp->handle);
Florin Corase04c2992017-03-01 08:17:34 -0800395
396 if (p)
397 {
398 session = pool_elt_at_index (utm->sessions, p[0]);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700399 hash_unset (utm->session_index_by_vpp_handles, mp->handle);
Florin Corase04c2992017-03-01 08:17:34 -0800400 pool_put (utm->sessions, session);
401 }
402 else
403 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700404 clib_warning ("couldn't find session key %llx", mp->handle);
Florin Corase04c2992017-03-01 08:17:34 -0800405 rv = -11;
406 }
407
Florin Corasf03a59a2017-06-09 21:07:32 -0700408// utm->time_to_stop = 1;
Florin Corase04c2992017-03-01 08:17:34 -0800409
410 rmp = vl_msg_api_alloc (sizeof (*rmp));
411 memset (rmp, 0, sizeof (*rmp));
412
413 rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY);
414 rmp->retval = rv;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700415 rmp->handle = mp->handle;
Florin Corase04c2992017-03-01 08:17:34 -0800416 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & rmp);
Florin Corasf03a59a2017-06-09 21:07:32 -0700417
418 if (session)
419 session_print_stats (utm, session);
Florin Corase04c2992017-03-01 08:17:34 -0800420}
421
422static void
423vl_api_reset_session_t_handler (vl_api_reset_session_t * mp)
424{
425 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
Florin Corase04c2992017-03-01 08:17:34 -0800426 vl_api_reset_session_reply_t *rmp;
427 uword *p;
428 int rv = 0;
Florin Corase04c2992017-03-01 08:17:34 -0800429
Florin Coras6cf30ad2017-04-04 23:08:23 -0700430 p = hash_get (utm->session_index_by_vpp_handles, mp->handle);
Dave Barach68b0fb02017-02-28 15:15:56 -0500431
432 if (p)
433 {
Florin Corasf6359c82017-06-19 12:26:09 -0400434 clib_warning ("got reset");
435 /* Cleanup later */
Florin Corasd79b41e2017-03-04 05:37:52 -0800436 utm->time_to_stop = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -0500437 }
438 else
439 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700440 clib_warning ("couldn't find session key %llx", mp->handle);
Dave Barach68b0fb02017-02-28 15:15:56 -0500441 rv = -11;
442 }
443
444 rmp = vl_msg_api_alloc (sizeof (*rmp));
445 memset (rmp, 0, sizeof (*rmp));
Florin Corasd79b41e2017-03-04 05:37:52 -0800446 rmp->_vl_msg_id = ntohs (VL_API_RESET_SESSION_REPLY);
Dave Barach68b0fb02017-02-28 15:15:56 -0500447 rmp->retval = rv;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700448 rmp->handle = mp->handle;
Florin Corase04c2992017-03-01 08:17:34 -0800449 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & rmp);
Dave Barach68b0fb02017-02-28 15:15:56 -0500450}
451
452void
Florin Corase04c2992017-03-01 08:17:34 -0800453client_handle_fifo_event_rx (uri_tcp_test_main_t * utm,
454 session_fifo_event_t * e)
Dave Barach68b0fb02017-02-28 15:15:56 -0500455{
Florin Corase04c2992017-03-01 08:17:34 -0800456 svm_fifo_t *rx_fifo;
457 int n_read, bytes, i;
Dave Barach68b0fb02017-02-28 15:15:56 -0500458
459 rx_fifo = e->fifo;
460
Florin Coras6792ec02017-03-13 03:49:51 -0700461 bytes = svm_fifo_max_dequeue (rx_fifo);
462 /* Allow enqueuing of new event */
463 svm_fifo_unset_event (rx_fifo);
464
465 /* Read the bytes */
Dave Barach68b0fb02017-02-28 15:15:56 -0500466 do
467 {
Florin Corasa5464812017-04-19 13:00:05 -0700468 n_read = svm_fifo_dequeue_nowait (rx_fifo,
Florin Coras6792ec02017-03-13 03:49:51 -0700469 clib_min (vec_len (utm->rx_buf),
470 bytes), utm->rx_buf);
Dave Barach68b0fb02017-02-28 15:15:56 -0500471 if (n_read > 0)
Florin Corase04c2992017-03-01 08:17:34 -0800472 {
473 bytes -= n_read;
Florin Corasf03a59a2017-06-09 21:07:32 -0700474 if (utm->test_return_packets)
Florin Corase04c2992017-03-01 08:17:34 -0800475 {
Florin Corasf03a59a2017-06-09 21:07:32 -0700476 for (i = 0; i < n_read; i++)
Florin Corase04c2992017-03-01 08:17:34 -0800477 {
Florin Corasf03a59a2017-06-09 21:07:32 -0700478 if (utm->rx_buf[i]
479 != ((utm->client_bytes_received + i) & 0xff))
480 {
481 clib_warning ("error at byte %lld, 0x%x not 0x%x",
482 utm->client_bytes_received + i,
483 utm->rx_buf[i],
484 ((utm->client_bytes_received +
485 i) & 0xff));
486 }
Florin Corase04c2992017-03-01 08:17:34 -0800487 }
488 }
489 utm->client_bytes_received += n_read;
490 }
Florin Coras6792ec02017-03-13 03:49:51 -0700491 else
492 {
493 if (n_read == -2)
494 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700495// clib_warning ("weird!");
Florin Coras6792ec02017-03-13 03:49:51 -0700496 break;
497 }
498 }
Florin Corase04c2992017-03-01 08:17:34 -0800499
Dave Barach68b0fb02017-02-28 15:15:56 -0500500 }
Florin Coras6792ec02017-03-13 03:49:51 -0700501 while (bytes > 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500502}
503
504void
Florin Corase04c2992017-03-01 08:17:34 -0800505client_handle_event_queue (uri_tcp_test_main_t * utm)
Dave Barach68b0fb02017-02-28 15:15:56 -0500506{
507 session_fifo_event_t _e, *e = &_e;;
508
Florin Corase04c2992017-03-01 08:17:34 -0800509 unix_shared_memory_queue_sub (utm->our_event_queue, (u8 *) e,
510 0 /* nowait */ );
Dave Barach68b0fb02017-02-28 15:15:56 -0500511 switch (e->event_type)
512 {
Florin Corasa5464812017-04-19 13:00:05 -0700513 case FIFO_EVENT_APP_RX:
Florin Corase04c2992017-03-01 08:17:34 -0800514 client_handle_fifo_event_rx (utm, e);
Dave Barach68b0fb02017-02-28 15:15:56 -0500515 break;
516
Florin Corasa5464812017-04-19 13:00:05 -0700517 case FIFO_EVENT_DISCONNECT:
Dave Barach68b0fb02017-02-28 15:15:56 -0500518 return;
519
520 default:
Florin Corase04c2992017-03-01 08:17:34 -0800521 clib_warning ("unknown event type %d", e->event_type);
Dave Barach68b0fb02017-02-28 15:15:56 -0500522 break;
523 }
524}
525
Florin Corase04c2992017-03-01 08:17:34 -0800526static void *
527client_rx_thread_fn (void *arg)
Dave Barach68b0fb02017-02-28 15:15:56 -0500528{
Florin Corase04c2992017-03-01 08:17:34 -0800529 session_fifo_event_t _e, *e = &_e;
530 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500531
Florin Corase04c2992017-03-01 08:17:34 -0800532 utm->client_bytes_received = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500533 while (1)
534 {
Florin Corase04c2992017-03-01 08:17:34 -0800535 unix_shared_memory_queue_sub (utm->our_event_queue, (u8 *) e,
536 0 /* nowait */ );
Dave Barach68b0fb02017-02-28 15:15:56 -0500537 switch (e->event_type)
Florin Corase04c2992017-03-01 08:17:34 -0800538 {
Florin Corasa5464812017-04-19 13:00:05 -0700539 case FIFO_EVENT_APP_RX:
Florin Corase04c2992017-03-01 08:17:34 -0800540 client_handle_fifo_event_rx (utm, e);
541 break;
Dave Barach68b0fb02017-02-28 15:15:56 -0500542
Florin Corasa5464812017-04-19 13:00:05 -0700543 case FIFO_EVENT_DISCONNECT:
Florin Corase04c2992017-03-01 08:17:34 -0800544 return 0;
545 default:
546 clib_warning ("unknown event type %d", e->event_type);
547 break;
548 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500549
Florin Corase04c2992017-03-01 08:17:34 -0800550 if (PREDICT_FALSE (utm->time_to_stop == 1))
551 break;
Dave Barach68b0fb02017-02-28 15:15:56 -0500552 }
Florin Corase04c2992017-03-01 08:17:34 -0800553 pthread_exit (0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500554}
555
Dave Barach68b0fb02017-02-28 15:15:56 -0500556
557static void
Dave Wallace33e002b2017-09-06 01:20:02 -0400558vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp)
Dave Barach68b0fb02017-02-28 15:15:56 -0500559{
560 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500561 session_t *session;
562 u32 session_index;
563 svm_fifo_t *rx_fifo, *tx_fifo;
564 int rv;
565
566 if (mp->retval)
567 {
Florin Corasa5464812017-04-19 13:00:05 -0700568 clib_warning ("connection failed with code: %U", format_api_error,
569 clib_net_to_host_u32 (mp->retval));
Dave Barach68b0fb02017-02-28 15:15:56 -0500570 utm->state = STATE_FAILED;
571 return;
572 }
Florin Corasade70e42017-10-14 18:56:41 -0700573 else
574 {
575 clib_warning ("connected with local ip %U port %d", format_ip46_address,
576 mp->lcl_ip, mp->is_ip4,
577 clib_net_to_host_u16 (mp->lcl_port));
578 }
Florin Corase04c2992017-03-01 08:17:34 -0800579
Damjan Marion7bee80c2017-04-26 15:32:12 +0200580 utm->vpp_event_queue =
581 uword_to_pointer (mp->vpp_event_queue_address,
582 unix_shared_memory_queue_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500583
584 /*
585 * Setup session
586 */
587
588 pool_get (utm->sessions, session);
589 session_index = session - utm->sessions;
590
Damjan Marion7bee80c2017-04-26 15:32:12 +0200591 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500592 rx_fifo->client_session_index = session_index;
Damjan Marion7bee80c2017-04-26 15:32:12 +0200593 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500594 tx_fifo->client_session_index = session_index;
595
596 session->server_rx_fifo = rx_fifo;
597 session->server_tx_fifo = tx_fifo;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700598 session->vpp_session_handle = mp->handle;
Florin Corasf03a59a2017-06-09 21:07:32 -0700599 session->start = clib_time_now (&utm->clib_time);
Dave Barach68b0fb02017-02-28 15:15:56 -0500600
601 /* Save handle */
602 utm->connected_session_index = session_index;
Florin Corase04c2992017-03-01 08:17:34 -0800603 utm->state = STATE_READY;
604
605 /* Add it to lookup table */
Florin Coras6cf30ad2017-04-04 23:08:23 -0700606 hash_set (utm->session_index_by_vpp_handles, mp->handle, session_index);
Florin Corase04c2992017-03-01 08:17:34 -0800607
608 /* Start RX thread */
609 rv = pthread_create (&utm->client_rx_thread_handle,
610 NULL /*attr */ , client_rx_thread_fn, 0);
611 if (rv)
612 {
613 clib_warning ("pthread_create returned %d", rv);
614 rv = VNET_API_ERROR_SYSCALL_ERROR_1;
615 }
616}
617
Florin Coras6792ec02017-03-13 03:49:51 -0700618static void
619send_test_chunk (uri_tcp_test_main_t * utm, svm_fifo_t * tx_fifo, int mypid,
620 u32 bytes)
Florin Corase04c2992017-03-01 08:17:34 -0800621{
622 u8 *test_data = utm->connect_test_data;
623 u64 bytes_sent = 0;
Florin Coras6792ec02017-03-13 03:49:51 -0700624 int test_buf_offset = 0;
625 u32 bytes_to_snd;
Florin Corasf03a59a2017-06-09 21:07:32 -0700626 u32 queue_max_chunk = 128 << 10, actual_write;
Florin Corase04c2992017-03-01 08:17:34 -0800627 session_fifo_event_t evt;
Florin Coras6792ec02017-03-13 03:49:51 -0700628 int rv;
Florin Corase04c2992017-03-01 08:17:34 -0800629
Florin Coras6792ec02017-03-13 03:49:51 -0700630 bytes_to_snd = (bytes == 0) ? vec_len (test_data) : bytes;
631 if (bytes_to_snd > vec_len (test_data))
632 bytes_to_snd = vec_len (test_data);
Florin Corase04c2992017-03-01 08:17:34 -0800633
Florin Corasf6359c82017-06-19 12:26:09 -0400634 while (bytes_to_snd > 0 && !utm->time_to_stop)
Florin Corase04c2992017-03-01 08:17:34 -0800635 {
Florin Corasf03a59a2017-06-09 21:07:32 -0700636 actual_write = (bytes_to_snd > queue_max_chunk) ?
637 queue_max_chunk : bytes_to_snd;
Florin Corasa5464812017-04-19 13:00:05 -0700638 rv = svm_fifo_enqueue_nowait (tx_fifo, actual_write,
Florin Coras6792ec02017-03-13 03:49:51 -0700639 test_data + test_buf_offset);
640
641 if (rv > 0)
Florin Corase04c2992017-03-01 08:17:34 -0800642 {
Florin Coras6792ec02017-03-13 03:49:51 -0700643 bytes_to_snd -= rv;
644 test_buf_offset += rv;
645 bytes_sent += rv;
Florin Corase04c2992017-03-01 08:17:34 -0800646
Florin Coras6792ec02017-03-13 03:49:51 -0700647 if (svm_fifo_set_event (tx_fifo))
Florin Corase04c2992017-03-01 08:17:34 -0800648 {
Florin Corase04c2992017-03-01 08:17:34 -0800649 /* Fabricate TX event, send to vpp */
650 evt.fifo = tx_fifo;
Florin Corasa5464812017-04-19 13:00:05 -0700651 evt.event_type = FIFO_EVENT_APP_TX;
Florin Corase04c2992017-03-01 08:17:34 -0800652
653 unix_shared_memory_queue_add (utm->vpp_event_queue,
654 (u8 *) & evt,
655 0 /* do wait for mutex */ );
656 }
657 }
658 }
Florin Coras6792ec02017-03-13 03:49:51 -0700659}
660
661void
662client_send_data (uri_tcp_test_main_t * utm)
663{
664 u8 *test_data = utm->connect_test_data;
665 int mypid = getpid ();
666 session_t *session;
667 svm_fifo_t *tx_fifo;
668 u32 n_iterations, leftover;
669 int i;
670
671 session = pool_elt_at_index (utm->sessions, utm->connected_session_index);
672 tx_fifo = session->server_tx_fifo;
673
Florin Coras82b13a82017-04-25 11:58:06 -0700674 ASSERT (vec_len (test_data) > 0);
675
Florin Coras6792ec02017-03-13 03:49:51 -0700676 vec_validate (utm->rx_buf, vec_len (test_data) - 1);
677 n_iterations = utm->bytes_to_send / vec_len (test_data);
678
679 for (i = 0; i < n_iterations; i++)
680 {
681 send_test_chunk (utm, tx_fifo, mypid, 0);
Florin Corasf6359c82017-06-19 12:26:09 -0400682 if (utm->time_to_stop)
683 break;
Florin Coras6792ec02017-03-13 03:49:51 -0700684 }
685
686 leftover = utm->bytes_to_send % vec_len (test_data);
687 if (leftover)
688 send_test_chunk (utm, tx_fifo, mypid, leftover);
Florin Corase04c2992017-03-01 08:17:34 -0800689
Florin Corasf03a59a2017-06-09 21:07:32 -0700690 if (!utm->drop_packets)
Florin Corase04c2992017-03-01 08:17:34 -0800691 {
Florin Corasf03a59a2017-06-09 21:07:32 -0700692 f64 timeout = clib_time_now (&utm->clib_time) + 10;
Florin Corase04c2992017-03-01 08:17:34 -0800693
694 /* Wait for the outstanding packets */
Florin Coras6792ec02017-03-13 03:49:51 -0700695 while (utm->client_bytes_received <
696 vec_len (test_data) * n_iterations + leftover)
Florin Corase04c2992017-03-01 08:17:34 -0800697 {
698 if (clib_time_now (&utm->clib_time) > timeout)
699 {
700 clib_warning ("timed out waiting for the missing packets");
701 break;
702 }
703 }
Florin Corase04c2992017-03-01 08:17:34 -0800704 }
Florin Coras6792ec02017-03-13 03:49:51 -0700705 utm->time_to_stop = 1;
Florin Corase04c2992017-03-01 08:17:34 -0800706}
707
708void
Florin Corasa5464812017-04-19 13:00:05 -0700709client_send_connect (uri_tcp_test_main_t * utm)
Florin Corase04c2992017-03-01 08:17:34 -0800710{
711 vl_api_connect_uri_t *cmp;
712 cmp = vl_msg_api_alloc (sizeof (*cmp));
713 memset (cmp, 0, sizeof (*cmp));
714
715 cmp->_vl_msg_id = ntohs (VL_API_CONNECT_URI);
716 cmp->client_index = utm->my_client_index;
717 cmp->context = ntohl (0xfeedface);
718 memcpy (cmp->uri, utm->connect_uri, vec_len (utm->connect_uri));
719 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & cmp);
720}
721
Florin Corasa5464812017-04-19 13:00:05 -0700722int
723client_connect (uri_tcp_test_main_t * utm)
724{
725 client_send_connect (utm);
726 if (wait_for_state_change (utm, STATE_READY))
727 {
728 clib_warning ("Connect failed");
729 return -1;
730 }
731 return 0;
732}
733
Florin Corase04c2992017-03-01 08:17:34 -0800734void
Florin Corasa5464812017-04-19 13:00:05 -0700735client_send_disconnect (uri_tcp_test_main_t * utm)
Florin Corase04c2992017-03-01 08:17:34 -0800736{
737 session_t *connected_session;
738 vl_api_disconnect_session_t *dmp;
739 connected_session = pool_elt_at_index (utm->sessions,
740 utm->connected_session_index);
741 dmp = vl_msg_api_alloc (sizeof (*dmp));
742 memset (dmp, 0, sizeof (*dmp));
743 dmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION);
744 dmp->client_index = utm->my_client_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700745 dmp->handle = connected_session->vpp_session_handle;
Florin Corase04c2992017-03-01 08:17:34 -0800746 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & dmp);
747}
748
Florin Corasa5464812017-04-19 13:00:05 -0700749int
750client_disconnect (uri_tcp_test_main_t * utm)
751{
752 client_send_disconnect (utm);
Florin Corasf03a59a2017-06-09 21:07:32 -0700753 clib_warning ("Sent disconnect");
Florin Corasa5464812017-04-19 13:00:05 -0700754 if (wait_for_state_change (utm, STATE_START))
755 {
756 clib_warning ("Disconnect failed");
757 return -1;
758 }
759 return 0;
760}
761
Florin Corase04c2992017-03-01 08:17:34 -0800762static void
Florin Coras90a63982017-12-19 04:50:01 -0800763client_run (uri_tcp_test_main_t * utm)
Florin Corase04c2992017-03-01 08:17:34 -0800764{
765 int i;
766
Florin Corasa5464812017-04-19 13:00:05 -0700767 if (application_attach (utm))
768 return;
Florin Corase04c2992017-03-01 08:17:34 -0800769
Florin Corasa5464812017-04-19 13:00:05 -0700770 if (client_connect (utm))
Florin Corase04c2992017-03-01 08:17:34 -0800771 {
Florin Corasa5464812017-04-19 13:00:05 -0700772 application_detach (utm);
Florin Corase04c2992017-03-01 08:17:34 -0800773 return;
774 }
775
776 /* Init test data */
Florin Corasf03a59a2017-06-09 21:07:32 -0700777 vec_validate (utm->connect_test_data, 128 * 1024 - 1);
Florin Corase04c2992017-03-01 08:17:34 -0800778 for (i = 0; i < vec_len (utm->connect_test_data); i++)
779 utm->connect_test_data[i] = i & 0xff;
780
781 /* Start send */
782 client_send_data (utm);
783
784 /* Disconnect */
785 client_disconnect (utm);
Florin Coras6792ec02017-03-13 03:49:51 -0700786
Florin Coras6cf30ad2017-04-04 23:08:23 -0700787 application_detach (utm);
Florin Corase04c2992017-03-01 08:17:34 -0800788}
789
790static void
791vl_api_bind_uri_reply_t_handler (vl_api_bind_uri_reply_t * mp)
792{
793 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
Florin Corase04c2992017-03-01 08:17:34 -0800794
795 if (mp->retval)
796 {
flyingeagle23a07779f2017-04-26 20:22:04 +0800797 clib_warning ("bind failed: %U", format_api_error,
Florin Corasa5464812017-04-19 13:00:05 -0700798 clib_net_to_host_u32 (mp->retval));
Florin Corase04c2992017-03-01 08:17:34 -0800799 utm->state = STATE_FAILED;
800 return;
801 }
802
Dave Barach68b0fb02017-02-28 15:15:56 -0500803 utm->state = STATE_READY;
804}
805
Dave Barach68b0fb02017-02-28 15:15:56 -0500806static void
Florin Corase04c2992017-03-01 08:17:34 -0800807vl_api_unbind_uri_reply_t_handler (vl_api_unbind_uri_reply_t * mp)
Dave Barach68b0fb02017-02-28 15:15:56 -0500808{
809 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
810
811 if (mp->retval != 0)
Florin Corase04c2992017-03-01 08:17:34 -0800812 clib_warning ("returned %d", ntohl (mp->retval));
Dave Barach68b0fb02017-02-28 15:15:56 -0500813
814 utm->state = STATE_START;
815}
816
Florin Coras6cf30ad2017-04-04 23:08:23 -0700817u8 *
818format_ip4_address (u8 * s, va_list * args)
819{
820 u8 *a = va_arg (*args, u8 *);
821 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
822}
823
824u8 *
825format_ip6_address (u8 * s, va_list * args)
826{
827 ip6_address_t *a = va_arg (*args, ip6_address_t *);
828 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
829
830 i_max_n_zero = ARRAY_LEN (a->as_u16);
831 max_n_zeros = 0;
832 i_first_zero = i_max_n_zero;
833 n_zeros = 0;
834 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
835 {
836 u32 is_zero = a->as_u16[i] == 0;
837 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
838 {
839 i_first_zero = i;
840 n_zeros = 0;
841 }
842 n_zeros += is_zero;
843 if ((!is_zero && n_zeros > max_n_zeros)
844 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
845 {
846 i_max_n_zero = i_first_zero;
847 max_n_zeros = n_zeros;
848 i_first_zero = ARRAY_LEN (a->as_u16);
849 n_zeros = 0;
850 }
851 }
852
853 last_double_colon = 0;
854 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
855 {
856 if (i == i_max_n_zero && max_n_zeros > 1)
857 {
858 s = format (s, "::");
859 i += max_n_zeros - 1;
860 last_double_colon = 1;
861 }
862 else
863 {
864 s = format (s, "%s%x",
865 (last_double_colon || i == 0) ? "" : ":",
866 clib_net_to_host_u16 (a->as_u16[i]));
867 last_double_colon = 0;
868 }
869 }
870
871 return s;
872}
873
874/* Format an IP46 address. */
875u8 *
876format_ip46_address (u8 * s, va_list * args)
877{
878 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
879 ip46_type_t type = va_arg (*args, ip46_type_t);
880 int is_ip4 = 1;
881
882 switch (type)
883 {
884 case IP46_TYPE_ANY:
885 is_ip4 = ip46_address_is_ip4 (ip46);
886 break;
887 case IP46_TYPE_IP4:
888 is_ip4 = 1;
889 break;
890 case IP46_TYPE_IP6:
891 is_ip4 = 0;
892 break;
893 }
894
895 return is_ip4 ?
896 format (s, "%U", format_ip4_address, &ip46->ip4) :
897 format (s, "%U", format_ip6_address, &ip46->ip6);
898}
899
Dave Barach68b0fb02017-02-28 15:15:56 -0500900static void
901vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
902{
903 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
904 vl_api_accept_session_reply_t *rmp;
Florin Corase04c2992017-03-01 08:17:34 -0800905 svm_fifo_t *rx_fifo, *tx_fifo;
906 session_t *session;
Dave Barach68b0fb02017-02-28 15:15:56 -0500907 static f64 start_time;
Dave Barach68b0fb02017-02-28 15:15:56 -0500908 u32 session_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700909 u8 *ip_str;
Dave Barach68b0fb02017-02-28 15:15:56 -0500910
911 if (start_time == 0.0)
Florin Corase04c2992017-03-01 08:17:34 -0800912 start_time = clib_time_now (&utm->clib_time);
Dave Barach68b0fb02017-02-28 15:15:56 -0500913
Florin Coras6cf30ad2017-04-04 23:08:23 -0700914 ip_str = format (0, "%U", format_ip46_address, &mp->ip, mp->is_ip4);
915 clib_warning ("Accepted session from: %s:%d", ip_str,
916 clib_net_to_host_u16 (mp->port));
Damjan Marion7bee80c2017-04-26 15:32:12 +0200917 utm->vpp_event_queue =
918 uword_to_pointer (mp->vpp_event_queue_address,
919 unix_shared_memory_queue_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500920
921 /* Allocate local session and set it up */
922 pool_get (utm->sessions, session);
923 session_index = session - utm->sessions;
924
Damjan Marion7bee80c2017-04-26 15:32:12 +0200925 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500926 rx_fifo->client_session_index = session_index;
Damjan Marion7bee80c2017-04-26 15:32:12 +0200927 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500928 tx_fifo->client_session_index = session_index;
929
930 session->server_rx_fifo = rx_fifo;
931 session->server_tx_fifo = tx_fifo;
932
933 /* Add it to lookup table */
Florin Coras6cf30ad2017-04-04 23:08:23 -0700934 hash_set (utm->session_index_by_vpp_handles, mp->handle, session_index);
Dave Barach68b0fb02017-02-28 15:15:56 -0500935
936 utm->state = STATE_READY;
937
938 /* Stats printing */
Florin Corase04c2992017-03-01 08:17:34 -0800939 if (pool_elts (utm->sessions) && (pool_elts (utm->sessions) % 20000) == 0)
Dave Barach68b0fb02017-02-28 15:15:56 -0500940 {
941 f64 now = clib_time_now (&utm->clib_time);
942 fformat (stdout, "%d active sessions in %.2f seconds, %.2f/sec...\n",
Florin Corase04c2992017-03-01 08:17:34 -0800943 pool_elts (utm->sessions), now - start_time,
944 (f64) pool_elts (utm->sessions) / (now - start_time));
Dave Barach68b0fb02017-02-28 15:15:56 -0500945 }
946
Florin Corase04c2992017-03-01 08:17:34 -0800947 /*
948 * Send accept reply to vpp
949 */
Dave Barach68b0fb02017-02-28 15:15:56 -0500950 rmp = vl_msg_api_alloc (sizeof (*rmp));
951 memset (rmp, 0, sizeof (*rmp));
952 rmp->_vl_msg_id = ntohs (VL_API_ACCEPT_SESSION_REPLY);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700953 rmp->handle = mp->handle;
Florin Coras3cbc04b2017-10-02 00:18:51 -0700954 rmp->context = mp->context;
Florin Corase04c2992017-03-01 08:17:34 -0800955 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & rmp);
Florin Corasf03a59a2017-06-09 21:07:32 -0700956
957 session->bytes_received = 0;
958 session->start = clib_time_now (&utm->clib_time);
Dave Barach68b0fb02017-02-28 15:15:56 -0500959}
960
961void
Florin Corase04c2992017-03-01 08:17:34 -0800962server_handle_fifo_event_rx (uri_tcp_test_main_t * utm,
963 session_fifo_event_t * e)
Dave Barach68b0fb02017-02-28 15:15:56 -0500964{
Florin Corase04c2992017-03-01 08:17:34 -0800965 svm_fifo_t *rx_fifo, *tx_fifo;
966 int n_read;
Florin Corase04c2992017-03-01 08:17:34 -0800967 session_fifo_event_t evt;
968 unix_shared_memory_queue_t *q;
Florin Corasf03a59a2017-06-09 21:07:32 -0700969 session_t *session;
970 int rv;
971 u32 max_dequeue, offset, max_transfer, rx_buf_len;
Florin Corase04c2992017-03-01 08:17:34 -0800972
Florin Corasf03a59a2017-06-09 21:07:32 -0700973 rx_buf_len = vec_len (utm->rx_buf);
Florin Corase04c2992017-03-01 08:17:34 -0800974 rx_fifo = e->fifo;
Florin Corasf03a59a2017-06-09 21:07:32 -0700975 session = &utm->sessions[rx_fifo->client_session_index];
976 tx_fifo = session->server_tx_fifo;
Florin Corase04c2992017-03-01 08:17:34 -0800977
Florin Corasf03a59a2017-06-09 21:07:32 -0700978 max_dequeue = svm_fifo_max_dequeue (rx_fifo);
Florin Coras6792ec02017-03-13 03:49:51 -0700979 /* Allow enqueuing of a new event */
980 svm_fifo_unset_event (rx_fifo);
981
Florin Corasf03a59a2017-06-09 21:07:32 -0700982 if (PREDICT_FALSE (max_dequeue == 0))
983 {
984 return;
985 }
Florin Coras6792ec02017-03-13 03:49:51 -0700986
Florin Corasf03a59a2017-06-09 21:07:32 -0700987 /* Read the max_dequeue */
Florin Corase04c2992017-03-01 08:17:34 -0800988 do
989 {
Florin Corasf03a59a2017-06-09 21:07:32 -0700990 max_transfer = clib_min (rx_buf_len, max_dequeue);
991 n_read = svm_fifo_dequeue_nowait (rx_fifo, max_transfer, utm->rx_buf);
Florin Coras6792ec02017-03-13 03:49:51 -0700992 if (n_read > 0)
Florin Corase04c2992017-03-01 08:17:34 -0800993 {
Florin Corasf03a59a2017-06-09 21:07:32 -0700994 max_dequeue -= n_read;
995 session->bytes_received += n_read;
996 }
997
998 /* Reflect if a non-drop session */
999 if (!utm->drop_packets && n_read > 0)
1000 {
1001 offset = 0;
Florin Corase04c2992017-03-01 08:17:34 -08001002 do
1003 {
Florin Corasf03a59a2017-06-09 21:07:32 -07001004 rv = svm_fifo_enqueue_nowait (tx_fifo, n_read,
1005 &utm->rx_buf[offset]);
1006 if (rv > 0)
1007 {
1008 n_read -= rv;
1009 offset += rv;
1010 }
Florin Corase04c2992017-03-01 08:17:34 -08001011 }
Florin Corasf03a59a2017-06-09 21:07:32 -07001012 while ((rv <= 0 || n_read > 0) && !utm->time_to_stop);
Florin Corase04c2992017-03-01 08:17:34 -08001013
Florin Coras6792ec02017-03-13 03:49:51 -07001014 /* If event wasn't set, add one */
1015 if (svm_fifo_set_event (tx_fifo))
1016 {
1017 /* Fabricate TX event, send to vpp */
1018 evt.fifo = tx_fifo;
Florin Corasa5464812017-04-19 13:00:05 -07001019 evt.event_type = FIFO_EVENT_APP_TX;
Florin Coras6792ec02017-03-13 03:49:51 -07001020
1021 q = utm->vpp_event_queue;
1022 unix_shared_memory_queue_add (q, (u8 *) & evt,
Florin Corasf03a59a2017-06-09 21:07:32 -07001023 1 /* do wait for mutex */ );
Florin Coras6792ec02017-03-13 03:49:51 -07001024 }
Florin Corase04c2992017-03-01 08:17:34 -08001025 }
Florin Corase04c2992017-03-01 08:17:34 -08001026 }
Florin Corasf03a59a2017-06-09 21:07:32 -07001027 while ((n_read < 0 || max_dequeue > 0) && !utm->time_to_stop);
Florin Corase04c2992017-03-01 08:17:34 -08001028}
1029
1030void
1031server_handle_event_queue (uri_tcp_test_main_t * utm)
1032{
Florin Coras3cbc04b2017-10-02 00:18:51 -07001033 session_fifo_event_t _e, *e = &_e;
Florin Corase04c2992017-03-01 08:17:34 -08001034
1035 while (1)
1036 {
1037 unix_shared_memory_queue_sub (utm->our_event_queue, (u8 *) e,
1038 0 /* nowait */ );
1039 switch (e->event_type)
1040 {
Florin Corasa5464812017-04-19 13:00:05 -07001041 case FIFO_EVENT_APP_RX:
Florin Corase04c2992017-03-01 08:17:34 -08001042 server_handle_fifo_event_rx (utm, e);
1043 break;
1044
Florin Corasa5464812017-04-19 13:00:05 -07001045 case FIFO_EVENT_DISCONNECT:
Florin Corase04c2992017-03-01 08:17:34 -08001046 return;
1047
1048 default:
1049 clib_warning ("unknown event type %d", e->event_type);
1050 break;
1051 }
1052 if (PREDICT_FALSE (utm->time_to_stop == 1))
1053 break;
1054 if (PREDICT_FALSE (utm->time_to_print_stats == 1))
1055 {
1056 utm->time_to_print_stats = 0;
1057 fformat (stdout, "%d connections\n", pool_elts (utm->sessions));
1058 }
1059 }
1060}
1061
1062void
Florin Corasa5464812017-04-19 13:00:05 -07001063server_send_listen (uri_tcp_test_main_t * utm)
Florin Corase04c2992017-03-01 08:17:34 -08001064{
1065 vl_api_bind_uri_t *bmp;
Florin Corase04c2992017-03-01 08:17:34 -08001066 bmp = vl_msg_api_alloc (sizeof (*bmp));
1067 memset (bmp, 0, sizeof (*bmp));
1068
1069 bmp->_vl_msg_id = ntohs (VL_API_BIND_URI);
1070 bmp->client_index = utm->my_client_index;
1071 bmp->context = ntohl (0xfeedface);
Florin Corase04c2992017-03-01 08:17:34 -08001072 memcpy (bmp->uri, utm->uri, vec_len (utm->uri));
1073 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & bmp);
1074}
1075
Florin Corasa5464812017-04-19 13:00:05 -07001076int
1077server_listen (uri_tcp_test_main_t * utm)
1078{
1079 server_send_listen (utm);
1080 if (wait_for_state_change (utm, STATE_READY))
1081 {
1082 clib_warning ("timeout waiting for STATE_READY");
1083 return -1;
1084 }
1085 return 0;
1086}
1087
Florin Corase04c2992017-03-01 08:17:34 -08001088void
Florin Corasa5464812017-04-19 13:00:05 -07001089server_send_unbind (uri_tcp_test_main_t * utm)
Florin Corase04c2992017-03-01 08:17:34 -08001090{
1091 vl_api_unbind_uri_t *ump;
1092
1093 ump = vl_msg_api_alloc (sizeof (*ump));
1094 memset (ump, 0, sizeof (*ump));
1095
1096 ump->_vl_msg_id = ntohs (VL_API_UNBIND_URI);
1097 ump->client_index = utm->my_client_index;
1098 memcpy (ump->uri, utm->uri, vec_len (utm->uri));
1099 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & ump);
1100}
1101
Florin Corasa5464812017-04-19 13:00:05 -07001102int
1103server_unbind (uri_tcp_test_main_t * utm)
1104{
1105 server_send_unbind (utm);
1106 if (wait_for_state_change (utm, STATE_START))
1107 {
1108 clib_warning ("timeout waiting for STATE_START");
1109 return -1;
1110 }
1111 return 0;
1112}
1113
Florin Corase04c2992017-03-01 08:17:34 -08001114void
Florin Coras90a63982017-12-19 04:50:01 -08001115server_run (uri_tcp_test_main_t * utm)
Florin Corase04c2992017-03-01 08:17:34 -08001116{
Florin Coras90a63982017-12-19 04:50:01 -08001117 session_t *session;
1118 int i;
1119
1120 /* $$$$ hack preallocation */
1121 for (i = 0; i < 200000; i++)
1122 {
1123 pool_get (utm->sessions, session);
1124 memset (session, 0, sizeof (*session));
1125 }
1126 for (i = 0; i < 200000; i++)
1127 pool_put_index (utm->sessions, i);
1128
Florin Corasa5464812017-04-19 13:00:05 -07001129 if (application_attach (utm))
1130 return;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001131
Dave Barach68b0fb02017-02-28 15:15:56 -05001132 /* Bind to uri */
Florin Corasa5464812017-04-19 13:00:05 -07001133 if (server_listen (utm))
1134 return;
Dave Barach68b0fb02017-02-28 15:15:56 -05001135
1136 /* Enter handle event loop */
Florin Corase04c2992017-03-01 08:17:34 -08001137 server_handle_event_queue (utm);
Dave Barach68b0fb02017-02-28 15:15:56 -05001138
1139 /* Cleanup */
Florin Corasa5464812017-04-19 13:00:05 -07001140 server_send_unbind (utm);
Dave Barach68b0fb02017-02-28 15:15:56 -05001141
Florin Coras6cf30ad2017-04-04 23:08:23 -07001142 application_detach (utm);
1143
Dave Barach68b0fb02017-02-28 15:15:56 -05001144 fformat (stdout, "Test complete...\n");
1145}
1146
Florin Corase69f4952017-03-07 10:06:24 -08001147static void
1148vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t *
1149 mp)
1150{
Florin Coras6792ec02017-03-13 03:49:51 -07001151 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
Florin Corasf03a59a2017-06-09 21:07:32 -07001152 session_t *session;
Florin Coras6792ec02017-03-13 03:49:51 -07001153
Florin Corasf03a59a2017-06-09 21:07:32 -07001154 if (mp->retval)
1155 {
1156 clib_warning ("vpp complained about disconnect: %d",
1157 ntohl (mp->retval));
1158 }
1159
Florin Coras6792ec02017-03-13 03:49:51 -07001160 utm->state = STATE_START;
Florin Corasf03a59a2017-06-09 21:07:32 -07001161 session = pool_elt_at_index (utm->sessions, utm->connected_session_index);
1162 if (session)
1163 session_print_stats (utm, session);
Florin Corase69f4952017-03-07 10:06:24 -08001164}
1165
Florin Coras90a63982017-12-19 04:50:01 -08001166#define foreach_uri_msg \
1167_(BIND_URI_REPLY, bind_uri_reply) \
1168_(UNBIND_URI_REPLY, unbind_uri_reply) \
1169_(ACCEPT_SESSION, accept_session) \
1170_(CONNECT_SESSION_REPLY, connect_session_reply) \
1171_(DISCONNECT_SESSION, disconnect_session) \
1172_(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \
1173_(RESET_SESSION, reset_session) \
1174_(APPLICATION_ATTACH_REPLY, application_attach_reply) \
1175_(APPLICATION_DETACH_REPLY, application_detach_reply) \
1176_(MAP_ANOTHER_SEGMENT, map_another_segment) \
Dave Barach68b0fb02017-02-28 15:15:56 -05001177
1178void
1179uri_api_hookup (uri_tcp_test_main_t * utm)
1180{
1181#define _(N,n) \
1182 vl_msg_api_set_handlers(VL_API_##N, #n, \
1183 vl_api_##n##_t_handler, \
1184 vl_noop_handler, \
1185 vl_api_##n##_t_endian, \
1186 vl_api_##n##_t_print, \
1187 sizeof(vl_api_##n##_t), 1);
1188 foreach_uri_msg;
1189#undef _
1190}
1191
1192int
1193main (int argc, char **argv)
1194{
1195 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
1196 unformat_input_t _argv, *a = &_argv;
1197 u8 *chroot_prefix;
Florin Corase69f4952017-03-07 10:06:24 -08001198 u8 *heap, *uri = 0;
1199 u8 *bind_uri = (u8 *) "tcp://0.0.0.0/1234";
1200 u8 *connect_uri = (u8 *) "tcp://6.0.1.2/1234";
Florin Coras6cf30ad2017-04-04 23:08:23 -07001201 u64 bytes_to_send = 64 << 10, mbytes;
Dave Barach68b0fb02017-02-28 15:15:56 -05001202 u32 tmp;
1203 mheap_t *h;
Florin Corase04c2992017-03-01 08:17:34 -08001204 int i_am_master = 1, drop_packets = 0, test_return_packets = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001205
1206 clib_mem_init (0, 256 << 20);
1207
1208 heap = clib_mem_get_per_cpu_heap ();
1209 h = mheap_header (heap);
1210
1211 /* make the main heap thread-safe */
1212 h->flags |= MHEAP_FLAG_THREAD_SAFE;
1213
Florin Corasf03a59a2017-06-09 21:07:32 -07001214 vec_validate (utm->rx_buf, 128 << 10);
Dave Barach68b0fb02017-02-28 15:15:56 -05001215
Florin Corase04c2992017-03-01 08:17:34 -08001216 utm->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
Dave Barach68b0fb02017-02-28 15:15:56 -05001217
Florin Corase04c2992017-03-01 08:17:34 -08001218 utm->my_pid = getpid ();
1219 utm->configured_segment_size = 1 << 20;
Florin Coras90a63982017-12-19 04:50:01 -08001220 utm->socket_name = 0;
1221 utm->use_sock_api = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -05001222
1223 clib_time_init (&utm->clib_time);
1224 init_error_string_table (utm);
Florin Corase04c2992017-03-01 08:17:34 -08001225 svm_fifo_segment_init (0x200000000ULL, 20);
Dave Barach68b0fb02017-02-28 15:15:56 -05001226 unformat_init_command_line (a, argv);
1227
1228 while (unformat_check_input (a) != UNFORMAT_END_OF_INPUT)
1229 {
1230 if (unformat (a, "chroot prefix %s", &chroot_prefix))
Florin Corase04c2992017-03-01 08:17:34 -08001231 {
1232 vl_set_memory_root_path ((char *) chroot_prefix);
1233 }
Florin Corase69f4952017-03-07 10:06:24 -08001234 else if (unformat (a, "uri %s", &uri))
Florin Corase04c2992017-03-01 08:17:34 -08001235 ;
Dave Barach68b0fb02017-02-28 15:15:56 -05001236 else if (unformat (a, "segment-size %dM", &tmp))
Florin Corase04c2992017-03-01 08:17:34 -08001237 utm->configured_segment_size = tmp << 20;
Dave Barach68b0fb02017-02-28 15:15:56 -05001238 else if (unformat (a, "segment-size %dG", &tmp))
Florin Corase04c2992017-03-01 08:17:34 -08001239 utm->configured_segment_size = tmp << 30;
Dave Barach68b0fb02017-02-28 15:15:56 -05001240 else if (unformat (a, "master"))
Florin Corase04c2992017-03-01 08:17:34 -08001241 i_am_master = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -05001242 else if (unformat (a, "slave"))
Florin Corase04c2992017-03-01 08:17:34 -08001243 i_am_master = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001244 else if (unformat (a, "drop"))
Florin Corase04c2992017-03-01 08:17:34 -08001245 drop_packets = 1;
1246 else if (unformat (a, "test"))
1247 test_return_packets = 1;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001248 else if (unformat (a, "mbytes %lld", &mbytes))
Florin Coras6792ec02017-03-13 03:49:51 -07001249 {
1250 bytes_to_send = mbytes << 20;
1251 }
Florin Coras6cf30ad2017-04-04 23:08:23 -07001252 else if (unformat (a, "gbytes %lld", &mbytes))
1253 {
1254 bytes_to_send = mbytes << 30;
1255 }
Florin Coras90a63982017-12-19 04:50:01 -08001256 else if (unformat (a, "socket-name %s", &utm->socket_name))
1257 ;
1258 else if (unformat (a, "use-svm-api"))
1259 utm->use_sock_api = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001260 else
Florin Corase04c2992017-03-01 08:17:34 -08001261 {
1262 fformat (stderr, "%s: usage [master|slave]\n");
1263 exit (1);
1264 }
Dave Barach68b0fb02017-02-28 15:15:56 -05001265 }
1266
Florin Coras90a63982017-12-19 04:50:01 -08001267 if (!utm->socket_name)
1268 utm->socket_name = format (0, "%s%c", API_SOCKET_FILE, 0);
1269
Florin Corase69f4952017-03-07 10:06:24 -08001270 if (uri)
1271 {
1272 utm->uri = format (0, "%s%c", uri, 0);
1273 utm->connect_uri = format (0, "%s%c", uri, 0);
1274 }
1275 else
1276 {
1277 utm->uri = format (0, "%s%c", bind_uri, 0);
1278 utm->connect_uri = format (0, "%s%c", connect_uri, 0);
1279 }
1280
Dave Barach68b0fb02017-02-28 15:15:56 -05001281 utm->i_am_master = i_am_master;
1282 utm->segment_main = &svm_fifo_segment_main;
1283 utm->drop_packets = drop_packets;
Florin Corase04c2992017-03-01 08:17:34 -08001284 utm->test_return_packets = test_return_packets;
Florin Coras6792ec02017-03-13 03:49:51 -07001285 utm->bytes_to_send = bytes_to_send;
Florin Corasf03a59a2017-06-09 21:07:32 -07001286 utm->time_to_stop = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001287
Florin Corase04c2992017-03-01 08:17:34 -08001288 setup_signal_handlers ();
Dave Barach68b0fb02017-02-28 15:15:56 -05001289 uri_api_hookup (utm);
1290
Florin Coras90a63982017-12-19 04:50:01 -08001291 if (connect_to_vpp (i_am_master ? "tcp_echo_server" : "tcp_echo_client") <
1292 0)
Dave Barach68b0fb02017-02-28 15:15:56 -05001293 {
1294 svm_region_exit ();
1295 fformat (stderr, "Couldn't connect to vpe, exiting...\n");
1296 exit (1);
1297 }
1298
1299 if (i_am_master == 0)
Florin Coras90a63982017-12-19 04:50:01 -08001300 client_run (utm);
1301 else
1302 server_run (utm);
Dave Barach68b0fb02017-02-28 15:15:56 -05001303
Florin Coras90a63982017-12-19 04:50:01 -08001304 disconnect_from_vpp (utm);
Dave Barach68b0fb02017-02-28 15:15:56 -05001305 exit (0);
1306}
Florin Corase04c2992017-03-01 08:17:34 -08001307
1308/*
1309 * fd.io coding-style-patch-verification: ON
1310 *
1311 * Local Variables:
1312 * eval: (c-set-style "gnu")
1313 * End:
1314 */