aboutsummaryrefslogtreecommitdiff
path: root/example/l2fwd_simple/odp_l2fwd_simple.c
diff options
context:
space:
mode:
Diffstat (limited to 'example/l2fwd_simple/odp_l2fwd_simple.c')
-rw-r--r--example/l2fwd_simple/odp_l2fwd_simple.c228
1 files changed, 157 insertions, 71 deletions
diff --git a/example/l2fwd_simple/odp_l2fwd_simple.c b/example/l2fwd_simple/odp_l2fwd_simple.c
index e63814555..1ea08cce1 100644
--- a/example/l2fwd_simple/odp_l2fwd_simple.c
+++ b/example/l2fwd_simple/odp_l2fwd_simple.c
@@ -1,7 +1,14 @@
-/* Copyright (c) 2016, Linaro Limited
- * All rights reserved.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2016-2018 Linaro Limited
+ * Copyright (c) 2024 Nokia
+ */
+
+/**
+ * @example odp_l2fwd_simple.c
*
- * SPDX-License-Identifier: BSD-3-Clause
+ * Minimal L2 forwarding example application
+ *
+ * @cond _ODP_HIDE_FROM_DOXYGEN_
*/
#include <stdlib.h>
@@ -17,20 +24,24 @@
#define MAX_PKT_BURST 32
#define MAX_WORKERS 1
-static int exit_thr;
-static int g_ret;
-
-struct {
+typedef struct {
odp_pktio_t if0, if1;
odp_pktin_queue_t if0in, if1in;
odp_pktout_queue_t if0out, if1out;
odph_ethaddr_t src, dst;
-} global;
+ odp_shm_t shm;
+ odp_atomic_u32_t exit_thr;
+ int wait_sec;
+} global_data_t;
+
+static global_data_t *global;
static void sig_handler(int signo ODP_UNUSED)
{
printf("sig_handler!\n");
- exit_thr = 1;
+ if (global == NULL)
+ return;
+ odp_atomic_store_u32(&global->exit_thr, 1);
}
static odp_pktio_t create_pktio(const char *name, odp_pool_t pool,
@@ -52,7 +63,7 @@ static odp_pktio_t create_pktio(const char *name, odp_pool_t pool,
}
odp_pktio_config_init(&config);
- config.parser.layer = ODP_PKTIO_PARSER_LAYER_L2;
+ config.parser.layer = ODP_PROTO_LAYER_L2;
odp_pktio_config(pktio, &config);
odp_pktin_queue_param_init(&in_queue_param);
@@ -87,26 +98,31 @@ static int run_worker(void *arg ODP_UNUSED)
{
odp_packet_t pkt_tbl[MAX_PKT_BURST];
int pkts, sent, tx_drops, i;
- int total_pkts = 0;
+ uint64_t wait_time = odp_pktin_wait_time(ODP_TIME_SEC_IN_NS);
- if (odp_pktio_start(global.if0)) {
+ if (odp_pktio_start(global->if0)) {
printf("unable to start input interface\n");
- exit(1);
+ return -1;
}
printf("started input interface\n");
- if (odp_pktio_start(global.if1)) {
+ if (odp_pktio_start(global->if1)) {
printf("unable to start output interface\n");
- exit(1);
+ return -1;
}
printf("started output interface\n");
printf("started all\n");
- while (!exit_thr) {
- pkts = odp_pktin_recv_tmo(global.if0in, pkt_tbl, MAX_PKT_BURST,
- ODP_PKTIN_NO_WAIT);
+ while (!odp_atomic_load_u32(&global->exit_thr)) {
+ pkts = odp_pktin_recv_tmo(global->if0in, pkt_tbl, MAX_PKT_BURST,
+ wait_time);
- if (odp_unlikely(pkts <= 0))
+ if (odp_unlikely(pkts <= 0)) {
+ if (global->wait_sec > 0)
+ if (!(--global->wait_sec))
+ break;
continue;
+ }
+
for (i = 0; i < pkts; i++) {
odp_packet_t pkt = pkt_tbl[i];
odph_ethhdr_t *eth;
@@ -116,65 +132,47 @@ static int run_worker(void *arg ODP_UNUSED)
return 0;
}
eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
- eth->src = global.src;
- eth->dst = global.dst;
+ eth->src = global->src;
+ eth->dst = global->dst;
}
- sent = odp_pktout_send(global.if1out, pkt_tbl, pkts);
+ sent = odp_pktout_send(global->if1out, pkt_tbl, pkts);
if (sent < 0)
sent = 0;
- total_pkts += sent;
tx_drops = pkts - sent;
if (odp_unlikely(tx_drops))
odp_packet_free_multi(&pkt_tbl[sent], tx_drops);
}
- if (total_pkts < 10)
- g_ret = -1;
-
return 0;
}
int main(int argc, char **argv)
{
+ odph_helper_options_t helper_options;
odp_pool_t pool;
odp_pool_param_t params;
odp_cpumask_t cpumask;
- odph_odpthread_t thd[MAX_WORKERS];
+ odph_thread_t thd[MAX_WORKERS];
odp_instance_t instance;
- odph_odpthread_params_t thr_params;
- int opt;
- int long_index;
-
- static const struct option longopts[] = { {NULL, 0, NULL, 0} };
- static const char *shortopts = "";
-
- /* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
-
- /*
- * parse own options: currentely none, but this will move optind
- * to the first non-option argument. (in case there where helprt args)
- */
- opterr = 0; /* do not issue errors on helper options */
- while (1) {
- opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
- if (-1 == opt)
- break; /* No more options */
- }
-
- if (argc != optind + 4 ||
- odph_eth_addr_parse(&global.dst, argv[optind + 2]) != 0 ||
- odph_eth_addr_parse(&global.src, argv[optind + 3]) != 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);
+ odp_init_t init_param;
+ odph_thread_common_param_t thr_common;
+ odph_thread_param_t thr_param;
+ odph_ethaddr_t correct_src;
+ uint32_t mtu1, mtu2;
+ odp_shm_t shm;
+ odph_thread_join_result_t res[MAX_WORKERS];
+
+ /* Let helper collect its own arguments (e.g. --odph_proc) */
+ argc = odph_parse_options(argc, argv);
+ if (odph_options(&helper_options)) {
+ printf("Error: reading ODP helper options failed.\n");
+ exit(EXIT_FAILURE);
}
- if (odp_init_global(&instance, NULL, NULL)) {
+ odp_init_param_init(&init_param);
+ init_param.mem_model = helper_options.mem_model;
+
+ if (odp_init_global(&instance, &init_param, NULL)) {
printf("Error: ODP global init failed.\n");
exit(1);
}
@@ -184,6 +182,41 @@ int main(int argc, char **argv)
exit(1);
}
+ /* Reserve memory for args from shared mem */
+ shm = odp_shm_reserve("_appl_global_data", sizeof(global_data_t),
+ ODP_CACHE_LINE_SIZE, 0);
+ if (shm == ODP_SHM_INVALID) {
+ printf("Error: shared mem reserve failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ global = odp_shm_addr(shm);
+ if (global == NULL) {
+ printf("Error: shared mem alloc failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ memset(global, 0, sizeof(global_data_t));
+ odp_atomic_init_u32(&global->exit_thr, 0);
+ global->shm = shm;
+
+ if (argc > 7 ||
+ 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 [-t sec]\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 (argc == 7 && !strncmp(argv[5], "-t", 2))
+ global->wait_sec = atoi(argv[6]);
+
+ if (global->wait_sec)
+ printf("running test for %d sec\n", global->wait_sec);
+
/* Create packet pool */
odp_pool_param_init(&params);
params.pkt.seg_len = POOL_SEG_LEN;
@@ -198,29 +231,82 @@ int main(int argc, char **argv)
exit(1);
}
- global.if0 = create_pktio(argv[optind], pool, &global.if0in,
- &global.if0out);
- global.if1 = create_pktio(argv[optind + 1], pool, &global.if1in,
- &global.if1out);
+ global->if0 = create_pktio(argv[1], pool, &global->if0in,
+ &global->if0out);
+ global->if1 = create_pktio(argv[2], pool, &global->if1in,
+ &global->if1out);
+
+ /* Do some operations to increase code coverage in tests */
+ if (odp_pktio_mac_addr(global->if0, &correct_src, sizeof(correct_src))
+ != sizeof(correct_src))
+ printf("Warning: can't get MAC address\n");
+ else if (memcmp(&correct_src, &global->src, sizeof(correct_src)) != 0)
+ printf("Warning: src MAC invalid\n");
+
+ odp_pktio_promisc_mode_set(global->if0, true);
+ odp_pktio_promisc_mode_set(global->if1, true);
+ (void)odp_pktio_promisc_mode(global->if0);
+ (void)odp_pktio_promisc_mode(global->if1);
+
+ mtu1 = odp_pktin_maxlen(global->if0);
+ mtu2 = odp_pktout_maxlen(global->if1);
+ if (mtu1 && mtu2 && mtu1 > mtu2)
+ printf("Warning: input MTU bigger than output MTU\n");
odp_cpumask_default_worker(&cpumask, MAX_WORKERS);
- memset(&thr_params, 0, sizeof(thr_params));
- thr_params.start = run_worker;
- thr_params.arg = NULL;
- thr_params.thr_type = ODP_THREAD_WORKER;
- thr_params.instance = instance;
+ odph_thread_common_param_init(&thr_common);
+ odph_thread_param_init(&thr_param);
+
+ thr_param.start = run_worker;
+ thr_param.thr_type = ODP_THREAD_WORKER;
+
+ thr_common.instance = instance;
+ thr_common.cpumask = &cpumask;
+ thr_common.share_param = 1;
signal(SIGINT, sig_handler);
- odph_odpthreads_create(thd, &cpumask, &thr_params);
- odph_odpthreads_join(thd);
+ if (odph_thread_create(thd, &thr_common, &thr_param, MAX_WORKERS) !=
+ MAX_WORKERS) {
+ printf("Error: failed to create threads\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (odph_thread_join_result(thd, res, MAX_WORKERS) != MAX_WORKERS) {
+ printf("Error: failed to join threads\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (int i = 0; i < MAX_WORKERS; i++) {
+ if (res[i].is_sig || res[i].ret != 0) {
+ printf("Error: thread failure%s: %d\n", res[i].is_sig ?
+ " (signaled)" : "", res[i].ret);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (odp_pktio_stop(global->if0) || odp_pktio_close(global->if0)) {
+ printf("Error: failed to close interface %s\n", argv[1]);
+ exit(EXIT_FAILURE);
+ }
+ if (odp_pktio_stop(global->if1) || odp_pktio_close(global->if1)) {
+ printf("Error: failed to close interface %s\n", argv[2]);
+ exit(EXIT_FAILURE);
+ }
if (odp_pool_destroy(pool)) {
printf("Error: pool destroy\n");
exit(EXIT_FAILURE);
}
+ global = NULL;
+ odp_mb_full();
+ if (odp_shm_free(shm)) {
+ printf("Error: shm free global data\n");
+ exit(EXIT_FAILURE);
+ }
+
if (odp_term_local()) {
printf("Error: term local\n");
exit(EXIT_FAILURE);
@@ -231,5 +317,5 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
- return g_ret;
+ return 0;
}