I like this.  Thanks for this contribution.

For this series:

Reviewed-and-tested-by: Bill Fischofer <[email protected]>

On Mon, Feb 22, 2016 at 4:15 AM, Juha-Matti Tilli <
[email protected]> wrote:

> The ODP distribution is lacking a simple example how to receive and send
> packets. The l2fwd is overly complicated because it supports an arbitrary
> number of interfaces, bi-directional operation and an arbitrary number of
> threads.
>
> To remedy this situation, add l2fwd_simple which is a single-threaded
> unidirectional variant of l2fwd for exactly two interfaces. l2fwd_simple
> can be used as an example application when learning how to use ODP. The
> focus when developing l2fwd_simple was to reduce the code line count to as
> small value as possible, and it turned out it requires 165 lines of code.
>
> For unidirectional traffic in single-threaded use cases, l2fwd_simple
> performs actually better than l2fwd with single thread, because
> l2fwd_simple does not need to poll two interfaces in a single thread.
>
> Signed-off-by: Juha-Matti Tilli <[email protected]>
> Reviewed-by: Petri Savolainen <[email protected]>
> ---
>  configure.ac                            |   1 +
>  example/Makefile.am                     |   2 +-
>  example/l2fwd_simple/.gitignore         |   1 +
>  example/l2fwd_simple/Makefile.am        |  10 ++
>  example/l2fwd_simple/odp_l2fwd_simple.c | 165
> ++++++++++++++++++++++++++++++++
>  5 files changed, 178 insertions(+), 1 deletion(-)
>  create mode 100644 example/l2fwd_simple/.gitignore
>  create mode 100644 example/l2fwd_simple/Makefile.am
>  create mode 100644 example/l2fwd_simple/odp_l2fwd_simple.c
>
> diff --git a/configure.ac b/configure.ac
> index 1aa44d2..2dcddbf 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -332,6 +332,7 @@ AC_CONFIG_FILES([Makefile
>                  example/time/Makefile
>                  example/timer/Makefile
>                  example/traffic_mgmt/Makefile
> +                example/l2fwd_simple/Makefile
>                  helper/Makefile
>                  helper/test/Makefile
>                  pkgconfig/libodp.pc
> diff --git a/example/Makefile.am b/example/Makefile.am
> index 906d907..2d425c6 100644
> --- a/example/Makefile.am
> +++ b/example/Makefile.am
> @@ -1 +1 @@
> -SUBDIRS = classifier generator ipsec packet time timer traffic_mgmt
> +SUBDIRS = classifier generator ipsec packet time timer traffic_mgmt
> l2fwd_simple
> diff --git a/example/l2fwd_simple/.gitignore
> b/example/l2fwd_simple/.gitignore
> new file mode 100644
> index 0000000..1326732
> --- /dev/null
> +++ b/example/l2fwd_simple/.gitignore
> @@ -0,0 +1 @@
> +odp_l2fwd_simple
> diff --git a/example/l2fwd_simple/Makefile.am
> b/example/l2fwd_simple/Makefile.am
> new file mode 100644
> index 0000000..88d2915
> --- /dev/null
> +++ b/example/l2fwd_simple/Makefile.am
> @@ -0,0 +1,10 @@
> +include $(top_srcdir)/example/Makefile.inc
> +
> +bin_PROGRAMS = odp_l2fwd_simple$(EXEEXT)
> +odp_l2fwd_simple_LDFLAGS = $(AM_LDFLAGS) -static
> +odp_l2fwd_simple_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example
> +
> +noinst_HEADERS = \
> +                 $(top_srcdir)/example/example_debug.h
> +
> +dist_odp_l2fwd_simple_SOURCES = odp_l2fwd_simple.c
> diff --git a/example/l2fwd_simple/odp_l2fwd_simple.c
> b/example/l2fwd_simple/odp_l2fwd_simple.c
> new file mode 100644
> index 0000000..11d342f
> --- /dev/null
> +++ b/example/l2fwd_simple/odp_l2fwd_simple.c
> @@ -0,0 +1,165 @@
> +/* Copyright (c) 2016, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#include <odp_api.h>
> +#include <odp/helper/linux.h>
> +#include <odp/helper/eth.h>
> +#include <odp/helper/ip.h>
> +
> +#define POOL_NUM_PKT 8192
> +#define POOL_SEG_LEN 1856
> +#define MAX_PKT_BURST 32
> +
> +struct {
> +       odp_pktio_t if0, if1;
> +       odp_pktin_queue_t if0in, if1in;
> +       odp_pktout_queue_t if0out, if1out;
> +       odph_ethaddr_t src, dst;
> +} global;
> +
> +static odp_pktio_t create_pktio(const char *name, odp_pool_t pool,
> +                               odp_pktin_queue_t *pktin,
> +                               odp_pktout_queue_t *pktout)
> +{
> +       odp_pktio_param_t pktio_param;
> +       odp_pktin_queue_param_t in_queue_param;
> +       odp_pktout_queue_param_t out_queue_param;
> +       odp_pktio_t pktio;
> +
> +       odp_pktio_param_init(&pktio_param);
> +
> +       pktio = odp_pktio_open(name, pool, &pktio_param);
> +       if (pktio == ODP_PKTIO_INVALID) {
> +               printf("Failed to open %s\n", name);
> +               exit(1);
> +       }
> +
> +       odp_pktin_queue_param_init(&in_queue_param);
> +       odp_pktout_queue_param_init(&out_queue_param);
> +
> +       in_queue_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;
> +
> +       if (odp_pktin_queue_config(pktio, &in_queue_param)) {
> +               printf("Failed to config input queue for %s\n", name);
> +               exit(1);
> +       }
> +
> +       out_queue_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;
> +
> +       if (odp_pktout_queue_config(pktio, &out_queue_param)) {
> +               printf("Failed to config output queue for %s\n", name);
> +               exit(1);
> +       }
> +
> +       if (odp_pktin_queue(pktio, pktin, 1) != 1) {
> +               printf("pktin queue query failed for %s\n", name);
> +               exit(1);
> +       }
> +       if (odp_pktout_queue(pktio, pktout, 1) != 1) {
> +               printf("pktout queue query failed for %s\n", name);
> +               exit(1);
> +       }
> +       return pktio;
> +}
> +
> +static void *run_worker(void *arg ODP_UNUSED)
> +{
> +       odp_packet_t pkt_tbl[MAX_PKT_BURST];
> +       int pkts, sent, tx_drops, i;
> +
> +       if (odp_pktio_start(global.if0)) {
> +               printf("unable to start input interface\n");
> +               exit(1);
> +       }
> +       printf("started input interface\n");
> +       if (odp_pktio_start(global.if1)) {
> +               printf("unable to start output interface\n");
> +               exit(1);
> +       }
> +       printf("started output interface\n");
> +       printf("started all\n");
> +
> +       for (;;) {
> +               pkts = odp_pktin_recv(global.if0in, pkt_tbl,
> MAX_PKT_BURST);
> +               if (odp_unlikely(pkts <= 0))
> +                       continue;
> +               for (i = 0; i < pkts; i++) {
> +                       odp_packet_t pkt = pkt_tbl[i];
> +                       odph_ethhdr_t *eth;
> +
> +                       if (odp_unlikely(!odp_packet_has_eth(pkt))) {
> +                               printf("warning: packet has no eth
> header\n");
> +                               return NULL;
> +                       }
> +                       eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt,
> NULL);
> +                       eth->src = global.src;
> +                       eth->dst = global.dst;
> +               }
> +               sent = odp_pktout_send(global.if1out, pkt_tbl, pkts);
> +               if (sent < 0)
> +                       sent = 0;
> +               tx_drops = pkts - sent;
> +               if (odp_unlikely(tx_drops))
> +                       odp_packet_free_multi(&pkt_tbl[sent], tx_drops);
> +       }
> +       return NULL;
> +}
> +
> +int main(int argc, char **argv)
> +{
> +       odp_pool_t pool;
> +       odp_pool_param_t params;
> +       odp_cpumask_t cpumask;
> +       odph_linux_pthread_t thd;
> +
> +       if (argc != 5 ||
> +           odph_eth_addr_parse(&global.dst, argv[3]) != 0 ||
> +           odph_eth_addr_parse(&global.src, argv[4]) != 0) {
> +               printf("Usage: odp_l2fwd_simple eth0 eth1
> 01:02:03:04:05:06"
> +                      " 07:08:09:0a:0b:0c\n");
> +               printf("Where eth0 and eth1 are the used interfaces"
> +                      " (must have 2 of them)\n");
> +               printf("And the hexadecimal numbers are destination MAC
> address"
> +                      " and source MAC address\n");
> +               exit(1);
> +       }
> +
> +       if (odp_init_global(NULL, NULL)) {
> +               printf("Error: ODP global init failed.\n");
> +               exit(1);
> +       }
> +
> +       if (odp_init_local(ODP_THREAD_CONTROL)) {
> +               printf("Error: ODP local init failed.\n");
> +               exit(1);
> +       }
> +
> +       /* Create packet pool */
> +       odp_pool_param_init(&params);
> +       params.pkt.seg_len = POOL_SEG_LEN;
> +       params.pkt.len     = POOL_SEG_LEN;
> +       params.pkt.num     = POOL_NUM_PKT;
> +       params.type        = ODP_POOL_PACKET;
> +
> +       pool = odp_pool_create("packet pool", &params);
> +
> +       if (pool == ODP_POOL_INVALID) {
> +               printf("Error: packet pool create failed.\n");
> +               exit(1);
> +       }
> +
> +       global.if0 = create_pktio(argv[1], pool, &global.if0in,
> &global.if0out);
> +       global.if1 = create_pktio(argv[2], pool, &global.if1in,
> &global.if1out);
> +
> +       odp_cpumask_default_worker(&cpumask, 1);
> +       odph_linux_pthread_create(&thd, &cpumask, run_worker, NULL,
> +                                 ODP_THREAD_WORKER);
> +       odph_linux_pthread_join(&thd, 1);
> +       return 0;
> +}
> --
> 2.1.4
>
> _______________________________________________
> lng-odp mailing list
> [email protected]
> https://lists.linaro.org/mailman/listinfo/lng-odp
>
_______________________________________________
lng-odp mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to