diff mbox series

[iproute2-next,3/5] devlink: Supporting add and delete of devlink port

Message ID 20210129165608.134965-4-parav@nvidia.com (mailing list archive)
State Superseded
Delegated to: David Ahern
Headers show
Series Support devlink port add delete | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Parav Pandit Jan. 29, 2021, 4:56 p.m. UTC
Enable user to add and delete the devlink port.

Examples for adding and deleting one SF port:

Examples of add, show and delete commands:
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev

$ devlink port show
pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical port 0 splittable false

Add devlink port of flavour 'pcipf' for PF number 0 SF number 88:

$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:06:00.0/32768: type eth netdev eth6 flavour pcisf controller 0 pfnum 0 sfnum 88 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached

Delete newly added devlink port
$ devlink port del pci/0000:06:00.0/32768

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
 devlink/devlink.c       | 128 ++++++++++++++++++++++++++++++++++++++++
 man/man8/devlink-port.8 |  63 ++++++++++++++++++++
 2 files changed, 191 insertions(+)

Comments

David Ahern Jan. 31, 2021, 5:26 p.m. UTC | #1
On 1/29/21 9:56 AM, Parav Pandit wrote:
> @@ -1383,6 +1389,37 @@ static int reload_limit_get(struct dl *dl, const char *limitstr,
>  	return 0;
>  }
>  
> +static int port_flavour_parse(const char *flavour, uint16_t *value)
> +{
> +	if (!flavour)
> +		return -EINVAL;
> +
> +	if (strcmp(flavour, "physical") == 0) {
> +		*value = DEVLINK_PORT_FLAVOUR_PHYSICAL;
> +		return 0;
> +	} else if (strcmp(flavour, "cpu") == 0) {
> +		*value = DEVLINK_PORT_FLAVOUR_CPU;
> +		return 0;
> +	} else if (strcmp(flavour, "dsa") == 0) {
> +		*value = DEVLINK_PORT_FLAVOUR_DSA;
> +		return 0;
> +	} else if (strcmp(flavour, "pcipf") == 0) {
> +		*value = DEVLINK_PORT_FLAVOUR_PCI_PF;
> +		return 0;
> +	} else if (strcmp(flavour, "pcivf") == 0) {
> +		*value = DEVLINK_PORT_FLAVOUR_PCI_VF;
> +		return 0;
> +	} else if (strcmp(flavour, "pcisf") == 0) {
> +		*value = DEVLINK_PORT_FLAVOUR_PCI_SF;
> +		return 0;
> +	} else if (strcmp(flavour, "virtual") == 0) {
> +		*value = DEVLINK_PORT_FLAVOUR_VIRTUAL;
> +		return 0;
> +	} else {
> +		return -EINVAL;
> +	}
> +}
use a struct for the string - value conversions; that should have been
done for port_flavour_name so it can be refactored to use that kind of
relationship. This function is just the inverse of it.
Parav Pandit Feb. 1, 2021, 8:42 p.m. UTC | #2
> From: David Ahern <dsahern@gmail.com>
> Sent: Sunday, January 31, 2021 10:56 PM
> 
> On 1/29/21 9:56 AM, Parav Pandit wrote:
> > @@ -1383,6 +1389,37 @@ static int reload_limit_get(struct dl *dl, const
> char *limitstr,
> >  	return 0;
> >  }
> >
> > +static int port_flavour_parse(const char *flavour, uint16_t *value) {
> > +	if (!flavour)
> > +		return -EINVAL;
> > +
> > +	if (strcmp(flavour, "physical") == 0) {
> > +		*value = DEVLINK_PORT_FLAVOUR_PHYSICAL;
> > +		return 0;
> > +	} else if (strcmp(flavour, "cpu") == 0) {
> > +		*value = DEVLINK_PORT_FLAVOUR_CPU;
> > +		return 0;
> > +	} else if (strcmp(flavour, "dsa") == 0) {
> > +		*value = DEVLINK_PORT_FLAVOUR_DSA;
> > +		return 0;
> > +	} else if (strcmp(flavour, "pcipf") == 0) {
> > +		*value = DEVLINK_PORT_FLAVOUR_PCI_PF;
> > +		return 0;
> > +	} else if (strcmp(flavour, "pcivf") == 0) {
> > +		*value = DEVLINK_PORT_FLAVOUR_PCI_VF;
> > +		return 0;
> > +	} else if (strcmp(flavour, "pcisf") == 0) {
> > +		*value = DEVLINK_PORT_FLAVOUR_PCI_SF;
> > +		return 0;
> > +	} else if (strcmp(flavour, "virtual") == 0) {
> > +		*value = DEVLINK_PORT_FLAVOUR_VIRTUAL;
> > +		return 0;
> > +	} else {
> > +		return -EINVAL;
> > +	}
> > +}
> use a struct for the string - value conversions; that should have been done
> for port_flavour_name so it can be refactored to use that kind of
> relationship. This function is just the inverse of it.
Yep. Doing it in v2. Added utils routine for it.
Few more functions will benefit from this helper routine post this series.
diff mbox series

Patch

diff --git a/devlink/devlink.c b/devlink/devlink.c
index ceafd179..515dadc8 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -306,6 +306,9 @@  static void ifname_map_free(struct ifname_map *ifname_map)
 #define DL_OPT_FLASH_OVERWRITE		BIT(39)
 #define DL_OPT_RELOAD_ACTION		BIT(40)
 #define DL_OPT_RELOAD_LIMIT	BIT(41)
+#define DL_OPT_PORT_FLAVOUR BIT(42)
+#define DL_OPT_PORT_PFNUMBER BIT(43)
+#define DL_OPT_PORT_SFNUMBER BIT(44)
 
 struct dl_opts {
 	uint64_t present; /* flags of present items */
@@ -356,6 +359,9 @@  struct dl_opts {
 	uint32_t overwrite_mask;
 	enum devlink_reload_action reload_action;
 	enum devlink_reload_limit reload_limit;
+	uint32_t port_sfnumber;
+	uint16_t port_flavour;
+	uint16_t port_pfnumber;
 };
 
 struct dl {
@@ -1383,6 +1389,37 @@  static int reload_limit_get(struct dl *dl, const char *limitstr,
 	return 0;
 }
 
+static int port_flavour_parse(const char *flavour, uint16_t *value)
+{
+	if (!flavour)
+		return -EINVAL;
+
+	if (strcmp(flavour, "physical") == 0) {
+		*value = DEVLINK_PORT_FLAVOUR_PHYSICAL;
+		return 0;
+	} else if (strcmp(flavour, "cpu") == 0) {
+		*value = DEVLINK_PORT_FLAVOUR_CPU;
+		return 0;
+	} else if (strcmp(flavour, "dsa") == 0) {
+		*value = DEVLINK_PORT_FLAVOUR_DSA;
+		return 0;
+	} else if (strcmp(flavour, "pcipf") == 0) {
+		*value = DEVLINK_PORT_FLAVOUR_PCI_PF;
+		return 0;
+	} else if (strcmp(flavour, "pcivf") == 0) {
+		*value = DEVLINK_PORT_FLAVOUR_PCI_VF;
+		return 0;
+	} else if (strcmp(flavour, "pcisf") == 0) {
+		*value = DEVLINK_PORT_FLAVOUR_PCI_SF;
+		return 0;
+	} else if (strcmp(flavour, "virtual") == 0) {
+		*value = DEVLINK_PORT_FLAVOUR_VIRTUAL;
+		return 0;
+	} else {
+		return -EINVAL;
+	}
+}
+
 struct dl_args_metadata {
 	uint64_t o_flag;
 	char err_msg[DL_ARGS_REQUIRED_MAX_ERR_LEN];
@@ -1414,6 +1451,8 @@  static const struct dl_args_metadata dl_args_required[] = {
 	{DL_OPT_TRAP_NAME,            "Trap's name is expected."},
 	{DL_OPT_TRAP_GROUP_NAME,      "Trap group's name is expected."},
 	{DL_OPT_PORT_FUNCTION_HW_ADDR, "Port function's hardware address is expected."},
+	{DL_OPT_PORT_FLAVOUR,          "Port flavour is expected."},
+	{DL_OPT_PORT_PFNUMBER,         "Port PCI PF number is expected."},
 };
 
 static int dl_args_finding_required_validate(uint64_t o_required,
@@ -1832,7 +1871,29 @@  static int dl_argv_parse(struct dl *dl, uint64_t o_required,
 			if (err)
 				return err;
 			o_found |= DL_OPT_PORT_FUNCTION_HW_ADDR;
+		} else if (dl_argv_match(dl, "flavour") && (o_all & DL_OPT_PORT_FLAVOUR)) {
+			const char *flavourstr;
 
+			dl_arg_inc(dl);
+			err = dl_argv_str(dl, &flavourstr);
+			if (err)
+				return err;
+			err = port_flavour_parse(flavourstr, &opts->port_flavour);
+			if (err)
+				return err;
+			o_found |= DL_OPT_PORT_FLAVOUR;
+		} else if (dl_argv_match(dl, "pfnum") && (o_all & DL_OPT_PORT_PFNUMBER)) {
+			dl_arg_inc(dl);
+			err = dl_argv_uint16_t(dl, &opts->port_pfnumber);
+			if (err)
+				return err;
+			o_found |= DL_OPT_PORT_PFNUMBER;
+		} else if (dl_argv_match(dl, "sfnum") && (o_all & DL_OPT_PORT_SFNUMBER)) {
+			dl_arg_inc(dl);
+			err = dl_argv_uint32_t(dl, &opts->port_sfnumber);
+			if (err)
+				return err;
+			o_found |= DL_OPT_PORT_SFNUMBER;
 		} else {
 			pr_err("Unknown option \"%s\"\n", dl_argv(dl));
 			return -EINVAL;
@@ -2015,6 +2076,12 @@  static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
 				 opts->trap_policer_burst);
 	if (opts->present & DL_OPT_PORT_FUNCTION_HW_ADDR)
 		dl_function_attr_put(nlh, opts);
+	if (opts->present & DL_OPT_PORT_FLAVOUR)
+		mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_FLAVOUR, opts->port_flavour);
+	if (opts->present & DL_OPT_PORT_PFNUMBER)
+		mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, opts->port_pfnumber);
+	if (opts->present & DL_OPT_PORT_SFNUMBER)
+		mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_PCI_SF_NUMBER, opts->port_sfnumber);
 }
 
 static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl,
@@ -3702,6 +3769,8 @@  static void cmd_port_help(void)
 	pr_err("       devlink port unsplit DEV/PORT_INDEX\n");
 	pr_err("       devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ]\n");
 	pr_err("       devlink port health show [ DEV/PORT_INDEX reporter REPORTER_NAME ]\n");
+	pr_err("       devlink port add DEV/PORT_INDEX flavour FLAVOUR [ controller CNUM ] pfnum PFNUM [ sfnum SFNUM ]\n");
+	pr_err("       devlink port del DEV/PORT_INDEX\n");
 }
 
 static const char *port_type_name(uint32_t type)
@@ -3977,6 +4046,58 @@  static int cmd_port_function(struct dl *dl)
 static int cmd_health(struct dl *dl);
 static int __cmd_health_show(struct dl *dl, bool show_device, bool show_port);
 
+static void cmd_port_add_help(void)
+{
+	pr_err("       devlink port add { DEV | DEV/PORT_INDEX } flavour FLAVOUR pfnum PFNUM [ sfnum SFNUM ]\n");
+}
+
+static int cmd_port_add(struct dl *dl)
+{
+	struct nlmsghdr *nlh;
+	int err;
+
+	if (dl_argv_match(dl, "help") || dl_no_arg(dl)) {
+		cmd_port_add_help();
+		return 0;
+	}
+
+	nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_NEW,
+			       NLM_F_REQUEST | NLM_F_ACK);
+
+	err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_HANDLEP |
+				DL_OPT_PORT_FLAVOUR | DL_OPT_PORT_PFNUMBER,
+				DL_OPT_PORT_SFNUMBER);
+	if (err)
+		return err;
+
+	return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_port_show_cb, dl);
+}
+
+static void cmd_port_del_help(void)
+{
+	pr_err("       devlink port del DEV/PORT_INDEX\n");
+}
+
+static int cmd_port_del(struct dl *dl)
+{
+	struct nlmsghdr *nlh;
+	int err;
+
+	if (dl_argv_match(dl, "help") || dl_no_arg(dl)) {
+		cmd_port_del_help();
+		return 0;
+	}
+
+	nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_DEL,
+			       NLM_F_REQUEST | NLM_F_ACK);
+
+	err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, 0);
+	if (err)
+		return err;
+
+	return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
+}
+
 static int cmd_port(struct dl *dl)
 {
 	if (dl_argv_match(dl, "help")) {
@@ -4007,7 +4128,14 @@  static int cmd_port(struct dl *dl)
 		} else {
 			return cmd_health(dl);
 		}
+	} else if (dl_argv_match(dl, "add")) {
+		dl_arg_inc(dl);
+		return cmd_port_add(dl);
+	} else if (dl_argv_match(dl, "del")) {
+		dl_arg_inc(dl);
+		return cmd_port_del(dl);
 	}
+
 	pr_err("Command \"%s\" not found\n", dl_argv(dl));
 	return -ENOENT;
 }
diff --git a/man/man8/devlink-port.8 b/man/man8/devlink-port.8
index 966faae6..4a1d3800 100644
--- a/man/man8/devlink-port.8
+++ b/man/man8/devlink-port.8
@@ -43,6 +43,23 @@  devlink-port \- devlink port configuration
 .B devlink port health
 .RI "{ " show " | " recover " | " diagnose " | " dump " | " set " }"
 
+.ti -8
+.BI "devlink port add"
+.RB "["
+.IR "DEV | DEV/PORT_INDEX"
+.RB "] "
+.RB "[ " flavour
+.IR FLAVOUR " ]"
+.RB "[ " pcipf
+.IR PFNUMBER " ]"
+.RB "{ " pcisf
+.IR SFNUMBER " }"
+.br
+
+.ti -8
+.B devlink port del
+.IR DEV/PORT_INDEX
+
 .ti -8
 .B devlink port help
 
@@ -99,6 +116,42 @@  If this argument is omitted all ports are listed.
 Is an alias for
 .BR devlink-health (8).
 
+.ti -8
+.SS devlink port add - add a devlink port
+.PP
+.B "DEV"
+- specifies the devlink device to operate on. or
+
+.PP
+.B "DEV/PORT_INDEX"
+- specifies the devlink port index to use for the requested new port.
+This is optional. When ommited, driver allocates unique port index.
+
+.TP
+.BR flavour " { " pcipf " | " pcisf " } "
+set port flavour
+
+.I pcipf
+- PCI PF port
+
+.I pcisf
+- PCI SF port
+
+.TP
+.BR pfnum " { " pfnumber " } "
+Specifies PCI pfnumber to use on which a SF device to create
+
+.TP
+.BR sfnum " { " sfnumber " } "
+Specifies sfnumber to assign to the device of the SF.
+This field is optional for those devices which supports auto assignment of the SF number.
+
+.ti -8
+.SS devlink port del - delete a devlink port
+.PP
+.B "DEV/PORT_INDEX"
+- specifies the devlink port to delete.
+
 .SH "EXAMPLES"
 .PP
 devlink port show
@@ -135,6 +188,16 @@  devlink port health show pci/0000:01:00.0/1 reporter tx
 .RS 4
 Shows status and configuration of tx reporter registered on pci/0000:01:00.0/1 devlink port.
 .RE
+.PP
+devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
+.RS 4
+Add a devlink port of flavour PCI SF on PCI PF having number 0 with SF number 88.
+.RE
+.PP
+devlink port del pci/0000:06:00.0/1
+.RS 4
+Delete previously created devlink port.
+.RE
 
 .SH SEE ALSO
 .BR devlink (8),