1 .. _libmemif_gettingstarted_doc:
6 For detailed information on api calls and structures please refer to
9 Start by creating a memif socket. Memif socket represents UNIX domain
10 socket and interfaces assigned to use this socket. Memif uses UNIX domain
11 socket to communicate with other memif drivers.
13 First fill out the ``memif_socket_args`` struct. The minimum required
14 configuration is the UNIX socket path. > Use ``@`` or ``\0`` at the
15 beginning of the path to use abstract socket.
19 memif_socket_args_t sargs;
21 strncpy(sargs.path, socket_path, sizeof(sargs.path));
25 memif_socket_handle_t memif_socket;
27 memif_create_socket(&memif_socket, &sargs, &private_data);
29 Once you have created your socket, you can create memif interfaces on
30 this socket. Fill out the ``memif_conn_args`` struct. Then call
35 memif_conn_args_t cargs;
37 /* Assign your socket handle */
38 cargs.socket = memif_socket;
42 memif_conn_handle_t conn;
44 /* Assign callbacks */
45 memif_create (&conn, &cargs, on_connect_cb, on_disconnect_cb, on_interrupt_cb, &private_data);
47 Now start the polling events using libmemifs builtin polling.
52 err = memif_poll_event(memif_socket, /* timeout -1 = blocking */ -1);
53 } while (err == MEMIF_ERR_SUCCESS);
55 Polling can be canceled by calling ``memif_cancel_poll_event()``.
59 memif_cancel_poll_event (memif_socket);
61 On link status change ``on_connect`` and ``on_disconnect`` callbacks are
62 called respectively. Before you can start transmitting data you, first
63 need to call ``memif_refill_queue()`` for each RX queue to initialize
68 int on_connect (memif_conn_handle_t conn, void *private_ctx)
70 my_private_data_t *data = (my_private_data_t *) private_ctx;
72 err = memif_refill_queue(conn, 0, -1, 0);
73 if (err != MEMIF_ERR_SUCCESS) {
74 INFO("memif_refill_queue: %s", memif_strerror(err));
85 Now you are ready to transmit packets. > Example implementation
86 ``examples/common/sender.c`` and ``examples/common/responder.c``
88 To transmit or receive data you will need to use ``memif_buffer``
89 struct. The important fields here are ``void *data``, ``uint32_t len``
90 and ``uint8_t flags``. The ``data`` pointer points directly to the
91 shared memory packet buffer. This is where you will find/insert your
92 packets. The ``len`` field is the length of the buffer. If the flag
93 ``MEMIF_BUFFER_FLAG_NEXT`` is present in ``flags`` field, this buffer is
94 chained so the rest of the data is located in the next buffer, and so
97 First let’s receive data. To receive data call ``memif_rx_burst()``. The
98 function will fill out memif buffers passed to it. Then you would
99 process your data (e.g. copy to your stack). Last you must refill the
100 queue using ``memif_refill_queue()`` to notify peer that the buffers are
101 now free and can be overwritten.
105 /* Fill out memif buffers and mark them as received */
106 err = memif_rx_burst(conn, qid, buffers, num_buffers, &num_received);
107 if (err != MEMIF_ERR_SUCCESS) {
108 INFO ("memif_rx_burst: %s", memif_strerror(err));
115 /* Refill the queue, so that the peer interface can transmit more packets */
116 err = memif_refill_queue(conn, qid, num_received, 0);
117 if (err != MEMIF_ERR_SUCCESS) {
118 INFO("memif_refill_queue: %s", memif_strerror(err));
122 In order to transmit data you first need to ‘allocate’ memif buffers
123 using ``memif_buffer_alloc()``. This function similar to
124 ``memif_rx_burst`` will fill out provided memif buffers. You will then
125 insert your packets directly into the shared memory (don’t forget to
126 update ``len`` filed if your packet is smaller that buffer length).
127 Finally call ``memif_tx_burst`` to transmit the buffers.
131 /* Alocate memif buffers */
132 err = memif_buffer_alloc(conn, qid, buffers, num_pkts, &num_allocated, packet_size);
133 if (err != MEMIF_ERR_SUCCESS) {
134 INFO("memif_buffer_alloc: %s", memif_strerror(err));
139 Fill out the buffers.
141 tx_buffers[i].data field points to the shared memory.
142 update tx_buffers[i].len to your packet length, if the packet is smaller.
145 /* Transmit the buffers */
146 err = memif_tx_burst(conn, qid, buffers, num_allocated, &num_transmitted);
147 if (err != MEMIF_ERR_SUCCESS) {
148 INFO("memif_tx_burst: %s", memif_strerror(err));
155 Interface with slave role is the buffer producer, as such it can use
158 After receiving buffers, process your packets in place. Then use
159 ``memif_buffer_enq_tx()`` to enqueue rx buffers to tx queue (by swapping
160 rx buffer with a free tx buffer).
164 /* Fill out memif buffers and mark them as received */
165 err = memif_rx_burst(conn, qid, buffers, num_buffers, &num_received);
166 if (err != MEMIF_ERR_SUCCESS) {
167 INFO ("memif_rx_burst: %s", memif_strerror(err));
172 Process the buffers in place.
175 /* Enqueue processed buffers to tx queue */
176 err = memif_buffer_enq_tx(conn, qid, buffers, num_buffers, &num_enqueued);
177 if (err != MEMIF_ERR_SUCCESS) {
178 INFO("memif_buffer_alloc: %s", memif_strerror(err));
182 /* Refill the queue, so that the peer interface can transmit more packets */
183 err = memif_refill_queue(conn, qid, num_enqueued, 0);
184 if (err != MEMIF_ERR_SUCCESS) {
185 INFO("memif_refill_queue: %s", memif_strerror(err));
189 /* Transmit the buffers. */
190 err = memif_tx_burst(conn, qid, buffers, num_enqueued, &num_transmitted);
191 if (err != MEMIF_ERR_SUCCESS) {
192 INFO("memif_tx_burst: %s", memif_strerror(err));
199 Libmemif can be integrated into your applications fd event polling. You
200 will need to implement ``memif_control_fd_update_t`` callback and pass
201 it to ``memif_socket_args.on_control_fd_update``. Now each time any file
202 descriptor belonging to that socket updates, ``on_control_fd_update``
203 callback is called. The file descriptor and event type is passed in
204 ``memif_fd_event_t``. It also contains private context that is
205 associated with this fd. When event is polled on the fd you need to call
206 ``memif_control_fd_handler`` and pass the event type and private context
207 associated with the fd.
212 Connection establishment
213 ~~~~~~~~~~~~~~~~~~~~~~~~
215 Memif sockets should not be handled in parallel. Instead each thread
216 should have it’s own socket. However the UNIX socket can be the same. In
217 case of non-listener socket, it’s straight forward, just create the
218 socket using the same path. In case of listener socket, the polling
219 should be done by single thread. > The socket becomes listener once a
220 Master interface is assigned to it.
225 Single queue must not be handled in parallel. Instead you can assign
226 queues to threads in such way that each queue is only assigned single
232 Please refer to `DPDK MEMIF
233 documentation <http://doc.dpdk.org/guides/nics/memif.html>`__
234 ``'Shared memory'`` section.