git: 95596d181dad - stable/13 - iovctl: allow vlan restrictions to be passed to the driver

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 02 Jul 2024 08:06:14 UTC
The branch stable/13 has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=95596d181dade90597e8badd7916f9aa0dfce87c

commit 95596d181dade90597e8badd7916f9aa0dfce87c
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2024-05-29 17:29:35 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2024-07-01 16:06:02 +0000

    iovctl: allow vlan restrictions to be passed to the driver
    
    Allow iovctl to create VFs that are restricted to specific VLAN IDs.
    
    Reviewed by:    kib, np
    MFC after:      2 weeks
    Sponsored by:   Orange Business Services
    Differential Revision:  https://reviews.freebsd.org/D45402
    
    (cherry picked from commit c57c26179033f64c2011a2d2a904ee3fa62e826a)
---
 sys/dev/pci/pci_iov_schema.c  | 61 +++++++++++++++++++++++++++++++++++++++++++
 sys/sys/iov.h                 |  2 ++
 sys/sys/iov_schema.h          |  3 ++-
 usr.sbin/iovctl/iovctl.c      |  6 +++++
 usr.sbin/iovctl/iovctl.conf.5 |  5 +++-
 usr.sbin/iovctl/parse.c       | 25 ++++++++++++++++++
 6 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/sys/dev/pci/pci_iov_schema.c b/sys/dev/pci/pci_iov_schema.c
index 742dfbd2b4d9..bb87e7215bc8 100644
--- a/sys/dev/pci/pci_iov_schema.c
+++ b/sys/dev/pci/pci_iov_schema.c
@@ -55,11 +55,13 @@ static validate_func pci_iov_schema_validate_bool;
 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;
@@ -108,6 +110,11 @@ static struct config_type_validator pci_iov_schema_validators[] = {
 		.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 *
@@ -262,6 +269,26 @@ pci_iov_schema_add_unicast_mac(nvlist_t *schema, const char *name,
 	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)
@@ -321,6 +348,24 @@ pci_iov_schema_validate_unicast_mac(
 	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)
@@ -401,6 +446,22 @@ pci_iov_validate_unicast_mac_default(
 	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
index 0171fc5a98cf..2ae7e5ac6767 100644
--- 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
index cb50f7796d30..66c883540563 100644
--- a/sys/sys/iov_schema.h
+++ b/sys/sys/iov_schema.h
@@ -48,5 +48,6 @@ 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);
-
+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
index 413fb7b2f4a5..368fa51c594f 100644
--- a/usr.sbin/iovctl/iovctl.c
+++ b/usr.sbin/iovctl/iovctl.c
@@ -346,6 +346,12 @@ print_default_value(const nvlist_t *parameter, const char *type)
 		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
index a7eb6c2077ee..1bae96e150ba 100644
--- 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 @@ The following option types are supported:
 .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 @@ DEFAULT {
 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
index a5810ba077eb..5114bd19e381 100644
--- a/usr.sbin/iovctl/parse.c
+++ b/usr.sbin/iovctl/parse.c
@@ -161,6 +161,29 @@ add_unicast_mac_config(const char *key, const ucl_object_t *obj, nvlist_t *confi
 	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 configuation value has the right type as specified
  * in the schema, and then adds the value to the configuation node.
@@ -187,6 +210,8 @@ add_config(const char *key, const ucl_object_t *obj, nvlist_t *config,
 		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);
 }