Concept (Connecting to VPP)
For detailed information on api calls and structures please refer to libmemif.h.
- Initialize memif
- Declare callback function handling file descriptor event polling.
- Call memif initialization function. memif_init
If event occurres on any file descriptor returned by this callback, call memif_control_fd_handler function. Since version 2.0, last two optional arguments are used to specify custom memory allocation.
If callback function parameter for memif_init function is set to NULL, libmemif will handle file descriptor event polling.
Api call memif_poll_event will call epoll_pwait with user defined timeout to poll event on file descriptors opened by libmemif.
while (1)
{
{
DBG (
"poll_event error!");
}
}
Memif initialization function will initialize internal structures and create timer file descriptor, which will be used for sending periodic connection requests. Timer is disarmed if no memif interface is created.
- Creating interface
- Declare memif connction handle.
example app uses struct that contains connection handle, rx/tx buffers and other connection specific information.
- Specify connection arguments.
memset (&args, 0, sizeof (args));
- Declare callback functions called on connected/disconnected/interrupted status changed.
int
{
...
}
int
{
INFO (
"memif connected!");
return 0;
}
- Call memif interface create function. memif_create
If connection is in slave mode, arms timer file descriptor. If on interrupt callback is set to NULL, user will not be notified about interrupt. Use memif_get_queue_efd call to get interrupt file descriptor for specific queue.
- Connection establishment
- User application will poll events on all file descriptors returned in memif_control_fd_update_t callback.
- On event call memif_control_fd_handler.
- Everything else regarding connection establishment will be done internally.
- Once connection has been established, a callback will inform the user about connection status change.
- Interrupt packet receive
- If event is polled on interrupt file descriptor, libmemif will call memif_interrupt_t callback specified for every connection instance.
- Memif buffers
- Packet data are stored in memif_buffer_t. Pointer data points to shared memory buffer, and unsigned integer *_len* contains buffer length.
- flags: MEMIF_BUFFER_FLAG_NEXT states that the buffer is not large enough to contain whole packet, so next buffer contains the rest of the packet. (chained buffers)
typedef struct
{
uint16_t desc_index;
- Packet receive
- Api call memif_rx_burst will set all required fields in memif buffers provided by user application and dequeue received buffers.
- User application can then process packets.
- Api call memif_refill_queue will enqueue rx buffers.
- Packet transmit
- Api call memif_buffer_alloc will find free tx buffers and set all required fields in memif buffers provided by user application.
- User application can populate shared memory buffers with packets.
- Api call memif_tx_burst will enqueue tx buffers
- Helper functions
- Memif version
- Memif details
- Api call memif_get_details will return details about connection.
- Memif error messages
- Every api call returns error code (integer value) mapped to error string.
- Call memif_strerror will return error message assigned to specific error code.
- Not all syscall errors are translated to memif error codes. If error code 1 (MEMIF_ERR_SYSCALL) is returned then libmemif needs to be compiled with -DMEMIF_DBG flag to print error message. Use make -B to rebuild libmemif in debug mode.
Example app (libmemif fd event polling):
Optional argument: transmit queue id.
Set transmit queue id to 1. Default is 0. Application will create memif interface in slave mode and try to connect to VPP. Exit using Ctrl+C. Application will handle SIGINT signal, free allocated memory and exit with EXIT_SUCCESS.
Example app:
ICMP Responder custom fd event polling.
Example app (multi-thread queue polling)
ICMP Responder multi-thread.
Simple example of libmemif multi-thread usage. Connection establishment is handled by main thread. There are two rx/tx queues in this example. One in polling mode and second in interrupt mode.
VPP config:
# create memif id 0 master
# set int state memif0 up
# set int ip address memif0 192.168.1.1/24
# ping 192.168.1.2
For multiple rings (queues) support run VPP with worker threads: example startup.conf:
unix {
interactive
nodaemon
full-coredump
}
cpu {
workers 2
}
VPP config:
# create memif id 0 master
# set int state memif0 up
# set int ip address memif0 192.168.1.1/24
# ping 192.168.1.2
Master mode queue number is limited by worker threads. Slave mode interface needs to specify number of queues.
# create memif id 0 slave rx-queues 2 tx-queues 2
Example applications use VPP default socket file for memif: /run/vpp/memif.sock For master mode, socket directory must exist prior to memif_create call.
Unit tests
Unit tests use Check framework. This framework must be installed in order to build unit_test binary. Ubuntu/Debian:
sudo apt-get install check
More platforms