From 7da891effec739bd858e4d64a4d8a9c6ce625b86 Mon Sep 17 00:00:00 2001 From: Ryan Stone Date: Sat, 3 May 2014 21:17:40 -0400 Subject: [PATCH 11/21] Add infrastructure for exporting config schema from PF drivers --- sys/conf/files | 1 + sys/dev/pci/pci_if.m | 6 ++ sys/dev/pci/pci_iov.c | 186 ++++++++++++++++++++++++++++++++++++- sys/dev/pci/pci_iov_private.h | 1 + sys/dev/pci/pci_iov_schema.c | 208 ++++++++++++++++++++++++++++++++++++++++++ sys/dev/pci/pci_private.h | 3 +- sys/dev/pci/pcivar.h | 7 +- sys/dev/pci/schema_private.h | 35 +++++++ sys/sys/iov.h | 127 ++++++++++++++++++++++++++ sys/sys/iov_schema.h | 52 +++++++++++ 10 files changed, 622 insertions(+), 4 deletions(-) create mode 100755 sys/dev/pci/pci_iov_schema.c create mode 100644 sys/dev/pci/schema_private.h create mode 100644 sys/sys/iov_schema.h diff --git a/sys/conf/files b/sys/conf/files index ce3c2b99..87333c5 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1981,6 +1981,7 @@ dev/pci/isa_pci.c optional pci isa dev/pci/pci.c optional pci dev/pci/pci_if.m standard dev/pci/pci_iov.c optional pci pci_iov +dev/pci/pci_iov_schema.c optional pci pci_iov dev/pci/pci_pci.c optional pci dev/pci/pci_subr.c optional pci dev/pci/pci_user.c optional pci diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m index babf896..aa6bc6c 100644 --- a/sys/dev/pci/pci_if.m +++ b/sys/dev/pci/pci_if.m @@ -38,6 +38,10 @@ CODE { } }; +HEADER { + struct nvlist; +} + METHOD u_int32_t read_config { device_t dev; @@ -168,6 +172,8 @@ METHOD uint16_t get_rid { METHOD int iov_attach { device_t dev; device_t child; + struct nvlist *pf_schema; + struct nvlist *vf_schema; }; METHOD int iov_detach { diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c index 5a5b3ac..33c177f 100755 --- a/sys/dev/pci/pci_iov.c +++ b/sys/dev/pci/pci_iov.c @@ -46,11 +46,16 @@ __FBSDID("$FreeBSD$"); #include #include +#include + +#include +#include #include #include #include #include +#include #include "pci_if.h" #include "pcib_if.h" @@ -71,18 +76,30 @@ static struct cdevsw iov_cdevsw = { #define IOV_WRITE(d, r, v, w) \ pci_write_config((d)->cfg.dev, (d)->cfg.iov->iov_pos + r, v, w) +static nvlist_t *pci_iov_build_schema(nvlist_t **pf_schema, + nvlist_t **vf_schema); +static void pci_iov_build_pf_schema(nvlist_t *schema, + nvlist_t **driver_schema); +static void pci_iov_build_vf_schema(nvlist_t *schema, + nvlist_t **driver_schema); +static nvlist_t *pci_iov_get_pf_subsystem_schema(void); +static nvlist_t *pci_iov_get_vf_subsystem_schema(void); + int -pci_iov_attach_method(device_t bus, device_t dev) +pci_iov_attach_method(device_t bus, device_t dev, nvlist_t *pf_schema, + nvlist_t *vf_schema) { device_t pcib; struct pci_devinfo *dinfo; struct pcicfg_iov *iov; + nvlist_t *schema; uint32_t version; int error; int iov_pos; dinfo = device_get_ivars(dev); pcib = device_get_parent(bus); + schema = NULL; error = pci_find_extcap(dev, PCIZ_SRIOV, &iov_pos); @@ -108,6 +125,13 @@ pci_iov_attach_method(device_t bus, device_t dev) } iov->iov_pos = iov_pos; + schema = pci_iov_build_schema(&pf_schema, &vf_schema); + if (schema == NULL) { + error = ENOMEM; + goto cleanup; + } + iov->iov_schema = schema; + iov->iov_cdev = make_dev(&iov_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "iov/%s", device_get_nameunit(dev)); @@ -123,6 +147,9 @@ pci_iov_attach_method(device_t bus, device_t dev) return (0); cleanup: + nvlist_destroy(schema); + nvlist_destroy(pf_schema); + nvlist_destroy(vf_schema); free(iov, M_SRIOV); mtx_unlock(&Giant); return (error); @@ -154,6 +181,7 @@ pci_iov_detach_method(device_t bus, device_t dev) destroy_dev(iov->iov_cdev); iov->iov_cdev = NULL; } + nvlist_destroy(iov->iov_schema); free(iov, M_SRIOV); mtx_unlock(&Giant); @@ -161,6 +189,115 @@ pci_iov_detach_method(device_t bus, device_t dev) return (0); } +static nvlist_t * +pci_iov_build_schema(nvlist_t **pf, nvlist_t **vf) +{ + nvlist_t *schema, *pf_driver, *vf_driver; + + /* We always take ownership of the schemas. */ + pf_driver = *pf; + *pf = NULL; + vf_driver = *vf; + *vf = NULL; + + schema = pci_iov_schema_alloc_node(); + if (schema == NULL) + goto cleanup; + + pci_iov_build_pf_schema(schema, &pf_driver); + pci_iov_build_vf_schema(schema, &vf_driver); + + if (nvlist_error(schema) != 0) + goto cleanup; + + return (schema); + +cleanup: + nvlist_destroy(schema); + nvlist_destroy(pf_driver); + nvlist_destroy(vf_driver); + return (NULL); +} + +static void +pci_iov_build_pf_schema(nvlist_t *schema, nvlist_t **driver_schema) +{ + nvlist_t *pf_schema, *iov_schema; + + pf_schema = pci_iov_schema_alloc_node(); + if (pf_schema == NULL) { + nvlist_set_error(schema, ENOMEM); + return; + } + + iov_schema = pci_iov_get_pf_subsystem_schema(); + + /* + * Note that if either *driver_schema or iov_schema is NULL, then + * nvlist_move_nvlist will put the schema in the error state and + * SR-IOV will fail to initialize later, so we don't have to explicitly + * handle that case. + */ + nvlist_move_nvlist(pf_schema, DRIVER_CONFIG_NAME, *driver_schema); + nvlist_move_nvlist(pf_schema, IOV_CONFIG_NAME, iov_schema); + nvlist_move_nvlist(schema, PF_CONFIG_NAME, pf_schema); + *driver_schema = NULL; +} + +static void +pci_iov_build_vf_schema(nvlist_t *schema, nvlist_t **driver_schema) +{ + nvlist_t *vf_schema, *iov_schema; + + vf_schema = pci_iov_schema_alloc_node(); + if (vf_schema == NULL) { + nvlist_set_error(schema, ENOMEM); + return; + } + + iov_schema = pci_iov_get_vf_subsystem_schema(); + + /* + * Note that if either *driver_schema or iov_schema is NULL, then + * nvlist_move_nvlist will put the schema in the error state and + * SR-IOV will fail to initialize later, so we don't have to explicitly + * handle that case. + */ + nvlist_move_nvlist(vf_schema, DRIVER_CONFIG_NAME, *driver_schema); + nvlist_move_nvlist(vf_schema, IOV_CONFIG_NAME, iov_schema); + nvlist_move_nvlist(schema, VF_SCHEMA_NAME, vf_schema); + *driver_schema = NULL; +} + +static nvlist_t * +pci_iov_get_pf_subsystem_schema(void) +{ + nvlist_t *pf; + + pf = pci_iov_schema_alloc_node(); + if (pf == NULL) + return (NULL); + + pci_iov_schema_add_uint16(pf, "num_vfs", IOV_SCHEMA_REQUIRED, -1); + pci_iov_schema_add_string(pf, "device", IOV_SCHEMA_REQUIRED, NULL); + + return (pf); +} + +static nvlist_t * +pci_iov_get_vf_subsystem_schema(void) +{ + nvlist_t *vf; + + vf = pci_iov_schema_alloc_node(); + if (vf == NULL) + return (NULL); + + pci_iov_schema_add_bool(vf, "passthrough", IOV_SCHEMA_HASDEFAULT, 0); + + return (vf); +} + static int pci_iov_alloc_bar(struct pci_devinfo *dinfo, int bar, pci_addr_t bar_shift) { @@ -601,6 +738,50 @@ out: return (error); } +static int +pci_iov_get_schema_ioctl(struct cdev *cdev, struct pci_iov_schema *output) +{ + struct pci_devinfo *dinfo; + void *packed; + size_t output_len, size; + int error; + + packed = NULL; + + mtx_lock(&Giant); + dinfo = cdev->si_drv1; + packed = nvlist_pack(dinfo->cfg.iov->iov_schema, &size); + mtx_unlock(&Giant); + + if (packed == NULL) { + error = ENOMEM; + goto fail; + } + + output_len = output->len; + output->len = size; + if (size <= output_len) { + error = copyout(packed, output->schema, size); + + if (error != 0) + goto fail; + + output->error = 0; + } else + /* + * If we return an error then the ioctl code won't copyout + * output back to userland, so we flag the error in the struct + * instead. + */ + output->error = EMSGSIZE; + + error = 0; + +fail: + free(packed, M_NVLIST); + + return (error); +} static int pci_iov_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, @@ -612,6 +793,9 @@ pci_iov_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, return (pci_iov_config(dev, (struct pci_iov_arg *)data)); case IOV_DELETE: return (pci_iov_delete(dev)); + case IOV_GET_SCHEMA: + return (pci_iov_get_schema_ioctl(dev, + (struct pci_iov_schema *)data)); default: return (EINVAL); } diff --git a/sys/dev/pci/pci_iov_private.h b/sys/dev/pci/pci_iov_private.h index e5f594c..f4f7f7d 100755 --- a/sys/dev/pci/pci_iov_private.h +++ b/sys/dev/pci/pci_iov_private.h @@ -38,6 +38,7 @@ struct pci_iov_bar { struct pcicfg_iov { struct cdev *iov_cdev; + nvlist_t *iov_schema; struct pci_iov_bar iov_bar[PCIR_MAX_BAR_0 + 1]; struct rman rman; diff --git a/sys/dev/pci/pci_iov_schema.c b/sys/dev/pci/pci_iov_schema.c new file mode 100755 index 0000000..fbe61c8 --- /dev/null +++ b/sys/dev/pci/pci_iov_schema.c @@ -0,0 +1,208 @@ +/*- + * Copyright (c) 2014 Sandvine Inc. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +static const char *pci_iov_schema_valid_types[] = { + "bool", + "string", + "uint8_t", + "uint16_t", + "uint32_t", + "uint64_t", + "unicast-mac", +}; + +static void +pci_iov_schema_add_type(nvlist_t *entry, const char *type) +{ + int i, error; + + error = EINVAL; + for (i = 0; i < nitems(pci_iov_schema_valid_types); i++) { + if (strcmp(type, pci_iov_schema_valid_types[i]) == 0) { + error = 0; + break; + } + } + + if (error != 0) { + nvlist_set_error(entry, error); + return; + } + + nvlist_add_string(entry, "type", type); +} + +static void +pci_iov_schema_add_required(nvlist_t *entry, uint32_t flags) +{ + + if (flags & IOV_SCHEMA_REQUIRED) { + if (flags & IOV_SCHEMA_HASDEFAULT) { + nvlist_set_error(entry, EINVAL); + return; + } + + nvlist_add_bool(entry, "required", 1); + } +} + +void +pci_iov_schema_add_bool(nvlist_t *schema, const char *name, uint32_t flags, + int defaultVal) +{ + nvlist_t *entry; + + entry = nvlist_create(NV_FLAG_IGNORE_CASE); + if (entry == NULL) { + nvlist_set_error(schema, ENOMEM); + return; + } + + pci_iov_schema_add_type(entry, "bool"); + if (flags & IOV_SCHEMA_HASDEFAULT) + nvlist_add_bool(entry, "default", defaultVal); + pci_iov_schema_add_required(entry, flags); + + nvlist_move_nvlist(schema, name, entry); +} + +void +pci_iov_schema_add_string(nvlist_t *schema, const char *name, uint32_t flags, + const char *defaultVal) +{ + nvlist_t *entry; + + entry = nvlist_create(NV_FLAG_IGNORE_CASE); + if (entry == NULL) { + nvlist_set_error(schema, ENOMEM); + return; + } + + pci_iov_schema_add_type(entry, "string"); + if (flags & IOV_SCHEMA_HASDEFAULT) + nvlist_add_string(entry, "default", defaultVal); + pci_iov_schema_add_required(entry, flags); + + nvlist_move_nvlist(schema, name, entry); +} + +static void +pci_iov_schema_int(nvlist_t *schema, const char *name, const char *type, + uint32_t flags, uint64_t defaultVal) +{ + nvlist_t *entry; + + entry = nvlist_create(NV_FLAG_IGNORE_CASE); + if (entry == NULL) { + nvlist_set_error(schema, ENOMEM); + return; + } + + pci_iov_schema_add_type(entry, type); + if (flags & IOV_SCHEMA_HASDEFAULT) + nvlist_add_number(entry, "default", defaultVal); + pci_iov_schema_add_required(entry, flags); + + nvlist_move_nvlist(schema, name, entry); +} + +void +pci_iov_schema_add_uint8(nvlist_t *schema, const char *name, uint32_t flags, + uint8_t defaultVal) +{ + + pci_iov_schema_int(schema, name, "uint8_t", flags, defaultVal); +} + +void +pci_iov_schema_add_uint16(nvlist_t *schema, const char *name, uint32_t flags, + uint16_t defaultVal) +{ + + pci_iov_schema_int(schema, name, "uint16_t", flags, defaultVal); +} + +void +pci_iov_schema_add_uint32(nvlist_t *schema, const char *name, uint32_t flags, + uint32_t defaultVal) +{ + + pci_iov_schema_int(schema, name, "uint32_t", flags, defaultVal); +} + +void +pci_iov_schema_add_uint64(nvlist_t *schema, const char *name, uint32_t flags, + uint64_t defaultVal) +{ + + pci_iov_schema_int(schema, name, "uint64_t", flags, defaultVal); +} + +void +pci_iov_schema_add_unicast_mac(nvlist_t *schema, const char *name, + uint32_t flags, const uint8_t * defaultVal) +{ + nvlist_t *entry; + + entry = nvlist_create(NV_FLAG_IGNORE_CASE); + if (entry == NULL) { + nvlist_set_error(schema, ENOMEM); + return; + } + + pci_iov_schema_add_type(entry, "unicast-mac"); + if (flags & IOV_SCHEMA_HASDEFAULT) + nvlist_add_binary(entry, "default", defaultVal, ETHER_ADDR_LEN); + pci_iov_schema_add_required(entry, flags); + + nvlist_move_nvlist(schema, name, entry); +} + +/* Allocate a new empty schema node. */ +nvlist_t * +pci_iov_schema_alloc_node(void) +{ + + return (nvlist_create(NV_FLAG_IGNORE_CASE)); +} \ No newline at end of file diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h index 89231d3..b9740b2 100644 --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -143,7 +143,8 @@ struct resource *pci_alloc_multi_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_long num, u_int flags); -int pci_iov_attach_method(device_t bus, device_t dev); +int pci_iov_attach_method(device_t bus, device_t dev, + struct nvlist *pf_schema, struct nvlist *vf_schema); int pci_iov_detach_method(device_t bus, device_t dev); struct resource *pci_vf_alloc_mem_resource(device_t dev, device_t child, diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 07ef801..af09ccf 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -39,6 +39,8 @@ typedef uint64_t pci_addr_t; +struct nvlist; + /* Interesting values for PCI power management */ struct pcicfg_pp { uint16_t pp_cap; /* PCI power management capabilities */ @@ -499,9 +501,10 @@ pci_get_rid(device_t dev) } static __inline int -pci_iov_attach(device_t dev) +pci_iov_attach(device_t dev, struct nvlist *pf_schema, struct nvlist *vf_schema) { - return (PCI_IOV_ATTACH(device_get_parent(dev), dev)); + return (PCI_IOV_ATTACH(device_get_parent(dev), dev, pf_schema, + vf_schema)); } static __inline int diff --git a/sys/dev/pci/schema_private.h b/sys/dev/pci/schema_private.h new file mode 100644 index 0000000..608ee6f --- /dev/null +++ b/sys/dev/pci/schema_private.h @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2014 Sandvine Inc. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SCHEMA_PRIVATE_H_ +#define _SCHEMA_PRIVATE_H_ + +int pci_iov_schema_validate_config(const nvlist_t *, nvlist_t *); +uint16_t pci_iov_config_get_num_vfs(const nvlist_t *); + +#endif diff --git a/sys/sys/iov.h b/sys/sys/iov.h index c0449ec..7f5c010 100755 --- a/sys/sys/iov.h +++ b/sys/sys/iov.h @@ -31,14 +31,141 @@ #include +#define PF_CONFIG_NAME "PF" +#define VF_SCHEMA_NAME "VF" + +#define DRIVER_CONFIG_NAME "DRIVER" +#define IOV_CONFIG_NAME "IOV" + +#define TYPE_SCHEMA_NAME "TYPE" +#define DEFAULT_SCHEMA_NAME "DEFAULT" +#define REQUIRED_SCHEMA_NAME "REQUIRED" + struct pci_iov_arg { int num_vfs; int passthrough; }; +/* + * Because each PF device is expected to expose a unique set of possible + * configurations, the SR-IOV infrastructure dynamically queries the PF + * driver for its capabilities. These capabilities are exposed to userland + * with a configuration schema. The schema is exported from the kernel as a + * packed nvlist. See nv(3) for the details of the nvlist API. The expected + * format of the nvlist is: + * + * BASIC RULES + * 1) All keys are case-insensitive. + * 2) No keys that are not specified below may exist at any level of the + * schema. + * 3) All keys are mandatory unless explicitly documented as optional. If a + * key is mandatory then the associated value is also mandatory. + * 4) Order of keys is irrelevant. + * + * TOP LEVEL + * 1) There must be a top-level key with the name PF_CONFIG_NAME. The value + * associated with this key is a nvlist that follows the device schema + * node format. The parameters in this node specify the configuration + * parameters that may be applied to a PF. + * 2) There must be a top-level key with the name VF_SCHEMA_NAME. The value + * associated with this key is a nvlist that follows the device schema + * node format. The parameters in this node specify the configuration + * parameters that may be applied to a VF. + * + * DEVICE SCHEMA NODE + * 1) There must be a key with the name DRIVER_CONFIG_NAME. The value + * associated with this key is a nvlist that follows the device/subsystem + * schema node format. The parameters in this node specify the + * configuration parameters that are specific to a particular device + * driver. + * 2) There must be a key with the name IOV_CONFIG_NAME. The value associated + * with this key is an nvlist that follows the device/subsystem schema node + * format. The parameters in this node specify the configuration + * parameters that are applied by the SR-IOV infrastructure. + * + * DEVICE/SUBSYSTEM SCHEMA NODE + * 1) All keys in the device/subsystem schema node are optional. + * 2) Each key specifies the name of a valid configuration parameter that may + * be applied to the device/subsystem combination specified by this node. + * The value associated with the key specifies the format of valid + * configuration values, and must be a nvlist in parameter schema node + * format. + * + * PARAMETER SCHEMA NODE + * 1) The parameter schema node must contain a key with the name + * TYPE_SCHEMA_NAME. The value associated with this key must be a string. + * This string specifies the type of value that the parameter specified by + * this node must take. The string must have one of the following values: + * - "bool" - The configuration value must be a boolean. + * - "mac-addr" - The configuration value must be a binary value. In + * addition, the value must be exactly 6 bytes long and + * the value must not be a multicast or broadcast mac. + * - "uint8_t" - The configuration value must be a integer value in + * the range [0, UINT8_MAX]. + * - "uint16_t" - The configuration value must be a integer value in + * the range [0, UINT16_MAX]. + * - "uint32_t" - The configuration value must be a integer value in + * the range [0, UINT32_MAX]. + * - "uint64_t" - The configuration value must be a integer value in + * the range [0, UINT64_MAX]. + * 2) The parameter schema may contain a key with the name + * REQUIRED_SCHEMA_NAME. This key is optional. If this key is present, the + * value associated with it must have a boolean type. If the value is true, + * then the parameter specified by this schema is a required parameter. All + * valid configurations must include all required parameters. + * 3) The parameter schema may contain a key with the name DEFAULT_SCHEMA_NAME. + * This key is optional. This key must not be present if the parameter + * specified by this schema is required. If this key is present, the value + * associated with the parent key must follow all restrictions specified by + * the type specified by this schema. If a configuration does not supply a + * value for the parameter specified by this schema, then the kernel will + * apply the value associated with this key in its place. + * + * The following is an example of a valid schema, as printed by nvlist_dump. + * Keys are printed followed by the type of the value in parantheses. The + * value is displayed following a colon. The indentation level reflects the + * level of nesting of nvlists. String values are displayed between [] + * brackets. Binary values are shown with the length of the binary value (in + * bytes) followed by the actual binary values. + * + * PF (NVLIST): + * IOV (NVLIST): + * num_vfs (NVLIST): + * type (STRING): [uint16_t] + * required (BOOL): TRUE + * device (NVLIST): + * type (STRING): [string] + * required (BOOL): TRUE + * DRIVER (NVLIST): + * VF (NVLIST): + * IOV (NVLIST): + * passthrough (NVLIST): + * type (STRING): [bool] + * default (BOOL): FALSE + * DRIVER (NVLIST): + * mac-addr (NVLIST): + * type (STRING): [mac-addr] + * default (BINARY): 6 000000000000 + * vlan (NVLIST): + * type (STRING): [uint16_t] + * spoof-check (NVLIST): + * type (STRING): [bool] + * default (BOOL): TRUE + * allow-set-mac (NVLIST): + * type (STRING): [bool] + * default (BOOL): FALSE + */ +struct pci_iov_schema +{ + void *schema; + size_t len; + int error; +}; + #define IOV_CONFIG _IOWR('p', 10, struct pci_iov_arg) #define IOV_DELETE _IO('p', 11) +#define IOV_GET_SCHEMA _IOWR('p', 12, struct pci_iov_schema) #endif diff --git a/sys/sys/iov_schema.h b/sys/sys/iov_schema.h new file mode 100644 index 0000000..5dac3e1 --- /dev/null +++ b/sys/sys/iov_schema.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2014 Sandvine Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS_IOV_SCHEMA_H_ +#define _SYS_IOV_SCHEMA_H_ + +#define IOV_SCHEMA_HASDEFAULT (1 << 0) +#define IOV_SCHEMA_REQUIRED (1 << 1) + +nvlist_t *pci_iov_schema_alloc_node(void); + +void pci_iov_schema_add_bool(nvlist_t *schema, const char *name, + uint32_t flags, int defaultVal); +void pci_iov_schema_add_string(nvlist_t *schema, const char *name, + uint32_t flags, const char *defaultVal); +void pci_iov_schema_add_uint8(nvlist_t *schema, const char *name, + uint32_t flags, uint8_t defaultVal); +void pci_iov_schema_add_uint16(nvlist_t *schema, const char *name, + uint32_t flags, uint16_t defaultVal); +void pci_iov_schema_add_uint32(nvlist_t *schema, const char *name, + uint32_t flags, uint32_t defaultVal); +void pci_iov_schema_add_uint64(nvlist_t *schema, const char *name, + uint32_t flags, uint64_t defaultVal); +void pci_iov_schema_add_unicast_mac(nvlist_t *schema, const char *name, + uint32_t flags, const uint8_t * defaultVal); + +#endif -- 1.9.2