FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
tcp_echo.c
Go to the documentation of this file.
1 /*
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 
20 #include <vlibmemory/api.h>
21 
22 #include <vpp/api/vpe_msg_enum.h>
23 #include <svm/fifo_segment.h>
24 
25 #define vl_typedefs /* define message structures */
26 #include <vpp/api/vpe_all_api_h.h>
27 #undef vl_typedefs
28 
29 /* declare message handlers for each api */
30 
31 #define vl_endianfun /* define message structures */
32 #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 
41 #define TCP_ECHO_DBG 0
42 #define DBG(_fmt,_args...) \
43  if (TCP_ECHO_DBG) \
44  clib_warning (_fmt, _args)
45 
46 typedef struct
47 {
48  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
49 #define _(type, name) type name;
51 #undef _
52  u64 vpp_session_handle;
53  u64 bytes_sent;
54  u64 bytes_to_send;
55  volatile u64 bytes_received;
56  volatile u64 bytes_to_receive;
57  f64 start;
59 
60 typedef enum
61 {
70 
71 typedef struct
72 {
73  /* vpe input queue */
74  svm_queue_t *vl_input_queue;
75 
76  /* API client handle */
77  u32 my_client_index;
78 
79  /* The URI we're playing with */
80  u8 *uri;
81 
82  /* Session pool */
83  echo_session_t *sessions;
84 
85  /* Hash table for disconnect processing */
86  uword *session_index_by_vpp_handles;
87 
88  /* intermediate rx buffer */
90 
91  /* URI for slave's connect */
93 
95 
96  int i_am_master;
97 
98  /* drop all packets */
99  int no_return;
100 
101  /* Our event queue */
102  svm_msg_q_t *our_event_queue;
103 
104  u8 *socket_name;
105 
106  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 
119 
120  /* VNET_API_ERROR_FOO -> "Foo" hash table */
122 
123  u8 *connect_test_data;
127  u8 test_return_packets;
128  u64 bytes_to_send;
129  u32 fifo_size;
130 
131  u32 n_clients;
132  u64 tx_total;
133  u64 rx_total;
134 
135  volatile u32 n_clients_connected;
137 
138 
139  /** 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 
144  fifo_segment_main_t segment_main;
145 } echo_main_t;
146 
148 
149 #if CLIB_DEBUG > 0
150 #define NITER 10000
151 #else
152 #define NITER 4000000
153 #endif
154 
155 static u8 *
156 format_api_error (u8 * s, va_list * args)
157 {
158  echo_main_t *em = &echo_main;
159  i32 error = va_arg (*args, u32);
160  uword *p;
161 
162  p = hash_get (em->error_string_by_error_number, -error);
163 
164  if (p)
165  s = format (s, "%s", p[0]);
166  else
167  s = format (s, "%d", error);
168  return s;
169 }
170 
171 static void
173 {
174  em->error_string_by_error_number = hash_create (0, sizeof (uword));
175 
176 #define _(n,v,s) hash_set (em->error_string_by_error_number, -v, s);
178 #undef _
179 
180  hash_set (em->error_string_by_error_number, 99, "Misc");
181 }
182 
183 static void handle_mq_event (session_event_t * e);
184 
185 static int
186 wait_for_state_change (echo_main_t * em, connection_state_t state)
187 {
188  svm_msg_q_msg_t msg;
189  session_event_t *e;
190  f64 timeout;
191 
192 #if CLIB_DEBUG > 0
193 #define TIMEOUT 600.0
194 #else
195 #define TIMEOUT 600.0
196 #endif
197 
198  timeout = clib_time_now (&em->clib_time) + TIMEOUT;
199 
200  while (clib_time_now (&em->clib_time) < timeout)
201  {
202  if (em->state == state)
203  return 0;
204  if (em->state == STATE_FAILED)
205  return -1;
206  if (em->time_to_stop == 1)
207  return 0;
208  if (!em->our_event_queue || em->state < STATE_ATTACHED)
209  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);
216  }
217  clib_warning ("timeout waiting for state %d", state);
218  return -1;
219 }
220 
221 void
223 {
227 
228  bmp = vl_msg_api_alloc (sizeof (*bmp));
229  clib_memset (bmp, 0, sizeof (*bmp));
230 
231  bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
232  bmp->client_index = em->my_client_index;
233  bmp->context = ntohl (0xfeedface);
234  bmp->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
235  bmp->options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ADD_SEGMENT;
239  bmp->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = 128 << 20;
240  bmp->options[APP_OPTIONS_SEGMENT_SIZE] = 256 << 20;
242  vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
243 
244  cert_mp = vl_msg_api_alloc (sizeof (*cert_mp) + test_srv_crt_rsa_len);
245  clib_memset (cert_mp, 0, sizeof (*cert_mp));
246  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);
251  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);
254  clib_memset (key_mp, 0, sizeof (*key_mp) + test_srv_key_rsa_len);
255  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);
260  vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & key_mp);
261 }
262 
263 static int
265 {
268  {
269  clib_warning ("timeout waiting for STATE_ATTACHED");
270  return -1;
271  }
272  return 0;
273 }
274 
275 void
277 {
279  bmp = vl_msg_api_alloc (sizeof (*bmp));
280  clib_memset (bmp, 0, sizeof (*bmp));
281 
282  bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
283  bmp->client_index = em->my_client_index;
284  bmp->context = ntohl (0xfeedface);
285  vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
286 
287  DBG ("%s", "Sent detach");
288 }
289 
290 static int
292 {
293  fifo_segment_create_args_t _a, *a = &_a;
294  fifo_segment_main_t *sm = &echo_main.segment_main;
295  int rv;
296 
297  clib_memset (a, 0, sizeof (*a));
298  a->segment_name = (char *) name;
299  a->segment_type = type;
300 
301  if (type == SSVM_SEGMENT_MEMFD)
302  a->memfd_fd = fd;
303 
304  if ((rv = fifo_segment_attach (sm, a)))
305  {
306  clib_warning ("svm_fifo_segment_attach ('%s') failed", name);
307  return rv;
308  }
309 
311  return 0;
312 }
313 
314 static void
316  mp)
317 {
318  echo_main_t *em = &echo_main;
319  int *fds = 0;
320  u32 n_fds = 0;
321 
322  if (mp->retval)
323  {
324  clib_warning ("attach failed: %U", format_api_error,
325  clib_net_to_host_u32 (mp->retval));
326  goto failed;
327  }
328 
329  if (mp->segment_name_length == 0)
330  {
331  clib_warning ("segment_name_length zero");
332  goto failed;
333  }
334 
337  svm_msg_q_t *);
338 
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)
355 
356  vec_free (fds);
357  }
358  else
359  {
361  -1))
362  goto failed;
363  }
364 
365  em->state = STATE_ATTACHED;
366  return;
367 failed:
368  em->state = STATE_FAILED;
369  return;
370 }
371 
372 static void
373 vl_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);
378  echo_main.state = STATE_DETACHED;
379 }
380 
381 static void
382 stop_signal (int signum)
383 {
384  echo_main_t *um = &echo_main;
385 
386  um->time_to_stop = 1;
387 }
388 
389 static void
390 stats_signal (int signum)
391 {
392  echo_main_t *um = &echo_main;
393 
394  um->time_to_print_stats = 1;
395 }
396 
397 static clib_error_t *
399 {
400  signal (SIGINT, stats_signal);
401  signal (SIGQUIT, stop_signal);
402  signal (SIGTERM, stop_signal);
403 
404  return 0;
405 }
406 
407 void
408 vlib_cli_output (struct vlib_main_t *vm, char *fmt, ...)
409 {
410  clib_warning ("BUG");
411 }
412 
413 int
415 {
416  echo_main_t *em = &echo_main;
417  api_main_t *am = &api_main;
418 
419  if (em->use_sock_api)
420  {
421  if (vl_socket_client_connect ((char *) em->socket_name, name,
422  0 /* default rx, tx buffer */ ))
423  {
424  clib_warning ("socket connect failed");
425  return -1;
426  }
427 
428  if (vl_socket_client_init_shm (0, 1 /* want_pthread */ ))
429  {
430  clib_warning ("init shm api failed");
431  return -1;
432  }
433  }
434  else
435  {
436  if (vl_client_connect_to_vlib ("/vpe-api", name, 32) < 0)
437  {
438  clib_warning ("shmem connect failed");
439  return -1;
440  }
441  }
444  return 0;
445 }
446 
447 void
449 {
450  if (em->use_sock_api)
452  else
454 }
455 
456 static void
458 {
459  fifo_segment_main_t *sm = &echo_main.segment_main;
460  fifo_segment_create_args_t _a, *a = &_a;
461  int rv;
462 
463  clib_memset (a, 0, sizeof (*a));
464  a->segment_name = (char *) mp->segment_name;
465  a->segment_size = mp->segment_size;
466  /* Attach to the segment vpp created */
467  rv = fifo_segment_attach (sm, a);
468  if (rv)
469  {
470  clib_warning ("svm_fifo_segment_attach ('%s') failed",
471  mp->segment_name);
472  return;
473  }
474  clib_warning ("Mapped new segment '%s' size %d", mp->segment_name,
475  mp->segment_size);
476 }
477 
478 static void
480 {
481  f64 deltat;
482  u64 bytes;
483 
484  deltat = clib_time_now (&em->clib_time) - session->start;
485  bytes = em->i_am_master ? session->bytes_received : em->bytes_to_send;
486  fformat (stdout, "Finished in %.6f\n", deltat);
487  fformat (stdout, "%.4f Gbit/second\n", (bytes * 8.0) / deltat / 1e9);
488 }
489 
490 static void
491 test_recv_bytes (echo_session_t * s, u8 * rx_buf, u32 n_read)
492 {
493  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 }
504 
505 static void
507 {
508  int n_to_read, n_read;
509 
510  n_to_read = svm_fifo_max_dequeue_cons (s->rx_fifo);
511  if (!n_to_read)
512  return;
513 
514  do
515  {
516  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
530  break;
531  }
532  while (n_to_read > 0);
533 }
534 
535 static void
537 {
538  u64 test_buf_len, bytes_this_chunk, test_buf_offset;
539  u8 *test_data = em->connect_test_data;
540  int n_sent;
541 
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);
546 
547  n_sent = app_send_stream ((app_session_t *) s, test_data + test_buf_offset,
548  bytes_this_chunk, 0);
549 
550  if (n_sent > 0)
551  {
552  s->bytes_to_send -= n_sent;
553  s->bytes_sent += n_sent;
554  }
555 }
556 
557 /*
558  * Rx/Tx polling thread per connection
559  */
560 static void *
561 client_thread_fn (void *arg)
562 {
563  echo_main_t *em = &echo_main;
564  static u8 *rx_buf = 0;
565  u32 session_index = *(u32 *) arg;
566  echo_session_t *s;
567 
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  {
576  send_data_chunk (em, s);
577  recv_data_chunk (em, s, rx_buf);
578  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 
590 void
592 {
594  cmp = vl_msg_api_alloc (sizeof (*cmp));
595  clib_memset (cmp, 0, sizeof (*cmp));
596 
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 
604 void
606 {
608  dmp = vl_msg_api_alloc (sizeof (*dmp));
609  clib_memset (dmp, 0, sizeof (*dmp));
610  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 
616 int
618 {
619  client_send_disconnect (em, s);
620  pool_put (em->sessions, s);
621  clib_memset (s, 0xfe, sizeof (*s));
622  return 0;
623 }
624 
625 static void
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,
640  em->state = STATE_READY;
641 }
642 
643 static void
645 {
646  app_session_evt_t _app_evt, *app_evt = &_app_evt;
648  svm_fifo_t *rx_fifo, *tx_fifo;
649  echo_main_t *em = &echo_main;
650  echo_session_t *session;
651  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->rmt.ip, mp->rmt.is_ip4);
659  clib_warning ("Accepted session from: %s:%d", ip_str,
660  clib_net_to_host_u16 (mp->rmt.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 
671  session->rx_fifo = rx_fifo;
672  session->tx_fifo = tx_fifo;
673  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,
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 
704 static void
706 {
707  echo_main_t *em = &echo_main;
708  echo_session_t *session;
709  u32 session_index;
710  svm_fifo_t *rx_fifo, *tx_fifo;
711  int rv;
712 
713  if (mp->retval)
714  {
715  clib_warning ("connection failed with code: %U", format_api_error,
716  clib_net_to_host_u32 (mp->retval));
717  em->state = STATE_FAILED;
718  return;
719  }
720 
721  /*
722  * Setup session
723  */
724 
725  pool_get (em->sessions, session);
726  clib_memset (session, 0, sizeof (*session));
727  session_index = session - em->sessions;
728 
729  rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
730  rx_fifo->client_session_index = session_index;
731  tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
732  tx_fifo->client_session_index = session_index;
733 
734  session->rx_fifo = rx_fifo;
735  session->tx_fifo = tx_fifo;
736  session->vpp_session_handle = mp->handle;
737  session->start = clib_time_now (&em->clib_time);
738  session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
739  svm_msg_q_t *);
740 
741  hash_set (em->session_index_by_vpp_handles, mp->handle, session_index);
742 
743  /*
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]);
750  if (rv)
751  {
752  clib_warning ("pthread_create returned %d", rv);
753  return;
754  }
755 
756  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->lcl.is_ip4, clib_net_to_host_u16 (mp->lcl.port));
760 }
761 
762 static void
764 {
765  app_session_evt_t _app_evt, *app_evt = &_app_evt;
767  echo_main_t *em = &echo_main;
768  echo_session_t *session = 0;
769  uword *p;
770  int rv = 0;
771 
773  if (!p)
774  {
775  clib_warning ("couldn't find session key %llx", mp->handle);
776  return;
777  }
778 
779  session = pool_elt_at_index (em->sessions, p[0]);
781  pool_put (em->sessions, session);
782 
783  app_alloc_ctrl_evt_to_vpp (session->vpp_evt_q, app_evt,
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 
791  session_print_stats (em, session);
792 }
793 
794 static void
796 {
797  app_session_evt_t _app_evt, *app_evt = &_app_evt;
798  echo_main_t *em = &echo_main;
800  echo_session_t *session = 0;
801  uword *p;
802  int rv = 0;
803 
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,
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);
825 }
826 
827 static void
828 handle_mq_event (session_event_t * e)
829 {
830  switch (e->event_type)
831  {
834  break;
837  break;
840  break;
843  break;
846  break;
847  default:
848  clib_warning ("unhandled %u", e->event_type);
849  }
850 }
851 
852 static void
854 {
855  f64 start_time, deltat, timeout = 100.0;
856  svm_msg_q_msg_t msg;
857  session_event_t *e;
858  echo_session_t *s;
859  int i;
860 
861  /* Init test data */
862  vec_validate (em->connect_test_data, 1024 * 1024 - 1);
863  for (i = 0; i < vec_len (em->connect_test_data); i++)
864  em->connect_test_data[i] = i & 0xff;
865 
866  /*
867  * Attach and connect the clients
868  */
869  if (application_attach (em))
870  return;
871 
872  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)
879 
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);
885  }
886 
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)
902  }
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)
912  {
913  if (svm_msg_q_sub (em->our_event_queue, &msg, SVM_Q_WAIT, 0))
914  {
915  clib_warning ("svm msg q returned");
916  continue;
917  }
918  e = svm_msg_q_msg_data (em->our_event_queue, &msg);
919  if (e->event_type != SESSION_IO_EVT_RX)
920  handle_mq_event (e);
922  }
923 
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 
939  application_detach (em);
940 }
941 
942 static void
943 vl_api_bind_uri_reply_t_handler (vl_api_bind_uri_reply_t * mp)
944 {
945  echo_main_t *em = &echo_main;
946 
947  if (mp->retval)
948  {
949  clib_warning ("bind failed: %U", format_api_error,
950  clib_net_to_host_u32 (mp->retval));
951  em->state = STATE_FAILED;
952  return;
953  }
954 
955  em->state = STATE_READY;
956 }
957 
958 static void
959 vl_api_unbind_uri_reply_t_handler (vl_api_unbind_uri_reply_t * mp)
960 {
961  echo_main_t *em = &echo_main;
962 
963  if (mp->retval != 0)
964  clib_warning ("returned %d", ntohl (mp->retval));
965 
966  em->state = STATE_START;
967 }
968 
969 u8 *
970 format_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 
976 u8 *
977 format_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. */
1027 u8 *
1028 format_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 
1052 static void
1053 server_handle_rx (echo_main_t * em, session_event_t * e)
1054 {
1055  int n_read, max_dequeue, n_sent;
1056  u32 offset, to_dequeue;
1057  echo_session_t *s;
1058 
1059  s = pool_elt_at_index (em->sessions, e->session_index);
1060 
1061  /* 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);
1065 
1066  max_dequeue = svm_fifo_max_dequeue_cons (s->rx_fifo);
1067  if (PREDICT_FALSE (!max_dequeue))
1068  return;
1069 
1070  do
1071  {
1072  /* 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 */ );
1078  if (n_read > 0)
1079  {
1080  max_dequeue -= n_read;
1081  s->bytes_received += n_read;
1082  }
1083  else
1084  break;
1085 
1086  /* Reflect if a non-drop session */
1087  if (!em->no_return && n_read > 0)
1088  {
1089  offset = 0;
1090  do
1091  {
1092  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)
1096  {
1097  n_read -= n_sent;
1098  offset += n_sent;
1099  }
1100  }
1101  while ((n_sent <= 0 || n_read > 0) && !em->time_to_stop);
1102  }
1103  }
1104  while (max_dequeue > 0 && !em->time_to_stop);
1105 }
1106 
1107 static void
1109 {
1110  svm_msg_q_msg_t msg;
1111  session_event_t *e;
1112 
1113  while (1)
1114  {
1115  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);
1117  switch (e->event_type)
1118  {
1119  case SESSION_IO_EVT_RX:
1120  server_handle_rx (em, e);
1121  break;
1122  default:
1123  handle_mq_event (e);
1124  break;
1125  }
1126  if (PREDICT_FALSE (em->time_to_stop == 1))
1127  break;
1128  if (PREDICT_FALSE (em->time_to_print_stats == 1))
1129  {
1130  em->time_to_print_stats = 0;
1131  fformat (stdout, "%d connections\n", pool_elts (em->sessions));
1132  }
1133  svm_msg_q_free_msg (em->our_event_queue, &msg);
1134  }
1135 }
1136 
1137 void
1139 {
1140  vl_api_bind_uri_t *bmp;
1141  bmp = vl_msg_api_alloc (sizeof (*bmp));
1142  clib_memset (bmp, 0, sizeof (*bmp));
1143 
1144  bmp->_vl_msg_id = ntohs (VL_API_BIND_URI);
1145  bmp->client_index = em->my_client_index;
1146  bmp->context = ntohl (0xfeedface);
1147  memcpy (bmp->uri, em->uri, vec_len (em->uri));
1148  vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
1149 }
1150 
1151 int
1153 {
1154  server_send_listen (em);
1156  {
1157  clib_warning ("timeout waiting for STATE_READY");
1158  return -1;
1159  }
1160  return 0;
1161 }
1162 
1163 void
1165 {
1166  vl_api_unbind_uri_t *ump;
1167 
1168  ump = vl_msg_api_alloc (sizeof (*ump));
1169  clib_memset (ump, 0, sizeof (*ump));
1170 
1171  ump->_vl_msg_id = ntohs (VL_API_UNBIND_URI);
1172  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);
1175 }
1176 
1177 int
1179 {
1180  server_send_unbind (em);
1182  {
1183  clib_warning ("timeout waiting for STATE_START");
1184  return -1;
1185  }
1186  return 0;
1187 }
1188 
1189 void
1191 {
1192  echo_session_t *session;
1193  int i;
1194 
1195  /* $$$$ hack preallocation */
1196  for (i = 0; i < 200000; i++)
1197  {
1198  pool_get (em->sessions, session);
1199  clib_memset (session, 0, sizeof (*session));
1200  }
1201  for (i = 0; i < 200000; i++)
1202  pool_put_index (em->sessions, i);
1203 
1204  if (application_attach (em))
1205  return;
1206 
1207  /* Bind to uri */
1208  if (server_listen (em))
1209  return;
1210 
1211  /* Enter handle event loop */
1212  server_handle_mq (em);
1213 
1214  /* Cleanup */
1215  server_send_unbind (em);
1216 
1217  application_detach (em);
1218 
1219  fformat (stdout, "Test complete...\n");
1220 }
1221 
1222 static void
1224  mp)
1225 {
1226  echo_main_t *em = &echo_main;
1227  uword *p;
1228 
1229  if (mp->retval)
1230  {
1231  clib_warning ("vpp complained about disconnect: %d",
1232  ntohl (mp->retval));
1233  return;
1234  }
1235 
1236  em->state = STATE_START;
1237 
1239  if (p)
1240  {
1242  }
1243  else
1244  {
1245  clib_warning ("couldn't find session key %llx", mp->handle);
1246  }
1247 }
1248 
1249 static void
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 
1257 static void
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) \
1268 _(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \
1269 _(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) \
1274 
1275 void
1277 {
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);
1286 #undef _
1287 }
1288 
1289 int
1290 main (int argc, char **argv)
1291 {
1292  int i_am_server = 1, test_return_packets = 0;
1293  echo_main_t *em = &echo_main;
1294  fifo_segment_main_t *sm = &em->segment_main;
1295  unformat_input_t _argv, *a = &_argv;
1296  u8 *chroot_prefix;
1297  u8 *uri = 0;
1298  u8 *bind_uri = (u8 *) "tcp://0.0.0.0/1234";
1299  u8 *connect_uri = (u8 *) "tcp://6.0.1.1/1234";
1300  u64 bytes_to_send = 64 << 10, mbytes;
1301  char *app_name;
1302  u32 tmp;
1303 
1304  clib_mem_init_thread_safe (0, 256 << 20);
1305 
1306  clib_memset (em, 0, sizeof (*em));
1307  em->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
1308  em->my_pid = getpid ();
1309  em->configured_segment_size = 1 << 20;
1310  em->socket_name = 0;
1311  em->use_sock_api = 1;
1312  em->fifo_size = 64 << 10;
1313  em->n_clients = 1;
1314 
1315  clib_time_init (&em->clib_time);
1318  unformat_init_command_line (a, argv);
1319 
1321  {
1322  if (unformat (a, "chroot prefix %s", &chroot_prefix))
1323  {
1324  vl_set_memory_root_path ((char *) chroot_prefix);
1325  }
1326  else if (unformat (a, "uri %s", &uri))
1327  ;
1328  else if (unformat (a, "segment-size %dM", &tmp))
1329  em->configured_segment_size = tmp << 20;
1330  else if (unformat (a, "segment-size %dG", &tmp))
1331  em->configured_segment_size = tmp << 30;
1332  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;
1338  else if (unformat (a, "test"))
1339  test_return_packets = 1;
1340  else if (unformat (a, "mbytes %lld", &mbytes))
1341  {
1342  bytes_to_send = mbytes << 20;
1343  }
1344  else if (unformat (a, "gbytes %lld", &mbytes))
1345  {
1346  bytes_to_send = mbytes << 30;
1347  }
1348  else if (unformat (a, "socket-name %s", &em->socket_name))
1349  ;
1350  else if (unformat (a, "use-svm-api"))
1351  em->use_sock_api = 0;
1352  else if (unformat (a, "fifo-size %d", &tmp))
1353  em->fifo_size = tmp << 10;
1354  else if (unformat (a, "nclients %d", &em->n_clients))
1355  ;
1356  else
1357  {
1358  fformat (stderr, "%s: usage [master|slave]\n", argv[0]);
1359  exit (1);
1360  }
1361  }
1362 
1363  if (!em->socket_name)
1364  em->socket_name = format (0, "%s%c", API_SOCKET_FILE, 0);
1365 
1366  if (uri)
1367  {
1368  em->uri = format (0, "%s%c", uri, 0);
1369  em->connect_uri = format (0, "%s%c", uri, 0);
1370  }
1371  else
1372  {
1373  em->uri = format (0, "%s%c", bind_uri, 0);
1374  em->connect_uri = format (0, "%s%c", connect_uri, 0);
1375  }
1376 
1377  em->i_am_master = i_am_server;
1378  em->test_return_packets = test_return_packets;
1379  em->bytes_to_send = bytes_to_send;
1380  em->time_to_stop = 0;
1381  vec_validate (em->rx_buf, 4 << 20);
1383  vec_validate (em->thread_args, em->n_clients - 1);
1384 
1386  tcp_echo_api_hookup (em);
1387 
1388  app_name = i_am_server ? "tcp_echo_server" : "tcp_echo_client";
1389  if (connect_to_vpp (app_name) < 0)
1390  {
1391  svm_region_exit ();
1392  fformat (stderr, "Couldn't connect to vpe, exiting...\n");
1393  exit (1);
1394  }
1395 
1396  if (i_am_server == 0)
1397  clients_run (em);
1398  else
1399  server_run (em);
1400 
1401  /* Make sure detach finishes */
1403 
1404  disconnect_from_vpp (em);
1405  exit (0);
1406 }
1407 
1408 /*
1409  * fd.io coding-style-patch-verification: ON
1410  *
1411  * Local Variables:
1412  * eval: (c-set-style "gnu")
1413  * End:
1414  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
#define foreach_app_session_field
flag for dgram mode
clib_time_t clib_time
Definition: quic_echo.h:167
static int app_recv_stream_raw(svm_fifo_t *f, u8 *buf, u32 len, u8 clear_evt, u8 peek)
static u8 * format_api_error(u8 *s, va_list *args)
Definition: tcp_echo.c:156
void server_run(echo_main_t *em)
Definition: tcp_echo.c:1190
u8 * rx_buf
Definition: tcp_echo.c:89
#define hash_set(h, key, value)
Definition: hash.h:255
void * svm_msg_q_msg_data(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Get data for message in queue.
#define CLIB_CACHE_LINE_ALIGN_MARK(mark)
Definition: cache.h:60
#define clib_min(x, y)
Definition: clib.h:295
int vl_socket_client_init_shm(vl_api_shm_elem_config_t *config, int want_pthread)
static void vl_api_application_tls_cert_add_reply_t_handler(vl_api_application_tls_cert_add_reply_t *mp)
Definition: tcp_echo.c:1251
int vl_client_connect_to_vlib(const char *svm_name, const char *client_name, int rx_queue_size)
#define hash_unset(h, key)
Definition: hash.h:261
int i_am_master
Definition: quic_echo.h:169
transport_endpoint_t rmt
a
Definition: bitmap.h:538
#define foreach_tcp_echo_msg
Definition: tcp_echo.c:1265
Application add TLS key.
Definition: session.api:83
static void vl_api_unbind_uri_reply_t_handler(vl_api_unbind_uri_reply_t *mp)
Definition: tcp_echo.c:959
u8 use_sock_api
Flag that decides if socket, instead of svm, api is used to connect to vpp.
Definition: quic_echo.h:189
#define DBG(_fmt, _args...)
Definition: tcp_echo.c:42
unsigned long u64
Definition: types.h:89
int my_client_index
All VLIB-side message handlers use my_client_index to identify the queue / client.
Definition: api_common.h:311
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define NULL
Definition: clib.h:58
static int wait_for_state_change(echo_main_t *em, connection_state_t state)
Definition: tcp_echo.c:186
pthread_t * client_thread_handles
Definition: tcp_echo.c:124
static f64 clib_time_now(clib_time_t *c)
Definition: time.h:215
static clib_error_t * setup_signal_handlers(void)
Definition: tcp_echo.c:398
int server_listen(echo_main_t *em)
Definition: tcp_echo.c:1152
static void clients_run(echo_main_t *em)
Definition: tcp_echo.c:853
static int app_send_stream(app_session_t *s, u8 *data, u32 len, u8 noblock)
static u8 svm_msg_q_is_empty(svm_msg_q_t *mq)
Check if message queue is empty.
static void stop_signal(int signum)
Definition: tcp_echo.c:382
int i
int vl_socket_client_connect(char *socket_path, char *client_name, u32 socket_buffer_size)
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
void disconnect_from_vpp(echo_main_t *em)
Definition: tcp_echo.c:448
pid_t my_pid
Definition: tcp_echo.c:106
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
volatile connection_state_t state
Definition: quic_echo.h:182
static void server_handle_mq(echo_main_t *em)
Definition: tcp_echo.c:1108
u32 * thread_args
Definition: tcp_echo.c:125
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
void * vl_msg_api_alloc(int nbytes)
static void session_reset_handler(session_reset_msg_t *mp)
Definition: tcp_echo.c:795
unsigned char u8
Definition: types.h:56
void application_detach(echo_main_t *em)
Definition: tcp_echo.c:276
foreach_app_session_field u64 vpp_session_handle
Definition: quic_echo.h:66
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
struct _svm_fifo svm_fifo_t
static void * client_thread_fn(void *arg)
Definition: tcp_echo.c:561
void svm_region_exit(void)
Definition: svm.c:1224
enum ssvm_segment_type_ ssvm_segment_type_t
static void app_alloc_ctrl_evt_to_vpp(svm_msg_q_t *mq, app_session_evt_t *app_evt, u8 evt_type)
static void init_error_string_table(echo_main_t *em)
Definition: tcp_echo.c:172
volatile u32 n_clients_connected
Definition: quic_echo.h:216
void client_send_disconnect(echo_main_t *em, echo_session_t *s)
Definition: tcp_echo.c:605
volatile u64 bytes_received
Definition: quic_echo.h:69
static const u32 test_srv_key_rsa_len
Definition: tls_test.h:77
static u32 svm_fifo_max_dequeue_cons(svm_fifo_t *f)
Fifo max bytes to dequeue optimized for consumer.
Definition: svm_fifo.h:489
volatile int time_to_stop
Definition: tcp_echo.c:115
volatile int time_to_print_stats
Definition: tcp_echo.c:116
static void vl_api_application_tls_key_add_reply_t_handler(vl_api_application_tls_key_add_reply_t *mp)
Definition: tcp_echo.c:1259
vhost_vring_state_t state
Definition: vhost_user.h:146
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
Definition: api_common.h:266
unsigned int u32
Definition: types.h:88
u32 my_client_index
Definition: quic_echo.h:163
void vl_msg_api_send_shmem(svm_queue_t *q, u8 *elem)
u32 fifo_size
Definition: quic_echo.h:195
char * segment_name
segment name
Definition: fifo_segment.h:68
int svm_msg_q_sub(svm_msg_q_t *mq, svm_msg_q_msg_t *msg, svm_q_conditional_wait_t cond, u32 time)
Consumer dequeue one message from queue.
u8 * connect_uri
Definition: tcp_echo.c:92
vl_api_fib_path_type_t type
Definition: fib_types.api:123
int fifo_segment_attach(fifo_segment_main_t *sm, fifo_segment_create_args_t *a)
Attach as slave to a fifo segment.
Definition: fifo_segment.c:99
connection_state_t
Definition: tcp_echo.c:60
void vl_set_memory_root_path(const char *name)
int server_unbind(echo_main_t *em)
Definition: tcp_echo.c:1178
static void session_accepted_handler(session_accepted_msg_t *mp)
Definition: tcp_echo.c:644
#define hash_get(h, key)
Definition: hash.h:249
int main(int argc, char **argv)
Definition: tcp_echo.c:1290
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
static void handle_mq_event(session_event_t *e)
Definition: tcp_echo.c:828
static int ssvm_segment_attach(char *name, ssvm_segment_type_t type, int fd)
Definition: tcp_echo.c:291
client->vpp, attach application to session layer
Definition: session.api:27
struct _unformat_input_t unformat_input_t
uword * session_index_by_vpp_handles
Definition: quic_echo.h:172
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
void unformat_init_command_line(unformat_input_t *input, char *argv[])
Definition: unformat.c:1013
u64 bytes_to_send
Definition: quic_echo.h:68
void server_send_listen(echo_main_t *em)
Definition: tcp_echo.c:1138
#define PREDICT_FALSE(x)
Definition: clib.h:111
uword * error_string_by_error_number
Definition: tcp_echo.c:121
static void svm_fifo_unset_event(svm_fifo_t *f)
Unset fifo event flag.
Definition: svm_fifo.h:752
static void server_handle_rx(echo_main_t *em, session_event_t *e)
Definition: tcp_echo.c:1053
Unbind a given URI.
Definition: session.api:153
static const char test_srv_crt_rsa[]
Definition: tls_test.h:23
fifo_segment_main_t segment_main
Definition: quic_echo.h:179
void clib_time_init(clib_time_t *c)
Definition: time.c:178
static void session_bound_handler(session_bound_msg_t *mp)
Definition: tcp_echo.c:626
static void vl_api_application_attach_reply_t_handler(vl_api_application_attach_reply_t *mp)
Definition: tcp_echo.c:315
u8 name[64]
Definition: memclnt.api:152
volatile u32 n_active_clients
Definition: tcp_echo.c:136
u64 bytes_to_send
Definition: quic_echo.h:193
word fformat(FILE *f, char *fmt,...)
Definition: format.c:462
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:203
u8 test_return_packets
Definition: quic_echo.h:192
#define ip46_address_is_ip4(ip46)
Definition: ip6_packet.h:88
static void vl_api_bind_uri_reply_t_handler(vl_api_bind_uri_reply_t *mp)
Definition: tcp_echo.c:943
static void app_send_ctrl_evt_to_vpp(svm_msg_q_t *mq, app_session_evt_t *app_evt)
u32 segment_size
size of the segment
Definition: fifo_segment.h:66
u8 * format_ip4_address(u8 *s, va_list *args)
Definition: tcp_echo.c:970
echo_session_t * sessions
Definition: quic_echo.h:165
clib_error_t * vl_socket_client_recv_fd_msg(int fds[], int n_fds, u32 wait)
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
void vl_socket_client_disconnect(void)
vlib_main_t * vm
Definition: buffer.c:312
int connect_to_vpp(char *name)
Definition: tcp_echo.c:414
static void vl_api_application_detach_reply_t_handler(vl_api_application_detach_reply_t *mp)
Definition: tcp_echo.c:373
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
static void recv_data_chunk(echo_main_t *em, echo_session_t *s, u8 *rx_buf)
Definition: tcp_echo.c:506
void fifo_segment_main_init(fifo_segment_main_t *sm, u64 baseva, u32 timeout_in_seconds)
Definition: fifo_segment.c:162
#define clib_warning(format, args...)
Definition: error.h:59
static void stats_signal(int signum)
Definition: tcp_echo.c:390
static void test_recv_bytes(echo_session_t *s, u8 *rx_buf, u32 n_read)
Definition: tcp_echo.c:491
volatile u8 time_to_stop
Definition: quic_echo.h:183
#define HIGH_SEGMENT_BASEVA
Definition: svm_common.h:84
#define ARRAY_LEN(x)
Definition: clib.h:62
blocking call - best used in combination with condvars, for eventfds we don&#39;t yield the cpu ...
Definition: queue.h:42
static int app_recv_stream(app_session_t *s, u8 *buf, u32 len)
int memfd_fd
fd for memfd segments
Definition: fifo_segment.h:67
Application attach reply.
Definition: session.api:50
void tcp_echo_api_hookup(echo_main_t *em)
Definition: tcp_echo.c:1276
svm_queue_t * vl_input_queue
Definition: memory_shared.h:84
#define foreach_vnet_api_error
Definition: api_errno.h:22
static const char test_srv_key_rsa[]
Definition: tls_test.h:49
void vlib_cli_output(struct vlib_main_t *vm, char *fmt,...)
Definition: tcp_echo.c:408
signed int i32
Definition: types.h:77
#define hash_create(elts, value_bytes)
Definition: hash.h:696
#define uword_to_pointer(u, type)
Definition: types.h:136
static void session_print_stats(echo_main_t *em, echo_session_t *session)
Definition: tcp_echo.c:479
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:311
#define ASSERT(truth)
ip46_type_t
Definition: ip6_packet.h:70
client->vpp, attach application to session layer
Definition: session.api:95
#define TIMEOUT
vpp->client, please map an additional shared memory segment
Definition: session.api:110
static void vl_api_disconnect_session_reply_t_handler(vl_api_disconnect_session_reply_t *mp)
Definition: tcp_echo.c:1223
u32 n_clients
Definition: quic_echo.h:213
void application_send_attach(echo_main_t *em)
Definition: tcp_echo.c:222
u32 configured_segment_size
Definition: tcp_echo.c:118
void svm_msg_q_set_consumer_eventfd(svm_msg_q_t *mq, int fd)
Set event fd for queue consumer.
ssvm_segment_type_t segment_type
type of segment requested
Definition: fifo_segment.h:65
bidirectional disconnect API
Definition: session.api:183
static void session_connected_handler(session_connected_msg_t *mp)
Definition: tcp_echo.c:705
void server_send_unbind(echo_main_t *em)
Definition: tcp_echo.c:1164
int client_disconnect(echo_main_t *em, echo_session_t *s)
Definition: tcp_echo.c:617
#define API_SOCKET_FILE
Definition: socket_api.h:25
static void send_data_chunk(echo_main_t *em, echo_session_t *s)
Definition: tcp_echo.c:536
void svm_msg_q_free_msg(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Free message buffer.
volatile u64 bytes_to_receive
Definition: quic_echo.h:70
svm_msg_q_t * our_event_queue
Definition: quic_echo.h:166
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void session_disconnected_handler(session_disconnected_msg_t *mp)
Definition: tcp_echo.c:763
Bind to a given URI.
Definition: session.api:139
u64 rx_total
Definition: quic_echo.h:222
u8 * connect_test_data
Definition: quic_echo.h:191
u64 uword
Definition: types.h:112
void client_send_connect(echo_main_t *em)
Definition: tcp_echo.c:591
int no_return
Definition: tcp_echo.c:99
static int application_attach(echo_main_t *em)
Definition: tcp_echo.c:264
struct _svm_queue svm_queue_t
u32 connected_session_index
Definition: tcp_echo.c:94
struct clib_bihash_value offset
template key/value backing page structure
u64 tx_total
Definition: quic_echo.h:221
u8 * format_ip6_address(u8 *s, va_list *args)
Definition: tcp_echo.c:977
void vl_client_disconnect_from_vlib(void)
u32 client_bytes_received
Definition: tcp_echo.c:126
Application add TLS certificate.
Definition: session.api:69
transport_endpoint_t lcl
Connect to a given URI.
Definition: session.api:169
u16 as_u16[8]
Definition: ip6_packet.h:49
svm_queue_t * vl_input_queue
Definition: quic_echo.h:162
bidirectional disconnect reply API
Definition: session.api:196
void * clib_mem_init_thread_safe(void *memory, uword memory_size)
Definition: mem_dlmalloc.c:226
api_main_t api_main
Definition: api_shared.c:35
static void vl_api_map_another_segment_t_handler(vl_api_map_another_segment_t *mp)
Definition: tcp_echo.c:457
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static const u32 test_srv_crt_rsa_len
Definition: tls_test.h:47
u8 * format_ip46_address(u8 *s, va_list *args)
Definition: tcp_echo.c:1028
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
non-blocking call - works with both condvar and eventfd signaling
Definition: queue.h:44
u32 * new_segment_indices
return vec of new seg indices
Definition: fifo_segment.h:69
u8 * socket_name
Definition: quic_echo.h:168
echo_main_t echo_main
Definition: tcp_echo.c:147
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128