2 *------------------------------------------------------------------
3 * Copyright (c) 2017 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *------------------------------------------------------------------
19 * @defgroup libmemif Example libmemif App
25 /** Libmemif version. */
26 #define LIBMEMIF_VERSION "4.0"
27 /** Default name of application using libmemif. */
28 #define MEMIF_DEFAULT_APP_NAME "libmemif-app"
31 #include <sys/types.h>
32 #include <sys/timerfd.h>
33 #include <sys/types.h>
38 MEMIF_ERR_SUCCESS = 0, /*!< success */
40 MEMIF_ERR_SYSCALL, /*!< other syscall error */
41 MEMIF_ERR_CONNREFUSED, /*!< connection refused */
42 MEMIF_ERR_ACCES, /*!< permission denied */
43 MEMIF_ERR_NO_FILE, /*!< file does not exist */
44 MEMIF_ERR_FILE_LIMIT, /*!< system open file limit */
45 MEMIF_ERR_PROC_FILE_LIMIT, /*!< process open file limit */
46 MEMIF_ERR_ALREADY, /*!< connection already requested */
47 MEMIF_ERR_AGAIN, /*!< fd is not socket, or operation would block */
48 MEMIF_ERR_BAD_FD, /*!< invalid fd */
49 MEMIF_ERR_NOMEM, /*!< out of memory */
51 MEMIF_ERR_INVAL_ARG, /*!< invalid argument */
52 MEMIF_ERR_NOCONN, /*!< handle points to no connection */
53 MEMIF_ERR_CONN, /*!< handle points to existing connection */
54 MEMIF_ERR_CB_FDUPDATE, /*!< user defined callback memif_control_fd_update_t
56 MEMIF_ERR_FILE_NOT_SOCK, /*!< file specified by socket path
57 exists, but it's not socket */
58 MEMIF_ERR_NO_SHMFD, /*!< missing shm fd */
59 MEMIF_ERR_COOKIE, /*!< wrong cookie on ring */
60 MEMIF_ERR_NOBUF_RING, /*!< ring buffer full */
61 MEMIF_ERR_NOBUF, /*!< not enough memif buffers */
62 MEMIF_ERR_NOBUF_DET, /*!< memif details needs larger buffer */
63 MEMIF_ERR_INT_WRITE, /*!< send interrupt error */
64 MEMIF_ERR_MFMSG, /*!< malformed msg received */
65 MEMIF_ERR_QID, /*!< invalid queue id */
66 /* MEMIF PROTO ERRORS */
67 MEMIF_ERR_PROTO, /*!< incompatible protocol version */
68 MEMIF_ERR_ID, /*!< unmatched interface id */
69 MEMIF_ERR_ACCSLAVE, /*!< slave cannot accept connection requests */
70 MEMIF_ERR_ALRCONN, /*!< memif is already connected */
71 MEMIF_ERR_MODE, /*!< mode mismatch */
72 MEMIF_ERR_SECRET, /*!< secret mismatch */
73 MEMIF_ERR_NOSECRET, /*!< secret required */
74 MEMIF_ERR_MAXREG, /*!< max region limit reached */
75 MEMIF_ERR_MAXRING, /*!< max ring limit reached */
76 MEMIF_ERR_NO_INTFD, /*!< missing interrupt fd */
77 MEMIF_ERR_DISCONNECT, /*!< disconnect received */
78 MEMIF_ERR_DISCONNECTED, /*!< peer interface disconnected */
79 MEMIF_ERR_UNKNOWN_MSG, /*!< unknown message type */
80 MEMIF_ERR_POLL_CANCEL, /*!< memif_poll_event() was cancelled */
81 MEMIF_ERR_MAX_RING, /*!< too large ring size */
82 MEMIF_ERR_PRIVHDR, /*!< private hdrs not supported */
86 * @defgroup MEMIF_FD_EVENT Types of events that need to be watched for specific fd.
91 /** \brief Memif fd events
92 * User needs to set events that occurred on fd and pass them to
93 * memif_control_fd_handler
95 typedef enum memif_fd_event_type
97 MEMIF_FD_EVENT_READ = 1, /* 00001 */
98 MEMIF_FD_EVENT_WRITE = 2, /* 00010 */
99 /** inform libmemif that error occurred on fd */
100 MEMIF_FD_EVENT_ERROR = 4, /* 00100 */
101 /** if set, informs that fd is going to be closed (user may want to stop
102 watching for events on this fd) */
103 MEMIF_FD_EVENT_DEL = 8, /* 01000 */
105 MEMIF_FD_EVENT_MOD = 16 /* 10000 */
106 } memif_fd_event_type_t;
109 /** \brief Memif connection handle
110 pointer of type void, pointing to internal structure
112 typedef void *memif_conn_handle_t;
114 /** \brief Memif socket handle
115 pointer of type void, pointing to internal structure
117 typedef void *memif_socket_handle_t;
119 /** \brief Memif allocator alloc
120 @param size - requested allocation size
122 custom memory allocator: alloc function template
124 typedef void *(memif_alloc_t) (size_t size);
127 /** \brief Memif realloc
128 @param ptr - pointer to memory block
129 @param size - requested allocation size
131 custom memory reallocation
133 typedef void *(memif_realloc_t) (void *ptr, size_t size);
135 /** \brief Memif allocator free
136 @param size - requested allocation size
138 custom memory allocator: free function template
140 typedef void (memif_free_t) (void *ptr);
143 * @defgroup CALLBACKS Callback functions definitions
149 /** \brief Memif fd event
150 @param fd - interrupt file descriptor
151 @param type - memif fd event type
152 @param private_ctx - private event data
154 typedef struct memif_fd_event
157 memif_fd_event_type_t type;
161 /** \brief Memif control file descriptor update (callback function)
162 @param fde - memif fd event
163 @param private_ctx - private context of socket this fd belongs to
166 This callback is called when there is new fd to watch for events on
167 or if fd is about to be closed (user mey want to stop watching for events
168 on this fd). Private context is taken from libmemif_main, 'private_ctx'
169 passed to memif_per_thread_init() or NULL in case of memif_init()
171 typedef int (memif_control_fd_update_t) (memif_fd_event_t fde,
174 /** \brief Memif connection status update (callback function)
175 @param conn - memif connection handle
176 @param private_ctx - private context
178 Informs user about connection status connected/disconnected.
179 On connected -> start watching for events on interrupt fd (optional).
181 typedef int (memif_connection_update_t) (memif_conn_handle_t conn,
184 /** \brief Memif interrupt occurred (callback function)
185 @param conn - memif connection handle
186 @param private_ctx - private context
187 @param qid - queue id on which interrupt occurred
189 Called when event is received on interrupt fd.
191 typedef int (memif_on_interrupt_t) (memif_conn_handle_t conn,
192 void *private_ctx, uint16_t qid);
197 * @defgroup EXTERNAL_REGION External region APIs
203 /** \brief Get external buffer offset (optional)
204 @param private_ctx - private context
206 Find unallocated external buffer and return its offset.
208 typedef uint32_t (memif_get_external_buffer_offset_t) (void *private_ctx);
210 /** \brief Add external region
211 @param[out] addr - region address
212 @param size - requested region size
213 @param fd[out] - file descriptor
214 @param private_ctx - private context
216 Called by slave. Add external region created by client.
218 typedef int (memif_add_external_region_t) (void * *addr, uint32_t size,
219 int *fd, void *private_ctx);
221 /** \brief Get external region address
222 @param size - requested region size
223 @param fd - file descriptor
224 @param private_ctx - private context
226 Called by master. Get region address from client.
228 \return region address
230 typedef void *(memif_get_external_region_addr_t) (uint32_t size, int fd,
233 /** \brief Delete external region
234 @param addr - region address
235 @param size - region size
236 @param fd - file descriptor
237 @param private_ctx - private context
239 Delete external region.
241 typedef int (memif_del_external_region_t) (void *addr, uint32_t size, int fd,
244 /** \brief Register external region
245 @param ar - add external region callback
246 @param gr - get external region addr callback
247 @param dr - delete external region callback
248 @param go - get external buffer offset callback (optional)
250 void memif_register_external_region (memif_socket_handle_t sock,
251 memif_add_external_region_t *ar,
252 memif_get_external_region_addr_t *gr,
253 memif_del_external_region_t *dr,
254 memif_get_external_buffer_offset_t *go);
256 /** \brief Register external region
257 @param pt_main - per thread main handle
258 @param ar - add external region callback
259 @param gr - get external region addr callback
260 @param dr - delete external region callback
261 @param go - get external buffer offset callback (optional)
263 void memif_per_thread_register_external_region (memif_per_thread_main_handle_t
265 memif_add_external_region_t *
267 memif_get_external_region_addr_t
269 memif_del_external_region_t *
271 memif_get_external_buffer_offset_t
277 * @defgroup ARGS_N_BUFS Connection arguments and buffers
286 MEMIF_INTERFACE_MODE_ETHERNET = 0,
287 MEMIF_INTERFACE_MODE_IP = 1,
288 MEMIF_INTERFACE_MODE_PUNT_INJECT = 2,
289 } memif_interface_mode_t;
290 #endif /* _MEMIF_H_ */
292 /** \brief Memif socket arguments
293 @param path - UNIX socket path, supports abstract socket (have '\0' or '@'
294 as the first char of the path)
295 @param app_name - application name
296 @param connection_request_timer - automaticaly request connection each time
297 this timer expires, must be non-zero to enable this feature
298 @param on_control_fd_update - if control fd updates inform user to watch
300 @param alloc - custom memory allocator, NULL = default
301 @param realloc - custom memory reallocation, NULL = default
302 @param free - custom memory free, NULL = default
304 If param on_control_fd_update is set to NULL,
305 libmemif will handle file descriptor event polling
306 if a valid callback is set, file descriptor event polling needs to be done
307 by user application, all file descriptors and event types will be passed in
308 this callback to user application
310 typedef struct memif_socket_args
315 struct itimerspec connection_request_timer;
317 memif_control_fd_update_t *on_control_fd_update;
318 memif_alloc_t *alloc;
319 memif_realloc_t *realloc;
321 } memif_socket_args_t;
323 /** \brief Memif connection arguments
324 @param socket - Memif socket handle, if NULL default socket will be used.
325 Default socket is only supported in global database (see memif_init).
326 Custom database does not create a default socket
327 (see memif_per_thread_init).
328 Memif connection is stored in the same database as the socket.
329 @param secret - optional parameter used as interface authentication
330 @param num_s2m_rings - number of slave to master rings
331 @param num_m2s_rings - number of master to slave rings
332 @param buffer_size - size of buffer in shared memory
333 @param log2_ring_size - logarithm base 2 of ring size
334 @param is_master - 0 == master, 1 == slave
335 @param interface_id - id used to identify peer connection
336 @param interface_name - interface name
337 @param mode - 0 == ethernet, 1 == ip , 2 == punt/inject
341 memif_socket_handle_t socket; /*!< default = /run/vpp/memif.sock */
342 uint8_t secret[24]; /*!< optional (interface authentication) */
344 uint8_t num_s2m_rings; /*!< default = 1 */
345 uint8_t num_m2s_rings; /*!< default = 1 */
346 uint16_t buffer_size; /*!< default = 2048 */
347 uint8_t log2_ring_size; /*!< default = 10 (1024) */
350 uint32_t interface_id;
351 uint8_t interface_name[32];
352 memif_interface_mode_t mode:8;
355 /*! memif receive mode */
358 MEMIF_RX_MODE_INTERRUPT = 0, /*!< interrupt mode */
359 MEMIF_RX_MODE_POLLING /*!< polling mode */
362 /** \brief Memif buffer
363 @param desc_index - ring descriptor index
364 @param ring - pointer to ring containing descriptor for this buffer
365 @param len - available length
366 @param flags - memif buffer flags
367 @param data - pointer to shared memory data
374 /** next buffer present (chained buffers) */
375 #define MEMIF_BUFFER_FLAG_NEXT (1 << 0)
382 * @defgroup MEMIF_DETAILS Memif details structs
388 /** \brief Memif queue details
389 @param region - region index
390 @param qid - queue id
391 @param ring_size - size of ring buffer in shared memory
392 @param flags - ring flags
393 @param head - ring head pointer
394 @param tail - ring tail pointer
395 @param buffer_size - buffer size on shared memory
402 /** if set queue is in polling mode, else in interrupt mode */
403 #define MEMIF_QUEUE_FLAG_POLLING 1
407 uint16_t buffer_size;
408 } memif_queue_details_t;
410 /** \brief Memif region details
411 @param index - region index
412 @param addr - region address
413 @param size - region size
414 @param fd - file descriptor
415 @param is_external - if not zero then region is defined by client
424 } memif_region_details_t;
426 /** \brief Memif details
427 @param if_name - interface name
428 @param inst_name - application name
429 @param remote_if_name - peer interface name
430 @param remote_inst_name - peer application name
431 @param id - connection id
432 @param secret - secret
433 @param role - 0 = master, 1 = slave
434 @param mode - 0 = ethernet, 1 = ip , 2 = punt/inject
435 @param socket_path - socket path
436 @param regions_num - number of regions
437 @param regions - struct containing region details
438 @param rx_queues_num - number of receive queues
439 @param tx_queues_num - number of transmit queues
440 @param rx_queues - struct containing receive queue details
441 @param tx_queues - struct containing transmit queue details
442 @param error - error string
443 @param link_up_down - 1 = up (connected), 2 = down (disconnected)
449 uint8_t *remote_if_name;
450 uint8_t *remote_inst_name;
453 uint8_t *secret; /* optional */
454 uint8_t role; /* 0 = master, 1 = slave */
455 uint8_t mode; /* 0 = ethernet, 1 = ip, 2 = punt/inject */
456 uint8_t *socket_path;
458 memif_region_details_t *regions;
459 uint8_t rx_queues_num;
460 uint8_t tx_queues_num;
461 memif_queue_details_t *rx_queues;
462 memif_queue_details_t *tx_queues;
465 uint8_t link_up_down; /* 1 = up, 0 = down */
470 * @defgroup API_CALLS Api calls
476 /** \brief Memif get version
478 \return ((MEMIF_VERSION_MAJOR << 8) | MEMIF_VERSION_MINOR)
480 uint16_t memif_get_version (void);
482 /** \brief Get memif version as string
485 const char *memif_get_version_str (void);
487 /** \brief Memif get queue event file descriptor
488 @param conn - memif connection handle
489 @param qid - queue id
490 @param[out] fd - returns event file descriptor
495 int memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *fd);
497 /** \brief Memif set rx mode
498 @param conn - memif connection handle
499 @param rx_mode - receive mode
500 @param qid - queue id
504 int memif_set_rx_mode (memif_conn_handle_t conn, memif_rx_mode_t rx_mode,
507 /** \brief Memif strerror
508 @param err_code - error code
510 Converts error code to error message.
514 char *memif_strerror (int err_code);
516 /** \brief Memif get details
517 @param conn - memif connection handle
518 @param md - pointer to memif details struct
519 @param buf - buffer containing details strings
520 @param buflen - length of buffer
524 int memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
525 char *buf, ssize_t buflen);
527 /** \brief Memory interface create function
528 @param conn - connection handle for client app
529 @param args - memory interface connection arguments
530 @param on_connect - inform user about connected status
531 @param on_disconnect - inform user about disconnected status
532 @param on_interrupt - informs user about interrupt, if set to null user will not be notified about interrupt, user can use memif_get_queue_efd call to get interrupt fd to poll for events
533 @param private_ctx - private context passed back to user with callback
535 Creates memory interface.
538 Start timer that will send events to timerfd. If this fd is passed to memif_control_fd_handler
539 every disconnected memif in slave mode will send connection request.
540 On success new fd is passed to user with memif_control_fd_update_t.
543 Create listener socket and pass fd to user with memif_control_fd_update_t.
544 If this fd is passed to memif_control_fd_handler accept will be called and
545 new fd will be passed to user with memif_control_fd_update_t.
550 int memif_create (memif_conn_handle_t *conn, memif_conn_args_t *args,
551 memif_connection_update_t *on_connect,
552 memif_connection_update_t *on_disconnect,
553 memif_on_interrupt_t *on_interrupt, void *private_ctx);
555 /** \brief Memif control file descriptor handler
556 @param ptr - pointer to event data
557 @param events - event type(s) that occurred
562 int memif_control_fd_handler (void *ptr, memif_fd_event_type_t events);
564 /** \brief Memif delete
565 @param conn - pointer to memif connection handle
568 disconnect session (free queues and regions, close file descriptors, unmap shared memory)
569 set connection handle to NULL, to avoid possible double free
573 int memif_delete (memif_conn_handle_t * conn);
575 /** \brief Memif buffer enq tx
576 @param conn - memif connection handle
577 @param qid - number identifying queue
578 @param bufs - memif buffers
579 @param count - number of memif buffers to enqueue
580 @param count_out - returns number of allocated buffers
582 Enqueue buffers to specified tx queue. Can only be used by slave.
583 Updates desc_index field for each memif buffer.
584 If connection handle points to master returns MEMIF_ERR_INVAL_ARG.
588 int memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
589 memif_buffer_t * bufs, uint16_t count,
590 uint16_t * count_out);
592 /** \brief Memif buffer enq tx at idx
593 @param conn - memif connection handle
594 @param buf_a - memif buffer
595 @param buf_b - memif buffer
597 Swap descriptors for provided buffers and update the buffers
599 int memif_buffer_requeue (memif_conn_handle_t conn, memif_buffer_t *buf_a,
600 memif_buffer_t *buf_b);
602 /** \brief Memif buffer alloc
603 @param conn - memif connection handle
604 @param qid - number identifying queue
605 @param bufs - memif buffers
606 @param count - number of memif buffers to allocate
607 @param count_out - returns number of allocated buffers
608 @param size - buffer size, may return chained buffers if size > buffer_size
612 int memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
613 memif_buffer_t * bufs, uint16_t count,
614 uint16_t * count_out, uint16_t size);
616 /** \brief Memif set next free buffer
617 @param conn - memif connection handle
618 @param qid - number identifying queue
619 @param buf - next free buffer
621 Sets next free descriptor pointer for specified tx queue.
622 The next allocation will happen at this buffer.
624 int memif_set_next_free_buffer (memif_conn_handle_t conn, uint16_t qid,
625 memif_buffer_t *buf);
627 /** \brief Memif refill queue
628 @param conn - memif connection handle
629 @param qid - number identifying queue
630 @param count - number of buffers to be placed on ring
631 @param headroom - offset the buffer by headroom
635 int memif_refill_queue (memif_conn_handle_t conn, uint16_t qid,
636 uint16_t count, uint16_t headroom);
638 /** \brief Memif transmit buffer burst
639 @param conn - memif connection handle
640 @param qid - number identifying queue
641 @param bufs - memif buffers
642 @param count - number of memif buffers to transmit
643 @param tx - returns number of transmitted buffers
647 int memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
648 memif_buffer_t * bufs, uint16_t count, uint16_t * tx);
650 /** \brief Memif receive buffer burst
651 @param conn - memif connection handle
652 @param qid - number identifying queue
653 @param bufs - memif buffers
654 @param count - number of memif buffers to receive
655 @param rx - returns number of received buffers
657 Consume interrupt event for receive queue.
658 The event is not consumed, if memif_rx_burst fails.
662 int memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
663 memif_buffer_t * bufs, uint16_t count, uint16_t * rx);
665 /** \brief Memif poll event
666 @param sock - socket to poll events on
667 @param timeout - timeout in seconds
669 Passive event polling -
670 timeout = 0 - dont wait for event, check event queue if there is an event
671 and return. timeout = -1 - wait until event
675 int memif_poll_event (memif_socket_handle_t sock, int timeout);
677 /** \brief Send signal to stop concurrently running memif_poll_event().
678 @param sock - stop polling on this socket
680 The function, however, does not wait for memif_poll_event() to stop.
681 memif_poll_event() may still return simply because an event has occurred
682 or the timeout has elapsed, but if called repeatedly in an infinite loop,
683 a canceled memif_poll_event() is guaranteed to return MEMIF_ERR_POLL_CANCEL
684 in the shortest possible time.
685 This feature was not available in the first release.
686 Use macro MEMIF_HAVE_CANCEL_POLL_EVENT to check if the feature is present.
690 #define MEMIF_HAVE_CANCEL_POLL_EVENT 1
691 int memif_cancel_poll_event (memif_socket_handle_t sock);
693 /** \brief Send connection request
694 @param conn - memif connection handle
696 Only slave interface can request connection.
700 int memif_request_connection (memif_conn_handle_t conn);
702 /** \brief Create memif socket
703 @param sock - socket handle for client app
704 @param args - memif socket arguments
705 @param private_ctx - private context
707 The first time an interface is assigned a socket, its type is determined.
708 For master role it's 'listener', for slave role it's 'client'. Each
709 interface requires socket of its respective type. Default socket is created
710 if no socket handle is passed to memif_create(). It's private context is
711 NULL. If all interfaces using this socket are deleted, the socket returns to
716 int memif_create_socket (memif_socket_handle_t *sock,
717 memif_socket_args_t *args, void *private_ctx);
719 /** \brief Get memif socket handle from connection
720 @param conn - memif connection handle
722 \return memif_socket_handle_t
724 memif_socket_handle_t memif_get_socket_handle (memif_conn_handle_t conn);
726 /** \brief Delete memif socket
727 @param sock - socket handle for client app
729 When trying to free socket in use, socket will not be freed and
730 MEMIF_ERR_INVAL_ARG is returned.
734 int memif_delete_socket (memif_socket_handle_t * sock);
736 /** \brief Get socket path
737 @param sock - socket handle for client app
739 Return constant pointer to socket path.
743 const char *memif_get_socket_path (memif_socket_handle_t sock);
745 /** \brief Get listener file descriptor
746 @param sock - memif socket handle
750 int memif_get_listener_fd (memif_socket_handle_t sock);
752 /** \brief Set listener file descriptor
753 @param sock - memif socket handle
754 @param if - file descriptor
758 int memif_set_listener_fd (memif_socket_handle_t sock, int fd);
760 /** \brief Set connection request timer value
761 @param sock - memif socket handle
762 @param timer - new timer value
764 Timer on which all disconnected slaves request connection.
765 If the timer doesn't exist (timerspec is 0) create new timer.
766 See system call 'timer_settime' man-page.
769 int memif_set_connection_request_timer (memif_socket_handle_t sock,
770 struct itimerspec timer);
774 #endif /* _LIBMEMIF_H_ */