DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/3] additional sample app guides
@ 2015-02-25 19:45 John McNamara
  2015-02-25 19:46 ` [dpdk-dev] [PATCH 1/3] examples/skeleton: minor refactoring to help documentation John McNamara
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: John McNamara @ 2015-02-25 19:45 UTC (permalink / raw)
  To: dev

This patchset includes two new sample app guides. 

The first is for the existing basic forwarding/skeleton application. 

The second is for the recently added rxtx_callbacks sample application.



John McNamara (3):
  examples/skeleton: minor refactoring to help documentation
  doc: add docs for basic forwarding skeleton app
  doc: add docs for the rxtx_callbacks sample app

 MAINTAINERS                                 |    4 +
 doc/guides/sample_app_ug/index.rst          |    4 +-
 doc/guides/sample_app_ug/rxtx_callbacks.rst |  251 ++++++++++++++++++++
 doc/guides/sample_app_ug/skeleton.rst       |  338 +++++++++++++++++++++++++++
 examples/skeleton/basicfwd.c                |   77 +++++--
 5 files changed, 653 insertions(+), 21 deletions(-)
 create mode 100644 doc/guides/sample_app_ug/rxtx_callbacks.rst
 create mode 100644 doc/guides/sample_app_ug/skeleton.rst

-- 
1.7.4.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [dpdk-dev] [PATCH 1/3] examples/skeleton: minor refactoring to help documentation
  2015-02-25 19:45 [dpdk-dev] [PATCH 0/3] additional sample app guides John McNamara
@ 2015-02-25 19:46 ` John McNamara
  2015-03-02 19:02   ` Butler, Siobhan A
  2015-02-25 19:46 ` [dpdk-dev] [PATCH 2/3] doc: add docs for basic forwarding skeleton app John McNamara
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: John McNamara @ 2015-02-25 19:46 UTC (permalink / raw)
  To: dev

Minor refactoring and comments to make the sample app and
code examples clearer for the sample app guide.

Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
 examples/skeleton/basicfwd.c |   77 +++++++++++++++++++++++++++++++-----------
 1 files changed, 57 insertions(+), 20 deletions(-)

diff --git a/examples/skeleton/basicfwd.c b/examples/skeleton/basicfwd.c
index 6aa931e..1bce6e7 100644
--- a/examples/skeleton/basicfwd.c
+++ b/examples/skeleton/basicfwd.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -48,12 +48,14 @@
 #define BURST_SIZE 32
 
 static const struct rte_eth_conf port_conf_default = {
-	.rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, },
+	.rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
 };
 
+/* basicfwd.c: Basic DPDK skeleton forwarding example. */
+
 /*
- * Initialises a given port using global settings and with the rx buffers
- * coming from the mbuf_pool passed as parameter
+ * Initializes a given port using global settings and with the RX buffers
+ * coming from the mbuf_pool passed as a parameter.
  */
 static inline int
 port_init(uint8_t port, struct rte_mempool *mbuf_pool)
@@ -66,10 +68,12 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool)
 	if (port >= rte_eth_dev_count())
 		return -1;
 
+	/* Configure the Ethernet device. */
 	retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
 	if (retval != 0)
 		return retval;
 
+	/* Allocate and set up 1 RX queue per Ethernet port. */
 	for (q = 0; q < rx_rings; q++) {
 		retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
 				rte_eth_dev_socket_id(port), NULL, mbuf_pool);
@@ -77,6 +81,7 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool)
 			return retval;
 	}
 
+	/* Allocate and set up 1 TX queue per Ethernet port. */
 	for (q = 0; q < tx_rings; q++) {
 		retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
 				rte_eth_dev_socket_id(port), NULL);
@@ -84,33 +89,41 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool)
 			return retval;
 	}
 
-	retval  = rte_eth_dev_start(port);
+	/* Start the Ethernet port. */
+	retval = rte_eth_dev_start(port);
 	if (retval < 0)
 		return retval;
 
+	/* Display the port MAC address. */
 	struct ether_addr addr;
 	rte_eth_macaddr_get(port, &addr);
-	printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
-			" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
+	printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
+			   " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
 			(unsigned)port,
 			addr.addr_bytes[0], addr.addr_bytes[1],
 			addr.addr_bytes[2], addr.addr_bytes[3],
 			addr.addr_bytes[4], addr.addr_bytes[5]);
 
+	/* Enable RX in promiscuous mode for the Ethernet device. */
 	rte_eth_promiscuous_enable(port);
 
 	return 0;
 }
 
 /*
- * Main thread that does the work, reading from INPUT_PORT
- * and writing to OUTPUT_PORT
+ * The lcore main. This is the main thread that does the work, reading from
+ * an input port and writing to an output port.
  */
-static  __attribute__((noreturn)) void
+static __attribute__((noreturn)) void
 lcore_main(void)
 {
 	const uint8_t nb_ports = rte_eth_dev_count();
 	uint8_t port;
+
+	/*
+	 * Check that the port is on the same NUMA node as the polling thread
+	 * for best performance.
+	 */
 	for (port = 0; port < nb_ports; port++)
 		if (rte_eth_dev_socket_id(port) > 0 &&
 				rte_eth_dev_socket_id(port) !=
@@ -121,15 +134,28 @@ lcore_main(void)
 
 	printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n",
 			rte_lcore_id());
+
+	/* Run until the application is quit or killed. */
 	for (;;) {
+		/*
+		 * Receive packets on a port and forward them on the paired
+		 * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc.
+		 */
 		for (port = 0; port < nb_ports; port++) {
+
+			/* Get burst of RX packets, from first port of pair. */
 			struct rte_mbuf *bufs[BURST_SIZE];
 			const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
 					bufs, BURST_SIZE);
+
 			if (unlikely(nb_rx == 0))
 				continue;
+
+			/* Send burst of TX packets, to second port of pair. */
 			const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
 					bufs, nb_rx);
+
+			/* Free any unsent packets. */
 			if (unlikely(nb_tx < nb_rx)) {
 				uint16_t buf;
 				for (buf = nb_tx; buf < nb_rx; buf++)
@@ -139,7 +165,10 @@ lcore_main(void)
 	}
 }
 
-/* Main function, does initialisation and calls the per-lcore functions */
+/*
+ * The main function, which does initialization and calls the per-lcore
+ * functions.
+ */
 int
 main(int argc, char *argv[])
 {
@@ -147,36 +176,44 @@ main(int argc, char *argv[])
 	unsigned nb_ports;
 	uint8_t portid;
 
-	/* init EAL */
+	/* Initialize the Environment Abstraction Layer (EAL). */
 	int ret = rte_eal_init(argc, argv);
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+
 	argc -= ret;
 	argv += ret;
 
+	/* Check that there is an even number of ports to send/receive on. */
 	nb_ports = rte_eth_dev_count();
 	if (nb_ports < 2 || (nb_ports & 1))
 		rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");
 
-	mbuf_pool = rte_mempool_create("MBUF_POOL", NUM_MBUFS * nb_ports,
-				       MBUF_SIZE, MBUF_CACHE_SIZE,
+	/* Creates a new mempool in memory to hold the mbufs. */
+	mbuf_pool = rte_mempool_create("MBUF_POOL",
+				       NUM_MBUFS * nb_ports,
+				       MBUF_SIZE,
+				       MBUF_CACHE_SIZE,
 				       sizeof(struct rte_pktmbuf_pool_private),
 				       rte_pktmbuf_pool_init, NULL,
-				       rte_pktmbuf_init, NULL,
-				       rte_socket_id(), 0);
+				       rte_pktmbuf_init,      NULL,
+				       rte_socket_id(),
+				       0);
+
 	if (mbuf_pool == NULL)
 		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
 
-	/* initialize all ports */
+	/* Initialize all ports. */
 	for (portid = 0; portid < nb_ports; portid++)
 		if (port_init(portid, mbuf_pool) != 0)
-			rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8"\n",
+			rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n",
 					portid);
 
 	if (rte_lcore_count() > 1)
-		printf("\nWARNING: Too much enabled lcores - App uses only 1 lcore\n");
+		printf("\nWARNING: Too many lcores enabled. Only 1 used.\n");
 
-	/* call lcore_main on master core only */
+	/* Call lcore_main on the master core only. */
 	lcore_main();
+
 	return 0;
 }
-- 
1.7.4.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [dpdk-dev] [PATCH 2/3] doc: add docs for basic forwarding skeleton app
  2015-02-25 19:45 [dpdk-dev] [PATCH 0/3] additional sample app guides John McNamara
  2015-02-25 19:46 ` [dpdk-dev] [PATCH 1/3] examples/skeleton: minor refactoring to help documentation John McNamara
@ 2015-02-25 19:46 ` John McNamara
  2015-02-25 19:46 ` [dpdk-dev] [PATCH 3/3] doc: add docs for the rxtx_callbacks sample app John McNamara
  2015-02-27  9:44 ` [dpdk-dev] [PATCH 0/3] additional sample app guides De Lara Guarch, Pablo
  3 siblings, 0 replies; 8+ messages in thread
From: John McNamara @ 2015-02-25 19:46 UTC (permalink / raw)
  To: dev

Added a sample application guide for the basic forwarding
/skeleton app.

Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
 MAINTAINERS                           |    3 +
 doc/guides/sample_app_ug/index.rst    |    3 +-
 doc/guides/sample_app_ug/skeleton.rst |  338 +++++++++++++++++++++++++++++++++
 3 files changed, 343 insertions(+), 1 deletions(-)
 create mode 100644 doc/guides/sample_app_ug/skeleton.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 349ad2b..86c1c6b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -444,7 +444,10 @@ M: Bruce Richardson <bruce.richardson@intel.com>
 M: John McNamara <john.mcnamara@intel.com>
 F: examples/rxtx_callbacks/
 
+M: Bruce Richardson <bruce.richardson@intel.com>
+M: John McNamara <john.mcnamara@intel.com>
 F: examples/skeleton/
+F: doc/guides/sample_app_ug/skeleton.rst
 
 F: examples/vmdq/
 F: examples/vmdq_dcb/
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index 5720181..4e9d59b 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+    Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -43,6 +43,7 @@ Sample Applications User Guide
     cmd_line
     exception_path
     hello_world
+    skeleton
     ip_frag
     ipv4_multicast
     ip_reassembly
diff --git a/doc/guides/sample_app_ug/skeleton.rst b/doc/guides/sample_app_ug/skeleton.rst
new file mode 100644
index 0000000..e832c13
--- /dev/null
+++ b/doc/guides/sample_app_ug/skeleton.rst
@@ -0,0 +1,338 @@
+..  BSD LICENSE
+    Copyright(c) 2015 Intel Corporation. All rights reserved.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+    * Neither the name of Intel Corporation nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Basic Forwarding Sample Application
+===================================
+
+The Basic Forwarding sample application is a simple *skeleton* example of a
+forwarding application.
+
+It is intended as a demonstration of the basic components of a DPDK forwarding
+application. For more detailed implementations see the L2 and L3 forwarding
+sample applications.
+
+
+Compiling the Application
+-------------------------
+
+To compile the application export the path to the DPDK source tree and go to
+the example directory:
+
+.. code-block:: console
+
+    export RTE_SDK=/path/to/rte_sdk
+
+    cd ${RTE_SDK}/examples/skeleton
+
+Set the target, for example:
+
+.. code-block:: console
+
+    export RTE_TARGET=x86_64-native-linuxapp-gcc
+
+See the *DPDK Getting Started* Guide for possible ``RTE_TARGET`` values.
+
+Build the application as follows:
+
+.. code-block:: console
+
+    make
+
+
+Running the Application
+-----------------------
+
+To run the example in a ``linuxapp`` environment:
+
+.. code-block:: console
+
+    ./build/basicfwd -c 2 -n 4
+
+Refer to *DPDK Getting Started Guide* for general information on running
+applications and the Environment Abstraction Layer (EAL) options.
+
+
+Explanation
+-----------
+
+The following sections provide an explanation of the main components of the
+code.
+
+All DPDK library functions used in the sample code are prefixed with ``rte_``
+and are explained in detail in the *DPDK API Documentation*.
+
+
+The Main Function
+~~~~~~~~~~~~~~~~~
+
+The ``main()`` function performs the initialization and calls the execution
+threads for each lcore.
+
+The first task is to initialize the Environment Abstraction Layer (EAL).  The
+``argc`` and ``argv`` arguments are provided to the ``rte_eal_init()``
+function. The value returned is the number of parsed arguments:
+
+.. code-block:: c
+
+    int ret = rte_eal_init(argc, argv);
+    if (ret < 0)
+        rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+
+
+The ``main()`` also allocates a mempool to hold the mbufs (Message Buffers)
+used by the application:
+
+.. code-block:: c
+
+    mbuf_pool = rte_mempool_create("MBUF_POOL",
+                                   NUM_MBUFS * nb_ports,
+                                   MBUF_SIZE,
+                                   MBUF_CACHE_SIZE,
+                                   sizeof(struct rte_pktmbuf_pool_private),
+                                   rte_pktmbuf_pool_init, NULL,
+                                   rte_pktmbuf_init,      NULL,
+                                   rte_socket_id(),
+                                   0);
+
+Mbufs are the packet buffer structure used by DPDK. They are explained in
+detail in the "Mbuf Library" section of the *DPDK Programmer's Guide*.
+
+The ``main()`` function also initializes all the ports using the user defined
+``port_init()`` function which is explained in the next section:
+
+.. code-block:: c
+
+    for (portid = 0; portid < nb_ports; portid++) {
+        if (port_init(portid, mbuf_pool) != 0) {
+            rte_exit(EXIT_FAILURE,
+                     "Cannot init port %" PRIu8 "\n", portid);
+        }
+    }
+
+
+Once the initialization is complete, the application is ready to launch a
+function on an lcore. In this example ``lcore_main()`` is called on a single
+lcore.
+
+
+.. code-block:: c
+
+	lcore_main();
+
+The ``lcore_main()`` function is explained below.
+
+
+
+The Port Initialization  Function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The main functional part of the port initialization used in the Basic
+Forwarding application is shown below:
+
+.. code-block:: c
+
+    static inline int
+    port_init(uint8_t port, struct rte_mempool *mbuf_pool)
+    {
+        struct rte_eth_conf port_conf = port_conf_default;
+        const uint16_t rx_rings = 1, tx_rings = 1;
+        struct ether_addr addr;
+        int retval;
+        uint16_t q;
+
+        if (port >= rte_eth_dev_count())
+            return -1;
+
+        /* Configure the Ethernet device. */
+        retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
+        if (retval != 0)
+            return retval;
+
+        /* Allocate and set up 1 RX queue per Ethernet port. */
+        for (q = 0; q < rx_rings; q++) {
+            retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
+                    rte_eth_dev_socket_id(port), NULL, mbuf_pool);
+            if (retval < 0)
+                return retval;
+        }
+
+        /* Allocate and set up 1 TX queue per Ethernet port. */
+        for (q = 0; q < tx_rings; q++) {
+            retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
+                    rte_eth_dev_socket_id(port), NULL);
+            if (retval < 0)
+                return retval;
+        }
+
+        /* Start the Ethernet port. */
+        retval = rte_eth_dev_start(port);
+        if (retval < 0)
+            return retval;
+
+        /* Enable RX in promiscuous mode for the Ethernet device. */
+        rte_eth_promiscuous_enable(port);
+
+        return 0;
+    }
+
+The Ethernet ports are configured with default settings using the
+``rte_eth_dev_configure()`` function and the ``port_conf_default`` struct:
+
+.. code-block:: c
+
+    static const struct rte_eth_conf port_conf_default = {
+        .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
+    };
+
+For this example the ports are set up with 1 RX and 1 TX queue using the
+``rte_eth_rx_queue_setup()`` and ``rte_eth_tx_queue_setup()`` functions.
+
+The Ethernet port is then started:
+
+.. code-block:: c
+
+        retval  = rte_eth_dev_start(port);
+
+
+Finally the RX port is set in promiscuous mode:
+
+.. code-block:: c
+
+        rte_eth_promiscuous_enable(port);
+
+
+The Lcores Main
+~~~~~~~~~~~~~~~
+
+As we saw above the ``main()`` function calls an application function on the
+available lcores. For the Basic Forwarding application the lcore function
+looks like the following:
+
+.. code-block:: c
+
+    static __attribute__((noreturn)) void
+    lcore_main(void)
+    {
+        const uint8_t nb_ports = rte_eth_dev_count();
+        uint8_t port;
+
+        /*
+         * Check that the port is on the same NUMA node as the polling thread
+         * for best performance.
+         */
+        for (port = 0; port < nb_ports; port++)
+            if (rte_eth_dev_socket_id(port) > 0 &&
+                    rte_eth_dev_socket_id(port) !=
+                            (int)rte_socket_id())
+                printf("WARNING, port %u is on remote NUMA node to "
+                        "polling thread.\n\tPerformance will "
+                        "not be optimal.\n", port);
+
+        printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n",
+                rte_lcore_id());
+
+        /* Run until the application is quit or killed. */
+        for (;;) {
+            /*
+             * Receive packets on a port and forward them on the paired
+             * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc.
+             */
+            for (port = 0; port < nb_ports; port++) {
+
+                /* Get burst of RX packets, from first port of pair. */
+                struct rte_mbuf *bufs[BURST_SIZE];
+                const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
+                        bufs, BURST_SIZE);
+
+                if (unlikely(nb_rx == 0))
+                    continue;
+
+                /* Send burst of TX packets, to second port of pair. */
+                const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
+                        bufs, nb_rx);
+
+                /* Free any unsent packets. */
+                if (unlikely(nb_tx < nb_rx)) {
+                    uint16_t buf;
+                    for (buf = nb_tx; buf < nb_rx; buf++)
+                        rte_pktmbuf_free(bufs[buf]);
+                }
+            }
+        }
+    }
+
+
+The main work of the application is done within the loop:
+
+.. code-block:: c
+
+        for (;;) {
+            for (port = 0; port < nb_ports; port++) {
+
+                /* Get burst of RX packets, from first port of pair. */
+                struct rte_mbuf *bufs[BURST_SIZE];
+                const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
+                        bufs, BURST_SIZE);
+
+                if (unlikely(nb_rx == 0))
+                    continue;
+
+                /* Send burst of TX packets, to second port of pair. */
+                const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
+                        bufs, nb_rx);
+
+                /* Free any unsent packets. */
+                if (unlikely(nb_tx < nb_rx)) {
+                    uint16_t buf;
+                    for (buf = nb_tx; buf < nb_rx; buf++)
+                        rte_pktmbuf_free(bufs[buf]);
+                }
+            }
+        }
+
+Packets are received in bursts on the RX ports and transmitted in bursts on
+the TX ports. The ports are grouped in pairs with a simple mapping scheme
+using the an XOR on the port number::
+
+    0 -> 1
+    1 -> 0
+
+    2 -> 3
+    3 -> 2
+
+    etc.
+
+The ``rte_eth_tx_burst()`` function frees the memory buffers of packets that
+are transmitted. If packets fail to transmit, ``(nb_tx < nb_rx)``, then they
+must be freed explicitly using ``rte_pktmbuf_free()``.
+
+The forwarding loop can be interrupted and the application closed using
+``Ctrl-C``.
-- 
1.7.4.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [dpdk-dev] [PATCH 3/3] doc: add docs for the rxtx_callbacks sample app
  2015-02-25 19:45 [dpdk-dev] [PATCH 0/3] additional sample app guides John McNamara
  2015-02-25 19:46 ` [dpdk-dev] [PATCH 1/3] examples/skeleton: minor refactoring to help documentation John McNamara
  2015-02-25 19:46 ` [dpdk-dev] [PATCH 2/3] doc: add docs for basic forwarding skeleton app John McNamara
@ 2015-02-25 19:46 ` John McNamara
  2015-03-02 19:02   ` Butler, Siobhan A
  2015-02-27  9:44 ` [dpdk-dev] [PATCH 0/3] additional sample app guides De Lara Guarch, Pablo
  3 siblings, 1 reply; 8+ messages in thread
From: John McNamara @ 2015-02-25 19:46 UTC (permalink / raw)
  To: dev

Added a sample application guide for the rxtx_callbacks app.

Signed-off-by: John McNamara <john.mcnamara@intel.com>
---
 MAINTAINERS                                 |    1 +
 doc/guides/sample_app_ug/index.rst          |    1 +
 doc/guides/sample_app_ug/rxtx_callbacks.rst |  251 +++++++++++++++++++++++++++
 3 files changed, 253 insertions(+), 0 deletions(-)
 create mode 100644 doc/guides/sample_app_ug/rxtx_callbacks.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 86c1c6b..2ddb312 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -443,6 +443,7 @@ F: doc/guides/sample_app_ug/quota_watermark.rst
 M: Bruce Richardson <bruce.richardson@intel.com>
 M: John McNamara <john.mcnamara@intel.com>
 F: examples/rxtx_callbacks/
+F: doc/guides/sample_app_ug/rxtx_callbacks.rst
 
 M: Bruce Richardson <bruce.richardson@intel.com>
 M: John McNamara <john.mcnamara@intel.com>
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index 4e9d59b..4a86459 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -44,6 +44,7 @@ Sample Applications User Guide
     exception_path
     hello_world
     skeleton
+    rxtx_callbacks
     ip_frag
     ipv4_multicast
     ip_reassembly
diff --git a/doc/guides/sample_app_ug/rxtx_callbacks.rst b/doc/guides/sample_app_ug/rxtx_callbacks.rst
new file mode 100644
index 0000000..9df57ed
--- /dev/null
+++ b/doc/guides/sample_app_ug/rxtx_callbacks.rst
@@ -0,0 +1,251 @@
+..  BSD LICENSE
+    Copyright(c) 2015 Intel Corporation. All rights reserved.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+    * Neither the name of Intel Corporation nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+RX/TX Callbacks Sample Application
+==================================
+
+The RX/TX Callbacks sample application is a packet forwarding application that
+demonstrates the use of user defined callbacks on received and transmitted
+packets. The application performs a simple latency check, using callbacks, to
+determine the time packets spend within the application.
+
+In the sample application a user defined callback is applied to all received
+packets to add a timestamp. A separate callback is applied to all packets
+prior to transmission to calculate the elapsed time, in CPU cycles.
+
+
+Compiling the Application
+-------------------------
+
+To compile the application export the path to the DPDK source tree and go to
+the example directory:
+
+.. code-block:: console
+
+    export RTE_SDK=/path/to/rte_sdk
+
+    cd ${RTE_SDK}/examples/rxtx_callbacks
+
+
+Set the target, for example:
+
+.. code-block:: console
+
+    export RTE_TARGET=x86_64-native-linuxapp-gcc
+
+See the *DPDK Getting Started* Guide for possible ``RTE_TARGET`` values.
+
+The callbacks feature requires that the ``CONFIG_RTE_ETHDEV_RXTX_CALLBACKS``
+setting is on in the ``config/common_`` config file that applies to the
+target. This is generally on by default:
+
+.. code-block:: console
+
+    CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
+
+Build the application as follows:
+
+.. code-block:: console
+
+    make
+
+
+Running the Application
+-----------------------
+
+To run the example in a ``linuxapp`` environment:
+
+.. code-block:: console
+
+    ./build/rxtx_callbacks -c 2 -n 4
+
+Refer to *DPDK Getting Started Guide* for general information on running
+applications and the Environment Abstraction Layer (EAL) options.
+
+
+
+Explanation
+-----------
+
+The ``rxtx_callbacks`` application is mainly a simple forwarding application
+based on the :doc:`skeleton`. See that section of the documentation for more
+details of the forwarding part of the application.
+
+The sections below explain the additional RX/TX callback code.
+
+
+The Main Function
+~~~~~~~~~~~~~~~~~
+
+The ``main()`` function performs the application initialization and calls the
+execution threads for each lcore. This function is effectively identical to
+the ``main()`` function explained in :doc:`skeleton`.
+
+The ``lcore_main()`` function is also identical.
+
+The main difference is in the user defined ``port_init()`` function where the
+callbacks are added. This is explained in the next section:
+
+
+The Port Initialization  Function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The main functional part of the port initialization is shown below with
+comments:
+
+.. code-block:: c
+
+    static inline int
+    port_init(uint8_t port, struct rte_mempool *mbuf_pool)
+    {
+        struct rte_eth_conf port_conf = port_conf_default;
+        const uint16_t rx_rings = 1, tx_rings = 1;
+        struct ether_addr addr;
+        int retval;
+        uint16_t q;
+
+        if (port >= rte_eth_dev_count())
+            return -1;
+
+        /* Configure the Ethernet device. */
+        retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
+        if (retval != 0)
+            return retval;
+
+        /* Allocate and set up 1 RX queue per Ethernet port. */
+        for (q = 0; q < rx_rings; q++) {
+            retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
+                    rte_eth_dev_socket_id(port), NULL, mbuf_pool);
+            if (retval < 0)
+                return retval;
+        }
+
+        /* Allocate and set up 1 TX queue per Ethernet port. */
+        for (q = 0; q < tx_rings; q++) {
+            retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
+                    rte_eth_dev_socket_id(port), NULL);
+            if (retval < 0)
+                return retval;
+        }
+
+        /* Start the Ethernet port. */
+        retval = rte_eth_dev_start(port);
+        if (retval < 0)
+            return retval;
+
+        /* Enable RX in promiscuous mode for the Ethernet device. */
+        rte_eth_promiscuous_enable(port);
+
+
+        /* Add the callbacks for RX and TX.*/
+        rte_eth_add_rx_callback(port, 0, add_timestamps, NULL);
+        rte_eth_add_tx_callback(port, 0, calc_latency, NULL);
+
+        return 0;
+    }
+
+
+The RX and TX callbacks are added to the ports/queues as function pointers:
+
+.. code-block:: c
+
+        rte_eth_add_rx_callback(port, 0, add_timestamps, NULL);
+        rte_eth_add_tx_callback(port, 0, calc_latency,   NULL);
+
+More than one callback can be added and additional information can be passed
+to callback function pointers as a ``void*``. In the examples above ``NULL``
+is used.
+
+The ``add_timestamps()`` and ``calc_latency()`` functions are explained below.
+
+
+The add_timestamps() Callback
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``add_timestamps()`` callback is added to the RX port and is applied to
+all packets received:
+
+.. code-block:: c
+
+    static uint16_t
+    add_timestamps(uint8_t port __rte_unused, uint16_t qidx __rte_unused,
+            struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused)
+    {
+        unsigned i;
+        uint64_t now = rte_rdtsc();
+
+        for (i = 0; i < nb_pkts; i++)
+            pkts[i]->udata64 = now;
+
+        return nb_pkts;
+    }
+
+The DPDK function ``rte_rdtsc()`` is used to add a cycle count timestamp to
+each packet (see the *cycles* section of the *DPDK API Documentation* for
+details).
+
+
+The calc_latency() Callback
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``calc_latency()`` callback is added to the TX port and is applied to all
+packets prior to transmission:
+
+.. code-block:: c
+
+    static uint16_t
+    calc_latency(uint8_t port __rte_unused, uint16_t qidx __rte_unused,
+            struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused)
+    {
+        uint64_t cycles = 0;
+        uint64_t now = rte_rdtsc();
+        unsigned i;
+
+        for (i = 0; i < nb_pkts; i++)
+            cycles += now - pkts[i]->udata64;
+
+        latency_numbers.total_cycles += cycles;
+        latency_numbers.total_pkts   += nb_pkts;
+
+        if (latency_numbers.total_pkts > (100 * 1000 * 1000ULL)) {
+            printf("Latency = %"PRIu64" cycles\n",
+                    latency_numbers.total_cycles / latency_numbers.total_pkts);
+
+            latency_numbers.total_cycles = latency_numbers.total_pkts = 0;
+        }
+
+        return nb_pkts;
+    }
+
+The ``calc_latency()`` function accumulates the total number of packets and
+the total number of cycles used. Once more than 100 million packets have been
+transmitted the average cycle count per packet is printed out and the counters
+are reset.
-- 
1.7.4.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [dpdk-dev] [PATCH 0/3] additional sample app guides
  2015-02-25 19:45 [dpdk-dev] [PATCH 0/3] additional sample app guides John McNamara
                   ` (2 preceding siblings ...)
  2015-02-25 19:46 ` [dpdk-dev] [PATCH 3/3] doc: add docs for the rxtx_callbacks sample app John McNamara
@ 2015-02-27  9:44 ` De Lara Guarch, Pablo
  2015-03-17 17:02   ` Thomas Monjalon
  3 siblings, 1 reply; 8+ messages in thread
From: De Lara Guarch, Pablo @ 2015-02-27  9:44 UTC (permalink / raw)
  To: Mcnamara, John, dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of John McNamara
> Sent: Wednesday, February 25, 2015 7:46 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH 0/3] additional sample app guides
> 
> This patchset includes two new sample app guides.
> 
> The first is for the existing basic forwarding/skeleton application.
> 
> The second is for the recently added rxtx_callbacks sample application.
> 
> 
> 
> John McNamara (3):
>   examples/skeleton: minor refactoring to help documentation
>   doc: add docs for basic forwarding skeleton app
>   doc: add docs for the rxtx_callbacks sample app
> 
>  MAINTAINERS                                 |    4 +
>  doc/guides/sample_app_ug/index.rst          |    4 +-
>  doc/guides/sample_app_ug/rxtx_callbacks.rst |  251
> ++++++++++++++++++++
>  doc/guides/sample_app_ug/skeleton.rst       |  338
> +++++++++++++++++++++++++++
>  examples/skeleton/basicfwd.c                |   77 +++++--
>  5 files changed, 653 insertions(+), 21 deletions(-)
>  create mode 100644 doc/guides/sample_app_ug/rxtx_callbacks.rst
>  create mode 100644 doc/guides/sample_app_ug/skeleton.rst
> 
> --
> 1.7.4.1

Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [dpdk-dev] [PATCH 1/3] examples/skeleton: minor refactoring to help documentation
  2015-02-25 19:46 ` [dpdk-dev] [PATCH 1/3] examples/skeleton: minor refactoring to help documentation John McNamara
@ 2015-03-02 19:02   ` Butler, Siobhan A
  0 siblings, 0 replies; 8+ messages in thread
From: Butler, Siobhan A @ 2015-03-02 19:02 UTC (permalink / raw)
  To: Mcnamara, John, dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of John McNamara
> Sent: Wednesday, February 25, 2015 7:46 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH 1/3] examples/skeleton: minor refactoring to
> help documentation
> 
> Minor refactoring and comments to make the sample app and code
> examples clearer for the sample app guide.
> 
> Signed-off-by: John McNamara <john.mcnamara@intel.com>
> ---
>  examples/skeleton/basicfwd.c |   77
> +++++++++++++++++++++++++++++++-----------
>  1 files changed, 57 insertions(+), 20 deletions(-)
> 
> diff --git a/examples/skeleton/basicfwd.c b/examples/skeleton/basicfwd.c
> index 6aa931e..1bce6e7 100644
> --- a/examples/skeleton/basicfwd.c
> +++ b/examples/skeleton/basicfwd.c
> @@ -1,7 +1,7 @@
>  /*-
>   *   BSD LICENSE
>   *
> - *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
> + *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
>   *   All rights reserved.
>   *
>   *   Redistribution and use in source and binary forms, with or without
> @@ -48,12 +48,14 @@
>  #define BURST_SIZE 32
> 
>  static const struct rte_eth_conf port_conf_default = {
> -	.rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, },
> +	.rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
>  };
> 
> +/* basicfwd.c: Basic DPDK skeleton forwarding example. */
> +
>  /*
> - * Initialises a given port using global settings and with the rx buffers
> - * coming from the mbuf_pool passed as parameter
> + * Initializes a given port using global settings and with the RX
> + buffers
> + * coming from the mbuf_pool passed as a parameter.
>   */
>  static inline int
>  port_init(uint8_t port, struct rte_mempool *mbuf_pool) @@ -66,10 +68,12
> @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool)
>  	if (port >= rte_eth_dev_count())
>  		return -1;
> 
> +	/* Configure the Ethernet device. */
>  	retval = rte_eth_dev_configure(port, rx_rings, tx_rings,
> &port_conf);
>  	if (retval != 0)
>  		return retval;
> 
> +	/* Allocate and set up 1 RX queue per Ethernet port. */
>  	for (q = 0; q < rx_rings; q++) {
>  		retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
>  				rte_eth_dev_socket_id(port), NULL,
> mbuf_pool); @@ -77,6 +81,7 @@ port_init(uint8_t port, struct rte_mempool
> *mbuf_pool)
>  			return retval;
>  	}
> 
> +	/* Allocate and set up 1 TX queue per Ethernet port. */
>  	for (q = 0; q < tx_rings; q++) {
>  		retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
>  				rte_eth_dev_socket_id(port), NULL); @@ -
> 84,33 +89,41 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool)
>  			return retval;
>  	}
> 
> -	retval  = rte_eth_dev_start(port);
> +	/* Start the Ethernet port. */
> +	retval = rte_eth_dev_start(port);
>  	if (retval < 0)
>  		return retval;
> 
> +	/* Display the port MAC address. */
>  	struct ether_addr addr;
>  	rte_eth_macaddr_get(port, &addr);
> -	printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
> -			" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
> +	printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
> +			   " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
>  			(unsigned)port,
>  			addr.addr_bytes[0], addr.addr_bytes[1],
>  			addr.addr_bytes[2], addr.addr_bytes[3],
>  			addr.addr_bytes[4], addr.addr_bytes[5]);
> 
> +	/* Enable RX in promiscuous mode for the Ethernet device. */
>  	rte_eth_promiscuous_enable(port);
> 
>  	return 0;
>  }
> 
>  /*
> - * Main thread that does the work, reading from INPUT_PORT
> - * and writing to OUTPUT_PORT
> + * The lcore main. This is the main thread that does the work, reading
> + from
> + * an input port and writing to an output port.
>   */
> -static  __attribute__((noreturn)) void
> +static __attribute__((noreturn)) void
>  lcore_main(void)
>  {
>  	const uint8_t nb_ports = rte_eth_dev_count();
>  	uint8_t port;
> +
> +	/*
> +	 * Check that the port is on the same NUMA node as the polling
> thread
> +	 * for best performance.
> +	 */
>  	for (port = 0; port < nb_ports; port++)
>  		if (rte_eth_dev_socket_id(port) > 0 &&
>  				rte_eth_dev_socket_id(port) !=
> @@ -121,15 +134,28 @@ lcore_main(void)
> 
>  	printf("\nCore %u forwarding packets. [Ctrl+C to quit]\n",
>  			rte_lcore_id());
> +
> +	/* Run until the application is quit or killed. */
>  	for (;;) {
> +		/*
> +		 * Receive packets on a port and forward them on the paired
> +		 * port. The mapping is 0 -> 1, 1 -> 0, 2 -> 3, 3 -> 2, etc.
> +		 */
>  		for (port = 0; port < nb_ports; port++) {
> +
> +			/* Get burst of RX packets, from first port of pair. */
>  			struct rte_mbuf *bufs[BURST_SIZE];
>  			const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
>  					bufs, BURST_SIZE);
> +
>  			if (unlikely(nb_rx == 0))
>  				continue;
> +
> +			/* Send burst of TX packets, to second port of pair. */
>  			const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0,
>  					bufs, nb_rx);
> +
> +			/* Free any unsent packets. */
>  			if (unlikely(nb_tx < nb_rx)) {
>  				uint16_t buf;
>  				for (buf = nb_tx; buf < nb_rx; buf++) @@ -
> 139,7 +165,10 @@ lcore_main(void)
>  	}
>  }
> 
> -/* Main function, does initialisation and calls the per-lcore functions */
> +/*
> + * The main function, which does initialization and calls the per-lcore
> + * functions.
> + */
>  int
>  main(int argc, char *argv[])
>  {
> @@ -147,36 +176,44 @@ main(int argc, char *argv[])
>  	unsigned nb_ports;
>  	uint8_t portid;
> 
> -	/* init EAL */
> +	/* Initialize the Environment Abstraction Layer (EAL). */
>  	int ret = rte_eal_init(argc, argv);
>  	if (ret < 0)
>  		rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
> +
>  	argc -= ret;
>  	argv += ret;
> 
> +	/* Check that there is an even number of ports to send/receive on.
> */
>  	nb_ports = rte_eth_dev_count();
>  	if (nb_ports < 2 || (nb_ports & 1))
>  		rte_exit(EXIT_FAILURE, "Error: number of ports must be
> even\n");
> 
> -	mbuf_pool = rte_mempool_create("MBUF_POOL", NUM_MBUFS *
> nb_ports,
> -				       MBUF_SIZE, MBUF_CACHE_SIZE,
> +	/* Creates a new mempool in memory to hold the mbufs. */
> +	mbuf_pool = rte_mempool_create("MBUF_POOL",
> +				       NUM_MBUFS * nb_ports,
> +				       MBUF_SIZE,
> +				       MBUF_CACHE_SIZE,
>  				       sizeof(struct rte_pktmbuf_pool_private),
>  				       rte_pktmbuf_pool_init, NULL,
> -				       rte_pktmbuf_init, NULL,
> -				       rte_socket_id(), 0);
> +				       rte_pktmbuf_init,      NULL,
> +				       rte_socket_id(),
> +				       0);
> +
>  	if (mbuf_pool == NULL)
>  		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
> 
> -	/* initialize all ports */
> +	/* Initialize all ports. */
>  	for (portid = 0; portid < nb_ports; portid++)
>  		if (port_init(portid, mbuf_pool) != 0)
> -			rte_exit(EXIT_FAILURE, "Cannot init port
> %"PRIu8"\n",
> +			rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8
> "\n",
>  					portid);
> 
>  	if (rte_lcore_count() > 1)
> -		printf("\nWARNING: Too much enabled lcores - App uses
> only 1 lcore\n");
> +		printf("\nWARNING: Too many lcores enabled. Only 1
> used.\n");
> 
> -	/* call lcore_main on master core only */
> +	/* Call lcore_main on the master core only. */
>  	lcore_main();
> +
>  	return 0;
>  }
> --
> 1.7.4.1
Acked-by: Siobhan Butler <siobhan.a.butler@intel.com>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [dpdk-dev] [PATCH 3/3] doc: add docs for the rxtx_callbacks sample app
  2015-02-25 19:46 ` [dpdk-dev] [PATCH 3/3] doc: add docs for the rxtx_callbacks sample app John McNamara
@ 2015-03-02 19:02   ` Butler, Siobhan A
  0 siblings, 0 replies; 8+ messages in thread
From: Butler, Siobhan A @ 2015-03-02 19:02 UTC (permalink / raw)
  To: Mcnamara, John, dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of John McNamara
> Sent: Wednesday, February 25, 2015 7:46 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH 3/3] doc: add docs for the rxtx_callbacks sample
> app
> 
> Added a sample application guide for the rxtx_callbacks app.
> 
> Signed-off-by: John McNamara <john.mcnamara@intel.com>
> ---
>  MAINTAINERS                                 |    1 +
>  doc/guides/sample_app_ug/index.rst          |    1 +
>  doc/guides/sample_app_ug/rxtx_callbacks.rst |  251
> +++++++++++++++++++++++++++
>  3 files changed, 253 insertions(+), 0 deletions(-)  create mode 100644
> doc/guides/sample_app_ug/rxtx_callbacks.rst
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 86c1c6b..2ddb312 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -443,6 +443,7 @@ F: doc/guides/sample_app_ug/quota_watermark.rst
>  M: Bruce Richardson <bruce.richardson@intel.com>
>  M: John McNamara <john.mcnamara@intel.com>
>  F: examples/rxtx_callbacks/
> +F: doc/guides/sample_app_ug/rxtx_callbacks.rst
> 
>  M: Bruce Richardson <bruce.richardson@intel.com>
>  M: John McNamara <john.mcnamara@intel.com> diff --git
> a/doc/guides/sample_app_ug/index.rst
> b/doc/guides/sample_app_ug/index.rst
> index 4e9d59b..4a86459 100644
> --- a/doc/guides/sample_app_ug/index.rst
> +++ b/doc/guides/sample_app_ug/index.rst
> @@ -44,6 +44,7 @@ Sample Applications User Guide
>      exception_path
>      hello_world
>      skeleton
> +    rxtx_callbacks
>      ip_frag
>      ipv4_multicast
>      ip_reassembly
> diff --git a/doc/guides/sample_app_ug/rxtx_callbacks.rst
> b/doc/guides/sample_app_ug/rxtx_callbacks.rst
> new file mode 100644
> index 0000000..9df57ed
> --- /dev/null
> +++ b/doc/guides/sample_app_ug/rxtx_callbacks.rst
> @@ -0,0 +1,251 @@
> +..  BSD LICENSE
> +    Copyright(c) 2015 Intel Corporation. All rights reserved.
> +    All rights reserved.
> +
> +    Redistribution and use in source and binary forms, with or without
> +    modification, are permitted provided that the following conditions
> +    are met:
> +
> +    * Redistributions of source code must retain the above copyright
> +    notice, this list of conditions and the following disclaimer.
> +    * Redistributions in binary form must reproduce the above copyright
> +    notice, this list of conditions and the following disclaimer in
> +    the documentation and/or other materials provided with the
> +    distribution.
> +    * Neither the name of Intel Corporation nor the names of its
> +    contributors may be used to endorse or promote products derived
> +    from this software without specific prior written permission.
> +
> +    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> +    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> +    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> +    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> +    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> +    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> +    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> +    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> AND ON ANY
> +    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> +    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> +
> +
> +RX/TX Callbacks Sample Application
> +==================================
> +
> +The RX/TX Callbacks sample application is a packet forwarding
> +application that demonstrates the use of user defined callbacks on
> +received and transmitted packets. The application performs a simple
> +latency check, using callbacks, to determine the time packets spend within
> the application.
> +
> +In the sample application a user defined callback is applied to all
> +received packets to add a timestamp. A separate callback is applied to
> +all packets prior to transmission to calculate the elapsed time, in CPU cycles.
> +
> +
> +Compiling the Application
> +-------------------------
> +
> +To compile the application export the path to the DPDK source tree and
> +go to the example directory:
> +
> +.. code-block:: console
> +
> +    export RTE_SDK=/path/to/rte_sdk
> +
> +    cd ${RTE_SDK}/examples/rxtx_callbacks
> +
> +
> +Set the target, for example:
> +
> +.. code-block:: console
> +
> +    export RTE_TARGET=x86_64-native-linuxapp-gcc
> +
> +See the *DPDK Getting Started* Guide for possible ``RTE_TARGET`` values.
> +
> +The callbacks feature requires that the
> +``CONFIG_RTE_ETHDEV_RXTX_CALLBACKS``
> +setting is on in the ``config/common_`` config file that applies to the
> +target. This is generally on by default:
> +
> +.. code-block:: console
> +
> +    CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
> +
> +Build the application as follows:
> +
> +.. code-block:: console
> +
> +    make
> +
> +
> +Running the Application
> +-----------------------
> +
> +To run the example in a ``linuxapp`` environment:
> +
> +.. code-block:: console
> +
> +    ./build/rxtx_callbacks -c 2 -n 4
> +
> +Refer to *DPDK Getting Started Guide* for general information on
> +running applications and the Environment Abstraction Layer (EAL) options.
> +
> +
> +
> +Explanation
> +-----------
> +
> +The ``rxtx_callbacks`` application is mainly a simple forwarding
> +application based on the :doc:`skeleton`. See that section of the
> +documentation for more details of the forwarding part of the application.
> +
> +The sections below explain the additional RX/TX callback code.
> +
> +
> +The Main Function
> +~~~~~~~~~~~~~~~~~
> +
> +The ``main()`` function performs the application initialization and
> +calls the execution threads for each lcore. This function is
> +effectively identical to the ``main()`` function explained in :doc:`skeleton`.
> +
> +The ``lcore_main()`` function is also identical.
> +
> +The main difference is in the user defined ``port_init()`` function
> +where the callbacks are added. This is explained in the next section:
> +
> +
> +The Port Initialization  Function
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +The main functional part of the port initialization is shown below with
> +comments:
> +
> +.. code-block:: c
> +
> +    static inline int
> +    port_init(uint8_t port, struct rte_mempool *mbuf_pool)
> +    {
> +        struct rte_eth_conf port_conf = port_conf_default;
> +        const uint16_t rx_rings = 1, tx_rings = 1;
> +        struct ether_addr addr;
> +        int retval;
> +        uint16_t q;
> +
> +        if (port >= rte_eth_dev_count())
> +            return -1;
> +
> +        /* Configure the Ethernet device. */
> +        retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
> +        if (retval != 0)
> +            return retval;
> +
> +        /* Allocate and set up 1 RX queue per Ethernet port. */
> +        for (q = 0; q < rx_rings; q++) {
> +            retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
> +                    rte_eth_dev_socket_id(port), NULL, mbuf_pool);
> +            if (retval < 0)
> +                return retval;
> +        }
> +
> +        /* Allocate and set up 1 TX queue per Ethernet port. */
> +        for (q = 0; q < tx_rings; q++) {
> +            retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
> +                    rte_eth_dev_socket_id(port), NULL);
> +            if (retval < 0)
> +                return retval;
> +        }
> +
> +        /* Start the Ethernet port. */
> +        retval = rte_eth_dev_start(port);
> +        if (retval < 0)
> +            return retval;
> +
> +        /* Enable RX in promiscuous mode for the Ethernet device. */
> +        rte_eth_promiscuous_enable(port);
> +
> +
> +        /* Add the callbacks for RX and TX.*/
> +        rte_eth_add_rx_callback(port, 0, add_timestamps, NULL);
> +        rte_eth_add_tx_callback(port, 0, calc_latency, NULL);
> +
> +        return 0;
> +    }
> +
> +
> +The RX and TX callbacks are added to the ports/queues as function pointers:
> +
> +.. code-block:: c
> +
> +        rte_eth_add_rx_callback(port, 0, add_timestamps, NULL);
> +        rte_eth_add_tx_callback(port, 0, calc_latency,   NULL);
> +
> +More than one callback can be added and additional information can be
> +passed to callback function pointers as a ``void*``. In the examples
> +above ``NULL`` is used.
> +
> +The ``add_timestamps()`` and ``calc_latency()`` functions are explained
> below.
> +
> +
> +The add_timestamps() Callback
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +The ``add_timestamps()`` callback is added to the RX port and is
> +applied to all packets received:
> +
> +.. code-block:: c
> +
> +    static uint16_t
> +    add_timestamps(uint8_t port __rte_unused, uint16_t qidx
> __rte_unused,
> +            struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused)
> +    {
> +        unsigned i;
> +        uint64_t now = rte_rdtsc();
> +
> +        for (i = 0; i < nb_pkts; i++)
> +            pkts[i]->udata64 = now;
> +
> +        return nb_pkts;
> +    }
> +
> +The DPDK function ``rte_rdtsc()`` is used to add a cycle count
> +timestamp to each packet (see the *cycles* section of the *DPDK API
> +Documentation* for details).
> +
> +
> +The calc_latency() Callback
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +The ``calc_latency()`` callback is added to the TX port and is applied
> +to all packets prior to transmission:
> +
> +.. code-block:: c
> +
> +    static uint16_t
> +    calc_latency(uint8_t port __rte_unused, uint16_t qidx __rte_unused,
> +            struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused)
> +    {
> +        uint64_t cycles = 0;
> +        uint64_t now = rte_rdtsc();
> +        unsigned i;
> +
> +        for (i = 0; i < nb_pkts; i++)
> +            cycles += now - pkts[i]->udata64;
> +
> +        latency_numbers.total_cycles += cycles;
> +        latency_numbers.total_pkts   += nb_pkts;
> +
> +        if (latency_numbers.total_pkts > (100 * 1000 * 1000ULL)) {
> +            printf("Latency = %"PRIu64" cycles\n",
> +                    latency_numbers.total_cycles /
> + latency_numbers.total_pkts);
> +
> +            latency_numbers.total_cycles = latency_numbers.total_pkts = 0;
> +        }
> +
> +        return nb_pkts;
> +    }
> +
> +The ``calc_latency()`` function accumulates the total number of packets
> +and the total number of cycles used. Once more than 100 million packets
> +have been transmitted the average cycle count per packet is printed out
> +and the counters are reset.
> --
> 1.7.4.1
Acked-by: Siobhan Butler <siobhan.a.butler@intel.com>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [dpdk-dev] [PATCH 0/3] additional sample app guides
  2015-02-27  9:44 ` [dpdk-dev] [PATCH 0/3] additional sample app guides De Lara Guarch, Pablo
@ 2015-03-17 17:02   ` Thomas Monjalon
  0 siblings, 0 replies; 8+ messages in thread
From: Thomas Monjalon @ 2015-03-17 17:02 UTC (permalink / raw)
  To: Mcnamara, John; +Cc: dev

> > This patchset includes two new sample app guides.
> > 
> > The first is for the existing basic forwarding/skeleton application.
> > 
> > The second is for the recently added rxtx_callbacks sample application.
> > 
> > John McNamara (3):
> >   examples/skeleton: minor refactoring to help documentation
> >   doc: add docs for basic forwarding skeleton app
> >   doc: add docs for the rxtx_callbacks sample app
> 
> Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

Applied, thanks

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-03-17 17:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-25 19:45 [dpdk-dev] [PATCH 0/3] additional sample app guides John McNamara
2015-02-25 19:46 ` [dpdk-dev] [PATCH 1/3] examples/skeleton: minor refactoring to help documentation John McNamara
2015-03-02 19:02   ` Butler, Siobhan A
2015-02-25 19:46 ` [dpdk-dev] [PATCH 2/3] doc: add docs for basic forwarding skeleton app John McNamara
2015-02-25 19:46 ` [dpdk-dev] [PATCH 3/3] doc: add docs for the rxtx_callbacks sample app John McNamara
2015-03-02 19:02   ` Butler, Siobhan A
2015-02-27  9:44 ` [dpdk-dev] [PATCH 0/3] additional sample app guides De Lara Guarch, Pablo
2015-03-17 17:02   ` Thomas Monjalon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).