1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2014 6WIND S.A. 3 */ 4 5 /* This file manages the list of devices and their arguments, as given 6 * by the user at startup 7 */ 8 9 #include <stdio.h> 10 #include <string.h> 11 #include <stdarg.h> 12 13 #include <rte_bus.h> 14 #include <rte_class.h> 15 #include <rte_compat.h> 16 #include <rte_dev.h> 17 #include <rte_devargs.h> 18 #include <rte_errno.h> 19 #include <rte_kvargs.h> 20 #include <rte_log.h> 21 #include <rte_tailq.h> 22 #include <rte_string_fns.h> 23 #include "eal_private.h" 24 25 /** user device double-linked queue type definition */ 26 TAILQ_HEAD(rte_devargs_list, rte_devargs); 27 28 /** Global list of user devices */ 29 static struct rte_devargs_list devargs_list = 30 TAILQ_HEAD_INITIALIZER(devargs_list); 31 32 static size_t 33 devargs_layer_count(const char *s) 34 { 35 size_t i = s ? 1 : 0; 36 37 while (s != NULL && s[0] != '\0') { 38 i += s[0] == '/'; 39 s++; 40 } 41 return i; 42 } 43 44 /* Resolve devargs name from bus arguments. */ 45 static int 46 devargs_bus_parse_default(struct rte_devargs *devargs, 47 struct rte_kvargs *bus_args) 48 { 49 const char *name; 50 51 /* Parse devargs name from bus key-value list. */ 52 name = rte_kvargs_get(bus_args, "name"); 53 if (name == NULL) { 54 RTE_LOG(INFO, EAL, "devargs name not found: %s\n", 55 devargs->data); 56 return 0; 57 } 58 if (rte_strscpy(devargs->name, name, sizeof(devargs->name)) < 0) { 59 RTE_LOG(ERR, EAL, "devargs name too long: %s\n", 60 devargs->data); 61 return -E2BIG; 62 } 63 return 0; 64 } 65 66 int 67 rte_devargs_layers_parse(struct rte_devargs *devargs, 68 const char *devstr) 69 { 70 struct { 71 const char *key; 72 const char *str; 73 struct rte_kvargs *kvlist; 74 } layers[] = { 75 { RTE_DEVARGS_KEY_BUS "=", NULL, NULL, }, 76 { RTE_DEVARGS_KEY_CLASS "=", NULL, NULL, }, 77 { RTE_DEVARGS_KEY_DRIVER "=", NULL, NULL, }, 78 }; 79 struct rte_kvargs_pair *kv = NULL; 80 struct rte_class *cls = NULL; 81 struct rte_bus *bus = NULL; 82 const char *s = devstr; 83 size_t nblayer; 84 size_t i = 0; 85 int ret = 0; 86 bool allocated_data = false; 87 88 /* Split each sub-lists. */ 89 nblayer = devargs_layer_count(devstr); 90 if (nblayer > RTE_DIM(layers)) { 91 RTE_LOG(ERR, EAL, "Invalid format: too many layers (%zu)\n", 92 nblayer); 93 ret = -E2BIG; 94 goto get_out; 95 } 96 97 /* If the devargs points the devstr 98 * as source data, then it should not allocate 99 * anything and keep referring only to it. 100 */ 101 if (devargs->data != devstr) { 102 devargs->data = strdup(devstr); 103 if (devargs->data == NULL) { 104 RTE_LOG(ERR, EAL, "OOM\n"); 105 ret = -ENOMEM; 106 goto get_out; 107 } 108 allocated_data = true; 109 s = devargs->data; 110 } 111 112 while (s != NULL) { 113 if (i >= RTE_DIM(layers)) { 114 RTE_LOG(ERR, EAL, "Unrecognized layer %s\n", s); 115 ret = -EINVAL; 116 goto get_out; 117 } 118 /* 119 * The last layer is free-form. 120 * The "driver" key is not required (but accepted). 121 */ 122 if (strncmp(layers[i].key, s, strlen(layers[i].key)) && 123 i != RTE_DIM(layers) - 1) 124 goto next_layer; 125 layers[i].str = s; 126 layers[i].kvlist = rte_kvargs_parse_delim(s, NULL, "/"); 127 if (layers[i].kvlist == NULL) { 128 ret = -EINVAL; 129 goto get_out; 130 } 131 s = strchr(s, '/'); 132 if (s != NULL) 133 s++; 134 next_layer: 135 i++; 136 } 137 138 /* Parse each sub-list. */ 139 for (i = 0; i < RTE_DIM(layers); i++) { 140 if (layers[i].kvlist == NULL) 141 continue; 142 kv = &layers[i].kvlist->pairs[0]; 143 if (kv->key == NULL) 144 continue; 145 if (strcmp(kv->key, RTE_DEVARGS_KEY_BUS) == 0) { 146 bus = rte_bus_find_by_name(kv->value); 147 if (bus == NULL) { 148 RTE_LOG(ERR, EAL, "Could not find bus \"%s\"\n", 149 kv->value); 150 ret = -EFAULT; 151 goto get_out; 152 } 153 } else if (strcmp(kv->key, RTE_DEVARGS_KEY_CLASS) == 0) { 154 cls = rte_class_find_by_name(kv->value); 155 if (cls == NULL) { 156 RTE_LOG(ERR, EAL, "Could not find class \"%s\"\n", 157 kv->value); 158 ret = -EFAULT; 159 goto get_out; 160 } 161 } else if (strcmp(kv->key, RTE_DEVARGS_KEY_DRIVER) == 0) { 162 /* Ignore */ 163 continue; 164 } 165 } 166 167 /* Fill devargs fields. */ 168 devargs->bus_str = layers[0].str; 169 devargs->cls_str = layers[1].str; 170 devargs->drv_str = layers[2].str; 171 devargs->bus = bus; 172 devargs->cls = cls; 173 174 /* If we own the data, clean up a bit 175 * the several layers string, to ease 176 * their parsing afterward. 177 */ 178 if (devargs->data != devstr) { 179 char *s = devargs->data; 180 181 while ((s = strchr(s, '/'))) { 182 *s = '\0'; 183 s++; 184 } 185 } 186 187 /* Resolve devargs name. */ 188 if (bus != NULL && bus->devargs_parse != NULL) 189 ret = bus->devargs_parse(devargs); 190 else if (layers[0].kvlist != NULL) 191 ret = devargs_bus_parse_default(devargs, layers[0].kvlist); 192 193 get_out: 194 for (i = 0; i < RTE_DIM(layers); i++) { 195 if (layers[i].kvlist) 196 rte_kvargs_free(layers[i].kvlist); 197 } 198 if (ret != 0) { 199 if (allocated_data) { 200 /* Free duplicated data. */ 201 free(devargs->data); 202 devargs->data = NULL; 203 } 204 rte_errno = -ret; 205 } 206 return ret; 207 } 208 209 static int 210 bus_name_cmp(const struct rte_bus *bus, const void *name) 211 { 212 return strncmp(bus->name, name, strlen(bus->name)); 213 } 214 215 int 216 rte_devargs_parse(struct rte_devargs *da, const char *dev) 217 { 218 struct rte_bus *bus = NULL; 219 const char *devname; 220 const size_t maxlen = sizeof(da->name); 221 size_t i; 222 223 if (da == NULL) 224 return -EINVAL; 225 226 /* First parse according global device syntax. */ 227 if (rte_devargs_layers_parse(da, dev) == 0) { 228 if (da->bus != NULL || da->cls != NULL) 229 return 0; 230 rte_devargs_reset(da); 231 } 232 233 /* Otherwise fallback to legacy syntax: */ 234 235 /* Retrieve eventual bus info */ 236 do { 237 devname = dev; 238 bus = rte_bus_find(bus, bus_name_cmp, dev); 239 if (bus == NULL) 240 break; 241 devname = dev + strlen(bus->name) + 1; 242 if (rte_bus_find_by_device_name(devname) == bus) 243 break; 244 } while (1); 245 /* Store device name */ 246 i = 0; 247 while (devname[i] != '\0' && devname[i] != ',') { 248 da->name[i] = devname[i]; 249 i++; 250 if (i == maxlen) { 251 RTE_LOG(WARNING, EAL, "Parsing \"%s\": device name should be shorter than %zu\n", 252 dev, maxlen); 253 da->name[i - 1] = '\0'; 254 return -EINVAL; 255 } 256 } 257 da->name[i] = '\0'; 258 if (bus == NULL) { 259 bus = rte_bus_find_by_device_name(da->name); 260 if (bus == NULL) { 261 RTE_LOG(ERR, EAL, "failed to parse device \"%s\"\n", 262 da->name); 263 return -EFAULT; 264 } 265 } 266 da->bus = bus; 267 /* Parse eventual device arguments */ 268 if (devname[i] == ',') 269 da->data = strdup(&devname[i + 1]); 270 else 271 da->data = strdup(""); 272 if (da->data == NULL) { 273 RTE_LOG(ERR, EAL, "not enough memory to parse arguments\n"); 274 return -ENOMEM; 275 } 276 da->drv_str = da->data; 277 return 0; 278 } 279 280 int 281 rte_devargs_parsef(struct rte_devargs *da, const char *format, ...) 282 { 283 va_list ap; 284 int len; 285 char *dev; 286 int ret; 287 288 if (da == NULL) 289 return -EINVAL; 290 291 va_start(ap, format); 292 len = vsnprintf(NULL, 0, format, ap); 293 va_end(ap); 294 if (len < 0) 295 return -EINVAL; 296 297 len += 1; 298 dev = calloc(1, (size_t)len); 299 if (dev == NULL) { 300 RTE_LOG(ERR, EAL, "not enough memory to parse device\n"); 301 return -ENOMEM; 302 } 303 304 va_start(ap, format); 305 vsnprintf(dev, (size_t)len, format, ap); 306 va_end(ap); 307 308 ret = rte_devargs_parse(da, dev); 309 310 free(dev); 311 return ret; 312 } 313 314 void 315 rte_devargs_reset(struct rte_devargs *da) 316 { 317 if (da == NULL) 318 return; 319 if (da->data) 320 free(da->data); 321 da->data = NULL; 322 } 323 324 int 325 rte_devargs_insert(struct rte_devargs **da) 326 { 327 struct rte_devargs *listed_da; 328 void *tmp; 329 330 if (*da == NULL || (*da)->bus == NULL) 331 return -1; 332 333 RTE_TAILQ_FOREACH_SAFE(listed_da, &devargs_list, next, tmp) { 334 if (listed_da == *da) 335 /* devargs already in the list */ 336 return 0; 337 if (strcmp(listed_da->bus->name, (*da)->bus->name) == 0 && 338 strcmp(listed_da->name, (*da)->name) == 0) { 339 /* device already in devargs list, must be updated */ 340 (*da)->next = listed_da->next; 341 rte_devargs_reset(listed_da); 342 *listed_da = **da; 343 /* replace provided devargs with found one */ 344 free(*da); 345 *da = listed_da; 346 return 0; 347 } 348 } 349 /* new device in the list */ 350 TAILQ_INSERT_TAIL(&devargs_list, *da, next); 351 return 0; 352 } 353 354 /* store in allowed list parameter for later parsing */ 355 int 356 rte_devargs_add(enum rte_devtype devtype, const char *devargs_str) 357 { 358 struct rte_devargs *devargs = NULL; 359 struct rte_bus *bus = NULL; 360 const char *dev = devargs_str; 361 362 /* use calloc instead of rte_zmalloc as it's called early at init */ 363 devargs = calloc(1, sizeof(*devargs)); 364 if (devargs == NULL) 365 goto fail; 366 367 if (rte_devargs_parse(devargs, dev)) 368 goto fail; 369 devargs->type = devtype; 370 bus = devargs->bus; 371 if (devargs->type == RTE_DEVTYPE_BLOCKED) 372 devargs->policy = RTE_DEV_BLOCKED; 373 if (bus->conf.scan_mode == RTE_BUS_SCAN_UNDEFINED) { 374 if (devargs->policy == RTE_DEV_ALLOWED) 375 bus->conf.scan_mode = RTE_BUS_SCAN_ALLOWLIST; 376 else if (devargs->policy == RTE_DEV_BLOCKED) 377 bus->conf.scan_mode = RTE_BUS_SCAN_BLOCKLIST; 378 } 379 TAILQ_INSERT_TAIL(&devargs_list, devargs, next); 380 return 0; 381 382 fail: 383 if (devargs) { 384 rte_devargs_reset(devargs); 385 free(devargs); 386 } 387 388 return -1; 389 } 390 391 int 392 rte_devargs_remove(struct rte_devargs *devargs) 393 { 394 struct rte_devargs *d; 395 void *tmp; 396 397 if (devargs == NULL || devargs->bus == NULL) 398 return -1; 399 400 RTE_TAILQ_FOREACH_SAFE(d, &devargs_list, next, tmp) { 401 if (strcmp(d->bus->name, devargs->bus->name) == 0 && 402 strcmp(d->name, devargs->name) == 0) { 403 TAILQ_REMOVE(&devargs_list, d, next); 404 rte_devargs_reset(d); 405 free(d); 406 return 0; 407 } 408 } 409 return 1; 410 } 411 412 /* count the number of devices of a specified type */ 413 unsigned int 414 rte_devargs_type_count(enum rte_devtype devtype) 415 { 416 struct rte_devargs *devargs; 417 unsigned int count = 0; 418 419 TAILQ_FOREACH(devargs, &devargs_list, next) { 420 if (devargs->type != devtype) 421 continue; 422 count++; 423 } 424 return count; 425 } 426 427 /* dump the user devices on the console */ 428 void 429 rte_devargs_dump(FILE *f) 430 { 431 struct rte_devargs *devargs; 432 433 fprintf(f, "User device list:\n"); 434 TAILQ_FOREACH(devargs, &devargs_list, next) { 435 fprintf(f, " [%s]: %s %s\n", 436 (devargs->bus ? devargs->bus->name : "??"), 437 devargs->name, devargs->args); 438 } 439 } 440 441 /* bus-aware rte_devargs iterator. */ 442 struct rte_devargs * 443 rte_devargs_next(const char *busname, const struct rte_devargs *start) 444 { 445 struct rte_devargs *da; 446 447 if (start != NULL) 448 da = TAILQ_NEXT(start, next); 449 else 450 da = TAILQ_FIRST(&devargs_list); 451 while (da != NULL) { 452 if (busname == NULL || 453 (strcmp(busname, da->bus->name) == 0)) 454 return da; 455 da = TAILQ_NEXT(da, next); 456 } 457 return NULL; 458 } 459