1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016 Intel Corporation 3 */ 4 5 #include <time.h> 6 7 #include <rte_common.h> 8 #include <rte_keepalive.h> 9 10 #include "shm.h" 11 12 struct rte_keepalive_shm *rte_keepalive_shm_create(void) 13 { 14 int fd; 15 int idx_core; 16 struct rte_keepalive_shm *ka_shm; 17 18 /* If any existing object is not unlinked, it makes it all too easy 19 * for clients to end up with stale shared memory blocks when 20 * restarted. Unlinking makes sure subsequent shm_open by clients 21 * will get the new block mapped below. 22 */ 23 if (shm_unlink(RTE_KEEPALIVE_SHM_NAME) == -1 && errno != ENOENT) 24 RTE_LOG(NOTICE, L2FWD, 25 "Warning: Error unlinking stale %s (%s)\n", 26 RTE_KEEPALIVE_SHM_NAME, strerror(errno)); 27 28 fd = shm_open(RTE_KEEPALIVE_SHM_NAME, 29 O_CREAT | O_TRUNC | O_RDWR, 0666); 30 if (fd < 0) 31 RTE_LOG(ERR, L2FWD, "Failed to open %s as SHM (%s)\n", 32 RTE_KEEPALIVE_SHM_NAME, strerror(errno)); 33 else if (ftruncate(fd, sizeof(struct rte_keepalive_shm)) != 0) 34 RTE_LOG(ERR, L2FWD, "Failed to resize SHM (%s)\n", strerror(errno)); 35 else { 36 ka_shm = (struct rte_keepalive_shm *) mmap( 37 0, sizeof(struct rte_keepalive_shm), 38 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 39 close(fd); 40 if (ka_shm == MAP_FAILED) 41 RTE_LOG(ERR, L2FWD, "Failed to mmap SHM (%s)\n", strerror(errno)); 42 else { 43 memset(ka_shm, 0, sizeof(struct rte_keepalive_shm)); 44 45 /* Initialize the semaphores for IPC/SHM use */ 46 if (sem_init(&ka_shm->core_died, 1, 0) != 0) { 47 RTE_LOG(ERR, L2FWD, "Failed to setup SHM semaphore (%s)\n", 48 strerror(errno)); 49 munmap(ka_shm, 50 sizeof(struct rte_keepalive_shm)); 51 return NULL; 52 } 53 54 /* Set all cores to 'not present' */ 55 for (idx_core = 0; 56 idx_core < RTE_KEEPALIVE_MAXCORES; 57 idx_core++) { 58 ka_shm->core_state[idx_core] = 59 RTE_KA_STATE_UNUSED; 60 ka_shm->core_last_seen_times[idx_core] = 0; 61 } 62 63 return ka_shm; 64 } 65 } 66 return NULL; 67 } 68 69 void rte_keepalive_relayed_state(struct rte_keepalive_shm *shm, 70 const int id_core, const enum rte_keepalive_state core_state, 71 __rte_unused uint64_t last_alive) 72 { 73 int count; 74 75 shm->core_state[id_core] = core_state; 76 shm->core_last_seen_times[id_core] = last_alive; 77 78 if (core_state == RTE_KEEPALIVE_SHM_DEAD) { 79 /* Since core has died, also signal ka_agent. 80 * 81 * Limit number of times semaphore can be incremented, in case 82 * ka_agent is not active. 83 */ 84 if (sem_getvalue(&shm->core_died, &count) == -1) { 85 RTE_LOG(ERR, L2FWD, "Semaphore check failed(%s)\n", 86 strerror(errno)); 87 return; 88 } 89 if (count > 1) 90 return; 91 92 if (sem_post(&shm->core_died) != 0) 93 RTE_LOG(ERR, L2FWD, "Failed to increment semaphore (%s)\n", 94 strerror(errno)); 95 } 96 } 97 98 void rte_keepalive_shm_cleanup(struct rte_keepalive_shm *ka_shm) 99 { 100 if (shm_unlink(RTE_KEEPALIVE_SHM_NAME) == -1 && errno != ENOENT) 101 RTE_LOG(NOTICE, L2FWD, "Warning: Error unlinking %s (%s)\n", 102 RTE_KEEPALIVE_SHM_NAME, strerror(errno)); 103 104 if (ka_shm && munmap(ka_shm, sizeof(struct rte_keepalive_shm)) != 0) 105 RTE_LOG(ERR, L2FWD, "Warning: munmap() failed: %s\n", 106 strerror(errno)); 107 } 108