1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. 5 * Copyright(c) 2014 6WIND S.A. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 #include <string.h> 35 #include <stdlib.h> 36 37 #include <rte_log.h> 38 #include <rte_string_fns.h> 39 40 #include "rte_kvargs.h" 41 42 /* 43 * Receive a string with a list of arguments following the pattern 44 * key=value;key=value;... and insert them into the list. 45 * strtok() is used so the params string will be copied to be modified. 46 */ 47 static int 48 rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *params) 49 { 50 unsigned i; 51 char *str; 52 char *ctx1 = NULL; 53 char *ctx2 = NULL; 54 55 /* Copy the const char *params to a modifiable string 56 * to pass to rte_strsplit 57 */ 58 kvlist->str = strdup(params); 59 if (kvlist->str == NULL) { 60 RTE_LOG(ERR, PMD, "Cannot parse arguments: not enough memory\n"); 61 return -1; 62 } 63 64 /* browse each key/value pair and add it in kvlist */ 65 str = kvlist->str; 66 while ((str = strtok_r(str, RTE_KVARGS_PAIRS_DELIM, &ctx1)) != NULL) { 67 68 i = kvlist->count; 69 if (i >= RTE_KVARGS_MAX) { 70 RTE_LOG(ERR, PMD, "Cannot parse arguments: list full\n"); 71 return -1; 72 } 73 74 kvlist->pairs[i].key = strtok_r(str, RTE_KVARGS_KV_DELIM, &ctx2); 75 kvlist->pairs[i].value = strtok_r(NULL, RTE_KVARGS_KV_DELIM, &ctx2); 76 if (kvlist->pairs[i].key == NULL || kvlist->pairs[i].value == NULL) { 77 RTE_LOG(ERR, PMD, 78 "Cannot parse arguments: wrong key or value\n" 79 "params=<%s>\n", params); 80 return -1; 81 } 82 83 kvlist->count++; 84 str = NULL; 85 } 86 87 return 0; 88 } 89 90 /* 91 * Determine whether a key is valid or not by looking 92 * into a list of valid keys. 93 */ 94 static int 95 is_valid_key(const char * const valid[], const char *key_match) 96 { 97 const char * const *valid_ptr; 98 99 for (valid_ptr = valid; *valid_ptr != NULL; valid_ptr++) { 100 if (strcmp(key_match, *valid_ptr) == 0) 101 return 1; 102 } 103 return 0; 104 } 105 106 /* 107 * Determine whether all keys are valid or not by looking 108 * into a list of valid keys. 109 */ 110 static int 111 check_for_valid_keys(struct rte_kvargs *kvlist, 112 const char * const valid[]) 113 { 114 unsigned i, ret; 115 struct rte_kvargs_pair *pair; 116 117 for (i = 0; i < kvlist->count; i++) { 118 pair = &kvlist->pairs[i]; 119 ret = is_valid_key(valid, pair->key); 120 if (!ret) { 121 RTE_LOG(ERR, PMD, 122 "Error parsing device, invalid key <%s>\n", 123 pair->key); 124 return -1; 125 } 126 } 127 return 0; 128 } 129 130 /* 131 * Return the number of times a given arg_name exists in the key/value list. 132 * E.g. given a list = { rx = 0, rx = 1, tx = 2 } the number of args for 133 * arg "rx" will be 2. 134 */ 135 unsigned 136 rte_kvargs_count(const struct rte_kvargs *kvlist, const char *key_match) 137 { 138 const struct rte_kvargs_pair *pair; 139 unsigned i, ret; 140 141 ret = 0; 142 for (i = 0; i < kvlist->count; i++) { 143 pair = &kvlist->pairs[i]; 144 if (key_match == NULL || strcmp(pair->key, key_match) == 0) 145 ret++; 146 } 147 148 return ret; 149 } 150 151 /* 152 * For each matching key, call the given handler function. 153 */ 154 int 155 rte_kvargs_process(const struct rte_kvargs *kvlist, 156 const char *key_match, 157 arg_handler_t handler, 158 void *opaque_arg) 159 { 160 const struct rte_kvargs_pair *pair; 161 unsigned i; 162 163 for (i = 0; i < kvlist->count; i++) { 164 pair = &kvlist->pairs[i]; 165 if (key_match == NULL || strcmp(pair->key, key_match) == 0) { 166 if ((*handler)(pair->key, pair->value, opaque_arg) < 0) 167 return -1; 168 } 169 } 170 return 0; 171 } 172 173 /* free the rte_kvargs structure */ 174 void 175 rte_kvargs_free(struct rte_kvargs *kvlist) 176 { 177 if (!kvlist) 178 return; 179 180 free(kvlist->str); 181 free(kvlist); 182 } 183 184 /* 185 * Parse the arguments "key=value;key=value;..." string and return 186 * an allocated structure that contains a key/value list. Also 187 * check if only valid keys were used. 188 */ 189 struct rte_kvargs * 190 rte_kvargs_parse(const char *args, const char * const valid_keys[]) 191 { 192 struct rte_kvargs *kvlist; 193 194 kvlist = malloc(sizeof(*kvlist)); 195 if (kvlist == NULL) 196 return NULL; 197 memset(kvlist, 0, sizeof(*kvlist)); 198 199 if (rte_kvargs_tokenize(kvlist, args) < 0) { 200 rte_kvargs_free(kvlist); 201 return NULL; 202 } 203 204 if (valid_keys != NULL && check_for_valid_keys(kvlist, valid_keys) < 0) { 205 rte_kvargs_free(kvlist); 206 return NULL; 207 } 208 209 return kvlist; 210 } 211