diff mbox series

[iproute2-next,4/4] devlink: print nested devlink handle for devlink dev

Message ID 20230918105416.1107260-5-jiri@resnulli.us (mailing list archive)
State Superseded
Delegated to: David Ahern
Headers show
Series expose devlink instances relationships | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch

Commit Message

Jiri Pirko Sept. 18, 2023, 10:54 a.m. UTC
From: Jiri Pirko <jiri@nvidia.com>

Devlink dev may contain one or more nested devlink instances. If one is
present, print it out simple. If more are present (there is no
such case in current kernel, but may be in theory in the future),
print them in array.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 devlink/devlink.c | 45 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 41 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/devlink/devlink.c b/devlink/devlink.c
index 8ea7b268c63c..a387da0f4995 100644
--- a/devlink/devlink.c
+++ b/devlink/devlink.c
@@ -3889,13 +3889,50 @@  static void pr_out_reload_data(struct dl *dl, struct nlattr **tb)
 	pr_out_object_end(dl);
 }
 
+static void pr_out_dev_nested(struct dl *dl, const struct nlmsghdr *nlh)
+{
+	struct nlattr *attr, *attr2;
+	int count = 0;
+
+	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
+		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_NESTED_DEVLINK) {
+			count++;
+			attr2 = attr;
+		}
+	}
+	if (!count) {
+		return;
+	} else if (count == 1) {
+		pr_out_nested_handle(attr2);
+		return;
+	}
+
+	pr_out_array_start(dl, "nested_devlinks");
+	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
+		if (mnl_attr_get_type(attr) == DEVLINK_ATTR_NESTED_DEVLINK) {
+			check_indent_newline(dl);
+			if (dl->json_output)
+				open_json_object(NULL);
+			check_indent_newline(dl);
+			pr_out_nested_handle(attr);
+			if (dl->json_output)
+				close_json_object();
+			else
+				__pr_out_newline();
+		}
+	}
+	pr_out_array_end(dl);
+}
 
-static void pr_out_dev(struct dl *dl, struct nlattr **tb)
+static void pr_out_dev(struct dl *dl, const struct nlmsghdr *nlh,
+		       struct nlattr **tb)
 {
 	if ((tb[DEVLINK_ATTR_RELOAD_FAILED] && mnl_attr_get_u8(tb[DEVLINK_ATTR_RELOAD_FAILED])) ||
-	    (tb[DEVLINK_ATTR_DEV_STATS] && dl->stats)) {
+	    (tb[DEVLINK_ATTR_DEV_STATS] && dl->stats) ||
+	     tb[DEVLINK_ATTR_NESTED_DEVLINK]) {
 		__pr_out_handle_start(dl, tb, true, false);
 		pr_out_reload_data(dl, tb);
+		pr_out_dev_nested(dl, nlh);
 		pr_out_handle_end(dl);
 	} else {
 		pr_out_handle(dl, tb);
@@ -3912,7 +3949,7 @@  static int cmd_dev_show_cb(const struct nlmsghdr *nlh, void *data)
 	if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME])
 		return MNL_CB_ERROR;
 
-	pr_out_dev(dl, tb);
+	pr_out_dev(dl, nlh, tb);
 	return MNL_CB_OK;
 }
 
@@ -6828,7 +6865,7 @@  static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data)
 			return MNL_CB_ERROR;
 		pr_out_mon_header(genl->cmd);
 		dl->stats = true;
-		pr_out_dev(dl, tb);
+		pr_out_dev(dl, nlh, tb);
 		pr_out_mon_footer();
 		break;
 	case DEVLINK_CMD_PORT_GET: /* fall through */