Modification of l2fwd to demonstrate keep-alive functionality. Signed-off-by: Remy Horton <remy.horton at intel.com> --- examples/l2fwd/Makefile | 2 +- examples/l2fwd/main.c | 125 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 118 insertions(+), 9 deletions(-)
diff --git a/examples/l2fwd/Makefile b/examples/l2fwd/Makefile index 78feeeb..8647174 100644 --- a/examples/l2fwd/Makefile +++ b/examples/l2fwd/Makefile @@ -39,7 +39,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk # binary name -APP = l2fwd +APP = l2fwd-keepalive # all source are stored in SRCS-y SRCS-y := main.c diff --git a/examples/l2fwd/main.c b/examples/l2fwd/main.c index 720fd5a..131e5a2 100644 --- a/examples/l2fwd/main.c +++ b/examples/l2fwd/main.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,6 +68,8 @@ #include <rte_ring.h> #include <rte_mempool.h> #include <rte_mbuf.h> +#include <rte_timer.h> +#include <rte_keepalive.h> #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 @@ -135,13 +137,18 @@ struct l2fwd_port_statistics { struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; /* A tsc-based timer responsible for triggering statistics printout */ -#define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */ +#define TIMER_MILLISECOND 1 #define MAX_TIMER_PERIOD 86400 /* 1 day max */ static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */ +static int64_t check_period = 5; /* default check cycle is 5ms */ + +/* Keepalive structure */ +struct rte_keepalive * rte_global_keepalive_info; /* Print out statistics on packets dropped */ static void -print_stats(void) +print_stats(__attribute__((unused)) struct rte_timer *ptr_timer, + __attribute__((unused)) void *ptr_data) { uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; unsigned portid; @@ -283,11 +290,23 @@ l2fwd_main_loop(void) portid); } + uint64_t tsc_initial = rte_rdtsc(); + uint64_t tsc_lifetime = (rand()&0x07) * rte_get_tsc_hz(); + while (1) { + /* Keepalive heartbeat */ + rte_keepalive_mark_alive(rte_global_keepalive_info); cur_tsc = rte_rdtsc(); /* + * Die randomly within 7 secs for demo purposes if + * keepalive enables + */ + if (check_period > 0 && cur_tsc - tsc_initial > tsc_lifetime) + break; + + /* * TX burst queue drain */ diff_tsc = cur_tsc - prev_tsc; @@ -313,7 +332,7 @@ l2fwd_main_loop(void) /* do this only on master core */ if (lcore_id == rte_get_master_lcore()) { - print_stats(); + print_stats(NULL, NULL); /* reset the timer */ timer_tsc = 0; } @@ -357,6 +376,7 @@ l2fwd_usage(const char *prgname) printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -q NQ: number of queue (=ports) per lcore (default is 1)\n" + " -K PERIOD: Keepalive check period (5 default; 86400 max)\n" " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n", prgname); } @@ -412,6 +432,22 @@ l2fwd_parse_timer_period(const char *q_arg) return n; } +static int +l2fwd_parse_check_period(const char *q_arg) +{ + char *end = NULL; + int n; + + /* parse number string */ + n = strtol(q_arg, &end, 10); + if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + if (n >= MAX_TIMER_PERIOD) + return -1; + + return n; +} + /* Parse the argument given in the command line of the application */ static int l2fwd_parse_args(int argc, char **argv) @@ -426,7 +462,7 @@ l2fwd_parse_args(int argc, char **argv) argvopt = argv; - while ((opt = getopt_long(argc, argvopt, "p:q:T:", + while ((opt = getopt_long(argc, argvopt, "p:q:T:K:", lgopts, &option_index)) != EOF) { switch (opt) { @@ -460,6 +496,16 @@ l2fwd_parse_args(int argc, char **argv) } break; + /* Check period */ + case 'K': + check_period = l2fwd_parse_check_period(optarg); + if (check_period < 0) { + printf("invalid check period\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* long options */ case 0: l2fwd_usage(prgname); @@ -534,6 +580,18 @@ check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) } } +static void +dead_core(__attribute__((unused)) void *ptr_data, const int id_core) +{ + printf("Dead core %i - restarting..\n", id_core); + if (rte_eal_get_lcore_state(id_core) == FINISHED) { + rte_eal_wait_lcore(id_core); + rte_eal_remote_launch(l2fwd_launch_one_lcore, NULL, id_core); + } else { + printf("..false positive!\n"); + } +} + int main(int argc, char **argv) { @@ -600,7 +658,7 @@ main(int argc, char **argv) l2fwd_dst_ports[last_port] = last_port; } - rx_lcore_id = 0; + rx_lcore_id = 1; qconf = NULL; /* Initialize the port/queue configuration of each logical core */ @@ -696,8 +754,59 @@ main(int argc, char **argv) check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); - /* launch per-lcore init on every lcore */ - rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MASTER); + struct rte_timer hb_timer, stats_timer; + + rte_timer_subsystem_init(); + rte_timer_init(&stats_timer); + + if (check_period > 0) { + rte_global_keepalive_info = rte_keepalive_create(&dead_core, NULL); + if( rte_global_keepalive_info == NULL) + rte_exit(EXIT_FAILURE, "init_keep_alive() failed"); + rte_timer_init(&hb_timer); + if (rte_timer_reset(&hb_timer, + (check_period * rte_get_timer_hz()) / 1000, + PERIODICAL, + rte_lcore_id(), + (void(*)(struct rte_timer*, void*)) + &rte_keepalive_dispatch_pings, + rte_global_keepalive_info + ) != 0 ) + rte_exit(EXIT_FAILURE, "Keepalive setup failure.\n"); + } + if (timer_period > 0) { + if (rte_timer_reset(&stats_timer, + (timer_period * rte_get_timer_hz()) / 1000, + PERIODICAL, + rte_lcore_id(), + &print_stats, NULL + ) != 0 ) + rte_exit(EXIT_FAILURE, "Stats setup failure.\n"); + } + /* launch per-lcore init on every slave lcore */ + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id]; + + if (qconf->n_rx_port == 0) + RTE_LOG(INFO, L2FWD, + "lcore %u has nothing to do\n", + lcore_id + ); + else { + rte_eal_remote_launch( + l2fwd_launch_one_lcore, + NULL, + lcore_id + ); + rte_keepalive_register_core(rte_global_keepalive_info, + lcore_id); + } + } + for (;;) { + rte_timer_manage(); + rte_delay_ms(5); + } + RTE_LCORE_FOREACH_SLAVE(lcore_id) { if (rte_eal_wait_lcore(lcore_id) < 0) return -1; -- 1.9.3