45 #define vl_print(handle, ...) 166 u8 *result = va_arg (*args,
u8 *);
169 if (!
unformat (input,
"%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
172 if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
188 uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
189 uword c, n_colon, double_colon_index;
191 n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
192 double_colon_index =
ARRAY_LEN (hex_quads);
196 if (c >=
'0' && c <=
'9')
198 else if (c >=
'a' && c <=
'f')
199 hex_digit = c + 10 -
'a';
200 else if (c >=
'A' && c <=
'F')
201 hex_digit = c + 10 -
'A';
202 else if (c ==
':' && n_colon < 2)
211 if (n_hex_quads >=
ARRAY_LEN (hex_quads))
216 hex_quad = (hex_quad << 4) | hex_digit;
219 if (n_hex_digits >= 4)
230 if (double_colon_index <
ARRAY_LEN (hex_quads))
232 double_colon_index = n_hex_quads;
235 if (n_colon > 0 && n_hex_digits > 0)
237 hex_quads[n_hex_quads++] = hex_quad;
243 if (n_hex_digits > 0)
244 hex_quads[n_hex_quads++] = hex_quad;
250 if (double_colon_index <
ARRAY_LEN (hex_quads))
254 for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
255 hex_quads[n_zero + i] = hex_quads[i];
257 for (i = 0; i < n_zero; i++)
258 hex_quads[double_colon_index + i] = 0;
267 for (i = 0; i <
ARRAY_LEN (hex_quads); i++)
268 result->
as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
284 sep->port = clib_host_to_net_u16 (port);
289 &sep->ip.ip6, &port))
291 sep->port = clib_host_to_net_u16 (port);
305 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
307 bmp->
context = ntohl (0xfeedface);
327 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
329 bmp->
context = ntohl (0xfeedface);
379 clib_warning (
"detach returned with err: %d", mp->retval);
387 i32 error = va_arg (*args,
u32);
393 s =
format (s,
"%s", p[0]);
395 s =
format (s,
"%d", error);
403 #define TIMEOUT 600.0 405 #define TIMEOUT 600.0 412 if (utm->
state == state)
422 __clib_unused
static void *
428 u8 *my_copy_buffer = 0;
431 int rv, do_dequeue = 0;
439 rx_fifo = s->rx_fifo;
440 tx_fifo = s->tx_fifo;
460 while (actual_transfer <= 0);
467 while (actual_transfer > 0)
470 my_copy_buffer + buffer_offset);
473 actual_transfer -= rv;
495 static f64 start_time;
499 if (start_time == 0.0)
509 session_index = session - utm->
sessions;
510 session->session_index = session_index;
512 rx_fifo->client_session_index = session_index;
513 tx_fifo->client_session_index = session_index;
514 session->rx_fifo = rx_fifo;
515 session->tx_fifo = tx_fifo;
517 sizeof (ip46_address_t));
518 session->transport.is_ip4 = mp->
rmt.is_ip4;
519 session->transport.rmt_port = mp->
rmt.port;
525 fformat (stdout,
"%d active sessions in %.2f seconds, %.2f/sec...\n",
558 clib_warning (
"disconnecting %u", session->session_index);
595 session->session_index = session - utm->
sessions;
606 session->is_dgram = 0;
608 session->rx_fifo->client_session_index = session->session_index;
609 session->tx_fifo->client_session_index = session->session_index;
618 session->rx_fifo->client_session_index = session->session_index;
619 session->tx_fifo->client_session_index = session->session_index;
621 sizeof (ip46_address_t));
622 session->transport.is_ip4 = mp->
lcl.is_ip4;
623 session->transport.lcl_port = mp->
lcl.port;
635 sizeof (ip46_address_t));
636 session->transport.rmt_port = sep->port;
662 session_index = session - utm->
sessions;
664 rx_fifo->client_session_index = session_index;
665 tx_fifo->client_session_index = session_index;
666 session->rx_fifo = rx_fifo;
667 session->tx_fifo = tx_fifo;
669 sizeof (ip46_address_t));
671 session->transport.lcl_port = mp->
lcl_port;
680 switch (e->event_type)
706 cmp->_vl_msg_id = ntohs (VL_API_CONNECT_URI);
708 cmp->
context = ntohl (0xfeedface);
716 u64 test_buf_len, bytes_this_chunk, test_buf_offset;
722 test_buf_len =
vec_len (test_data);
723 test_buf_offset = utm->
bytes_sent % test_buf_len;
724 bytes_this_chunk =
clib_min (test_buf_len - test_buf_offset,
727 bytes_this_chunk =
clib_min (bytes_this_chunk, enq_space);
729 written =
app_send (s, test_data + test_buf_offset, bytes_this_chunk,
747 f64 start_time, end_time, delta;
760 ASSERT (vec_len (test_data) > 0);
782 delta = end_time - start_time;
783 transfer_type = utm->
have_return ?
"full-duplex" :
"half-duplex";
784 clib_warning (
"%lld bytes (%lld mbytes, %lld gbytes) in %.2f seconds",
809 f64 start_time, timeout = 100.0;
879 clib_warning (
"segment not mapped: %s", segment_handle);
906 #define foreach_tcp_echo_msg \ 907 _(UNBIND_URI_REPLY, unbind_uri_reply) \ 908 _(MAP_ANOTHER_SEGMENT, map_another_segment) \ 909 _(UNMAP_SEGMENT, unmap_segment) \ 910 _(APPLICATION_ATTACH_REPLY, application_attach_reply) \ 911 _(APPLICATION_DETACH_REPLY, application_detach_reply) \ 912 _(APP_CUT_THROUGH_REGISTRATION_ADD, app_cut_through_registration_add) \ 918 vl_msg_api_set_handlers(VL_API_##N, #n, \ 919 vl_api_##n##_t_handler, \ 921 vl_api_##n##_t_endian, \ 922 vl_api_##n##_t_print, \ 923 sizeof(vl_api_##n##_t), 1); 955 #define _(n,v,s) hash_set (utm->error_string_by_error_number, -v, s); 969 u32 max_dequeue,
offset, max_transfer, rx_buf_len;
973 rx_fifo = session->rx_fifo;
974 tx_fifo = session->tx_fifo;
987 max_transfer =
clib_min (rx_buf_len, max_dequeue);
988 if (session->is_dgram)
990 &session->transport, 0, 0);
996 max_dequeue -= n_read;
1017 tx_fifo->master_session_index,
1021 while ((n_read < 0 || max_dequeue > 0) && !utm->
time_to_stop);
1042 switch (e->event_type)
1071 ump->_vl_msg_id = ntohs (VL_API_UNBIND_URI);
1085 bmp->_vl_msg_id = ntohs (VL_API_BIND_URI);
1087 bmp->
context = ntohl (0xfeedface);
1120 fformat (stdout,
"Test complete...\n");
1128 u8 *uri = (
u8 *)
"udp://6.0.1.1/1234";
1130 int i_am_server = 1;
1156 if (
unformat (a,
"chroot prefix %s", &chroot_prefix))
1160 else if (
unformat (a,
"uri %s", &uri))
1162 else if (
unformat (a,
"segment-size %dM", &tmp))
1164 else if (
unformat (a,
"segment-size %dG", &tmp))
1170 else if (
unformat (a,
"no-return"))
1172 else if (
unformat (a,
"mbytes %d", &tmp))
1174 else if (
unformat (a,
"fifo-size %d", &tmp))
1178 fformat (stderr,
"%s: usage [server|client]\n");
1183 utm->i_am_server = i_am_server;
1190 utm->listen_uri =
format (0,
"%s%c", uri, 0);
1191 utm->is_connected = (utm->listen_uri[4] ==
'c');
1192 app_name =
"udp_echo_server";
1196 app_name =
"udp_echo_client";
1197 utm->connect_uri =
format (0,
"%s%c", uri, 0);
1198 utm->is_connected = (utm->connect_uri[4] ==
'c');
1203 fformat (stderr,
"Couldn't connect to vpe, exiting...\n");
1207 if (i_am_server == 0)
1214 for (
i = 0;
i < 200000;
i++)
1219 for (
i = 0;
i < 200000;
i++)
1229 #undef vl_api_version 1230 #define vl_api_version(n,v) static u32 vpe_api_version = v; 1231 #include <vpp/api/vpe.api.h> 1232 #undef vl_api_version 1241 mp->
api_versions[0] = clib_host_to_net_u32 (vpe_api_version);
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
volatile int time_to_print_stats
static void vl_api_unmap_segment_t_handler(vl_api_unmap_segment_t *mp)
void udp_server_test(udp_echo_main_t *utm)
static int app_recv_stream_raw(svm_fifo_t *f, u8 *buf, u32 len, u8 clear_evt, u8 peek)
#define hash_set(h, key, value)
void * svm_msg_q_msg_data(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Get data for message in queue.
#define foreach_tcp_echo_msg
int vl_client_connect_to_vlib(const char *svm_name, const char *client_name, int rx_queue_size)
static u32 svm_fifo_max_enqueue_prod(svm_fifo_t *f)
Maximum number of bytes that can be enqueued into fifo.
#define hash_unset(h, key)
svm_queue_t * vl_input_queue
uword vpp_event_queue_address
int my_client_index
All VLIB-side message handlers use my_client_index to identify the queue / client.
#define clib_memcpy_fast(a, b, c)
void fifo_segment_delete(fifo_segment_main_t *sm, fifo_segment_t *s)
static void send_test_chunk(udp_echo_main_t *utm, app_session_t *s, u32 bytes)
static void vl_api_unbind_uri_reply_t_handler(vl_api_unbind_uri_reply_t *mp)
static void recv_test_chunk(udp_echo_main_t *utm, app_session_t *s)
static f64 clib_time_now(clib_time_t *c)
static void stop_signal(int signum)
static void udp_client_send_connect(udp_echo_main_t *utm)
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
static clib_error_t * setup_signal_handlers(void)
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
void * vl_msg_api_alloc(int nbytes)
void application_detach(udp_echo_main_t *utm)
u8 * format_api_error(u8 *s, va_list *args)
struct _svm_fifo svm_fifo_t
static void server_bind(udp_echo_main_t *utm)
fifo_segment_t * fifo_segment_get_segment(fifo_segment_main_t *sm, u32 segment_index)
void svm_region_exit(void)
static void app_alloc_ctrl_evt_to_vpp(svm_msg_q_t *mq, app_session_evt_t *app_evt, u8 evt_type)
static int app_send(app_session_t *s, u8 *data, u32 len, u8 noblock)
void client_send_data(udp_echo_main_t *utm, u32 session_index)
volatile connection_state_t state
volatile u32 cut_through_session_index
uword * session_index_by_vpp_handles
void server_handle_fifo_event_rx(udp_echo_main_t *utm, u32 session_index)
static u32 svm_fifo_max_dequeue_cons(svm_fifo_t *f)
Fifo max bytes to dequeue optimized for consumer.
static int app_send_io_evt_to_vpp(svm_msg_q_t *mq, u32 session_index, u8 evt_type, u8 noblock)
Send fifo io event to vpp worker thread.
static void client_test(udp_echo_main_t *utm)
vhost_vring_state_t state
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
int svm_fifo_dequeue(svm_fifo_t *f, u32 len, u8 *dst)
Dequeue data from fifo.
static int app_recv_dgram_raw(svm_fifo_t *f, u8 *buf, u32 len, app_session_transport_t *at, u8 clear_evt, u8 peek)
void vl_msg_api_send_shmem(svm_queue_t *q, u8 *elem)
char * segment_name
segment name
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.
static void session_accepted_handler(session_accepted_msg_t *mp)
int main(int argc, char **argv)
struct _session_endpoint_cfg session_endpoint_cfg_t
int fifo_segment_attach(fifo_segment_main_t *sm, fifo_segment_create_args_t *a)
Attach as slave to a fifo segment.
vpp->client unmap shared memory segment
void vl_set_memory_root_path(const char *name)
static int app_recv(app_session_t *s, u8 *data, u32 len)
static void handle_mq_event(session_event_t *e)
uword * error_string_by_error_number
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
client->vpp, attach application to session layer
#define pool_put(P, E)
Free an object E in pool P.
void tcp_echo_api_hookup(udp_echo_main_t *utm)
int svm_fifo_enqueue(svm_fifo_t *f, u32 len, const u8 *src)
Enqueue data to fifo.
static void svm_fifo_unset_event(svm_fifo_t *f)
Unset fifo event flag.
volatile int time_to_stop
uword vpp_event_queue_address
void clib_time_init(clib_time_t *c)
API main structure, used by both vpp and binary API clients.
static void session_bound_handler(session_bound_msg_t *mp)
static void vl_api_application_attach_reply_t_handler(vl_api_application_attach_reply_t *mp)
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
static u8 svm_fifo_set_event(svm_fifo_t *f)
Set fifo event flag.
ssvm_private_t ssvm
ssvm segment data
static void stats_signal(int signum)
volatile u32 connected_session
int connect_to_vpp(char *name)
void fifo_segment_main_init(fifo_segment_main_t *sm, u64 baseva, u32 timeout_in_seconds)
#define clib_warning(format, args...)
static void vl_api_application_detach_reply_t_handler(vl_api_application_detach_reply_t *mp)
static __clib_unused void * cut_through_thread_fn(void *arg)
#define HIGH_SEGMENT_BASEVA
void vlib_cli_output(struct vlib_main_t *vm, char *fmt,...)
blocking call - best used in combination with condvars, for eventfds we don't yield the cpu ...
Application attach reply.
static void init_error_string_table(udp_echo_main_t *utm)
uword unformat_uri(unformat_input_t *input, va_list *args)
svm_queue_t * vl_input_queue
svm_msg_q_t * our_event_queue
#define foreach_vnet_api_error
svm_msg_q_t * vpp_event_queue
#define hash_create(elts, value_bytes)
static void vl_api_app_cut_through_registration_add_t_handler(vl_api_app_cut_through_registration_add_t *mp)
#define uword_to_pointer(u, type)
#define pool_put_index(p, i)
Free pool element with given index.
u64 app_event_queue_address
client->vpp, attach application to session layer
u64 server_bytes_received
vpp->client, please map an additional shared memory segment
ask app to add a new cut-through registration
static void server_handle_event_queue(udp_echo_main_t *utm)
pthread_t cut_through_thread_handle
int wait_for_state_change(udp_echo_main_t *utm, connection_state_t state)
static void server_unbind(udp_echo_main_t *utm)
u32 configured_segment_size
svm_msg_q_t * ct_event_queue
void vl_client_add_api_signatures(vl_api_memclnt_create_t *mp)
void svm_msg_q_free_msg(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Free message buffer.
static void application_send_attach(udp_echo_main_t *utm)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void session_connected_handler(session_connected_msg_t *mp)
static int application_attach(udp_echo_main_t *utm)
static void session_disconnected_handler(session_disconnected_msg_t *mp)
struct _svm_queue svm_queue_t
struct clib_bihash_value offset
template key/value backing page structure
void vl_client_disconnect_from_vlib(void)
uword unformat_ip6_address(unformat_input_t *input, va_list *args)
#define CLIB_MEMORY_BARRIER()
fifo_segment_main_t segment_main
uword unformat_ip4_address(unformat_input_t *input, va_list *args)
#define CLIB_CACHE_LINE_BYTES
void * clib_mem_init_thread_safe(void *memory, uword memory_size)
int svm_fifo_dequeue_drop(svm_fifo_t *f, u32 len)
Dequeue and drop bytes from fifo.
udp_echo_main_t udp_echo_main
u32 * new_segment_indices
return vec of new seg indices
static void vl_api_map_another_segment_t_handler(vl_api_map_another_segment_t *mp)
static uword pool_elts(void *v)
Number of active elements in a pool.