xref: /dpdk/lib/eal/common/rte_keepalive.c (revision e9fd1ebf981f361844aea9ec94e17f4bda5e1479)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2015-2016 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include <inttypes.h>
6*e9fd1ebfSTyler Retzlaff #include <stdalign.h>
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson #include <rte_common.h>
999a2dd95SBruce Richardson #include <rte_cycles.h>
1099a2dd95SBruce Richardson #include <rte_lcore.h>
1199a2dd95SBruce Richardson #include <rte_log.h>
1299a2dd95SBruce Richardson #include <rte_keepalive.h>
1399a2dd95SBruce Richardson #include <rte_malloc.h>
1499a2dd95SBruce Richardson 
15ae67895bSDavid Marchand #include "eal_private.h"
16ae67895bSDavid Marchand 
1799a2dd95SBruce Richardson struct rte_keepalive {
1899a2dd95SBruce Richardson 	/** Core Liveness. */
1999a2dd95SBruce Richardson 	struct {
2099a2dd95SBruce Richardson 		/*
2199a2dd95SBruce Richardson 		 * Each element must be cache aligned to prevent false sharing.
2299a2dd95SBruce Richardson 		 */
23*e9fd1ebfSTyler Retzlaff 		alignas(RTE_CACHE_LINE_SIZE) enum rte_keepalive_state core_state;
2499a2dd95SBruce Richardson 	} live_data[RTE_KEEPALIVE_MAXCORES];
2599a2dd95SBruce Richardson 
2699a2dd95SBruce Richardson 	/** Last-seen-alive timestamps */
2799a2dd95SBruce Richardson 	uint64_t last_alive[RTE_KEEPALIVE_MAXCORES];
2899a2dd95SBruce Richardson 
2999a2dd95SBruce Richardson 	/**
3099a2dd95SBruce Richardson 	 * Cores to check.
3199a2dd95SBruce Richardson 	 * Indexed by core id, non-zero if the core should be checked.
3299a2dd95SBruce Richardson 	 */
3399a2dd95SBruce Richardson 	uint8_t active_cores[RTE_KEEPALIVE_MAXCORES];
3499a2dd95SBruce Richardson 
3599a2dd95SBruce Richardson 	/** Dead core handler. */
3699a2dd95SBruce Richardson 	rte_keepalive_failure_callback_t callback;
3799a2dd95SBruce Richardson 
3899a2dd95SBruce Richardson 	/**
3999a2dd95SBruce Richardson 	 * Dead core handler app data.
4099a2dd95SBruce Richardson 	 * Pointer is passed to dead core handler.
4199a2dd95SBruce Richardson 	 */
4299a2dd95SBruce Richardson 	void *callback_data;
4399a2dd95SBruce Richardson 	uint64_t tsc_initial;
4499a2dd95SBruce Richardson 	uint64_t tsc_mhz;
4599a2dd95SBruce Richardson 
4699a2dd95SBruce Richardson 	/** Core state relay handler. */
4799a2dd95SBruce Richardson 	rte_keepalive_relay_callback_t relay_callback;
4899a2dd95SBruce Richardson 
4999a2dd95SBruce Richardson 	/**
5099a2dd95SBruce Richardson 	 * Core state relay handler app data.
5199a2dd95SBruce Richardson 	 * Pointer is passed to live core handler.
5299a2dd95SBruce Richardson 	 */
5399a2dd95SBruce Richardson 	void *relay_callback_data;
5499a2dd95SBruce Richardson };
5599a2dd95SBruce Richardson 
5699a2dd95SBruce Richardson static void
print_trace(const char * msg,struct rte_keepalive * keepcfg,int idx_core)5799a2dd95SBruce Richardson print_trace(const char *msg, struct rte_keepalive *keepcfg, int idx_core)
5899a2dd95SBruce Richardson {
59ae67895bSDavid Marchand 	EAL_LOG(INFO, "%sLast seen %" PRId64 "ms ago.",
6099a2dd95SBruce Richardson 		msg,
6199a2dd95SBruce Richardson 		((rte_rdtsc() - keepcfg->last_alive[idx_core])*1000)
6299a2dd95SBruce Richardson 		/ rte_get_tsc_hz()
6399a2dd95SBruce Richardson 	      );
6499a2dd95SBruce Richardson }
6599a2dd95SBruce Richardson 
6699a2dd95SBruce Richardson void
rte_keepalive_dispatch_pings(__rte_unused void * ptr_timer,void * ptr_data)6799a2dd95SBruce Richardson rte_keepalive_dispatch_pings(__rte_unused void *ptr_timer,
6899a2dd95SBruce Richardson 	void *ptr_data)
6999a2dd95SBruce Richardson {
7099a2dd95SBruce Richardson 	struct rte_keepalive *keepcfg = ptr_data;
7199a2dd95SBruce Richardson 	int idx_core;
7299a2dd95SBruce Richardson 
7399a2dd95SBruce Richardson 	for (idx_core = 0; idx_core < RTE_KEEPALIVE_MAXCORES; idx_core++) {
7499a2dd95SBruce Richardson 		if (keepcfg->active_cores[idx_core] == 0)
7599a2dd95SBruce Richardson 			continue;
7699a2dd95SBruce Richardson 
7799a2dd95SBruce Richardson 		switch (keepcfg->live_data[idx_core].core_state) {
7899a2dd95SBruce Richardson 		case RTE_KA_STATE_UNUSED:
7999a2dd95SBruce Richardson 			break;
8099a2dd95SBruce Richardson 		case RTE_KA_STATE_ALIVE: /* Alive */
8199a2dd95SBruce Richardson 			keepcfg->live_data[idx_core].core_state =
8299a2dd95SBruce Richardson 			    RTE_KA_STATE_MISSING;
8399a2dd95SBruce Richardson 			keepcfg->last_alive[idx_core] = rte_rdtsc();
8499a2dd95SBruce Richardson 			break;
8599a2dd95SBruce Richardson 		case RTE_KA_STATE_MISSING: /* MIA */
8699a2dd95SBruce Richardson 			print_trace("Core MIA. ", keepcfg, idx_core);
8799a2dd95SBruce Richardson 			keepcfg->live_data[idx_core].core_state =
8899a2dd95SBruce Richardson 			    RTE_KA_STATE_DEAD;
8999a2dd95SBruce Richardson 			break;
9099a2dd95SBruce Richardson 		case RTE_KA_STATE_DEAD: /* Dead */
9199a2dd95SBruce Richardson 			keepcfg->live_data[idx_core].core_state =
9299a2dd95SBruce Richardson 			    RTE_KA_STATE_GONE;
9399a2dd95SBruce Richardson 			print_trace("Core died. ", keepcfg, idx_core);
9499a2dd95SBruce Richardson 			if (keepcfg->callback)
9599a2dd95SBruce Richardson 				keepcfg->callback(
9699a2dd95SBruce Richardson 					keepcfg->callback_data,
9799a2dd95SBruce Richardson 					idx_core
9899a2dd95SBruce Richardson 					);
9999a2dd95SBruce Richardson 			break;
10099a2dd95SBruce Richardson 		case RTE_KA_STATE_GONE: /* Buried */
10199a2dd95SBruce Richardson 			break;
10299a2dd95SBruce Richardson 		case RTE_KA_STATE_DOZING: /* Core going idle */
10399a2dd95SBruce Richardson 			keepcfg->live_data[idx_core].core_state =
10499a2dd95SBruce Richardson 			    RTE_KA_STATE_SLEEP;
10599a2dd95SBruce Richardson 			keepcfg->last_alive[idx_core] = rte_rdtsc();
10699a2dd95SBruce Richardson 			break;
10799a2dd95SBruce Richardson 		case RTE_KA_STATE_SLEEP: /* Idled core */
10899a2dd95SBruce Richardson 			break;
10999a2dd95SBruce Richardson 		}
11099a2dd95SBruce Richardson 		if (keepcfg->relay_callback)
11199a2dd95SBruce Richardson 			keepcfg->relay_callback(
11299a2dd95SBruce Richardson 				keepcfg->relay_callback_data,
11399a2dd95SBruce Richardson 				idx_core,
11499a2dd95SBruce Richardson 				keepcfg->live_data[idx_core].core_state,
11599a2dd95SBruce Richardson 				keepcfg->last_alive[idx_core]
11699a2dd95SBruce Richardson 				);
11799a2dd95SBruce Richardson 	}
11899a2dd95SBruce Richardson }
11999a2dd95SBruce Richardson 
12099a2dd95SBruce Richardson struct rte_keepalive *
rte_keepalive_create(rte_keepalive_failure_callback_t callback,void * data)12199a2dd95SBruce Richardson rte_keepalive_create(rte_keepalive_failure_callback_t callback,
12299a2dd95SBruce Richardson 	void *data)
12399a2dd95SBruce Richardson {
12499a2dd95SBruce Richardson 	struct rte_keepalive *keepcfg;
12599a2dd95SBruce Richardson 
12699a2dd95SBruce Richardson 	keepcfg = rte_zmalloc("RTE_EAL_KEEPALIVE",
12799a2dd95SBruce Richardson 		sizeof(struct rte_keepalive),
12899a2dd95SBruce Richardson 		RTE_CACHE_LINE_SIZE);
12999a2dd95SBruce Richardson 	if (keepcfg != NULL) {
13099a2dd95SBruce Richardson 		keepcfg->callback = callback;
13199a2dd95SBruce Richardson 		keepcfg->callback_data = data;
13299a2dd95SBruce Richardson 		keepcfg->tsc_initial = rte_rdtsc();
13399a2dd95SBruce Richardson 		keepcfg->tsc_mhz = rte_get_tsc_hz() / 1000;
13499a2dd95SBruce Richardson 	}
13599a2dd95SBruce Richardson 	return keepcfg;
13699a2dd95SBruce Richardson }
13799a2dd95SBruce Richardson 
rte_keepalive_register_relay_callback(struct rte_keepalive * keepcfg,rte_keepalive_relay_callback_t callback,void * data)13899a2dd95SBruce Richardson void rte_keepalive_register_relay_callback(struct rte_keepalive *keepcfg,
13999a2dd95SBruce Richardson 	rte_keepalive_relay_callback_t callback,
14099a2dd95SBruce Richardson 	void *data)
14199a2dd95SBruce Richardson {
14299a2dd95SBruce Richardson 	keepcfg->relay_callback = callback;
14399a2dd95SBruce Richardson 	keepcfg->relay_callback_data = data;
14499a2dd95SBruce Richardson }
14599a2dd95SBruce Richardson 
14699a2dd95SBruce Richardson void
rte_keepalive_register_core(struct rte_keepalive * keepcfg,const int id_core)14799a2dd95SBruce Richardson rte_keepalive_register_core(struct rte_keepalive *keepcfg, const int id_core)
14899a2dd95SBruce Richardson {
14999a2dd95SBruce Richardson 	if (id_core < RTE_KEEPALIVE_MAXCORES) {
15099a2dd95SBruce Richardson 		keepcfg->active_cores[id_core] = RTE_KA_STATE_ALIVE;
15199a2dd95SBruce Richardson 		keepcfg->last_alive[id_core] = rte_rdtsc();
15299a2dd95SBruce Richardson 	}
15399a2dd95SBruce Richardson }
15499a2dd95SBruce Richardson 
15599a2dd95SBruce Richardson void
rte_keepalive_mark_alive(struct rte_keepalive * keepcfg)15699a2dd95SBruce Richardson rte_keepalive_mark_alive(struct rte_keepalive *keepcfg)
15799a2dd95SBruce Richardson {
15899a2dd95SBruce Richardson 	keepcfg->live_data[rte_lcore_id()].core_state = RTE_KA_STATE_ALIVE;
15999a2dd95SBruce Richardson }
16099a2dd95SBruce Richardson 
16199a2dd95SBruce Richardson void
rte_keepalive_mark_sleep(struct rte_keepalive * keepcfg)16299a2dd95SBruce Richardson rte_keepalive_mark_sleep(struct rte_keepalive *keepcfg)
16399a2dd95SBruce Richardson {
16499a2dd95SBruce Richardson 	keepcfg->live_data[rte_lcore_id()].core_state = RTE_KA_STATE_DOZING;
16599a2dd95SBruce Richardson }
166