Line data Source code
1 : /*
2 : * memif VAT support
3 : *
4 : * Copyright (c) 2017 Cisco and/or its affiliates.
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at:
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #include <inttypes.h>
19 :
20 : #include <vat/vat.h>
21 : #include <vlibapi/api.h>
22 : #include <vlibmemory/api.h>
23 :
24 : #include <vppinfra/error.h>
25 : #include <vnet/ip/ip.h>
26 : #include <memif/memif.h>
27 : #include <memif/private.h>
28 :
29 : #define __plugin_msg_base memif_test_main.msg_id_base
30 : #include <vlibapi/vat_helper_macros.h>
31 :
32 : /* declare message IDs */
33 : #include <vnet/format_fns.h>
34 : #include <memif/memif.api_enum.h>
35 : #include <memif/memif.api_types.h>
36 : #include <vlibmemory/vlib.api_types.h>
37 :
38 : typedef struct
39 : {
40 : /* API message ID base */
41 : u16 msg_id_base;
42 : u32 ping_id;
43 : vat_main_t *vat_main;
44 : } memif_test_main_t;
45 :
46 : memif_test_main_t memif_test_main;
47 :
48 : static uword
49 0 : unformat_memif_queues (unformat_input_t * input, va_list * args)
50 : {
51 0 : u32 *rx_queues = va_arg (*args, u32 *);
52 0 : u32 *tx_queues = va_arg (*args, u32 *);
53 :
54 0 : if (unformat (input, "rx-queues %u", rx_queues))
55 : ;
56 0 : if (unformat (input, "tx-queues %u", tx_queues))
57 : ;
58 :
59 0 : return 1;
60 : }
61 :
62 : /* memif_socket_filename_add_del API */
63 : static int
64 0 : api_memif_socket_filename_add_del (vat_main_t * vam)
65 : {
66 0 : unformat_input_t *i = vam->input;
67 : vl_api_memif_socket_filename_add_del_t *mp;
68 : u8 is_add;
69 : u32 socket_id;
70 : u8 *socket_filename;
71 : int ret;
72 :
73 0 : is_add = 1;
74 0 : socket_id = ~0;
75 0 : socket_filename = 0;
76 :
77 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
78 : {
79 0 : if (unformat (i, "id %u", &socket_id))
80 : ;
81 0 : else if (unformat (i, "filename %s", &socket_filename))
82 : ;
83 0 : else if (unformat (i, "del"))
84 0 : is_add = 0;
85 0 : else if (unformat (i, "add"))
86 0 : is_add = 1;
87 : else
88 : {
89 0 : vec_free (socket_filename);
90 0 : clib_warning ("unknown input `%U'", format_unformat_error, i);
91 0 : return -99;
92 : }
93 : }
94 :
95 0 : if (socket_id == 0 || socket_id == ~0)
96 : {
97 0 : vec_free (socket_filename);
98 0 : errmsg ("Invalid socket id");
99 0 : return -99;
100 : }
101 :
102 0 : if (is_add && (!socket_filename || *socket_filename == 0))
103 : {
104 0 : vec_free (socket_filename);
105 0 : errmsg ("Invalid socket filename");
106 0 : return -99;
107 : }
108 :
109 0 : M2 (MEMIF_SOCKET_FILENAME_ADD_DEL, mp, strlen ((char *) socket_filename));
110 :
111 0 : mp->is_add = is_add;
112 0 : mp->socket_id = htonl (socket_id);
113 0 : char *p = (char *) &mp->socket_filename;
114 0 : p += vl_api_vec_to_api_string (socket_filename, (vl_api_string_t *) p);
115 :
116 0 : vec_free (socket_filename);
117 :
118 0 : S (mp);
119 0 : W (ret);
120 :
121 0 : return ret;
122 : }
123 :
124 : /* memif_socket_filename_add_del API */
125 : static int
126 0 : api_memif_socket_filename_add_del_v2 (vat_main_t *vam)
127 : {
128 0 : unformat_input_t *i = vam->input;
129 : vl_api_memif_socket_filename_add_del_v2_t *mp;
130 : u8 is_add;
131 : u32 socket_id;
132 : u8 *socket_filename;
133 : int ret;
134 :
135 0 : is_add = 1;
136 0 : socket_id = ~0;
137 0 : socket_filename = 0;
138 :
139 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
140 : {
141 0 : if (unformat (i, "id %u", &socket_id))
142 : ;
143 0 : else if (unformat (i, "filename %s", &socket_filename))
144 : ;
145 0 : else if (unformat (i, "del"))
146 0 : is_add = 0;
147 0 : else if (unformat (i, "add"))
148 0 : is_add = 1;
149 : else
150 : {
151 0 : vec_free (socket_filename);
152 0 : clib_warning ("unknown input `%U'", format_unformat_error, i);
153 0 : return -99;
154 : }
155 : }
156 :
157 0 : if (socket_id == 0 || socket_id == ~0)
158 : {
159 0 : vec_free (socket_filename);
160 0 : errmsg ("Invalid socket id");
161 0 : return -99;
162 : }
163 :
164 0 : if (is_add && (!socket_filename || *socket_filename == 0))
165 : {
166 0 : vec_free (socket_filename);
167 0 : errmsg ("Invalid socket filename");
168 0 : return -99;
169 : }
170 :
171 0 : M2 (MEMIF_SOCKET_FILENAME_ADD_DEL_V2, mp, strlen ((char *) socket_filename));
172 :
173 0 : mp->is_add = is_add;
174 0 : mp->socket_id = htonl (socket_id);
175 0 : char *p = (char *) &mp->socket_filename;
176 0 : p += vl_api_vec_to_api_string (socket_filename, (vl_api_string_t *) p);
177 :
178 0 : vec_free (socket_filename);
179 :
180 0 : S (mp);
181 0 : W (ret);
182 :
183 0 : return ret;
184 : }
185 :
186 : /* memif socket-create reply handler */
187 : static void
188 0 : vl_api_memif_socket_filename_add_del_v2_reply_t_handler (
189 : vl_api_memif_socket_filename_add_del_v2_reply_t *mp)
190 : {
191 0 : vat_main_t *vam = memif_test_main.vat_main;
192 0 : i32 retval = ntohl (mp->retval);
193 :
194 0 : if (retval == 0)
195 : {
196 0 : fformat (vam->ofp, "created memif socket with socket_id %d\n",
197 : ntohl (mp->socket_id));
198 : }
199 :
200 0 : vam->retval = retval;
201 0 : vam->result_ready = 1;
202 0 : }
203 :
204 : /* memif_socket_filename_add_del reply handler */
205 : #define VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_REPLY_T_HANDLER
206 0 : static void vl_api_memif_socket_filename_add_del_reply_t_handler
207 : (vl_api_memif_socket_filename_add_del_reply_t * mp)
208 : {
209 0 : vat_main_t *vam = memif_test_main.vat_main;
210 0 : i32 retval = ntohl (mp->retval);
211 :
212 0 : vam->retval = retval;
213 0 : vam->result_ready = 1;
214 0 : vam->regenerate_interface_table = 1;
215 0 : }
216 :
217 : /* memif-create API */
218 : static int
219 0 : api_memif_create (vat_main_t * vam)
220 : {
221 0 : unformat_input_t *i = vam->input;
222 : vl_api_memif_create_t *mp;
223 0 : u32 id = 0;
224 0 : u32 socket_id = 0;
225 0 : u8 *secret = 0;
226 0 : u8 role = 1;
227 0 : u32 ring_size = 0;
228 0 : u32 buffer_size = 0;
229 0 : u8 hw_addr[6] = { 0 };
230 0 : u32 rx_queues = MEMIF_DEFAULT_RX_QUEUES;
231 0 : u32 tx_queues = MEMIF_DEFAULT_TX_QUEUES;
232 : int ret;
233 0 : u8 mode = MEMIF_INTERFACE_MODE_ETHERNET;
234 :
235 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
236 : {
237 0 : if (unformat (i, "id %u", &id))
238 : ;
239 0 : else if (unformat (i, "socket-id %u", &socket_id))
240 : ;
241 0 : else if (unformat (i, "secret %s", &secret))
242 : ;
243 0 : else if (unformat (i, "ring_size %u", &ring_size))
244 : ;
245 0 : else if (unformat (i, "buffer_size %u", &buffer_size))
246 : ;
247 0 : else if (unformat (i, "master"))
248 0 : role = 0;
249 0 : else if (unformat (i, "slave %U",
250 : unformat_memif_queues, &rx_queues, &tx_queues))
251 0 : role = 1;
252 0 : else if (unformat (i, "mode ip"))
253 0 : mode = MEMIF_INTERFACE_MODE_IP;
254 0 : else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
255 : ;
256 : else
257 : {
258 0 : clib_warning ("unknown input '%U'", format_unformat_error, i);
259 0 : return -99;
260 : }
261 : }
262 :
263 0 : if (socket_id == ~0)
264 : {
265 0 : errmsg ("invalid socket-id\n");
266 0 : return -99;
267 : }
268 :
269 0 : if (!is_pow2 (ring_size))
270 : {
271 0 : errmsg ("ring size must be power of 2\n");
272 0 : return -99;
273 : }
274 :
275 0 : if (rx_queues > 255 || rx_queues < 1)
276 : {
277 0 : errmsg ("rx queue must be between 1 - 255\n");
278 0 : return -99;
279 : }
280 :
281 0 : if (tx_queues > 255 || tx_queues < 1)
282 : {
283 0 : errmsg ("tx queue must be between 1 - 255\n");
284 0 : return -99;
285 : }
286 :
287 0 : M2 (MEMIF_CREATE, mp, strlen ((char *) secret));
288 :
289 0 : mp->mode = mode;
290 0 : mp->id = clib_host_to_net_u32 (id);
291 0 : mp->role = role;
292 0 : mp->ring_size = clib_host_to_net_u32 (ring_size);
293 0 : mp->buffer_size = clib_host_to_net_u16 (buffer_size & 0xffff);
294 0 : mp->socket_id = clib_host_to_net_u32 (socket_id);
295 0 : if (secret != 0)
296 : {
297 0 : char *p = (char *) &mp->secret;
298 0 : p += vl_api_vec_to_api_string (secret, (vl_api_string_t *) p);
299 0 : vec_free (secret);
300 : }
301 0 : memcpy (mp->hw_addr, hw_addr, 6);
302 0 : mp->rx_queues = rx_queues;
303 0 : mp->tx_queues = tx_queues;
304 :
305 0 : S (mp);
306 0 : W (ret);
307 0 : return ret;
308 : }
309 :
310 : /* memif-create reply handler */
311 0 : static void vl_api_memif_create_reply_t_handler
312 : (vl_api_memif_create_reply_t * mp)
313 : {
314 0 : vat_main_t *vam = memif_test_main.vat_main;
315 0 : i32 retval = ntohl (mp->retval);
316 :
317 0 : if (retval == 0)
318 : {
319 0 : fformat (vam->ofp, "created memif with sw_if_index %d\n",
320 : ntohl (mp->sw_if_index));
321 : }
322 :
323 0 : vam->retval = retval;
324 0 : vam->result_ready = 1;
325 0 : vam->regenerate_interface_table = 1;
326 0 : }
327 :
328 : /* memif-create_v2 API */
329 : static int
330 0 : api_memif_create_v2 (vat_main_t *vam)
331 : {
332 0 : unformat_input_t *i = vam->input;
333 : vl_api_memif_create_v2_t *mp;
334 0 : u32 id = 0;
335 0 : u32 socket_id = 0;
336 0 : u8 *secret = 0;
337 0 : u8 role = 1;
338 0 : u32 ring_size = 0;
339 0 : u8 use_dma = 0;
340 0 : u32 buffer_size = 0;
341 0 : u8 hw_addr[6] = { 0 };
342 0 : u32 rx_queues = MEMIF_DEFAULT_RX_QUEUES;
343 0 : u32 tx_queues = MEMIF_DEFAULT_TX_QUEUES;
344 : int ret;
345 0 : u8 mode = MEMIF_INTERFACE_MODE_ETHERNET;
346 :
347 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
348 : {
349 0 : if (unformat (i, "id %u", &id))
350 : ;
351 0 : else if (unformat (i, "socket-id %u", &socket_id))
352 : ;
353 0 : else if (unformat (i, "secret %s", &secret))
354 : ;
355 0 : else if (unformat (i, "ring_size %u", &ring_size))
356 : ;
357 0 : else if (unformat (i, "buffer_size %u", &buffer_size))
358 : ;
359 0 : else if (unformat (i, "master"))
360 0 : role = 0;
361 0 : else if (unformat (i, "use_dma %u", &use_dma))
362 : ;
363 0 : else if (unformat (i, "slave %U", unformat_memif_queues, &rx_queues,
364 : &tx_queues))
365 0 : role = 1;
366 0 : else if (unformat (i, "mode ip"))
367 0 : mode = MEMIF_INTERFACE_MODE_IP;
368 0 : else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
369 : ;
370 : else
371 : {
372 0 : clib_warning ("unknown input '%U'", format_unformat_error, i);
373 0 : return -99;
374 : }
375 : }
376 :
377 0 : if (socket_id == ~0)
378 : {
379 0 : errmsg ("invalid socket-id\n");
380 0 : return -99;
381 : }
382 :
383 0 : if (!is_pow2 (ring_size))
384 : {
385 0 : errmsg ("ring size must be power of 2\n");
386 0 : return -99;
387 : }
388 :
389 0 : if (rx_queues > 255 || rx_queues < 1)
390 : {
391 0 : errmsg ("rx queue must be between 1 - 255\n");
392 0 : return -99;
393 : }
394 :
395 0 : if (tx_queues > 255 || tx_queues < 1)
396 : {
397 0 : errmsg ("tx queue must be between 1 - 255\n");
398 0 : return -99;
399 : }
400 :
401 0 : M2 (MEMIF_CREATE, mp, strlen ((char *) secret));
402 :
403 0 : mp->mode = mode;
404 0 : mp->id = clib_host_to_net_u32 (id);
405 0 : mp->role = role;
406 0 : mp->use_dma = use_dma;
407 0 : mp->ring_size = clib_host_to_net_u32 (ring_size);
408 0 : mp->buffer_size = clib_host_to_net_u16 (buffer_size & 0xffff);
409 0 : mp->socket_id = clib_host_to_net_u32 (socket_id);
410 :
411 0 : char *p = (char *) &mp->secret;
412 0 : p += vl_api_vec_to_api_string (secret, (vl_api_string_t *) p);
413 0 : vec_free (secret);
414 :
415 0 : memcpy (mp->hw_addr, hw_addr, 6);
416 0 : mp->rx_queues = rx_queues;
417 0 : mp->tx_queues = tx_queues;
418 :
419 0 : S (mp);
420 0 : W (ret);
421 0 : return ret;
422 : }
423 :
424 : /* memif-create_v2 reply handler */
425 : static void
426 0 : vl_api_memif_create_v2_reply_t_handler (vl_api_memif_create_reply_t *mp)
427 : {
428 0 : vat_main_t *vam = memif_test_main.vat_main;
429 0 : i32 retval = ntohl (mp->retval);
430 :
431 0 : if (retval == 0)
432 : {
433 0 : fformat (vam->ofp, "created memif with sw_if_index %d\n",
434 : ntohl (mp->sw_if_index));
435 : }
436 :
437 0 : vam->retval = retval;
438 0 : vam->result_ready = 1;
439 0 : vam->regenerate_interface_table = 1;
440 0 : }
441 :
442 : /* memif-delete API */
443 : static int
444 0 : api_memif_delete (vat_main_t * vam)
445 : {
446 0 : unformat_input_t *i = vam->input;
447 : vl_api_memif_delete_t *mp;
448 0 : u32 sw_if_index = 0;
449 0 : u8 index_defined = 0;
450 : int ret;
451 :
452 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
453 : {
454 0 : if (unformat (i, "sw_if_index %u", &sw_if_index))
455 0 : index_defined = 1;
456 : else
457 : {
458 0 : clib_warning ("unknown input '%U'", format_unformat_error, i);
459 0 : return -99;
460 : }
461 : }
462 :
463 0 : if (!index_defined)
464 : {
465 0 : errmsg ("missing sw_if_index\n");
466 0 : return -99;
467 : }
468 :
469 0 : M (MEMIF_DELETE, mp);
470 :
471 0 : mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
472 :
473 0 : S (mp);
474 0 : W (ret);
475 0 : return ret;
476 : }
477 :
478 : /* memif-dump API */
479 : static int
480 0 : api_memif_dump (vat_main_t * vam)
481 : {
482 0 : memif_test_main_t *mm = &memif_test_main;
483 : vl_api_memif_dump_t *mp;
484 : vl_api_control_ping_t *mp_ping;
485 : int ret;
486 :
487 0 : if (vam->json_output)
488 : {
489 0 : clib_warning ("JSON output not supported for memif_dump");
490 0 : return -99;
491 : }
492 :
493 0 : M (MEMIF_DUMP, mp);
494 0 : S (mp);
495 :
496 : /* Use a control ping for synchronization */
497 0 : if (!mm->ping_id)
498 0 : mm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC));
499 0 : mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
500 0 : mp_ping->_vl_msg_id = htons (mm->ping_id);
501 0 : mp_ping->client_index = vam->my_client_index;
502 :
503 0 : fformat (vam->ofp, "Sending ping id=%d\n", mm->ping_id);
504 :
505 0 : vam->result_ready = 0;
506 0 : S (mp_ping);
507 :
508 0 : W (ret);
509 0 : return ret;
510 : }
511 :
512 : /* memif-details message handler */
513 : static void
514 0 : vl_api_memif_details_t_handler (vl_api_memif_details_t * mp)
515 : {
516 0 : vat_main_t *vam = memif_test_main.vat_main;
517 :
518 0 : fformat (vam->ofp, "%s: sw_if_index %u mac %U\n"
519 : " id %u socket-id %u role %s\n"
520 : " ring_size %u buffer_size %u\n"
521 : " state %s link %s\n",
522 0 : mp->if_name, ntohl (mp->sw_if_index), format_ethernet_address,
523 0 : mp->hw_addr, clib_net_to_host_u32 (mp->id),
524 : clib_net_to_host_u32 (mp->socket_id),
525 0 : mp->role ? "slave" : "master",
526 0 : ntohl (mp->ring_size), ntohs (mp->buffer_size),
527 0 : (mp->flags & IF_STATUS_API_FLAG_ADMIN_UP) ? "up" : "down",
528 0 : (mp->flags & IF_STATUS_API_FLAG_LINK_UP) ? "up" : "down");
529 0 : }
530 :
531 : /* memif_socket_filename_dump API */
532 : static int
533 0 : api_memif_socket_filename_dump (vat_main_t * vam)
534 : {
535 0 : memif_test_main_t *mm = &memif_test_main;
536 : vl_api_memif_socket_filename_dump_t *mp;
537 : vl_api_control_ping_t *mp_ping;
538 : int ret;
539 :
540 0 : if (vam->json_output)
541 : {
542 0 : clib_warning
543 : ("JSON output not supported for memif_socket_filename_dump");
544 0 : return -99;
545 : }
546 :
547 0 : M (MEMIF_SOCKET_FILENAME_DUMP, mp);
548 0 : S (mp);
549 :
550 : /* Use a control ping for synchronization */
551 0 : if (!mm->ping_id)
552 0 : mm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC));
553 0 : mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
554 0 : mp_ping->_vl_msg_id = htons (mm->ping_id);
555 0 : mp_ping->client_index = vam->my_client_index;
556 :
557 0 : fformat (vam->ofp, "Sending ping id=%d\n", mm->ping_id);
558 :
559 0 : vam->result_ready = 0;
560 0 : S (mp_ping);
561 :
562 0 : W (ret);
563 0 : return ret;
564 : }
565 :
566 : /* memif_socket_format_details message handler */
567 0 : static void vl_api_memif_socket_filename_details_t_handler
568 : (vl_api_memif_socket_filename_details_t * mp)
569 : {
570 0 : vat_main_t *vam = memif_test_main.vat_main;
571 :
572 0 : fformat (vam->ofp,
573 : "id %u : filename %s\n",
574 0 : ntohl (mp->socket_id), mp->socket_filename);
575 0 : }
576 :
577 : #include <memif/memif.api_test.c>
578 :
579 : /*
580 : * fd.io coding-style-patch-verification: ON
581 : *
582 : * Local Variables:
583 : * eval: (c-set-style "gnu")
584 : * End:
585 : */
|