Line data Source code
1 : /*
2 : *------------------------------------------------------------------
3 : * memif_api.c - memif api
4 : *
5 : * Copyright (c) 2017 Cisco and/or its affiliates.
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at:
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : *------------------------------------------------------------------
18 : */
19 :
20 : #include <vlib/vlib.h>
21 : #include <vnet/ethernet/ethernet.h>
22 : #include <vlib/unix/unix.h>
23 : #include <memif/memif.h>
24 : #include <memif/private.h>
25 :
26 : #include <vlibapi/api.h>
27 : #include <vlibmemory/api.h>
28 :
29 : #include <vnet/ip/ip_types_api.h>
30 : #include <vnet/ethernet/ethernet_types_api.h>
31 :
32 : /* define message IDs */
33 : #include <vnet/format_fns.h>
34 : #include <memif/memif.api_enum.h>
35 : #include <memif/memif.api_types.h>
36 :
37 : #define REPLY_MSG_ID_BASE mm->msg_id_base
38 : #include <vlibapi/api_helper_macros.h>
39 :
40 : /**
41 : * @brief Message handler for memif_socket_filename_add_del API.
42 : * @param mp the vl_api_memif_socket_filename_add_del_t API message
43 : */
44 : void
45 24 : vl_api_memif_socket_filename_add_del_t_handler
46 : (vl_api_memif_socket_filename_add_del_t * mp)
47 : {
48 24 : memif_main_t *mm = &memif_main;
49 : u8 is_add;
50 : u32 socket_id;
51 : vl_api_memif_socket_filename_add_del_reply_t *rmp;
52 : int rv;
53 :
54 : /* is_add */
55 24 : is_add = mp->is_add;
56 :
57 : /* socket_id */
58 24 : socket_id = clib_net_to_host_u32 (mp->socket_id);
59 24 : if (socket_id == 0 || socket_id == ~0)
60 : {
61 0 : rv = VNET_API_ERROR_INVALID_ARGUMENT;
62 0 : goto reply;
63 : }
64 :
65 : /* socket filename */
66 24 : mp->socket_filename[ARRAY_LEN (mp->socket_filename) - 1] = 0;
67 :
68 24 : rv = vnet_get_api_error_and_free (memif_socket_filename_add_del (
69 24 : is_add, socket_id, (char *) mp->socket_filename));
70 :
71 24 : reply:
72 24 : REPLY_MACRO (VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_REPLY);
73 : }
74 :
75 : /**
76 : * @brief Message handler for memif_socket_filename_add_del API.
77 : * @param mp the vl_api_memif_socket_filename_add_del_t API message
78 : */
79 : void
80 0 : vl_api_memif_socket_filename_add_del_v2_t_handler (
81 : vl_api_memif_socket_filename_add_del_v2_t *mp)
82 : {
83 : vl_api_memif_socket_filename_add_del_v2_reply_t *rmp;
84 0 : memif_main_t *mm = &memif_main;
85 0 : char *socket_filename = 0;
86 : u32 socket_id;
87 : int rv;
88 :
89 : /* socket_id */
90 0 : socket_id = clib_net_to_host_u32 (mp->socket_id);
91 0 : if (socket_id == 0)
92 : {
93 0 : rv = VNET_API_ERROR_INVALID_ARGUMENT;
94 0 : goto reply;
95 : }
96 :
97 : /* socket filename */
98 0 : socket_filename = vl_api_from_api_to_new_c_string (&mp->socket_filename);
99 0 : if (mp->is_add && socket_id == (u32) ~0)
100 0 : socket_id = memif_get_unused_socket_id ();
101 :
102 0 : rv = vnet_get_api_error_and_free (
103 0 : memif_socket_filename_add_del (mp->is_add, socket_id, socket_filename));
104 :
105 0 : vec_free (socket_filename);
106 :
107 0 : reply:
108 0 : REPLY_MACRO2 (VL_API_MEMIF_SOCKET_FILENAME_ADD_DEL_V2_REPLY,
109 : ({ rmp->socket_id = htonl (socket_id); }));
110 : }
111 :
112 : /**
113 : * @brief Message handler for memif_create API.
114 : * @param mp vl_api_memif_create_t * mp the api message
115 : */
116 : void
117 22 : vl_api_memif_create_t_handler (vl_api_memif_create_t * mp)
118 : {
119 22 : memif_main_t *mm = &memif_main;
120 22 : vlib_main_t *vm = vlib_get_main ();
121 : vl_api_memif_create_reply_t *rmp;
122 22 : memif_create_if_args_t args = { 0 };
123 22 : u32 ring_size = MEMIF_DEFAULT_RING_SIZE;
124 : static const u8 empty_hw_addr[6];
125 22 : int rv = 0;
126 : mac_address_t mac;
127 :
128 : /* id */
129 22 : args.id = clib_net_to_host_u32 (mp->id);
130 :
131 : /* socket-id */
132 22 : args.socket_id = clib_net_to_host_u32 (mp->socket_id);
133 :
134 : /* secret */
135 22 : mp->secret[ARRAY_LEN (mp->secret) - 1] = 0;
136 22 : if (strlen ((char *) mp->secret) > 0)
137 : {
138 6 : vec_validate (args.secret, strlen ((char *) mp->secret));
139 6 : strncpy ((char *) args.secret, (char *) mp->secret,
140 6 : vec_len (args.secret));
141 : }
142 :
143 : /* role */
144 22 : args.is_master = (ntohl (mp->role) == MEMIF_ROLE_API_MASTER);
145 :
146 : /* mode */
147 22 : args.mode = ntohl (mp->mode);
148 :
149 22 : args.is_zero_copy = mp->no_zero_copy ? 0 : 1;
150 :
151 : /* rx/tx queues */
152 22 : if (args.is_master == 0)
153 : {
154 11 : args.rx_queues = MEMIF_DEFAULT_RX_QUEUES;
155 11 : args.tx_queues = MEMIF_DEFAULT_TX_QUEUES;
156 11 : if (mp->rx_queues)
157 : {
158 0 : args.rx_queues = mp->rx_queues;
159 : }
160 11 : if (mp->tx_queues)
161 : {
162 0 : args.tx_queues = mp->tx_queues;
163 : }
164 : }
165 :
166 : /* ring size */
167 22 : if (mp->ring_size)
168 : {
169 6 : ring_size = ntohl (mp->ring_size);
170 : }
171 22 : if (!is_pow2 (ring_size))
172 : {
173 0 : rv = VNET_API_ERROR_INVALID_ARGUMENT;
174 0 : goto reply;
175 : }
176 22 : args.log2_ring_size = min_log2 (ring_size);
177 :
178 : /* buffer size */
179 22 : args.buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
180 22 : if (mp->buffer_size)
181 : {
182 6 : args.buffer_size = ntohs (mp->buffer_size);
183 : }
184 :
185 : /* MAC address */
186 22 : mac_address_decode (mp->hw_addr, &mac);
187 22 : if (memcmp (&mac, empty_hw_addr, 6) != 0)
188 : {
189 0 : memcpy (args.hw_addr, &mac, 6);
190 0 : args.hw_addr_set = 1;
191 : }
192 :
193 22 : rv = vnet_get_api_error_and_free (memif_create_if (vm, &args));
194 :
195 22 : vec_free (args.secret);
196 :
197 22 : reply:
198 : /* *INDENT-OFF* */
199 22 : REPLY_MACRO2 (VL_API_MEMIF_CREATE_REPLY,
200 : ({
201 : rmp->sw_if_index = htonl (args.sw_if_index);
202 : }));
203 : /* *INDENT-ON* */
204 : }
205 :
206 : /**
207 : * @brief Message handler for memif_create_v2 API.
208 : * @param mp vl_api_memif_create_v2_t * mp the api message
209 : */
210 : void
211 0 : vl_api_memif_create_v2_t_handler (vl_api_memif_create_v2_t *mp)
212 : {
213 0 : memif_main_t *mm = &memif_main;
214 0 : vlib_main_t *vm = vlib_get_main ();
215 : vl_api_memif_create_reply_t *rmp;
216 0 : memif_create_if_args_t args = { 0 };
217 0 : u32 ring_size = MEMIF_DEFAULT_RING_SIZE;
218 : static const u8 empty_hw_addr[6];
219 0 : int rv = 0;
220 : mac_address_t mac;
221 :
222 : /* id */
223 0 : args.id = clib_net_to_host_u32 (mp->id);
224 :
225 : /* socket-id */
226 0 : args.socket_id = clib_net_to_host_u32 (mp->socket_id);
227 :
228 : /* secret */
229 0 : mp->secret[ARRAY_LEN (mp->secret) - 1] = 0;
230 0 : if (strlen ((char *) mp->secret) > 0)
231 : {
232 0 : vec_validate (args.secret, strlen ((char *) mp->secret));
233 0 : strncpy ((char *) args.secret, (char *) mp->secret,
234 0 : vec_len (args.secret));
235 : }
236 :
237 : /* role */
238 0 : args.is_master = (ntohl (mp->role) == MEMIF_ROLE_API_MASTER);
239 :
240 : /* mode */
241 0 : args.mode = ntohl (mp->mode);
242 :
243 0 : args.is_zero_copy = mp->no_zero_copy ? 0 : 1;
244 :
245 0 : args.use_dma = mp->use_dma;
246 :
247 : /* rx/tx queues */
248 0 : if (args.is_master == 0)
249 : {
250 0 : args.rx_queues = MEMIF_DEFAULT_RX_QUEUES;
251 0 : args.tx_queues = MEMIF_DEFAULT_TX_QUEUES;
252 0 : if (mp->rx_queues)
253 : {
254 0 : args.rx_queues = mp->rx_queues;
255 : }
256 0 : if (mp->tx_queues)
257 : {
258 0 : args.tx_queues = mp->tx_queues;
259 : }
260 : }
261 :
262 : /* ring size */
263 0 : if (mp->ring_size)
264 : {
265 0 : ring_size = ntohl (mp->ring_size);
266 : }
267 0 : if (!is_pow2 (ring_size))
268 : {
269 0 : rv = VNET_API_ERROR_INVALID_ARGUMENT;
270 0 : goto reply;
271 : }
272 0 : args.log2_ring_size = min_log2 (ring_size);
273 :
274 : /* buffer size */
275 0 : args.buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
276 0 : if (mp->buffer_size)
277 : {
278 0 : args.buffer_size = ntohs (mp->buffer_size);
279 : }
280 :
281 : /* MAC address */
282 0 : mac_address_decode (mp->hw_addr, &mac);
283 0 : if (memcmp (&mac, empty_hw_addr, 6) != 0)
284 : {
285 0 : memcpy (args.hw_addr, &mac, 6);
286 0 : args.hw_addr_set = 1;
287 : }
288 :
289 0 : rv = vnet_api_error (memif_create_if (vm, &args));
290 :
291 0 : vec_free (args.secret);
292 :
293 0 : reply:
294 0 : REPLY_MACRO2 (VL_API_MEMIF_CREATE_V2_REPLY,
295 : ({ rmp->sw_if_index = htonl (args.sw_if_index); }));
296 : }
297 :
298 : /**
299 : * @brief Message handler for memif_delete API.
300 : * @param mp vl_api_memif_delete_t * mp the api message
301 : */
302 : void
303 16 : vl_api_memif_delete_t_handler (vl_api_memif_delete_t * mp)
304 : {
305 16 : memif_main_t *mm = &memif_main;
306 16 : vlib_main_t *vm = vlib_get_main ();
307 16 : vnet_main_t *vnm = vnet_get_main ();
308 : vl_api_memif_delete_reply_t *rmp;
309 : vnet_hw_interface_t *hi;
310 : memif_if_t *mif;
311 16 : int rv = 0;
312 :
313 : hi =
314 16 : vnet_get_sup_hw_interface_api_visible_or_null (vnm,
315 : ntohl (mp->sw_if_index));
316 :
317 16 : if (hi == NULL || memif_device_class.index != hi->dev_class_index)
318 0 : rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
319 : else
320 : {
321 16 : mif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
322 16 : rv = vnet_get_api_error_and_free (memif_delete_if (vm, mif));
323 : }
324 :
325 16 : REPLY_MACRO (VL_API_MEMIF_DELETE_REPLY);
326 : }
327 :
328 : static void
329 51 : send_memif_details (vl_api_registration_t * reg,
330 : memif_if_t * mif,
331 : vnet_sw_interface_t * swif,
332 : u8 * interface_name, u32 context)
333 : {
334 : vl_api_memif_details_t *mp;
335 51 : vnet_main_t *vnm = vnet_get_main ();
336 51 : memif_main_t *mm = &memif_main;
337 : vnet_hw_interface_t *hwif;
338 : memif_socket_file_t *msf;
339 :
340 51 : hwif = vnet_get_sup_hw_interface (vnm, swif->sw_if_index);
341 :
342 51 : mp = vl_msg_api_alloc (sizeof (*mp));
343 51 : clib_memset (mp, 0, sizeof (*mp));
344 :
345 51 : mp->_vl_msg_id = htons (VL_API_MEMIF_DETAILS + mm->msg_id_base);
346 51 : mp->context = context;
347 :
348 51 : mp->sw_if_index = htonl (swif->sw_if_index);
349 51 : strncpy ((char *) mp->if_name,
350 : (char *) interface_name, ARRAY_LEN (mp->if_name) - 1);
351 :
352 51 : if (hwif->hw_address)
353 : {
354 51 : mac_address_encode ((mac_address_t *) hwif->hw_address, mp->hw_addr);
355 : }
356 :
357 51 : mp->id = clib_host_to_net_u32 (mif->id);
358 :
359 51 : msf = pool_elt_at_index (mm->socket_files, mif->socket_file_index);
360 51 : mp->socket_id = clib_host_to_net_u32 (msf->socket_id);
361 :
362 51 : mp->role =
363 51 : (mif->flags & MEMIF_IF_FLAG_IS_SLAVE) ? MEMIF_ROLE_API_SLAVE :
364 : MEMIF_ROLE_API_MASTER;
365 51 : mp->role = htonl (mp->role);
366 51 : mp->mode = htonl (mif->mode);
367 51 : mp->ring_size = htonl (1 << mif->run.log2_ring_size);
368 51 : mp->buffer_size = htons (mif->run.buffer_size);
369 51 : mp->zero_copy = (mif->flags & MEMIF_IF_FLAG_ZERO_COPY) ? 1 : 0;
370 :
371 51 : mp->flags = 0;
372 51 : mp->flags |= (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
373 51 : IF_STATUS_API_FLAG_ADMIN_UP : 0;
374 51 : mp->flags |= (hwif->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
375 51 : IF_STATUS_API_FLAG_LINK_UP : 0;
376 51 : mp->flags = htonl (mp->flags);
377 :
378 :
379 51 : vl_api_send_msg (reg, (u8 *) mp);
380 51 : }
381 :
382 : /**
383 : * @brief Message handler for memif_dump API.
384 : * @param mp vl_api_memif_dump_t * mp the api message
385 : */
386 : void
387 44 : vl_api_memif_dump_t_handler (vl_api_memif_dump_t * mp)
388 : {
389 44 : memif_main_t *mm = &memif_main;
390 44 : vnet_main_t *vnm = vnet_get_main ();
391 : vnet_sw_interface_t *swif;
392 : memif_if_t *mif;
393 44 : u8 *if_name = 0;
394 : vl_api_registration_t *reg;
395 :
396 44 : reg = vl_api_client_index_to_registration (mp->client_index);
397 44 : if (!reg)
398 0 : return;
399 :
400 : /* *INDENT-OFF* */
401 95 : pool_foreach (mif, mm->interfaces)
402 : {
403 51 : swif = vnet_get_sw_interface (vnm, mif->sw_if_index);
404 :
405 51 : if_name = format (if_name, "%U%c",
406 : format_vnet_sw_interface_name,
407 : vnm, swif, 0);
408 :
409 51 : send_memif_details (reg, mif, swif, if_name, mp->context);
410 51 : vec_set_len (if_name, 0);
411 : }
412 : /* *INDENT-ON* */
413 :
414 44 : vec_free (if_name);
415 : }
416 :
417 : static void
418 28 : send_memif_socket_filename_details (vl_api_registration_t * reg,
419 : u32 socket_id,
420 : u8 * socket_filename, u32 context)
421 : {
422 : vl_api_memif_socket_filename_details_t *mp;
423 28 : memif_main_t *mm = &memif_main;
424 :
425 28 : mp = vl_msg_api_alloc (sizeof (*mp));
426 28 : clib_memset (mp, 0, sizeof (*mp));
427 :
428 28 : mp->_vl_msg_id = htons (VL_API_MEMIF_SOCKET_FILENAME_DETAILS
429 28 : + mm->msg_id_base);
430 28 : mp->context = context;
431 :
432 28 : mp->socket_id = clib_host_to_net_u32 (socket_id);
433 28 : strncpy ((char *) mp->socket_filename,
434 : (char *) socket_filename, ARRAY_LEN (mp->socket_filename) - 1);
435 :
436 28 : vl_api_send_msg (reg, (u8 *) mp);
437 28 : }
438 :
439 : /**
440 : * @brief Message handler for memif_socket_filename_dump API.
441 : * @param mp vl_api_memif_socket_filename_dump_t api message
442 : */
443 : void
444 17 : vl_api_memif_socket_filename_dump_t_handler
445 : (vl_api_memif_socket_filename_dump_t * mp)
446 : {
447 17 : memif_main_t *mm = &memif_main;
448 : vl_api_registration_t *reg;
449 : u32 sock_id;
450 : u32 msf_idx;
451 :
452 17 : reg = vl_api_client_index_to_registration (mp->client_index);
453 17 : if (!reg)
454 0 : return;
455 :
456 : /* *INDENT-OFF* */
457 1133 : hash_foreach (sock_id, msf_idx, mm->socket_file_index_by_sock_id,
458 : ({
459 : memif_socket_file_t *msf;
460 : u8 *filename;
461 :
462 : msf = pool_elt_at_index(mm->socket_files, msf_idx);
463 : filename = msf->filename;
464 : send_memif_socket_filename_details(reg, sock_id, filename, mp->context);
465 : }));
466 : /* *INDENT-ON* */
467 : }
468 :
469 : /* Set up the API message handling tables */
470 : #include <memif/memif.api.c>
471 : clib_error_t *
472 559 : memif_plugin_api_hookup (vlib_main_t * vm)
473 : {
474 559 : memif_main_t *mm = &memif_main;
475 :
476 : /* Ask for a correctly-sized block of API message decode slots */
477 559 : mm->msg_id_base = setup_message_id_table ();
478 559 : return 0;
479 : }
480 :
481 : /*
482 : * fd.io coding-style-patch-verification: ON
483 : *
484 : * Local Variables:
485 : * eval: (c-set-style "gnu")
486 : * End:
487 : */
|