36 #define vl_print(handle, ...) 41 #define TCP_ECHO_DBG 0 42 #define DBG(_fmt,_args...) \ 44 clib_warning (_fmt, _args) 49 #define _(type, name) type name; 52 u64 vpp_session_handle;
55 volatile u64 bytes_received;
56 volatile u64 bytes_to_receive;
86 uword *session_index_by_vpp_handles;
112 volatile connection_state_t
state;
123 u8 *connect_test_data;
127 u8 test_return_packets;
135 volatile u32 n_clients_connected;
152 #define NITER 4000000 159 i32 error = va_arg (*args,
u32);
165 s =
format (s,
"%s", p[0]);
167 s =
format (s,
"%d", error);
176 #define _(n,v,s) hash_set (em->error_string_by_error_number, -v, s); 193 #define TIMEOUT 600.0 195 #define TIMEOUT 600.0 202 if (em->
state == state)
231 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
233 bmp->
context = ntohl (0xfeedface);
246 cert_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_CERT_ADD);
248 cert_mp->
context = ntohl (0xfeedface);
255 key_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_KEY_ADD);
257 key_mp->
context = ntohl (0xfeedface);
282 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
284 bmp->
context = ntohl (0xfeedface);
287 DBG (
"%s",
"Sent detach");
306 clib_warning (
"svm_fifo_segment_attach ('%s') failed", name);
325 clib_net_to_host_u32 (mp->
retval));
344 if (mp->
fd_flags & SESSION_FD_F_VPP_MQ_SEGMENT)
348 if (mp->
fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
353 if (mp->
fd_flags & SESSION_FD_F_MQ_EVENTFD)
377 clib_warning (
"detach returned with err: %d", mp->retval);
486 fformat (stdout,
"Finished in %.6f\n", deltat);
487 fformat (stdout,
"%.4f Gbit/second\n", (bytes * 8.0) / deltat / 1e9);
494 for (i = 0; i < n_read; i++)
508 int n_to_read, n_read;
532 while (n_to_read > 0);
538 u64 test_buf_len, bytes_this_chunk, test_buf_offset;
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,
548 bytes_this_chunk, 0);
564 static u8 *rx_buf = 0;
565 u32 session_index = *(
u32 *) arg;
582 DBG (
"session %d done", session_index);
597 cmp->_vl_msg_id = ntohs (VL_API_CONNECT_URI);
599 cmp->
context = ntohl (0xfeedface);
610 dmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION);
633 clib_net_to_host_u32 (mp->
retval));
651 static f64 start_time;
655 if (start_time == 0.0)
660 clib_net_to_host_u16 (mp->
rmt.port));
664 session_index = session - em->
sessions;
667 rx_fifo->client_session_index = session_index;
669 tx_fifo->client_session_index = session_index;
671 session->rx_fifo = rx_fifo;
672 session->tx_fifo = tx_fifo;
685 fformat (stdout,
"%d active sessions in %.2f seconds, %.2f/sec...\n",
716 clib_net_to_host_u32 (mp->
retval));
727 session_index = session - em->
sessions;
730 rx_fifo->client_session_index = session_index;
732 tx_fifo->client_session_index = session_index;
734 session->rx_fifo = rx_fifo;
735 session->tx_fifo = tx_fifo;
757 clib_warning (
"session %u (0x%llx) connected with local ip %U port %d",
759 mp->
lcl.is_ip4, clib_net_to_host_u16 (mp->
lcl.port));
830 switch (e->event_type)
855 f64 start_time, deltat, timeout = 100.0;
934 fformat (stdout,
"%lld bytes (%lld mbytes, %lld gbytes) in %.2f seconds\n",
936 em->
tx_total / (1ULL << 30), deltat);
937 fformat (stdout,
"%.4f Gbit/second\n", (em->
tx_total * 8.0) / deltat / 1e9);
950 clib_net_to_host_u32 (mp->retval));
972 u8 *
a = va_arg (*args,
u8 *);
973 return format (s,
"%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
980 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
984 i_first_zero = i_max_n_zero;
989 if (is_zero && i_first_zero >= ARRAY_LEN (a->
as_u16))
995 if ((!is_zero && n_zeros > max_n_zeros)
998 i_max_n_zero = i_first_zero;
999 max_n_zeros = n_zeros;
1005 last_double_colon = 0;
1008 if (i == i_max_n_zero && max_n_zeros > 1)
1011 i += max_n_zeros - 1;
1012 last_double_colon = 1;
1017 (last_double_colon || i == 0) ?
"" :
":",
1018 clib_net_to_host_u16 (a->
as_u16[i]));
1019 last_double_colon = 0;
1030 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
1055 int n_read, max_dequeue, n_sent;
1080 max_dequeue -= n_read;
1101 while ((n_sent <= 0 || n_read > 0) && !em->
time_to_stop);
1117 switch (e->event_type)
1144 bmp->_vl_msg_id = ntohs (VL_API_BIND_URI);
1146 bmp->
context = ntohl (0xfeedface);
1171 ump->_vl_msg_id = ntohs (VL_API_UNBIND_URI);
1196 for (i = 0; i < 200000; i++)
1201 for (i = 0; i < 200000; i++)
1219 fformat (stdout,
"Test complete...\n");
1251 (vl_api_application_tls_cert_add_reply_t * mp)
1259 (vl_api_application_tls_key_add_reply_t * mp)
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) \ 1279 vl_msg_api_set_handlers(VL_API_##N, #n, \ 1280 vl_api_##n##_t_handler, \ 1282 vl_api_##n##_t_endian, \ 1283 vl_api_##n##_t_print, \ 1284 sizeof(vl_api_##n##_t), 1); 1292 int i_am_server = 1, test_return_packets = 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;
1322 if (
unformat (a,
"chroot prefix %s", &chroot_prefix))
1326 else if (
unformat (a,
"uri %s", &uri))
1328 else if (
unformat (a,
"segment-size %dM", &tmp))
1330 else if (
unformat (a,
"segment-size %dG", &tmp))
1336 else if (
unformat (a,
"no-return"))
1339 test_return_packets = 1;
1340 else if (
unformat (a,
"mbytes %lld", &mbytes))
1342 bytes_to_send = mbytes << 20;
1344 else if (
unformat (a,
"gbytes %lld", &mbytes))
1346 bytes_to_send = mbytes << 30;
1350 else if (
unformat (a,
"use-svm-api"))
1352 else if (
unformat (a,
"fifo-size %d", &tmp))
1358 fformat (stderr,
"%s: usage [master|slave]\n", argv[0]);
1373 em->
uri =
format (0,
"%s%c", bind_uri, 0);
1388 app_name = i_am_server ?
"tcp_echo_server" :
"tcp_echo_client";
1392 fformat (stderr,
"Couldn't connect to vpe, exiting...\n");
1396 if (i_am_server == 0)
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
#define foreach_app_session_field
flag for dgram mode
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)
void server_run(echo_main_t *em)
#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 CLIB_CACHE_LINE_ALIGN_MARK(mark)
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)
int vl_client_connect_to_vlib(const char *svm_name, const char *client_name, int rx_queue_size)
#define hash_unset(h, key)
#define foreach_tcp_echo_msg
static void vl_api_unbind_uri_reply_t_handler(vl_api_unbind_uri_reply_t *mp)
u8 use_sock_api
Flag that decides if socket, instead of svm, api is used to connect to vpp.
#define DBG(_fmt, _args...)
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)
static int wait_for_state_change(echo_main_t *em, connection_state_t state)
pthread_t * client_thread_handles
static f64 clib_time_now(clib_time_t *c)
static clib_error_t * setup_signal_handlers(void)
int server_listen(echo_main_t *em)
static void clients_run(echo_main_t *em)
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)
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)
volatile connection_state_t state
static void server_handle_mq(echo_main_t *em)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
void * vl_msg_api_alloc(int nbytes)
static void session_reset_handler(session_reset_msg_t *mp)
void application_detach(echo_main_t *em)
foreach_app_session_field u64 vpp_session_handle
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
struct _svm_fifo svm_fifo_t
static void * client_thread_fn(void *arg)
void svm_region_exit(void)
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)
volatile u32 n_clients_connected
void client_send_disconnect(echo_main_t *em, echo_session_t *s)
volatile u64 bytes_received
static const u32 test_srv_key_rsa_len
static u32 svm_fifo_max_dequeue_cons(svm_fifo_t *f)
Fifo max bytes to dequeue optimized for consumer.
volatile int time_to_stop
volatile int time_to_print_stats
static void vl_api_application_tls_key_add_reply_t_handler(vl_api_application_tls_key_add_reply_t *mp)
vhost_vring_state_t state
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
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.
vl_api_fib_path_type_t type
int fifo_segment_attach(fifo_segment_main_t *sm, fifo_segment_create_args_t *a)
Attach as slave to a fifo segment.
void vl_set_memory_root_path(const char *name)
int server_unbind(echo_main_t *em)
static void session_accepted_handler(session_accepted_msg_t *mp)
int main(int argc, char **argv)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static void handle_mq_event(session_event_t *e)
static int ssvm_segment_attach(char *name, ssvm_segment_type_t type, int fd)
client->vpp, attach application to session layer
uword * session_index_by_vpp_handles
#define pool_put(P, E)
Free an object E in pool P.
void server_send_listen(echo_main_t *em)
uword * error_string_by_error_number
static void svm_fifo_unset_event(svm_fifo_t *f)
Unset fifo event flag.
static void server_handle_rx(echo_main_t *em, session_event_t *e)
uword vpp_event_queue_address
static const char test_srv_crt_rsa[]
fifo_segment_main_t segment_main
void clib_time_init(clib_time_t *c)
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)
volatile u32 n_active_clients
API main structure, used by both vpp and binary API clients.
#define ip46_address_is_ip4(ip46)
static void vl_api_bind_uri_reply_t_handler(vl_api_bind_uri_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
u8 * format_ip4_address(u8 *s, va_list *args)
echo_session_t * sessions
clib_error_t * vl_socket_client_recv_fd_msg(int fds[], int n_fds, u32 wait)
void vl_socket_client_disconnect(void)
int connect_to_vpp(char *name)
static void vl_api_application_detach_reply_t_handler(vl_api_application_detach_reply_t *mp)
#define vec_free(V)
Free vector's memory (no header).
static void recv_data_chunk(echo_main_t *em, echo_session_t *s, u8 *rx_buf)
void fifo_segment_main_init(fifo_segment_main_t *sm, u64 baseva, u32 timeout_in_seconds)
#define clib_warning(format, args...)
static void stats_signal(int signum)
static void test_recv_bytes(echo_session_t *s, u8 *rx_buf, u32 n_read)
#define HIGH_SEGMENT_BASEVA
blocking call - best used in combination with condvars, for eventfds we don't yield the cpu ...
static int app_recv_stream(app_session_t *s, u8 *buf, u32 len)
int memfd_fd
fd for memfd segments
Application attach reply.
void tcp_echo_api_hookup(echo_main_t *em)
svm_queue_t * vl_input_queue
#define foreach_vnet_api_error
static const char test_srv_key_rsa[]
void vlib_cli_output(struct vlib_main_t *vm, char *fmt,...)
#define hash_create(elts, value_bytes)
#define uword_to_pointer(u, type)
static void session_print_stats(echo_main_t *em, echo_session_t *session)
#define pool_put_index(p, i)
Free pool element with given index.
u64 app_event_queue_address
client->vpp, attach application to session layer
vpp->client, please map an additional shared memory segment
static void vl_api_disconnect_session_reply_t_handler(vl_api_disconnect_session_reply_t *mp)
void application_send_attach(echo_main_t *em)
u32 configured_segment_size
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
bidirectional disconnect API
static void session_connected_handler(session_connected_msg_t *mp)
void server_send_unbind(echo_main_t *em)
int client_disconnect(echo_main_t *em, echo_session_t *s)
static void send_data_chunk(echo_main_t *em, echo_session_t *s)
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
svm_msg_q_t * our_event_queue
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void session_disconnected_handler(session_disconnected_msg_t *mp)
void client_send_connect(echo_main_t *em)
static int application_attach(echo_main_t *em)
struct _svm_queue svm_queue_t
u32 connected_session_index
struct clib_bihash_value offset
template key/value backing page structure
u8 * format_ip6_address(u8 *s, va_list *args)
void vl_client_disconnect_from_vlib(void)
u32 client_bytes_received
Application add TLS certificate.
svm_queue_t * vl_input_queue
bidirectional disconnect reply API
void * clib_mem_init_thread_safe(void *memory, uword memory_size)
static void vl_api_map_another_segment_t_handler(vl_api_map_another_segment_t *mp)
static const u32 test_srv_crt_rsa_len
u8 * format_ip46_address(u8 *s, va_list *args)
non-blocking call - works with both condvar and eventfd signaling
u32 * new_segment_indices
return vec of new seg indices
static uword pool_elts(void *v)
Number of active elements in a pool.