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(¶ms); > + 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", ¶ms); > + > + 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
