From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wg0-f52.google.com (mail-wg0-f52.google.com [74.125.82.52]) by dpdk.org (Postfix) with ESMTP id 470EA678E for ; Tue, 28 Jan 2014 17:05:50 +0100 (CET) Received: by mail-wg0-f52.google.com with SMTP id b13so1191763wgh.7 for ; Tue, 28 Jan 2014 08:07:08 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=szalQJzUkZvYK6WnZrX0vZlVgmBrmLMcujevdnLr6X8=; b=F2cSbASF1qARuEG9theqSvEMdcw7xORIEQJSHX9FC14AwRMcn+PqHMfSmIXLlMReYi TpANd6yiaSL/qbSbvSNgJGT+oEYUYTLalUg/5PfkbE1QVYdxD0A4FVvaLCT+XnnxIm9n XmkZLUzimgvwwi7b8xK3P0AYPNgW2EHsGoCE6kskFjI5JGhd2P7RtKYbJuBVA8kOysWA Qq3IARXr78Dk69wE9zU2wh2tO/K8Ifpj0bXv98jln8Boaj0pPDQSE3MXHGiJSTjWzXaU CoHA1JFyHG037W/nh2vObMjLtJsBj2qSwBX+TREuiy3fkSuLL5BIE3OybKuH8gJR4aYf HaLg== X-Gm-Message-State: ALoCoQlgJOkdbHWD+NiJvs+NSlRmZQJDTlFIfV13swvCRzTweua9A6uLjh3lBSJciAbGrd5TKxZc X-Received: by 10.194.63.228 with SMTP id j4mr1646407wjs.34.1390925228717; Tue, 28 Jan 2014 08:07:08 -0800 (PST) Received: from glumotte.dev.6wind.com (6wind.net2.nerim.net. [213.41.180.237]) by mx.google.com with ESMTPSA id d6sm36407821wic.9.2014.01.28.08.07.07 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jan 2014 08:07:07 -0800 (PST) From: Olivier Matz To: dev@dpdk.org Date: Tue, 28 Jan 2014 17:06:34 +0100 Message-Id: <1390925204-10800-2-git-send-email-olivier.matz@6wind.com> X-Mailer: git-send-email 1.8.4.rc3 In-Reply-To: <1390925204-10800-1-git-send-email-olivier.matz@6wind.com> References: <1390925204-10800-1-git-send-email-olivier.matz@6wind.com> Subject: [dpdk-dev] [PATCH 01/11] kvargs: add a new library to parse key/value arguments X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Jan 2014 16:05:50 -0000 Copy the code from rte_eth_pcap_arg_parser.[ch], without any functional modifications, only: - rename functions and structure - restyle (indentation) - add comments (doxygen style) - add "const" or "static" attributes, remove unneeded "inline" Signed-off-by: Olivier Matz --- config/defconfig_i686-default-linuxapp-gcc | 5 + config/defconfig_i686-default-linuxapp-icc | 5 + config/defconfig_x86_64-default-linuxapp-gcc | 5 + config/defconfig_x86_64-default-linuxapp-icc | 5 + lib/Makefile | 1 + lib/librte_kvargs/Makefile | 50 ++++++ lib/librte_kvargs/rte_kvargs.c | 248 +++++++++++++++++++++++++++ lib/librte_kvargs/rte_kvargs.h | 159 +++++++++++++++++ mk/rte.app.mk | 4 + 9 files changed, 482 insertions(+) create mode 100644 lib/librte_kvargs/Makefile create mode 100644 lib/librte_kvargs/rte_kvargs.c create mode 100644 lib/librte_kvargs/rte_kvargs.h diff --git a/config/defconfig_i686-default-linuxapp-gcc b/config/defconfig_i686-default-linuxapp-gcc index 4f57242..349ca24 100644 --- a/config/defconfig_i686-default-linuxapp-gcc +++ b/config/defconfig_i686-default-linuxapp-gcc @@ -141,6 +141,11 @@ CONFIG_RTE_LIBRTE_EAL_BAREMETAL=n CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y # +# Compile the argument parser library +# +CONFIG_RTE_LIBRTE_KVARGS=y + +# # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y diff --git a/config/defconfig_i686-default-linuxapp-icc b/config/defconfig_i686-default-linuxapp-icc index 90521e1..4e7338f 100644 --- a/config/defconfig_i686-default-linuxapp-icc +++ b/config/defconfig_i686-default-linuxapp-icc @@ -141,6 +141,11 @@ CONFIG_RTE_LIBRTE_EAL_BAREMETAL=n CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y # +# Compile the argument parser library +# +CONFIG_RTE_LIBRTE_KVARGS=y + +# # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y diff --git a/config/defconfig_x86_64-default-linuxapp-gcc b/config/defconfig_x86_64-default-linuxapp-gcc index 4c05ffc..ca85b1a 100644 --- a/config/defconfig_x86_64-default-linuxapp-gcc +++ b/config/defconfig_x86_64-default-linuxapp-gcc @@ -141,6 +141,11 @@ CONFIG_RTE_LIBRTE_EAL_BAREMETAL=n CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y # +# Compile the argument parser library +# +CONFIG_RTE_LIBRTE_KVARGS=y + +# # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y diff --git a/config/defconfig_x86_64-default-linuxapp-icc b/config/defconfig_x86_64-default-linuxapp-icc index c4d5c73..37dbdd0 100644 --- a/config/defconfig_x86_64-default-linuxapp-icc +++ b/config/defconfig_x86_64-default-linuxapp-icc @@ -141,6 +141,11 @@ CONFIG_RTE_LIBRTE_EAL_BAREMETAL=n CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y # +# Compile the argument parser library +# +CONFIG_RTE_LIBRTE_KVARGS=y + +# # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y diff --git a/lib/Makefile b/lib/Makefile index b655d4f..31644f2 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -52,6 +52,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl +DIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += librte_kvargs ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_kvargs/Makefile b/lib/librte_kvargs/Makefile new file mode 100644 index 0000000..c4c2855 --- /dev/null +++ b/lib/librte_kvargs/Makefile @@ -0,0 +1,50 @@ +# BSD LICENSE +# +# Copyright(c) 2014 6WIND S.A. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_kvargs.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) := rte_kvargs.c + +# install includes +INCS := rte_kvargs.h +SYMLINK-$(CONFIG_RTE_LIBRTE_KVARGS)-include := $(INCS) + +# this lib needs eal and malloc +DEPDIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_KVARGS) += lib/librte_malloc + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_kvargs/rte_kvargs.c b/lib/librte_kvargs/rte_kvargs.c new file mode 100644 index 0000000..7a950d6 --- /dev/null +++ b/lib/librte_kvargs/rte_kvargs.c @@ -0,0 +1,248 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * Copyright(c) 2014 6WIND S.A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#include +#include +#include + +#include "rte_kvargs.h" + +/* + * Initialize a rte_kvargs structure to an empty key/value list. + */ +int +rte_kvargs_init(struct rte_kvargs *kvlist) +{ + kvlist->count = 0; + kvlist->size = RTE_KVARGS_MAX; + memset(kvlist->pairs, 0, kvlist->size); + return 0; +} + +/* + * Add a key-value pair at the end of a given key/value list. + * Return an error if the list is full or if the key is duplicated. + */ +static int +rte_kvargs_add_pair(struct rte_kvargs *kvlist, char *key, char *val) +{ + unsigned i; + struct rte_kvargs_pair* entry; + + /* is the list full? */ + if (kvlist->count >= kvlist->size) { + RTE_LOG(ERR, PMD, "Couldn't add %s, key/value list is full\n", key); + return -1; + } + + /* Check if the key is duplicated */ + for (i = 0; i < kvlist->count; i++) { + entry = &kvlist->pairs[i]; + if (strcmp(entry->key, key) == 0) { + RTE_LOG(ERR, PMD, "Couldn't add %s, duplicated key\n", key); + return -1; + } + } + + entry = &kvlist->pairs[kvlist->count]; + entry->key = key; + entry->value = val; + kvlist->count++; + return 0; +} + +/* + * Receive a string with a list of arguments following the pattern + * key=value;key=value;... and insert them into the list. + * strtok() is used so the params string will be copied to be modified. + */ +static int +rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *name, + const char *params) +{ + unsigned i, count; + char *args; + char *pairs[RTE_KVARGS_MAX]; + char *pair[2]; + + /* If params are empty, nothing to do */ + if (params == NULL || params[0] == 0) { + RTE_LOG(ERR, PMD, "Couldn't parse %s device, empty arguments\n", name); + return -1; + } + + /* Copy the const char *params to a modifiable string + * to pass to rte_strsplit + */ + args = strdup(params); + if(args == NULL){ + RTE_LOG(ERR, PMD, "Couldn't parse %s device \n", name); + return -1; + } + + count = rte_strsplit(args, strnlen(args, MAX_ARG_STRLEN), pairs, + RTE_KVARGS_MAX, RTE_KVARGS_PAIRS_DELIM); + + for (i = 0; i < count; i++) { + pair[0] = NULL; + pair[1] = NULL; + + rte_strsplit(pairs[i], strnlen(pairs[i], MAX_ARG_STRLEN), pair, 2, + RTE_KVARGS_KV_DELIM); + + if (pair[0] == NULL || pair[1] == NULL || pair[0][0] == 0 + || pair[1][0] == 0) { + RTE_LOG(ERR, PMD, + "Couldn't parse %s device, wrong key or value \n", name); + goto error; + } + + if (rte_kvargs_add_pair(kvlist, pair[0], pair[1]) < 0) + goto error; + } + return 0; + +error: + rte_free(args); + return -1; +} + +/* + * Determine whether a key is valid or not by looking + * into a list of valid keys. + */ +static int +is_valid_key(const char *valid[], const char *key_match) +{ + const char **valid_ptr; + + for (valid_ptr = valid; *valid_ptr != NULL; valid_ptr++) + if (strstr(key_match, *valid_ptr) != NULL) + return 1; + return 0; +} + +/* + * Determine whether all keys are valid or not by looking + * into a list of valid keys. + */ +static int +check_for_valid_keys(struct rte_kvargs *kvlist, + const char *valid[]) +{ + unsigned i, ret; + struct rte_kvargs_pair *pair; + + for (i = 0; i < kvlist->count; i++) { + pair = &kvlist->pairs[i]; + ret = is_valid_key(valid, pair->key); + if (!ret) { + RTE_LOG(ERR, PMD, + "Error parsing device, invalid key <%s>\n", + pair->key); + return -1; + } + } + return 0; +} + +/* + * Return the number of times a given arg_name exists in the key/value list. + * E.g. given a list = { rx = 0, rx = 1, tx = 2 } the number of args for + * arg "rx" will be 2. + */ +unsigned +rte_kvargs_count(const struct rte_kvargs *kvlist, const char *key_match) +{ + const struct rte_kvargs_pair *pair; + unsigned i, ret; + + ret = 0; + for (i = 0; i < kvlist->count; i++) { + pair = &kvlist->pairs[i]; + if (strcmp(pair->key, key_match) == 0) + ret++; + } + + return ret; +} + +/* + * For each matching key, call the given handler function. + */ +int +rte_kvargs_process(const struct rte_kvargs *kvlist, + const char *key_match, + arg_handler_t handler, + void *opaque_arg) +{ + const struct rte_kvargs_pair *pair; + unsigned i; + + for (i = 0; i < kvlist->count; i++) { + pair = &kvlist->pairs[i]; + if (strstr(pair->key, key_match) != NULL) { + if ((*handler)(pair->value, opaque_arg) < 0) + return -1; + } + } + return 0; +} + +/* + * Parse the arguments "key=value;key=value;..." string and return + * an allocated structure that contains a key/value list. Also + * check if only valid keys were used. + */ +int +rte_kvargs_parse(struct rte_kvargs *kvlist, + const char *name, + const char *args, + const char *valid_keys[]) +{ + + int ret; + + ret = rte_kvargs_tokenize(kvlist, name, args); + if (ret < 0) + return ret; + + if (valid_keys == NULL) + return 0; + + return check_for_valid_keys(kvlist, valid_keys); +} diff --git a/lib/librte_kvargs/rte_kvargs.h b/lib/librte_kvargs/rte_kvargs.h new file mode 100644 index 0000000..19485b1 --- /dev/null +++ b/lib/librte_kvargs/rte_kvargs.h @@ -0,0 +1,159 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. + * Copyright(c) 2014 6WIND S.A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_KVARGS_H_ +#define _RTE_KVARGS_H_ + +/** + * @file + * RTE Argument parsing + * + * This module can be used to parse arguments whose format is + * key1=value1;key2=value2;key3=value3;... + * + * This file provides some helpers that are especially used by virtual + * ethernet devices at initialization for arguments parsing. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Maximum number of key/value associations */ +#define RTE_KVARGS_MAX 32 + +/** separator character used between each pair */ +#define RTE_KVARGS_PAIRS_DELIM ';' + +/** separator character used between key and value */ +#define RTE_KVARGS_KV_DELIM '=' + +/** Type of callback function used by rte_kvargs_process() */ +typedef int (*arg_handler_t)(char *value, void *opaque); + +/** A key/value association */ +struct rte_kvargs_pair { + char *key; /**< the name (key) of the association */ + char *value; /**< the value associated to that key */ +}; + +/** Store a list of key/value associations */ +struct rte_kvargs { + unsigned count; /**< number of entries in the list */ + size_t size; /**< maximum number of entries */ + struct rte_kvargs_pair pairs[RTE_KVARGS_MAX]; /**< list of key/values */ +}; + +/** + * Initialize an empty rte_kvargs structure + * + * Set the content of the rte_kvargs structure given as a parameter + * to an empty list of key/value. + * + * @param kvlist + * The rte_kvargs structure + * + * @return + * - 0 on success + * - Negative on error + */ +int rte_kvargs_init(struct rte_kvargs *kvlist); + +/** + * Append key/value associations in a rte_kvargs structure from a string + * + * The function fills a rte_kvargs structure from a string whose format + * is key1=value1;key2=value2;... + * The key/value associations are appended to those which are already + * present in the rte_kvargs structure. + * + * @param kvlist + * The rte_kvargs structure + * @param name + * The name of the driver + * @param args + * The input string containing the key/value associations + * @param valid_keys + * A list of valid keys (table of const char *, the last must be NULL). + * This argument is ignored if NULL + * + * @return + * - 0 on success + * - Negative on error + */ +int rte_kvargs_parse(struct rte_kvargs *kvlist, const char *name, + const char *args, const char *valid_keys[]); + +/** + * Call a handler function for each key/value matching the key + * + * For each key/value association that matches the given key, calls the + * handler function with the for a given arg_name passing the value on the + * dictionary for that key and a given extra argument. + * + * @param kvlist + * The rte_kvargs structure + * @param key_match + * The key on which the handler should be called + * @param handler + * The function to call for each matching key + * @param opaque_arg + * A pointer passed unchanged to the handler + * + * @return + * - 0 on success + * - Negative on error + */ +int rte_kvargs_process(const struct rte_kvargs *kvlist, + const char *key_match, arg_handler_t handler, void *opaque_arg); + +/** + * Count the number of associations matching the given key + * + * @param kvlist + * The rte_kvargs structure + * @param key_match + * The key that should match + + * @return + * The number of entries + */ +unsigned rte_kvargs_count(const struct rte_kvargs *kvlist, + const char *key_match); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 786100c..1652029 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -112,6 +112,10 @@ endif LDLIBS += --start-group +ifeq ($(CONFIG_RTE_LIBRTE_KVARGS),y) +LDLIBS += -lrte_kvargs +endif + ifeq ($(CONFIG_RTE_LIBRTE_MBUF),y) LDLIBS += -lrte_mbuf endif -- 1.8.4.rc3