blob: 0108b16ac7b916c20f167516225c11066cf29bb4 [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>
Florin Coras90a63982017-12-19 04:50:01 -080018
19#include <vnet/session/application_interface.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050020#include <svm/svm_fifo_segment.h>
21#include <vlibmemory/api.h>
Florin Coras90a63982017-12-19 04:50:01 -080022
Dave Barach68b0fb02017-02-28 15:15:56 -050023#include <vpp/api/vpe_msg_enum.h>
24
Florin Corase04c2992017-03-01 08:17:34 -080025#define vl_typedefs /* define message structures */
Dave Barach68b0fb02017-02-28 15:15:56 -050026#include <vpp/api/vpe_all_api_h.h>
27#undef vl_typedefs
28
29/* declare message handlers for each api */
30
Florin Corase04c2992017-03-01 08:17:34 -080031#define vl_endianfun /* define message structures */
Dave Barach68b0fb02017-02-28 15:15:56 -050032#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
Dave Barach68b0fb02017-02-28 15:15:56 -050041typedef struct
42{
Florin Corase04c2992017-03-01 08:17:34 -080043 svm_fifo_t *server_rx_fifo;
44 svm_fifo_t *server_tx_fifo;
Dave Barach68b0fb02017-02-28 15:15:56 -050045
Florin Corasa5464812017-04-19 13:00:05 -070046 u64 vpp_session_handle;
Florin Corasf03a59a2017-06-09 21:07:32 -070047 u64 bytes_received;
48 f64 start;
Dave Barach68b0fb02017-02-28 15:15:56 -050049} session_t;
50
51typedef enum
52{
53 STATE_START,
Florin Corasa5464812017-04-19 13:00:05 -070054 STATE_ATTACHED,
Dave Barach68b0fb02017-02-28 15:15:56 -050055 STATE_READY,
56 STATE_DISCONNECTING,
57 STATE_FAILED
58} connection_state_t;
59
60typedef struct
61{
62 /* vpe input queue */
Florin Corase86a8ed2018-01-05 03:20:25 -080063 svm_queue_t *vl_input_queue;
Dave Barach68b0fb02017-02-28 15:15:56 -050064
65 /* API client handle */
66 u32 my_client_index;
67
68 /* The URI we're playing with */
Florin Corase04c2992017-03-01 08:17:34 -080069 u8 *uri;
Dave Barach68b0fb02017-02-28 15:15:56 -050070
71 /* Session pool */
Florin Corase04c2992017-03-01 08:17:34 -080072 session_t *sessions;
Dave Barach68b0fb02017-02-28 15:15:56 -050073
74 /* Hash table for disconnect processing */
Florin Corase04c2992017-03-01 08:17:34 -080075 uword *session_index_by_vpp_handles;
Dave Barach68b0fb02017-02-28 15:15:56 -050076
77 /* intermediate rx buffer */
Florin Corase04c2992017-03-01 08:17:34 -080078 u8 *rx_buf;
Dave Barach68b0fb02017-02-28 15:15:56 -050079
80 /* URI for slave's connect */
Florin Corase04c2992017-03-01 08:17:34 -080081 u8 *connect_uri;
Dave Barach68b0fb02017-02-28 15:15:56 -050082
83 u32 connected_session_index;
84
85 int i_am_master;
86
87 /* drop all packets */
88 int drop_packets;
89
90 /* Our event queue */
Florin Corase86a8ed2018-01-05 03:20:25 -080091 svm_queue_t *our_event_queue;
Dave Barach68b0fb02017-02-28 15:15:56 -050092
93 /* $$$ single thread only for the moment */
Florin Corase86a8ed2018-01-05 03:20:25 -080094 svm_queue_t *vpp_event_queue;
Dave Barach68b0fb02017-02-28 15:15:56 -050095
Florin Coras90a63982017-12-19 04:50:01 -080096 u8 *socket_name;
97
Dave Barach68b0fb02017-02-28 15:15:56 -050098 pid_t my_pid;
99
100 /* For deadman timers */
101 clib_time_t clib_time;
102
103 /* State of the connection, shared between msg RX thread and main thread */
104 volatile connection_state_t state;
105
106 /* Signal variables */
107 volatile int time_to_stop;
108 volatile int time_to_print_stats;
109
110 u32 configured_segment_size;
111
112 /* VNET_API_ERROR_FOO -> "Foo" hash table */
Florin Corase04c2992017-03-01 08:17:34 -0800113 uword *error_string_by_error_number;
Dave Barach68b0fb02017-02-28 15:15:56 -0500114
115 u8 *connect_test_data;
Florin Corase04c2992017-03-01 08:17:34 -0800116 pthread_t client_rx_thread_handle;
117 u32 client_bytes_received;
118 u8 test_return_packets;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700119 u64 bytes_to_send;
Florin Corase04c2992017-03-01 08:17:34 -0800120
Florin Coras90a63982017-12-19 04:50:01 -0800121 /** Flag that decides if socket, instead of svm, api is used to connect to
122 * vpp. If sock api is used, shm binary api is subsequently bootstrapped
123 * and all other messages are exchanged using shm IPC. */
124 u8 use_sock_api;
125
Florin Corase04c2992017-03-01 08:17:34 -0800126 /* convenience */
127 svm_fifo_segment_main_t *segment_main;
Florin Corasb384b542018-01-15 01:08:33 -0800128} echo_main_t;
Dave Barach68b0fb02017-02-28 15:15:56 -0500129
Florin Corasb384b542018-01-15 01:08:33 -0800130echo_main_t echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500131
132#if CLIB_DEBUG > 0
133#define NITER 10000
134#else
135#define NITER 4000000
136#endif
137
Florin Corase3e2f072018-03-04 07:24:30 -0800138const char test_srv_crt_rsa[] =
139 "-----BEGIN CERTIFICATE-----\r\n"
Florin Coras8f89dd02018-03-05 16:53:07 -0800140 "MIID5zCCAs+gAwIBAgIJALeMYCEHrTtJMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD\r\n"
141 "VQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMQ4wDAYDVQQK\r\n"
142 "DAVDaXNjbzEOMAwGA1UECwwFZmQuaW8xFjAUBgNVBAMMDXRlc3R0bHMuZmQuaW8x\r\n"
143 "IjAgBgkqhkiG9w0BCQEWE3ZwcC1kZXZAbGlzdHMuZmQuaW8wHhcNMTgwMzA1MjEx\r\n"
144 "NTEyWhcNMjgwMzAyMjExNTEyWjCBiTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNB\r\n"
145 "MREwDwYDVQQHDAhTYW4gSm9zZTEOMAwGA1UECgwFQ2lzY28xDjAMBgNVBAsMBWZk\r\n"
146 "LmlvMRYwFAYDVQQDDA10ZXN0dGxzLmZkLmlvMSIwIAYJKoZIhvcNAQkBFhN2cHAt\r\n"
147 "ZGV2QGxpc3RzLmZkLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\r\n"
148 "4C1k8a1DuStgggqT4o09fP9sJ2dC54bxhS/Xk2VEfaIZ222WSo4X/syRVfVy9Yah\r\n"
149 "cpI1zJ/RDxaZSFhgA+nPZBrFMsrULkrdAOpOVj8eDEp9JuWdO2ODSoFnCvLxcYWB\r\n"
150 "Yc5kHryJpEaGJl1sFQSesnzMFty/59ta0stk0Fp8r5NhIjWvSovGzPo6Bhz+VS2c\r\n"
151 "ebIZh4x1t2hHaFcgm0qJoJ6DceReWCW8w+yOVovTolGGq+bpb2Hn7MnRSZ2K2NdL\r\n"
152 "+aLXpkZbS/AODP1FF2vTO1mYL290LO7/51vJmPXNKSDYMy5EvILr5/VqtjsFCwRL\r\n"
153 "Q4jcM/+GeHSAFWx4qIv0BwIDAQABo1AwTjAdBgNVHQ4EFgQUWa1SOB37xmT53tZQ\r\n"
154 "aXuLLhRI7U8wHwYDVR0jBBgwFoAUWa1SOB37xmT53tZQaXuLLhRI7U8wDAYDVR0T\r\n"
155 "BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoUht13W4ya27NVzQuCMvqPWL3VM4\r\n"
156 "3xbPFk02FaGz/WupPu276zGlzJAZrbuDcQowwwU1Ni1Yygxl96s1c2M5rHDTrOKG\r\n"
157 "rK0hbkSFBo+i6I8u4HiiQ4rYmG0Hv6+sXn3of0HsbtDPGgWZoipPWDljPYEURu3e\r\n"
158 "3HRe/Dtsj9CakBoSDzs8ndWaBR+f4sM9Tk1cjD46Gq2T/qpSPXqKxEUXlzhdCAn4\r\n"
159 "twub17Bq2kykHpppCwPg5M+v30tHG/R2Go15MeFWbEJthFk3TZMjKL7UFs7fH+x2\r\n"
160 "wSonXb++jY+KmCb93C+soABBizE57g/KmiR2IxQ/LMjDik01RSUIaM0lLA==\r\n"
161 "-----END CERTIFICATE-----\r\n";
Florin Corase3e2f072018-03-04 07:24:30 -0800162const u32 test_srv_crt_rsa_len = sizeof (test_srv_crt_rsa);
163
164const char test_srv_key_rsa[] =
Florin Coras8f89dd02018-03-05 16:53:07 -0800165 "-----BEGIN PRIVATE KEY-----\r\n"
166 "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgLWTxrUO5K2CC\r\n"
167 "CpPijT18/2wnZ0LnhvGFL9eTZUR9ohnbbZZKjhf+zJFV9XL1hqFykjXMn9EPFplI\r\n"
168 "WGAD6c9kGsUyytQuSt0A6k5WPx4MSn0m5Z07Y4NKgWcK8vFxhYFhzmQevImkRoYm\r\n"
169 "XWwVBJ6yfMwW3L/n21rSy2TQWnyvk2EiNa9Ki8bM+joGHP5VLZx5shmHjHW3aEdo\r\n"
170 "VyCbSomgnoNx5F5YJbzD7I5Wi9OiUYar5ulvYefsydFJnYrY10v5otemRltL8A4M\r\n"
171 "/UUXa9M7WZgvb3Qs7v/nW8mY9c0pINgzLkS8guvn9Wq2OwULBEtDiNwz/4Z4dIAV\r\n"
172 "bHioi/QHAgMBAAECggEBAMzGipP8+oT166U+NlJXRFifFVN1DvdhG9PWnOxGL+c3\r\n"
173 "ILmBBC08WQzmHshPemBvR6DZkA1H23cV5JTiLWrFtC00CvhXsLRMrE5+uWotI6yE\r\n"
174 "iofybMroHvD6/X5R510UX9hQ6MHu5ShLR5VZ9zXHz5MpTmB/60jG5dLx+jgcwBK8\r\n"
175 "LuGv2YB/WCUwT9QJ3YU2eaingnXtz/MrFbkbltrqlnBdlD+kTtw6Yac9y1XuuQXc\r\n"
176 "BPeulLNDuPolJVWbUvDBZrpt2dXTgz8ws1sv+wCNE0xwQJsqW4Nx3QkpibUL9RUr\r\n"
177 "CVbKlNfa9lopT6nGKlgX69R/uH35yh9AOsfasro6w0ECgYEA82UJ8u/+ORah+0sF\r\n"
178 "Q0FfW5MTdi7OAUHOz16pUsGlaEv0ERrjZxmAkHA/VRwpvDBpx4alCv0Hc39PFLIk\r\n"
179 "nhSsM2BEuBkTAs6/GaoNAiBtQVE/hN7awNRWVmlieS0go3Y3dzaE9IUMyj8sPOFT\r\n"
180 "5JdJ6BM69PHKCkY3dKdnnfpFEuECgYEA68mRpteunF1mdZgXs+WrN+uLlRrQR20F\r\n"
181 "ZyMYiUCH2Dtn26EzA2moy7FipIIrQcX/j+KhYNGM3e7MU4LymIO29E18mn8JODnH\r\n"
182 "sQOXzBTsf8A4yIVMkcuQD3bfb0JiUGYUPOidTp2N7IJA7+6Yc3vQOyb74lnKnJoO\r\n"
183 "gougPT2wS+cCgYAn7muzb6xFsXDhyW0Tm6YJYBfRS9yAWEuVufINobeBZPSl2cN1\r\n"
184 "Jrnw+HlrfTNbrJWuJmjtZJXUXQ6cVp2rUbjutNyRV4vG6iRwEXYQ40EJdkr1gZpi\r\n"
185 "CHQhuShuuPih2MNAy7EEbM+sXrDjTBR3bFqzuHPzu7dp+BshCFX3lRfAAQKBgGQt\r\n"
186 "K5i7IhCFDjb/+3IPLgOAK7mZvsvZ4eXD33TQ2eZgtut1PXtBtNl17/b85uv293Fm\r\n"
187 "VDISVcsk3eLNS8zIiT6afUoWlxAwXEs0v5WRfjl4radkGvgGiJpJYvyeM67877RB\r\n"
188 "EDSKc/X8ESLfOB44iGvZUEMG6zJFscx9DgN25iQZAoGAbyd+JEWwdVH9/K3IH1t2\r\n"
189 "PBkZX17kNWv+iVM1WyFjbe++vfKZCrOJiyiqhDeEqgrP3AuNMlaaduC3VRC3G5oV\r\n"
190 "Mj1tlhDWQ/qhvKdCKNdIVQYDE75nw+FRWV8yYkHAnXYW3tNoweDIwixE0hkPR1bc\r\n"
191 "oEjPLVNtx8SOj/M4rhaPT3I=\r\n" "-----END PRIVATE KEY-----\r\n";
Florin Corase3e2f072018-03-04 07:24:30 -0800192const u32 test_srv_key_rsa_len = sizeof (test_srv_key_rsa);
193
Florin Corasa5464812017-04-19 13:00:05 -0700194static u8 *
195format_api_error (u8 * s, va_list * args)
196{
Florin Corasb384b542018-01-15 01:08:33 -0800197 echo_main_t *em = &echo_main;
Florin Corasa5464812017-04-19 13:00:05 -0700198 i32 error = va_arg (*args, u32);
199 uword *p;
200
Florin Corasb384b542018-01-15 01:08:33 -0800201 p = hash_get (em->error_string_by_error_number, -error);
Florin Corasa5464812017-04-19 13:00:05 -0700202
203 if (p)
204 s = format (s, "%s", p[0]);
205 else
206 s = format (s, "%d", error);
207 return s;
208}
209
210static void
Florin Corasb384b542018-01-15 01:08:33 -0800211init_error_string_table (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -0700212{
Florin Corasb384b542018-01-15 01:08:33 -0800213 em->error_string_by_error_number = hash_create (0, sizeof (uword));
Florin Corasa5464812017-04-19 13:00:05 -0700214
Florin Corasb384b542018-01-15 01:08:33 -0800215#define _(n,v,s) hash_set (em->error_string_by_error_number, -v, s);
Florin Corasa5464812017-04-19 13:00:05 -0700216 foreach_vnet_api_error;
217#undef _
218
Florin Corasb384b542018-01-15 01:08:33 -0800219 hash_set (em->error_string_by_error_number, 99, "Misc");
Florin Corasa5464812017-04-19 13:00:05 -0700220}
221
Dave Barach68b0fb02017-02-28 15:15:56 -0500222int
Florin Corasb384b542018-01-15 01:08:33 -0800223wait_for_state_change (echo_main_t * em, connection_state_t state)
Dave Barach68b0fb02017-02-28 15:15:56 -0500224{
225#if CLIB_DEBUG > 0
226#define TIMEOUT 600.0
227#else
228#define TIMEOUT 600.0
229#endif
230
Florin Corasb384b542018-01-15 01:08:33 -0800231 f64 timeout = clib_time_now (&em->clib_time) + TIMEOUT;
Dave Barach68b0fb02017-02-28 15:15:56 -0500232
Florin Corasb384b542018-01-15 01:08:33 -0800233 while (clib_time_now (&em->clib_time) < timeout)
Dave Barach68b0fb02017-02-28 15:15:56 -0500234 {
Florin Corasb384b542018-01-15 01:08:33 -0800235 if (em->state == state)
Florin Corase04c2992017-03-01 08:17:34 -0800236 return 0;
Florin Corasb384b542018-01-15 01:08:33 -0800237 if (em->state == STATE_FAILED)
Dave Barach68b0fb02017-02-28 15:15:56 -0500238 return -1;
Florin Corasb384b542018-01-15 01:08:33 -0800239 if (em->time_to_stop == 1)
Florin Corasf03a59a2017-06-09 21:07:32 -0700240 return 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500241 }
242 clib_warning ("timeout waiting for STATE_READY");
243 return -1;
244}
245
Florin Coras6cf30ad2017-04-04 23:08:23 -0700246void
Florin Corasb384b542018-01-15 01:08:33 -0800247application_send_attach (echo_main_t * em)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700248{
249 vl_api_application_attach_t *bmp;
Florin Corase3e2f072018-03-04 07:24:30 -0800250 vl_api_application_tls_cert_add_t *cert_mp;
251 vl_api_application_tls_key_add_t *key_mp;
252
Florin Corasf03a59a2017-06-09 21:07:32 -0700253 u32 fifo_size = 4 << 20;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700254 bmp = vl_msg_api_alloc (sizeof (*bmp));
255 memset (bmp, 0, sizeof (*bmp));
256
257 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_ATTACH);
Florin Corasb384b542018-01-15 01:08:33 -0800258 bmp->client_index = em->my_client_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700259 bmp->context = ntohl (0xfeedface);
Florin Corasa5464812017-04-19 13:00:05 -0700260 bmp->options[APP_OPTIONS_FLAGS] =
Florin Corascea194d2017-10-02 00:18:51 -0700261 APP_OPTIONS_FLAGS_ACCEPT_REDIRECT | APP_OPTIONS_FLAGS_ADD_SEGMENT;
Dave Barach10d8cc62017-05-30 09:30:07 -0400262 bmp->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = 16;
Florin Corasff6e7692017-12-11 04:59:01 -0800263 bmp->options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
264 bmp->options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
265 bmp->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = 128 << 20;
266 bmp->options[APP_OPTIONS_SEGMENT_SIZE] = 256 << 20;
Florin Corasb384b542018-01-15 01:08:33 -0800267 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
Florin Corase3e2f072018-03-04 07:24:30 -0800268
269 cert_mp = vl_msg_api_alloc (sizeof (*cert_mp) + test_srv_crt_rsa_len);
270 memset (cert_mp, 0, sizeof (*cert_mp));
271 cert_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_CERT_ADD);
272 cert_mp->client_index = em->my_client_index;
273 cert_mp->context = ntohl (0xfeedface);
274 cert_mp->cert_len = clib_host_to_net_u16 (test_srv_crt_rsa_len);
275 clib_memcpy (cert_mp->cert, test_srv_crt_rsa, test_srv_crt_rsa_len);
276 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & cert_mp);
277
278 key_mp = vl_msg_api_alloc (sizeof (*key_mp) + test_srv_key_rsa_len);
279 memset (key_mp, 0, sizeof (*key_mp) + test_srv_key_rsa_len);
280 key_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_KEY_ADD);
281 key_mp->client_index = em->my_client_index;
282 key_mp->context = ntohl (0xfeedface);
283 key_mp->key_len = clib_host_to_net_u16 (test_srv_key_rsa_len);
284 clib_memcpy (key_mp->key, test_srv_key_rsa, test_srv_key_rsa_len);
285 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & key_mp);
Florin Coras6cf30ad2017-04-04 23:08:23 -0700286}
287
Florin Corasa5464812017-04-19 13:00:05 -0700288int
Florin Corasb384b542018-01-15 01:08:33 -0800289application_attach (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -0700290{
Florin Corasb384b542018-01-15 01:08:33 -0800291 application_send_attach (em);
292 if (wait_for_state_change (em, STATE_ATTACHED))
Florin Corasa5464812017-04-19 13:00:05 -0700293 {
294 clib_warning ("timeout waiting for STATE_ATTACHED");
295 return -1;
296 }
297 return 0;
298}
299
Florin Coras6cf30ad2017-04-04 23:08:23 -0700300void
Florin Corasb384b542018-01-15 01:08:33 -0800301application_detach (echo_main_t * em)
Florin Coras6cf30ad2017-04-04 23:08:23 -0700302{
303 vl_api_application_detach_t *bmp;
304 bmp = vl_msg_api_alloc (sizeof (*bmp));
305 memset (bmp, 0, sizeof (*bmp));
306
307 bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
Florin Corasb384b542018-01-15 01:08:33 -0800308 bmp->client_index = em->my_client_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700309 bmp->context = ntohl (0xfeedface);
Florin Corasb384b542018-01-15 01:08:33 -0800310 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
311
312 clib_warning ("Sent detach");
313}
314
315static int
316memfd_segment_attach (void)
317{
318 ssvm_private_t _ssvm = { 0 }, *ssvm = &_ssvm;
319 clib_error_t *error;
320 int rv;
321
322 if ((error = vl_socket_client_recv_fd_msg (&ssvm->fd, 5)))
323 {
324 clib_error_report (error);
325 return -1;
326 }
327
328 if ((rv = ssvm_slave_init_memfd (ssvm)))
329 return rv;
330
331 return 0;
332}
333
334static int
335fifo_segment_attach (char *name, u32 size, ssvm_segment_type_t type)
336{
337 svm_fifo_segment_create_args_t _a, *a = &_a;
338 clib_error_t *error;
339 int rv;
340
341 memset (a, 0, sizeof (*a));
342 a->segment_name = (char *) name;
343 a->segment_size = size;
344 a->segment_type = type;
345
346 if (type == SSVM_SEGMENT_MEMFD)
347 {
348 if ((error = vl_socket_client_recv_fd_msg (&a->memfd_fd, 5)))
349 {
350 clib_error_report (error);
351 return -1;
352 }
353 }
354
355 if ((rv = svm_fifo_segment_attach (a)))
356 {
357 clib_warning ("svm_fifo_segment_attach ('%s') failed", name);
358 return rv;
359 }
360
361 return 0;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700362}
363
364static void
365vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t *
366 mp)
367{
Florin Corasb384b542018-01-15 01:08:33 -0800368 echo_main_t *em = &echo_main;
369 ssvm_segment_type_t seg_type;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700370
371 if (mp->retval)
372 {
Florin Corasa5464812017-04-19 13:00:05 -0700373 clib_warning ("attach failed: %U", format_api_error,
374 clib_net_to_host_u32 (mp->retval));
Florin Corasb384b542018-01-15 01:08:33 -0800375 em->state = STATE_FAILED;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700376 return;
377 }
378
379 if (mp->segment_name_length == 0)
380 {
381 clib_warning ("segment_name_length zero");
382 return;
383 }
384
Florin Corasb384b542018-01-15 01:08:33 -0800385 seg_type = em->use_sock_api ? SSVM_SEGMENT_MEMFD : SSVM_SEGMENT_SHM;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700386
Florin Corasb384b542018-01-15 01:08:33 -0800387 /* Attach to fifo segment */
388 if (fifo_segment_attach ((char *) mp->segment_name, mp->segment_size,
389 seg_type))
Florin Coras6cf30ad2017-04-04 23:08:23 -0700390 {
Florin Corasb384b542018-01-15 01:08:33 -0800391 em->state = STATE_FAILED;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700392 return;
393 }
394
Florin Corasb384b542018-01-15 01:08:33 -0800395 /* If we're using memfd segments, read and attach to event qs segment */
396 if (seg_type == SSVM_SEGMENT_MEMFD)
397 {
398 if (memfd_segment_attach ())
399 {
400 clib_warning ("failed to attach to evt q segment");
401 em->state = STATE_FAILED;
402 return;
403 }
404 }
405
406 ASSERT (mp->app_event_queue_address);
407 em->our_event_queue = uword_to_pointer (mp->app_event_queue_address,
408 svm_queue_t *);
409 em->state = STATE_ATTACHED;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700410}
411
412static void
413vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t *
414 mp)
415{
416 if (mp->retval)
417 clib_warning ("detach returned with err: %d", mp->retval);
418}
419
Dave Barach68b0fb02017-02-28 15:15:56 -0500420static void
Dave Barach68b0fb02017-02-28 15:15:56 -0500421stop_signal (int signum)
422{
Florin Corasb384b542018-01-15 01:08:33 -0800423 echo_main_t *um = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500424
425 um->time_to_stop = 1;
426}
427
428static void
429stats_signal (int signum)
430{
Florin Corasb384b542018-01-15 01:08:33 -0800431 echo_main_t *um = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500432
433 um->time_to_print_stats = 1;
434}
435
436static clib_error_t *
437setup_signal_handlers (void)
438{
439 signal (SIGINT, stats_signal);
440 signal (SIGQUIT, stop_signal);
441 signal (SIGTERM, stop_signal);
442
443 return 0;
444}
445
446void
447vlib_cli_output (struct vlib_main_t *vm, char *fmt, ...)
448{
449 clib_warning ("BUG");
450}
451
452int
453connect_to_vpp (char *name)
454{
Florin Corasb384b542018-01-15 01:08:33 -0800455 echo_main_t *em = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500456 api_main_t *am = &api_main;
457
Florin Corasb384b542018-01-15 01:08:33 -0800458 if (em->use_sock_api)
Florin Coras90a63982017-12-19 04:50:01 -0800459 {
Florin Corasb384b542018-01-15 01:08:33 -0800460 if (vl_socket_client_connect ((char *) em->socket_name, name,
Florin Coras90a63982017-12-19 04:50:01 -0800461 0 /* default rx, tx buffer */ ))
Florin Corasb384b542018-01-15 01:08:33 -0800462 {
463 clib_warning ("socket connect failed");
464 return -1;
465 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500466
Florin Corasb384b542018-01-15 01:08:33 -0800467 if (vl_socket_client_init_shm (0))
468 {
469 clib_warning ("init shm api failed");
470 return -1;
471 }
Florin Coras90a63982017-12-19 04:50:01 -0800472 }
473 else
474 {
475 if (vl_client_connect_to_vlib ("/vpe-api", name, 32) < 0)
Florin Corasb384b542018-01-15 01:08:33 -0800476 {
477 clib_warning ("shmem connect failed");
478 return -1;
479 }
Florin Coras90a63982017-12-19 04:50:01 -0800480 }
Florin Corasb384b542018-01-15 01:08:33 -0800481 em->vl_input_queue = am->shmem_hdr->vl_input_queue;
482 em->my_client_index = am->my_client_index;
Dave Barach68b0fb02017-02-28 15:15:56 -0500483 return 0;
484}
485
Florin Coras90a63982017-12-19 04:50:01 -0800486void
Florin Corasb384b542018-01-15 01:08:33 -0800487disconnect_from_vpp (echo_main_t * em)
Florin Coras90a63982017-12-19 04:50:01 -0800488{
Florin Corasb384b542018-01-15 01:08:33 -0800489 if (em->use_sock_api)
Florin Coras90a63982017-12-19 04:50:01 -0800490 vl_socket_client_disconnect ();
491 else
492 vl_client_disconnect_from_vlib ();
493}
494
Dave Barach68b0fb02017-02-28 15:15:56 -0500495static void
Florin Corase04c2992017-03-01 08:17:34 -0800496vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
Dave Barach68b0fb02017-02-28 15:15:56 -0500497{
498 svm_fifo_segment_create_args_t _a, *a = &_a;
499 int rv;
500
Florin Coras3cbc04b2017-10-02 00:18:51 -0700501 memset (a, 0, sizeof (*a));
Dave Barach68b0fb02017-02-28 15:15:56 -0500502 a->segment_name = (char *) mp->segment_name;
503 a->segment_size = mp->segment_size;
504 /* Attach to the segment vpp created */
505 rv = svm_fifo_segment_attach (a);
506 if (rv)
507 {
508 clib_warning ("svm_fifo_segment_attach ('%s') failed",
Florin Corase04c2992017-03-01 08:17:34 -0800509 mp->segment_name);
Dave Barach68b0fb02017-02-28 15:15:56 -0500510 return;
511 }
512 clib_warning ("Mapped new segment '%s' size %d", mp->segment_name,
Florin Corase04c2992017-03-01 08:17:34 -0800513 mp->segment_size);
Dave Barach68b0fb02017-02-28 15:15:56 -0500514}
515
516static void
Florin Corasb384b542018-01-15 01:08:33 -0800517session_print_stats (echo_main_t * em, session_t * session)
Florin Corasf03a59a2017-06-09 21:07:32 -0700518{
519 f64 deltat;
520 u64 bytes;
521
Florin Corasb384b542018-01-15 01:08:33 -0800522 deltat = clib_time_now (&em->clib_time) - session->start;
523 bytes = em->i_am_master ? session->bytes_received : em->bytes_to_send;
Florin Corasf03a59a2017-06-09 21:07:32 -0700524 fformat (stdout, "Finished in %.6f\n", deltat);
525 fformat (stdout, "%.4f Gbit/second\n", (bytes * 8.0) / deltat / 1e9);
526}
527
528static void
Dave Barach68b0fb02017-02-28 15:15:56 -0500529vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp)
530{
Florin Corasb384b542018-01-15 01:08:33 -0800531 echo_main_t *em = &echo_main;
Florin Corasf03a59a2017-06-09 21:07:32 -0700532 session_t *session = 0;
Florin Corase04c2992017-03-01 08:17:34 -0800533 vl_api_disconnect_session_reply_t *rmp;
534 uword *p;
Dave Barach68b0fb02017-02-28 15:15:56 -0500535 int rv = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500536
Florin Corasb384b542018-01-15 01:08:33 -0800537 p = hash_get (em->session_index_by_vpp_handles, mp->handle);
Florin Corase04c2992017-03-01 08:17:34 -0800538
539 if (p)
540 {
Florin Corasb384b542018-01-15 01:08:33 -0800541 session = pool_elt_at_index (em->sessions, p[0]);
542 hash_unset (em->session_index_by_vpp_handles, mp->handle);
543 pool_put (em->sessions, session);
Florin Corase04c2992017-03-01 08:17:34 -0800544 }
545 else
546 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700547 clib_warning ("couldn't find session key %llx", mp->handle);
Florin Corase04c2992017-03-01 08:17:34 -0800548 rv = -11;
549 }
550
Florin Corasb384b542018-01-15 01:08:33 -0800551// em->time_to_stop = 1;
Florin Corase04c2992017-03-01 08:17:34 -0800552
553 rmp = vl_msg_api_alloc (sizeof (*rmp));
554 memset (rmp, 0, sizeof (*rmp));
555
556 rmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION_REPLY);
557 rmp->retval = rv;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700558 rmp->handle = mp->handle;
Florin Corasf8f516a2018-02-08 15:10:09 -0800559 rmp->context = mp->context;
Florin Corasb384b542018-01-15 01:08:33 -0800560 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & rmp);
Florin Corasf03a59a2017-06-09 21:07:32 -0700561
562 if (session)
Florin Corasb384b542018-01-15 01:08:33 -0800563 session_print_stats (em, session);
Florin Corase04c2992017-03-01 08:17:34 -0800564}
565
566static void
567vl_api_reset_session_t_handler (vl_api_reset_session_t * mp)
568{
Florin Corasb384b542018-01-15 01:08:33 -0800569 echo_main_t *em = &echo_main;
Florin Corase04c2992017-03-01 08:17:34 -0800570 vl_api_reset_session_reply_t *rmp;
571 uword *p;
572 int rv = 0;
Florin Corase04c2992017-03-01 08:17:34 -0800573
Florin Corasb384b542018-01-15 01:08:33 -0800574 p = hash_get (em->session_index_by_vpp_handles, mp->handle);
Dave Barach68b0fb02017-02-28 15:15:56 -0500575
576 if (p)
577 {
Florin Corasf6359c82017-06-19 12:26:09 -0400578 clib_warning ("got reset");
579 /* Cleanup later */
Florin Corasb384b542018-01-15 01:08:33 -0800580 em->time_to_stop = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -0500581 }
582 else
583 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700584 clib_warning ("couldn't find session key %llx", mp->handle);
Dave Barach68b0fb02017-02-28 15:15:56 -0500585 rv = -11;
586 }
587
588 rmp = vl_msg_api_alloc (sizeof (*rmp));
589 memset (rmp, 0, sizeof (*rmp));
Florin Corasd79b41e2017-03-04 05:37:52 -0800590 rmp->_vl_msg_id = ntohs (VL_API_RESET_SESSION_REPLY);
Dave Barach68b0fb02017-02-28 15:15:56 -0500591 rmp->retval = rv;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700592 rmp->handle = mp->handle;
Florin Corasb384b542018-01-15 01:08:33 -0800593 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & rmp);
Dave Barach68b0fb02017-02-28 15:15:56 -0500594}
595
596void
Florin Corasb384b542018-01-15 01:08:33 -0800597client_handle_fifo_event_rx (echo_main_t * em, session_fifo_event_t * e)
Dave Barach68b0fb02017-02-28 15:15:56 -0500598{
Florin Corase04c2992017-03-01 08:17:34 -0800599 svm_fifo_t *rx_fifo;
600 int n_read, bytes, i;
Dave Barach68b0fb02017-02-28 15:15:56 -0500601
602 rx_fifo = e->fifo;
603
Florin Coras6792ec02017-03-13 03:49:51 -0700604 bytes = svm_fifo_max_dequeue (rx_fifo);
605 /* Allow enqueuing of new event */
606 svm_fifo_unset_event (rx_fifo);
607
608 /* Read the bytes */
Dave Barach68b0fb02017-02-28 15:15:56 -0500609 do
610 {
Florin Corasa5464812017-04-19 13:00:05 -0700611 n_read = svm_fifo_dequeue_nowait (rx_fifo,
Florin Corasb384b542018-01-15 01:08:33 -0800612 clib_min (vec_len (em->rx_buf),
613 bytes), em->rx_buf);
Dave Barach68b0fb02017-02-28 15:15:56 -0500614 if (n_read > 0)
Florin Corase04c2992017-03-01 08:17:34 -0800615 {
616 bytes -= n_read;
Florin Corasb384b542018-01-15 01:08:33 -0800617 if (em->test_return_packets)
Florin Corase04c2992017-03-01 08:17:34 -0800618 {
Florin Corasf03a59a2017-06-09 21:07:32 -0700619 for (i = 0; i < n_read; i++)
Florin Corase04c2992017-03-01 08:17:34 -0800620 {
Florin Corasb384b542018-01-15 01:08:33 -0800621 if (em->rx_buf[i]
622 != ((em->client_bytes_received + i) & 0xff))
Florin Corasf03a59a2017-06-09 21:07:32 -0700623 {
624 clib_warning ("error at byte %lld, 0x%x not 0x%x",
Florin Corasb384b542018-01-15 01:08:33 -0800625 em->client_bytes_received + i,
626 em->rx_buf[i],
627 ((em->client_bytes_received + i) & 0xff));
Florin Corasf03a59a2017-06-09 21:07:32 -0700628 }
Florin Corase04c2992017-03-01 08:17:34 -0800629 }
630 }
Florin Corasb384b542018-01-15 01:08:33 -0800631 em->client_bytes_received += n_read;
Florin Corase04c2992017-03-01 08:17:34 -0800632 }
Florin Coras6792ec02017-03-13 03:49:51 -0700633 else
634 {
635 if (n_read == -2)
636 {
Florin Coras6cf30ad2017-04-04 23:08:23 -0700637// clib_warning ("weird!");
Florin Coras6792ec02017-03-13 03:49:51 -0700638 break;
639 }
640 }
Florin Corase04c2992017-03-01 08:17:34 -0800641
Dave Barach68b0fb02017-02-28 15:15:56 -0500642 }
Florin Coras6792ec02017-03-13 03:49:51 -0700643 while (bytes > 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500644}
645
646void
Florin Corasb384b542018-01-15 01:08:33 -0800647client_handle_event_queue (echo_main_t * em)
Dave Barach68b0fb02017-02-28 15:15:56 -0500648{
649 session_fifo_event_t _e, *e = &_e;;
650
Florin Corasb384b542018-01-15 01:08:33 -0800651 svm_queue_sub (em->our_event_queue, (u8 *) e, SVM_Q_WAIT, 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500652 switch (e->event_type)
653 {
Florin Corasa5464812017-04-19 13:00:05 -0700654 case FIFO_EVENT_APP_RX:
Florin Corasb384b542018-01-15 01:08:33 -0800655 client_handle_fifo_event_rx (em, e);
Dave Barach68b0fb02017-02-28 15:15:56 -0500656 break;
657
Florin Corasa5464812017-04-19 13:00:05 -0700658 case FIFO_EVENT_DISCONNECT:
Dave Barach68b0fb02017-02-28 15:15:56 -0500659 return;
660
661 default:
Florin Corase04c2992017-03-01 08:17:34 -0800662 clib_warning ("unknown event type %d", e->event_type);
Dave Barach68b0fb02017-02-28 15:15:56 -0500663 break;
664 }
665}
666
Florin Corase04c2992017-03-01 08:17:34 -0800667static void *
668client_rx_thread_fn (void *arg)
Dave Barach68b0fb02017-02-28 15:15:56 -0500669{
Florin Corase04c2992017-03-01 08:17:34 -0800670 session_fifo_event_t _e, *e = &_e;
Florin Corasb384b542018-01-15 01:08:33 -0800671 echo_main_t *em = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500672
Florin Corasb384b542018-01-15 01:08:33 -0800673 em->client_bytes_received = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -0500674 while (1)
675 {
Florin Corasb384b542018-01-15 01:08:33 -0800676 svm_queue_sub (em->our_event_queue, (u8 *) e, SVM_Q_WAIT, 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500677 switch (e->event_type)
Florin Corase04c2992017-03-01 08:17:34 -0800678 {
Florin Corasa5464812017-04-19 13:00:05 -0700679 case FIFO_EVENT_APP_RX:
Florin Corasb384b542018-01-15 01:08:33 -0800680 client_handle_fifo_event_rx (em, e);
Florin Corase04c2992017-03-01 08:17:34 -0800681 break;
Dave Barach68b0fb02017-02-28 15:15:56 -0500682
Florin Corasa5464812017-04-19 13:00:05 -0700683 case FIFO_EVENT_DISCONNECT:
Florin Corase04c2992017-03-01 08:17:34 -0800684 return 0;
685 default:
686 clib_warning ("unknown event type %d", e->event_type);
687 break;
688 }
Dave Barach68b0fb02017-02-28 15:15:56 -0500689
Florin Corasb384b542018-01-15 01:08:33 -0800690 if (PREDICT_FALSE (em->time_to_stop == 1))
Florin Corase04c2992017-03-01 08:17:34 -0800691 break;
Dave Barach68b0fb02017-02-28 15:15:56 -0500692 }
Florin Corase04c2992017-03-01 08:17:34 -0800693 pthread_exit (0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500694}
695
Dave Barach68b0fb02017-02-28 15:15:56 -0500696
697static void
Dave Wallace33e002b2017-09-06 01:20:02 -0400698vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp)
Dave Barach68b0fb02017-02-28 15:15:56 -0500699{
Florin Corasb384b542018-01-15 01:08:33 -0800700 echo_main_t *em = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500701 session_t *session;
702 u32 session_index;
703 svm_fifo_t *rx_fifo, *tx_fifo;
704 int rv;
705
706 if (mp->retval)
707 {
Florin Corasa5464812017-04-19 13:00:05 -0700708 clib_warning ("connection failed with code: %U", format_api_error,
709 clib_net_to_host_u32 (mp->retval));
Florin Corasb384b542018-01-15 01:08:33 -0800710 em->state = STATE_FAILED;
Dave Barach68b0fb02017-02-28 15:15:56 -0500711 return;
712 }
Florin Corasade70e42017-10-14 18:56:41 -0700713 else
714 {
715 clib_warning ("connected with local ip %U port %d", format_ip46_address,
716 mp->lcl_ip, mp->is_ip4,
717 clib_net_to_host_u16 (mp->lcl_port));
718 }
Florin Corase04c2992017-03-01 08:17:34 -0800719
Florin Corasb384b542018-01-15 01:08:33 -0800720 em->vpp_event_queue =
Florin Corase86a8ed2018-01-05 03:20:25 -0800721 uword_to_pointer (mp->vpp_event_queue_address, svm_queue_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500722
723 /*
724 * Setup session
725 */
726
Florin Corasb384b542018-01-15 01:08:33 -0800727 pool_get (em->sessions, session);
728 session_index = session - em->sessions;
Dave Barach68b0fb02017-02-28 15:15:56 -0500729
Damjan Marion7bee80c2017-04-26 15:32:12 +0200730 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500731 rx_fifo->client_session_index = session_index;
Damjan Marion7bee80c2017-04-26 15:32:12 +0200732 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -0500733 tx_fifo->client_session_index = session_index;
734
735 session->server_rx_fifo = rx_fifo;
736 session->server_tx_fifo = tx_fifo;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700737 session->vpp_session_handle = mp->handle;
Florin Corasb384b542018-01-15 01:08:33 -0800738 session->start = clib_time_now (&em->clib_time);
Dave Barach68b0fb02017-02-28 15:15:56 -0500739
740 /* Save handle */
Florin Corasb384b542018-01-15 01:08:33 -0800741 em->connected_session_index = session_index;
742 em->state = STATE_READY;
Florin Corase04c2992017-03-01 08:17:34 -0800743
744 /* Add it to lookup table */
Florin Corasb384b542018-01-15 01:08:33 -0800745 hash_set (em->session_index_by_vpp_handles, mp->handle, session_index);
Florin Corase04c2992017-03-01 08:17:34 -0800746
747 /* Start RX thread */
Florin Corasb384b542018-01-15 01:08:33 -0800748 rv = pthread_create (&em->client_rx_thread_handle,
Florin Corase04c2992017-03-01 08:17:34 -0800749 NULL /*attr */ , client_rx_thread_fn, 0);
750 if (rv)
751 {
752 clib_warning ("pthread_create returned %d", rv);
753 rv = VNET_API_ERROR_SYSCALL_ERROR_1;
754 }
755}
756
Florin Coras6792ec02017-03-13 03:49:51 -0700757static void
Florin Corasb384b542018-01-15 01:08:33 -0800758send_test_chunk (echo_main_t * em, svm_fifo_t * tx_fifo, int mypid, u32 bytes)
Florin Corase04c2992017-03-01 08:17:34 -0800759{
Florin Corasb384b542018-01-15 01:08:33 -0800760 u8 *test_data = em->connect_test_data;
Florin Corase04c2992017-03-01 08:17:34 -0800761 u64 bytes_sent = 0;
Florin Coras6792ec02017-03-13 03:49:51 -0700762 int test_buf_offset = 0;
763 u32 bytes_to_snd;
Florin Corasf03a59a2017-06-09 21:07:32 -0700764 u32 queue_max_chunk = 128 << 10, actual_write;
Florin Corase04c2992017-03-01 08:17:34 -0800765 session_fifo_event_t evt;
Florin Coras6792ec02017-03-13 03:49:51 -0700766 int rv;
Florin Corase04c2992017-03-01 08:17:34 -0800767
Florin Coras6792ec02017-03-13 03:49:51 -0700768 bytes_to_snd = (bytes == 0) ? vec_len (test_data) : bytes;
769 if (bytes_to_snd > vec_len (test_data))
770 bytes_to_snd = vec_len (test_data);
Florin Corase04c2992017-03-01 08:17:34 -0800771
Florin Corasb384b542018-01-15 01:08:33 -0800772 while (bytes_to_snd > 0 && !em->time_to_stop)
Florin Corase04c2992017-03-01 08:17:34 -0800773 {
Florin Corasf03a59a2017-06-09 21:07:32 -0700774 actual_write = (bytes_to_snd > queue_max_chunk) ?
775 queue_max_chunk : bytes_to_snd;
Florin Corasa5464812017-04-19 13:00:05 -0700776 rv = svm_fifo_enqueue_nowait (tx_fifo, actual_write,
Florin Coras6792ec02017-03-13 03:49:51 -0700777 test_data + test_buf_offset);
778
779 if (rv > 0)
Florin Corase04c2992017-03-01 08:17:34 -0800780 {
Florin Coras6792ec02017-03-13 03:49:51 -0700781 bytes_to_snd -= rv;
782 test_buf_offset += rv;
783 bytes_sent += rv;
Florin Corase04c2992017-03-01 08:17:34 -0800784
Florin Coras6792ec02017-03-13 03:49:51 -0700785 if (svm_fifo_set_event (tx_fifo))
Florin Corase04c2992017-03-01 08:17:34 -0800786 {
Florin Corase04c2992017-03-01 08:17:34 -0800787 /* Fabricate TX event, send to vpp */
788 evt.fifo = tx_fifo;
Florin Corasa5464812017-04-19 13:00:05 -0700789 evt.event_type = FIFO_EVENT_APP_TX;
Florin Corase04c2992017-03-01 08:17:34 -0800790
Florin Corasb384b542018-01-15 01:08:33 -0800791 svm_queue_add (em->vpp_event_queue,
Florin Corase86a8ed2018-01-05 03:20:25 -0800792 (u8 *) & evt, 0 /* do wait for mutex */ );
Florin Corase04c2992017-03-01 08:17:34 -0800793 }
794 }
795 }
Florin Coras6792ec02017-03-13 03:49:51 -0700796}
797
798void
Florin Corasb384b542018-01-15 01:08:33 -0800799client_send_data (echo_main_t * em)
Florin Coras6792ec02017-03-13 03:49:51 -0700800{
Florin Corasb384b542018-01-15 01:08:33 -0800801 u8 *test_data = em->connect_test_data;
Florin Coras6792ec02017-03-13 03:49:51 -0700802 int mypid = getpid ();
803 session_t *session;
804 svm_fifo_t *tx_fifo;
805 u32 n_iterations, leftover;
806 int i;
807
Florin Corasb384b542018-01-15 01:08:33 -0800808 session = pool_elt_at_index (em->sessions, em->connected_session_index);
Florin Coras6792ec02017-03-13 03:49:51 -0700809 tx_fifo = session->server_tx_fifo;
810
Florin Coras82b13a82017-04-25 11:58:06 -0700811 ASSERT (vec_len (test_data) > 0);
812
Florin Corasb384b542018-01-15 01:08:33 -0800813 vec_validate (em->rx_buf, vec_len (test_data) - 1);
814 n_iterations = em->bytes_to_send / vec_len (test_data);
Florin Coras6792ec02017-03-13 03:49:51 -0700815
816 for (i = 0; i < n_iterations; i++)
817 {
Florin Corasb384b542018-01-15 01:08:33 -0800818 send_test_chunk (em, tx_fifo, mypid, 0);
819 if (em->time_to_stop)
Florin Corasf6359c82017-06-19 12:26:09 -0400820 break;
Florin Coras6792ec02017-03-13 03:49:51 -0700821 }
822
Florin Corasb384b542018-01-15 01:08:33 -0800823 leftover = em->bytes_to_send % vec_len (test_data);
Florin Coras6792ec02017-03-13 03:49:51 -0700824 if (leftover)
Florin Corasb384b542018-01-15 01:08:33 -0800825 send_test_chunk (em, tx_fifo, mypid, leftover);
Florin Corase04c2992017-03-01 08:17:34 -0800826
Florin Corasb384b542018-01-15 01:08:33 -0800827 if (!em->drop_packets)
Florin Corase04c2992017-03-01 08:17:34 -0800828 {
Florin Corasb384b542018-01-15 01:08:33 -0800829 f64 timeout = clib_time_now (&em->clib_time) + 10;
Florin Corase04c2992017-03-01 08:17:34 -0800830
831 /* Wait for the outstanding packets */
Florin Corasb384b542018-01-15 01:08:33 -0800832 while (em->client_bytes_received <
Florin Coras6792ec02017-03-13 03:49:51 -0700833 vec_len (test_data) * n_iterations + leftover)
Florin Corase04c2992017-03-01 08:17:34 -0800834 {
Florin Corasb384b542018-01-15 01:08:33 -0800835 if (clib_time_now (&em->clib_time) > timeout)
Florin Corase04c2992017-03-01 08:17:34 -0800836 {
837 clib_warning ("timed out waiting for the missing packets");
838 break;
839 }
840 }
Florin Corase04c2992017-03-01 08:17:34 -0800841 }
Florin Corasb384b542018-01-15 01:08:33 -0800842 em->time_to_stop = 1;
Florin Corase04c2992017-03-01 08:17:34 -0800843}
844
845void
Florin Corasb384b542018-01-15 01:08:33 -0800846client_send_connect (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -0800847{
848 vl_api_connect_uri_t *cmp;
849 cmp = vl_msg_api_alloc (sizeof (*cmp));
850 memset (cmp, 0, sizeof (*cmp));
851
852 cmp->_vl_msg_id = ntohs (VL_API_CONNECT_URI);
Florin Corasb384b542018-01-15 01:08:33 -0800853 cmp->client_index = em->my_client_index;
Florin Corase04c2992017-03-01 08:17:34 -0800854 cmp->context = ntohl (0xfeedface);
Florin Corasb384b542018-01-15 01:08:33 -0800855 memcpy (cmp->uri, em->connect_uri, vec_len (em->connect_uri));
856 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & cmp);
Florin Corase04c2992017-03-01 08:17:34 -0800857}
858
Florin Corasa5464812017-04-19 13:00:05 -0700859int
Florin Corasb384b542018-01-15 01:08:33 -0800860client_connect (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -0700861{
Florin Corasb384b542018-01-15 01:08:33 -0800862 client_send_connect (em);
863 if (wait_for_state_change (em, STATE_READY))
Florin Corasa5464812017-04-19 13:00:05 -0700864 {
865 clib_warning ("Connect failed");
866 return -1;
867 }
868 return 0;
869}
870
Florin Corase04c2992017-03-01 08:17:34 -0800871void
Florin Corasb384b542018-01-15 01:08:33 -0800872client_send_disconnect (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -0800873{
874 session_t *connected_session;
875 vl_api_disconnect_session_t *dmp;
Florin Corasb384b542018-01-15 01:08:33 -0800876 connected_session = pool_elt_at_index (em->sessions,
877 em->connected_session_index);
Florin Corase04c2992017-03-01 08:17:34 -0800878 dmp = vl_msg_api_alloc (sizeof (*dmp));
879 memset (dmp, 0, sizeof (*dmp));
880 dmp->_vl_msg_id = ntohs (VL_API_DISCONNECT_SESSION);
Florin Corasb384b542018-01-15 01:08:33 -0800881 dmp->client_index = em->my_client_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -0700882 dmp->handle = connected_session->vpp_session_handle;
Florin Corasb384b542018-01-15 01:08:33 -0800883 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & dmp);
Florin Corase04c2992017-03-01 08:17:34 -0800884}
885
Florin Corasa5464812017-04-19 13:00:05 -0700886int
Florin Corasb384b542018-01-15 01:08:33 -0800887client_disconnect (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -0700888{
Florin Corasb384b542018-01-15 01:08:33 -0800889 client_send_disconnect (em);
Florin Corasf03a59a2017-06-09 21:07:32 -0700890 clib_warning ("Sent disconnect");
Florin Corasb384b542018-01-15 01:08:33 -0800891 if (wait_for_state_change (em, STATE_START))
Florin Corasa5464812017-04-19 13:00:05 -0700892 {
893 clib_warning ("Disconnect failed");
894 return -1;
895 }
896 return 0;
897}
898
Florin Corase04c2992017-03-01 08:17:34 -0800899static void
Florin Corasb384b542018-01-15 01:08:33 -0800900client_run (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -0800901{
902 int i;
903
Florin Corasb384b542018-01-15 01:08:33 -0800904 if (application_attach (em))
Florin Corasa5464812017-04-19 13:00:05 -0700905 return;
Florin Corase04c2992017-03-01 08:17:34 -0800906
Florin Corasb384b542018-01-15 01:08:33 -0800907 if (client_connect (em))
Florin Corase04c2992017-03-01 08:17:34 -0800908 {
Florin Corasb384b542018-01-15 01:08:33 -0800909 application_detach (em);
Florin Corase04c2992017-03-01 08:17:34 -0800910 return;
911 }
912
913 /* Init test data */
Florin Corasb384b542018-01-15 01:08:33 -0800914 vec_validate (em->connect_test_data, 128 * 1024 - 1);
915 for (i = 0; i < vec_len (em->connect_test_data); i++)
916 em->connect_test_data[i] = i & 0xff;
Florin Corase04c2992017-03-01 08:17:34 -0800917
918 /* Start send */
Florin Corasb384b542018-01-15 01:08:33 -0800919 client_send_data (em);
Florin Corase04c2992017-03-01 08:17:34 -0800920
Florin Corasb384b542018-01-15 01:08:33 -0800921 /* Disconnect and detach */
922 client_disconnect (em);
923 application_detach (em);
Florin Corase04c2992017-03-01 08:17:34 -0800924}
925
926static void
927vl_api_bind_uri_reply_t_handler (vl_api_bind_uri_reply_t * mp)
928{
Florin Corasb384b542018-01-15 01:08:33 -0800929 echo_main_t *em = &echo_main;
Florin Corase04c2992017-03-01 08:17:34 -0800930
931 if (mp->retval)
932 {
flyingeagle23a07779f2017-04-26 20:22:04 +0800933 clib_warning ("bind failed: %U", format_api_error,
Florin Corasa5464812017-04-19 13:00:05 -0700934 clib_net_to_host_u32 (mp->retval));
Florin Corasb384b542018-01-15 01:08:33 -0800935 em->state = STATE_FAILED;
Florin Corase04c2992017-03-01 08:17:34 -0800936 return;
937 }
938
Florin Corasb384b542018-01-15 01:08:33 -0800939 em->state = STATE_READY;
Dave Barach68b0fb02017-02-28 15:15:56 -0500940}
941
Dave Barach68b0fb02017-02-28 15:15:56 -0500942static void
Florin Corase04c2992017-03-01 08:17:34 -0800943vl_api_unbind_uri_reply_t_handler (vl_api_unbind_uri_reply_t * mp)
Dave Barach68b0fb02017-02-28 15:15:56 -0500944{
Florin Corasb384b542018-01-15 01:08:33 -0800945 echo_main_t *em = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -0500946
947 if (mp->retval != 0)
Florin Corase04c2992017-03-01 08:17:34 -0800948 clib_warning ("returned %d", ntohl (mp->retval));
Dave Barach68b0fb02017-02-28 15:15:56 -0500949
Florin Corasb384b542018-01-15 01:08:33 -0800950 em->state = STATE_START;
Dave Barach68b0fb02017-02-28 15:15:56 -0500951}
952
Florin Coras6cf30ad2017-04-04 23:08:23 -0700953u8 *
954format_ip4_address (u8 * s, va_list * args)
955{
956 u8 *a = va_arg (*args, u8 *);
957 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
958}
959
960u8 *
961format_ip6_address (u8 * s, va_list * args)
962{
963 ip6_address_t *a = va_arg (*args, ip6_address_t *);
964 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
965
966 i_max_n_zero = ARRAY_LEN (a->as_u16);
967 max_n_zeros = 0;
968 i_first_zero = i_max_n_zero;
969 n_zeros = 0;
970 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
971 {
972 u32 is_zero = a->as_u16[i] == 0;
973 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
974 {
975 i_first_zero = i;
976 n_zeros = 0;
977 }
978 n_zeros += is_zero;
979 if ((!is_zero && n_zeros > max_n_zeros)
980 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
981 {
982 i_max_n_zero = i_first_zero;
983 max_n_zeros = n_zeros;
984 i_first_zero = ARRAY_LEN (a->as_u16);
985 n_zeros = 0;
986 }
987 }
988
989 last_double_colon = 0;
990 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
991 {
992 if (i == i_max_n_zero && max_n_zeros > 1)
993 {
994 s = format (s, "::");
995 i += max_n_zeros - 1;
996 last_double_colon = 1;
997 }
998 else
999 {
1000 s = format (s, "%s%x",
1001 (last_double_colon || i == 0) ? "" : ":",
1002 clib_net_to_host_u16 (a->as_u16[i]));
1003 last_double_colon = 0;
1004 }
1005 }
1006
1007 return s;
1008}
1009
1010/* Format an IP46 address. */
1011u8 *
1012format_ip46_address (u8 * s, va_list * args)
1013{
1014 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
1015 ip46_type_t type = va_arg (*args, ip46_type_t);
1016 int is_ip4 = 1;
1017
1018 switch (type)
1019 {
1020 case IP46_TYPE_ANY:
1021 is_ip4 = ip46_address_is_ip4 (ip46);
1022 break;
1023 case IP46_TYPE_IP4:
1024 is_ip4 = 1;
1025 break;
1026 case IP46_TYPE_IP6:
1027 is_ip4 = 0;
1028 break;
1029 }
1030
1031 return is_ip4 ?
1032 format (s, "%U", format_ip4_address, &ip46->ip4) :
1033 format (s, "%U", format_ip6_address, &ip46->ip6);
1034}
1035
Dave Barach68b0fb02017-02-28 15:15:56 -05001036static void
1037vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
1038{
Florin Corasb384b542018-01-15 01:08:33 -08001039 echo_main_t *em = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -05001040 vl_api_accept_session_reply_t *rmp;
Florin Corase04c2992017-03-01 08:17:34 -08001041 svm_fifo_t *rx_fifo, *tx_fifo;
1042 session_t *session;
Dave Barach68b0fb02017-02-28 15:15:56 -05001043 static f64 start_time;
Dave Barach68b0fb02017-02-28 15:15:56 -05001044 u32 session_index;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001045 u8 *ip_str;
Dave Barach68b0fb02017-02-28 15:15:56 -05001046
1047 if (start_time == 0.0)
Florin Corasb384b542018-01-15 01:08:33 -08001048 start_time = clib_time_now (&em->clib_time);
Dave Barach68b0fb02017-02-28 15:15:56 -05001049
Florin Coras6cf30ad2017-04-04 23:08:23 -07001050 ip_str = format (0, "%U", format_ip46_address, &mp->ip, mp->is_ip4);
1051 clib_warning ("Accepted session from: %s:%d", ip_str,
1052 clib_net_to_host_u16 (mp->port));
Florin Corasb384b542018-01-15 01:08:33 -08001053 em->vpp_event_queue =
Florin Corase86a8ed2018-01-05 03:20:25 -08001054 uword_to_pointer (mp->vpp_event_queue_address, svm_queue_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -05001055
1056 /* Allocate local session and set it up */
Florin Corasb384b542018-01-15 01:08:33 -08001057 pool_get (em->sessions, session);
1058 session_index = session - em->sessions;
Dave Barach68b0fb02017-02-28 15:15:56 -05001059
Damjan Marion7bee80c2017-04-26 15:32:12 +02001060 rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -05001061 rx_fifo->client_session_index = session_index;
Damjan Marion7bee80c2017-04-26 15:32:12 +02001062 tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
Dave Barach68b0fb02017-02-28 15:15:56 -05001063 tx_fifo->client_session_index = session_index;
1064
1065 session->server_rx_fifo = rx_fifo;
1066 session->server_tx_fifo = tx_fifo;
1067
1068 /* Add it to lookup table */
Florin Corasb384b542018-01-15 01:08:33 -08001069 hash_set (em->session_index_by_vpp_handles, mp->handle, session_index);
Dave Barach68b0fb02017-02-28 15:15:56 -05001070
Florin Corasb384b542018-01-15 01:08:33 -08001071 em->state = STATE_READY;
Dave Barach68b0fb02017-02-28 15:15:56 -05001072
1073 /* Stats printing */
Florin Corasb384b542018-01-15 01:08:33 -08001074 if (pool_elts (em->sessions) && (pool_elts (em->sessions) % 20000) == 0)
Dave Barach68b0fb02017-02-28 15:15:56 -05001075 {
Florin Corasb384b542018-01-15 01:08:33 -08001076 f64 now = clib_time_now (&em->clib_time);
Dave Barach68b0fb02017-02-28 15:15:56 -05001077 fformat (stdout, "%d active sessions in %.2f seconds, %.2f/sec...\n",
Florin Corasb384b542018-01-15 01:08:33 -08001078 pool_elts (em->sessions), now - start_time,
1079 (f64) pool_elts (em->sessions) / (now - start_time));
Dave Barach68b0fb02017-02-28 15:15:56 -05001080 }
1081
Florin Corase04c2992017-03-01 08:17:34 -08001082 /*
1083 * Send accept reply to vpp
1084 */
Dave Barach68b0fb02017-02-28 15:15:56 -05001085 rmp = vl_msg_api_alloc (sizeof (*rmp));
1086 memset (rmp, 0, sizeof (*rmp));
1087 rmp->_vl_msg_id = ntohs (VL_API_ACCEPT_SESSION_REPLY);
Florin Coras6cf30ad2017-04-04 23:08:23 -07001088 rmp->handle = mp->handle;
Florin Coras3cbc04b2017-10-02 00:18:51 -07001089 rmp->context = mp->context;
Florin Corasb384b542018-01-15 01:08:33 -08001090 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & rmp);
Florin Corasf03a59a2017-06-09 21:07:32 -07001091
1092 session->bytes_received = 0;
Florin Corasb384b542018-01-15 01:08:33 -08001093 session->start = clib_time_now (&em->clib_time);
Dave Barach68b0fb02017-02-28 15:15:56 -05001094}
1095
1096void
Florin Corasb384b542018-01-15 01:08:33 -08001097server_handle_fifo_event_rx (echo_main_t * em, session_fifo_event_t * e)
Dave Barach68b0fb02017-02-28 15:15:56 -05001098{
Florin Corase04c2992017-03-01 08:17:34 -08001099 svm_fifo_t *rx_fifo, *tx_fifo;
1100 int n_read;
Florin Corase04c2992017-03-01 08:17:34 -08001101 session_fifo_event_t evt;
Florin Corase86a8ed2018-01-05 03:20:25 -08001102 svm_queue_t *q;
Florin Corasf03a59a2017-06-09 21:07:32 -07001103 session_t *session;
1104 int rv;
1105 u32 max_dequeue, offset, max_transfer, rx_buf_len;
Florin Corase04c2992017-03-01 08:17:34 -08001106
Florin Corasb384b542018-01-15 01:08:33 -08001107 rx_buf_len = vec_len (em->rx_buf);
Florin Corase04c2992017-03-01 08:17:34 -08001108 rx_fifo = e->fifo;
Florin Corasb384b542018-01-15 01:08:33 -08001109 session = &em->sessions[rx_fifo->client_session_index];
Florin Corasf03a59a2017-06-09 21:07:32 -07001110 tx_fifo = session->server_tx_fifo;
Florin Corase04c2992017-03-01 08:17:34 -08001111
Florin Corasf03a59a2017-06-09 21:07:32 -07001112 max_dequeue = svm_fifo_max_dequeue (rx_fifo);
Florin Coras6792ec02017-03-13 03:49:51 -07001113 /* Allow enqueuing of a new event */
1114 svm_fifo_unset_event (rx_fifo);
1115
Florin Corasf03a59a2017-06-09 21:07:32 -07001116 if (PREDICT_FALSE (max_dequeue == 0))
1117 {
1118 return;
1119 }
Florin Coras6792ec02017-03-13 03:49:51 -07001120
Florin Corasf03a59a2017-06-09 21:07:32 -07001121 /* Read the max_dequeue */
Florin Corase04c2992017-03-01 08:17:34 -08001122 do
1123 {
Florin Corasf03a59a2017-06-09 21:07:32 -07001124 max_transfer = clib_min (rx_buf_len, max_dequeue);
Florin Corasb384b542018-01-15 01:08:33 -08001125 n_read = svm_fifo_dequeue_nowait (rx_fifo, max_transfer, em->rx_buf);
Florin Coras6792ec02017-03-13 03:49:51 -07001126 if (n_read > 0)
Florin Corase04c2992017-03-01 08:17:34 -08001127 {
Florin Corasf03a59a2017-06-09 21:07:32 -07001128 max_dequeue -= n_read;
1129 session->bytes_received += n_read;
1130 }
1131
1132 /* Reflect if a non-drop session */
Florin Corasb384b542018-01-15 01:08:33 -08001133 if (!em->drop_packets && n_read > 0)
Florin Corasf03a59a2017-06-09 21:07:32 -07001134 {
1135 offset = 0;
Florin Corase04c2992017-03-01 08:17:34 -08001136 do
1137 {
Florin Corasf03a59a2017-06-09 21:07:32 -07001138 rv = svm_fifo_enqueue_nowait (tx_fifo, n_read,
Florin Corasb384b542018-01-15 01:08:33 -08001139 &em->rx_buf[offset]);
Florin Corasf03a59a2017-06-09 21:07:32 -07001140 if (rv > 0)
1141 {
1142 n_read -= rv;
1143 offset += rv;
1144 }
Florin Corase04c2992017-03-01 08:17:34 -08001145 }
Florin Corasb384b542018-01-15 01:08:33 -08001146 while ((rv <= 0 || n_read > 0) && !em->time_to_stop);
Florin Corase04c2992017-03-01 08:17:34 -08001147
Florin Coras6792ec02017-03-13 03:49:51 -07001148 /* If event wasn't set, add one */
1149 if (svm_fifo_set_event (tx_fifo))
1150 {
1151 /* Fabricate TX event, send to vpp */
1152 evt.fifo = tx_fifo;
Florin Corasa5464812017-04-19 13:00:05 -07001153 evt.event_type = FIFO_EVENT_APP_TX;
Florin Coras6792ec02017-03-13 03:49:51 -07001154
Florin Corasb384b542018-01-15 01:08:33 -08001155 q = em->vpp_event_queue;
Florin Corase86a8ed2018-01-05 03:20:25 -08001156 svm_queue_add (q, (u8 *) & evt, 1 /* do wait for mutex */ );
Florin Coras6792ec02017-03-13 03:49:51 -07001157 }
Florin Corase04c2992017-03-01 08:17:34 -08001158 }
Florin Corase04c2992017-03-01 08:17:34 -08001159 }
Florin Corasb384b542018-01-15 01:08:33 -08001160 while ((n_read < 0 || max_dequeue > 0) && !em->time_to_stop);
Florin Corase04c2992017-03-01 08:17:34 -08001161}
1162
1163void
Florin Corasb384b542018-01-15 01:08:33 -08001164server_handle_event_queue (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -08001165{
Florin Coras3cbc04b2017-10-02 00:18:51 -07001166 session_fifo_event_t _e, *e = &_e;
Florin Corase04c2992017-03-01 08:17:34 -08001167
1168 while (1)
1169 {
Florin Corasb384b542018-01-15 01:08:33 -08001170 svm_queue_sub (em->our_event_queue, (u8 *) e, SVM_Q_WAIT, 0);
Florin Corase04c2992017-03-01 08:17:34 -08001171 switch (e->event_type)
1172 {
Florin Corasa5464812017-04-19 13:00:05 -07001173 case FIFO_EVENT_APP_RX:
Florin Corasb384b542018-01-15 01:08:33 -08001174 server_handle_fifo_event_rx (em, e);
Florin Corase04c2992017-03-01 08:17:34 -08001175 break;
1176
Florin Corasa5464812017-04-19 13:00:05 -07001177 case FIFO_EVENT_DISCONNECT:
Florin Corase04c2992017-03-01 08:17:34 -08001178 return;
1179
1180 default:
1181 clib_warning ("unknown event type %d", e->event_type);
1182 break;
1183 }
Florin Corasb384b542018-01-15 01:08:33 -08001184 if (PREDICT_FALSE (em->time_to_stop == 1))
Florin Corase04c2992017-03-01 08:17:34 -08001185 break;
Florin Corasb384b542018-01-15 01:08:33 -08001186 if (PREDICT_FALSE (em->time_to_print_stats == 1))
Florin Corase04c2992017-03-01 08:17:34 -08001187 {
Florin Corasb384b542018-01-15 01:08:33 -08001188 em->time_to_print_stats = 0;
1189 fformat (stdout, "%d connections\n", pool_elts (em->sessions));
Florin Corase04c2992017-03-01 08:17:34 -08001190 }
1191 }
1192}
1193
1194void
Florin Corasb384b542018-01-15 01:08:33 -08001195server_send_listen (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -08001196{
1197 vl_api_bind_uri_t *bmp;
Florin Corase04c2992017-03-01 08:17:34 -08001198 bmp = vl_msg_api_alloc (sizeof (*bmp));
1199 memset (bmp, 0, sizeof (*bmp));
1200
1201 bmp->_vl_msg_id = ntohs (VL_API_BIND_URI);
Florin Corasb384b542018-01-15 01:08:33 -08001202 bmp->client_index = em->my_client_index;
Florin Corase04c2992017-03-01 08:17:34 -08001203 bmp->context = ntohl (0xfeedface);
Florin Corasb384b542018-01-15 01:08:33 -08001204 memcpy (bmp->uri, em->uri, vec_len (em->uri));
1205 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
Florin Corase04c2992017-03-01 08:17:34 -08001206}
1207
Florin Corasa5464812017-04-19 13:00:05 -07001208int
Florin Corasb384b542018-01-15 01:08:33 -08001209server_listen (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -07001210{
Florin Corasb384b542018-01-15 01:08:33 -08001211 server_send_listen (em);
1212 if (wait_for_state_change (em, STATE_READY))
Florin Corasa5464812017-04-19 13:00:05 -07001213 {
1214 clib_warning ("timeout waiting for STATE_READY");
1215 return -1;
1216 }
1217 return 0;
1218}
1219
Florin Corase04c2992017-03-01 08:17:34 -08001220void
Florin Corasb384b542018-01-15 01:08:33 -08001221server_send_unbind (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -08001222{
1223 vl_api_unbind_uri_t *ump;
1224
1225 ump = vl_msg_api_alloc (sizeof (*ump));
1226 memset (ump, 0, sizeof (*ump));
1227
1228 ump->_vl_msg_id = ntohs (VL_API_UNBIND_URI);
Florin Corasb384b542018-01-15 01:08:33 -08001229 ump->client_index = em->my_client_index;
1230 memcpy (ump->uri, em->uri, vec_len (em->uri));
1231 vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & ump);
Florin Corase04c2992017-03-01 08:17:34 -08001232}
1233
Florin Corasa5464812017-04-19 13:00:05 -07001234int
Florin Corasb384b542018-01-15 01:08:33 -08001235server_unbind (echo_main_t * em)
Florin Corasa5464812017-04-19 13:00:05 -07001236{
Florin Corasb384b542018-01-15 01:08:33 -08001237 server_send_unbind (em);
1238 if (wait_for_state_change (em, STATE_START))
Florin Corasa5464812017-04-19 13:00:05 -07001239 {
1240 clib_warning ("timeout waiting for STATE_START");
1241 return -1;
1242 }
1243 return 0;
1244}
1245
Florin Corase04c2992017-03-01 08:17:34 -08001246void
Florin Corasb384b542018-01-15 01:08:33 -08001247server_run (echo_main_t * em)
Florin Corase04c2992017-03-01 08:17:34 -08001248{
Florin Coras90a63982017-12-19 04:50:01 -08001249 session_t *session;
1250 int i;
1251
1252 /* $$$$ hack preallocation */
1253 for (i = 0; i < 200000; i++)
1254 {
Florin Corasb384b542018-01-15 01:08:33 -08001255 pool_get (em->sessions, session);
Florin Coras90a63982017-12-19 04:50:01 -08001256 memset (session, 0, sizeof (*session));
1257 }
1258 for (i = 0; i < 200000; i++)
Florin Corasb384b542018-01-15 01:08:33 -08001259 pool_put_index (em->sessions, i);
Florin Coras90a63982017-12-19 04:50:01 -08001260
Florin Corasb384b542018-01-15 01:08:33 -08001261 if (application_attach (em))
Florin Corasa5464812017-04-19 13:00:05 -07001262 return;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001263
Dave Barach68b0fb02017-02-28 15:15:56 -05001264 /* Bind to uri */
Florin Corasb384b542018-01-15 01:08:33 -08001265 if (server_listen (em))
Florin Corasa5464812017-04-19 13:00:05 -07001266 return;
Dave Barach68b0fb02017-02-28 15:15:56 -05001267
1268 /* Enter handle event loop */
Florin Corasb384b542018-01-15 01:08:33 -08001269 server_handle_event_queue (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001270
1271 /* Cleanup */
Florin Corasb384b542018-01-15 01:08:33 -08001272 server_send_unbind (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001273
Florin Corasb384b542018-01-15 01:08:33 -08001274 application_detach (em);
Florin Coras6cf30ad2017-04-04 23:08:23 -07001275
Dave Barach68b0fb02017-02-28 15:15:56 -05001276 fformat (stdout, "Test complete...\n");
1277}
1278
Florin Corase69f4952017-03-07 10:06:24 -08001279static void
1280vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t *
1281 mp)
1282{
Florin Corasb384b542018-01-15 01:08:33 -08001283 echo_main_t *em = &echo_main;
Florin Corasf03a59a2017-06-09 21:07:32 -07001284 session_t *session;
Florin Coras6792ec02017-03-13 03:49:51 -07001285
Florin Corasf03a59a2017-06-09 21:07:32 -07001286 if (mp->retval)
1287 {
1288 clib_warning ("vpp complained about disconnect: %d",
1289 ntohl (mp->retval));
1290 }
1291
Florin Corasb384b542018-01-15 01:08:33 -08001292 em->state = STATE_START;
1293 session = pool_elt_at_index (em->sessions, em->connected_session_index);
Florin Corasf03a59a2017-06-09 21:07:32 -07001294 if (session)
Florin Corasb384b542018-01-15 01:08:33 -08001295 session_print_stats (em, session);
Florin Corase69f4952017-03-07 10:06:24 -08001296}
1297
Florin Corase3e2f072018-03-04 07:24:30 -08001298static void
1299 vl_api_application_tls_cert_add_reply_t_handler
1300 (vl_api_application_tls_cert_add_reply_t * mp)
1301{
1302 if (mp->retval)
1303 clib_warning ("failed to add tls cert");
1304}
1305
1306static void
1307 vl_api_application_tls_key_add_reply_t_handler
1308 (vl_api_application_tls_key_add_reply_t * mp)
1309{
1310 if (mp->retval)
1311 clib_warning ("failed to add tls key");
1312}
1313
1314#define foreach_tcp_echo_msg \
1315_(BIND_URI_REPLY, bind_uri_reply) \
1316_(UNBIND_URI_REPLY, unbind_uri_reply) \
1317_(ACCEPT_SESSION, accept_session) \
1318_(CONNECT_SESSION_REPLY, connect_session_reply) \
1319_(DISCONNECT_SESSION, disconnect_session) \
1320_(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \
1321_(RESET_SESSION, reset_session) \
1322_(APPLICATION_ATTACH_REPLY, application_attach_reply) \
1323_(APPLICATION_DETACH_REPLY, application_detach_reply) \
1324_(MAP_ANOTHER_SEGMENT, map_another_segment) \
1325_(APPLICATION_TLS_CERT_ADD_REPLY, application_tls_cert_add_reply) \
1326_(APPLICATION_TLS_KEY_ADD_REPLY, application_tls_key_add_reply) \
Dave Barach68b0fb02017-02-28 15:15:56 -05001327
1328void
Florin Corasb384b542018-01-15 01:08:33 -08001329tcp_echo_api_hookup (echo_main_t * em)
Dave Barach68b0fb02017-02-28 15:15:56 -05001330{
1331#define _(N,n) \
1332 vl_msg_api_set_handlers(VL_API_##N, #n, \
1333 vl_api_##n##_t_handler, \
1334 vl_noop_handler, \
1335 vl_api_##n##_t_endian, \
1336 vl_api_##n##_t_print, \
1337 sizeof(vl_api_##n##_t), 1);
Florin Corasb384b542018-01-15 01:08:33 -08001338 foreach_tcp_echo_msg;
Dave Barach68b0fb02017-02-28 15:15:56 -05001339#undef _
1340}
1341
1342int
1343main (int argc, char **argv)
1344{
Florin Corasb384b542018-01-15 01:08:33 -08001345 int i_am_master = 1, drop_packets = 0, test_return_packets = 0;
1346 echo_main_t *em = &echo_main;
Dave Barach68b0fb02017-02-28 15:15:56 -05001347 unformat_input_t _argv, *a = &_argv;
1348 u8 *chroot_prefix;
Florin Corase69f4952017-03-07 10:06:24 -08001349 u8 *heap, *uri = 0;
1350 u8 *bind_uri = (u8 *) "tcp://0.0.0.0/1234";
1351 u8 *connect_uri = (u8 *) "tcp://6.0.1.2/1234";
Florin Coras6cf30ad2017-04-04 23:08:23 -07001352 u64 bytes_to_send = 64 << 10, mbytes;
Florin Corasb384b542018-01-15 01:08:33 -08001353 char *app_name;
Dave Barach68b0fb02017-02-28 15:15:56 -05001354 u32 tmp;
1355 mheap_t *h;
Dave Barach68b0fb02017-02-28 15:15:56 -05001356
1357 clib_mem_init (0, 256 << 20);
1358
1359 heap = clib_mem_get_per_cpu_heap ();
1360 h = mheap_header (heap);
1361
1362 /* make the main heap thread-safe */
1363 h->flags |= MHEAP_FLAG_THREAD_SAFE;
1364
Florin Corasb384b542018-01-15 01:08:33 -08001365 vec_validate (em->rx_buf, 128 << 10);
Dave Barach68b0fb02017-02-28 15:15:56 -05001366
Florin Corasb384b542018-01-15 01:08:33 -08001367 em->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
Dave Barach68b0fb02017-02-28 15:15:56 -05001368
Florin Corasb384b542018-01-15 01:08:33 -08001369 em->my_pid = getpid ();
1370 em->configured_segment_size = 1 << 20;
1371 em->socket_name = 0;
1372 em->use_sock_api = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -05001373
Florin Corasb384b542018-01-15 01:08:33 -08001374 clib_time_init (&em->clib_time);
1375 init_error_string_table (em);
Florin Corasa332c462018-01-31 06:52:17 -08001376 svm_fifo_segment_main_init (0x200000000ULL, 20);
Dave Barach68b0fb02017-02-28 15:15:56 -05001377 unformat_init_command_line (a, argv);
1378
1379 while (unformat_check_input (a) != UNFORMAT_END_OF_INPUT)
1380 {
1381 if (unformat (a, "chroot prefix %s", &chroot_prefix))
Florin Corase04c2992017-03-01 08:17:34 -08001382 {
1383 vl_set_memory_root_path ((char *) chroot_prefix);
1384 }
Florin Corase69f4952017-03-07 10:06:24 -08001385 else if (unformat (a, "uri %s", &uri))
Florin Corase04c2992017-03-01 08:17:34 -08001386 ;
Dave Barach68b0fb02017-02-28 15:15:56 -05001387 else if (unformat (a, "segment-size %dM", &tmp))
Florin Corasb384b542018-01-15 01:08:33 -08001388 em->configured_segment_size = tmp << 20;
Dave Barach68b0fb02017-02-28 15:15:56 -05001389 else if (unformat (a, "segment-size %dG", &tmp))
Florin Corasb384b542018-01-15 01:08:33 -08001390 em->configured_segment_size = tmp << 30;
Dave Barach68b0fb02017-02-28 15:15:56 -05001391 else if (unformat (a, "master"))
Florin Corase04c2992017-03-01 08:17:34 -08001392 i_am_master = 1;
Dave Barach68b0fb02017-02-28 15:15:56 -05001393 else if (unformat (a, "slave"))
Florin Corase04c2992017-03-01 08:17:34 -08001394 i_am_master = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001395 else if (unformat (a, "drop"))
Florin Corase04c2992017-03-01 08:17:34 -08001396 drop_packets = 1;
1397 else if (unformat (a, "test"))
1398 test_return_packets = 1;
Florin Coras6cf30ad2017-04-04 23:08:23 -07001399 else if (unformat (a, "mbytes %lld", &mbytes))
Florin Coras6792ec02017-03-13 03:49:51 -07001400 {
1401 bytes_to_send = mbytes << 20;
1402 }
Florin Coras6cf30ad2017-04-04 23:08:23 -07001403 else if (unformat (a, "gbytes %lld", &mbytes))
1404 {
1405 bytes_to_send = mbytes << 30;
1406 }
Florin Corasb384b542018-01-15 01:08:33 -08001407 else if (unformat (a, "socket-name %s", &em->socket_name))
Florin Coras90a63982017-12-19 04:50:01 -08001408 ;
1409 else if (unformat (a, "use-svm-api"))
Florin Corasb384b542018-01-15 01:08:33 -08001410 em->use_sock_api = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001411 else
Florin Corase04c2992017-03-01 08:17:34 -08001412 {
1413 fformat (stderr, "%s: usage [master|slave]\n");
1414 exit (1);
1415 }
Dave Barach68b0fb02017-02-28 15:15:56 -05001416 }
1417
Florin Corasb384b542018-01-15 01:08:33 -08001418 if (!em->socket_name)
1419 em->socket_name = format (0, "%s%c", API_SOCKET_FILE, 0);
Florin Coras90a63982017-12-19 04:50:01 -08001420
Florin Corase69f4952017-03-07 10:06:24 -08001421 if (uri)
1422 {
Florin Corasb384b542018-01-15 01:08:33 -08001423 em->uri = format (0, "%s%c", uri, 0);
1424 em->connect_uri = format (0, "%s%c", uri, 0);
Florin Corase69f4952017-03-07 10:06:24 -08001425 }
1426 else
1427 {
Florin Corasb384b542018-01-15 01:08:33 -08001428 em->uri = format (0, "%s%c", bind_uri, 0);
1429 em->connect_uri = format (0, "%s%c", connect_uri, 0);
Florin Corase69f4952017-03-07 10:06:24 -08001430 }
1431
Florin Corasb384b542018-01-15 01:08:33 -08001432 em->i_am_master = i_am_master;
1433 em->segment_main = &svm_fifo_segment_main;
1434 em->drop_packets = drop_packets;
1435 em->test_return_packets = test_return_packets;
1436 em->bytes_to_send = bytes_to_send;
1437 em->time_to_stop = 0;
Dave Barach68b0fb02017-02-28 15:15:56 -05001438
Florin Corase04c2992017-03-01 08:17:34 -08001439 setup_signal_handlers ();
Florin Corasb384b542018-01-15 01:08:33 -08001440 tcp_echo_api_hookup (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001441
Florin Corasb384b542018-01-15 01:08:33 -08001442 app_name = i_am_master ? "tcp_echo_server" : "tcp_echo_client";
1443 if (connect_to_vpp (app_name) < 0)
Dave Barach68b0fb02017-02-28 15:15:56 -05001444 {
1445 svm_region_exit ();
1446 fformat (stderr, "Couldn't connect to vpe, exiting...\n");
1447 exit (1);
1448 }
1449
1450 if (i_am_master == 0)
Florin Corasb384b542018-01-15 01:08:33 -08001451 client_run (em);
Florin Coras90a63982017-12-19 04:50:01 -08001452 else
Florin Corasb384b542018-01-15 01:08:33 -08001453 server_run (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001454
Florin Corasb384b542018-01-15 01:08:33 -08001455 disconnect_from_vpp (em);
Dave Barach68b0fb02017-02-28 15:15:56 -05001456 exit (0);
1457}
Florin Corase04c2992017-03-01 08:17:34 -08001458
1459/*
1460 * fd.io coding-style-patch-verification: ON
1461 *
1462 * Local Variables:
1463 * eval: (c-set-style "gnu")
1464 * End:
1465 */