When the secondary process testpmd application running any fwd_engine and after that primary has exited will cause a crash.
This patch forces secondary process forwarding lcores in fwd_engine to stop before the primary process exits. Fixes: a550baf24af90f ("app/testpmd: support multi-process") Cc: sta...@dpdk.org Signed-off-by: Khadem Ullah <14pwcse1...@uetpeshawar.edu.pk> Signed-off-by: Stephen Hemminger <step...@networkplumber.org> --- app/test-pmd/testpmd.c | 104 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 4 deletions(-) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 0f58a31eb5..6c97026962 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -3609,6 +3609,83 @@ detach_devargs(char *identifier) rte_devargs_reset(&da); } +#ifndef RTE_EXEC_ENV_WINDOWS + +enum testpmd_req_type { + TESTPMD_REQ_TYPE_EXIT, +}; + +struct testpmd_mp_req { + enum testpmd_req_type t; +}; + +struct testpmd_mp_resp { + int result; +}; + +#define TESTPMD_MP "mp_testpmd" + +/* Send reply to this peer when testpmd exits */ +static RTE_ATOMIC(const char *) primary_name; + +static void +reply_to_primary(const char *peer, int result) +{ + struct rte_mp_msg reply = { }; + struct testpmd_mp_resp *resp = (struct testpmd_mp_resp *) &reply.param; + + strlcpy(reply.name, TESTPMD_MP, RTE_MP_MAX_NAME_LEN); + reply.len_param = sizeof(*resp); + resp->result = result; + + printf("Replying %d to primary\n", result); + fflush(stdout); + + if (rte_mp_reply(&reply, peer) < 0) + printf("Failed to send response to primary:%s", strerror(rte_errno)); +} + +/* Primary process is exiting, stop secondary process */ +static void +pmd_notify_secondary(void) +{ + struct testpmd_mp_req request = { + .t = TESTPMD_REQ_TYPE_EXIT, + }; + struct rte_mp_msg mp_req = { + .name = TESTPMD_MP, + .len_param = sizeof(request), + }; + struct rte_mp_reply reply; + struct timespec ts = {.tv_sec = 5, .tv_nsec = 0}; + + printf("\nPrimary: Sending 'stop_req' request to secondary...\n"); + fflush(stdout); + + memcpy(mp_req.param, &request, sizeof(request)); + rte_mp_request_sync(&mp_req, &reply, &ts); +} + +static int +handle_testpmd_request(const struct rte_mp_msg *request, const void *peer) +{ + const struct testpmd_mp_req *req = (const struct testpmd_mp_req *)request->param; + + if (req->t == TESTPMD_REQ_TYPE_EXIT) { + printf("\nReceived notification of primary exiting\n"); + fflush(stdout); + + /* Response is sent after forwarding loop exits */ + rte_atomic_store_explicit(&primary_name, peer, rte_memory_order_relaxed); + + kill(getpid(), SIGINT); + } else { + reply_to_primary(peer, -EINVAL); + } + return 0; +} +#endif + void pmd_test_exit(void) { @@ -3620,6 +3697,10 @@ pmd_test_exit(void) stop_packet_forwarding(); #ifndef RTE_EXEC_ENV_WINDOWS + /* Tell secondary to exit */ + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + pmd_notify_secondary(); + for (i = 0 ; i < RTE_DIM(mempools) ; i++) { if (mempools[i]) { if (mp_alloc_type == MP_ALLOC_ANON) @@ -3628,6 +3709,7 @@ pmd_test_exit(void) } } #endif + if (ports != NULL) { no_link_check = 1; RTE_ETH_FOREACH_DEV(pt_id) { @@ -4429,9 +4511,12 @@ main(int argc, char** argv) rte_strerror(rte_errno)); #ifndef RTE_EXEC_ENV_WINDOWS - if (rte_eal_process_type() == RTE_PROC_SECONDARY && - enable_primary_monitor() < 0) - rte_exit(EXIT_FAILURE, "Cannot setup primary monitor"); + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + if (enable_primary_monitor() < 0) + rte_exit(EXIT_FAILURE, "Cannot setup primary monitor"); + if (rte_mp_action_register(TESTPMD_MP, handle_testpmd_request) < 0) + rte_exit(EXIT_FAILURE, "Failed to register message action\n"); + } #endif /* allocate port structures, and init them */ @@ -4628,12 +4713,23 @@ main(int argc, char** argv) } #ifndef RTE_EXEC_ENV_WINDOWS - if (rte_eal_process_type() == RTE_PROC_SECONDARY) + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { disable_primary_monitor(); + rte_mp_action_unregister(TESTPMD_MP); + } #endif pmd_test_exit(); +#ifndef RTE_EXEC_ENV_WINDOWS + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + const char *peer = rte_atomic_exchange_explicit(&primary_name, NULL, + rte_memory_order_relaxed); + if (peer) + reply_to_primary(peer, 0); + } +#endif + #ifdef RTE_LIB_PDUMP /* uninitialize packet capture framework */ rte_pdump_uninit(); -- 2.27.0