* [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
* 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
* [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 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-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 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