From patchwork Thu Jun 28 01:52:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qi Zhang X-Patchwork-Id: 41764 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 68FFD7CDA; Thu, 28 Jun 2018 03:53:22 +0200 (CEST) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id 1485A1B3A3 for ; Thu, 28 Jun 2018 03:52:49 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Jun 2018 18:52:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,281,1526367600"; d="scan'208";a="52818246" Received: from dpdk51.sh.intel.com ([10.67.110.190]) by orsmga008.jf.intel.com with ESMTP; 27 Jun 2018 18:52:48 -0700 From: Qi Zhang To: thomas@monjalon.net, anatoly.burakov@intel.com Cc: konstantin.ananyev@intel.com, dev@dpdk.org, bruce.richardson@intel.com, ferruh.yigit@intel.com, benjamin.h.shelton@intel.com, narender.vangati@intel.com, Qi Zhang Date: Thu, 28 Jun 2018 09:52:46 +0800 Message-Id: <20180628015247.42232-19-qi.z.zhang@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180628015247.42232-1-qi.z.zhang@intel.com> References: <20180607123849.14439-1-qi.z.zhang@intel.com> <20180628015247.42232-1-qi.z.zhang@intel.com> Subject: [dpdk-dev] [PATCH v6 18/19] examples/multi_process: add hotplug sample X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The sample code demonstrate device (ethdev only) management at multi-process envrionment. User can attach/detach a device on primary process and see it is synced on secondary process automatically, also user can lock a device to prevent it be detached or unlock it to go back to default behaviour. How to start? ./hotplug_mp --proc-type=auto Command Line Example: >help >list /* attach a af_packet vdev */ >attach net_af_packet,iface=eth0 /* detach port 0 */ >detach 0 /* attach a private af_packet vdev (secondary process only)*/ >attachp net_af_packet,iface=eth0 /* detach a private device (secondary process only) */ >detachp 0 /* lock port 0 */ >lock 0 /* unlock port 0 */ >unlock 0 Signed-off-by: Qi Zhang --- examples/multi_process/Makefile | 1 + examples/multi_process/hotplug_mp/Makefile | 23 ++ examples/multi_process/hotplug_mp/commands.c | 356 +++++++++++++++++++++++++++ examples/multi_process/hotplug_mp/commands.h | 10 + examples/multi_process/hotplug_mp/main.c | 41 +++ 5 files changed, 431 insertions(+) create mode 100644 examples/multi_process/hotplug_mp/Makefile create mode 100644 examples/multi_process/hotplug_mp/commands.c create mode 100644 examples/multi_process/hotplug_mp/commands.h create mode 100644 examples/multi_process/hotplug_mp/main.c diff --git a/examples/multi_process/Makefile b/examples/multi_process/Makefile index a6708b7e4..b76b02fcb 100644 --- a/examples/multi_process/Makefile +++ b/examples/multi_process/Makefile @@ -13,5 +13,6 @@ include $(RTE_SDK)/mk/rte.vars.mk DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += client_server_mp DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += simple_mp DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += symmetric_mp +DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += hotplug_mp include $(RTE_SDK)/mk/rte.extsubdir.mk diff --git a/examples/multi_process/hotplug_mp/Makefile b/examples/multi_process/hotplug_mp/Makefile new file mode 100644 index 000000000..c09a57bfa --- /dev/null +++ b/examples/multi_process/hotplug_mp/Makefile @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2010-2014 Intel Corporation + +ifeq ($(RTE_SDK),) +$(error "Please define RTE_SDK environment variable") +endif + +# Default target, can be overridden by command line or environment +RTE_TARGET ?= x86_64-native-linuxapp-gcc + +include $(RTE_SDK)/mk/rte.vars.mk + +# binary name +APP = hotplug_mp + +# all source are stored in SRCS-y +SRCS-y := main.c commands.c + +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) +CFLAGS += -DALLOW_EXPERIMENTAL_API + +include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/examples/multi_process/hotplug_mp/commands.c b/examples/multi_process/hotplug_mp/commands.c new file mode 100644 index 000000000..31f9e2e15 --- /dev/null +++ b/examples/multi_process/hotplug_mp/commands.c @@ -0,0 +1,356 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation. + */ + +#include +#include +#include +#include +#include +#include +#include + +/**********************************************************/ + +struct cmd_help_result { + cmdline_fixed_string_t help; +}; + +static void cmd_help_parsed(__attribute__((unused)) void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + cmdline_printf(cl, + "commands:\n" + "- attach \n" + "- detach \n" + "- attachp \n" + "- detachp \n" + "- lock \n" + "- unlock \n" + "- list\n\n"); +} + +cmdline_parse_token_string_t cmd_help_help = + TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); + +cmdline_parse_inst_t cmd_help = { + .f = cmd_help_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "show help", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_help_help, + NULL, + }, +}; + +/**********************************************************/ + +struct cmd_quit_result { + cmdline_fixed_string_t quit; +}; + +static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + cmdline_quit(cl); +} + +cmdline_parse_token_string_t cmd_quit_quit = + TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); + +cmdline_parse_inst_t cmd_quit = { + .f = cmd_quit_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "quit", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_quit_quit, + NULL, + }, +}; + +/**********************************************************/ + +struct cmd_list_result { + cmdline_fixed_string_t list; +}; + +static void cmd_list_parsed(__attribute__((unused)) void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + uint16_t port_id; + char dev_name[RTE_DEV_NAME_MAX_LEN]; + + cmdline_printf(cl, "list all etherdev\n"); + + RTE_ETH_FOREACH_DEV(port_id) { + rte_eth_dev_get_name_by_port(port_id, dev_name); + if (strlen(dev_name) > 0) + cmdline_printf(cl, "%d\t%s\n", port_id, dev_name); + else + printf("empty dev_name is not expected!\n"); + } +} + +cmdline_parse_token_string_t cmd_list_list = + TOKEN_STRING_INITIALIZER(struct cmd_list_result, list, "list"); + +cmdline_parse_inst_t cmd_list = { + .f = cmd_list_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "list all devices", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_list_list, + NULL, + }, +}; + +/**********************************************************/ + +struct cmd_dev_attach_result { + cmdline_fixed_string_t attach; + cmdline_fixed_string_t device; +}; + +static void cmd_dev_attach_parsed(void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_dev_attach_result *res = parsed_result; + uint16_t port_id; + + if (!rte_eth_dev_attach(res->device, &port_id)) + cmdline_printf(cl, "attached device %s at port %d\n", + res->device, port_id); + else + cmdline_printf(cl, "failed to attached device %s\n", + res->device); +} + +cmdline_parse_token_string_t cmd_dev_attach_attach = + TOKEN_STRING_INITIALIZER(struct cmd_dev_attach_result, attach, + "attach"); +cmdline_parse_token_string_t cmd_dev_attach_device = + TOKEN_STRING_INITIALIZER(struct cmd_dev_attach_result, device, NULL); + +cmdline_parse_inst_t cmd_attach_device = { + .f = cmd_dev_attach_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "attach a device", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_dev_attach_attach, + (void *)&cmd_dev_attach_device, + NULL, + }, +}; + +/**********************************************************/ + +struct cmd_dev_attachp_result { + cmdline_fixed_string_t attachp; + cmdline_fixed_string_t device; +}; + +static void cmd_dev_attachp_parsed(void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_dev_attachp_result *res = parsed_result; + uint16_t port_id; + + if (!rte_eth_dev_attach_private(res->device, &port_id)) + cmdline_printf(cl, "attached prviate device %s at port %d\n", + res->device, port_id); + else + cmdline_printf(cl, "failed to attached private device %s\n", + res->device); +} + +cmdline_parse_token_string_t cmd_dev_attachp_attachp = + TOKEN_STRING_INITIALIZER(struct cmd_dev_attachp_result, attachp, + "attachp"); +cmdline_parse_token_string_t cmd_dev_attachp_device = + TOKEN_STRING_INITIALIZER(struct cmd_dev_attachp_result, device, NULL); + +cmdline_parse_inst_t cmd_attachp_device = { + .f = cmd_dev_attachp_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "attach a private device", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_dev_attachp_attachp, + (void *)&cmd_dev_attachp_device, + NULL, + }, +}; + +/**********************************************************/ + +struct cmd_dev_detach_result { + cmdline_fixed_string_t detach; + uint16_t port_id; +}; + +static void cmd_dev_detach_parsed(void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_dev_detach_result *res = parsed_result; + uint16_t port_id = res->port_id; + char dev_name[RTE_DEV_NAME_MAX_LEN]; + + printf("detaching...\n"); + if (!rte_eth_dev_detach(port_id, dev_name)) + cmdline_printf(cl, "detached device at port %d\n", + port_id); + else + cmdline_printf(cl, "failed to dettached at port %d\n", + port_id); +} + +cmdline_parse_token_string_t cmd_dev_detach_detach = + TOKEN_STRING_INITIALIZER(struct cmd_dev_detach_result, detach, + "detach"); +cmdline_parse_token_num_t cmd_dev_detach_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_dev_detach_result, port_id, UINT16); + +cmdline_parse_inst_t cmd_detach_device = { + .f = cmd_dev_detach_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "detach a device", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_dev_detach_detach, + (void *)&cmd_dev_detach_port_id, + NULL, + }, +}; + +/**********************************************************/ + +struct cmd_dev_detachp_result { + cmdline_fixed_string_t detachp; + uint16_t port_id; +}; + +static void cmd_dev_detachp_parsed(void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_dev_detachp_result *res = parsed_result; + uint16_t port_id = res->port_id; + char dev_name[RTE_DEV_NAME_MAX_LEN]; + + printf("detaching...\n"); + if (!rte_eth_dev_detach_private(port_id, dev_name)) + cmdline_printf(cl, "detached private device at port %d\n", + port_id); + else + cmdline_printf(cl, "failed to detach private device at port %d\n", + port_id); +} + +cmdline_parse_token_string_t cmd_dev_detachp_detachp = + TOKEN_STRING_INITIALIZER(struct cmd_dev_detachp_result, detachp, + "detachp"); +cmdline_parse_token_num_t cmd_dev_detachp_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_dev_detachp_result, port_id, UINT16); + +cmdline_parse_inst_t cmd_detachp_device = { + .f = cmd_dev_detachp_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "detach a private device", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_dev_detachp_detachp, + (void *)&cmd_dev_detachp_port_id, + NULL, + }, +}; + +/**********************************************************/ + +struct cmd_dev_lock_result { + cmdline_fixed_string_t lock; + uint16_t port_id; +}; + +static void cmd_dev_lock_parsed(void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_dev_lock_result *res = parsed_result; + uint16_t port_id = res->port_id; + int ret = 0; + + ret = rte_eth_dev_lock(res->port_id); + cmdline_printf(cl, "lock port %d, ret = %d\n", port_id, ret); +} + +cmdline_parse_token_string_t cmd_dev_lock_lock = + TOKEN_STRING_INITIALIZER(struct cmd_dev_lock_result, lock, "lock"); +cmdline_parse_token_num_t cmd_dev_lock_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_dev_lock_result, port_id, UINT16); + +cmdline_parse_inst_t cmd_lock_device = { + .f = cmd_dev_lock_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "lock a device", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_dev_lock_lock, + (void *)&cmd_dev_lock_port_id, + NULL, + }, +}; + +/**********************************************************/ + +struct cmd_dev_unlock_result { + cmdline_fixed_string_t unlock; + uint16_t port_id; +}; + +static void cmd_dev_unlock_parsed(void *parsed_result, + struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_dev_unlock_result *res = parsed_result; + uint16_t port_id = res->port_id; + int ret = 0; + + ret = rte_eth_dev_unlock(res->port_id); + cmdline_printf(cl, "unlock port %d, ret = %d\n", port_id, ret); +} + +cmdline_parse_token_string_t cmd_dev_unlock_unlock = + TOKEN_STRING_INITIALIZER(struct cmd_dev_unlock_result, unlock, + "unlock"); +cmdline_parse_token_num_t cmd_dev_unlock_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_dev_unlock_result, port_id, UINT16); + +cmdline_parse_inst_t cmd_unlock_device = { + .f = cmd_dev_unlock_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = "unlock a device", + .tokens = { /* token list, NULL terminated */ + (void *)&cmd_dev_unlock_unlock, + (void *)&cmd_dev_unlock_port_id, + NULL, + }, +}; + +/**********************************************************/ +/**********************************************************/ +/****** CONTEXT (list of instruction) */ + +cmdline_parse_ctx_t main_ctx[] = { + (cmdline_parse_inst_t *)&cmd_help, + (cmdline_parse_inst_t *)&cmd_quit, + (cmdline_parse_inst_t *)&cmd_list, + (cmdline_parse_inst_t *)&cmd_attach_device, + (cmdline_parse_inst_t *)&cmd_detach_device, + (cmdline_parse_inst_t *)&cmd_attachp_device, + (cmdline_parse_inst_t *)&cmd_detachp_device, + (cmdline_parse_inst_t *)&cmd_lock_device, + (cmdline_parse_inst_t *)&cmd_unlock_device, + NULL, +}; diff --git a/examples/multi_process/hotplug_mp/commands.h b/examples/multi_process/hotplug_mp/commands.h new file mode 100644 index 000000000..afcf177db --- /dev/null +++ b/examples/multi_process/hotplug_mp/commands.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#ifndef _COMMANDS_H_ +#define _COMMANDS_H_ + +extern cmdline_parse_ctx_t main_ctx[]; + +#endif /* _COMMANDS_H_ */ diff --git a/examples/multi_process/hotplug_mp/main.c b/examples/multi_process/hotplug_mp/main.c new file mode 100644 index 000000000..d66858078 --- /dev/null +++ b/examples/multi_process/hotplug_mp/main.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "commands.h" + +int main(int argc, char **argv) +{ + int ret; + struct cmdline *cl; + + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_panic("Cannot init EAL\n"); + + cl = cmdline_stdin_new(main_ctx, "example> "); + if (cl == NULL) + rte_panic("Cannot create cmdline instance\n"); + cmdline_interact(cl); + cmdline_stdin_exit(cl); + + rte_eal_cleanup(); + + return 0; +}