blob: ed5a37d813b6912868c829c767553fca01f20ff5 [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>
18#include <vlib/vlib.h>
19#include <vnet/vnet.h>
20#include <svm/svm_fifo_segment.h>
21#include <vlibmemory/api.h>
22#include <vpp/api/vpe_msg_enum.h>
23
24#include "../vnet/session/application_interface.h"
25
26#define vl_typedefs /* define message structures */
27#include <vpp/api/vpe_all_api_h.h>
28#undef vl_typedefs
29
30/* declare message handlers for each api */
31
32#define vl_endianfun /* define message structures */
33#include <vpp/api/vpe_all_api_h.h>
34#undef vl_endianfun
35
36/* instantiate all the print functions we know about */
37#define vl_print(handle, ...)
38#define vl_printfun
39#include <vpp/api/vpe_all_api_h.h>
40#undef vl_printfun
41
42/* Satisfy external references when not linking with -lvlib */
43vlib_main_t vlib_global_main;
44vlib_main_t **vlib_mains;
45
46typedef struct
47{
48 svm_fifo_t * server_rx_fifo;
49 svm_fifo_t * server_tx_fifo;
50
51 u32 vpp_session_index;
52 u32 vpp_session_thread;
53} session_t;
54
55typedef enum
56{
57 STATE_START,
58 STATE_READY,
59 STATE_DISCONNECTING,
60 STATE_FAILED
61} connection_state_t;
62
63typedef struct
64{
65 /* vpe input queue */
66 unix_shared_memory_queue_t *vl_input_queue;
67
68 /* API client handle */
69 u32 my_client_index;
70
71 /* The URI we're playing with */
72 u8 * uri;
73
74 /* Session pool */
75 session_t * sessions;
76
77 /* Hash table for disconnect processing */
78 uword * session_index_by_vpp_handles;
79
80 /* intermediate rx buffer */
81 u8 * rx_buf;
82
83 /* URI for slave's connect */
84 u8 * connect_uri;
85
86 u32 connected_session_index;
87
88 int i_am_master;
89
90 /* drop all packets */
91 int drop_packets;
92
93 /* Our event queue */
94 unix_shared_memory_queue_t * our_event_queue;
95
96 /* $$$ single thread only for the moment */
97 unix_shared_memory_queue_t * vpp_event_queue;
98
99 pid_t my_pid;
100
101 /* For deadman timers */
102 clib_time_t clib_time;
103
104 /* State of the connection, shared between msg RX thread and main thread */
105 volatile connection_state_t state;
106
107 /* Signal variables */
108 volatile int time_to_stop;
109 volatile int time_to_print_stats;
110
111 u32 configured_segment_size;
112
113 /* VNET_API_ERROR_FOO -> "Foo" hash table */
114 uword * error_string_by_error_number;
115
116 /* convenience */
117 svm_fifo_segment_main_t * segment_main;
118
119 u8 *connect_test_data;
120} uri_tcp_test_main_t;
121
122uri_tcp_test_main_t uri_tcp_test_main;
123
124#if CLIB_DEBUG > 0
125#define NITER 10000
126#else
127#define NITER 4000000
128#endif
129
130int
131wait_for_state_change (uri_tcp_test_main_t * utm, connection_state_t state)
132{
133#if CLIB_DEBUG > 0
134#define TIMEOUT 600.0
135#else
136#define TIMEOUT 600.0
137#endif
138
139 f64 timeout = clib_time_now (&utm->clib_time) + TIMEOUT;
140
141 while (clib_time_now (&utm->clib_time) < timeout)
142 {
143 if (utm->state == state)
144 return 0;
145 if (utm->state == STATE_FAILED)
146 return -1;
147 }
148 clib_warning ("timeout waiting for STATE_READY");
149 return -1;
150}
151
152static void
153init_error_string_table (uri_tcp_test_main_t * utm)
154{
155 utm->error_string_by_error_number = hash_create (0, sizeof (uword));
156
157#define _(n,v,s) hash_set (utm->error_string_by_error_number, -v, s);
158 foreach_vnet_api_error;
159#undef _
160
161 hash_set (utm->error_string_by_error_number, 99, "Misc");
162}
163
164static void
165stop_signal (int signum)
166{
167 uri_tcp_test_main_t *um = &uri_tcp_test_main;
168
169 um->time_to_stop = 1;
170}
171
172static void
173stats_signal (int signum)
174{
175 uri_tcp_test_main_t *um = &uri_tcp_test_main;
176
177 um->time_to_print_stats = 1;
178}
179
180static clib_error_t *
181setup_signal_handlers (void)
182{
183 signal (SIGINT, stats_signal);
184 signal (SIGQUIT, stop_signal);
185 signal (SIGTERM, stop_signal);
186
187 return 0;
188}
189
190void
191vlib_cli_output (struct vlib_main_t *vm, char *fmt, ...)
192{
193 clib_warning ("BUG");
194}
195
196int
197connect_to_vpp (char *name)
198{
199 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
200 api_main_t *am = &api_main;
201
202 if (vl_client_connect_to_vlib ("/vpe-api", name, 32) < 0)
203 return -1;
204
205 utm->vl_input_queue = am->shmem_hdr->vl_input_queue;
206 utm->my_client_index = am->my_client_index;
207
208 return 0;
209}
210
211static void
212vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t *mp)
213{
214 svm_fifo_segment_create_args_t _a, *a = &_a;
215 int rv;
216
217 a->segment_name = (char *) mp->segment_name;
218 a->segment_size = mp->segment_size;
219 /* Attach to the segment vpp created */
220 rv = svm_fifo_segment_attach (a);
221 if (rv)
222 {
223 clib_warning ("svm_fifo_segment_attach ('%s') failed",
224 mp->segment_name);
225 return;
226 }
227 clib_warning ("Mapped new segment '%s' size %d", mp->segment_name,
228 mp->segment_size);
229}
230
231static void
232vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp)
233{
234 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
235 session_t * session;
236 vl_api_disconnect_session_reply_t * rmp;
237 uword * p;
238 int rv = 0;
239 u64 key;
240
241 key = (((u64)mp->session_thread_index) << 32) | (u64)mp->session_index;
242
243 p = hash_get (utm->session_index_by_vpp_handles, key);
244
245 if (p)
246 {
247 session = pool_elt_at_index (utm->sessions, p[0]);
248 hash_unset (utm->session_index_by_vpp_handles, key);
249 pool_put (utm->sessions, session);
250 }
251 else
252 {
253 clib_warning ("couldn't find session key %llx", key);
254 rv = -11;
255 }
256
257 rmp = vl_msg_api_alloc (sizeof (*rmp));
258 memset (rmp, 0, sizeof (*rmp));
259
260 rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY);
261 rmp->retval = rv;
262 rmp->session_index = mp->session_index;
263 rmp->session_thread_index = mp->session_thread_index;
264 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *)&rmp);
265}
266
267static void
268vl_api_reset_session_t_handler (vl_api_reset_session_t * mp)
269{
270 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
271 session_t * session;
272 vl_api_reset_session_reply_t * rmp;
273 uword * p;
274 int rv = 0;
275 u64 key;
276
277 key = (((u64)mp->session_thread_index) << 32) | (u64)mp->session_index;
278
279 p = hash_get(utm->session_index_by_vpp_handles, key);
280
281 if (p)
282 {
283 session = pool_elt_at_index(utm->sessions, p[0]);
284 hash_unset(utm->session_index_by_vpp_handles, key);
285 pool_put(utm->sessions, session);
286 }
287 else
288 {
289 clib_warning("couldn't find session key %llx", key);
290 rv = -11;
291 }
292
293 rmp = vl_msg_api_alloc (sizeof (*rmp));
294 memset (rmp, 0, sizeof (*rmp));
295 rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY);
296 rmp->retval = rv;
297 rmp->session_index = mp->session_index;
298 rmp->session_thread_index = mp->session_thread_index;
299 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *)&rmp);
300}
301
302void
303handle_fifo_event_connect_rx (uri_tcp_test_main_t *utm, session_fifo_event_t * e)
304{
305 svm_fifo_t * rx_fifo;
306 int n_read, bytes;
307
308 rx_fifo = e->fifo;
309
310 bytes = e->enqueue_length;
311 do
312 {
313 n_read = svm_fifo_dequeue_nowait (rx_fifo, 0, vec_len(utm->rx_buf),
314 utm->rx_buf);
315 if (n_read > 0)
316 bytes -= n_read;
317 }
318 while (n_read < 0 || bytes > 0);
319
320 // bytes_to_read = svm_fifo_max_dequeue (rx_fifo);
321 //
322 // bytes_to_read = vec_len(utm->rx_buf) > bytes_to_read ?
323 // bytes_to_read : vec_len(utm->rx_buf);
324 //
325 // buffer_offset = 0;
326 // while (bytes_to_read > 0)
327 // {
328 // rv = svm_fifo_dequeue_nowait2 (rx_fifo, mypid,
329 // bytes_to_read,
330 // utm->rx_buf + buffer_offset);
331 // if (rv > 0)
332 // {
333 // bytes_to_read -= rv;
334 // buffer_offset += rv;
335 // bytes_received += rv;
336 // }
337 // }
338
339
340 // while (bytes_received < bytes_sent)
341 // {
342 // rv = svm_fifo_dequeue_nowait2 (rx_fifo, mypid,
343 // vec_len (utm->rx_buf),
344 // utm->rx_buf);
345 // if (rv > 0)
346 // {
347 //#if CLIB_DEBUG > 0
348 // int j;
349 // for (j = 0; j < rv; j++)
350 // {
351 // if (utm->rx_buf[j] != ((bytes_received + j) & 0xff))
352 // {
353 // clib_warning ("error at byte %lld, 0x%x not 0x%x",
354 // bytes_received + j,
355 // utm->rx_buf[j],
356 // ((bytes_received + j )&0xff));
357 // }
358 // }
359 //#endif
360 // bytes_received += (u64) rv;
361 // }
362 // }
363}
364
365void
366handle_connect_event_queue (uri_tcp_test_main_t * utm)
367{
368 session_fifo_event_t _e, *e = &_e;;
369
370 unix_shared_memory_queue_sub (utm->our_event_queue, (u8 *) e, 0 /* nowait */);
371 switch (e->event_type)
372 {
373 case FIFO_EVENT_SERVER_RX:
374 handle_fifo_event_connect_rx (utm, e);
375 break;
376
377 case FIFO_EVENT_SERVER_EXIT:
378 return;
379
380 default:
381 clib_warning("unknown event type %d", e->event_type);
382 break;
383 }
384}
385
386void
387uri_tcp_connect_send (uri_tcp_test_main_t *utm)
388{
389 u8 *test_data = utm->connect_test_data;
390 u64 bytes_sent = 0;
391 int rv;
392 int mypid = getpid();
393 session_t * session;
394 svm_fifo_t *tx_fifo;
395 int buffer_offset, bytes_to_send = 0;
396 session_fifo_event_t evt;
397 static int serial_number = 0;
398 int i;
399 u32 max_chunk = 64 << 10, write;
400
401 session = pool_elt_at_index (utm->sessions, utm->connected_session_index);
402 tx_fifo = session->server_tx_fifo;
403
404 vec_validate (utm->rx_buf, vec_len (test_data) - 1);
405
406 for (i = 0; i < 10; i++)
407 {
408 bytes_to_send = vec_len (test_data);
409 buffer_offset = 0;
410 while (bytes_to_send > 0)
411 {
412 write = bytes_to_send > max_chunk ? max_chunk : bytes_to_send;
413 rv = svm_fifo_enqueue_nowait (tx_fifo, mypid, write,
414 test_data + buffer_offset);
415
416 if (rv > 0)
417 {
418 bytes_to_send -= rv;
419 buffer_offset += rv;
420 bytes_sent += rv;
421
422 /* Fabricate TX event, send to vpp */
423 evt.fifo = tx_fifo;
424 evt.event_type = FIFO_EVENT_SERVER_TX;
425 /* $$$$ for event logging */
426 evt.enqueue_length = rv;
427 evt.event_id = serial_number++;
428
429 unix_shared_memory_queue_add (utm->vpp_event_queue, (u8 *) &evt,
430 0 /* do wait for mutex */);
431 }
432 }
433 }
434}
435
436static void
437uri_tcp_client_test (uri_tcp_test_main_t * utm)
438{
439 vl_api_connect_uri_t * cmp;
440 vl_api_disconnect_session_t *dmp;
441 session_t *connected_session;
442 int i;
443
444 cmp = vl_msg_api_alloc (sizeof (*cmp));
445 memset (cmp, 0, sizeof (*cmp));
446
447 cmp->_vl_msg_id = ntohs (VL_API_CONNECT_URI);
448 cmp->client_index = utm->my_client_index;
449 cmp->context = ntohl(0xfeedface);
450 memcpy (cmp->uri, utm->connect_uri, vec_len (utm->connect_uri));
451 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *)&cmp);
452
453 if (wait_for_state_change (utm, STATE_READY))
454 {
455 return;
456 }
457
458 /* Init test data */
459 vec_validate (utm->connect_test_data, 64 * 1024 - 1);
460 for (i = 0; i < vec_len (utm->connect_test_data); i++)
461 utm->connect_test_data[i] = i & 0xff;
462
463 /* Start reader thread */
464 /* handle_connect_event_queue (utm); */
465
466 /* Start send */
467 uri_tcp_connect_send (utm);
468
469 /* Disconnect */
470 connected_session = pool_elt_at_index(utm->sessions,
471 utm->connected_session_index);
472 dmp = vl_msg_api_alloc (sizeof (*dmp));
473 memset (dmp, 0, sizeof (*dmp));
474 dmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION);
475 dmp->client_index = utm->my_client_index;
476 dmp->session_index = connected_session->vpp_session_index;
477 dmp->session_thread_index = connected_session->vpp_session_thread;
478 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *)&dmp);
479}
480
481void
482handle_fifo_event_server_rx (uri_tcp_test_main_t *utm, session_fifo_event_t * e)
483{
484 svm_fifo_t * rx_fifo, * tx_fifo;
485 int n_read;
486
487 session_fifo_event_t evt;
488 unix_shared_memory_queue_t *q;
489 int rv, bytes;
490
491 rx_fifo = e->fifo;
492 tx_fifo = utm->sessions[rx_fifo->client_session_index].server_tx_fifo;
493
494 bytes = e->enqueue_length;
495 do
496 {
497 n_read = svm_fifo_dequeue_nowait (rx_fifo, 0, vec_len(utm->rx_buf),
498 utm->rx_buf);
499
500 /* Reflect if a non-drop session */
501 if (!utm->drop_packets && n_read > 0)
502 {
503 do
504 {
505 rv = svm_fifo_enqueue_nowait (tx_fifo, 0, n_read, utm->rx_buf);
506 }
507 while (rv == -2);
508
509 /* Fabricate TX event, send to vpp */
510 evt.fifo = tx_fifo;
511 evt.event_type = FIFO_EVENT_SERVER_TX;
512 /* $$$$ for event logging */
513 evt.enqueue_length = n_read;
514 evt.event_id = e->event_id;
515 q = utm->vpp_event_queue;
516 unix_shared_memory_queue_add (q, (u8 *) &evt, 0 /* do wait for mutex */);
517 }
518
519 if (n_read > 0)
520 bytes -= n_read;
521 }
522 while (n_read < 0 || bytes > 0);
523}
524
525void
526handle_event_queue (uri_tcp_test_main_t * utm)
527{
528 session_fifo_event_t _e, *e = &_e;;
529
530 while (1)
531 {
532 unix_shared_memory_queue_sub (utm->our_event_queue, (u8 *)e,
533 0 /* nowait */);
534 switch (e->event_type)
535 {
536 case FIFO_EVENT_SERVER_RX:
537 handle_fifo_event_server_rx (utm, e);
538 break;
539
540 case FIFO_EVENT_SERVER_EXIT:
541 return;
542
543 default:
544 clib_warning ("unknown event type %d", e->event_type);
545 break;
546 }
547 if (PREDICT_FALSE(utm->time_to_stop == 1))
548 break;
549 if (PREDICT_FALSE(utm->time_to_print_stats == 1))
550 {
551 utm->time_to_print_stats = 0;
552 fformat(stdout, "%d connections\n", pool_elts (utm->sessions));
553 }
554 }
555}
556
557static void
558vl_api_bind_uri_reply_t_handler (vl_api_bind_uri_reply_t * mp)
559{
560 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
561 svm_fifo_segment_create_args_t _a, *a = &_a;
562 int rv;
563
564 if (mp->retval)
565 {
566 clib_warning("bind failed: %d", mp->retval);
567 return;
568 }
569
570 if (mp->segment_name_length == 0)
571 {
572 clib_warning("segment_name_length zero");
573 return;
574 }
575
576 a->segment_name = (char *) mp->segment_name;
577 a->segment_size = mp->segment_size;
578
579 ASSERT(mp->server_event_queue_address);
580
581 /* Attach to the segment vpp created */
582 rv = svm_fifo_segment_attach (a);
583 if (rv)
584 {
585 clib_warning("svm_fifo_segment_attach ('%s') failed", mp->segment_name);
586 return;
587 }
588
589 utm->our_event_queue =
590 (unix_shared_memory_queue_t *) mp->server_event_queue_address;
591
592 utm->state = STATE_READY;
593}
594
595static void
596vl_api_connect_uri_reply_t_handler (vl_api_connect_uri_reply_t * mp)
597{
598 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
599 svm_fifo_segment_create_args_t _a, *a = &_a;
600 session_t *session;
601 u32 session_index;
602 svm_fifo_t *rx_fifo, *tx_fifo;
603 int rv;
604
605 if (mp->retval)
606 {
607 clib_warning ("connection failed with code: %d", mp->retval);
608 utm->state = STATE_FAILED;
609 return;
610 }
611 /*
612 * Attatch to segment
613 */
614
615 if (mp->segment_name_length == 0)
616 {
617 clib_warning ("segment_name_length zero");
618 utm->state = STATE_FAILED;
619 return;
620 }
621
622 a->segment_name = (char *) mp->segment_name;
623 a->segment_size = mp->segment_size;
624
625 ASSERT(mp->client_event_queue_address);
626
627 /* Attach to the segment vpp created */
628 rv = svm_fifo_segment_attach (a);
629 if (rv)
630 {
631 clib_warning ("svm_fifo_segment_attach ('%s') failed",
632 mp->segment_name);
633 return;
634 }
635
636 /*
637 * Save the queues
638 */
639
640 utm->our_event_queue = (unix_shared_memory_queue_t *)
641 mp->client_event_queue_address;
642
643 utm->vpp_event_queue = (unix_shared_memory_queue_t *)
644 mp->vpp_event_queue_address;
645
646 /*
647 * Setup session
648 */
649
650 pool_get (utm->sessions, session);
651 session_index = session - utm->sessions;
652
653 rx_fifo = (svm_fifo_t *)mp->server_rx_fifo;
654 rx_fifo->client_session_index = session_index;
655 tx_fifo = (svm_fifo_t *)mp->server_tx_fifo;
656 tx_fifo->client_session_index = session_index;
657
658 session->server_rx_fifo = rx_fifo;
659 session->server_tx_fifo = tx_fifo;
660 session->vpp_session_index = mp->session_index;
661 session->vpp_session_thread = mp->session_thread_index;
662
663 /* Save handle */
664 utm->connected_session_index = session_index;
665
666 utm->state = STATE_READY;
667}
668
669void
670uri_tcp_bind (uri_tcp_test_main_t *utm)
671{
672 vl_api_bind_uri_t * bmp;
673 u32 fifo_size = 3 << 20;
674 bmp = vl_msg_api_alloc (sizeof (*bmp));
675 memset (bmp, 0, sizeof (*bmp));
676
677 bmp->_vl_msg_id = ntohs (VL_API_BIND_URI);
678 bmp->client_index = utm->my_client_index;
679 bmp->context = ntohl(0xfeedface);
680 bmp->initial_segment_size = 256<<20; /* size of initial segment */
681 bmp->options[SESSION_OPTIONS_FLAGS] =
682 SESSION_OPTIONS_FLAGS_USE_FIFO | SESSION_OPTIONS_FLAGS_ADD_SEGMENT;
683 bmp->options[SESSION_OPTIONS_RX_FIFO_SIZE] = fifo_size;
684 bmp->options[SESSION_OPTIONS_TX_FIFO_SIZE] = fifo_size;
685 bmp->options[SESSION_OPTIONS_ADD_SEGMENT_SIZE] = 128<<20;
686 memcpy (bmp->uri, utm->uri, vec_len (utm->uri));
687 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *)&bmp);
688}
689
690static void
691vl_api_unbind_uri_reply_t_handler (vl_api_unbind_uri_reply_t *mp)
692{
693 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
694
695 if (mp->retval != 0)
696 clib_warning ("returned %d", ntohl(mp->retval));
697
698 utm->state = STATE_START;
699}
700
701void
702uri_tcp_unbind (uri_tcp_test_main_t *utm)
703{
704 vl_api_unbind_uri_t * ump;
705
706 ump = vl_msg_api_alloc (sizeof (*ump));
707 memset (ump, 0, sizeof (*ump));
708
709 ump->_vl_msg_id = ntohs (VL_API_UNBIND_URI);
710 ump->client_index = utm->my_client_index;
711 memcpy (ump->uri, utm->uri, vec_len (utm->uri));
712 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *)&ump);
713}
714
715static void
716vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
717{
718 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
719 vl_api_accept_session_reply_t *rmp;
720 svm_fifo_t * rx_fifo, * tx_fifo;
721 session_t * session;
722 static f64 start_time;
723 u64 key;
724 u32 session_index;
725
726 if (start_time == 0.0)
727 start_time = clib_time_now (&utm->clib_time);
728
729 utm->vpp_event_queue = (unix_shared_memory_queue_t *)
730 mp->vpp_event_queue_address;
731
732 /* Allocate local session and set it up */
733 pool_get (utm->sessions, session);
734 session_index = session - utm->sessions;
735
736 rx_fifo = (svm_fifo_t *)mp->server_rx_fifo;
737 rx_fifo->client_session_index = session_index;
738 tx_fifo = (svm_fifo_t *)mp->server_tx_fifo;
739 tx_fifo->client_session_index = session_index;
740
741 session->server_rx_fifo = rx_fifo;
742 session->server_tx_fifo = tx_fifo;
743
744 /* Add it to lookup table */
745 key = (((u64)mp->session_thread_index) << 32) | (u64)mp->session_index;
746 hash_set (utm->session_index_by_vpp_handles, key, session_index);
747
748 utm->state = STATE_READY;
749
750 /* Stats printing */
751 if (pool_elts (utm->sessions) && (pool_elts(utm->sessions) % 20000) == 0)
752 {
753 f64 now = clib_time_now (&utm->clib_time);
754 fformat (stdout, "%d active sessions in %.2f seconds, %.2f/sec...\n",
755 pool_elts(utm->sessions), now - start_time,
756 (f64)pool_elts(utm->sessions) / (now - start_time));
757 }
758
759 /* Send accept reply to vpp */
760 rmp = vl_msg_api_alloc (sizeof (*rmp));
761 memset (rmp, 0, sizeof (*rmp));
762 rmp->_vl_msg_id = ntohs (VL_API_ACCEPT_SESSION_REPLY);
763 rmp->session_type = mp->session_type;
764 rmp->session_index = mp->session_index;
765 rmp->session_thread_index = mp->session_thread_index;
766 vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *)&rmp);
767}
768
769void
770uri_tcp_server_test (uri_tcp_test_main_t * utm)
771{
772
773 /* Bind to uri */
774 uri_tcp_bind (utm);
775
776 if (wait_for_state_change (utm, STATE_READY))
777 {
778 clib_warning ("timeout waiting for STATE_READY");
779 return;
780 }
781
782 /* Enter handle event loop */
783 handle_event_queue (utm);
784
785 /* Cleanup */
786 uri_tcp_unbind (utm);
787
788 if (wait_for_state_change (utm, STATE_START))
789 {
790 clib_warning ("timeout waiting for STATE_START");
791 return;
792 }
793
794 fformat (stdout, "Test complete...\n");
795}
796
797#define foreach_uri_msg \
798_(BIND_URI_REPLY, bind_uri_reply) \
799_(UNBIND_URI_REPLY, unbind_uri_reply) \
800_(ACCEPT_SESSION, accept_session) \
801_(CONNECT_URI_REPLY, connect_uri_reply) \
802_(DISCONNECT_SESSION, disconnect_session) \
803_(RESET_SESSION, reset_session) \
804_(MAP_ANOTHER_SEGMENT, map_another_segment)
805
806void
807uri_api_hookup (uri_tcp_test_main_t * utm)
808{
809#define _(N,n) \
810 vl_msg_api_set_handlers(VL_API_##N, #n, \
811 vl_api_##n##_t_handler, \
812 vl_noop_handler, \
813 vl_api_##n##_t_endian, \
814 vl_api_##n##_t_print, \
815 sizeof(vl_api_##n##_t), 1);
816 foreach_uri_msg;
817#undef _
818}
819
820int
821main (int argc, char **argv)
822{
823 uri_tcp_test_main_t *utm = &uri_tcp_test_main;
824 unformat_input_t _argv, *a = &_argv;
825 u8 *chroot_prefix;
826 u8 *heap;
827 u8 * bind_name = (u8 *) "tcp://0.0.0.0/1234";
828 u32 tmp;
829 mheap_t *h;
830 session_t * session;
831 int i;
832 int i_am_master = 1, drop_packets = 0;
833
834 clib_mem_init (0, 256 << 20);
835
836 heap = clib_mem_get_per_cpu_heap ();
837 h = mheap_header (heap);
838
839 /* make the main heap thread-safe */
840 h->flags |= MHEAP_FLAG_THREAD_SAFE;
841
842 vec_validate (utm->rx_buf, 65536);
843
844 utm->session_index_by_vpp_handles =
845 hash_create (0, sizeof(uword));
846
847 utm->my_pid = getpid();
848 utm->configured_segment_size = 1<<20;
849
850 clib_time_init (&utm->clib_time);
851 init_error_string_table (utm);
852 svm_fifo_segment_init(0x200000000ULL, 20);
853 unformat_init_command_line (a, argv);
854
855 while (unformat_check_input (a) != UNFORMAT_END_OF_INPUT)
856 {
857 if (unformat (a, "chroot prefix %s", &chroot_prefix))
858 {
859 vl_set_memory_root_path ((char *) chroot_prefix);
860 }
861 else if (unformat (a, "uri %s", &bind_name))
862 ;
863 else if (unformat (a, "segment-size %dM", &tmp))
864 utm->configured_segment_size = tmp<<20;
865 else if (unformat (a, "segment-size %dG", &tmp))
866 utm->configured_segment_size = tmp<<30;
867 else if (unformat (a, "master"))
868 i_am_master = 1;
869 else if (unformat (a, "slave"))
870 i_am_master = 0;
871 else if (unformat (a, "drop"))
872 drop_packets = 1;
873 else
874 {
875 fformat (stderr, "%s: usage [master|slave]\n");
876 exit (1);
877 }
878 }
879
880 utm->uri = format (0, "%s%c", bind_name, 0);
881 utm->i_am_master = i_am_master;
882 utm->segment_main = &svm_fifo_segment_main;
883 utm->drop_packets = drop_packets;
884
885 utm->connect_uri = format (0, "tcp://6.0.1.2/1234%c", 0);
886
887 setup_signal_handlers();
888 uri_api_hookup (utm);
889
890 if (connect_to_vpp (i_am_master? "uri_tcp_server":"uri_tcp_client") < 0)
891 {
892 svm_region_exit ();
893 fformat (stderr, "Couldn't connect to vpe, exiting...\n");
894 exit (1);
895 }
896
897 if (i_am_master == 0)
898 {
899 uri_tcp_client_test (utm);
900 exit (0);
901 }
902
903 /* $$$$ hack preallocation */
904 for (i = 0; i < 200000; i++)
905 {
906 pool_get (utm->sessions, session);
907 memset (session, 0, sizeof (*session));
908 }
909 for (i = 0; i < 200000; i++)
910 pool_put_index (utm->sessions, i);
911
912 uri_tcp_server_test (utm);
913
914 vl_client_disconnect_from_vlib ();
915 exit (0);
916}