From patchwork Thu Jun 7 12:38:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qi Zhang X-Patchwork-Id: 40766 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 405AC1B685; Thu, 7 Jun 2018 14:39:08 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 4B5911B66E for ; Thu, 7 Jun 2018 14:39:04 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Jun 2018 05:39:03 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,486,1520924400"; d="scan'208";a="62605697" Received: from dpdk51.sh.intel.com ([10.67.110.184]) by orsmga001.jf.intel.com with ESMTP; 07 Jun 2018 05:39:02 -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, 7 Jun 2018 20:38:49 +0800 Message-Id: <20180607123849.14439-23-qi.z.zhang@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180607123849.14439-1-qi.z.zhang@intel.com> References: <20180607123849.14439-1-qi.z.zhang@intel.com> Subject: [dpdk-dev] [PATCH 22/22] examples/devmgm_mp: add simple device management 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? ./devmgm_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/devmgm_mp/Makefile | 64 +++++++ examples/devmgm_mp/commands.c | 383 +++++++++++++++++++++++++++++++++++++++++ examples/devmgm_mp/commands.h | 10 ++ examples/devmgm_mp/main.c | 41 +++++ examples/devmgm_mp/meson.build | 11 ++ 5 files changed, 509 insertions(+) create mode 100644 examples/devmgm_mp/Makefile create mode 100644 examples/devmgm_mp/commands.c create mode 100644 examples/devmgm_mp/commands.h create mode 100644 examples/devmgm_mp/main.c create mode 100644 examples/devmgm_mp/meson.build diff --git a/examples/devmgm_mp/Makefile b/examples/devmgm_mp/Makefile new file mode 100644 index 000000000..e6c0cb0c5 --- /dev/null +++ b/examples/devmgm_mp/Makefile @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2010-2014 Intel Corporation + +# binary name +APP = devmgm_mp + +# all source are stored in SRCS-y +SRCS-y := main.c commands.c + +# Build using pkg-config variables if possible +$(shell pkg-config --exists libdpdk) +ifeq ($(.SHELLSTATUS),0) + +all: shared +.PHONY: shared static +shared: build/$(APP)-shared + ln -sf $(APP)-shared build/$(APP) +static: build/$(APP)-static + ln -sf $(APP)-static build/$(APP) + +PC_FILE := $(shell pkg-config --path libdpdk) +CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) +LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) +LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) + +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build + $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) + +build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build + $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) + +build: + @mkdir -p $@ + +.PHONY: clean +clean: + rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared + rmdir --ignore-fail-on-non-empty build + +else + +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 = devmgm_mp + +# all source are stored in SRCS-y +SRCS-y := main.c commands.c + +CFLAGS += -O3 +CFLAGS += -DALLOW_EXPERIMENTAL_API +CFLAGS += $(WERROR_FLAGS) +CFLAGS_parse_obj_list.o := -D_GNU_SOURCE + +include $(RTE_SDK)/mk/rte.extapp.mk + +endif diff --git a/examples/devmgm_mp/commands.c b/examples/devmgm_mp/commands.c new file mode 100644 index 000000000..145cb766e --- /dev/null +++ b/examples/devmgm_mp/commands.c @@ -0,0 +1,383 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation. + * Copyright (c) 2009, Olivier MATZ + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef __linux__ + #ifdef __FreeBSD__ + #include + #else + #include + #endif +#endif + +#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); + /* Secondary process's ethdev->state may not be + * updated after detach on primary process, but + * ethdev->data should already be reset, so + * use strlen(dev_name) == 0 to know the port is + * not used. + * + * TODO: Secondary process should be informed when a + * port is released on primary through mp channel. + */ + 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, NULL, NULL); + 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, NULL, NULL); + 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/devmgm_mp/commands.h b/examples/devmgm_mp/commands.h new file mode 100644 index 000000000..791204547 --- /dev/null +++ b/examples/devmgm_mp/commands.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation + */ + +#ifndef _COMMANDS_H_ +#define _COMMANDS_H_ + +extern cmdline_parse_ctx_t main_ctx[]; + +#endif /* _COMMANDS_H_ */ diff --git a/examples/devmgm_mp/main.c b/examples/devmgm_mp/main.c new file mode 100644 index 000000000..f2f2e5a2f --- /dev/null +++ b/examples/devmgm_mp/main.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation. + * Copyright (c) 2009, Olivier MATZ + * All rights reserved. + */ + +#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); + + return 0; +} diff --git a/examples/devmgm_mp/meson.build b/examples/devmgm_mp/meson.build new file mode 100644 index 000000000..f916eb9af --- /dev/null +++ b/examples/devmgm_mp/meson.build @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +sources = files( + 'commands.c', 'main.c' +)