+u64 server_bytes_received, server_bytes_sent;
+
+static void *
+cut_through_thread_fn (void *arg)
+{
+ session_t *s;
+ svm_fifo_t *rx_fifo;
+ svm_fifo_t *tx_fifo;
+ u8 *my_copy_buffer = 0;
+ uri_udp_test_main_t *utm = &uri_udp_test_main;
+ i32 actual_transfer;
+ int rv;
+ u32 buffer_offset;
+
+ while (utm->cut_through_session_index == ~0)
+ ;
+
+ s = pool_elt_at_index (utm->sessions, utm->cut_through_session_index);
+
+ rx_fifo = s->server_rx_fifo;
+ tx_fifo = s->server_tx_fifo;
+
+ vec_validate (my_copy_buffer, 64 * 1024 - 1);
+
+ while (true)
+ {
+ /* We read from the tx fifo and write to the rx fifo */
+ do
+ {
+ actual_transfer = svm_fifo_dequeue_nowait (tx_fifo, 0,
+ vec_len (my_copy_buffer),
+ my_copy_buffer);
+ }
+ while (actual_transfer <= 0);
+
+ server_bytes_received += actual_transfer;
+
+ buffer_offset = 0;
+ while (actual_transfer > 0)
+ {
+ rv = svm_fifo_enqueue_nowait (rx_fifo, 0, actual_transfer,
+ my_copy_buffer + buffer_offset);
+ if (rv > 0)
+ {
+ actual_transfer -= rv;
+ buffer_offset += rv;
+ server_bytes_sent += rv;
+ }
+
+ }
+ if (PREDICT_FALSE (utm->time_to_stop))
+ break;
+ }
+
+ pthread_exit (0);
+}
+
+static void
+uri_udp_slave_test (uri_udp_test_main_t * utm)
+{
+ vl_api_connect_uri_t *cmp;
+ int i;
+ u8 *test_data = 0;
+ u64 bytes_received = 0, bytes_sent = 0;
+ i32 bytes_to_read;
+ int rv;
+ int mypid = getpid ();
+ f64 before, after, delta, bytes_per_second;
+ session_t *session;
+ svm_fifo_t *rx_fifo, *tx_fifo;
+ int buffer_offset, bytes_to_send = 0;
+
+ vec_validate (test_data, 64 * 1024 - 1);
+ for (i = 0; i < vec_len (test_data); i++)
+ test_data[i] = i & 0xff;
+
+ cmp = vl_msg_api_alloc (sizeof (*cmp));
+ memset (cmp, 0, sizeof (*cmp));
+
+ cmp->_vl_msg_id = ntohs (VL_API_CONNECT_URI);
+ cmp->client_index = utm->my_client_index;
+ cmp->context = ntohl (0xfeedface);
+ memcpy (cmp->uri, utm->connect_uri, vec_len (utm->connect_uri));
+ vl_msg_api_send_shmem (utm->vl_input_queue, (u8 *) & cmp);
+
+ if (wait_for_state_change (utm, STATE_READY))
+ {
+ clib_warning ("timeout waiting for STATE_READY");
+ return;
+ }
+
+ session = pool_elt_at_index (utm->sessions, utm->cut_through_session_index);
+ rx_fifo = session->server_rx_fifo;
+ tx_fifo = session->server_tx_fifo;
+
+ before = clib_time_now (&utm->clib_time);
+
+ vec_validate (utm->rx_buf, vec_len (test_data) - 1);
+
+ for (i = 0; i < NITER; i++)
+ {
+ bytes_to_send = vec_len (test_data);
+ buffer_offset = 0;
+ while (bytes_to_send > 0)
+ {
+ rv = svm_fifo_enqueue_nowait (tx_fifo, mypid,
+ bytes_to_send,
+ test_data + buffer_offset);
+
+ if (rv > 0)
+ {
+ bytes_to_send -= rv;
+ buffer_offset += rv;
+ bytes_sent += rv;
+ }
+ }
+
+ bytes_to_read = svm_fifo_max_dequeue (rx_fifo);
+
+ bytes_to_read = vec_len (utm->rx_buf) > bytes_to_read ?
+ bytes_to_read : vec_len (utm->rx_buf);
+
+ buffer_offset = 0;
+ while (bytes_to_read > 0)
+ {
+ rv = svm_fifo_dequeue_nowait (rx_fifo, mypid,
+ bytes_to_read,
+ utm->rx_buf + buffer_offset);
+ if (rv > 0)
+ {
+ bytes_to_read -= rv;
+ buffer_offset += rv;
+ bytes_received += rv;
+ }
+ }
+ }
+ while (bytes_received < bytes_sent)
+ {
+ rv = svm_fifo_dequeue_nowait (rx_fifo, mypid,
+ vec_len (utm->rx_buf), utm->rx_buf);
+ if (rv > 0)
+ {
+#if CLIB_DEBUG > 0
+ int j;
+ for (j = 0; j < rv; j++)
+ {
+ if (utm->rx_buf[j] != ((bytes_received + j) & 0xff))
+ {
+ clib_warning ("error at byte %lld, 0x%x not 0x%x",
+ bytes_received + j,
+ utm->rx_buf[j],
+ ((bytes_received + j) & 0xff));
+ }
+ }
+#endif
+ bytes_received += (u64) rv;
+ }
+ }
+
+ after = clib_time_now (&utm->clib_time);
+ delta = after - before;
+ bytes_per_second = 0.0;
+
+ if (delta > 0.0)
+ bytes_per_second = (f64) bytes_received / delta;
+
+ fformat (stdout,
+ "Done: %lld recv bytes in %.2f seconds, %.2f bytes/sec...\n\n",
+ bytes_received, delta, bytes_per_second);
+ fformat (stdout,
+ "Done: %lld sent bytes in %.2f seconds, %.2f bytes/sec...\n\n",
+ bytes_sent, delta, bytes_per_second);
+ fformat (stdout,
+ "client -> server -> client round trip: %.2f Gbit/sec \n\n",
+ (bytes_per_second * 8.0) / 1e9);
+}
+