diff --git a/sys/dev/pci/pci_iov_schema.c b/sys/dev/pci/pci_iov_schema.c --- a/sys/dev/pci/pci_iov_schema.c +++ b/sys/dev/pci/pci_iov_schema.c @@ -54,11 +54,13 @@ static validate_func pci_iov_schema_validate_string; static validate_func pci_iov_schema_validate_uint; static validate_func pci_iov_schema_validate_unicast_mac; +static validate_func pci_iov_schema_validate_vlan; static default_validate_t pci_iov_validate_bool_default; static default_validate_t pci_iov_validate_string_default; static default_validate_t pci_iov_validate_uint_default; static default_validate_t pci_iov_validate_unicast_mac_default; +static default_validate_t pci_iov_validate_vlan_default; struct config_type_validator { const char *type_name; @@ -107,6 +109,11 @@ .validate = pci_iov_schema_validate_unicast_mac, .default_validate = pci_iov_validate_unicast_mac_default, }, + { + .type_name = "vlan", + .validate = pci_iov_schema_validate_vlan, + .default_validate = pci_iov_validate_vlan_default, + }, }; static const struct config_type_validator * @@ -261,6 +268,26 @@ nvlist_move_nvlist(schema, name, entry); } +void +pci_iov_schema_add_vlan(nvlist_t *schema, const char *name, + uint32_t flags, const uint16_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, "vlan"); + if (flags & IOV_SCHEMA_HASDEFAULT) + nvlist_add_number(entry, "default", defaultVal); + pci_iov_schema_add_required(entry, flags); + + nvlist_move_nvlist(schema, name, entry); +} + static int pci_iov_schema_validate_bool(const struct config_type_validator * validator, const nvlist_t *config, const char *name) @@ -320,6 +347,24 @@ return (0); } +static int +pci_iov_schema_validate_vlan( + const struct config_type_validator * validator, + const nvlist_t *config, const char *name) +{ + uint16_t vlan; + + if (!nvlist_exists_number(config, name)) + return (EINVAL); + + vlan = nvlist_get_number(config, name); + + if (vlan > 4095 && vlan != VF_VLAN_TRUNK) + return (EINVAL); + + return (0); +} + static void pci_iov_config_add_default(const nvlist_t *param_schema, const char *name, nvlist_t *config) @@ -400,6 +445,22 @@ return (0); } +static int +pci_iov_validate_vlan_default( + const struct config_type_validator * validator, const nvlist_t *param) +{ + uint16_t vlan; + + if (! nvlist_exists_number(param, DEFAULT_SCHEMA_NAME)) + return (EINVAL); + + vlan = nvlist_get_number(param, DEFAULT_SCHEMA_NAME); + if (vlan > 4095 && vlan != VF_VLAN_TRUNK) + return (EINVAL); + + return (0); +} + static int pci_iov_validate_param_schema(const nvlist_t *schema) { diff --git a/sys/sys/iov.h b/sys/sys/iov.h --- a/sys/sys/iov.h +++ b/sys/sys/iov.h @@ -46,6 +46,8 @@ #define DEFAULT_SCHEMA_NAME "DEFAULT" #define REQUIRED_SCHEMA_NAME "REQUIRED" +#define VF_VLAN_TRUNK 4096 + /* * Because each PF device is expected to expose a unique set of possible * configurations, the SR-IOV infrastructure dynamically queries the PF diff --git a/sys/sys/iov_schema.h b/sys/sys/iov_schema.h --- a/sys/sys/iov_schema.h +++ b/sys/sys/iov_schema.h @@ -48,5 +48,6 @@ 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); - +void pci_iov_schema_add_vlan(nvlist_t *schema, const char *name, + uint32_t flags, const uint16_t defaultVal); #endif diff --git a/usr.sbin/iovctl/iovctl.c b/usr.sbin/iovctl/iovctl.c --- a/usr.sbin/iovctl/iovctl.c +++ b/usr.sbin/iovctl/iovctl.c @@ -345,6 +345,12 @@ mac = nvlist_get_binary(parameter, DEFAULT_SCHEMA_NAME, &size); printf(" (default = %02x:%02x:%02x:%02x:%02x:%02x)", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } else if (strcasecmp(type, "vlan") == 0) { + uint16_t vlan = nvlist_get_number(parameter, DEFAULT_SCHEMA_NAME); + if (vlan == VF_VLAN_TRUNK) + printf(" (default = trunk)"); + else + printf(" (default = %d)", vlan); } else errx(1, "Unexpected type in schema: '%s'", type); } diff --git a/usr.sbin/iovctl/iovctl.conf.5 b/usr.sbin/iovctl/iovctl.conf.5 --- a/usr.sbin/iovctl/iovctl.conf.5 +++ b/usr.sbin/iovctl/iovctl.conf.5 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 29, 2020 +.Dd May 30, 2024 .Dt IOVCTL.CONF 5 .Os .Sh NAME @@ -95,6 +95,8 @@ .Bl -tag -width indent .It boolean Accepts a boolean value of true or false. +.It vlan +Accepts a VLAN ID, or "trunk" to allow any VLAN ID. .It mac-addr Accepts a unicast MAC address specified as a string of the form xx:xx:xx:xx:xx:xx, where xx is one or two hexadecimal digits. @@ -159,6 +161,7 @@ VF-0 { mac-addr : "02:56:48:7e:d9:f7"; passthrough : false; + vlan: 1; } .Ed .Sh SEE ALSO diff --git a/usr.sbin/iovctl/parse.c b/usr.sbin/iovctl/parse.c --- a/usr.sbin/iovctl/parse.c +++ b/usr.sbin/iovctl/parse.c @@ -160,6 +160,29 @@ nvlist_add_binary(config, key, mac, ETHER_ADDR_LEN); } +static void +add_vlan_config(const char *key, const ucl_object_t *obj, nvlist_t *config) +{ + int64_t val; + const char *strVal = ""; + + if(ucl_object_tostring_safe(obj, &strVal)) { + if (strcasecmp(strVal, "trunk") == 0) { + nvlist_add_number(config, key, VF_VLAN_TRUNK); + return; + } + report_config_error(key, obj, "vlan"); + } + + if (!ucl_object_toint_safe(obj, &val)) + report_config_error(key, obj, "vlan"); + + if (val < 0 || val > 4095) + report_config_error(key, obj, "vlan"); + + nvlist_add_number(config, key, val); +} + /* * Validates that the given configuration value has the right type as specified * in the schema, and then adds the value to the configuration node. @@ -186,6 +209,8 @@ add_uint_config(key, obj, config, type, UINT64_MAX); else if (strcasecmp(type, "unicast-mac") == 0) add_unicast_mac_config(key, obj, config); + else if (strcasecmp(type, "vlan") == 0) + add_vlan_config(key, obj, config); else errx(1, "Unexpected type '%s' in schema", type); }