aboutsummaryrefslogtreecommitdiff
path: root/example
diff options
context:
space:
mode:
authorJuha-Matti Tilli <juha-matti.tilli@nokia.com>2016-02-29 11:28:52 +0200
committerMaxim Uvarov <maxim.uvarov@linaro.org>2016-03-04 13:24:49 +0300
commit6aa4e56fec65abe7b96a717b0c7f533b9975172f (patch)
treee96e7bc60d95d14114d6ee6d2edc6912fad75ed4 /example
parentdcc37e3793202143a515a9ea3be69a61212967c7 (diff)
example: l2fwd_simple: add single-threaded l2fwd example
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 <juha-matti.tilli@nokia.com> Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Diffstat (limited to 'example')
-rw-r--r--example/Makefile.am2
-rw-r--r--example/l2fwd_simple/.gitignore1
-rw-r--r--example/l2fwd_simple/Makefile.am10
-rw-r--r--example/l2fwd_simple/odp_l2fwd_simple.c165
-rw-r--r--example/m4/configure.m43
5 files changed, 179 insertions, 2 deletions
diff --git a/example/Makefile.am b/example/Makefile.am
index 39d9b0198..5c97fbb64 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -1 +1 @@
-SUBDIRS = classifier generator ipsec packet time timer
+SUBDIRS = classifier generator ipsec packet time timer l2fwd_simple
diff --git a/example/l2fwd_simple/.gitignore b/example/l2fwd_simple/.gitignore
new file mode 100644
index 000000000..132673244
--- /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 000000000..88d2915d5
--- /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 000000000..11d342f3c
--- /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;
+}
diff --git a/example/m4/configure.m4 b/example/m4/configure.m4
index bc90f820c..1710a31b8 100644
--- a/example/m4/configure.m4
+++ b/example/m4/configure.m4
@@ -4,4 +4,5 @@ AC_CONFIG_FILES([example/classifier/Makefile
example/Makefile
example/packet/Makefile
example/time/Makefile
- example/timer/Makefile])
+ example/timer/Makefile
+ example/l2fwd_simple/Makefile])