diff options
Diffstat (limited to 'example/l2fwd_simple/odp_l2fwd_simple.c')
-rw-r--r-- | example/l2fwd_simple/odp_l2fwd_simple.c | 228 |
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(¶ms); 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; } |