All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 iproute2 0/7] RDMAtool
@ 2017-08-15 13:00 Leon Romanovsky
  2017-08-15 13:00 ` [PATCH v4 iproute2 1/7] rdma: Add basic infrastructure for RDMA tool Leon Romanovsky
                   ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 13:00 UTC (permalink / raw)
  To: Doug Ledford, Stephen Hemminger
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, Leon Romanovsky,
	Dennis Dalessandro, Jason Gunthorpe, Jiri Pirko, Ariel Almog,
	Linux Netdev

Hi,

This is fourth revision of series implementing the RDAMtool -  the tool
to configure RDMA devices. The initial proposal was sent as RFC [1] and
was based on sysfs entries as POC.

The current series was rewritten completely to work with RDMA netlinks as
a source of user<->kernel communications. In order to achieve that, the
RDMA netlinks were extensively refactored and modernized [2, 3, 4 and 5].

The Doug's for-next tag includes most of the needed patches for this
tool and I posted to the ML the last batch [6] which exports various
device and port properties.

The following is an example of various runs on my machine with 5 devices
(4 in IB mode and one in Ethernet mode).

### Without parameters
$ rdma
Usage: rdma [ OPTIONS ] OBJECT { COMMAND | help }
where  OBJECT := { dev | link | help }
       OPTIONS := { -V[ersion] | -d[etails] | -j[son] | -p[retty]}

### With unspecified device name
$ rdma dev
1: mlx5_0: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:3457 sys_image_guid 5254:00c0:fe12:3457
2: mlx5_1: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:3458 sys_image_guid 5254:00c0:fe12:3458
3: mlx5_2: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:3459 sys_image_guid 5254:00c0:fe12:3459
4: mlx5_3: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:345a sys_image_guid 5254:00c0:fe12:345a
5: mlx5_4: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:345b sys_image_guid 5254:00c0:fe12:345b

### Detailed mode
$ rdma -d dev
1: mlx5_0: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:3457 sys_image_guid 5254:00c0:fe12:3457
    caps: <BAD_PKEY_CNTR, BAD_QKEY_CNTR, CHANGE_PHY_POR, PORT_ACTIVE_EVENT, SYS_IMAGE_GUID, RC_RNR_NAK_GEN, MEM_WINDOW, UD_IP_CSUM, UD_TSO, XRC, MEM_MGT_EXTENSIONS, BLOCK_MULTICAST_LOOPBACK, MEM_WINDOW_TYPE_2B, RAW_IP_CSUM, MANAGED_FLOW_STEERING, RESIZE_MAX_WR>
2: mlx5_1: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:3458 sys_image_guid 5254:00c0:fe12:3458
    caps: <BAD_PKEY_CNTR, BAD_QKEY_CNTR, CHANGE_PHY_POR, PORT_ACTIVE_EVENT, SYS_IMAGE_GUID, RC_RNR_NAK_GEN, MEM_WINDOW, UD_IP_CSUM, UD_TSO, XRC, MEM_MGT_EXTENSIONS, BLOCK_MULTICAST_LOOPBACK, MEM_WINDOW_TYPE_2B, RAW_IP_CSUM, MANAGED_FLOW_STEERING, RESIZE_MAX_WR>
3: mlx5_2: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:3459 sys_image_guid 5254:00c0:fe12:3459
    caps: <BAD_PKEY_CNTR, BAD_QKEY_CNTR, CHANGE_PHY_POR, PORT_ACTIVE_EVENT, SYS_IMAGE_GUID, RC_RNR_NAK_GEN, MEM_WINDOW, UD_IP_CSUM, UD_TSO, XRC, MEM_MGT_EXTENSIONS, BLOCK_MULTICAST_LOOPBACK, MEM_WINDOW_TYPE_2B, RAW_IP_CSUM, MANAGED_FLOW_STEERING, RESIZE_MAX_WR>
4: mlx5_3: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:345a sys_image_guid 5254:00c0:fe12:345a
    caps: <BAD_PKEY_CNTR, BAD_QKEY_CNTR, CHANGE_PHY_POR, PORT_ACTIVE_EVENT, SYS_IMAGE_GUID, RC_RNR_NAK_GEN, MEM_WINDOW, UD_IP_CSUM, UD_TSO, XRC, MEM_MGT_EXTENSIONS, BLOCK_MULTICAST_LOOPBACK, MEM_WINDOW_TYPE_2B, RAW_IP_CSUM, MANAGED_FLOW_STEERING, RESIZE_MAX_WR>
5: mlx5_4: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:345b sys_image_guid 5254:00c0:fe12:345b
    caps: <BAD_PKEY_CNTR, BAD_QKEY_CNTR, CHANGE_PHY_POR, PORT_ACTIVE_EVENT, SYS_IMAGE_GUID, RC_RNR_NAK_GEN, MEM_WINDOW, UD_IP_CSUM, UD_TSO, XRC, MEM_MGT_EXTENSIONS, BLOCK_MULTICAST_LOOPBACK, MEM_WINDOW_TYPE_2B, RAW_IP_CSUM, MANAGED_FLOW_STEERING, RESIZE_MAX_WR>

### Specific device
$ rdma dev show mlx5_4
5: mlx5_4: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:345b sys_image_guid 5254:00c0:fe12:345b

### Specific device in detailed mode
$ rdma dev show mlx5_4 -d
5: mlx5_4: node_type ca fw 2.8.9999 node_guid 5254:00c0:fe12:345b sys_image_guid 5254:00c0:fe12:345b
    caps: <BAD_PKEY_CNTR, BAD_QKEY_CNTR, CHANGE_PHY_POR, PORT_ACTIVE_EVENT, SYS_IMAGE_GUID, RC_RNR_NAK_GEN, MEM_WINDOW, UD_IP_CSUM, UD_TSO, XRC, MEM_MGT_EXTENSIONS, BLOCK_MULTICAST_LOOPBACK, MEM_WINDOW_TYPE_2B, RAW_IP_CSUM, MANAGED_FLOW_STEERING, RESIZE_MAX_WR>

### Unknown command (caps)
$ rdma dev show mlx5_4 caps
Unknown parameter 'caps'.

### Link properties without device name
$ rdma link
1/1: mlx5_0/1: subnet_prefix fe80:0000:0000:0000 lid 13399 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP
2/1: mlx5_1/1: subnet_prefix fe80:0000:0000:0000 lid 13400 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP
3/1: mlx5_2/1: subnet_prefix fe80:0000:0000:0000 lid 13401 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP
4/1: mlx5_3/1: state DOWN physical_state DISABLED
5/1: mlx5_4/1: subnet_prefix fe80:0000:0000:0000 lid 13403 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP

### Link properties in detailed mode
$ rdma link -d
1/1: mlx5_0/1: subnet_prefix fe80:0000:0000:0000 lid 13399 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP
    caps: <AUTO_MIGR>
2/1: mlx5_1/1: subnet_prefix fe80:0000:0000:0000 lid 13400 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP
    caps: <AUTO_MIGR>
3/1: mlx5_2/1: subnet_prefix fe80:0000:0000:0000 lid 13401 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP
    caps: <AUTO_MIGR>
4/1: mlx5_3/1: state DOWN physical_state DISABLED
    caps: <CM, IP_BASED_GIDS>
5/1: mlx5_4/1: subnet_prefix fe80:0000:0000:0000 lid 13403 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP
    caps: <AUTO_MIGR>

### All links for specific device
$ rdma link show mlx5_3
1/1: mlx5_0/1: subnet_prefix fe80:0000:0000:0000 lid 13399 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP

### Detailed link properties for specific device
$ rdma link -d show mlx5_3
1/1: mlx5_0/1: subnet_prefix fe80:0000:0000:0000 lid 13399 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP
    caps: <AUTO_MIGR>

### Specific port for specific device
$ rdma link show mlx5_4/1
1/1: mlx5_0/1: subnet_prefix fe80:0000:0000:0000 lid 13399 sm_lid 49151 lmc 0 state ACTIVE physical_state LINK_UP

### Unknown parameter
$ rdma link show mlx5_4/1 caps
Unknown parameter 'caps'.

Thanks

Changelog:
v2->v4:
 * Rebased on latest net-next branch
 * Added JSON output -j (json) and -p (pretty output)
 * Exported and reused kernel UAPIs and defines instead of hard coded
   version.
v2->v3:
 * Removed MAX()
 * Reduced scope of rd_argv_match
 * Removed return from rdma_free_devmap
 * Added extra break at rdma_send_msg
v1->v2:
 * Squashed multiple (and similar) patches to be one patch for dev object
   and one patch for link object.
 * Removed port_map struct
 * Removed global netlink dump during initialization, it removed the need to store
   the intermediate variables and reuse ability of netlink to signal if variable
   exists or doesn't.
 * Added "-d" --details option and put all CAPs under it.

v0->v1:
 * Moved hunk with changes in man/Makefile from first patch to the last patch
 * Removed the "unknown command" from the examples in commit messages
 * Removed special "caps" parsing command and put it to be part of general "show" command
 * Changed parsed capability format to be similar to iproute2 suite
 * Added FW version as an output of show command.
 * Added forgotten CAP_FLAGS to the nla_policy list
RFC->v0:
 * Removed everything that is not implemented yet.
 * Abandoned sysfs interfaces in favor of netlink.

Available in the "topic/rdmatool-netlink-v4" topic branch of this git repo:
git://git.kernel.org/pub/scm/linux/kernel/git/leon/iproute2.git

Or for browsing:
https://git.kernel.org/cgit/linux/kernel/git/leon/iproute2.git/log/?h=topic/rdmatool-netlink-v4

Thanks

[1] https://www.spinics.net/lists/linux-rdma/msg49575.html
[2] https://patchwork.kernel.org/patch/9752865/
[3] https://www.spinics.net/lists/linux-rdma/msg50827.html
[4] https://www.spinics.net/lists/linux-rdma/msg51210.html
[5] https://patchwork.kernel.org/patch/9811729/ and https://patchwork.kernel.org/patch/9811731/]
[6] http://marc.info/?l=linux-rdma&m=150278847820844&w=2

Cc: Doug Ledford <dledford-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Dennis Dalessandro <dennis.dalessandro-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Cc: Jiri Pirko <jiri-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Cc: Ariel Almog <ariela-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Cc: Linux RDMA <linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Cc: Linux Netdev <netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>

Leon Romanovsky (7):
  rdma: Add basic infrastructure for RDMA tool
  rdma: Add dev object
  rdma: Add link object
  rdma: Add initial manual for the tool
  rdma: Add json and pretty outputs
  rdma: Implement json output for dev object
  rdma: Add json output to link object

 Makefile             |   2 +-
 man/man8/rdma-dev.8  |  55 +++++++++
 man/man8/rdma-link.8 |  55 +++++++++
 man/man8/rdma.8      | 102 ++++++++++++++++
 rdma/.gitignore      |   1 +
 rdma/Makefile        |  22 ++++
 rdma/dev.c           | 281 ++++++++++++++++++++++++++++++++++++++++++
 rdma/link.c          | 340 +++++++++++++++++++++++++++++++++++++++++++++++++++
 rdma/rdma.c          | 143 ++++++++++++++++++++++
 rdma/rdma.h          |  90 ++++++++++++++
 rdma/utils.c         | 266 ++++++++++++++++++++++++++++++++++++++++
 11 files changed, 1356 insertions(+), 1 deletion(-)
 create mode 100644 man/man8/rdma-dev.8
 create mode 100644 man/man8/rdma-link.8
 create mode 100644 man/man8/rdma.8
 create mode 100644 rdma/.gitignore
 create mode 100644 rdma/Makefile
 create mode 100644 rdma/dev.c
 create mode 100644 rdma/link.c
 create mode 100644 rdma/rdma.c
 create mode 100644 rdma/rdma.h
 create mode 100644 rdma/utils.c

--
2.14.0

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v4 iproute2 1/7] rdma: Add basic infrastructure for RDMA tool
  2017-08-15 13:00 [PATCH v4 iproute2 0/7] RDMAtool Leon Romanovsky
@ 2017-08-15 13:00 ` Leon Romanovsky
  2017-08-15 23:54   ` Stephen Hemminger
       [not found] ` <20170815130020.29509-1-leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 13:00 UTC (permalink / raw)
  To: Doug Ledford, Stephen Hemminger
  Cc: linux-rdma, Leon Romanovsky, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

RDMA devices are cross-functional devices from one side,
but very tailored for the specific markets from another.

Such diversity caused to spread of RDMA related configuration
across various tools, e.g. devlink, ip, ethtool, ib specific and
vendor specific solutions.

This patch adds ability to fill device and port information
by reading RDMA netlink.

Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 Makefile        |   2 +-
 rdma/.gitignore |   1 +
 rdma/Makefile   |  22 ++++++
 rdma/rdma.c     | 116 ++++++++++++++++++++++++++++++
 rdma/rdma.h     |  74 +++++++++++++++++++
 rdma/utils.c    | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 431 insertions(+), 1 deletion(-)
 create mode 100644 rdma/.gitignore
 create mode 100644 rdma/Makefile
 create mode 100644 rdma/rdma.c
 create mode 100644 rdma/rdma.h
 create mode 100644 rdma/utils.c

diff --git a/Makefile b/Makefile
index 1f88f7f5..dbb4a4af 100644
--- a/Makefile
+++ b/Makefile
@@ -49,7 +49,7 @@ WFLAGS += -Wmissing-declarations -Wold-style-definition -Wformat=2
 CFLAGS := $(WFLAGS) $(CCOPTS) -I../include $(DEFINES) $(CFLAGS)
 YACCFLAGS = -d -t -v
 
-SUBDIRS=lib ip tc bridge misc netem genl tipc devlink man
+SUBDIRS=lib ip tc bridge misc netem genl tipc devlink rdma man
 
 LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a
 LDLIBS += $(LIBNETLINK)
diff --git a/rdma/.gitignore b/rdma/.gitignore
new file mode 100644
index 00000000..51fb172b
--- /dev/null
+++ b/rdma/.gitignore
@@ -0,0 +1 @@
+rdma
diff --git a/rdma/Makefile b/rdma/Makefile
new file mode 100644
index 00000000..64da2142
--- /dev/null
+++ b/rdma/Makefile
@@ -0,0 +1,22 @@
+include ../Config
+
+ifeq ($(HAVE_MNL),y)
+
+RDMA_OBJ = rdma.o utils.o
+
+TARGETS=rdma
+CFLAGS += $(shell $(PKG_CONFIG) libmnl --cflags)
+LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
+
+endif
+
+all:	$(TARGETS) $(LIBS)
+
+rdma:	$(RDMA_OBJ) $(LIBS)
+	$(QUIET_LINK)$(CC) $^ $(LDFLAGS) $(LDLIBS) -o $@
+
+install: all
+	install -m 0755 $(TARGETS) $(DESTDIR)$(SBINDIR)
+
+clean:
+	rm -f $(RDMA_OBJ) $(TARGETS)
diff --git a/rdma/rdma.c b/rdma/rdma.c
new file mode 100644
index 00000000..d850e396
--- /dev/null
+++ b/rdma/rdma.c
@@ -0,0 +1,116 @@
+/*
+ * rdma.c	RDMA tool
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:     Leon Romanovsky <leonro@mellanox.com>
+ */
+
+#include "rdma.h"
+#include "SNAPSHOT.h"
+
+static void help(char *name)
+{
+	pr_out("Usage: %s [ OPTIONS ] OBJECT { COMMAND | help }\n"
+	       "where  OBJECT := { help }\n"
+	       "       OPTIONS := { -V[ersion] | -d[etails]}\n", name);
+}
+
+static int cmd_help(struct rd *rd)
+{
+	help(rd->filename);
+	return 0;
+}
+
+static int rd_cmd(struct rd *rd)
+{
+	const struct rd_cmd cmds[] = {
+		{ NULL,		cmd_help },
+		{ "help",	cmd_help },
+		{ 0 }
+	};
+
+	return rd_exec_cmd(rd, cmds, "object");
+}
+
+static int rd_init(struct rd *rd, int argc, char **argv, char *filename)
+{
+	uint32_t seq;
+	int ret;
+
+	rd->filename = filename;
+	rd->argc = argc;
+	rd->argv = argv;
+	INIT_LIST_HEAD(&rd->dev_map_list);
+	rd->buff = malloc(MNL_SOCKET_BUFFER_SIZE);
+	if (!rd->buff)
+		return -ENOMEM;
+
+	rd_prepare_msg(rd, RDMA_NLDEV_CMD_GET,
+		       &seq, (NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP));
+	ret = rd_send_msg(rd);
+	if (ret)
+		return ret;
+
+	return rd_recv_msg(rd, rd_dev_init_cb, rd, seq);
+}
+
+static void rd_free(struct rd *rd)
+{
+	free(rd->buff);
+	rd_free_devmap(rd);
+}
+
+int main(int argc, char **argv)
+{
+	static const struct option long_options[] = {
+		{ "version",		no_argument,		NULL, 'V' },
+		{ "help",		no_argument,		NULL, 'h' },
+		{ "details",		no_argument,		NULL, 'd' },
+		{ NULL, 0, NULL, 0 }
+	};
+	bool show_details = false;
+	char *filename;
+	struct rd rd;
+	int opt;
+	int err;
+
+	filename = basename(argv[0]);
+
+	while ((opt = getopt_long(argc, argv, "Vhd",
+				  long_options, NULL)) >= 0) {
+		switch (opt) {
+		case 'V':
+			printf("%s utility, iproute2-ss%s\n",
+			       filename, SNAPSHOT);
+			return EXIT_SUCCESS;
+		case 'd':
+			show_details = true;
+			break;
+		case 'h':
+			help(filename);
+			return EXIT_SUCCESS;
+		default:
+			pr_err("Unknown option.\n");
+			help(filename);
+			return EXIT_FAILURE;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	err = rd_init(&rd, argc, argv, filename);
+	if (err)
+		goto out;
+
+	rd.show_details = show_details;
+	err = rd_cmd(&rd);
+out:
+	/* Always cleanup */
+	rd_free(&rd);
+	return err ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/rdma/rdma.h b/rdma/rdma.h
new file mode 100644
index 00000000..361888b8
--- /dev/null
+++ b/rdma/rdma.h
@@ -0,0 +1,74 @@
+/*
+ * rdma.c	RDMA tool
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:     Leon Romanovsky <leonro@mellanox.com>
+ */
+#ifndef _RDMA_TOOL_H_
+#define _RDMA_TOOL_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <libmnl/libmnl.h>
+#include <rdma/rdma_netlink.h>
+#include <time.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/rdma_netlink.h>
+#include <rdma/rdma.h>
+
+#include "list.h"
+
+#define pr_err(args...) fprintf(stderr, ##args)
+#define pr_out(args...) fprintf(stdout, ##args)
+
+struct dev_map {
+	struct list_head list;
+	char *dev_name;
+	uint32_t num_ports;
+	uint32_t idx;
+};
+
+struct rd {
+	int argc;
+	char **argv;
+	char *filename;
+	bool show_details;
+	struct list_head dev_map_list;
+	struct mnl_socket *nl;
+	struct nlmsghdr *nlh;
+	char *buff;
+};
+
+struct rd_cmd {
+	const char *cmd;
+	int (*func)(struct rd *rd);
+};
+
+/*
+ * Parser interface
+ */
+bool rd_no_arg(struct rd *rd);
+void rd_arg_inc(struct rd *rd);
+
+int rd_exec_cmd(struct rd *rd, const struct rd_cmd *c, const char *str);
+
+/*
+ * Device manipulation
+ */
+void rd_free_devmap(struct rd *rd);
+
+/*
+ * Netlink
+ */
+int rd_send_msg(struct rd *rd);
+int rd_recv_msg(struct rd *rd, mnl_cb_t callback, void *data, uint32_t seq);
+void rd_prepare_msg(struct rd *rd, uint32_t cmd, uint32_t *seq, uint16_t flags);
+int rd_dev_init_cb(const struct nlmsghdr *nlh, void *data);
+int rd_attr_cb(const struct nlattr *attr, void *data);
+#endif /* _RDMA_TOOL_H_ */
diff --git a/rdma/utils.c b/rdma/utils.c
new file mode 100644
index 00000000..9bd7418f
--- /dev/null
+++ b/rdma/utils.c
@@ -0,0 +1,217 @@
+/*
+ * utils.c	RDMA tool
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:     Leon Romanovsky <leonro@mellanox.com>
+ */
+
+#include "rdma.h"
+
+static int rd_argc(struct rd *rd)
+{
+	return rd->argc;
+}
+
+static char *rd_argv(struct rd *rd)
+{
+	if (!rd_argc(rd))
+		return NULL;
+	return *rd->argv;
+}
+
+static int strcmpx(const char *str1, const char *str2)
+{
+	if (strlen(str1) > strlen(str2))
+		return -1;
+	return strncmp(str1, str2, strlen(str1));
+}
+
+static bool rd_argv_match(struct rd *rd, const char *pattern)
+{
+	if (!rd_argc(rd))
+		return false;
+	return strcmpx(rd_argv(rd), pattern) == 0;
+}
+
+void rd_arg_inc(struct rd *rd)
+{
+	if (!rd_argc(rd))
+		return;
+	rd->argc--;
+	rd->argv++;
+}
+
+bool rd_no_arg(struct rd *rd)
+{
+	return rd_argc(rd) == 0;
+}
+
+static struct dev_map *dev_map_alloc(const char *dev_name)
+{
+	struct dev_map *dev_map;
+
+	dev_map = calloc(1, sizeof(*dev_map));
+	if (!dev_map)
+		return NULL;
+	dev_map->dev_name = strdup(dev_name);
+
+	return dev_map;
+}
+
+static void dev_map_free(struct dev_map *dev_map)
+{
+	if (!dev_map)
+		return;
+
+	free(dev_map->dev_name);
+	free(dev_map);
+}
+
+static void dev_map_cleanup(struct rd *rd)
+{
+	struct dev_map *dev_map, *tmp;
+
+	list_for_each_entry_safe(dev_map, tmp,
+				 &rd->dev_map_list, list) {
+		list_del(&dev_map->list);
+		dev_map_free(dev_map);
+	}
+}
+
+static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
+	[RDMA_NLDEV_ATTR_DEV_NAME] = MNL_TYPE_NUL_STRING,
+	[RDMA_NLDEV_ATTR_PORT_INDEX] = MNL_TYPE_U32,
+};
+
+int rd_attr_cb(const struct nlattr *attr, void *data)
+{
+	const struct nlattr **tb = data;
+	int type;
+
+	if (mnl_attr_type_valid(attr, RDMA_NLDEV_ATTR_MAX) < 0)
+		return MNL_CB_ERROR;
+
+	type = mnl_attr_get_type(attr);
+
+	if (mnl_attr_validate(attr, nldev_policy[type]) < 0)
+		return MNL_CB_ERROR;
+
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+int rd_dev_init_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
+	struct dev_map *dev_map;
+	struct rd *rd = data;
+	const char *dev_name;
+
+	mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
+	if (!tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
+		return MNL_CB_ERROR;
+	if (!tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {
+		pr_err("This tool doesn't support switches yet\n");
+		return MNL_CB_ERROR;
+	}
+
+	dev_name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
+
+	dev_map = dev_map_alloc(dev_name);
+	if (!dev_map)
+		/* The main function will cleanup the allocations */
+		return MNL_CB_ERROR;
+	list_add_tail(&dev_map->list, &rd->dev_map_list);
+
+	dev_map->num_ports = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
+	dev_map->idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
+	return MNL_CB_OK;
+}
+
+void rd_free_devmap(struct rd *rd)
+{
+	if (!rd)
+		return;
+	dev_map_cleanup(rd);
+}
+
+int rd_exec_cmd(struct rd *rd, const struct rd_cmd *cmds, const char *str)
+{
+	const struct rd_cmd *c;
+
+	/* First argument in objs table is default variant */
+	if (rd_no_arg(rd))
+		return cmds->func(rd);
+
+	for (c = cmds + 1; c->cmd; ++c) {
+		if (rd_argv_match(rd, c->cmd)) {
+			/* Move to next argument */
+			rd_arg_inc(rd);
+			return c->func(rd);
+		}
+	}
+
+	pr_err("Unknown %s '%s'.\n", str, rd_argv(rd));
+	return 0;
+}
+
+void rd_prepare_msg(struct rd *rd, uint32_t cmd, uint32_t *seq, uint16_t flags)
+{
+	*seq = time(NULL);
+
+	rd->nlh = mnl_nlmsg_put_header(rd->buff);
+	rd->nlh->nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, cmd);
+	rd->nlh->nlmsg_seq = *seq;
+	rd->nlh->nlmsg_flags = flags;
+}
+
+int rd_send_msg(struct rd *rd)
+{
+	int ret;
+
+	rd->nl = mnl_socket_open(NETLINK_RDMA);
+	if (!rd->nl) {
+		pr_err("Failed to open NETLINK_RDMA socket\n");
+		return -ENODEV;
+	}
+
+	ret = mnl_socket_bind(rd->nl, 0, MNL_SOCKET_AUTOPID);
+	if (ret < 0) {
+		pr_err("Failed to bind socket with err %d\n", ret);
+		goto err;
+	}
+
+	ret = mnl_socket_sendto(rd->nl, rd->nlh, rd->nlh->nlmsg_len);
+	if (ret < 0) {
+		pr_err("Failed to send to socket with err %d\n", ret);
+		goto err;
+	}
+	return 0;
+
+err:
+	mnl_socket_close(rd->nl);
+	return ret;
+}
+
+int rd_recv_msg(struct rd *rd, mnl_cb_t callback, void *data, unsigned int seq)
+{
+	int ret;
+	unsigned int portid;
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+
+	portid = mnl_socket_get_portid(rd->nl);
+	do {
+		ret = mnl_socket_recvfrom(rd->nl, buf, sizeof(buf));
+		if (ret <= 0)
+			break;
+
+		ret = mnl_cb_run(buf, ret, seq, portid, callback, data);
+	} while (ret > 0);
+
+	mnl_socket_close(rd->nl);
+	return ret;
+}
-- 
2.14.0

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

* [PATCH v4 iproute2 2/7] rdma: Add dev object
       [not found] ` <20170815130020.29509-1-leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
@ 2017-08-15 13:00   ` Leon Romanovsky
  2017-08-15 16:12     ` Stephen Hemminger
  2017-08-15 13:00   ` [PATCH v4 iproute2 4/7] rdma: Add initial manual for the tool Leon Romanovsky
  1 sibling, 1 reply; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 13:00 UTC (permalink / raw)
  To: Doug Ledford, Stephen Hemminger
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, Leon Romanovsky,
	Dennis Dalessandro, Jason Gunthorpe, Jiri Pirko, Ariel Almog,
	Linux Netdev

Device (dev) object represents struct ib_device to the user space.

Device properties:
 * Device capabilities
 * FW version to the device output
 * node_guid and sys_image_guid
 * node_type

Signed-off-by: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 rdma/Makefile |   2 +-
 rdma/dev.c    | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 rdma/rdma.c   |   3 +-
 rdma/rdma.h   |  13 ++++
 rdma/utils.c  |  54 +++++++++++++-
 5 files changed, 296 insertions(+), 3 deletions(-)
 create mode 100644 rdma/dev.c

diff --git a/rdma/Makefile b/rdma/Makefile
index 64da2142..123d7ac5 100644
--- a/rdma/Makefile
+++ b/rdma/Makefile
@@ -2,7 +2,7 @@ include ../Config
 
 ifeq ($(HAVE_MNL),y)
 
-RDMA_OBJ = rdma.o utils.o
+RDMA_OBJ = rdma.o utils.o dev.o
 
 TARGETS=rdma
 CFLAGS += $(shell $(PKG_CONFIG) libmnl --cflags)
diff --git a/rdma/dev.c b/rdma/dev.c
new file mode 100644
index 00000000..e984f805
--- /dev/null
+++ b/rdma/dev.c
@@ -0,0 +1,227 @@
+/*
+ * dev.c	RDMA tool
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:     Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
+ */
+
+#include "rdma.h"
+
+static int dev_help(struct rd *rd)
+{
+	pr_out("Usage: %s dev show [DEV]\n", rd->filename);
+	return 0;
+}
+
+static const char *dev_caps_to_str(uint32_t idx)
+{
+	uint64_t cap = 1 << idx;
+
+	switch (cap) {
+	case RDMA_DEV_RESIZE_MAX_WR: return "RESIZE_MAX_WR";
+	case RDMA_DEV_BAD_PKEY_CNTR: return "BAD_PKEY_CNTR";
+	case RDMA_DEV_BAD_QKEY_CNTR: return "BAD_QKEY_CNTR";
+	case RDMA_DEV_RAW_MULTI: return "RAW_MULTI";
+	case RDMA_DEV_AUTO_PATH_MIG: return "AUTO_PATH_MIG";
+	case RDMA_DEV_CHANGE_PHY_PORT: return "CHANGE_PHY_POR";
+	case RDMA_DEV_UD_AV_PORT_ENFORCE: return "UD_AV_PORT_ENFORCE";
+	case RDMA_DEV_CURR_QP_STATE_MOD: return "CURR_QP_STATE_MOD";
+	case RDMA_DEV_SHUTDOWN_PORT: return "SHUTDOWN_PORT";
+	case RDMA_DEV_INIT_TYPE: return "INIT_TYPE";
+	case RDMA_DEV_PORT_ACTIVE_EVENT: return "PORT_ACTIVE_EVENT";
+	case RDMA_DEV_SYS_IMAGE_GUID: return "SYS_IMAGE_GUID";
+	case RDMA_DEV_RC_RNR_NAK_GEN: return "RC_RNR_NAK_GEN";
+	case RDMA_DEV_SRQ_RESIZE: return "SRQ_RESIZE";
+	case RDMA_DEV_N_NOTIFY_CQ: return "N_NOTIFY_CQ";
+	case RDMA_DEV_LOCAL_DMA_LKEY: return "LOCAL_DMA_LKEY";
+	case RDMA_DEV_MEM_WINDOW: return "MEM_WINDOW";
+	case RDMA_DEV_UD_IP_CSUM: return "UD_IP_CSUM";
+	case RDMA_DEV_UD_TSO: return "UD_TSO";
+	case RDMA_DEV_XRC: return "XRC";
+	case RDMA_DEV_MEM_MGT_EXTENSIONS: return "MEM_MGT_EXTENSIONS";
+	case RDMA_DEV_BLOCK_MULTICAST_LOOPBACK:
+					return "BLOCK_MULTICAST_LOOPBACK";
+	case RDMA_DEV_MEM_WINDOW_TYPE_2A: return "MEM_WINDOW_TYPE_2A";
+	case RDMA_DEV_MEM_WINDOW_TYPE_2B: return "MEM_WINDOW_TYPE_2B";
+	case RDMA_DEV_RC_IP_CSUM: return "RC_IP_CSUM";
+	case RDMA_DEV_RAW_IP_CSUM: return "RAW_IP_CSUM";
+	case RDMA_DEV_CROSS_CHANNEL: return "CROSS_CHANNEL";
+	case RDMA_DEV_MANAGED_FLOW_STEERING: return "MANAGED_FLOW_STEERING";
+	case RDMA_DEV_SIGNATURE_HANDOVER: return "SIGNATURE_HANDOVER";
+	case RDMA_DEV_ON_DEMAND_PAGING: return "ON_DEMAND_PAGING";
+	case RDMA_DEV_SG_GAPS_REG: return "SG_GAPS_REG";
+	case RDMA_DEV_VIRTUAL_FUNCTION: return "VIRTUAL_FUNCTION";
+	case RDMA_DEV_RAW_SCATTER_FCS: return "RAW_SCATTER_FCS";
+	case RDMA_DEV_RDMA_NETDEV_OPA_VNIC: return "RDMA_NETDEV_OPA_VNIC";
+	default: return "UNKNOWN";
+	}
+}
+
+static void dev_print_caps(struct nlattr **tb)
+{
+	uint64_t caps;
+	uint32_t idx;
+
+	if (!tb[RDMA_NLDEV_ATTR_CAP_FLAGS])
+		return;
+
+	caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
+
+	pr_out("\n    caps: <");
+	for (idx = 0; caps; idx++) {
+		if (caps & 0x1) {
+			pr_out("%s", dev_caps_to_str(idx));
+			if (caps >> 0x1)
+				pr_out(", ");
+		}
+		caps >>= 0x1;
+	}
+
+	pr_out(">");
+}
+
+static void dev_print_fw(struct nlattr **tb)
+{
+	if (!tb[RDMA_NLDEV_ATTR_FW_VERSION])
+		return;
+
+	pr_out("fw %s ",
+	       mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION]));
+}
+
+static void dev_print_node_guid(struct nlattr **tb)
+{
+	uint64_t node_guid;
+
+	if (!tb[RDMA_NLDEV_ATTR_NODE_GUID])
+		return;
+
+	node_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_NODE_GUID]);
+	rd_print_u64("node_guid", node_guid);
+}
+
+static void dev_print_sys_image_guid(struct nlattr **tb)
+{
+	uint64_t sys_image_guid;
+
+	if (!tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID])
+		return;
+
+	sys_image_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID]);
+	rd_print_u64("sys_image_guid", sys_image_guid);
+}
+
+static const char *node_type_to_str(uint8_t node_type)
+{
+	switch (node_type) {
+	case RDMA_NODE_IB_CA: return "ca";
+	case RDMA_NODE_IB_SWITCH: return "switch";
+	case RDMA_NODE_IB_ROUTER: return "router";
+	case RDMA_NODE_RNIC: return "rnic";
+	case RDMA_NODE_USNIC: return "usnic";
+	case RDMA_NODE_USNIC_UDP: return "usnic_dp";
+	default: return "unknown";
+	}
+}
+
+static void dev_print_node_type(struct nlattr **tb)
+{
+	uint8_t node_type;
+
+	if (!tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE])
+		return;
+
+	node_type = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE]);
+	pr_out("node_type %s ", node_type_to_str(node_type));
+}
+
+static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
+	struct rd *rd = data;
+
+	mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
+	if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
+		return MNL_CB_ERROR;
+
+	pr_out("%u: %s: ",
+	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]),
+	       mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]));
+	dev_print_node_type(tb);
+	dev_print_fw(tb);
+	dev_print_node_guid(tb);
+	dev_print_sys_image_guid(tb);
+	if (rd->show_details)
+		dev_print_caps(tb);
+
+	pr_out("\n");
+	return MNL_CB_OK;
+}
+
+static int dev_no_args(struct rd *rd)
+{
+	uint32_t seq;
+	int ret;
+
+	rd_prepare_msg(rd, RDMA_NLDEV_CMD_GET,
+		       &seq, (NLM_F_REQUEST | NLM_F_ACK));
+	mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
+	ret = rd_send_msg(rd);
+	if (ret)
+		return ret;
+
+	return rd_recv_msg(rd, dev_parse_cb, rd, seq);
+}
+
+static int dev_one_show(struct rd *rd)
+{
+	const struct rd_cmd cmds[] = {
+		{ NULL,		dev_no_args},
+		{ 0 }
+	};
+
+	return rd_exec_cmd(rd, cmds, "parameter");
+}
+
+static int dev_show(struct rd *rd)
+{
+	struct dev_map *dev_map;
+	int ret = 0;
+
+	if (rd_no_arg(rd)) {
+		list_for_each_entry(dev_map, &rd->dev_map_list, list) {
+			rd->dev_idx = dev_map->idx;
+			ret = dev_one_show(rd);
+			if (ret)
+				return ret;
+		}
+
+	} else {
+		dev_map = dev_map_lookup(rd, false);
+		if (!dev_map) {
+			pr_err("Wrong device name\n");
+			return -ENOENT;
+		}
+		rd_arg_inc(rd);
+		rd->dev_idx = dev_map->idx;
+		ret = dev_one_show(rd);
+	}
+	return ret;
+}
+
+int cmd_dev(struct rd *rd)
+{
+	const struct rd_cmd cmds[] = {
+		{ NULL,		dev_show },
+		{ "show",	dev_show },
+		{ "list",	dev_show },
+		{ "help",	dev_help },
+		{ 0 }
+	};
+
+	return rd_exec_cmd(rd, cmds, "dev command");
+}
diff --git a/rdma/rdma.c b/rdma/rdma.c
index d850e396..9c2bdc8f 100644
--- a/rdma/rdma.c
+++ b/rdma/rdma.c
@@ -15,7 +15,7 @@
 static void help(char *name)
 {
 	pr_out("Usage: %s [ OPTIONS ] OBJECT { COMMAND | help }\n"
-	       "where  OBJECT := { help }\n"
+	       "where  OBJECT := { dev | help }\n"
 	       "       OPTIONS := { -V[ersion] | -d[etails]}\n", name);
 }
 
@@ -30,6 +30,7 @@ static int rd_cmd(struct rd *rd)
 	const struct rd_cmd cmds[] = {
 		{ NULL,		cmd_help },
 		{ "help",	cmd_help },
+		{ "dev",	cmd_dev },
 		{ 0 }
 	};
 
diff --git a/rdma/rdma.h b/rdma/rdma.h
index 361888b8..b9d75d29 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -40,6 +40,8 @@ struct rd {
 	char *filename;
 	bool show_details;
 	struct list_head dev_map_list;
+	uint32_t dev_idx;
+	uint32_t port_idx;
 	struct mnl_socket *nl;
 	struct nlmsghdr *nlh;
 	char *buff;
@@ -56,12 +58,23 @@ struct rd_cmd {
 bool rd_no_arg(struct rd *rd);
 void rd_arg_inc(struct rd *rd);
 
+char *rd_argv(struct rd *rd);
+uint32_t get_port_from_argv(struct rd *rd);
+
+void rd_print_u64(char *name, uint64_t val);
+/*
+ * Commands interface
+ */
+int cmd_dev(struct rd *rd);
+int cmd_link(struct rd *rd);
 int rd_exec_cmd(struct rd *rd, const struct rd_cmd *c, const char *str);
 
 /*
  * Device manipulation
  */
 void rd_free_devmap(struct rd *rd);
+struct dev_map *dev_map_lookup(struct rd *rd, bool allow_port_index);
+struct dev_map *_dev_map_lookup(struct rd *rd, const char *dev_name);
 
 /*
  * Netlink
diff --git a/rdma/utils.c b/rdma/utils.c
index 9bd7418f..0e32eefe 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -16,7 +16,7 @@ static int rd_argc(struct rd *rd)
 	return rd->argc;
 }
 
-static char *rd_argv(struct rd *rd)
+char *rd_argv(struct rd *rd)
 {
 	if (!rd_argc(rd))
 		return NULL;
@@ -50,6 +50,23 @@ bool rd_no_arg(struct rd *rd)
 	return rd_argc(rd) == 0;
 }
 
+uint32_t get_port_from_argv(struct rd *rd)
+{
+	char *slash;
+
+	slash = strchr(rd_argv(rd), '/');
+	/* if no port found, return 0 */
+	return slash ? atoi(slash + 1) : 0;
+}
+
+void rd_print_u64(char *name, uint64_t val)
+{
+	uint16_t vp[4];
+
+	memcpy(vp, &val, sizeof(uint64_t));
+	pr_out("%s %04x:%04x:%04x:%04x ", name, vp[3], vp[2], vp[1], vp[0]);
+}
+
 static struct dev_map *dev_map_alloc(const char *dev_name)
 {
 	struct dev_map *dev_map;
@@ -83,8 +100,14 @@ static void dev_map_cleanup(struct rd *rd)
 }
 
 static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
+	[RDMA_NLDEV_ATTR_DEV_INDEX] = MNL_TYPE_U32,
 	[RDMA_NLDEV_ATTR_DEV_NAME] = MNL_TYPE_NUL_STRING,
 	[RDMA_NLDEV_ATTR_PORT_INDEX] = MNL_TYPE_U32,
+	[RDMA_NLDEV_ATTR_CAP_FLAGS] = MNL_TYPE_U64,
+	[RDMA_NLDEV_ATTR_FW_VERSION] = MNL_TYPE_NUL_STRING,
+	[RDMA_NLDEV_ATTR_NODE_GUID] = MNL_TYPE_U64,
+	[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID] = MNL_TYPE_U64,
+	[RDMA_NLDEV_ATTR_DEV_NODE_TYPE] = MNL_TYPE_U8,
 };
 
 int rd_attr_cb(const struct nlattr *attr, void *data)
@@ -215,3 +238,32 @@ int rd_recv_msg(struct rd *rd, mnl_cb_t callback, void *data, unsigned int seq)
 	mnl_socket_close(rd->nl);
 	return ret;
 }
+
+struct dev_map *_dev_map_lookup(struct rd *rd, const char *dev_name)
+{
+	struct dev_map *dev_map;
+
+	list_for_each_entry(dev_map, &rd->dev_map_list, list)
+		if (strcmp(dev_name, dev_map->dev_name) == 0)
+			return dev_map;
+
+	return NULL;
+}
+
+struct dev_map *dev_map_lookup(struct rd *rd, bool allow_port_index)
+{
+	struct dev_map *dev_map;
+	char *dev_name;
+	char *slash;
+
+	dev_name = strdup(rd_argv(rd));
+	if (allow_port_index) {
+		slash = strrchr(dev_name, '/');
+		if (slash)
+			*slash = '\0';
+	}
+
+	dev_map = _dev_map_lookup(rd, dev_name);
+	free(dev_name);
+	return dev_map;
+}
-- 
2.14.0

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v4 iproute2 3/7] rdma: Add link object
  2017-08-15 13:00 [PATCH v4 iproute2 0/7] RDMAtool Leon Romanovsky
  2017-08-15 13:00 ` [PATCH v4 iproute2 1/7] rdma: Add basic infrastructure for RDMA tool Leon Romanovsky
       [not found] ` <20170815130020.29509-1-leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
@ 2017-08-15 13:00 ` Leon Romanovsky
  2017-08-15 13:00 ` [PATCH v4 iproute2 5/7] rdma: Add json and pretty outputs Leon Romanovsky
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 13:00 UTC (permalink / raw)
  To: Doug Ledford, Stephen Hemminger
  Cc: linux-rdma, Leon Romanovsky, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

Link (port) object represent struct ib_port to the user space.

Link properties:
 * Port capabilities
 * IB subnet prefix
 * LID, SM_LID and LMC
 * Port state
 * Physical state

Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 rdma/Makefile |   2 +-
 rdma/link.c   | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 rdma/rdma.c   |   3 +-
 rdma/utils.c  |   5 ++
 4 files changed, 282 insertions(+), 2 deletions(-)
 create mode 100644 rdma/link.c

diff --git a/rdma/Makefile b/rdma/Makefile
index 123d7ac5..1a9e4b1a 100644
--- a/rdma/Makefile
+++ b/rdma/Makefile
@@ -2,7 +2,7 @@ include ../Config
 
 ifeq ($(HAVE_MNL),y)
 
-RDMA_OBJ = rdma.o utils.o dev.o
+RDMA_OBJ = rdma.o utils.o dev.o link.o
 
 TARGETS=rdma
 CFLAGS += $(shell $(PKG_CONFIG) libmnl --cflags)
diff --git a/rdma/link.c b/rdma/link.c
new file mode 100644
index 00000000..51858965
--- /dev/null
+++ b/rdma/link.c
@@ -0,0 +1,274 @@
+/*
+ * link.c	RDMA tool
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:     Leon Romanovsky <leonro@mellanox.com>
+ */
+
+#include "rdma.h"
+
+static int link_help(struct rd *rd)
+{
+	pr_out("Usage: %s link show [DEV/PORT_INDEX]\n", rd->filename);
+	return 0;
+}
+
+static const char *caps_to_str(uint32_t idx)
+{
+	uint64_t cap = 1 << idx;
+
+	switch (cap) {
+	case RDMA_PORT_SM: return "SM";
+	case RDMA_PORT_NOTICE: return "NOTICE";
+	case RDMA_PORT_TRAP: return "TRAP";
+	case RDMA_PORT_OPT_IPD: return "OPT_IPD";
+	case RDMA_PORT_AUTO_MIGR: return "AUTO_MIG";
+	case RDMA_PORT_SL_MAP: return "SL_MAP";
+	case RDMA_PORT_MKEY_NVRAM: return "MKEY_NVRAM";
+	case RDMA_PORT_PKEY_NVRAM: return "PKEY_NVRAM";
+	case RDMA_PORT_LED_INFO: return "LED_INFO";
+	case RDMA_PORT_SM_DISABLED: return "SM_DISABLED";
+	case RDMA_PORT_SYS_IMAGE_GUID: return "SYS_IMAGE_GUID";
+	case RDMA_PORT_PKEY_SW_EXT_PORT_TRAP: return "PKEY_SW_EXT_PORT_TRAP";
+	case RDMA_PORT_EXTENDED_SPEEDS: return "EXTENDED_SPEEDS";
+	case RDMA_PORT_CM: return "CM";
+	case RDMA_PORT_SNMP_TUNNEL: return "SNMP_TUNNEL";
+	case RDMA_PORT_REINIT: return "REINIT";
+	case RDMA_PORT_DEVICE_MGMT: return "DEVICE_MGMT";
+	case RDMA_PORT_VENDOR_CLASS: return "VENDOR_CLASS";
+	case RDMA_PORT_DR_NOTICE: return "PORT_DR_NOTICE";
+	case RDMA_PORT_CAP_MASK_NOTICE: return "CAP_MASK_NOTICE";
+	case RDMA_PORT_BOOT_MGMT: return "BOOT_MGMT";
+	case RDMA_PORT_LINK_LATENCY: return "LINK_LATENCY";
+	case RDMA_PORT_CLIENT_REG: return "CLIENT_REG";
+	case RDMA_PORT_IP_BASED_GIDS: return "IP_BASED_GIDS";
+	default: return "UKNOWN";
+	}
+};
+
+static void link_print_caps(struct nlattr **tb)
+{
+	uint64_t caps;
+	uint32_t idx;
+
+	if (!tb[RDMA_NLDEV_ATTR_CAP_FLAGS])
+		return;
+
+	caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
+
+	pr_out("\n    caps: <");
+	for (idx = 0; caps; idx++) {
+		if (caps & 0x1) {
+			pr_out("%s", caps_to_str(idx));
+			if (caps >> 0x1)
+				pr_out(", ");
+		}
+		caps >>= 0x1;
+	}
+
+	pr_out(">");
+}
+
+static void link_print_subnet_prefix(struct nlattr **tb)
+{
+	uint64_t subnet_prefix;
+
+	if (!tb[RDMA_NLDEV_ATTR_SUBNET_PREFIX])
+		return;
+
+	subnet_prefix = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SUBNET_PREFIX]);
+	rd_print_u64("subnet_prefix", subnet_prefix);
+}
+
+static void link_print_lid(struct nlattr **tb)
+{
+	if (!tb[RDMA_NLDEV_ATTR_LID])
+		return;
+
+	pr_out("lid %u ",
+	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_LID]));
+}
+
+static void link_print_sm_lid(struct nlattr **tb)
+{
+	if (!tb[RDMA_NLDEV_ATTR_SM_LID])
+		return;
+
+	pr_out("sm_lid %u ",
+	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_SM_LID]));
+}
+
+static void link_print_lmc(struct nlattr **tb)
+{
+	if (!tb[RDMA_NLDEV_ATTR_LMC])
+		return;
+
+	pr_out("lmc %u ", mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_LMC]));
+}
+
+static const char *link_state_to_str(uint8_t link_state)
+{
+	switch (link_state) {
+	case RDMA_LINK_STATE_NOP: return "NOP";
+	case RDMA_LINK_STATE_DOWN: return "DOWN";
+	case RDMA_LINK_STATE_INIT: return "INIT";
+	case RDMA_LINK_STATE_ARMED: return "ARMED";
+	case RDMA_LINK_STATE_ACTIVE: return "ACTIVE";
+	case RDMA_LINK_STATE_ACTIVE_DEFER: return "ACTIVE_DEFER";
+	default: return "UKNOWN";
+	}
+};
+
+static void link_print_state(struct nlattr **tb)
+{
+	uint8_t state;
+
+	if (!tb[RDMA_NLDEV_ATTR_PORT_STATE])
+		return;
+
+	state = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_PORT_STATE]);
+	pr_out("state %s ", link_state_to_str(state));
+}
+
+static const char *phys_state_to_str(uint8_t phys_state)
+{
+	switch (phys_state) {
+	case RDMA_LINK_PHYS_STATE_SLEEP: return "SLEEP";
+	case RDMA_LINK_PHYS_STATE_POLLING: return "POLLING";
+	case RDMA_LINK_PHYS_STATE_DISABLED: return "DISABLED";
+	case RDMA_LINK_PHYS_STATE_PORT_CONFIGURATION_TRAINING: return "ARMED";
+	case RDMA_LINK_PHYS_STATE_LINK_UP: return "LINK_UP";
+	case RDMA_LINK_PHYS_STATE_LINK_ERROR_RECOVER:
+						return "LINK_ERROR_RECOVER";
+	case RDMA_LINK_PHYS_STATE_LINK_PHY_TEST: return "PHY_TEST";
+	default: return "UKNOWN";
+	}
+};
+
+static void link_print_phys_state(struct nlattr **tb)
+{
+	uint8_t phys_state;
+
+	if (!tb[RDMA_NLDEV_ATTR_PORT_PHYS_STATE])
+		return;
+
+	phys_state = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_PORT_PHYS_STATE]);
+	pr_out("physical_state %s ", phys_state_to_str(phys_state));
+}
+
+static int link_parse_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
+	struct rd *rd = data;
+
+	mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
+	if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
+		return MNL_CB_ERROR;
+
+	if (!tb[RDMA_NLDEV_ATTR_PORT_INDEX]) {
+		pr_err("This tool doesn't support switches yet\n");
+		return MNL_CB_ERROR;
+	}
+
+	pr_out("%u/%u: %s/%u: ",
+	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]),
+	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]),
+	       mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]),
+	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]));
+	link_print_subnet_prefix(tb);
+	link_print_lid(tb);
+	link_print_sm_lid(tb);
+	link_print_lmc(tb);
+	link_print_state(tb);
+	link_print_phys_state(tb);
+	if (rd->show_details)
+		link_print_caps(tb);
+
+	pr_out("\n");
+	return MNL_CB_OK;
+}
+
+static int link_no_args(struct rd *rd)
+{
+	uint32_t seq;
+	int ret;
+
+	rd_prepare_msg(rd, RDMA_NLDEV_CMD_PORT_GET, &seq,
+		       (NLM_F_REQUEST | NLM_F_ACK));
+	mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
+	mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_PORT_INDEX, rd->port_idx);
+	ret = rd_send_msg(rd);
+	if (ret)
+		return ret;
+
+	return rd_recv_msg(rd, link_parse_cb, rd, seq);
+}
+
+static int link_one_show(struct rd *rd)
+{
+	const struct rd_cmd cmds[] = {
+		{ NULL,		link_no_args},
+		{ 0 }
+	};
+
+	return rd_exec_cmd(rd, cmds, "parameter");
+}
+
+static int link_show(struct rd *rd)
+{
+	struct dev_map *dev_map;
+	uint32_t port;
+	int ret;
+
+	if (rd_no_arg(rd)) {
+		list_for_each_entry(dev_map, &rd->dev_map_list, list) {
+			rd->dev_idx = dev_map->idx;
+			for (port = 1; port < dev_map->num_ports + 1; port++) {
+				rd->port_idx = port;
+				ret = link_one_show(rd);
+				if (ret)
+					return ret;
+			}
+		}
+
+	} else {
+		dev_map = dev_map_lookup(rd, true);
+		port = get_port_from_argv(rd);
+		if (!dev_map || port > dev_map->num_ports) {
+			pr_err("Wrong device name\n");
+			return -ENOENT;
+		}
+		rd_arg_inc(rd);
+		rd->dev_idx = dev_map->idx;
+		rd->port_idx = port ? : 1;
+		for (; rd->port_idx < dev_map->num_ports + 1; rd->port_idx++) {
+			ret = link_one_show(rd);
+			if (ret)
+				return ret;
+			if (port)
+				/*
+				 * We got request to show link for devname
+				 * with port index.
+				 */
+				break;
+		}
+	}
+	return 0;
+}
+
+int cmd_link(struct rd *rd)
+{
+	const struct rd_cmd cmds[] = {
+		{ NULL,		link_show },
+		{ "show",	link_show },
+		{ "list",	link_show },
+		{ "help",	link_help },
+		{ 0 }
+	};
+
+	return rd_exec_cmd(rd, cmds, "link command");
+}
diff --git a/rdma/rdma.c b/rdma/rdma.c
index 9c2bdc8f..74c09e8b 100644
--- a/rdma/rdma.c
+++ b/rdma/rdma.c
@@ -15,7 +15,7 @@
 static void help(char *name)
 {
 	pr_out("Usage: %s [ OPTIONS ] OBJECT { COMMAND | help }\n"
-	       "where  OBJECT := { dev | help }\n"
+	       "where  OBJECT := { dev | link | help }\n"
 	       "       OPTIONS := { -V[ersion] | -d[etails]}\n", name);
 }
 
@@ -31,6 +31,7 @@ static int rd_cmd(struct rd *rd)
 		{ NULL,		cmd_help },
 		{ "help",	cmd_help },
 		{ "dev",	cmd_dev },
+		{ "link",	cmd_link },
 		{ 0 }
 	};
 
diff --git a/rdma/utils.c b/rdma/utils.c
index 0e32eefe..91d05271 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -107,6 +107,11 @@ static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
 	[RDMA_NLDEV_ATTR_FW_VERSION] = MNL_TYPE_NUL_STRING,
 	[RDMA_NLDEV_ATTR_NODE_GUID] = MNL_TYPE_U64,
 	[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID] = MNL_TYPE_U64,
+	[RDMA_NLDEV_ATTR_LID] = MNL_TYPE_U32,
+	[RDMA_NLDEV_ATTR_SM_LID] = MNL_TYPE_U32,
+	[RDMA_NLDEV_ATTR_LMC] = MNL_TYPE_U8,
+	[RDMA_NLDEV_ATTR_PORT_STATE] = MNL_TYPE_U8,
+	[RDMA_NLDEV_ATTR_PORT_PHYS_STATE] = MNL_TYPE_U8,
 	[RDMA_NLDEV_ATTR_DEV_NODE_TYPE] = MNL_TYPE_U8,
 };
 
-- 
2.14.0

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

* [PATCH v4 iproute2 4/7] rdma: Add initial manual for the tool
       [not found] ` <20170815130020.29509-1-leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
  2017-08-15 13:00   ` [PATCH v4 iproute2 2/7] rdma: Add dev object Leon Romanovsky
@ 2017-08-15 13:00   ` Leon Romanovsky
  1 sibling, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 13:00 UTC (permalink / raw)
  To: Doug Ledford, Stephen Hemminger
  Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, Leon Romanovsky,
	Dennis Dalessandro, Jason Gunthorpe, Jiri Pirko, Ariel Almog,
	Linux Netdev

Signed-off-by: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 man/man8/rdma-dev.8  |  55 +++++++++++++++++++++++++++
 man/man8/rdma-link.8 |  55 +++++++++++++++++++++++++++
 man/man8/rdma.8      | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 212 insertions(+)
 create mode 100644 man/man8/rdma-dev.8
 create mode 100644 man/man8/rdma-link.8
 create mode 100644 man/man8/rdma.8

diff --git a/man/man8/rdma-dev.8 b/man/man8/rdma-dev.8
new file mode 100644
index 00000000..461681b6
--- /dev/null
+++ b/man/man8/rdma-dev.8
@@ -0,0 +1,55 @@
+.TH RDMA\-DEV 8 "06 Jul 2017" "iproute2" "Linux"
+.SH NAME
+rdmak-dev \- RDMA device configuration
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+.ti -8
+.B rdma
+.RI "[ " OPTIONS " ]"
+.B dev
+.RI  " { " COMMAND " | "
+.BR help " }"
+.sp
+
+.ti -8
+.IR OPTIONS " := { "
+\fB\-V\fR[\fIersion\fR] |
+\fB\-d\fR[\fIetails\fR] }
+
+.ti -8
+.B rdma dev show
+.RI "[ " DEV " ]"
+
+.ti -8
+.B rdma dev help
+
+.SH "DESCRIPTION"
+.SS rdma dev show - display rdma device attributes
+
+.PP
+.I "DEV"
+- specifies the RDMA device to show.
+If this argument is omitted all devices are listed.
+
+.SH "EXAMPLES"
+.PP
+rdma dev
+.RS 4
+Shows the state of all RDMA devices on the system.
+.RE
+.PP
+rdma dev show mlx5_3
+.RS 4
+Shows the state of specified RDMA device.
+.RE
+.PP
+
+.SH SEE ALSO
+.BR rdma (8),
+.BR rdma-link (8),
+.br
+
+.SH AUTHOR
+Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
diff --git a/man/man8/rdma-link.8 b/man/man8/rdma-link.8
new file mode 100644
index 00000000..8ed049ef
--- /dev/null
+++ b/man/man8/rdma-link.8
@@ -0,0 +1,55 @@
+.TH RDMA\-LINK 8 "06 Jul 2017" "iproute2" "Linux"
+.SH NAME
+rdma-link \- rdma link configuration
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+.ti -8
+.B devlink
+.RI "[ " OPTIONS " ]"
+.B link
+.RI  " { " COMMAND " | "
+.BR help " }"
+.sp
+
+.ti -8
+.IR OPTIONS " := { "
+\fB\-V\fR[\fIersion\fR] |
+\fB\-d\fR[\fIetails\fR] }
+
+.ti -8
+.B rdma link show
+.RI "[ " DEV/PORT_INDEX " ]"
+
+.ti -8
+.B rdma link help
+
+.SH "DESCRIPTION"
+.SS rdma link show - display rdma link attributes
+
+.PP
+.I "DEV/PORT_INDEX"
+- specifies the RDMa link to show.
+If this argument is omitted all links are listed.
+
+.SH "EXAMPLES"
+.PP
+rdma link show
+.RS 4
+Shows the state of all rdma links on the system.
+.RE
+.PP
+rdma link show mlx5_2/1
+.RS 4
+Shows the state of specified rdma link.
+.RE
+.PP
+
+.SH SEE ALSO
+.BR rdma (8),
+.BR rdma-dev (8),
+.br
+
+.SH AUTHOR
+Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
diff --git a/man/man8/rdma.8 b/man/man8/rdma.8
new file mode 100644
index 00000000..798b33d3
--- /dev/null
+++ b/man/man8/rdma.8
@@ -0,0 +1,102 @@
+.TH RDMA 8 "28 Mar 2017" "iproute2" "Linux"
+.SH NAME
+rdma \- RDMA tool
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+.ti -8
+.B rdma
+.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | "
+.BR help " }"
+.sp
+
+.ti -8
+.IR OBJECT " := { "
+.BR dev " | " link " }"
+.sp
+
+.ti -8
+.IR OPTIONS " := { "
+\fB\-V\fR[\fIersion\fR] |
+\fB\-d\fR[\fIetails\fR] }
+\fB\-j\fR[\fIson\fR] }
+\fB\-p\fR[\fIretty\fR] }
+
+.SH OPTIONS
+
+.TP
+.BR "\-V" , " -Version"
+Print the version of the
+.B rdma
+tool and exit.
+
+.TP
+.BR "\-d" , " --details"
+Otuput detailed information.
+
+.TP
+.BR "\-p" , " --pretty"
+When combined with -j generate a pretty JSON output.
+
+.TP
+.BR "\-j" , " --json"
+Generate JSON output.
+
+.SS
+.I OBJECT
+
+.TP
+.B dev
+- RDMA device.
+
+.TP
+.B link
+- RDMA port related.
+
+.PP
+The names of all objects may be written in full or
+abbreviated form, for example
+.B stats
+can be abbreviated as
+.B stat
+or just
+.B s.
+
+.SS
+.I COMMAND
+
+Specifies the action to perform on the object.
+The set of possible actions depends on the object type.
+As a rule, it is possible to
+.B show
+(or
+.B list
+) objects, but some objects do not allow all of these operations
+or have some additional commands. The
+.B help
+command is available for all objects. It prints
+out a list of available commands and argument syntax conventions.
+.sp
+If no command is given, some default command is assumed.
+Usually it is
+.B list
+or, if the objects of this class cannot be listed,
+.BR "help" .
+
+.SH EXIT STATUS
+Exit status is 0 if command was successful or a positive integer upon failure.
+
+.SH SEE ALSO
+.BR rdma-dev (8),
+.BR rdma-link (8),
+.br
+
+.SH REPORTING BUGS
+Report any bugs to the Linux RDMA mailing list
+.B <linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
+where the development and maintenance is primarily done.
+You do not have to be subscribed to the list to send a message there.
+
+.SH AUTHOR
+Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
-- 
2.14.0

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v4 iproute2 5/7] rdma: Add json and pretty outputs
  2017-08-15 13:00 [PATCH v4 iproute2 0/7] RDMAtool Leon Romanovsky
                   ` (2 preceding siblings ...)
  2017-08-15 13:00 ` [PATCH v4 iproute2 3/7] rdma: Add link object Leon Romanovsky
@ 2017-08-15 13:00 ` Leon Romanovsky
  2017-08-15 13:00 ` [PATCH v4 iproute2 6/7] rdma: Implement json output for dev object Leon Romanovsky
  2017-08-15 13:00 ` [PATCH v4 iproute2 7/7] rdma: Add json output to link object Leon Romanovsky
  5 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 13:00 UTC (permalink / raw)
  To: Doug Ledford, Stephen Hemminger
  Cc: linux-rdma, Leon Romanovsky, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 rdma/rdma.c | 31 ++++++++++++++++++++++++++++---
 rdma/rdma.h |  4 ++++
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/rdma/rdma.c b/rdma/rdma.c
index 74c09e8b..f9f4f2a2 100644
--- a/rdma/rdma.c
+++ b/rdma/rdma.c
@@ -16,7 +16,7 @@ static void help(char *name)
 {
 	pr_out("Usage: %s [ OPTIONS ] OBJECT { COMMAND | help }\n"
 	       "where  OBJECT := { dev | link | help }\n"
-	       "       OPTIONS := { -V[ersion] | -d[etails]}\n", name);
+	       "       OPTIONS := { -V[ersion] | -d[etails] | -j[son] | -p[retty]}\n", name);
 }
 
 static int cmd_help(struct rd *rd)
@@ -47,6 +47,16 @@ static int rd_init(struct rd *rd, int argc, char **argv, char *filename)
 	rd->argc = argc;
 	rd->argv = argv;
 	INIT_LIST_HEAD(&rd->dev_map_list);
+
+	if (rd->json_output) {
+		rd->jw = jsonw_new(stdout);
+		if (!rd->jw) {
+			pr_err("Failed to create JSON writer\n");
+			return -ENOMEM;
+		}
+		jsonw_pretty(rd->jw, rd->pretty_output);
+	}
+
 	rd->buff = malloc(MNL_SOCKET_BUFFER_SIZE);
 	if (!rd->buff)
 		return -ENOMEM;
@@ -62,6 +72,8 @@ static int rd_init(struct rd *rd, int argc, char **argv, char *filename)
 
 static void rd_free(struct rd *rd)
 {
+	if (rd->json_output)
+		jsonw_destroy(&rd->jw);
 	free(rd->buff);
 	rd_free_devmap(rd);
 }
@@ -71,10 +83,14 @@ int main(int argc, char **argv)
 	static const struct option long_options[] = {
 		{ "version",		no_argument,		NULL, 'V' },
 		{ "help",		no_argument,		NULL, 'h' },
+		{ "json",		no_argument,		NULL, 'j' },
+		{ "pretty",		no_argument,		NULL, 'p' },
 		{ "details",		no_argument,		NULL, 'd' },
 		{ NULL, 0, NULL, 0 }
 	};
+	bool pretty_output = false;
 	bool show_details = false;
+	bool json_output = false;
 	char *filename;
 	struct rd rd;
 	int opt;
@@ -82,16 +98,22 @@ int main(int argc, char **argv)
 
 	filename = basename(argv[0]);
 
-	while ((opt = getopt_long(argc, argv, "Vhd",
+	while ((opt = getopt_long(argc, argv, "Vhdpj",
 				  long_options, NULL)) >= 0) {
 		switch (opt) {
 		case 'V':
 			printf("%s utility, iproute2-ss%s\n",
 			       filename, SNAPSHOT);
 			return EXIT_SUCCESS;
+		case 'p':
+			pretty_output = true;
+			break;
 		case 'd':
 			show_details = true;
 			break;
+		case 'j':
+			json_output = true;
+			break;
 		case 'h':
 			help(filename);
 			return EXIT_SUCCESS;
@@ -105,11 +127,14 @@ int main(int argc, char **argv)
 	argc -= optind;
 	argv += optind;
 
+	rd.show_details = show_details;
+	rd.json_output = json_output;
+	rd.pretty_output = pretty_output;
+
 	err = rd_init(&rd, argc, argv, filename);
 	if (err)
 		goto out;
 
-	rd.show_details = show_details;
 	err = rd_cmd(&rd);
 out:
 	/* Always cleanup */
diff --git a/rdma/rdma.h b/rdma/rdma.h
index b9d75d29..620ec3db 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -23,6 +23,7 @@
 #include <rdma/rdma.h>
 
 #include "list.h"
+#include "json_writer.h"
 
 #define pr_err(args...) fprintf(stderr, ##args)
 #define pr_out(args...) fprintf(stdout, ##args)
@@ -45,6 +46,9 @@ struct rd {
 	struct mnl_socket *nl;
 	struct nlmsghdr *nlh;
 	char *buff;
+	json_writer_t *jw;
+	bool json_output;
+	bool pretty_output;
 };
 
 struct rd_cmd {
-- 
2.14.0

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

* [PATCH v4 iproute2 6/7] rdma: Implement json output for dev object
  2017-08-15 13:00 [PATCH v4 iproute2 0/7] RDMAtool Leon Romanovsky
                   ` (3 preceding siblings ...)
  2017-08-15 13:00 ` [PATCH v4 iproute2 5/7] rdma: Add json and pretty outputs Leon Romanovsky
@ 2017-08-15 13:00 ` Leon Romanovsky
  2017-08-15 13:00 ` [PATCH v4 iproute2 7/7] rdma: Add json output to link object Leon Romanovsky
  5 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 13:00 UTC (permalink / raw)
  To: Doug Ledford, Stephen Hemminger
  Cc: linux-rdma, Leon Romanovsky, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

The example output for machine with two devices

root@mtr-leonro:~# rdma dev -j -p
[{
	"ifindex": 1,
	"ifname": "mlx5_0",
	"node_type": "ca",
	"fw": "2.8.9999",
	"node_guid": "5254:00c0:fe12:3457",
	"sys_image_guid": 5254:00c0:fe12:3457",
	"caps": [ "BAD_PKEY_CNTR", "BAD_QKEY_CNTR", "CHANGE_PHY_POR",
		  "PORT_ACTIVE_EVENT", "SYS_IMAGE_GUID", "RC_RNR_NAK_GEN",
		  "MEM_WINDOW", "UD_IP_CSUM", "UD_TSO", "XRC",
		  "MEM_MGT_EXTENSIONS", "BLOCK_MULTICAST_LOOPBACK",
		  "MEM_WINDOW_TYPE_2B", "RAW_IP_CSUM",
		  "MANAGED_FLOW_STEERING", "RESIZE_MAX_WR" ]
	},{
	"ifindex": 2,
	"ifname": mlx5_1,
	"node_type": "ca",
	"fw": "2.8.9999",
	"node_guid": "5254:00c0:fe12:3458",
	"sys_image_guid": "5254:00c0:fe12:3458",
	"caps": [ "BAD_PKEY_CNTR", "BAD_QKEY_CNTR", "CHANGE_PHY_POR",
		  "PORT_ACTIVE_EVENT", "SYS_IMAGE_GUID", "RC_RNR_NAK_GEN",
		  "MEM_WINDOW", "UD_IP_CSUM", "UD_TSO", "XRC",
		  "MEM_MGT_EXTENSIONS", "BLOCK_MULTICAST_LOOPBACK",
		  "MEM_WINDOW_TYPE_2B", "RAW_IP_CSUM",
		  "MANAGED_FLOW_STEERING", "RESIZE_MAX_WR" ]
	}
]

Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 rdma/dev.c | 110 +++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 82 insertions(+), 28 deletions(-)

diff --git a/rdma/dev.c b/rdma/dev.c
index e984f805..621c4808 100644
--- a/rdma/dev.c
+++ b/rdma/dev.c
@@ -61,7 +61,7 @@ static const char *dev_caps_to_str(uint32_t idx)
 	}
 }
 
-static void dev_print_caps(struct nlattr **tb)
+static void dev_print_caps(struct rd *rd, struct nlattr **tb)
 {
 	uint64_t caps;
 	uint32_t idx;
@@ -71,48 +71,78 @@ static void dev_print_caps(struct nlattr **tb)
 
 	caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
 
-	pr_out("\n    caps: <");
+	if (rd->json_output) {
+		jsonw_name(rd->jw, "caps");
+		jsonw_start_array(rd->jw);
+	} else {
+		pr_out("\n    caps: <");
+	}
 	for (idx = 0; caps; idx++) {
 		if (caps & 0x1) {
-			pr_out("%s", dev_caps_to_str(idx));
-			if (caps >> 0x1)
-				pr_out(", ");
+			if (rd->json_output) {
+				jsonw_string(rd->jw, dev_caps_to_str(idx));
+			} else {
+				pr_out("%s", dev_caps_to_str(idx));
+				if (caps >> 0x1)
+					pr_out(", ");
+			}
 		}
 		caps >>= 0x1;
 	}
 
-	pr_out(">");
+	if (rd->json_output)
+		jsonw_end_array(rd->jw);
+	else
+		pr_out(">");
 }
 
-static void dev_print_fw(struct nlattr **tb)
+static void dev_print_fw(struct rd *rd, struct nlattr **tb)
 {
+	const char *str;
 	if (!tb[RDMA_NLDEV_ATTR_FW_VERSION])
 		return;
 
-	pr_out("fw %s ",
-	       mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION]));
+	str = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION]);
+	if (rd->json_output)
+		jsonw_string_field(rd->jw, "fw", str);
+	else
+		pr_out("fw %s ", str);
 }
 
-static void dev_print_node_guid(struct nlattr **tb)
+static void dev_print_node_guid(struct rd *rd, struct nlattr **tb)
 {
 	uint64_t node_guid;
+	uint16_t vp[4];
+	char str[32];
 
 	if (!tb[RDMA_NLDEV_ATTR_NODE_GUID])
 		return;
 
 	node_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_NODE_GUID]);
-	rd_print_u64("node_guid", node_guid);
+	memcpy(vp, &node_guid, sizeof(uint64_t));
+	snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
+	if (rd->json_output)
+		jsonw_string_field(rd->jw, "node_guid", str);
+	else
+		pr_out("node_guid %s ", str);
 }
 
-static void dev_print_sys_image_guid(struct nlattr **tb)
+static void dev_print_sys_image_guid(struct rd *rd, struct nlattr **tb)
 {
 	uint64_t sys_image_guid;
+	uint16_t vp[4];
+	char str[32];
 
 	if (!tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID])
 		return;
 
 	sys_image_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID]);
-	rd_print_u64("sys_image_guid", sys_image_guid);
+	memcpy(vp, &sys_image_guid, sizeof(uint64_t));
+	snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
+	if (rd->json_output)
+		jsonw_string_field(rd->jw, "sys_image_guid", str);
+	else
+		pr_out("sys_image_guid %s ", str);
 }
 
 static const char *node_type_to_str(uint8_t node_type)
@@ -128,37 +158,51 @@ static const char *node_type_to_str(uint8_t node_type)
 	}
 }
 
-static void dev_print_node_type(struct nlattr **tb)
+static void dev_print_node_type(struct rd *rd, struct nlattr **tb)
 {
+	const char *node_str;
 	uint8_t node_type;
 
 	if (!tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE])
 		return;
 
 	node_type = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE]);
-	pr_out("node_type %s ", node_type_to_str(node_type));
+	node_str = node_type_to_str(node_type);
+	if (rd->json_output)
+		jsonw_string_field(rd->jw, "node_type", node_str);
+	else
+		pr_out("node_type %s ", node_str);
 }
 
 static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
 {
 	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
 	struct rd *rd = data;
+	const char *name;
+	uint32_t idx;
 
 	mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
 	if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
 		return MNL_CB_ERROR;
 
-	pr_out("%u: %s: ",
-	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]),
-	       mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]));
-	dev_print_node_type(tb);
-	dev_print_fw(tb);
-	dev_print_node_guid(tb);
-	dev_print_sys_image_guid(tb);
+	idx =  mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
+	name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
+	if (rd->json_output) {
+		jsonw_uint_field(rd->jw, "ifindex", idx);
+		jsonw_string_field(rd->jw, "ifname", name);
+	} else {
+		pr_out("%u: %s: ", idx, name);
+	}
+
+	dev_print_node_type(rd, tb);
+	dev_print_fw(rd, tb);
+	dev_print_node_guid(rd, tb);
+	dev_print_sys_image_guid(rd, tb);
 	if (rd->show_details)
-		dev_print_caps(tb);
+		dev_print_caps(rd, tb);
 
-	pr_out("\n");
+	if (!rd->json_output)
+		pr_out("\n");
 	return MNL_CB_OK;
 }
 
@@ -174,7 +218,12 @@ static int dev_no_args(struct rd *rd)
 	if (ret)
 		return ret;
 
-	return rd_recv_msg(rd, dev_parse_cb, rd, seq);
+	if (rd->json_output)
+		jsonw_start_object(rd->jw);
+	ret = rd_recv_msg(rd, dev_parse_cb, rd, seq);
+	if (rd->json_output)
+		jsonw_end_object(rd->jw);
+	return ret;
 }
 
 static int dev_one_show(struct rd *rd)
@@ -192,24 +241,29 @@ static int dev_show(struct rd *rd)
 	struct dev_map *dev_map;
 	int ret = 0;
 
+	if (rd->json_output)
+		jsonw_start_array(rd->jw);
 	if (rd_no_arg(rd)) {
 		list_for_each_entry(dev_map, &rd->dev_map_list, list) {
 			rd->dev_idx = dev_map->idx;
 			ret = dev_one_show(rd);
 			if (ret)
-				return ret;
+				goto out;
 		}
-
 	} else {
 		dev_map = dev_map_lookup(rd, false);
 		if (!dev_map) {
 			pr_err("Wrong device name\n");
-			return -ENOENT;
+			ret = -ENOENT;
+			goto out;
 		}
 		rd_arg_inc(rd);
 		rd->dev_idx = dev_map->idx;
 		ret = dev_one_show(rd);
 	}
+out:
+	if (rd->json_output)
+		jsonw_end_array(rd->jw);
 	return ret;
 }
 
-- 
2.14.0

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

* [PATCH v4 iproute2 7/7] rdma: Add json output to link object
  2017-08-15 13:00 [PATCH v4 iproute2 0/7] RDMAtool Leon Romanovsky
                   ` (4 preceding siblings ...)
  2017-08-15 13:00 ` [PATCH v4 iproute2 6/7] rdma: Implement json output for dev object Leon Romanovsky
@ 2017-08-15 13:00 ` Leon Romanovsky
  5 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 13:00 UTC (permalink / raw)
  To: Doug Ledford, Stephen Hemminger
  Cc: linux-rdma, Leon Romanovsky, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

An example for the JSON output for two devices system.

root@mtr-leonro:~# rdma link -d -p -j
[{
        "ifindex": 1,
        "port": 1,
        "ifname": "mlx5_0/1",
        "subnet_prefix": "fe80:0000:0000:0000",
        "lid": 13399,
        "sm_lid": 49151,
        "lmc": 0,
        "state": "ACTIVE",
        "physical_state": "LINK_UP",
        "caps": ["AUTO_MIG"
        ]
    },{
        "ifindex": 2,
        "port": 1,
        "ifname": "mlx5_1/1",
        "subnet_prefix": "fe80:0000:0000:0000",
        "lid": 13400,
        "sm_lid": 49151,
        "lmc": 0,
        "state": "ACTIVE",
        "physical_state": "LINK_UP",
        "caps": ["AUTO_MIG"
        ]
    }
]

Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 rdma/link.c  | 144 +++++++++++++++++++++++++++++++++++++++++++----------------
 rdma/rdma.h  |   1 -
 rdma/utils.c |   8 ----
 3 files changed, 105 insertions(+), 48 deletions(-)

diff --git a/rdma/link.c b/rdma/link.c
index 51858965..b3316e7e 100644
--- a/rdma/link.c
+++ b/rdma/link.c
@@ -50,7 +50,7 @@ static const char *caps_to_str(uint32_t idx)
 	}
 };
 
-static void link_print_caps(struct nlattr **tb)
+static void link_print_caps(struct rd *rd, struct nlattr **tb)
 {
 	uint64_t caps;
 	uint32_t idx;
@@ -60,54 +60,89 @@ static void link_print_caps(struct nlattr **tb)
 
 	caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
 
-	pr_out("\n    caps: <");
+	if (rd->json_output) {
+		jsonw_name(rd->jw, "caps");
+		jsonw_start_array(rd->jw);
+	} else {
+		pr_out("\n    caps: <");
+	}
 	for (idx = 0; caps; idx++) {
 		if (caps & 0x1) {
-			pr_out("%s", caps_to_str(idx));
-			if (caps >> 0x1)
-				pr_out(", ");
+			if (rd->json_output) {
+				jsonw_string(rd->jw, caps_to_str(idx));
+			} else {
+				pr_out("%s", caps_to_str(idx));
+				if (caps >> 0x1)
+					pr_out(", ");
+			}
 		}
 		caps >>= 0x1;
 	}
 
-	pr_out(">");
+	if (rd->json_output)
+		jsonw_end_array(rd->jw);
+	else
+		pr_out(">");
 }
 
-static void link_print_subnet_prefix(struct nlattr **tb)
+static void link_print_subnet_prefix(struct rd *rd, struct nlattr **tb)
 {
 	uint64_t subnet_prefix;
+	uint16_t vp[4];
+	char str[32];
 
 	if (!tb[RDMA_NLDEV_ATTR_SUBNET_PREFIX])
 		return;
 
 	subnet_prefix = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SUBNET_PREFIX]);
-	rd_print_u64("subnet_prefix", subnet_prefix);
+	memcpy(vp, &subnet_prefix, sizeof(uint64_t));
+	snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
+	if (rd->json_output)
+		jsonw_string_field(rd->jw, "subnet_prefix", str);
+	else
+		pr_out("subnet_prefix %s ", str);
 }
 
-static void link_print_lid(struct nlattr **tb)
+static void link_print_lid(struct rd *rd, struct nlattr **tb)
 {
+	uint32_t lid;
+
 	if (!tb[RDMA_NLDEV_ATTR_LID])
 		return;
 
-	pr_out("lid %u ",
-	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_LID]));
+	lid = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_LID]);
+	if (rd->json_output)
+		jsonw_uint_field(rd->jw, "lid", lid);
+	else
+		pr_out("lid %u ", lid);
 }
 
-static void link_print_sm_lid(struct nlattr **tb)
+static void link_print_sm_lid(struct rd *rd, struct nlattr **tb)
 {
+	uint32_t sm_lid;
+
 	if (!tb[RDMA_NLDEV_ATTR_SM_LID])
 		return;
 
-	pr_out("sm_lid %u ",
-	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_SM_LID]));
+	sm_lid = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_SM_LID]);
+	if (rd->json_output)
+		jsonw_uint_field(rd->jw, "sm_lid", sm_lid);
+	else
+		pr_out("sm_lid %u ", sm_lid);
 }
 
-static void link_print_lmc(struct nlattr **tb)
+static void link_print_lmc(struct rd *rd, struct nlattr **tb)
 {
+	uint8_t lmc;
+
 	if (!tb[RDMA_NLDEV_ATTR_LMC])
 		return;
 
-	pr_out("lmc %u ", mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_LMC]));
+	lmc = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_LMC]);
+	if (rd->json_output)
+		jsonw_uint_field(rd->jw, "lmc", lmc);
+	else
+		pr_out("lmc %u ", lmc);
 }
 
 static const char *link_state_to_str(uint8_t link_state)
@@ -123,7 +158,7 @@ static const char *link_state_to_str(uint8_t link_state)
 	}
 };
 
-static void link_print_state(struct nlattr **tb)
+static void link_print_state(struct rd *rd, struct nlattr **tb)
 {
 	uint8_t state;
 
@@ -131,7 +166,10 @@ static void link_print_state(struct nlattr **tb)
 		return;
 
 	state = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_PORT_STATE]);
-	pr_out("state %s ", link_state_to_str(state));
+	if (rd->json_output)
+		jsonw_string_field(rd->jw, "state", link_state_to_str(state));
+	else
+		pr_out("state %s ", link_state_to_str(state));
 }
 
 static const char *phys_state_to_str(uint8_t phys_state)
@@ -149,7 +187,7 @@ static const char *phys_state_to_str(uint8_t phys_state)
 	}
 };
 
-static void link_print_phys_state(struct nlattr **tb)
+static void link_print_phys_state(struct rd *rd, struct nlattr **tb)
 {
 	uint8_t phys_state;
 
@@ -157,13 +195,19 @@ static void link_print_phys_state(struct nlattr **tb)
 		return;
 
 	phys_state = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_PORT_PHYS_STATE]);
-	pr_out("physical_state %s ", phys_state_to_str(phys_state));
+	if (rd->json_output)
+		jsonw_string_field(rd->jw, "physical_state",
+				   phys_state_to_str(phys_state));
+	else
+		pr_out("physical_state %s ", phys_state_to_str(phys_state));
 }
 
 static int link_parse_cb(const struct nlmsghdr *nlh, void *data)
 {
 	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
 	struct rd *rd = data;
+	uint32_t port, idx;
+	char name[32];
 
 	mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
 	if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
@@ -174,21 +218,31 @@ static int link_parse_cb(const struct nlmsghdr *nlh, void *data)
 		return MNL_CB_ERROR;
 	}
 
-	pr_out("%u/%u: %s/%u: ",
-	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]),
-	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]),
-	       mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]),
-	       mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]));
-	link_print_subnet_prefix(tb);
-	link_print_lid(tb);
-	link_print_sm_lid(tb);
-	link_print_lmc(tb);
-	link_print_state(tb);
-	link_print_phys_state(tb);
+	idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
+	port = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
+	snprintf(name, 32, "%s/%u",
+		 mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]), port);
+
+	if (rd->json_output) {
+		jsonw_uint_field(rd->jw, "ifindex", idx);
+		jsonw_uint_field(rd->jw, "port", port);
+		jsonw_string_field(rd->jw, "ifname", name);
+
+	} else {
+		pr_out("%u/%u: %s: ", idx, port, name);
+	}
+
+	link_print_subnet_prefix(rd, tb);
+	link_print_lid(rd, tb);
+	link_print_sm_lid(rd, tb);
+	link_print_lmc(rd, tb);
+	link_print_state(rd, tb);
+	link_print_phys_state(rd, tb);
 	if (rd->show_details)
-		link_print_caps(tb);
+		link_print_caps(rd, tb);
 
-	pr_out("\n");
+	if (!rd->json_output)
+		pr_out("\n");
 	return MNL_CB_OK;
 }
 
@@ -205,7 +259,12 @@ static int link_no_args(struct rd *rd)
 	if (ret)
 		return ret;
 
-	return rd_recv_msg(rd, link_parse_cb, rd, seq);
+	if (rd->json_output)
+		jsonw_start_object(rd->jw);
+	ret = rd_recv_msg(rd, link_parse_cb, rd, seq);
+	if (rd->json_output)
+		jsonw_end_object(rd->jw);
+	return ret;
 }
 
 static int link_one_show(struct rd *rd)
@@ -222,8 +281,10 @@ static int link_show(struct rd *rd)
 {
 	struct dev_map *dev_map;
 	uint32_t port;
-	int ret;
+	int ret = 0;
 
+	if (rd->json_output)
+		jsonw_start_array(rd->jw);
 	if (rd_no_arg(rd)) {
 		list_for_each_entry(dev_map, &rd->dev_map_list, list) {
 			rd->dev_idx = dev_map->idx;
@@ -231,7 +292,7 @@ static int link_show(struct rd *rd)
 				rd->port_idx = port;
 				ret = link_one_show(rd);
 				if (ret)
-					return ret;
+					goto out;
 			}
 		}
 
@@ -240,7 +301,8 @@ static int link_show(struct rd *rd)
 		port = get_port_from_argv(rd);
 		if (!dev_map || port > dev_map->num_ports) {
 			pr_err("Wrong device name\n");
-			return -ENOENT;
+			ret = -ENOENT;
+			goto out;
 		}
 		rd_arg_inc(rd);
 		rd->dev_idx = dev_map->idx;
@@ -248,7 +310,7 @@ static int link_show(struct rd *rd)
 		for (; rd->port_idx < dev_map->num_ports + 1; rd->port_idx++) {
 			ret = link_one_show(rd);
 			if (ret)
-				return ret;
+				goto out;
 			if (port)
 				/*
 				 * We got request to show link for devname
@@ -257,7 +319,11 @@ static int link_show(struct rd *rd)
 				break;
 		}
 	}
-	return 0;
+
+out:
+	if (rd->json_output)
+		jsonw_end_array(rd->jw);
+	return ret;
 }
 
 int cmd_link(struct rd *rd)
diff --git a/rdma/rdma.h b/rdma/rdma.h
index 620ec3db..4a9391c1 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -65,7 +65,6 @@ void rd_arg_inc(struct rd *rd);
 char *rd_argv(struct rd *rd);
 uint32_t get_port_from_argv(struct rd *rd);
 
-void rd_print_u64(char *name, uint64_t val);
 /*
  * Commands interface
  */
diff --git a/rdma/utils.c b/rdma/utils.c
index 91d05271..eb4377cf 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -59,14 +59,6 @@ uint32_t get_port_from_argv(struct rd *rd)
 	return slash ? atoi(slash + 1) : 0;
 }
 
-void rd_print_u64(char *name, uint64_t val)
-{
-	uint16_t vp[4];
-
-	memcpy(vp, &val, sizeof(uint64_t));
-	pr_out("%s %04x:%04x:%04x:%04x ", name, vp[3], vp[2], vp[1], vp[0]);
-}
-
 static struct dev_map *dev_map_alloc(const char *dev_name)
 {
 	struct dev_map *dev_map;
-- 
2.14.0

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

* Re: [PATCH v4 iproute2 2/7] rdma: Add dev object
  2017-08-15 13:00   ` [PATCH v4 iproute2 2/7] rdma: Add dev object Leon Romanovsky
@ 2017-08-15 16:12     ` Stephen Hemminger
  2017-08-15 16:23       ` David Laight
  2017-08-15 16:43       ` Leon Romanovsky
  0 siblings, 2 replies; 16+ messages in thread
From: Stephen Hemminger @ 2017-08-15 16:12 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Doug Ledford, linux-rdma, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

On Tue, 15 Aug 2017 16:00:15 +0300
Leon Romanovsky <leonro@mellanox.com> wrote:

> +
> +static const char *dev_caps_to_str(uint32_t idx)
> +{
> +	uint64_t cap = 1 << idx;
> +
> +	switch (cap) {
> +	case RDMA_DEV_RESIZE_MAX_WR: return "RESIZE_MAX_WR";
> +	case RDMA_DEV_BAD_PKEY_CNTR: return "BAD_PKEY_CNTR";
> +	case RDMA_DEV_BAD_QKEY_CNTR: return "BAD_QKEY_CNTR";
> +	case RDMA_DEV_RAW_MULTI: return "RAW_MULTI";
> +	case RDMA_DEV_AUTO_PATH_MIG: return "AUTO_PATH_MIG";
> +	case RDMA_DEV_CHANGE_PHY_PORT: return "CHANGE_PHY_POR";
> +	case RDMA_DEV_UD_AV_PORT_ENFORCE: return "UD_AV_PORT_ENFORCE";
> +	case RDMA_DEV_CURR_QP_STATE_MOD: return "CURR_QP_STATE_MOD";
> +	case RDMA_DEV_SHUTDOWN_PORT: return "SHUTDOWN_PORT";
> +	case RDMA_DEV_INIT_TYPE: return "INIT_TYPE";
> +	case RDMA_DEV_PORT_ACTIVE_EVENT: return "PORT_ACTIVE_EVENT";
> +	case RDMA_DEV_SYS_IMAGE_GUID: return "SYS_IMAGE_GUID";
> +	case RDMA_DEV_RC_RNR_NAK_GEN: return "RC_RNR_NAK_GEN";
> +	case RDMA_DEV_SRQ_RESIZE: return "SRQ_RESIZE";
> +	case RDMA_DEV_N_NOTIFY_CQ: return "N_NOTIFY_CQ";
> +	case RDMA_DEV_LOCAL_DMA_LKEY: return "LOCAL_DMA_LKEY";
> +	case RDMA_DEV_MEM_WINDOW: return "MEM_WINDOW";
> +	case RDMA_DEV_UD_IP_CSUM: return "UD_IP_CSUM";
> +	case RDMA_DEV_UD_TSO: return "UD_TSO";
> +	case RDMA_DEV_XRC: return "XRC";
> +	case RDMA_DEV_MEM_MGT_EXTENSIONS: return "MEM_MGT_EXTENSIONS";
> +	case RDMA_DEV_BLOCK_MULTICAST_LOOPBACK:
> +					return "BLOCK_MULTICAST_LOOPBACK";
> +	case RDMA_DEV_MEM_WINDOW_TYPE_2A: return "MEM_WINDOW_TYPE_2A";
> +	case RDMA_DEV_MEM_WINDOW_TYPE_2B: return "MEM_WINDOW_TYPE_2B";
> +	case RDMA_DEV_RC_IP_CSUM: return "RC_IP_CSUM";
> +	case RDMA_DEV_RAW_IP_CSUM: return "RAW_IP_CSUM";
> +	case RDMA_DEV_CROSS_CHANNEL: return "CROSS_CHANNEL";
> +	case RDMA_DEV_MANAGED_FLOW_STEERING: return "MANAGED_FLOW_STEERING";
> +	case RDMA_DEV_SIGNATURE_HANDOVER: return "SIGNATURE_HANDOVER";
> +	case RDMA_DEV_ON_DEMAND_PAGING: return "ON_DEMAND_PAGING";
> +	case RDMA_DEV_SG_GAPS_REG: return "SG_GAPS_REG";
> +	case RDMA_DEV_VIRTUAL_FUNCTION: return "VIRTUAL_FUNCTION";
> +	case RDMA_DEV_RAW_SCATTER_FCS: return "RAW_SCATTER_FCS";
> +	case RDMA_DEV_RDMA_NETDEV_OPA_VNIC: return "RDMA_NETDEV_OPA_VNIC";
> +	default: return "UNKNOWN";
> +	}

Could this be a table in future versions?

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

* RE: [PATCH v4 iproute2 2/7] rdma: Add dev object
  2017-08-15 16:12     ` Stephen Hemminger
@ 2017-08-15 16:23       ` David Laight
       [not found]         ` <063D6719AE5E284EB5DD2968C1650D6DD005604E-VkEWCZq2GCInGFn1LkZF6NBPR1lH4CV8@public.gmane.org>
  2017-08-15 16:43       ` Leon Romanovsky
  1 sibling, 1 reply; 16+ messages in thread
From: David Laight @ 2017-08-15 16:23 UTC (permalink / raw)
  To: 'Stephen Hemminger', Leon Romanovsky
  Cc: Doug Ledford, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	Dennis Dalessandro, Jason Gunthorpe, Jiri Pirko, Ariel Almog,
	Linux Netdev

From: Stephen Hemminger
> Sent: 15 August 2017 17:12
> On Tue, 15 Aug 2017 16:00:15 +0300
> Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org> wrote:
> 
> > +
> > +static const char *dev_caps_to_str(uint32_t idx)
> > +{
> > +	uint64_t cap = 1 << idx;
> > +
> > +	switch (cap) {
> > +	case RDMA_DEV_RESIZE_MAX_WR: return "RESIZE_MAX_WR";
> > +	case RDMA_DEV_BAD_PKEY_CNTR: return "BAD_PKEY_CNTR";
...
> > +	case RDMA_DEV_RAW_SCATTER_FCS: return "RAW_SCATTER_FCS";
> > +	case RDMA_DEV_RDMA_NETDEV_OPA_VNIC: return "RDMA_NETDEV_OPA_VNIC";
> > +	default: return "UNKNOWN";
> > +	}
> 
> Could this be a table in future versions?

Potentially you could define the constants using some pre-processor
'magic' that would create the table for you.
Something like (but not compiled):

#define RDMA_DEV_FLAGS(x) \
	x(RESIZE_MAX_WR, 0) \
	x(BAD_PKEY_CNTR, 1) \
(continue for all the bits)

#define RDMA_DEV_ENUM(name, bit_no) RDMA_DEV_##name = BIT(bit_no),
enum {RDMA_DEV_FLAGS(RDMA_DEV_ENUM)};
#undef RDMA_DEV_ENUM

#define RDMA_DEV_NAMES(name, bit_no) [bit_no] = #name,
static const char rdma_dev_names[] = {RDMA_DEV_FLAGS(RDMA_DEV_NAMES)};

	David

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v4 iproute2 2/7] rdma: Add dev object
  2017-08-15 16:12     ` Stephen Hemminger
  2017-08-15 16:23       ` David Laight
@ 2017-08-15 16:43       ` Leon Romanovsky
  1 sibling, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 16:43 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Doug Ledford, linux-rdma, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

[-- Attachment #1: Type: text/plain, Size: 3156 bytes --]

On Tue, Aug 15, 2017 at 09:12:05AM -0700, Stephen Hemminger wrote:
> On Tue, 15 Aug 2017 16:00:15 +0300
> Leon Romanovsky <leonro@mellanox.com> wrote:
>
> > +
> > +static const char *dev_caps_to_str(uint32_t idx)
> > +{
> > +	uint64_t cap = 1 << idx;
> > +
> > +	switch (cap) {
> > +	case RDMA_DEV_RESIZE_MAX_WR: return "RESIZE_MAX_WR";
> > +	case RDMA_DEV_BAD_PKEY_CNTR: return "BAD_PKEY_CNTR";
> > +	case RDMA_DEV_BAD_QKEY_CNTR: return "BAD_QKEY_CNTR";
> > +	case RDMA_DEV_RAW_MULTI: return "RAW_MULTI";
> > +	case RDMA_DEV_AUTO_PATH_MIG: return "AUTO_PATH_MIG";
> > +	case RDMA_DEV_CHANGE_PHY_PORT: return "CHANGE_PHY_POR";
> > +	case RDMA_DEV_UD_AV_PORT_ENFORCE: return "UD_AV_PORT_ENFORCE";
> > +	case RDMA_DEV_CURR_QP_STATE_MOD: return "CURR_QP_STATE_MOD";
> > +	case RDMA_DEV_SHUTDOWN_PORT: return "SHUTDOWN_PORT";
> > +	case RDMA_DEV_INIT_TYPE: return "INIT_TYPE";
> > +	case RDMA_DEV_PORT_ACTIVE_EVENT: return "PORT_ACTIVE_EVENT";
> > +	case RDMA_DEV_SYS_IMAGE_GUID: return "SYS_IMAGE_GUID";
> > +	case RDMA_DEV_RC_RNR_NAK_GEN: return "RC_RNR_NAK_GEN";
> > +	case RDMA_DEV_SRQ_RESIZE: return "SRQ_RESIZE";
> > +	case RDMA_DEV_N_NOTIFY_CQ: return "N_NOTIFY_CQ";
> > +	case RDMA_DEV_LOCAL_DMA_LKEY: return "LOCAL_DMA_LKEY";
> > +	case RDMA_DEV_MEM_WINDOW: return "MEM_WINDOW";
> > +	case RDMA_DEV_UD_IP_CSUM: return "UD_IP_CSUM";
> > +	case RDMA_DEV_UD_TSO: return "UD_TSO";
> > +	case RDMA_DEV_XRC: return "XRC";
> > +	case RDMA_DEV_MEM_MGT_EXTENSIONS: return "MEM_MGT_EXTENSIONS";
> > +	case RDMA_DEV_BLOCK_MULTICAST_LOOPBACK:
> > +					return "BLOCK_MULTICAST_LOOPBACK";
> > +	case RDMA_DEV_MEM_WINDOW_TYPE_2A: return "MEM_WINDOW_TYPE_2A";
> > +	case RDMA_DEV_MEM_WINDOW_TYPE_2B: return "MEM_WINDOW_TYPE_2B";
> > +	case RDMA_DEV_RC_IP_CSUM: return "RC_IP_CSUM";
> > +	case RDMA_DEV_RAW_IP_CSUM: return "RAW_IP_CSUM";
> > +	case RDMA_DEV_CROSS_CHANNEL: return "CROSS_CHANNEL";
> > +	case RDMA_DEV_MANAGED_FLOW_STEERING: return "MANAGED_FLOW_STEERING";
> > +	case RDMA_DEV_SIGNATURE_HANDOVER: return "SIGNATURE_HANDOVER";
> > +	case RDMA_DEV_ON_DEMAND_PAGING: return "ON_DEMAND_PAGING";
> > +	case RDMA_DEV_SG_GAPS_REG: return "SG_GAPS_REG";
> > +	case RDMA_DEV_VIRTUAL_FUNCTION: return "VIRTUAL_FUNCTION";
> > +	case RDMA_DEV_RAW_SCATTER_FCS: return "RAW_SCATTER_FCS";
> > +	case RDMA_DEV_RDMA_NETDEV_OPA_VNIC: return "RDMA_NETDEV_OPA_VNIC";
> > +	default: return "UNKNOWN";
> > +	}
>
> Could this be a table in future versions?

The device capability is 64 bit field -> the table will have 64 entry,
while most of them should be marked as "UNKNOWN". Because we have holes
[1] in the fields (for example bit 9), I can't use simple
"if (idx > max_value) return "uknown"" logic.

So the answer is yes, I can do it as a table, but it won't look better than
it is now :)

By writing "future versions", are you asking me to resubmit? or followup patch
will be possible solution too?

Thanks

[1] http://marc.info/?l=linux-rdma&m=150278850520856&w=2

> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 iproute2 2/7] rdma: Add dev object
       [not found]         ` <063D6719AE5E284EB5DD2968C1650D6DD005604E-VkEWCZq2GCInGFn1LkZF6NBPR1lH4CV8@public.gmane.org>
@ 2017-08-15 16:47           ` Leon Romanovsky
  2017-08-15 17:00             ` David Laight
  0 siblings, 1 reply; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 16:47 UTC (permalink / raw)
  To: David Laight
  Cc: 'Stephen Hemminger',
	Doug Ledford, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	Dennis Dalessandro, Jason Gunthorpe, Jiri Pirko, Ariel Almog,
	Linux Netdev

[-- Attachment #1: Type: text/plain, Size: 1580 bytes --]

On Tue, Aug 15, 2017 at 04:23:11PM +0000, David Laight wrote:
> From: Stephen Hemminger
> > Sent: 15 August 2017 17:12
> > On Tue, 15 Aug 2017 16:00:15 +0300
> > Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org> wrote:
> >
> > > +
> > > +static const char *dev_caps_to_str(uint32_t idx)
> > > +{
> > > +	uint64_t cap = 1 << idx;
> > > +
> > > +	switch (cap) {
> > > +	case RDMA_DEV_RESIZE_MAX_WR: return "RESIZE_MAX_WR";
> > > +	case RDMA_DEV_BAD_PKEY_CNTR: return "BAD_PKEY_CNTR";
> ...
> > > +	case RDMA_DEV_RAW_SCATTER_FCS: return "RAW_SCATTER_FCS";
> > > +	case RDMA_DEV_RDMA_NETDEV_OPA_VNIC: return "RDMA_NETDEV_OPA_VNIC";
> > > +	default: return "UNKNOWN";
> > > +	}
> >
> > Could this be a table in future versions?
>
> Potentially you could define the constants using some pre-processor
> 'magic' that would create the table for you.
> Something like (but not compiled):
>
> #define RDMA_DEV_FLAGS(x) \
> 	x(RESIZE_MAX_WR, 0) \
> 	x(BAD_PKEY_CNTR, 1) \
> (continue for all the bits)
>
> #define RDMA_DEV_ENUM(name, bit_no) RDMA_DEV_##name = BIT(bit_no),
> enum {RDMA_DEV_FLAGS(RDMA_DEV_ENUM)};
> #undef RDMA_DEV_ENUM
>
> #define RDMA_DEV_NAMES(name, bit_no) [bit_no] = #name,
> static const char rdma_dev_names[] = {RDMA_DEV_FLAGS(RDMA_DEV_NAMES)};
>

David,

How should I handle "uknown" fields without names?

Thanks

> 	David
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* RE: [PATCH v4 iproute2 2/7] rdma: Add dev object
  2017-08-15 16:47           ` Leon Romanovsky
@ 2017-08-15 17:00             ` David Laight
       [not found]               ` <063D6719AE5E284EB5DD2968C1650D6DD005613D-VkEWCZq2GCInGFn1LkZF6NBPR1lH4CV8@public.gmane.org>
  0 siblings, 1 reply; 16+ messages in thread
From: David Laight @ 2017-08-15 17:00 UTC (permalink / raw)
  To: 'Leon Romanovsky'
  Cc: 'Stephen Hemminger',
	Doug Ledford, linux-rdma, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

From: Leon Romanovsky
> Sent: 15 August 2017 17:47
> On Tue, Aug 15, 2017 at 04:23:11PM +0000, David Laight wrote:
> > From: Stephen Hemminger
> > > Sent: 15 August 2017 17:12
> > > On Tue, 15 Aug 2017 16:00:15 +0300
> > > Leon Romanovsky <leonro@mellanox.com> wrote:
> > >
> > > > +
> > > > +static const char *dev_caps_to_str(uint32_t idx)
> > > > +{
> > > > +	uint64_t cap = 1 << idx;
> > > > +
> > > > +	switch (cap) {
> > > > +	case RDMA_DEV_RESIZE_MAX_WR: return "RESIZE_MAX_WR";
> > > > +	case RDMA_DEV_BAD_PKEY_CNTR: return "BAD_PKEY_CNTR";
> > ...
> > > > +	case RDMA_DEV_RAW_SCATTER_FCS: return "RAW_SCATTER_FCS";
> > > > +	case RDMA_DEV_RDMA_NETDEV_OPA_VNIC: return "RDMA_NETDEV_OPA_VNIC";
> > > > +	default: return "UNKNOWN";
> > > > +	}
> > >
> > > Could this be a table in future versions?
> >
> > Potentially you could define the constants using some pre-processor
> > 'magic' that would create the table for you.
> > Something like (but not compiled):
> >
> > #define RDMA_DEV_FLAGS(x) \
> > 	x(RESIZE_MAX_WR, 0) \
> > 	x(BAD_PKEY_CNTR, 1) \
> > (continue for all the bits)
> >
> > #define RDMA_DEV_ENUM(name, bit_no) RDMA_DEV_##name = BIT(bit_no),
> > enum {RDMA_DEV_FLAGS(RDMA_DEV_ENUM)};
> > #undef RDMA_DEV_ENUM
> >
> > #define RDMA_DEV_NAMES(name, bit_no) [bit_no] = #name,
> > static const char rdma_dev_names[] = {RDMA_DEV_FLAGS(RDMA_DEV_NAMES)};
I missed the #undef
> >
> 
> David,
> 
> How should I handle "uknown" fields without names?

The function that accesses rdma_dev_names[] checks ARRAY_SIZE()
and for a NULL pointer.

WRT the other comment, the spare pointers consume far less space than
the code for your switch statement.

	David

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

* Re: [PATCH v4 iproute2 2/7] rdma: Add dev object
       [not found]               ` <063D6719AE5E284EB5DD2968C1650D6DD005613D-VkEWCZq2GCInGFn1LkZF6NBPR1lH4CV8@public.gmane.org>
@ 2017-08-15 17:46                 ` Leon Romanovsky
  0 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-15 17:46 UTC (permalink / raw)
  To: David Laight
  Cc: 'Stephen Hemminger',
	Doug Ledford, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	Dennis Dalessandro, Jason Gunthorpe, Jiri Pirko, Ariel Almog,
	Linux Netdev

[-- Attachment #1: Type: text/plain, Size: 1944 bytes --]

On Tue, Aug 15, 2017 at 05:00:54PM +0000, David Laight wrote:
> From: Leon Romanovsky
> > Sent: 15 August 2017 17:47
> > On Tue, Aug 15, 2017 at 04:23:11PM +0000, David Laight wrote:
> > > From: Stephen Hemminger
> > > > Sent: 15 August 2017 17:12
> > > > On Tue, 15 Aug 2017 16:00:15 +0300
> > > > Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org> wrote:
> > > >
> > > > > +
> > > > > +static const char *dev_caps_to_str(uint32_t idx)
> > > > > +{
> > > > > +	uint64_t cap = 1 << idx;
> > > > > +
> > > > > +	switch (cap) {
> > > > > +	case RDMA_DEV_RESIZE_MAX_WR: return "RESIZE_MAX_WR";
> > > > > +	case RDMA_DEV_BAD_PKEY_CNTR: return "BAD_PKEY_CNTR";
> > > ...
> > > > > +	case RDMA_DEV_RAW_SCATTER_FCS: return "RAW_SCATTER_FCS";
> > > > > +	case RDMA_DEV_RDMA_NETDEV_OPA_VNIC: return "RDMA_NETDEV_OPA_VNIC";
> > > > > +	default: return "UNKNOWN";
> > > > > +	}
> > > >
> > > > Could this be a table in future versions?
> > >
> > > Potentially you could define the constants using some pre-processor
> > > 'magic' that would create the table for you.
> > > Something like (but not compiled):
> > >
> > > #define RDMA_DEV_FLAGS(x) \
> > > 	x(RESIZE_MAX_WR, 0) \
> > > 	x(BAD_PKEY_CNTR, 1) \
> > > (continue for all the bits)
> > >
> > > #define RDMA_DEV_ENUM(name, bit_no) RDMA_DEV_##name = BIT(bit_no),
> > > enum {RDMA_DEV_FLAGS(RDMA_DEV_ENUM)};
> > > #undef RDMA_DEV_ENUM
> > >
> > > #define RDMA_DEV_NAMES(name, bit_no) [bit_no] = #name,
> > > static const char rdma_dev_names[] = {RDMA_DEV_FLAGS(RDMA_DEV_NAMES)};
> I missed the #undef
> > >
> >
> > David,
> >
> > How should I handle "uknown" fields without names?
>
> The function that accesses rdma_dev_names[] checks ARRAY_SIZE()
> and for a NULL pointer.

Thanks, I'll definitely try it.

>
> WRT the other comment, the spare pointers consume far less space than
> the code for your switch statement.

I don't think that space is matter for this tool.

>
> 	David
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 iproute2 1/7] rdma: Add basic infrastructure for RDMA tool
  2017-08-15 13:00 ` [PATCH v4 iproute2 1/7] rdma: Add basic infrastructure for RDMA tool Leon Romanovsky
@ 2017-08-15 23:54   ` Stephen Hemminger
  2017-08-16  5:32     ` Leon Romanovsky
  0 siblings, 1 reply; 16+ messages in thread
From: Stephen Hemminger @ 2017-08-15 23:54 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Doug Ledford, linux-rdma, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

On Tue, 15 Aug 2017 16:00:14 +0300
Leon Romanovsky <leonro@mellanox.com> wrote:

> RDMA devices are cross-functional devices from one side,
> but very tailored for the specific markets from another.
> 
> Such diversity caused to spread of RDMA related configuration
> across various tools, e.g. devlink, ip, ethtool, ib specific and
> vendor specific solutions.
> 
> This patch adds ability to fill device and port information
> by reading RDMA netlink.
> 
> Signed-off-by: Leon Romanovsky <leonro@mellanox.com>

Won't build for me.

$ make distclean

$ make

In file included from rdma.c:12:0:
rdma.h:23:23: fatal error: rdma/rdma.h: No such file or directory
 #include <rdma/rdma.h>
                       ^

I think your Makefile expects something different.
Or more Config fallout

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

* Re: [PATCH v4 iproute2 1/7] rdma: Add basic infrastructure for RDMA tool
  2017-08-15 23:54   ` Stephen Hemminger
@ 2017-08-16  5:32     ` Leon Romanovsky
  0 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2017-08-16  5:32 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Doug Ledford, linux-rdma, Dennis Dalessandro, Jason Gunthorpe,
	Jiri Pirko, Ariel Almog, Linux Netdev

[-- Attachment #1: Type: text/plain, Size: 1377 bytes --]

On Tue, Aug 15, 2017 at 04:54:16PM -0700, Stephen Hemminger wrote:
> On Tue, 15 Aug 2017 16:00:14 +0300
> Leon Romanovsky <leonro@mellanox.com> wrote:
>
> > RDMA devices are cross-functional devices from one side,
> > but very tailored for the specific markets from another.
> >
> > Such diversity caused to spread of RDMA related configuration
> > across various tools, e.g. devlink, ip, ethtool, ib specific and
> > vendor specific solutions.
> >
> > This patch adds ability to fill device and port information
> > by reading RDMA netlink.
> >
> > Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
>
> Won't build for me.
>
> $ make distclean
>
> $ make
>
> In file included from rdma.c:12:0:
> rdma.h:23:23: fatal error: rdma/rdma.h: No such file or directory
>  #include <rdma/rdma.h>
>                        ^
>
> I think your Makefile expects something different.
> Or more Config fallout

Your kernel tree should have this [1] pull request to be merged, because
I'm adding new header file to UAPI [2].

 create mode 100644 include/uapi/rdma/rdma.h

[1] http://marc.info/?l=linux-rdma&m=150278847820844&w=2
[2] http://marc.info/?l=linux-rdma&m=150278850520856&w=2

> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

end of thread, other threads:[~2017-08-16  5:32 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-15 13:00 [PATCH v4 iproute2 0/7] RDMAtool Leon Romanovsky
2017-08-15 13:00 ` [PATCH v4 iproute2 1/7] rdma: Add basic infrastructure for RDMA tool Leon Romanovsky
2017-08-15 23:54   ` Stephen Hemminger
2017-08-16  5:32     ` Leon Romanovsky
     [not found] ` <20170815130020.29509-1-leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2017-08-15 13:00   ` [PATCH v4 iproute2 2/7] rdma: Add dev object Leon Romanovsky
2017-08-15 16:12     ` Stephen Hemminger
2017-08-15 16:23       ` David Laight
     [not found]         ` <063D6719AE5E284EB5DD2968C1650D6DD005604E-VkEWCZq2GCInGFn1LkZF6NBPR1lH4CV8@public.gmane.org>
2017-08-15 16:47           ` Leon Romanovsky
2017-08-15 17:00             ` David Laight
     [not found]               ` <063D6719AE5E284EB5DD2968C1650D6DD005613D-VkEWCZq2GCInGFn1LkZF6NBPR1lH4CV8@public.gmane.org>
2017-08-15 17:46                 ` Leon Romanovsky
2017-08-15 16:43       ` Leon Romanovsky
2017-08-15 13:00   ` [PATCH v4 iproute2 4/7] rdma: Add initial manual for the tool Leon Romanovsky
2017-08-15 13:00 ` [PATCH v4 iproute2 3/7] rdma: Add link object Leon Romanovsky
2017-08-15 13:00 ` [PATCH v4 iproute2 5/7] rdma: Add json and pretty outputs Leon Romanovsky
2017-08-15 13:00 ` [PATCH v4 iproute2 6/7] rdma: Implement json output for dev object Leon Romanovsky
2017-08-15 13:00 ` [PATCH v4 iproute2 7/7] rdma: Add json output to link object Leon Romanovsky

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.