All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH iproute2-next 0/5] Support devlink port add delete
@ 2021-01-29 16:56 Parav Pandit
  2021-01-29 16:56 ` [PATCH iproute2-next 1/5] devlink: Update kernel headers Parav Pandit
                   ` (5 more replies)
  0 siblings, 6 replies; 19+ messages in thread
From: Parav Pandit @ 2021-01-29 16:56 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit

This patchset implements devlink port add, delete and function state
management commands.

An example sequence for a PCI SF:

Set the device in switchdev mode:
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev

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

Add a subfunction port for PCI PF 0 with sfnumber 88:
$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08: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

Show a newly added port:
$ devlink port show pci/0000:06:00.0/32768
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached

Set the function state to active:
$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active

Show the port in JSON format:
$ devlink port show pci/0000:06:00.0/32768 -jp
{
    "port": {
        "pci/0000:06:00.0/32768": {
            "type": "eth",
            "netdev": "ens2f0npf0sf88",
            "flavour": "pcisf",
            "controller": 0,
            "pfnum": 0,
            "sfnum": 88,
            "splittable": false,
            "function": {
                "hw_addr": "00:00:00:00:88:88",
                "state": "active",
                "opstate": "attached"
            }
        }
    }
}

Set the function state to active:
$ devlink port function set pci/0000:06:00.0/32768 state inactive

Delete the port after use:
$ devlink port del pci/0000:06:00.0/32768

Patch summary:
Patch-1 updates kernel headers
Patch-2 shows PCI SF port attributes
Patch-3 adds devlink commands to add and delete a port along with man
page
Patch-4 shows function state and operational state
Patch-5 enables user to set function state and adds man page
documentation

Parav Pandit (5):
  devlink: Update kernel headers
  devlink: Introduce PCI SF port flavour and attribute
  devlink: Supporting add and delete of devlink port
  devlink: Support get port function state
  devlink: Support set of port function state

 devlink/devlink.c            | 249 ++++++++++++++++++++++++++++++++---
 include/uapi/linux/devlink.h |  25 ++++
 man/man8/devlink-port.8      | 127 ++++++++++++++++++
 3 files changed, 384 insertions(+), 17 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next 1/5] devlink: Update kernel headers
  2021-01-29 16:56 [PATCH iproute2-next 0/5] Support devlink port add delete Parav Pandit
@ 2021-01-29 16:56 ` Parav Pandit
  2021-01-29 16:56 ` [PATCH iproute2-next 2/5] devlink: Introduce PCI SF port flavour and attribute Parav Pandit
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-01-29 16:56 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit

Update kernel headers to
commit a556dded9c23 ("devlink: Support get and set state of port function")

Signed-off-by: Parav Pandit <parav@nvidia.com>
---
 include/uapi/linux/devlink.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 958ef7b9..a430775d 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -200,6 +200,10 @@ enum devlink_port_flavour {
 	DEVLINK_PORT_FLAVOUR_UNUSED, /* Port which exists in the switch, but
 				      * is not used in any way.
 				      */
+	DEVLINK_PORT_FLAVOUR_PCI_SF, /* Represents eswitch port
+				      * for the PCI SF. It is an internal
+				      * port that faces the PCI SF.
+				      */
 };
 
 enum devlink_param_cmode {
@@ -529,6 +533,7 @@ enum devlink_attr {
 	DEVLINK_ATTR_RELOAD_ACTION_INFO,        /* nested */
 	DEVLINK_ATTR_RELOAD_ACTION_STATS,       /* nested */
 
+	DEVLINK_ATTR_PORT_PCI_SF_NUMBER,	/* u32 */
 	/* add new attributes above here, update the policy in devlink.c */
 
 	__DEVLINK_ATTR_MAX,
@@ -578,9 +583,29 @@ enum devlink_resource_unit {
 enum devlink_port_function_attr {
 	DEVLINK_PORT_FUNCTION_ATTR_UNSPEC,
 	DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,	/* binary */
+	DEVLINK_PORT_FN_ATTR_STATE,	/* u8 */
+	DEVLINK_PORT_FN_ATTR_OPSTATE,	/* u8 */
 
 	__DEVLINK_PORT_FUNCTION_ATTR_MAX,
 	DEVLINK_PORT_FUNCTION_ATTR_MAX = __DEVLINK_PORT_FUNCTION_ATTR_MAX - 1
 };
 
+enum devlink_port_fn_state {
+	DEVLINK_PORT_FN_STATE_INACTIVE,
+	DEVLINK_PORT_FN_STATE_ACTIVE,
+};
+
+/**
+ * enum devlink_port_fn_opstate - indicates operational state of the function
+ * @DEVLINK_PORT_FN_OPSTATE_ATTACHED: Driver is attached to the function.
+ * For graceful tear down of the function, after inactivation of the
+ * function, user should wait for operational state to turn DETACHED.
+ * @DEVLINK_PORT_FN_OPSTATE_DETACHED: Driver is detached from the function.
+ * It is safe to delete the port.
+ */
+enum devlink_port_fn_opstate {
+	DEVLINK_PORT_FN_OPSTATE_DETACHED,
+	DEVLINK_PORT_FN_OPSTATE_ATTACHED,
+};
+
 #endif /* _LINUX_DEVLINK_H_ */
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next 2/5] devlink: Introduce PCI SF port flavour and attribute
  2021-01-29 16:56 [PATCH iproute2-next 0/5] Support devlink port add delete Parav Pandit
  2021-01-29 16:56 ` [PATCH iproute2-next 1/5] devlink: Update kernel headers Parav Pandit
@ 2021-01-29 16:56 ` Parav Pandit
  2021-01-29 16:56 ` [PATCH iproute2-next 3/5] devlink: Supporting add and delete of devlink port Parav Pandit
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-01-29 16:56 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit, Jiri Pirko

Introduce PCI SF port flavour and port attributes such as PF
number and SF number.

$ 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

$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08: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

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

$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active

$ devlink port show pci/0000:06:00.0/32768 -jp
{
    "port": {
        "pci/0000:06:00.0/32768": {
            "type": "eth",
            "netdev": "ens2f0npf0sf88",
            "flavour": "pcisf",
            "controller": 0,
            "pfnum": 0,
            "sfnum": 88,
            "splittable": false,
            "function": {
                "hw_addr": "00:00:00:00:88:88",
                "state": "active",
                "opstate": "attached"
            }
        }
    }
}

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
 devlink/devlink.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/devlink/devlink.c b/devlink/devlink.c
index a2e06644..ceafd179 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -3728,6 +3728,8 @@ static const char *port_flavour_name(uint16_t flavour)
 		return "pcipf";
 	case DEVLINK_PORT_FLAVOUR_PCI_VF:
 		return "pcivf";
+	case DEVLINK_PORT_FLAVOUR_PCI_SF:
+		return "pcisf";
 	case DEVLINK_PORT_FLAVOUR_VIRTUAL:
 		return "virtual";
 	default:
@@ -3735,7 +3737,7 @@ static const char *port_flavour_name(uint16_t flavour)
 	}
 }
 
-static void pr_out_port_pfvf_num(struct dl *dl, struct nlattr **tb)
+static void pr_out_port_pfvfsf_num(struct dl *dl, struct nlattr **tb)
 {
 	uint16_t fn_num;
 
@@ -3750,6 +3752,10 @@ static void pr_out_port_pfvf_num(struct dl *dl, struct nlattr **tb)
 		fn_num = mnl_attr_get_u16(tb[DEVLINK_ATTR_PORT_PCI_VF_NUMBER]);
 		print_uint(PRINT_ANY, "vfnum", " vfnum %u", fn_num);
 	}
+	if (tb[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]) {
+		fn_num = mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]);
+		print_uint(PRINT_ANY, "sfnum", " sfnum %u", fn_num);
+	}
 	if (tb[DEVLINK_ATTR_PORT_EXTERNAL]) {
 		uint8_t external;
 
@@ -3827,7 +3833,8 @@ static void pr_out_port(struct dl *dl, struct nlattr **tb)
 		switch (port_flavour) {
 		case DEVLINK_PORT_FLAVOUR_PCI_PF:
 		case DEVLINK_PORT_FLAVOUR_PCI_VF:
-			pr_out_port_pfvf_num(dl, tb);
+		case DEVLINK_PORT_FLAVOUR_PCI_SF:
+			pr_out_port_pfvfsf_num(dl, tb);
 			break;
 		default:
 			break;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next 3/5] devlink: Supporting add and delete of devlink port
  2021-01-29 16:56 [PATCH iproute2-next 0/5] Support devlink port add delete Parav Pandit
  2021-01-29 16:56 ` [PATCH iproute2-next 1/5] devlink: Update kernel headers Parav Pandit
  2021-01-29 16:56 ` [PATCH iproute2-next 2/5] devlink: Introduce PCI SF port flavour and attribute Parav Pandit
@ 2021-01-29 16:56 ` Parav Pandit
  2021-01-31 17:26   ` David Ahern
  2021-01-29 16:56 ` [PATCH iproute2-next 4/5] devlink: Support get port function state Parav Pandit
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 19+ messages in thread
From: Parav Pandit @ 2021-01-29 16:56 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit, Jiri Pirko

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(+)

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),
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next 4/5] devlink: Support get port function state
  2021-01-29 16:56 [PATCH iproute2-next 0/5] Support devlink port add delete Parav Pandit
                   ` (2 preceding siblings ...)
  2021-01-29 16:56 ` [PATCH iproute2-next 3/5] devlink: Supporting add and delete of devlink port Parav Pandit
@ 2021-01-29 16:56 ` Parav Pandit
  2021-01-29 16:56 ` [PATCH iproute2-next 5/5] devlink: Support set of " Parav Pandit
  2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
  5 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-01-29 16:56 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit, Jiri Pirko

Print port function state and operational state whenever reported by
kernel.

Example of a PCI SF port function which supports the state:

$ 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

$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08: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

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

$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88

$ devlink port show pci/0000:06:00.0/32768 -jp
{
    "port": {
        "pci/0000:06:00.0/32768": {
            "type": "eth",
            "netdev": "ens2f0npf0sf88",
            "flavour": "pcisf",
            "controller": 0,
            "pfnum": 0,
            "sfnum": 88,
            "splittable": false,
            "function": {
                "hw_addr": "00:00:00:00:88:88",
                "state": "inactive",
                "opstate": "detached"
            }
        }
    }
}

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
 devlink/devlink.c | 55 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 47 insertions(+), 8 deletions(-)

diff --git a/devlink/devlink.c b/devlink/devlink.c
index 515dadc8..85b9bce9 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -3833,6 +3833,30 @@ static void pr_out_port_pfvfsf_num(struct dl *dl, struct nlattr **tb)
 	}
 }
 
+static const char *port_function_state(uint8_t state)
+{
+	switch (state) {
+	case DEVLINK_PORT_FN_STATE_INACTIVE:
+		return "inactive";
+	case DEVLINK_PORT_FN_STATE_ACTIVE:
+		return "active";
+	default:
+		return "unknown";
+	}
+}
+
+static const char *port_function_opstate(uint8_t state)
+{
+	switch (state) {
+	case DEVLINK_PORT_FN_OPSTATE_DETACHED:
+		return "detached";
+	case DEVLINK_PORT_FN_OPSTATE_ATTACHED:
+		return "attached";
+	default:
+		return "unknown";
+	}
+}
+
 static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port)
 {
 	struct nlattr *tb[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = {};
@@ -3849,16 +3873,31 @@ static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port)
 	if (err != MNL_CB_OK)
 		return;
 
-	if (!tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR])
-		return;
-
-	len = mnl_attr_get_payload_len(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
-	data = mnl_attr_get_payload(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
-
 	pr_out_object_start(dl, "function");
 	check_indent_newline(dl);
-	print_string(PRINT_ANY, "hw_addr", "hw_addr %s",
-		     ll_addr_n2a(data, len, 0, hw_addr, sizeof(hw_addr)));
+
+	if (tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]) {
+		len = mnl_attr_get_payload_len(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
+		data = mnl_attr_get_payload(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
+
+		print_string(PRINT_ANY, "hw_addr", "hw_addr %s",
+			     ll_addr_n2a(data, len, 0, hw_addr, sizeof(hw_addr)));
+	}
+	if (tb[DEVLINK_PORT_FN_ATTR_STATE]) {
+		uint8_t state;
+
+		state = mnl_attr_get_u8(tb[DEVLINK_PORT_FN_ATTR_STATE]);
+
+		print_string(PRINT_ANY, "state", " state %s", port_function_state(state));
+	}
+	if (tb[DEVLINK_PORT_FN_ATTR_OPSTATE]) {
+		uint8_t state;
+
+		state = mnl_attr_get_u8(tb[DEVLINK_PORT_FN_ATTR_OPSTATE]);
+
+		print_string(PRINT_ANY, "opstate", " opstate %s", port_function_opstate(state));
+	}
+
 	if (!dl->json_output)
 		__pr_out_indent_dec();
 	pr_out_object_end(dl);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next 5/5] devlink: Support set of port function state
  2021-01-29 16:56 [PATCH iproute2-next 0/5] Support devlink port add delete Parav Pandit
                   ` (3 preceding siblings ...)
  2021-01-29 16:56 ` [PATCH iproute2-next 4/5] devlink: Support get port function state Parav Pandit
@ 2021-01-29 16:56 ` Parav Pandit
  2021-01-31 17:30   ` David Ahern
  2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
  5 siblings, 1 reply; 19+ messages in thread
From: Parav Pandit @ 2021-01-29 16:56 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit, Jiri Pirko

Support set operation of the devlink port function state.

Example of a PCI SF port function which supports the state:

$ 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

$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08: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

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

$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active

$ devlink port show pci/0000:06:00.0/32768 -jp
{
    "port": {
        "pci/0000:06:00.0/32768": {
            "type": "eth",
            "netdev": "ens2f0npf0sf88",
            "flavour": "pcisf",
            "controller": 0,
            "pfnum": 0,
            "sfnum": 88,
            "splittable": false,
            "function": {
                "hw_addr": "00:00:00:00:88:88",
                "state": "active",
                "opstate": "attached"
            }
        }
    }
}

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

diff --git a/devlink/devlink.c b/devlink/devlink.c
index 85b9bce9..d233dcdd 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -309,6 +309,7 @@ static void ifname_map_free(struct ifname_map *ifname_map)
 #define DL_OPT_PORT_FLAVOUR BIT(42)
 #define DL_OPT_PORT_PFNUMBER BIT(43)
 #define DL_OPT_PORT_SFNUMBER BIT(44)
+#define DL_OPT_PORT_FUNCTION_STATE BIT(45)
 
 struct dl_opts {
 	uint64_t present; /* flags of present items */
@@ -362,6 +363,7 @@ struct dl_opts {
 	uint32_t port_sfnumber;
 	uint16_t port_flavour;
 	uint16_t port_pfnumber;
+	uint8_t port_function_state;
 };
 
 struct dl {
@@ -747,6 +749,7 @@ static int attr_stats_cb(const struct nlattr *attr, void *data)
 static const enum mnl_attr_data_type
 devlink_function_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = {
 	[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR ] = MNL_TYPE_BINARY,
+	[DEVLINK_PORT_FN_ATTR_STATE] = MNL_TYPE_U8,
 };
 
 static int function_attr_cb(const struct nlattr *attr, void *data)
@@ -1420,6 +1423,22 @@ static int port_flavour_parse(const char *flavour, uint16_t *value)
 	}
 }
 
+static int port_function_state_parse(const char *statestr, uint8_t *state)
+{
+	if (!statestr)
+		return -EINVAL;
+
+	if (strcmp(statestr, "inactive") == 0) {
+		*state = DEVLINK_PORT_FN_STATE_INACTIVE;
+		return 0;
+	} else if (strcmp(statestr, "active") == 0) {
+		*state = DEVLINK_PORT_FN_STATE_ACTIVE;
+		return 0;
+	} else {
+		return -EINVAL;
+	}
+}
+
 struct dl_args_metadata {
 	uint64_t o_flag;
 	char err_msg[DL_ARGS_REQUIRED_MAX_ERR_LEN];
@@ -1871,6 +1890,19 @@ 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, "state") &&
+			   (o_all & DL_OPT_PORT_FUNCTION_STATE)) {
+			const char *statestr;
+
+			dl_arg_inc(dl);
+			err = dl_argv_str(dl, &statestr);
+			if (err)
+				return err;
+			err = port_function_state_parse(statestr, &opts->port_function_state);
+			if (err)
+				return err;
+
+			o_found |= DL_OPT_PORT_FUNCTION_STATE;
 		} else if (dl_argv_match(dl, "flavour") && (o_all & DL_OPT_PORT_FLAVOUR)) {
 			const char *flavourstr;
 
@@ -1916,9 +1948,14 @@ dl_function_attr_put(struct nlmsghdr *nlh, const struct dl_opts *opts)
 	struct nlattr *nest;
 
 	nest = mnl_attr_nest_start(nlh, DEVLINK_ATTR_PORT_FUNCTION);
-	mnl_attr_put(nlh, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,
-		     opts->port_function_hw_addr_len,
-		     opts->port_function_hw_addr);
+
+	if (opts->present & DL_OPT_PORT_FUNCTION_HW_ADDR)
+		mnl_attr_put(nlh, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,
+			     opts->port_function_hw_addr_len,
+			     opts->port_function_hw_addr);
+	if (opts->present & DL_OPT_PORT_FUNCTION_STATE)
+		mnl_attr_put_u8(nlh, DEVLINK_PORT_FN_ATTR_STATE,
+				opts->port_function_state);
 	mnl_attr_nest_end(nlh, nest);
 }
 
@@ -2074,7 +2111,7 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
 	if (opts->present & DL_OPT_TRAP_POLICER_BURST)
 		mnl_attr_put_u64(nlh, DEVLINK_ATTR_TRAP_POLICER_BURST,
 				 opts->trap_policer_burst);
-	if (opts->present & DL_OPT_PORT_FUNCTION_HW_ADDR)
+	if (opts->present & (DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE))
 		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);
@@ -3767,7 +3804,7 @@ static void cmd_port_help(void)
 	pr_err("       devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
 	pr_err("       devlink port split DEV/PORT_INDEX count COUNT\n");
 	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 function set DEV/PORT_INDEX [ hw_addr ADDR ] [ state STATE ]\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");
@@ -3897,7 +3934,6 @@ static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port)
 
 		print_string(PRINT_ANY, "opstate", " opstate %s", port_function_opstate(state));
 	}
-
 	if (!dl->json_output)
 		__pr_out_indent_dec();
 	pr_out_object_end(dl);
@@ -4052,7 +4088,7 @@ static int cmd_port_unsplit(struct dl *dl)
 
 static void cmd_port_function_help(void)
 {
-	pr_err("Usage: devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ]\n");
+	pr_err("Usage: devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ] [ state STATE ]\n");
 }
 
 static int cmd_port_function_set(struct dl *dl)
@@ -4060,9 +4096,14 @@ static int cmd_port_function_set(struct dl *dl)
 	struct nlmsghdr *nlh;
 	int err;
 
+	if (dl_no_arg(dl)) {
+		cmd_port_function_help();
+		return 0;
+	}
 	nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_SET, NLM_F_REQUEST | NLM_F_ACK);
 
-	err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_PORT_FUNCTION_HW_ADDR, 0);
+	err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP,
+				DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE);
 	if (err)
 		return err;
 
diff --git a/man/man8/devlink-port.8 b/man/man8/devlink-port.8
index 4a1d3800..55f1cce6 100644
--- a/man/man8/devlink-port.8
+++ b/man/man8/devlink-port.8
@@ -60,6 +60,16 @@ devlink-port \- devlink port configuration
 .B devlink port del
 .IR DEV/PORT_INDEX
 
+.ti -8
+.BR "devlink port function set "
+.IR DEV/PORT_INDEX
+.RI "{ "
+.BR "hw_addr "
+.RI "ADDR }"
+.RI "{ "
+.BR "state"
+.RI "STATE }"
+
 .ti -8
 .B devlink port help
 
@@ -144,7 +154,30 @@ 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.
+This field is optional for those devices which supports auto assignment of the
+SF number.
+
+.ti -8
+.SS devlink port function set - Set the port function attribute(s).
+
+.PP
+.B "DEV/PORT_INDEX"
+- specifies the devlink port to operate on.
+
+.TP
+.BR hw_addr " ADDR"
+- hardware address of the function to set. This is a Ethernet MAC address when
+port type is Ethernet.
+
+.TP
+.BR state " { " active " | " inactive " } "
+- new state of the function to change to.
+
+.I active
+- Once configuration of the function is done, activate the function.
+
+.I inactive
+- To inactivate the function and its device(s), set to inactive.
 
 .ti -8
 .SS devlink port del - delete a devlink port
@@ -192,11 +225,42 @@ Shows status and configuration of tx reporter registered on pci/0000:01:00.0/1 d
 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.
+To make use of the function an example sequence is to add a port, configure the
+function attribute and activate the function. Once function usage is completed,
+inactivate the function and finally delete the port. When there is desire to
+reuse the port without deletion, it can be reconfigured and activated again when
+function is in inactive state and function's operational state is detached.
 .RE
 .PP
 devlink port del pci/0000:06:00.0/1
 .RS 4
-Delete previously created devlink port.
+Delete previously created devlink port. It is recommended to first deactivate
+the function if the function supports state management.
+.RE
+.PP
+devlink port function set pci/0000:01:00.0/1 hw_addr 00:00:00:11:22:33
+.RS 4
+Configure hardware address of the PCI function represented by devlink port.
+If the port supports change in function state, hardware address must be configured
+before activating the function.
+.RE
+.PP
+devlink port function set pci/0000:01:00.0/1 state active
+.RS 4
+Activate the function. This will initiate the function enumeration and driver loading.
+.RE
+.PP
+devlink port function set pci/0000:01:00.0/1 state inactive
+.RS 4
+Deactivate the function. This will initiate the function teardown which results
+in driver unload and device removal.
+.RE
+.PP
+devlink port function set pci/0000:01:00.0/1 hw_addr 00:00:00:11:22:33 state active
+.RS 4
+Configure hardware address and also active the function. When a function is
+activated together with other configuration in a single command, all the
+configuration is applied first before changing the state to active.
 .RE
 
 .SH SEE ALSO
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH iproute2-next 3/5] devlink: Supporting add and delete of devlink port
  2021-01-29 16:56 ` [PATCH iproute2-next 3/5] devlink: Supporting add and delete of devlink port Parav Pandit
@ 2021-01-31 17:26   ` David Ahern
  2021-02-01 20:42     ` Parav Pandit
  0 siblings, 1 reply; 19+ messages in thread
From: David Ahern @ 2021-01-31 17:26 UTC (permalink / raw)
  To: Parav Pandit, stephen, netdev; +Cc: Jiri Pirko

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.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH iproute2-next 5/5] devlink: Support set of port function state
  2021-01-29 16:56 ` [PATCH iproute2-next 5/5] devlink: Support set of " Parav Pandit
@ 2021-01-31 17:30   ` David Ahern
  2021-02-01 20:50     ` Parav Pandit
  0 siblings, 1 reply; 19+ messages in thread
From: David Ahern @ 2021-01-31 17:30 UTC (permalink / raw)
  To: Parav Pandit, stephen, netdev; +Cc: Jiri Pirko

On 1/29/21 9:56 AM, Parav Pandit wrote:
> @@ -1420,6 +1423,22 @@ static int port_flavour_parse(const char *flavour, uint16_t *value)
>  	}
>  }
>  
> +static int port_function_state_parse(const char *statestr, uint8_t *state)
> +{
> +	if (!statestr)
> +		return -EINVAL;
> +
> +	if (strcmp(statestr, "inactive") == 0) {
> +		*state = DEVLINK_PORT_FN_STATE_INACTIVE;
> +		return 0;
> +	} else if (strcmp(statestr, "active") == 0) {
> +		*state = DEVLINK_PORT_FN_STATE_ACTIVE;
> +		return 0;
> +	} else {
> +		return -EINVAL;
> +	}
> +}
> +

if another state gets added this too should be table driven - string to
type here and the inverse in the previous patch.

>  struct dl_args_metadata {
>  	uint64_t o_flag;
>  	char err_msg[DL_ARGS_REQUIRED_MAX_ERR_LEN];



> @@ -3897,7 +3934,6 @@ static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port)
>  
>  		print_string(PRINT_ANY, "opstate", " opstate %s", port_function_opstate(state));
>  	}
> -
>  	if (!dl->json_output)
>  		__pr_out_indent_dec();
>  	pr_out_object_end(dl);

Removing the newline intentional?





^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH iproute2-next 3/5] devlink: Supporting add and delete of devlink port
  2021-01-31 17:26   ` David Ahern
@ 2021-02-01 20:42     ` Parav Pandit
  0 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-01 20:42 UTC (permalink / raw)
  To: David Ahern, stephen, netdev; +Cc: Jiri Pirko



> 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.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH iproute2-next 5/5] devlink: Support set of port function state
  2021-01-31 17:30   ` David Ahern
@ 2021-02-01 20:50     ` Parav Pandit
  0 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-01 20:50 UTC (permalink / raw)
  To: David Ahern, stephen, netdev; +Cc: Jiri Pirko



> From: David Ahern <dsahern@gmail.com>
> Sent: Sunday, January 31, 2021 11:01 PM
> 
> On 1/29/21 9:56 AM, Parav Pandit wrote:
> > @@ -1420,6 +1423,22 @@ static int port_flavour_parse(const char
> *flavour, uint16_t *value)
> >  	}
> >  }
> >
> > +static int port_function_state_parse(const char *statestr, uint8_t
> > +*state) {
> > +	if (!statestr)
> > +		return -EINVAL;
> > +
> > +	if (strcmp(statestr, "inactive") == 0) {
> > +		*state = DEVLINK_PORT_FN_STATE_INACTIVE;
> > +		return 0;
> > +	} else if (strcmp(statestr, "active") == 0) {
> > +		*state = DEVLINK_PORT_FN_STATE_ACTIVE;
> > +		return 0;
> > +	} else {
> > +		return -EINVAL;
> > +	}
> > +}
> > +
> 
> if another state gets added this too should be table driven - string to type
> here and the inverse in the previous patch.
>
Yes. Will reuse the helper that I am introducing for port flavour in v2.
 
> >  struct dl_args_metadata {
> >  	uint64_t o_flag;
> >  	char err_msg[DL_ARGS_REQUIRED_MAX_ERR_LEN];
> 
> 
> 
> > @@ -3897,7 +3934,6 @@ static void pr_out_port_function(struct dl *dl,
> > struct nlattr **tb_port)
> >
> >  		print_string(PRINT_ANY, "opstate", " opstate %s",
> port_function_opstate(state));
> >  	}
> > -
> >  	if (!dl->json_output)
> >  		__pr_out_indent_dec();
> >  	pr_out_object_end(dl);
> 
> Removing the newline intentional?
> 
Oops. Will add back.
> 
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next v2 0/6] Support devlink port add delete
  2021-01-29 16:56 [PATCH iproute2-next 0/5] Support devlink port add delete Parav Pandit
                   ` (4 preceding siblings ...)
  2021-01-29 16:56 ` [PATCH iproute2-next 5/5] devlink: Support set of " Parav Pandit
@ 2021-02-01 21:35 ` Parav Pandit
  2021-02-01 21:35   ` [PATCH iproute2-next v2 1/6] devlink: Update kernel headers Parav Pandit
                     ` (6 more replies)
  5 siblings, 7 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-01 21:35 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit

This patchset implements devlink port add, delete and function state
management commands.

An example sequence for a PCI SF:

Set the device in switchdev mode:
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev

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

Add a subfunction port for PCI PF 0 with sfnumber 88:
$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08: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

Show a newly added port:
$ devlink port show pci/0000:06:00.0/32768
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached

Set the function state to active:
$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active

Show the port in JSON format:
$ devlink port show pci/0000:06:00.0/32768 -jp
{
    "port": {
        "pci/0000:06:00.0/32768": {
            "type": "eth",
            "netdev": "ens2f0npf0sf88",
            "flavour": "pcisf",
            "controller": 0,
            "pfnum": 0,
            "sfnum": 88,
            "splittable": false,
            "function": {
                "hw_addr": "00:00:00:00:88:88",
                "state": "active",
                "opstate": "attached"
            }
        }
    }
}

Set the function state to active:
$ devlink port function set pci/0000:06:00.0/32768 state inactive

Delete the port after use:
$ devlink port del pci/0000:06:00.0/32768

Patch summary:
Patch-1 updates kernel headers
Patch-2 introduces string to number map helper and uses it for port
flavour
Patch-3 shows PCI SF port attributes
Patch-4 adds devlink commands to add and delete a port along with man
page
Patch-5 shows function state and operational state to user
Patch-6 enables user to set function state and adds man page
documentation


Parav Pandit (6):
  devlink: Update kernel headers
  devlink: Introduce and use string to number mapper
  devlink: Introduce PCI SF port flavour and attribute
  devlink: Supporting add and delete of devlink port
  devlink: Support get port function state
  devlink: Support set of port function state

 devlink/devlink.c            | 260 ++++++++++++++++++++++++++++++-----
 include/uapi/linux/devlink.h |  25 ++++
 include/utils.h              |   9 ++
 lib/utils.c                  |  41 ++++++
 man/man8/devlink-port.8      | 127 +++++++++++++++++
 5 files changed, 429 insertions(+), 33 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next v2 1/6] devlink: Update kernel headers
  2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
@ 2021-02-01 21:35   ` Parav Pandit
  2021-02-01 21:35   ` [PATCH iproute2-next v2 2/6] devlink: Introduce and use string to number mapper Parav Pandit
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-01 21:35 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit

Update kernel headers to
commit a556dded9c23 ("devlink: Support get and set state of port function")

Signed-off-by: Parav Pandit <parav@nvidia.com>
---
 include/uapi/linux/devlink.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 958ef7b9..a430775d 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -200,6 +200,10 @@ enum devlink_port_flavour {
 	DEVLINK_PORT_FLAVOUR_UNUSED, /* Port which exists in the switch, but
 				      * is not used in any way.
 				      */
+	DEVLINK_PORT_FLAVOUR_PCI_SF, /* Represents eswitch port
+				      * for the PCI SF. It is an internal
+				      * port that faces the PCI SF.
+				      */
 };
 
 enum devlink_param_cmode {
@@ -529,6 +533,7 @@ enum devlink_attr {
 	DEVLINK_ATTR_RELOAD_ACTION_INFO,        /* nested */
 	DEVLINK_ATTR_RELOAD_ACTION_STATS,       /* nested */
 
+	DEVLINK_ATTR_PORT_PCI_SF_NUMBER,	/* u32 */
 	/* add new attributes above here, update the policy in devlink.c */
 
 	__DEVLINK_ATTR_MAX,
@@ -578,9 +583,29 @@ enum devlink_resource_unit {
 enum devlink_port_function_attr {
 	DEVLINK_PORT_FUNCTION_ATTR_UNSPEC,
 	DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,	/* binary */
+	DEVLINK_PORT_FN_ATTR_STATE,	/* u8 */
+	DEVLINK_PORT_FN_ATTR_OPSTATE,	/* u8 */
 
 	__DEVLINK_PORT_FUNCTION_ATTR_MAX,
 	DEVLINK_PORT_FUNCTION_ATTR_MAX = __DEVLINK_PORT_FUNCTION_ATTR_MAX - 1
 };
 
+enum devlink_port_fn_state {
+	DEVLINK_PORT_FN_STATE_INACTIVE,
+	DEVLINK_PORT_FN_STATE_ACTIVE,
+};
+
+/**
+ * enum devlink_port_fn_opstate - indicates operational state of the function
+ * @DEVLINK_PORT_FN_OPSTATE_ATTACHED: Driver is attached to the function.
+ * For graceful tear down of the function, after inactivation of the
+ * function, user should wait for operational state to turn DETACHED.
+ * @DEVLINK_PORT_FN_OPSTATE_DETACHED: Driver is detached from the function.
+ * It is safe to delete the port.
+ */
+enum devlink_port_fn_opstate {
+	DEVLINK_PORT_FN_OPSTATE_DETACHED,
+	DEVLINK_PORT_FN_OPSTATE_ATTACHED,
+};
+
 #endif /* _LINUX_DEVLINK_H_ */
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next v2 2/6] devlink: Introduce and use string to number mapper
  2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
  2021-02-01 21:35   ` [PATCH iproute2-next v2 1/6] devlink: Update kernel headers Parav Pandit
@ 2021-02-01 21:35   ` Parav Pandit
  2021-02-01 21:35   ` [PATCH iproute2-next v2 3/6] devlink: Introduce PCI SF port flavour and attribute Parav Pandit
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-01 21:35 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit

Instead of using static mapping in code, introduce a helper routine to
map a value to string.

Signed-off-by: Parav Pandit <parav@nvidia.com>
---
changelog:
v1->v2:
 - addressed David's comment to use helper routine to map num->string
---
 devlink/devlink.c | 30 ++++++++++++++----------------
 include/utils.h   |  8 ++++++++
 lib/utils.c       | 28 ++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 16 deletions(-)

diff --git a/devlink/devlink.c b/devlink/devlink.c
index a2e06644..d21a7c4d 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -1383,6 +1383,16 @@ static int reload_limit_get(struct dl *dl, const char *limitstr,
 	return 0;
 }
 
+static struct str_num_map port_flavour_map[] = {
+	{ .str = "physical", .num = DEVLINK_PORT_FLAVOUR_PHYSICAL },
+	{ .str = "cpu", .num = DEVLINK_PORT_FLAVOUR_CPU },
+	{ .str = "dsa", .num = DEVLINK_PORT_FLAVOUR_DSA },
+	{ .str = "pcipf", .num = DEVLINK_PORT_FLAVOUR_PCI_PF },
+	{ .str = "pcivf", .num = DEVLINK_PORT_FLAVOUR_PCI_VF },
+	{ .str = "virtual", .num = DEVLINK_PORT_FLAVOUR_VIRTUAL},
+	{ .str = NULL, },
+};
+
 struct dl_args_metadata {
 	uint64_t o_flag;
 	char err_msg[DL_ARGS_REQUIRED_MAX_ERR_LEN];
@@ -3717,22 +3727,10 @@ static const char *port_type_name(uint32_t type)
 
 static const char *port_flavour_name(uint16_t flavour)
 {
-	switch (flavour) {
-	case DEVLINK_PORT_FLAVOUR_PHYSICAL:
-		return "physical";
-	case DEVLINK_PORT_FLAVOUR_CPU:
-		return "cpu";
-	case DEVLINK_PORT_FLAVOUR_DSA:
-		return "dsa";
-	case DEVLINK_PORT_FLAVOUR_PCI_PF:
-		return "pcipf";
-	case DEVLINK_PORT_FLAVOUR_PCI_VF:
-		return "pcivf";
-	case DEVLINK_PORT_FLAVOUR_VIRTUAL:
-		return "virtual";
-	default:
-		return "<unknown flavour>";
-	}
+	const char *str;
+
+	str = str_map_lookup_u16(port_flavour_map, flavour);
+	return str ? str : "<unknown flavour>";
 }
 
 static void pr_out_port_pfvf_num(struct dl *dl, struct nlattr **tb)
diff --git a/include/utils.h b/include/utils.h
index f1403f73..1d67443e 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -340,4 +340,12 @@ int parse_mapping(int *argcp, char ***argvp, bool allow_all,
 		  int (*mapping_cb)(__u32 key, char *value, void *data),
 		  void *mapping_cb_data);
 
+struct str_num_map {
+	const char *str;
+	int num;
+};
+
+int str_map_lookup_str(const struct str_num_map *map, const char *needle);
+const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val);
+
 #endif /* __UTILS_H__ */
diff --git a/lib/utils.c b/lib/utils.c
index 90e58fa3..9fef2d76 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1937,3 +1937,31 @@ int parse_mapping(int *argcp, char ***argvp, bool allow_all,
 		return parse_mapping_gen(argcp, argvp, parse_mapping_num,
 					 mapping_cb, mapping_cb_data);
 }
+
+int str_map_lookup_str(const struct str_num_map *map, const char *needle)
+{
+	if (!needle)
+		return -EINVAL;
+
+	/* Process array which is NULL terminated by the string. */
+	while (map && map->str) {
+		if (strcmp(map->str, needle) == 0)
+			return map->num;
+
+		map++;
+	}
+	return -EINVAL;
+}
+
+const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val)
+{
+	int num = val;
+
+	while (map && map->str) {
+		if (num == map->num)
+			return map->str;
+
+		map++;
+	}
+	return NULL;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next v2 3/6] devlink: Introduce PCI SF port flavour and attribute
  2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
  2021-02-01 21:35   ` [PATCH iproute2-next v2 1/6] devlink: Update kernel headers Parav Pandit
  2021-02-01 21:35   ` [PATCH iproute2-next v2 2/6] devlink: Introduce and use string to number mapper Parav Pandit
@ 2021-02-01 21:35   ` Parav Pandit
  2021-02-01 21:35   ` [PATCH iproute2-next v2 4/6] devlink: Supporting add and delete of devlink port Parav Pandit
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-01 21:35 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit, Jiri Pirko

Introduce PCI SF port flavour and port attributes such as PF
number and SF number.

$ 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

$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08: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

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

$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active

$ devlink port show pci/0000:06:00.0/32768 -jp
{
    "port": {
        "pci/0000:06:00.0/32768": {
            "type": "eth",
            "netdev": "ens2f0npf0sf88",
            "flavour": "pcisf",
            "controller": 0,
            "pfnum": 0,
            "sfnum": 88,
            "splittable": false,
            "function": {
                "hw_addr": "00:00:00:00:88:88",
                "state": "active",
                "opstate": "attached"
            }
        }
    }
}

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
 devlink/devlink.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/devlink/devlink.c b/devlink/devlink.c
index d21a7c4d..338cb035 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -1389,6 +1389,7 @@ static struct str_num_map port_flavour_map[] = {
 	{ .str = "dsa", .num = DEVLINK_PORT_FLAVOUR_DSA },
 	{ .str = "pcipf", .num = DEVLINK_PORT_FLAVOUR_PCI_PF },
 	{ .str = "pcivf", .num = DEVLINK_PORT_FLAVOUR_PCI_VF },
+	{ .str = "pcisf", .num = DEVLINK_PORT_FLAVOUR_PCI_SF },
 	{ .str = "virtual", .num = DEVLINK_PORT_FLAVOUR_VIRTUAL},
 	{ .str = NULL, },
 };
@@ -3733,7 +3734,7 @@ static const char *port_flavour_name(uint16_t flavour)
 	return str ? str : "<unknown flavour>";
 }
 
-static void pr_out_port_pfvf_num(struct dl *dl, struct nlattr **tb)
+static void pr_out_port_pfvfsf_num(struct dl *dl, struct nlattr **tb)
 {
 	uint16_t fn_num;
 
@@ -3748,6 +3749,10 @@ static void pr_out_port_pfvf_num(struct dl *dl, struct nlattr **tb)
 		fn_num = mnl_attr_get_u16(tb[DEVLINK_ATTR_PORT_PCI_VF_NUMBER]);
 		print_uint(PRINT_ANY, "vfnum", " vfnum %u", fn_num);
 	}
+	if (tb[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]) {
+		fn_num = mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]);
+		print_uint(PRINT_ANY, "sfnum", " sfnum %u", fn_num);
+	}
 	if (tb[DEVLINK_ATTR_PORT_EXTERNAL]) {
 		uint8_t external;
 
@@ -3825,7 +3830,8 @@ static void pr_out_port(struct dl *dl, struct nlattr **tb)
 		switch (port_flavour) {
 		case DEVLINK_PORT_FLAVOUR_PCI_PF:
 		case DEVLINK_PORT_FLAVOUR_PCI_VF:
-			pr_out_port_pfvf_num(dl, tb);
+		case DEVLINK_PORT_FLAVOUR_PCI_SF:
+			pr_out_port_pfvfsf_num(dl, tb);
 			break;
 		default:
 			break;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next v2 4/6] devlink: Supporting add and delete of devlink port
  2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
                     ` (2 preceding siblings ...)
  2021-02-01 21:35   ` [PATCH iproute2-next v2 3/6] devlink: Introduce PCI SF port flavour and attribute Parav Pandit
@ 2021-02-01 21:35   ` Parav Pandit
  2021-02-01 21:35   ` [PATCH iproute2-next v2 5/6] devlink: Support get port function state Parav Pandit
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-01 21:35 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit, Jiri Pirko

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>
---
changelog:
v1->v2:
 - addressed David's comment to use struct for string->num mapping
   using helper library routine
---
 devlink/devlink.c       | 108 ++++++++++++++++++++++++++++++++++++++++
 man/man8/devlink-port.8 |  63 +++++++++++++++++++++++
 2 files changed, 171 insertions(+)

diff --git a/devlink/devlink.c b/devlink/devlink.c
index 338cb035..76ea7cac 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 {
@@ -1394,6 +1400,17 @@ static struct str_num_map port_flavour_map[] = {
 	{ .str = NULL, },
 };
 
+static int port_flavour_parse(const char *flavour, uint16_t *value)
+{
+	int num;
+
+	num = str_map_lookup_str(port_flavour_map, flavour);
+	if (num < 0)
+		return num;
+	*value = num;
+	return 0;
+}
+
 struct dl_args_metadata {
 	uint64_t o_flag;
 	char err_msg[DL_ARGS_REQUIRED_MAX_ERR_LEN];
@@ -1425,6 +1442,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,
@@ -1843,7 +1862,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;
@@ -2026,6 +2067,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,
@@ -3713,6 +3760,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 pfnum PFNUM [ sfnum SFNUM ]\n");
+	pr_err("       devlink port del DEV/PORT_INDEX\n");
 }
 
 static const char *port_type_name(uint32_t type)
@@ -3974,6 +4023,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")) {
@@ -4004,7 +4105,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),
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next v2 5/6] devlink: Support get port function state
  2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
                     ` (3 preceding siblings ...)
  2021-02-01 21:35   ` [PATCH iproute2-next v2 4/6] devlink: Supporting add and delete of devlink port Parav Pandit
@ 2021-02-01 21:35   ` Parav Pandit
  2021-02-01 21:35   ` [PATCH iproute2-next v2 6/6] devlink: Support set of " Parav Pandit
  2021-02-02  3:20   ` [PATCH iproute2-next v2 0/6] Support devlink port add delete David Ahern
  6 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-01 21:35 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit, Jiri Pirko

Print port function state and operational state whenever reported by
kernel.

Example of a PCI SF port function which supports the state:

$ 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

$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08: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

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

$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88

$ devlink port show pci/0000:06:00.0/32768 -jp
{
    "port": {
        "pci/0000:06:00.0/32768": {
            "type": "eth",
            "netdev": "ens2f0npf0sf88",
            "flavour": "pcisf",
            "controller": 0,
            "pfnum": 0,
            "sfnum": 88,
            "splittable": false,
            "function": {
                "hw_addr": "00:00:00:00:88:88",
                "state": "inactive",
                "opstate": "detached"
            }
        }
    }
}

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
changelog:
v1->v2:
 - using helper routine to perform string<->u8 mapping for state and
   operational state
---
 devlink/devlink.c | 61 ++++++++++++++++++++++++++++++++++++++++-------
 include/utils.h   |  1 +
 lib/utils.c       | 13 ++++++++++
 3 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/devlink/devlink.c b/devlink/devlink.c
index 76ea7cac..17db8623 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -1400,6 +1400,18 @@ static struct str_num_map port_flavour_map[] = {
 	{ .str = NULL, },
 };
 
+static struct str_num_map port_fn_state_map[] = {
+	{ .str = "inactive", .num = DEVLINK_PORT_FN_STATE_INACTIVE},
+	{ .str = "active", .num = DEVLINK_PORT_FN_STATE_ACTIVE },
+	{ .str = NULL, }
+};
+
+static struct str_num_map port_fn_opstate_map[] = {
+	{ .str = "attached", .num = DEVLINK_PORT_FN_OPSTATE_ATTACHED},
+	{ .str = "detached", .num = DEVLINK_PORT_FN_OPSTATE_DETACHED},
+	{ .str = NULL, }
+};
+
 static int port_flavour_parse(const char *flavour, uint16_t *value)
 {
 	int num;
@@ -3810,6 +3822,22 @@ static void pr_out_port_pfvfsf_num(struct dl *dl, struct nlattr **tb)
 	}
 }
 
+static const char *port_fn_state(uint8_t state)
+{
+	const char *str;
+
+	str = str_map_lookup_u8(port_fn_state_map, state);
+	return str ? str : "<unknown state>";
+}
+
+static const char *port_fn_opstate(uint8_t state)
+{
+	const char *str;
+
+	str = str_map_lookup_u8(port_fn_opstate_map, state);
+	return str ? str : "<unknown state>";
+}
+
 static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port)
 {
 	struct nlattr *tb[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = {};
@@ -3826,16 +3854,33 @@ static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port)
 	if (err != MNL_CB_OK)
 		return;
 
-	if (!tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR])
-		return;
-
-	len = mnl_attr_get_payload_len(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
-	data = mnl_attr_get_payload(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
-
 	pr_out_object_start(dl, "function");
 	check_indent_newline(dl);
-	print_string(PRINT_ANY, "hw_addr", "hw_addr %s",
-		     ll_addr_n2a(data, len, 0, hw_addr, sizeof(hw_addr)));
+
+	if (tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]) {
+		len = mnl_attr_get_payload_len(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
+		data = mnl_attr_get_payload(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
+
+		print_string(PRINT_ANY, "hw_addr", "hw_addr %s",
+			     ll_addr_n2a(data, len, 0, hw_addr, sizeof(hw_addr)));
+	}
+	if (tb[DEVLINK_PORT_FN_ATTR_STATE]) {
+		uint8_t state;
+
+		state = mnl_attr_get_u8(tb[DEVLINK_PORT_FN_ATTR_STATE]);
+
+		print_string(PRINT_ANY, "state", " state %s",
+			     port_fn_state(state));
+	}
+	if (tb[DEVLINK_PORT_FN_ATTR_OPSTATE]) {
+		uint8_t state;
+
+		state = mnl_attr_get_u8(tb[DEVLINK_PORT_FN_ATTR_OPSTATE]);
+
+		print_string(PRINT_ANY, "opstate", " opstate %s",
+			     port_fn_opstate(state));
+	}
+
 	if (!dl->json_output)
 		__pr_out_indent_dec();
 	pr_out_object_end(dl);
diff --git a/include/utils.h b/include/utils.h
index 1d67443e..e66090ae 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -347,5 +347,6 @@ struct str_num_map {
 
 int str_map_lookup_str(const struct str_num_map *map, const char *needle);
 const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val);
+const char *str_map_lookup_u8(const struct str_num_map *map, uint8_t val);
 
 #endif /* __UTILS_H__ */
diff --git a/lib/utils.c b/lib/utils.c
index 9fef2d76..af1b553c 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1965,3 +1965,16 @@ const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val)
 	}
 	return NULL;
 }
+
+const char *str_map_lookup_u8(const struct str_num_map *map, uint8_t val)
+{
+	int num = val;
+
+	while (map && map->str) {
+		if (num == map->num)
+			return map->str;
+
+		map++;
+	}
+	return NULL;
+}
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH iproute2-next v2 6/6] devlink: Support set of port function state
  2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
                     ` (4 preceding siblings ...)
  2021-02-01 21:35   ` [PATCH iproute2-next v2 5/6] devlink: Support get port function state Parav Pandit
@ 2021-02-01 21:35   ` Parav Pandit
  2021-02-02  3:20   ` [PATCH iproute2-next v2 0/6] Support devlink port add delete David Ahern
  6 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-01 21:35 UTC (permalink / raw)
  To: dsahern, stephen, netdev; +Cc: Parav Pandit, Jiri Pirko

Support set operation of the devlink port function state.

Example of a PCI SF port function which supports the state:

$ 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

$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08: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

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

$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active

$ devlink port show pci/0000:06:00.0/32768 -jp
{
    "port": {
        "pci/0000:06:00.0/32768": {
            "type": "eth",
            "netdev": "ens2f0npf0sf88",
            "flavour": "pcisf",
            "controller": 0,
            "pfnum": 0,
            "sfnum": 88,
            "splittable": false,
            "function": {
                "hw_addr": "00:00:00:00:88:88",
                "state": "active",
                "opstate": "attached"
            }
        }
    }
}

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
changelog:
v1->v2:
 - using sting<->num mapping helper routine for state and operational
   state
 - change port_function_state to shoter name port_fn_state
---
 devlink/devlink.c       | 51 ++++++++++++++++++++++++++-----
 man/man8/devlink-port.8 | 68 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 110 insertions(+), 9 deletions(-)

diff --git a/devlink/devlink.c b/devlink/devlink.c
index 17db8623..10398f77 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -309,6 +309,7 @@ static void ifname_map_free(struct ifname_map *ifname_map)
 #define DL_OPT_PORT_FLAVOUR BIT(42)
 #define DL_OPT_PORT_PFNUMBER BIT(43)
 #define DL_OPT_PORT_SFNUMBER BIT(44)
+#define DL_OPT_PORT_FUNCTION_STATE BIT(45)
 
 struct dl_opts {
 	uint64_t present; /* flags of present items */
@@ -362,6 +363,7 @@ struct dl_opts {
 	uint32_t port_sfnumber;
 	uint16_t port_flavour;
 	uint16_t port_pfnumber;
+	uint8_t port_fn_state;
 };
 
 struct dl {
@@ -747,6 +749,7 @@ static int attr_stats_cb(const struct nlattr *attr, void *data)
 static const enum mnl_attr_data_type
 devlink_function_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = {
 	[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR ] = MNL_TYPE_BINARY,
+	[DEVLINK_PORT_FN_ATTR_STATE] = MNL_TYPE_U8,
 };
 
 static int function_attr_cb(const struct nlattr *attr, void *data)
@@ -1423,6 +1426,17 @@ static int port_flavour_parse(const char *flavour, uint16_t *value)
 	return 0;
 }
 
+static int port_fn_state_parse(const char *statestr, uint8_t *state)
+{
+	int num;
+
+	num = str_map_lookup_str(port_fn_state_map, statestr);
+	if (num < 0)
+		return num;
+	*state = num;
+	return 0;
+}
+
 struct dl_args_metadata {
 	uint64_t o_flag;
 	char err_msg[DL_ARGS_REQUIRED_MAX_ERR_LEN];
@@ -1874,6 +1888,19 @@ 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, "state") &&
+			   (o_all & DL_OPT_PORT_FUNCTION_STATE)) {
+			const char *statestr;
+
+			dl_arg_inc(dl);
+			err = dl_argv_str(dl, &statestr);
+			if (err)
+				return err;
+			err = port_fn_state_parse(statestr, &opts->port_fn_state);
+			if (err)
+				return err;
+
+			o_found |= DL_OPT_PORT_FUNCTION_STATE;
 		} else if (dl_argv_match(dl, "flavour") && (o_all & DL_OPT_PORT_FLAVOUR)) {
 			const char *flavourstr;
 
@@ -1919,9 +1946,14 @@ dl_function_attr_put(struct nlmsghdr *nlh, const struct dl_opts *opts)
 	struct nlattr *nest;
 
 	nest = mnl_attr_nest_start(nlh, DEVLINK_ATTR_PORT_FUNCTION);
-	mnl_attr_put(nlh, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,
-		     opts->port_function_hw_addr_len,
-		     opts->port_function_hw_addr);
+
+	if (opts->present & DL_OPT_PORT_FUNCTION_HW_ADDR)
+		mnl_attr_put(nlh, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,
+			     opts->port_function_hw_addr_len,
+			     opts->port_function_hw_addr);
+	if (opts->present & DL_OPT_PORT_FUNCTION_STATE)
+		mnl_attr_put_u8(nlh, DEVLINK_PORT_FN_ATTR_STATE,
+				opts->port_fn_state);
 	mnl_attr_nest_end(nlh, nest);
 }
 
@@ -2077,7 +2109,7 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
 	if (opts->present & DL_OPT_TRAP_POLICER_BURST)
 		mnl_attr_put_u64(nlh, DEVLINK_ATTR_TRAP_POLICER_BURST,
 				 opts->trap_policer_burst);
-	if (opts->present & DL_OPT_PORT_FUNCTION_HW_ADDR)
+	if (opts->present & (DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE))
 		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);
@@ -3770,7 +3802,7 @@ static void cmd_port_help(void)
 	pr_err("       devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
 	pr_err("       devlink port split DEV/PORT_INDEX count COUNT\n");
 	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 function set DEV/PORT_INDEX [ hw_addr ADDR ] [ state STATE ]\n");
 	pr_err("       devlink port health show [ DEV/PORT_INDEX reporter REPORTER_NAME ]\n");
 	pr_err("       devlink port add DEV/PORT_INDEX flavour FLAVOUR pfnum PFNUM [ sfnum SFNUM ]\n");
 	pr_err("       devlink port del DEV/PORT_INDEX\n");
@@ -4035,7 +4067,7 @@ static int cmd_port_unsplit(struct dl *dl)
 
 static void cmd_port_function_help(void)
 {
-	pr_err("Usage: devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ]\n");
+	pr_err("Usage: devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ] [ state STATE ]\n");
 }
 
 static int cmd_port_function_set(struct dl *dl)
@@ -4043,9 +4075,14 @@ static int cmd_port_function_set(struct dl *dl)
 	struct nlmsghdr *nlh;
 	int err;
 
+	if (dl_no_arg(dl)) {
+		cmd_port_function_help();
+		return 0;
+	}
 	nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_SET, NLM_F_REQUEST | NLM_F_ACK);
 
-	err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_PORT_FUNCTION_HW_ADDR, 0);
+	err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP,
+				DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE);
 	if (err)
 		return err;
 
diff --git a/man/man8/devlink-port.8 b/man/man8/devlink-port.8
index 4a1d3800..55f1cce6 100644
--- a/man/man8/devlink-port.8
+++ b/man/man8/devlink-port.8
@@ -60,6 +60,16 @@ devlink-port \- devlink port configuration
 .B devlink port del
 .IR DEV/PORT_INDEX
 
+.ti -8
+.BR "devlink port function set "
+.IR DEV/PORT_INDEX
+.RI "{ "
+.BR "hw_addr "
+.RI "ADDR }"
+.RI "{ "
+.BR "state"
+.RI "STATE }"
+
 .ti -8
 .B devlink port help
 
@@ -144,7 +154,30 @@ 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.
+This field is optional for those devices which supports auto assignment of the
+SF number.
+
+.ti -8
+.SS devlink port function set - Set the port function attribute(s).
+
+.PP
+.B "DEV/PORT_INDEX"
+- specifies the devlink port to operate on.
+
+.TP
+.BR hw_addr " ADDR"
+- hardware address of the function to set. This is a Ethernet MAC address when
+port type is Ethernet.
+
+.TP
+.BR state " { " active " | " inactive " } "
+- new state of the function to change to.
+
+.I active
+- Once configuration of the function is done, activate the function.
+
+.I inactive
+- To inactivate the function and its device(s), set to inactive.
 
 .ti -8
 .SS devlink port del - delete a devlink port
@@ -192,11 +225,42 @@ Shows status and configuration of tx reporter registered on pci/0000:01:00.0/1 d
 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.
+To make use of the function an example sequence is to add a port, configure the
+function attribute and activate the function. Once function usage is completed,
+inactivate the function and finally delete the port. When there is desire to
+reuse the port without deletion, it can be reconfigured and activated again when
+function is in inactive state and function's operational state is detached.
 .RE
 .PP
 devlink port del pci/0000:06:00.0/1
 .RS 4
-Delete previously created devlink port.
+Delete previously created devlink port. It is recommended to first deactivate
+the function if the function supports state management.
+.RE
+.PP
+devlink port function set pci/0000:01:00.0/1 hw_addr 00:00:00:11:22:33
+.RS 4
+Configure hardware address of the PCI function represented by devlink port.
+If the port supports change in function state, hardware address must be configured
+before activating the function.
+.RE
+.PP
+devlink port function set pci/0000:01:00.0/1 state active
+.RS 4
+Activate the function. This will initiate the function enumeration and driver loading.
+.RE
+.PP
+devlink port function set pci/0000:01:00.0/1 state inactive
+.RS 4
+Deactivate the function. This will initiate the function teardown which results
+in driver unload and device removal.
+.RE
+.PP
+devlink port function set pci/0000:01:00.0/1 hw_addr 00:00:00:11:22:33 state active
+.RS 4
+Configure hardware address and also active the function. When a function is
+activated together with other configuration in a single command, all the
+configuration is applied first before changing the state to active.
 .RE
 
 .SH SEE ALSO
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH iproute2-next v2 0/6] Support devlink port add delete
  2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
                     ` (5 preceding siblings ...)
  2021-02-01 21:35   ` [PATCH iproute2-next v2 6/6] devlink: Support set of " Parav Pandit
@ 2021-02-02  3:20   ` David Ahern
  2021-02-02  4:01     ` Parav Pandit
  6 siblings, 1 reply; 19+ messages in thread
From: David Ahern @ 2021-02-02  3:20 UTC (permalink / raw)
  To: Parav Pandit, stephen, netdev

On 2/1/21 2:35 PM, Parav Pandit wrote:
> This patchset implements devlink port add, delete and function state
> management commands.
> 
> An example sequence for a PCI SF:
> 
> Set the device in switchdev mode:
> $ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
> 
> View ports in switchdev mode:
> $ devlink port show
> pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical port 0 splittable false
> 
> Add a subfunction port for PCI PF 0 with sfnumber 88:
> $ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
> pci/0000:08: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
> 
> Show a newly added port:
> $ devlink port show pci/0000:06:00.0/32768
> pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 splittable false
>   function:
>     hw_addr 00:00:00:00:00:00 state inactive opstate detached
> 
> Set the function state to active:
> $ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active
> 
> Show the port in JSON format:
> $ devlink port show pci/0000:06:00.0/32768 -jp
> {
>     "port": {
>         "pci/0000:06:00.0/32768": {
>             "type": "eth",
>             "netdev": "ens2f0npf0sf88",
>             "flavour": "pcisf",
>             "controller": 0,
>             "pfnum": 0,
>             "sfnum": 88,
>             "splittable": false,
>             "function": {
>                 "hw_addr": "00:00:00:00:88:88",
>                 "state": "active",
>                 "opstate": "attached"
>             }
>         }
>     }
> }
> 
> Set the function state to active:
> $ devlink port function set pci/0000:06:00.0/32768 state inactive
> 
> Delete the port after use:
> $ devlink port del pci/0000:06:00.0/32768
> 

applied to iproute2-next.

In the future, please split additions and changes to utility functions
into a separate standalone patch.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: [PATCH iproute2-next v2 0/6] Support devlink port add delete
  2021-02-02  3:20   ` [PATCH iproute2-next v2 0/6] Support devlink port add delete David Ahern
@ 2021-02-02  4:01     ` Parav Pandit
  0 siblings, 0 replies; 19+ messages in thread
From: Parav Pandit @ 2021-02-02  4:01 UTC (permalink / raw)
  To: David Ahern, stephen, netdev


> From: David Ahern <dsahern@gmail.com>
> Sent: Tuesday, February 2, 2021 8:50 AM
> 
> On 2/1/21 2:35 PM, Parav Pandit wrote:
> > This patchset implements devlink port add, delete and function state
> > management commands.
> >
> > An example sequence for a PCI SF:
> >
> > Set the device in switchdev mode:
> > $ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
> >
> > View ports in switchdev mode:
> > $ devlink port show
> > pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical
> > port 0 splittable false
> >
> > Add a subfunction port for PCI PF 0 with sfnumber 88:
> > $ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
> > pci/0000:08: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
> >
> > Show a newly added port:
> > $ devlink port show pci/0000:06:00.0/32768
> > pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf
> controller 0 pfnum 0 sfnum 88 splittable false
> >   function:
> >     hw_addr 00:00:00:00:00:00 state inactive opstate detached
> >
> > Set the function state to active:
> > $ devlink port function set pci/0000:06:00.0/32768 hw_addr
> > 00:00:00:00:88:88 state active
> >
> > Show the port in JSON format:
> > $ devlink port show pci/0000:06:00.0/32768 -jp {
> >     "port": {
> >         "pci/0000:06:00.0/32768": {
> >             "type": "eth",
> >             "netdev": "ens2f0npf0sf88",
> >             "flavour": "pcisf",
> >             "controller": 0,
> >             "pfnum": 0,
> >             "sfnum": 88,
> >             "splittable": false,
> >             "function": {
> >                 "hw_addr": "00:00:00:00:88:88",
> >                 "state": "active",
> >                 "opstate": "attached"
> >             }
> >         }
> >     }
> > }
> >
> > Set the function state to active:
> > $ devlink port function set pci/0000:06:00.0/32768 state inactive
> >
> > Delete the port after use:
> > $ devlink port del pci/0000:06:00.0/32768
> >
> 
> applied to iproute2-next.
> 
> In the future, please split additions and changes to utility functions into a
> separate standalone patch.
Ok. Will do. I rebase and send v3 with the split utils functions addition into a standalone patch for vdpa tool series [1].
Thanks.
[1] https://lore.kernel.org/netdev/20210128184319.29174-1-parav@nvidia.com/


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2021-02-02  4:02 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-29 16:56 [PATCH iproute2-next 0/5] Support devlink port add delete Parav Pandit
2021-01-29 16:56 ` [PATCH iproute2-next 1/5] devlink: Update kernel headers Parav Pandit
2021-01-29 16:56 ` [PATCH iproute2-next 2/5] devlink: Introduce PCI SF port flavour and attribute Parav Pandit
2021-01-29 16:56 ` [PATCH iproute2-next 3/5] devlink: Supporting add and delete of devlink port Parav Pandit
2021-01-31 17:26   ` David Ahern
2021-02-01 20:42     ` Parav Pandit
2021-01-29 16:56 ` [PATCH iproute2-next 4/5] devlink: Support get port function state Parav Pandit
2021-01-29 16:56 ` [PATCH iproute2-next 5/5] devlink: Support set of " Parav Pandit
2021-01-31 17:30   ` David Ahern
2021-02-01 20:50     ` Parav Pandit
2021-02-01 21:35 ` [PATCH iproute2-next v2 0/6] Support devlink port add delete Parav Pandit
2021-02-01 21:35   ` [PATCH iproute2-next v2 1/6] devlink: Update kernel headers Parav Pandit
2021-02-01 21:35   ` [PATCH iproute2-next v2 2/6] devlink: Introduce and use string to number mapper Parav Pandit
2021-02-01 21:35   ` [PATCH iproute2-next v2 3/6] devlink: Introduce PCI SF port flavour and attribute Parav Pandit
2021-02-01 21:35   ` [PATCH iproute2-next v2 4/6] devlink: Supporting add and delete of devlink port Parav Pandit
2021-02-01 21:35   ` [PATCH iproute2-next v2 5/6] devlink: Support get port function state Parav Pandit
2021-02-01 21:35   ` [PATCH iproute2-next v2 6/6] devlink: Support set of " Parav Pandit
2021-02-02  3:20   ` [PATCH iproute2-next v2 0/6] Support devlink port add delete David Ahern
2021-02-02  4:01     ` Parav Pandit

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.