libmemif: version 3.0

Add support for multi-thread connection establishment.

- control_fd_update() callback now passes private context
  associated with updated file descriptor. File descriptor
  can belong to memif socket, memif connection or timerfd.
  In case of timerfd the context is NULL.

- memif_create_socket() new API. Creates memif socket
  handle to be passed to memif_create() in memif_conn_args_t.
  This API allows to pass private context whenever the file
  descriptor is updated.

- memif_delete_socket() new API. Deletes memif socket.
  Socket must not be in use by any interface.

Type: feature

Change-Id: I7ca4e4349595d4477195f1c32403d3e3a6eb5361
Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com>
This commit is contained in:
Jakub Grajciar
2019-07-01 14:24:48 +02:00
committed by Damjan Marion
parent 312758f9af
commit 12df497bb6
12 changed files with 425 additions and 341 deletions

View File

@ -1,53 +1,47 @@
## Build Instructions {#libmemif_build_doc}
Install dependencies
#### Install dependencies
```
# sudo apt-get install -y git autoconf pkg_config libtool check
# sudo apt-get install -y git cmake autoconf pkg_config libtool check
```
Libmemif is now part of VPP repository. Follow fd.io wiki to pull source code from VPP repository.
[https://wiki.fd.io/view/VPP/Pulling,_Building,_Running,_Hacking_and_Pushing_VPP_Code#Pushing_Patches](https://wiki.fd.io/view/VPP/Pulling,_Building,_Running,_Hacking_and_Pushing_VPP_Code#Pushing_Patches)
Libmemif is located under extras/libmemif.
For debug build:
Libmemif is located under extras/libmemif. From extras/libmemif:
```
# ./bootstrap
# ./configure
# make
# mkdir build
# cd build
# cmake ..
# make install
```
For release build:
#### Verify installation:
```
# ./bootstrap
# ./configure
# make release
# make install
build# ./examples/icmpr-epoll
```
Verify installation:
```
# ./.libs/icmpr-epoll
```
> Make sure to run the binary file from ./.libs. File ./icmp\_responder in libmemif root directory is script that links the library, so it only verifies successful build. Default install path is /usr/lib.
Use _help_ command to display build information and commands:
```
ICMP_Responder:add_epoll_fd:233: fd 0 added to epoll
ICMP_Responder:add_epoll_fd:233: fd 5 added to epoll
LIBMEMIF EXAMPLE APP: ICMP_Responder (debug)
LIBMEMIF EXAMPLE APP: ICMP_Responder
==============================
libmemif version: 2.0 (debug)
libmemif version: 3.0
memif version: 512
commands:
help - prints this help
exit - exit app
conn <index> <mode> [<interrupt-desc>] - create memif. index is also used as interface id, mode 0 = slave 1 = master, interrupt-desc none = default 0 = if ring is full wait 1 = handle only ARP requests
del <index> - delete memif
show - show connection details
ip-set <index> <ip-addr> - set interface ip address
rx-mode <index> <qid> <polling|interrupt> - set queue rx mode
sh-count - print counters
cl-count - clear counters
send <index> <tx> <ip> <mac> - send icmp
use CTRL+C to exit
MEMIF DETAILS
==============================
interface name: memif_connection
app name: ICMP_Responder
remote interface name:
remote app name:
id: 0
secret: (null)
role: slave
mode: ethernet
socket filename: /run/vpp/memif.sock
socket filename: /run/vpp/memif.sock
rx queues:
tx queues:
link: down
```
#### Examples

View File

@ -375,7 +375,7 @@ on_disconnect (memif_conn_handle_t conn, void *private_ctx)
}
int
control_fd_update (int fd, uint8_t events)
control_fd_update (int fd, uint8_t events, void *ctx)
{
/* convert memif event definitions to epoll events */
if (events & MEMIF_FD_EVENT_DEL)
@ -562,7 +562,7 @@ error:
if (err != MEMIF_ERR_SUCCESS)
INFO ("memif_buffer_free: %s", memif_strerror (err));
c->rx_buf_num -= rx;
DBG ("freed %d buffers. %u/%u alloc/free buffers", fb, c->rx_buf_num,
DBG ("freed %d buffers. %u/%u alloc/free buffers", rx, c->rx_buf_num,
MAX_MEMIF_BUFS - c->rx_buf_num);
return 0;
}
@ -637,7 +637,7 @@ error:
INFO ("memif_buffer_free: %s", memif_strerror (err));
c->rx_buf_num -= rx;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
return 0;
}

View File

@ -304,7 +304,7 @@ on_disconnect (memif_conn_handle_t conn, void *private_ctx)
/* user needs to watch new fd or stop watching fd that is about to be closed.
control fd will be modified during connection establishment to minimize CPU usage */
int
control_fd_update (int fd, uint8_t events)
control_fd_update (int fd, uint8_t events, void *ctx)
{
/* convert memif event definitions to epoll events */
if (events & MEMIF_FD_EVENT_DEL)
@ -436,7 +436,7 @@ error:
INFO ("memif_buffer_free: %s", memif_strerror (err));
c->rx_buf_num -= rx;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
return 0;
}
@ -521,7 +521,7 @@ on_interrupt0 (memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
rx -= j;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, rx, MAX_MEMIF_BUFS - rx);
rx, rx, MAX_MEMIF_BUFS - rx);
/* transmit allocated buffers */
err = memif_tx_burst (c->conn, qid, c->tx_bufs, j, &tx);
@ -545,7 +545,7 @@ error:
INFO ("memif_buffer_free: %s", memif_strerror (err));
c->rx_buf_num -= rx;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
return 0;
}
@ -612,7 +612,7 @@ error:
INFO ("memif_buffer_free: %s", memif_strerror (err));
c->rx_buf_num -= rx;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
return 0;
}

View File

@ -565,7 +565,7 @@ on_disconnect (memif_conn_handle_t conn, void *private_ctx)
/* user needs to watch new fd or stop watching fd that is about to be closed.
control fd will be modified during connection establishment to minimize CPU usage */
int
control_fd_update (int fd, uint8_t events)
control_fd_update (int fd, uint8_t events, void *ctx)
{
/* convert memif event definitions to epoll events */
if (events & MEMIF_FD_EVENT_DEL)

View File

@ -296,7 +296,7 @@ on_disconnect (memif_conn_handle_t conn, void *private_ctx)
/* user needs to watch new fd or stop watching fd that is about to be closed.
control fd will be modified during connection establishment to minimize CPU usage */
int
control_fd_update (int fd, uint8_t events)
control_fd_update (int fd, uint8_t events, void *ctx)
{
/* convert memif event definitions to epoll events */
if (events & MEMIF_FD_EVENT_DEL)
@ -371,7 +371,7 @@ on_interrupt (memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
c->rx_buf_num -= rx;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, rx, MAX_MEMIF_BUFS - rx);
rx, rx, MAX_MEMIF_BUFS - rx);
/* transmit allocated buffers */
err = memif_tx_burst (c->conn, qid, c->bufs, rx, &tx);
@ -393,7 +393,7 @@ error:
INFO ("memif_buffer_free: %s", memif_strerror (err));
c->rx_buf_num = 0;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
return 0;
}
@ -450,7 +450,7 @@ on_interrupt0 (memif_conn_handle_t conn, void *private_ctx, uint16_t qid)
c->rx_buf_num -= rx;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, rx, MAX_MEMIF_BUFS - rx);
rx, rx, MAX_MEMIF_BUFS - rx);
/* transmit allocated buffers */
err = memif_tx_burst (c->conn, qid, c->bufs, i, &tx);
@ -472,7 +472,7 @@ error:
INFO ("memif_buffer_free: %s", memif_strerror (err));
c->rx_buf_num = 0;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
return 0;
}
@ -538,7 +538,7 @@ error:
INFO ("memif_buffer_free: %s", memif_strerror (err));
c->rx_buf_num = 0;
DBG ("freed %d buffers. %u/%u alloc/free buffers",
fb, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
rx, c->rx_buf_num, MAX_MEMIF_BUFS - c->rx_buf_num);
return 0;
}

View File

@ -23,7 +23,7 @@
#define _LIBMEMIF_H_
/** Libmemif version. */
#define LIBMEMIF_VERSION "2.1"
#define LIBMEMIF_VERSION "3.0"
/** Default name of application using libmemif. */
#define MEMIF_DEFAULT_APP_NAME "libmemif-app"
@ -101,6 +101,11 @@ typedef enum
*/
typedef void *memif_conn_handle_t;
/** \brief Memif socket handle
pointer of type void, pointing to internal structure
*/
typedef void *memif_socket_handle_t;
/** \brief Memif allocator alloc
@param size - requested allocation size
@ -138,7 +143,8 @@ typedef void (memif_free_t) (void *ptr);
This callback is called when there is new fd to watch for events on
or if fd is about to be closed (user mey want to stop watching for events on this fd).
*/
typedef int (memif_control_fd_update_t) (int fd, uint8_t events);
typedef int (memif_control_fd_update_t) (int fd, uint8_t events,
void *private_ctx);
/** \brief Memif connection status update (callback function)
@param conn - memif connection handle
@ -240,7 +246,7 @@ typedef enum
#endif /* _MEMIF_H_ */
/** \brief Memif connection arguments
@param socket_filename - socket filename
@param socket - memif socket handle, if NULL default socket will be used
@param secret - otional parameter used as interface autenthication
@param num_s2m_rings - number of slave to master rings
@param num_m2s_rings - number of master to slave rings
@ -253,7 +259,7 @@ typedef enum
*/
typedef struct
{
uint8_t *socket_filename; /*!< default = /run/vpp/memif.sock */
memif_socket_handle_t socket; /*!< default = /run/vpp/memif.sock */
uint8_t secret[24]; /*!< optional (interface authentication) */
uint8_t num_s2m_rings; /*!< default = 1 */
@ -468,7 +474,7 @@ int memif_init (memif_control_fd_update_t * on_control_fd_update,
int memif_cleanup ();
/** \brief Memory interface create function
@param conn - connection handle for user app
@param conn - connection handle for client app
@param args - memory interface connection arguments
@param on_connect - inform user about connected status
@param on_disconnect - inform user about disconnected status
@ -625,7 +631,7 @@ int memif_cancel_poll_event ();
\return memif_err_t
*/
int memif_set_connection_request_timer(struct itimerspec timer);
int memif_set_connection_request_timer (struct itimerspec timer);
/** \brief Send connection request
@param conn - memif connection handle
@ -634,7 +640,35 @@ int memif_set_connection_request_timer(struct itimerspec timer);
\return memif_err_t
*/
int memif_request_connection(memif_conn_handle_t conn);
int memif_request_connection (memif_conn_handle_t conn);
/** \brief Create memif socket
@param sock - socket handle for client app
@param filename - path to socket file
@param private_ctx - private context
The first time an interface is assigned a socket, its type is determined.
For master role it's 'listener', for slave role it's 'client'. Each interface
requires socket of its respective type. Default socket is creted if no
socket handle is passed to memif_create(). It's private context is NULL.
If all interfaces using this socket are deleted, the socket returns
to its default state.
\return memif_err_t
*/
int memif_create_socket (memif_socket_handle_t * sock, const char * filename,
void * private_ctx);
/** \brief Delete memif socket
@param sock - socket handle for client app
When trying to free socket in use, socket will not be freed and
MEMIF_ERR_INVAL_ARG is returned.
\return memif_err_t
*/
int memif_delete_socket (memif_socket_handle_t * sock);
/** @} */
#endif /* _LIBMEMIF_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -35,8 +35,7 @@
_Static_assert (strlen (MEMIF_DEFAULT_APP_NAME) <= MEMIF_NAME_LEN,
"MEMIF_DEFAULT_APP_NAME max length is 32");
#define MEMIF_DEFAULT_SOCKET_DIR "/run/vpp"
#define MEMIF_DEFAULT_SOCKET_FILENAME "memif.sock"
#define MEMIF_DEFAULT_SOCKET_PATH "/run/vpp/memif.sock"
#define MEMIF_DEFAULT_RING_SIZE 1024
#define MEMIF_DEFAULT_LOG2_RING_SIZE 10
#define MEMIF_DEFAULT_RX_QUEUES 1
@ -67,6 +66,13 @@ _Static_assert (strlen (MEMIF_DEFAULT_APP_NAME) <= MEMIF_NAME_LEN,
#define DBG(...)
#endif /* MEMIF_DBG */
typedef enum
{
MEMIF_SOCKET_TYPE_NONE = 0, /* unassigned, not used by any interface */
MEMIF_SOCKET_TYPE_LISTENER, /* listener socket, master interface assigned */
MEMIF_SOCKET_TYPE_CLIENT /* client socket, slave interface assigned */
} memif_socket_type_t;
typedef struct
{
void *addr;
@ -121,7 +127,6 @@ typedef struct memif_connection
memif_conn_run_args_t run_args;
int fd;
int listener_fd;
memif_fn *write_fn, *read_fn, *error_fn;
@ -158,8 +163,10 @@ typedef struct
{
int fd;
uint16_t use_count;
memif_socket_type_t type;
uint8_t *filename;
uint16_t interface_list_len;
void *private_ctx;
memif_list_elt_t *interface_list; /* memif master interfaces listening on this socket */
} memif_socket_t;
@ -171,6 +178,8 @@ typedef struct
uint16_t disconn_slaves;
uint8_t app_name[MEMIF_NAME_LEN];
memif_socket_handle_t default_socket;
memif_add_external_region_t *add_external_region;
memif_get_external_region_addr_t *get_external_region_addr;
memif_del_external_region_t *del_external_region;
@ -182,11 +191,11 @@ typedef struct
uint16_t control_list_len;
uint16_t interrupt_list_len;
uint16_t listener_list_len;
uint16_t socket_list_len;
uint16_t pending_list_len;
memif_list_elt_t *control_list;
memif_list_elt_t *interrupt_list;
memif_list_elt_t *listener_list;
memif_list_elt_t *socket_list;
memif_list_elt_t *pending_list;
} libmemif_main_t;

View File

@ -471,7 +471,7 @@ memif_msg_receive_init (memif_socket_t * ms, int fd, memif_msg_t * msg)
error:
memif_msg_send_disconnect (fd, err_string, 0);
lm->control_fd_update (fd, MEMIF_FD_EVENT_DEL);
lm->control_fd_update (fd, MEMIF_FD_EVENT_DEL, c->private_ctx);
free_list_elt (lm->pending_list, lm->pending_list_len, fd);
close (fd);
fd = -1;
@ -600,7 +600,8 @@ memif_msg_receive_connect (memif_connection_t * c, memif_msg_t * msg)
elt.data_struct = c;
add_list_elt (&elt, &lm->interrupt_list, &lm->interrupt_list_len);
lm->control_fd_update (c->rx_queues[i].int_fd, MEMIF_FD_EVENT_READ);
lm->control_fd_update (c->rx_queues[i].int_fd, MEMIF_FD_EVENT_READ,
c->private_ctx);
}
}
@ -630,7 +631,8 @@ memif_msg_receive_connected (memif_connection_t * c, memif_msg_t * msg)
{
for (i = 0; i < c->run_args.num_s2m_rings; i++)
{
lm->control_fd_update (c->rx_queues[i].int_fd, MEMIF_FD_EVENT_READ);
lm->control_fd_update (c->rx_queues[i].int_fd, MEMIF_FD_EVENT_READ,
c->private_ctx);
}
}
@ -808,8 +810,7 @@ memif_msg_receive (int ifd)
if (c != NULL)
c->flags |= MEMIF_CONNECTION_FLAG_WRITE;
/* libmemif_main_t *lm = &libmemif_main;
lm->control_fd_update (c->fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_MOD); */
return MEMIF_ERR_SUCCESS; /* 0 */
}
@ -853,12 +854,7 @@ memif_conn_fd_write_ready (memif_connection_t * c)
c->msg_queue = c->msg_queue->next;
c->flags &= ~MEMIF_CONNECTION_FLAG_WRITE;
/*
libmemif_main_t *lm = &libmemif_main;
lm->control_fd_update (c->fd,
MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_WRITE | MEMIF_FD_EVENT_MOD);
*/
err = memif_msg_send (c->fd, &e->msg, e->fd);
lm->free (e);
goto done;
@ -893,7 +889,8 @@ memif_conn_fd_accept_ready (memif_socket_t * ms)
elt.data_struct = ms;
add_list_elt (&elt, &lm->pending_list, &lm->pending_list_len);
lm->control_fd_update (conn_fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_WRITE);
lm->control_fd_update (conn_fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_WRITE,
ms->private_ctx);
return memif_msg_send_hello (conn_fd);
}

View File

@ -148,7 +148,6 @@ START_TEST (test_create)
ck_assert_ptr_ne (c->on_interrupt, NULL);
ck_assert_str_eq ((char *)c->args.interface_name, (char *)args.interface_name);
ck_assert_str_eq ((char *)c->args.socket_filename, SOCKET_FILENAME);
struct itimerspec timer;
timerfd_gettime (lm->timerfd, &timer);
@ -210,7 +209,6 @@ START_TEST (test_create_master)
ck_assert_ptr_ne (c->on_interrupt, NULL);
ck_assert_str_eq ((char *)c->args.interface_name, (char *)args.interface_name);
ck_assert_str_eq ((char *)c->args.socket_filename, SOCKET_FILENAME);
struct stat file_stat;
@ -295,9 +293,7 @@ START_TEST (test_create_mult)
ck_assert_ptr_ne (c1->on_interrupt, NULL);
ck_assert_str_eq ((char *)c->args.interface_name, (char *)args.interface_name);
ck_assert_str_eq ((char *)c->args.socket_filename, SOCKET_FILENAME);
ck_assert_str_eq ((char *)c1->args.interface_name, (char *)args.interface_name);
ck_assert_str_eq ((char *)c1->args.socket_filename, SOCKET_FILENAME);
struct itimerspec timer;
timerfd_gettime (lm->timerfd, &timer);
@ -720,7 +716,6 @@ START_TEST (test_get_details)
ck_assert_str_eq ((char *)md.remote_if_name, (char *)c->remote_if_name);
ck_assert_str_eq ((char *)md.remote_inst_name, (char *)c->remote_name);
ck_assert_str_eq ((char *)md.secret, (char *)c->args.secret);
ck_assert_str_eq ((char *)md.socket_filename, (char *)c->args.socket_filename);
ck_assert_uint_eq (md.id, c->args.interface_id);
ck_assert_uint_ne (md.role, c->args.is_master);

View File

@ -37,7 +37,7 @@ on_interrupt (memif_conn_handle_t conn, void *ctx, uint16_t qid)
}
int
control_fd_update (int fd, uint8_t events)
control_fd_update (int fd, uint8_t events, void *ctx)
{
return 0;
}

View File

@ -34,6 +34,6 @@ int on_disconnect (memif_conn_handle_t conn, void *ctx);
int on_interrupt (memif_conn_handle_t conn, void *ctx, uint16_t qid);
int control_fd_update (int fd, uint8_t events);
int control_fd_update (int fd, uint8_t events, void *ctx);
#endif /* _UNIT_TEST_H_ */