aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>2021-10-12 14:00:25 +0200
committerDave Wallace <dwallacelf@gmail.com>2021-10-13 15:30:03 +0000
commit8acc5ee9079d0b03229a72e72a5308e7de0a359a (patch)
treeba3e5789abc2c3cd4edd9806fc44991c45d705f1
parent87e90830b8931b4c55526bf7cb5a148a10df061f (diff)
libmemif: docs md->rst
Type: improvement Change-Id: Ibebd2d47a4268189f11601d004073e4858548f25 Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
-rw-r--r--extras/libmemif/docs/buildinstructions_doc.md47
-rw-r--r--extras/libmemif/docs/buildinstructions_doc.rst61
-rw-r--r--extras/libmemif/docs/gettingstarted_doc.md164
-rw-r--r--extras/libmemif/docs/gettingstarted_doc.rst234
-rw-r--r--extras/libmemif/examples/example_setup_doc.md207
-rw-r--r--extras/libmemif/examples/example_setup_doc.rst248
-rw-r--r--extras/libmemif/examples/examples_doc.md18
-rw-r--r--extras/libmemif/examples/examples_doc.rst42
-rw-r--r--extras/libmemif/libmemif_doc.md58
-rw-r--r--extras/libmemif/libmemif_doc.rst67
10 files changed, 652 insertions, 494 deletions
diff --git a/extras/libmemif/docs/buildinstructions_doc.md b/extras/libmemif/docs/buildinstructions_doc.md
deleted file mode 100644
index 3f7c8e8d66d..00000000000
--- a/extras/libmemif/docs/buildinstructions_doc.md
+++ /dev/null
@@ -1,47 +0,0 @@
-## Build Instructions {#libmemif_build_doc}
-
-#### Install dependencies
-```
-# sudo apt-get install -y git cmake autoconf pkg_config libtool
-```
-
-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. From extras/libmemif:
-```
-# mkdir build
-# cd build
-# cmake ..
-# make install
-```
-
-#### Verify installation:
-```
-build# ./examples/icmp_responder -?
-```
-Use `-?` flag to display help:
-```
-LIBMEMIF EXAMPLE APP: icmp_responder_example
-==============================
-libmemif version: 4.0, memif version: 2.0
-==============================
-In this example, memif endpoint connects to an external application.
-The example application can resolve ARP and reply to ICMPv4 packets.
-The program will exit once the interface is disconnected.
-==============================
-Usage: icmp_responder [OPTIONS]
-
-Options:
- -r Interface role <slave|master>. Default: slave
- -s Socket path. Supports abstract socket using @ before the path. Default: /run/vpp/memif.sock
- -i Interface id. Default: 0
- -a IPv4 address. Default: 192.168.1.1
- -h Mac address. Default: aa:aa:aa:aa:aa:aa
- -? Show help and exit.
- -v Show libmemif and memif version information and exit.
-```
-
-#### Examples
-
-Once the library is built/installed, refer to @ref libmemif_examples_doc and @ref libmemif_gettingstarted_doc for additional information on basic use cases and API usage.
diff --git a/extras/libmemif/docs/buildinstructions_doc.rst b/extras/libmemif/docs/buildinstructions_doc.rst
new file mode 100644
index 00000000000..090b9d6ff75
--- /dev/null
+++ b/extras/libmemif/docs/buildinstructions_doc.rst
@@ -0,0 +1,61 @@
+.. _libmemif_build_doc:
+
+Build Instructions
+==================
+
+Install dependencies
+--------------------
+
+::
+
+ # sudo apt-get install -y git cmake autoconf pkg_config libtool
+
+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
+
+Libmemif is located under extras/libmemif. From extras/libmemif:
+
+::
+
+ # mkdir build
+ # cd build
+ # cmake ..
+ # make install
+
+Verify installation:
+--------------------
+
+::
+
+ build# ./examples/icmp_responder -?
+
+Use ``-?`` flag to display help:
+
+::
+
+ LIBMEMIF EXAMPLE APP: icmp_responder_example
+ ==============================
+ libmemif version: 4.0, memif version: 2.0
+ ==============================
+ In this example, memif endpoint connects to an external application.
+ The example application can resolve ARP and reply to ICMPv4 packets.
+ The program will exit once the interface is disconnected.
+ ==============================
+ Usage: icmp_responder [OPTIONS]
+
+ Options:
+ -r Interface role <slave|master>. Default: slave
+ -s Socket path. Supports abstract socket using @ before the path. Default: /run/vpp/memif.sock
+ -i Interface id. Default: 0
+ -a IPv4 address. Default: 192.168.1.1
+ -h Mac address. Default: aa:aa:aa:aa:aa:aa
+ -? Show help and exit.
+ -v Show libmemif and memif version information and exit.
+
+Examples
+--------
+
+Once the library is built/installed, refer to :ref:`libmemif_examples_doc`
+and :ref:`libmemif_gettingstarted_doc` for additional information on basic
+use cases and API usage.
diff --git a/extras/libmemif/docs/gettingstarted_doc.md b/extras/libmemif/docs/gettingstarted_doc.md
deleted file mode 100644
index 6f2a99c8c69..00000000000
--- a/extras/libmemif/docs/gettingstarted_doc.md
+++ /dev/null
@@ -1,164 +0,0 @@
-## Getting started {#libmemif_gettingstarted_doc}
-
-For detailed information on api calls and structures please refer to @ref libmemif.h.
-
-Start by creating a memif socket. Memif socket represents UNIX domain socket and interfaces assigned to use this socket. Memif uses UNIX doman socket to communicate with other memif drivers.
-
-First fill out the `memif_socket_args` struct. The minimum required configuration is the UNIX socket path.
-> Use `@` or `\0` at the beginning of the path to use abstract socket.
-```c
-memif_socket_args_t sargs;
-
-strncpy(sargs.path, socket_path, sizeof(sargs.path));
-```
-```c
-memif_socket_handle_t memif_socket;
-
-memif_create_socket(&memif_socket, &sargs, &private_data);
-```
-Once you have created your socket, you can create memif interfaces on this socket. Fill out the `memif_conn_args` struct. Then call `memif_create()`.
-```c
-memif_conn_args_t cargs;
-
-/* Assign your socket handle */
-cargs.socket = memif_socket;
-```
-```c
-memif_conn_handle_t conn;
-
-/* Assign callbacks */
-memif_create (&conn, &cargs, on_connect_cb, on_disconnect_cb, on_interrupt_cb, &private_data);
-```
-Now start the polling events using libmemifs builtin polling.
-```c
-do {
- err = memif_poll_event(memif_socket, /* timeout -1 = blocking */ -1);
-} while (err == MEMIF_ERR_SUCCESS);
-```
-Polling can be canceled by calling `memif_cancel_poll_event()`.
-```c
-memif_cancel_poll_event (memif_socket);
-```
-On link status change `on_connect` and `on_disconnect` callbacks are called respectively. Before you can start transmitting data you, first need to call `memif_refill_queue()` for each RX queue to initialize this queue.
-```c
-int on_connect (memif_conn_handle_t conn, void *private_ctx)
-{
- my_private_data_t *data = (my_private_data_t *) private_ctx;
-
- err = memif_refill_queue(conn, 0, -1, 0);
- if (err != MEMIF_ERR_SUCCESS) {
- INFO("memif_refill_queue: %s", memif_strerror(err));
- return err;
- }
-
- /*
- * Do stuff.
- */
-
- return 0;
-}
-```
-Now you are ready to transmit packets.
-> Example implementation @ref examples/common/sender.c and @ref examples/common/responder.c
-
-To transmit or receive data you will need to use `memif_buffer` struct. The important fields here are `void *data`, `uint32_t len` and `uint8_t flags`. The `data` pointer points directly to the shared memory packet buffer. This is where you will find/insert your packets. The `len` field is the length of the buffer. If the flag `MEMIF_BUFFER_FLAG_NEXT` is present in `flags` field, this buffer is chained so the rest of the data is located in the next buffer, and so on.
-
-First let's receive data. To receive data call `memif_rx_burst()`. The function will fill out memif buffers passed to it. Then you would process your data (e.g. copy to your stack). Last you must refill the queue using `memif_refill_queue()` to notify peer that the buffers are now free and can be overwritten.
-```c
-/* Fill out memif buffers and mark them as received */
-err = memif_rx_burst(conn, qid, buffers, num_buffers, &num_received);
-if (err != MEMIF_ERR_SUCCESS) {
- INFO ("memif_rx_burst: %s", memif_strerror(err));
- return err;
-}
-/*
- Process the buffers.
-*/
-
-/* Refill the queue, so that the peer interface can transmit more packets */
-err = memif_refill_queue(conn, qid, num_received, 0);
-if (err != MEMIF_ERR_SUCCESS) {
- INFO("memif_refill_queue: %s", memif_strerror(err));
- goto error;
-}
-```
-In order to transmit data you first need to 'allocate' memif buffers using `memif_buffer_alloc()`. This function simmilar to `memif_rx_burst` will fill out provided memif buffers. You will then insert your packets directly into the shared memory (don't forget to update `len` filed if your packet is smaller that buffer length). Finaly call `memif_tx_burst` to transmit the buffers.
-```c
-/* Alocate memif buffers */
-err = memif_buffer_alloc(conn, qid, buffers, num_pkts, &num_allocated, packet_size);
-if (err != MEMIF_ERR_SUCCESS) {
- INFO("memif_buffer_alloc: %s", memif_strerror(err));
- goto error;
-}
-
-/*
- Fill out the buffers.
-
- tx_buffers[i].data field points to the shared memory.
- update tx_buffers[i].len to your packet length, if the packet is smaller.
-*/
-
-/* Transmit the buffers */
-err = memif_tx_burst(conn, qid, buffers, num_allocated, &num_transmitted);
-if (err != MEMIF_ERR_SUCCESS) {
- INFO("memif_tx_burst: %s", memif_strerror(err));
- goto error;
-}
-```
-### Zero-copy Slave
-
-Interface with slave role is the buffer producer, as such it can use zero-copy mode.
-
-After receiving buffers, process your packets in place. Then use `memif_buffer_enq_tx()` to enqueue rx buffers to tx queue (by swapping rx buffer with a free tx buffer).
-```c
-/* Fill out memif buffers and mark them as received */
-err = memif_rx_burst(conn, qid, buffers, num_buffers, &num_received);
-if (err != MEMIF_ERR_SUCCESS) {
- INFO ("memif_rx_burst: %s", memif_strerror(err));
- return err;
-}
-
-/*
- Process the buffers in place.
-*/
-
-/* Enqueue processed buffers to tx queue */
-err = memif_buffer_enq_tx(conn, qid, buffers, num_buffers, &num_enqueued);
-if (err != MEMIF_ERR_SUCCESS) {
- INFO("memif_buffer_alloc: %s", memif_strerror(err));
- goto error;
-}
-
-/* Refill the queue, so that the peer interface can transmit more packets */
-err = memif_refill_queue(conn, qid, num_enqueued, 0);
-if (err != MEMIF_ERR_SUCCESS) {
- INFO("memif_refill_queue: %s", memif_strerror(err));
- goto error;
-}
-
-/* Transmit the buffers. */
-err = memif_tx_burst(conn, qid, buffers, num_enqueued, &num_transmitted);
-if (err != MEMIF_ERR_SUCCESS) {
- INFO("memif_tx_burst: %s", memif_strerror(err));
- goto error;
-}
-```
-
-### Custom Event Polling
-
-Libmemif can be integrated into your applications fd event polling. You will need to implement `memif_control_fd_update_t` callback and pass it to `memif_socket_args.on_control_fd_update`. Now each time any file descriptor belonging to that socket updates, `on_control_fd_update` callback is called. The file descriptor and event type is passed in `memif_fd_event_t`. It also contains private context that is associated with this fd. When event is polled on the fd you need to call `memif_control_fd_handler` and pass the event type and private context associated with the fd.
-
-### Multi Threading
-
-#### Connection establishment
-
-Memif sockets should not be handled in paralell. Instead each thread should have it's own socket. However the UNIX socket can be the same. In case of non-listener socket, it's straight forward, just create the socket using the same path. In case of listener socket, the polling should be done by single thread.
-> The socket becomes listener once a Master interface is assigned to it.
-
-#### Packet handling
-
-Single queue must not be handled in paralel. Instead you can assign queues to threads in such way that each queue is only assigned single thread.
-
-### Shared Memory Layout
-
-Please refer to [DPDK MEMIF documentation](http://doc.dpdk.org/guides/nics/memif.html) `'Shared memory'` section. \ No newline at end of file
diff --git a/extras/libmemif/docs/gettingstarted_doc.rst b/extras/libmemif/docs/gettingstarted_doc.rst
new file mode 100644
index 00000000000..f576fe25145
--- /dev/null
+++ b/extras/libmemif/docs/gettingstarted_doc.rst
@@ -0,0 +1,234 @@
+.. _libmemif_gettingstarted_doc:
+
+Getting started
+===============
+
+For detailed information on api calls and structures please refer to
+``libmemif.h``.
+
+Start by creating a memif socket. Memif socket represents UNIX domain
+socket and interfaces assigned to use this socket. Memif uses UNIX domain
+socket to communicate with other memif drivers.
+
+First fill out the ``memif_socket_args`` struct. The minimum required
+configuration is the UNIX socket path. > Use ``@`` or ``\0`` at the
+beginning of the path to use abstract socket.
+
+.. code:: c
+
+ memif_socket_args_t sargs;
+
+ strncpy(sargs.path, socket_path, sizeof(sargs.path));
+
+.. code:: c
+
+ memif_socket_handle_t memif_socket;
+
+ memif_create_socket(&memif_socket, &sargs, &private_data);
+
+Once you have created your socket, you can create memif interfaces on
+this socket. Fill out the ``memif_conn_args`` struct. Then call
+``memif_create()``.
+
+.. code:: c
+
+ memif_conn_args_t cargs;
+
+ /* Assign your socket handle */
+ cargs.socket = memif_socket;
+
+.. code:: c
+
+ memif_conn_handle_t conn;
+
+ /* Assign callbacks */
+ memif_create (&conn, &cargs, on_connect_cb, on_disconnect_cb, on_interrupt_cb, &private_data);
+
+Now start the polling events using libmemifs builtin polling.
+
+.. code:: c
+
+ do {
+ err = memif_poll_event(memif_socket, /* timeout -1 = blocking */ -1);
+ } while (err == MEMIF_ERR_SUCCESS);
+
+Polling can be canceled by calling ``memif_cancel_poll_event()``.
+
+.. code:: c
+
+ memif_cancel_poll_event (memif_socket);
+
+On link status change ``on_connect`` and ``on_disconnect`` callbacks are
+called respectively. Before you can start transmitting data you, first
+need to call ``memif_refill_queue()`` for each RX queue to initialize
+this queue.
+
+.. code:: c
+
+ int on_connect (memif_conn_handle_t conn, void *private_ctx)
+ {
+ my_private_data_t *data = (my_private_data_t *) private_ctx;
+
+ err = memif_refill_queue(conn, 0, -1, 0);
+ if (err != MEMIF_ERR_SUCCESS) {
+ INFO("memif_refill_queue: %s", memif_strerror(err));
+ return err;
+ }
+
+ /*
+ * Do stuff.
+ */
+
+ return 0;
+ }
+
+Now you are ready to transmit packets. > Example implementation
+``examples/common/sender.c`` and ``examples/common/responder.c``
+
+To transmit or receive data you will need to use ``memif_buffer``
+struct. The important fields here are ``void *data``, ``uint32_t len``
+and ``uint8_t flags``. The ``data`` pointer points directly to the
+shared memory packet buffer. This is where you will find/insert your
+packets. The ``len`` field is the length of the buffer. If the flag
+``MEMIF_BUFFER_FLAG_NEXT`` is present in ``flags`` field, this buffer is
+chained so the rest of the data is located in the next buffer, and so
+on.
+
+First let’s receive data. To receive data call ``memif_rx_burst()``. The
+function will fill out memif buffers passed to it. Then you would
+process your data (e.g. copy to your stack). Last you must refill the
+queue using ``memif_refill_queue()`` to notify peer that the buffers are
+now free and can be overwritten.
+
+.. code:: c
+
+ /* Fill out memif buffers and mark them as received */
+ err = memif_rx_burst(conn, qid, buffers, num_buffers, &num_received);
+ if (err != MEMIF_ERR_SUCCESS) {
+ INFO ("memif_rx_burst: %s", memif_strerror(err));
+ return err;
+ }
+ /*
+ Process the buffers.
+ */
+
+ /* Refill the queue, so that the peer interface can transmit more packets */
+ err = memif_refill_queue(conn, qid, num_received, 0);
+ if (err != MEMIF_ERR_SUCCESS) {
+ INFO("memif_refill_queue: %s", memif_strerror(err));
+ goto error;
+ }
+
+In order to transmit data you first need to ‘allocate’ memif buffers
+using ``memif_buffer_alloc()``. This function similar to
+``memif_rx_burst`` will fill out provided memif buffers. You will then
+insert your packets directly into the shared memory (don’t forget to
+update ``len`` filed if your packet is smaller that buffer length).
+Finally call ``memif_tx_burst`` to transmit the buffers.
+
+.. code:: c
+
+ /* Alocate memif buffers */
+ err = memif_buffer_alloc(conn, qid, buffers, num_pkts, &num_allocated, packet_size);
+ if (err != MEMIF_ERR_SUCCESS) {
+ INFO("memif_buffer_alloc: %s", memif_strerror(err));
+ goto error;
+ }
+
+ /*
+ Fill out the buffers.
+
+ tx_buffers[i].data field points to the shared memory.
+ update tx_buffers[i].len to your packet length, if the packet is smaller.
+ */
+
+ /* Transmit the buffers */
+ err = memif_tx_burst(conn, qid, buffers, num_allocated, &num_transmitted);
+ if (err != MEMIF_ERR_SUCCESS) {
+ INFO("memif_tx_burst: %s", memif_strerror(err));
+ goto error;
+ }
+
+Zero-copy Slave
+---------------
+
+Interface with slave role is the buffer producer, as such it can use
+zero-copy mode.
+
+After receiving buffers, process your packets in place. Then use
+``memif_buffer_enq_tx()`` to enqueue rx buffers to tx queue (by swapping
+rx buffer with a free tx buffer).
+
+.. code:: c
+
+ /* Fill out memif buffers and mark them as received */
+ err = memif_rx_burst(conn, qid, buffers, num_buffers, &num_received);
+ if (err != MEMIF_ERR_SUCCESS) {
+ INFO ("memif_rx_burst: %s", memif_strerror(err));
+ return err;
+ }
+
+ /*
+ Process the buffers in place.
+ */
+
+ /* Enqueue processed buffers to tx queue */
+ err = memif_buffer_enq_tx(conn, qid, buffers, num_buffers, &num_enqueued);
+ if (err != MEMIF_ERR_SUCCESS) {
+ INFO("memif_buffer_alloc: %s", memif_strerror(err));
+ goto error;
+ }
+
+ /* Refill the queue, so that the peer interface can transmit more packets */
+ err = memif_refill_queue(conn, qid, num_enqueued, 0);
+ if (err != MEMIF_ERR_SUCCESS) {
+ INFO("memif_refill_queue: %s", memif_strerror(err));
+ goto error;
+ }
+
+ /* Transmit the buffers. */
+ err = memif_tx_burst(conn, qid, buffers, num_enqueued, &num_transmitted);
+ if (err != MEMIF_ERR_SUCCESS) {
+ INFO("memif_tx_burst: %s", memif_strerror(err));
+ goto error;
+ }
+
+Custom Event Polling
+--------------------
+
+Libmemif can be integrated into your applications fd event polling. You
+will need to implement ``memif_control_fd_update_t`` callback and pass
+it to ``memif_socket_args.on_control_fd_update``. Now each time any file
+descriptor belonging to that socket updates, ``on_control_fd_update``
+callback is called. The file descriptor and event type is passed in
+``memif_fd_event_t``. It also contains private context that is
+associated with this fd. When event is polled on the fd you need to call
+``memif_control_fd_handler`` and pass the event type and private context
+associated with the fd.
+
+Multi Threading
+---------------
+
+Connection establishment
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Memif sockets should not be handled in parallel. Instead each thread
+should have it’s own socket. However the UNIX socket can be the same. In
+case of non-listener socket, it’s straight forward, just create the
+socket using the same path. In case of listener socket, the polling
+should be done by single thread. > The socket becomes listener once a
+Master interface is assigned to it.
+
+Packet handling
+~~~~~~~~~~~~~~~
+
+Single queue must not be handled in parallel. Instead you can assign
+queues to threads in such way that each queue is only assigned single
+thread.
+
+Shared Memory Layout
+--------------------
+
+Please refer to `DPDK MEMIF
+documentation <http://doc.dpdk.org/guides/nics/memif.html>`__
+``'Shared memory'`` section.
diff --git a/extras/libmemif/examples/example_setup_doc.md b/extras/libmemif/examples/example_setup_doc.md
deleted file mode 100644
index 136477ddebb..00000000000
--- a/extras/libmemif/examples/example_setup_doc.md
+++ /dev/null
@@ -1,207 +0,0 @@
-## Example setup {#libmemif_example_setup_doc}
-
-#### VPP-memif master icmp_responder slave
-
-> Libmemif example app(s) use memif default socket file: `/run/vpp/memif.sock`.
-
-Run VPP and icmpr-epoll example (default example when running in container).
-
-> Other examples work similar to icmpr-epoll. Brief explanation can be found in @ref libmemif_examples_doc .
-
-VPP-side config:
-```
-DBGvpp# create interface memif id 0 master
-DBGvpp# set int state memif0/0 up
-DBGvpp# set int ip address memif0/0 192.168.1.1/24
-```
-icmpr-epoll:
-```
-conn 0 0
-```
-Memif in slave mode will try to connect every 2 seconds. If connection establishment is successful, a message will show.
-```
-INFO: memif connected!
-```
-> Error messages like "unmatched interface id" are printed only in debug mode.
-
-Check connected status.
-Use show command in icmpr-epoll:
-```
-show
-MEMIF DETAILS
-==============================
-interface index: 0
- interface ip: 192.168.1.2
- interface name: memif_connection
- app name: ICMP_Responder
- remote interface name: memif0/0
- remote app name: VPP 17.10-rc0~132-g62f9cdd
- id: 0
- secret:
- role: slave
- mode: ethernet
- socket filename: /run/vpp/memif.sock
- rx queues:
- queue id: 0
- ring size: 1024
- buffer size: 2048
- tx queues:
- queue id: 0
- ring size: 1024
- buffer size: 2048
- link: up
-interface index: 1
- no connection
-
-```
-Use sh memif command in VPP:
-```
-DBGvpp# sh memif
-interface memif0/0
- remote-name "ICMP_Responder"
- remote-interface "memif_connection"
- id 0 mode ethernet file /run/vpp/memif.sock
- flags admin-up connected
- listener-fd 12 conn-fd 13
- num-s2m-rings 1 num-m2s-rings 1 buffer-size 0
- master-to-slave ring 0:
- region 0 offset 32896 ring-size 1024 int-fd 16
- head 0 tail 0 flags 0x0000 interrupts 0
- master-to-slave ring 0:
- region 0 offset 0 ring-size 1024 int-fd 15
- head 0 tail 0 flags 0x0001 interrupts 0
-```
-
-Send ping from VPP to icmpr-epoll:
-```
-DBGvpp# ping 192.168.1.2
-64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=.1888 ms
-64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=.1985 ms
-64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=.1813 ms
-64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=.1929 ms
-
-Statistics: 5 sent, 4 received, 20% packet loss
-```
-#### multiple queues VPP-memif slave icmp_responder master
-
-Run icmpr-epoll as in previous example setup.
-Run VPP with startup conf, enabling 2 worker threads.
-Example startup.conf:
-```
-unix {
- interactive
- nodaemon
- full-coredump
-}
-
-cpu {
- workers 2
-}
-```
-VPP-side config:
-```
-DBGvpp# create memif id 0 slave rx-queues 2 tx-queues 2
-DBGvpp# set int state memif0/0 up
-DBGvpp# set int ip address memif0/0 192.168.1.1/24
-```
-icmpr-epoll:
-```
-conn 0 1
-```
-When connection is established a message will print:
-```
-INFO: memif connected!
-```
-> Error messages like "unmatched interface id" are printed only in debug mode.
-
-Check connected status.
-Use show command in icmpr-epoll:
-```
-show
-MEMIF DETAILS
-==============================
-interface index: 0
- interface ip: 192.168.1.2
- interface name: memif_connection
- app name: ICMP_Responder
- remote interface name: memif0/0
- remote app name: VPP 17.10-rc0~132-g62f9cdd
- id: 0
- secret:
- role: master
- mode: ethernet
- socket filename: /run/vpp/memif.sock
- rx queues:
- queue id: 0
- ring size: 1024
- buffer size: 2048
- queue id: 1
- ring size: 1024
- buffer size: 2048
- tx queues:
- queue id: 0
- ring size: 1024
- buffer size: 2048
- queue id: 1
- ring size: 1024
- buffer size: 2048
- link: up
-interface index: 1
- no connection
-
-```
-Use sh memif command in VPP:
-```
-DBGvpp# sh memif
-interface memif0/0
- remote-name "ICMP_Responder"
- remote-interface "memif_connection"
- id 0 mode ethernet file /run/vpp/memif.sock
- flags admin-up slave connected
- listener-fd -1 conn-fd 12
- num-s2m-rings 2 num-m2s-rings 2 buffer-size 2048
- slave-to-master ring 0:
- region 0 offset 0 ring-size 1024 int-fd 14
- head 0 tail 0 flags 0x0000 interrupts 0
- slave-to-master ring 1:
- region 0 offset 32896 ring-size 1024 int-fd 15
- head 0 tail 0 flags 0x0000 interrupts 0
- slave-to-master ring 0:
- region 0 offset 65792 ring-size 1024 int-fd 16
- head 0 tail 0 flags 0x0001 interrupts 0
- slave-to-master ring 1:
- region 0 offset 98688 ring-size 1024 int-fd 17
- head 0 tail 0 flags 0x0001 interrupts 0
-
-```
-Send ping from VPP to icmpr-epoll:
-```
-DBGvpp# ping 192.168.1.2
-64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=.1439 ms
-64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=.2184 ms
-64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=.1458 ms
-64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=.1687 ms
-
-Statistics: 5 sent, 4 received, 20% packet loss
-```
-
-#### icmp_responder master icmp_responder slave
-
-> This setup creates connection between two applications using libmemif. Traffic functionality is the same as when connection to VPP. App can receive ARP/ICMP request and transmit response.
-
-Run two instances of icmpr-epoll example.
-> If not running in container, make sure folder /run/vpp/ exists before creating memif master.
-Instance 1 will be in master mode, instance 2 in slave mode.
-instance 1:
-```
-conn 0 1
-```
-instance 2:
-```
-conn 0 0
-```
-In 2 seconds, both instances should print connected! message:
-```
-INFO: memif connected!
-```
-Check peer interface names using show command.
diff --git a/extras/libmemif/examples/example_setup_doc.rst b/extras/libmemif/examples/example_setup_doc.rst
new file mode 100644
index 00000000000..76ce78dab72
--- /dev/null
+++ b/extras/libmemif/examples/example_setup_doc.rst
@@ -0,0 +1,248 @@
+.. _libmemif_example_setup_doc:
+
+Example setup
+=============
+
+VPP-memif master icmp_responder slave
+-------------------------------------
+
+ Libmemif example app(s) use memif default socket file:
+ ``/run/vpp/memif.sock``.
+
+Run VPP and icmpr-epoll example (default example when running in
+container).
+
+ Other examples work similar to icmpr-epoll. Brief explanation can be
+ found in :ref:`libmemif_examples_doc` .
+
+VPP-side config:
+
+::
+
+ DBGvpp# create interface memif id 0 master
+ DBGvpp# set int state memif0/0 up
+ DBGvpp# set int ip address memif0/0 192.168.1.1/24
+
+icmpr-epoll:
+
+::
+
+ conn 0 0
+
+Memif in slave mode will try to connect every 2 seconds. If connection
+establishment is successful, a message will show.
+
+::
+
+ INFO: memif connected!
+
+..
+
+ Error messages like “unmatched interface id” are printed only in
+ debug mode.
+
+Check connected status. Use show command in icmpr-epoll:
+
+::
+
+ show
+ MEMIF DETAILS
+ ==============================
+ interface index: 0
+ interface ip: 192.168.1.2
+ interface name: memif_connection
+ app name: ICMP_Responder
+ remote interface name: memif0/0
+ remote app name: VPP 17.10-rc0~132-g62f9cdd
+ id: 0
+ secret:
+ role: slave
+ mode: ethernet
+ socket filename: /run/vpp/memif.sock
+ rx queues:
+ queue id: 0
+ ring size: 1024
+ buffer size: 2048
+ tx queues:
+ queue id: 0
+ ring size: 1024
+ buffer size: 2048
+ link: up
+ interface index: 1
+ no connection
+
+Use sh memif command in VPP:
+
+::
+
+ DBGvpp# sh memif
+ interface memif0/0
+ remote-name "ICMP_Responder"
+ remote-interface "memif_connection"
+ id 0 mode ethernet file /run/vpp/memif.sock
+ flags admin-up connected
+ listener-fd 12 conn-fd 13
+ num-s2m-rings 1 num-m2s-rings 1 buffer-size 0
+ master-to-slave ring 0:
+ region 0 offset 32896 ring-size 1024 int-fd 16
+ head 0 tail 0 flags 0x0000 interrupts 0
+ master-to-slave ring 0:
+ region 0 offset 0 ring-size 1024 int-fd 15
+ head 0 tail 0 flags 0x0001 interrupts 0
+
+Send ping from VPP to icmpr-epoll:
+
+::
+
+ DBGvpp# ping 192.168.1.2
+ 64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=.1888 ms
+ 64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=.1985 ms
+ 64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=.1813 ms
+ 64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=.1929 ms
+
+ Statistics: 5 sent, 4 received, 20% packet loss
+
+multiple queues VPP-memif slave icmp_responder master
+-----------------------------------------------------
+
+Run icmpr-epoll as in previous example setup. Run VPP with startup conf,
+enabling 2 worker threads. Example startup.conf:
+
+::
+
+ unix {
+ interactive
+ nodaemon
+ full-coredump
+ }
+
+ cpu {
+ workers 2
+ }
+
+VPP-side config:
+
+::
+
+ DBGvpp# create memif id 0 slave rx-queues 2 tx-queues 2
+ DBGvpp# set int state memif0/0 up
+ DBGvpp# set int ip address memif0/0 192.168.1.1/24
+
+icmpr-epoll:
+
+::
+
+ conn 0 1
+
+When connection is established a message will print:
+
+::
+
+ INFO: memif connected!
+
+..
+
+ Error messages like “unmatched interface id” are printed only in
+ debug mode.
+
+Check connected status. Use show command in icmpr-epoll:
+
+::
+
+ show
+ MEMIF DETAILS
+ ==============================
+ interface index: 0
+ interface ip: 192.168.1.2
+ interface name: memif_connection
+ app name: ICMP_Responder
+ remote interface name: memif0/0
+ remote app name: VPP 17.10-rc0~132-g62f9cdd
+ id: 0
+ secret:
+ role: master
+ mode: ethernet
+ socket filename: /run/vpp/memif.sock
+ rx queues:
+ queue id: 0
+ ring size: 1024
+ buffer size: 2048
+ queue id: 1
+ ring size: 1024
+ buffer size: 2048
+ tx queues:
+ queue id: 0
+ ring size: 1024
+ buffer size: 2048
+ queue id: 1
+ ring size: 1024
+ buffer size: 2048
+ link: up
+ interface index: 1
+ no connection
+
+Use sh memif command in VPP:
+
+::
+
+ DBGvpp# sh memif
+ interface memif0/0
+ remote-name "ICMP_Responder"
+ remote-interface "memif_connection"
+ id 0 mode ethernet file /run/vpp/memif.sock
+ flags admin-up slave connected
+ listener-fd -1 conn-fd 12
+ num-s2m-rings 2 num-m2s-rings 2 buffer-size 2048
+ slave-to-master ring 0:
+ region 0 offset 0 ring-size 1024 int-fd 14
+ head 0 tail 0 flags 0x0000 interrupts 0
+ slave-to-master ring 1:
+ region 0 offset 32896 ring-size 1024 int-fd 15
+ head 0 tail 0 flags 0x0000 interrupts 0
+ slave-to-master ring 0:
+ region 0 offset 65792 ring-size 1024 int-fd 16
+ head 0 tail 0 flags 0x0001 interrupts 0
+ slave-to-master ring 1:
+ region 0 offset 98688 ring-size 1024 int-fd 17
+ head 0 tail 0 flags 0x0001 interrupts 0
+
+Send ping from VPP to icmpr-epoll:
+
+::
+
+ DBGvpp# ping 192.168.1.2
+ 64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=.1439 ms
+ 64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=.2184 ms
+ 64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=.1458 ms
+ 64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=.1687 ms
+
+ Statistics: 5 sent, 4 received, 20% packet loss
+
+icmp_responder master icmp_responder slave
+------------------------------------------
+
+ This setup creates connection between two applications using
+ libmemif. Traffic functionality is the same as when connection to
+ VPP. App can receive ARP/ICMP request and transmit response.
+
+Run two instances of icmpr-epoll example. > If not running in container,
+make sure folder /run/vpp/ exists before creating memif master. Instance
+1 will be in master mode, instance 2 in slave mode. instance 1:
+
+::
+
+ conn 0 1
+
+instance 2:
+
+::
+
+ conn 0 0
+
+In 2 seconds, both instances should print connected! message:
+
+::
+
+ INFO: memif connected!
+
+Check peer interface names using show command.
diff --git a/extras/libmemif/examples/examples_doc.md b/extras/libmemif/examples/examples_doc.md
deleted file mode 100644
index 4422d42d44b..00000000000
--- a/extras/libmemif/examples/examples_doc.md
+++ /dev/null
@@ -1,18 +0,0 @@
-## Examples {#libmemif_examples_doc}
-
-After build, root folder will contain scripts linking binary examples with library (same name as example apps). These scripts can be executed to run example apps without installing the library. Example apps binaries can be found in _libs_ filder. To run binaries directly, make sure that libmemif library is installed.
-
-#### Run in container
-
-`ligato/libmemif-sample-service` image contains built and installed libmemf. To run different examples, override docker CMD to start container in bash:
-
-```
-# docker run -it --entrypoint=/bin/bash -i --rm --name icmp-responder --hostname icmp-responder --privileged -v "/run/vpp/:/run/vpp/" ligato/libmemif-sample-service
-```
-Current WORKDIR is set to root repository directory. Example apps can be run from this directory (a script linking binary with library), or browse to `./.libs` folder and execute binary directly.
-
-Example app | Description
-------------|------------
-@ref extras/libmemif/examples/icmp_responder | Simplest implementation. Event polling is handled by libmemif. Single memif connection in slave mode is created (id 0). Use Ctrl + C to exit app. Memif receive mode: interrupt.
-@ref extras/libmemif/examples/icmp_responder-epoll (run in container by default) | Supports multiple connections and master mode. User can create/delete connections, set ip addresses, print connection information. @ref libmemif_example_setup_doc contains instructions on basic connection use cases setups. Memif receive mode: interrupt. App provides functionality to disable interrupts for specified queue/s for testing purposes. Polling mode is not implemented in this example.
-@ref extras/libmemif/examples/icmp_responder-mt) | Multi-thread example, very similar to icmpr-epoll. Packets are handled in threads assigned to specific queues. Slave mode only. Memif receive mode: polling (memif_rx_poll function), interrupt (memif_rx_interrupt function). Receive modes differ per queue.
diff --git a/extras/libmemif/examples/examples_doc.rst b/extras/libmemif/examples/examples_doc.rst
new file mode 100644
index 00000000000..3fb8c3127f8
--- /dev/null
+++ b/extras/libmemif/examples/examples_doc.rst
@@ -0,0 +1,42 @@
+.. _libmemif_examples_doc:
+
+Examples
+========
+
+After build, root folder will contain scripts linking binary examples
+with library (same name as example apps). These scripts can be executed
+to run example apps without installing the library. Example apps
+binaries can be found in *libs* folder. To run binaries directly, make
+sure that libmemif library is installed.
+
+Run in container
+----------------
+
+``ligato/libmemif-sample-service`` image contains built and installed
+libmemf. To run different examples, override docker CMD to start
+container in bash:
+
+::
+
+ # docker run -it --entrypoint=/bin/bash -i --rm --name icmp-responder --hostname icmp-responder --privileged -v "/run/vpp/:/run/vpp/" ligato/libmemif-sample-service
+
+Current WORKDIR is set to root repository directory. Example apps can be
+run from this directory (a script linking binary with library), or
+browse to ``./.libs`` folder and execute binary directly.
+
+* ``extras/libmemif/examples/icmp_responder``
+
+Simplest implementation. Event polling is handled by libmemif.
+Single memif connection in slave mode is created (id 0). Use Ctrl + C to exit app.
+Memif receive mode: interrupt.
+
+* ``extras/libmemif/examples/icmp_responder-epoll`` (run in container by default)
+
+Supports multiple connections and master mode. User can create/delete connections, set ip addresses,
+print connection information. :ref:`libmemif_example_setup_doc` contains instructions on basic
+connection use cases setups. Memif receive mode: interrupt. App provides functionality to disable
+interrupts for specified queue/s for testing purposes. Polling mode is not implemented in this example.
+
+* ``extras/libmemif/examples/icmp_responder-mt``
+
+Multi-thread example, very similar to icmpr-epoll. Packets are handled in threads assigned to specific queues. Slave mode only. Memif receive mode: polling (memif_rx_poll function), interrupt (memif_rx_interrupt function). Receive modes differ per queue.
diff --git a/extras/libmemif/libmemif_doc.md b/extras/libmemif/libmemif_doc.md
deleted file mode 100644
index ac3d6dadcfb..00000000000
--- a/extras/libmemif/libmemif_doc.md
+++ /dev/null
@@ -1,58 +0,0 @@
-Shared Memory Packet Interface (memif) Library {#libmemif_doc}
-==============================================
-
-## Introduction
-
-Shared memory packet interface (memif) provides high performance packet transmit and receive between user application and Vector Packet Processing (VPP) or multiple user applications. Using libmemif, user application can create shared memory interface in master or slave mode and connect to VPP or another application using libmemif. Once the connection is established, user application can receive or transmit packets using libmemif API.
-
-![Architecture](docs/architecture.png)
-
-## Features
-
-- [x] Slave mode
- - [x] Connect to VPP over memif
- - [x] ICMP responder example app
-- [x] Transmit/receive packets
-- [x] Interrupt mode support
-- [x] File descriptor event polling in libmemif (optional)
- - [x] Simplify file descriptor event polling (one handler for control and interrupt channel)
-- [x] Multiple connections
-- [x] Multiple queues
- - [x] Multi-thread support
-- [x] Master mode
- - [x] Multiple regions
-- [x] Loopback
-
-## Quickstart
-
-This setup will run libmemif ICMP responder example app in container. Install [docker](https://docs.docker.com/engine/installation) engine.
-Useful link: [Docker documentation](https://docs.docker.com/get-started).
-
-Build the docker image:
-```
-# docker build . -t libmemif
-```
-
-Now you should be able to see libmemif image on your local machine:
-```
-# docker images
-REPOSITORY TAG IMAGE ID CREATED SIZE
-libmemif latest 32ecc2f9d013 About a minute ago 468MB
-...
-```
-
-Run container:
-```
-# docker run -it --rm --name icmp-responder --hostname icmp-responder --privileged -v "/run/vpp/:/run/vpp/" libmemif
-```
-
-The interface will by default connect to a master interface listening on `/run/vpp/master.sock`. The example will handle ARP requests and respond to ICMPv4 requests to `192.168.1.1`.
-
-Continue with @ref libmemif_example_setup which contains instructions on how to set up connection between icmpr-epoll example app and VPP-memif.
-
-#### Next steps
-
-- @subpage libmemif_build_doc
-- @subpage libmemif_examples_doc
-- @subpage libmemif_example_setup_doc
-- @subpage libmemif_gettingstarted_doc
diff --git a/extras/libmemif/libmemif_doc.rst b/extras/libmemif/libmemif_doc.rst
new file mode 100644
index 00000000000..a6478cfa89e
--- /dev/null
+++ b/extras/libmemif/libmemif_doc.rst
@@ -0,0 +1,67 @@
+.. _libmemif_doc:
+
+Shared Memory Packet Interface (memif) Library
+==============================================
+
+Features
+--------
+
+- ✅ Slave mode
+
+ - ✅ Connect to VPP over memif
+ - ✅ ICMP responder example app
+
+- ✅ Transmit/receive packets
+- ✅ Interrupt mode support
+- ✅ File descriptor event polling in libmemif (optional)
+
+ - ✅ Simplify file descriptor event polling (one handler for control
+ and interrupt channel)
+
+- ✅ Multiple connections
+- ✅ Multiple queues
+
+ - ✅ Multi-thread support
+
+- ✅ Master mode
+
+ - ✅ Multiple regions
+
+- ✅ Loopback
+
+Quickstart
+----------
+
+This setup will run libmemif ICMP responder example app in container.
+Install `docker <https://docs.docker.com/engine/installation>`__ engine.
+Useful link: `Docker
+documentation <https://docs.docker.com/get-started>`__.
+
+Build the docker image:
+
+::
+
+ # docker build . -t libmemif
+
+Now you should be able to see libmemif image on your local machine:
+
+::
+
+ # docker images
+ REPOSITORY TAG IMAGE ID CREATED SIZE
+ libmemif latest 32ecc2f9d013 About a minute ago 468MB
+ ...
+
+Run container:
+
+::
+
+ # docker run -it --rm --name icmp-responder --hostname icmp-responder --privileged -v "/run/vpp/:/run/vpp/" libmemif
+
+The interface will by default connect to a master interface listening on
+``/run/vpp/master.sock``. The example will handle ARP requests and
+respond to ICMPv4 requests to ``192.168.1.1``.
+
+Continue with :ref:`libmemif_example_setup_doc` which contains instructions on
+how to set up connection between icmpr-epoll example app and VPP-memif.
+