• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * dev.c	RDMA tool
3  *
4  *              This program is free software; you can redistribute it and/or
5  *              modify it under the terms of the GNU General Public License
6  *              as published by the Free Software Foundation; either version
7  *              2 of the License, or (at your option) any later version.
8  *
9  * Authors:     Leon Romanovsky <leonro@mellanox.com>
10  */
11 
12 #include "rdma.h"
13 
dev_help(struct rd * rd)14 static int dev_help(struct rd *rd)
15 {
16 	pr_out("Usage: %s dev show [DEV]\n", rd->filename);
17 	return 0;
18 }
19 
dev_caps_to_str(uint32_t idx)20 static const char *dev_caps_to_str(uint32_t idx)
21 {
22 #define RDMA_DEV_FLAGS(x) \
23 	x(RESIZE_MAX_WR, 0) \
24 	x(BAD_PKEY_CNTR, 1) \
25 	x(BAD_QKEY_CNTR, 2) \
26 	x(RAW_MULTI, 3) \
27 	x(AUTO_PATH_MIG, 4) \
28 	x(CHANGE_PHY_PORT, 5) \
29 	x(UD_AV_PORT_ENFORCE_PORT_ENFORCE, 6) \
30 	x(CURR_QP_STATE_MOD, 7) \
31 	x(SHUTDOWN_PORT, 8) \
32 	x(INIT_TYPE, 9) \
33 	x(PORT_ACTIVE_EVENT, 10) \
34 	x(SYS_IMAGE_GUID, 11) \
35 	x(RC_RNR_NAK_GEN, 12) \
36 	x(SRQ_RESIZE, 13) \
37 	x(N_NOTIFY_CQ, 14) \
38 	x(LOCAL_DMA_LKEY, 15) \
39 	x(MEM_WINDOW, 17) \
40 	x(UD_IP_CSUM, 18) \
41 	x(UD_TSO, 19) \
42 	x(XRC, 20) \
43 	x(MEM_MGT_EXTENSIONS, 21) \
44 	x(BLOCK_MULTICAST_LOOPBACK, 22) \
45 	x(MEM_WINDOW_TYPE_2A, 23) \
46 	x(MEM_WINDOW_TYPE_2B, 24) \
47 	x(RC_IP_CSUM, 25) \
48 	x(RAW_IP_CSUM, 26) \
49 	x(CROSS_CHANNEL, 27) \
50 	x(MANAGED_FLOW_STEERING, 29) \
51 	x(SIGNATURE_HANDOVER, 30) \
52 	x(ON_DEMAND_PAGING, 31) \
53 	x(SG_GAPS_REG, 32) \
54 	x(VIRTUAL_FUNCTION, 33) \
55 	x(RAW_SCATTER_FCS, 34) \
56 	x(RDMA_NETDEV_OPA_VNIC, 35)
57 
58 	enum { RDMA_DEV_FLAGS(RDMA_BITMAP_ENUM) };
59 
60 	static const char * const
61 		rdma_dev_names[] = { RDMA_DEV_FLAGS(RDMA_BITMAP_NAMES) };
62 	#undef RDMA_DEV_FLAGS
63 
64 	if (idx < ARRAY_SIZE(rdma_dev_names) && rdma_dev_names[idx])
65 		return rdma_dev_names[idx];
66 	return "UNKNOWN";
67 }
68 
dev_print_caps(struct rd * rd,struct nlattr ** tb)69 static void dev_print_caps(struct rd *rd, struct nlattr **tb)
70 {
71 	uint64_t caps;
72 	uint32_t idx;
73 
74 	if (!tb[RDMA_NLDEV_ATTR_CAP_FLAGS])
75 		return;
76 
77 	caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
78 
79 	if (rd->json_output) {
80 		jsonw_name(rd->jw, "caps");
81 		jsonw_start_array(rd->jw);
82 	} else {
83 		pr_out("\n    caps: <");
84 	}
85 	for (idx = 0; caps; idx++) {
86 		if (caps & 0x1) {
87 			if (rd->json_output) {
88 				jsonw_string(rd->jw, dev_caps_to_str(idx));
89 			} else {
90 				pr_out("%s", dev_caps_to_str(idx));
91 				if (caps >> 0x1)
92 					pr_out(", ");
93 			}
94 		}
95 		caps >>= 0x1;
96 	}
97 
98 	if (rd->json_output)
99 		jsonw_end_array(rd->jw);
100 	else
101 		pr_out(">");
102 }
103 
dev_print_fw(struct rd * rd,struct nlattr ** tb)104 static void dev_print_fw(struct rd *rd, struct nlattr **tb)
105 {
106 	const char *str;
107 	if (!tb[RDMA_NLDEV_ATTR_FW_VERSION])
108 		return;
109 
110 	str = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION]);
111 	if (rd->json_output)
112 		jsonw_string_field(rd->jw, "fw", str);
113 	else
114 		pr_out("fw %s ", str);
115 }
116 
dev_print_node_guid(struct rd * rd,struct nlattr ** tb)117 static void dev_print_node_guid(struct rd *rd, struct nlattr **tb)
118 {
119 	uint64_t node_guid;
120 	uint16_t vp[4];
121 	char str[32];
122 
123 	if (!tb[RDMA_NLDEV_ATTR_NODE_GUID])
124 		return;
125 
126 	node_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_NODE_GUID]);
127 	memcpy(vp, &node_guid, sizeof(uint64_t));
128 	snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
129 	if (rd->json_output)
130 		jsonw_string_field(rd->jw, "node_guid", str);
131 	else
132 		pr_out("node_guid %s ", str);
133 }
134 
dev_print_sys_image_guid(struct rd * rd,struct nlattr ** tb)135 static void dev_print_sys_image_guid(struct rd *rd, struct nlattr **tb)
136 {
137 	uint64_t sys_image_guid;
138 	uint16_t vp[4];
139 	char str[32];
140 
141 	if (!tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID])
142 		return;
143 
144 	sys_image_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID]);
145 	memcpy(vp, &sys_image_guid, sizeof(uint64_t));
146 	snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
147 	if (rd->json_output)
148 		jsonw_string_field(rd->jw, "sys_image_guid", str);
149 	else
150 		pr_out("sys_image_guid %s ", str);
151 }
152 
node_type_to_str(uint8_t node_type)153 static const char *node_type_to_str(uint8_t node_type)
154 {
155 	static const char * const node_type_str[] = { "unknown", "ca",
156 						      "switch", "router",
157 						      "rnic", "usnic",
158 						      "usnic_dp" };
159 	if (node_type < ARRAY_SIZE(node_type_str))
160 		return node_type_str[node_type];
161 	return "unknown";
162 }
163 
dev_print_node_type(struct rd * rd,struct nlattr ** tb)164 static void dev_print_node_type(struct rd *rd, struct nlattr **tb)
165 {
166 	const char *node_str;
167 	uint8_t node_type;
168 
169 	if (!tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE])
170 		return;
171 
172 	node_type = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE]);
173 	node_str = node_type_to_str(node_type);
174 	if (rd->json_output)
175 		jsonw_string_field(rd->jw, "node_type", node_str);
176 	else
177 		pr_out("node_type %s ", node_str);
178 }
179 
dev_parse_cb(const struct nlmsghdr * nlh,void * data)180 static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
181 {
182 	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
183 	struct rd *rd = data;
184 	const char *name;
185 	uint32_t idx;
186 
187 	mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
188 	if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
189 		return MNL_CB_ERROR;
190 
191 	idx =  mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
192 	name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
193 	if (rd->json_output) {
194 		jsonw_uint_field(rd->jw, "ifindex", idx);
195 		jsonw_string_field(rd->jw, "ifname", name);
196 	} else {
197 		pr_out("%u: %s: ", idx, name);
198 	}
199 
200 	dev_print_node_type(rd, tb);
201 	dev_print_fw(rd, tb);
202 	dev_print_node_guid(rd, tb);
203 	dev_print_sys_image_guid(rd, tb);
204 	if (rd->show_details)
205 		dev_print_caps(rd, tb);
206 
207 	if (!rd->json_output)
208 		pr_out("\n");
209 	return MNL_CB_OK;
210 }
211 
dev_no_args(struct rd * rd)212 static int dev_no_args(struct rd *rd)
213 {
214 	uint32_t seq;
215 	int ret;
216 
217 	rd_prepare_msg(rd, RDMA_NLDEV_CMD_GET,
218 		       &seq, (NLM_F_REQUEST | NLM_F_ACK));
219 	mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
220 	ret = rd_send_msg(rd);
221 	if (ret)
222 		return ret;
223 
224 	if (rd->json_output)
225 		jsonw_start_object(rd->jw);
226 	ret = rd_recv_msg(rd, dev_parse_cb, rd, seq);
227 	if (rd->json_output)
228 		jsonw_end_object(rd->jw);
229 	return ret;
230 }
231 
dev_one_show(struct rd * rd)232 static int dev_one_show(struct rd *rd)
233 {
234 	const struct rd_cmd cmds[] = {
235 		{ NULL,		dev_no_args},
236 		{ 0 }
237 	};
238 
239 	return rd_exec_cmd(rd, cmds, "parameter");
240 }
241 
dev_show(struct rd * rd)242 static int dev_show(struct rd *rd)
243 {
244 	struct dev_map *dev_map;
245 	int ret = 0;
246 
247 	if (rd->json_output)
248 		jsonw_start_array(rd->jw);
249 	if (rd_no_arg(rd)) {
250 		list_for_each_entry(dev_map, &rd->dev_map_list, list) {
251 			rd->dev_idx = dev_map->idx;
252 			ret = dev_one_show(rd);
253 			if (ret)
254 				goto out;
255 		}
256 	} else {
257 		dev_map = dev_map_lookup(rd, false);
258 		if (!dev_map) {
259 			pr_err("Wrong device name\n");
260 			ret = -ENOENT;
261 			goto out;
262 		}
263 		rd_arg_inc(rd);
264 		rd->dev_idx = dev_map->idx;
265 		ret = dev_one_show(rd);
266 	}
267 out:
268 	if (rd->json_output)
269 		jsonw_end_array(rd->jw);
270 	return ret;
271 }
272 
cmd_dev(struct rd * rd)273 int cmd_dev(struct rd *rd)
274 {
275 	const struct rd_cmd cmds[] = {
276 		{ NULL,		dev_show },
277 		{ "show",	dev_show },
278 		{ "list",	dev_show },
279 		{ "help",	dev_help },
280 		{ 0 }
281 	};
282 
283 	return rd_exec_cmd(rd, cmds, "dev command");
284 }
285