]> git.proxmox.com Git - mirror_iproute2.git/blame - rdma/dev.c
Merge branch 'master' into next
[mirror_iproute2.git] / rdma / dev.c
CommitLineData
835d8321 1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
40df8263
LR
2/*
3 * dev.c RDMA tool
40df8263
LR
4 * Authors: Leon Romanovsky <leonro@mellanox.com>
5 */
6
d17a0248 7#include <fcntl.h>
40df8263
LR
8#include "rdma.h"
9
10static int dev_help(struct rd *rd)
11{
12 pr_out("Usage: %s dev show [DEV]\n", rd->filename);
4443c9c6 13 pr_out(" %s dev set [DEV] name DEVNAME\n", rd->filename);
d17a0248 14 pr_out(" %s dev set [DEV] netns NSNAME\n", rd->filename);
8a56ef32 15 pr_out(" %s dev set [DEV] adaptive-moderation [on|off]\n", rd->filename);
40df8263
LR
16 return 0;
17}
18
19static const char *dev_caps_to_str(uint32_t idx)
20{
378dd31b 21#define RDMA_DEV_FLAGS_LOW(x) \
40df8263
LR
22 x(RESIZE_MAX_WR, 0) \
23 x(BAD_PKEY_CNTR, 1) \
24 x(BAD_QKEY_CNTR, 2) \
25 x(RAW_MULTI, 3) \
26 x(AUTO_PATH_MIG, 4) \
27 x(CHANGE_PHY_PORT, 5) \
28 x(UD_AV_PORT_ENFORCE_PORT_ENFORCE, 6) \
29 x(CURR_QP_STATE_MOD, 7) \
30 x(SHUTDOWN_PORT, 8) \
31 x(INIT_TYPE, 9) \
32 x(PORT_ACTIVE_EVENT, 10) \
33 x(SYS_IMAGE_GUID, 11) \
34 x(RC_RNR_NAK_GEN, 12) \
35 x(SRQ_RESIZE, 13) \
36 x(N_NOTIFY_CQ, 14) \
37 x(LOCAL_DMA_LKEY, 15) \
38 x(MEM_WINDOW, 17) \
39 x(UD_IP_CSUM, 18) \
40 x(UD_TSO, 19) \
41 x(XRC, 20) \
42 x(MEM_MGT_EXTENSIONS, 21) \
43 x(BLOCK_MULTICAST_LOOPBACK, 22) \
44 x(MEM_WINDOW_TYPE_2A, 23) \
45 x(MEM_WINDOW_TYPE_2B, 24) \
46 x(RC_IP_CSUM, 25) \
47 x(RAW_IP_CSUM, 26) \
48 x(CROSS_CHANNEL, 27) \
49 x(MANAGED_FLOW_STEERING, 29) \
50 x(SIGNATURE_HANDOVER, 30) \
378dd31b 51 x(ON_DEMAND_PAGING, 31)
40df8263 52
378dd31b
LR
53#define RDMA_DEV_FLAGS_HIGH(x) \
54 x(SG_GAPS_REG, 0) \
55 x(VIRTUAL_FUNCTION, 1) \
56 x(RAW_SCATTER_FCS, 2) \
57 x(RDMA_NETDEV_OPA_VNIC, 3) \
58 x(PCI_WRITE_END_PADDING, 4)
40df8263 59
378dd31b
LR
60 /*
61 * Separation below is needed to allow compilation of rdmatool
62 * on 32bits systems. On such systems, C-enum is limited to be
63 * int and can't hold more than 32 bits.
64 */
65 enum { RDMA_DEV_FLAGS_LOW(RDMA_BITMAP_ENUM) };
66 enum { RDMA_DEV_FLAGS_HIGH(RDMA_BITMAP_ENUM) };
67
68 static const char * const
69 rdma_dev_names_low[] = { RDMA_DEV_FLAGS_LOW(RDMA_BITMAP_NAMES) };
40df8263 70 static const char * const
378dd31b
LR
71 rdma_dev_names_high[] = { RDMA_DEV_FLAGS_HIGH(RDMA_BITMAP_NAMES) };
72 uint32_t high_idx;
73 #undef RDMA_DEV_FLAGS_LOW
74 #undef RDMA_DEV_FLAGS_HIGH
75
76 if (idx < ARRAY_SIZE(rdma_dev_names_low) && rdma_dev_names_low[idx])
77 return rdma_dev_names_low[idx];
78
79 high_idx = idx - ARRAY_SIZE(rdma_dev_names_low);
80 if (high_idx < ARRAY_SIZE(rdma_dev_names_high) &&
81 rdma_dev_names_high[high_idx])
82 return rdma_dev_names_high[high_idx];
40df8263 83
40df8263
LR
84 return "UNKNOWN";
85}
86
ef353e2e 87static void dev_print_caps(struct rd *rd, struct nlattr **tb)
40df8263
LR
88{
89 uint64_t caps;
90 uint32_t idx;
91
92 if (!tb[RDMA_NLDEV_ATTR_CAP_FLAGS])
93 return;
94
95 caps = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_CAP_FLAGS]);
96
ef353e2e
LR
97 if (rd->json_output) {
98 jsonw_name(rd->jw, "caps");
99 jsonw_start_array(rd->jw);
100 } else {
101 pr_out("\n caps: <");
102 }
40df8263
LR
103 for (idx = 0; caps; idx++) {
104 if (caps & 0x1) {
ef353e2e
LR
105 if (rd->json_output) {
106 jsonw_string(rd->jw, dev_caps_to_str(idx));
107 } else {
108 pr_out("%s", dev_caps_to_str(idx));
109 if (caps >> 0x1)
110 pr_out(", ");
111 }
40df8263
LR
112 }
113 caps >>= 0x1;
114 }
115
ef353e2e
LR
116 if (rd->json_output)
117 jsonw_end_array(rd->jw);
118 else
119 pr_out(">");
40df8263
LR
120}
121
ef353e2e 122static void dev_print_fw(struct rd *rd, struct nlattr **tb)
40df8263 123{
ef353e2e 124 const char *str;
40df8263
LR
125 if (!tb[RDMA_NLDEV_ATTR_FW_VERSION])
126 return;
127
ef353e2e
LR
128 str = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_FW_VERSION]);
129 if (rd->json_output)
130 jsonw_string_field(rd->jw, "fw", str);
131 else
132 pr_out("fw %s ", str);
40df8263
LR
133}
134
ef353e2e 135static void dev_print_node_guid(struct rd *rd, struct nlattr **tb)
40df8263
LR
136{
137 uint64_t node_guid;
ef353e2e
LR
138 uint16_t vp[4];
139 char str[32];
40df8263
LR
140
141 if (!tb[RDMA_NLDEV_ATTR_NODE_GUID])
142 return;
143
144 node_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_NODE_GUID]);
ef353e2e
LR
145 memcpy(vp, &node_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, "node_guid", str);
149 else
150 pr_out("node_guid %s ", str);
40df8263
LR
151}
152
ef353e2e 153static void dev_print_sys_image_guid(struct rd *rd, struct nlattr **tb)
40df8263
LR
154{
155 uint64_t sys_image_guid;
ef353e2e
LR
156 uint16_t vp[4];
157 char str[32];
40df8263
LR
158
159 if (!tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID])
160 return;
161
162 sys_image_guid = mnl_attr_get_u64(tb[RDMA_NLDEV_ATTR_SYS_IMAGE_GUID]);
ef353e2e
LR
163 memcpy(vp, &sys_image_guid, sizeof(uint64_t));
164 snprintf(str, 32, "%04x:%04x:%04x:%04x", vp[3], vp[2], vp[1], vp[0]);
165 if (rd->json_output)
166 jsonw_string_field(rd->jw, "sys_image_guid", str);
167 else
168 pr_out("sys_image_guid %s ", str);
40df8263
LR
169}
170
8a56ef32
YF
171static void dev_print_dim_setting(struct rd *rd, struct nlattr **tb)
172{
173 uint8_t dim_setting;
174
175 if (!tb[RDMA_NLDEV_ATTR_DEV_DIM])
176 return;
177
178 dim_setting = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_DIM]);
179 if (dim_setting > 1)
180 return;
181
182 print_on_off(rd, "adaptive-moderation", dim_setting);
183
184}
185
40df8263
LR
186static const char *node_type_to_str(uint8_t node_type)
187{
188 static const char * const node_type_str[] = { "unknown", "ca",
189 "switch", "router",
190 "rnic", "usnic",
7087f7c0
GP
191 "usnic_udp",
192 "unspecified" };
40df8263
LR
193 if (node_type < ARRAY_SIZE(node_type_str))
194 return node_type_str[node_type];
195 return "unknown";
196}
197
ef353e2e 198static void dev_print_node_type(struct rd *rd, struct nlattr **tb)
40df8263 199{
ef353e2e 200 const char *node_str;
40df8263
LR
201 uint8_t node_type;
202
203 if (!tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE])
204 return;
205
206 node_type = mnl_attr_get_u8(tb[RDMA_NLDEV_ATTR_DEV_NODE_TYPE]);
ef353e2e
LR
207 node_str = node_type_to_str(node_type);
208 if (rd->json_output)
209 jsonw_string_field(rd->jw, "node_type", node_str);
210 else
211 pr_out("node_type %s ", node_str);
40df8263
LR
212}
213
214static int dev_parse_cb(const struct nlmsghdr *nlh, void *data)
215{
216 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
217 struct rd *rd = data;
ef353e2e
LR
218 const char *name;
219 uint32_t idx;
40df8263
LR
220
221 mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
222 if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME])
223 return MNL_CB_ERROR;
224
ef353e2e
LR
225 idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
226 name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
227 if (rd->json_output) {
228 jsonw_uint_field(rd->jw, "ifindex", idx);
229 jsonw_string_field(rd->jw, "ifname", name);
230 } else {
231 pr_out("%u: %s: ", idx, name);
232 }
233
234 dev_print_node_type(rd, tb);
235 dev_print_fw(rd, tb);
236 dev_print_node_guid(rd, tb);
237 dev_print_sys_image_guid(rd, tb);
8a56ef32
YF
238 if (rd->show_details) {
239 dev_print_dim_setting(rd, tb);
ef353e2e 240 dev_print_caps(rd, tb);
8a56ef32 241 }
40df8263 242
ef353e2e
LR
243 if (!rd->json_output)
244 pr_out("\n");
40df8263
LR
245 return MNL_CB_OK;
246}
247
248static int dev_no_args(struct rd *rd)
249{
250 uint32_t seq;
251 int ret;
252
253 rd_prepare_msg(rd, RDMA_NLDEV_CMD_GET,
254 &seq, (NLM_F_REQUEST | NLM_F_ACK));
255 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
256 ret = rd_send_msg(rd);
257 if (ret)
258 return ret;
259
ef353e2e
LR
260 if (rd->json_output)
261 jsonw_start_object(rd->jw);
262 ret = rd_recv_msg(rd, dev_parse_cb, rd, seq);
263 if (rd->json_output)
264 jsonw_end_object(rd->jw);
265 return ret;
40df8263
LR
266}
267
268static int dev_one_show(struct rd *rd)
269{
270 const struct rd_cmd cmds[] = {
271 { NULL, dev_no_args},
272 { 0 }
273 };
274
275 return rd_exec_cmd(rd, cmds, "parameter");
276}
277
4443c9c6
LR
278static int dev_set_name(struct rd *rd)
279{
280 uint32_t seq;
281
282 if (rd_no_arg(rd)) {
283 pr_err("Please provide device new name.\n");
284 return -EINVAL;
285 }
286
287 rd_prepare_msg(rd, RDMA_NLDEV_CMD_SET,
288 &seq, (NLM_F_REQUEST | NLM_F_ACK));
289 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
290 mnl_attr_put_strz(rd->nlh, RDMA_NLDEV_ATTR_DEV_NAME, rd_argv(rd));
291
8f5cfd23 292 return rd_sendrecv_msg(rd, seq);
4443c9c6
LR
293}
294
d17a0248
PP
295static int dev_set_netns(struct rd *rd)
296{
297 char *netns_path;
298 uint32_t seq;
299 int netns;
300 int ret;
301
302 if (rd_no_arg(rd)) {
303 pr_err("Please provide device name.\n");
304 return -EINVAL;
305 }
306
307 if (asprintf(&netns_path, "%s/%s", NETNS_RUN_DIR, rd_argv(rd)) < 0)
308 return -ENOMEM;
309
310 netns = open(netns_path, O_RDONLY | O_CLOEXEC);
311 if (netns < 0) {
312 fprintf(stderr, "Cannot open network namespace \"%s\": %s\n",
313 rd_argv(rd), strerror(errno));
314 ret = -EINVAL;
315 goto done;
316 }
317
318 rd_prepare_msg(rd, RDMA_NLDEV_CMD_SET,
319 &seq, (NLM_F_REQUEST | NLM_F_ACK));
320 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
321 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_NET_NS_FD, netns);
322 ret = rd_sendrecv_msg(rd, seq);
323 close(netns);
324done:
325 free(netns_path);
326 return ret;
327}
328
8a56ef32
YF
329static int dev_set_dim_sendmsg(struct rd *rd, uint8_t dim_setting)
330{
331 uint32_t seq;
332
333 rd_prepare_msg(rd, RDMA_NLDEV_CMD_SET, &seq,
334 (NLM_F_REQUEST | NLM_F_ACK));
335 mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
336 mnl_attr_put_u8(rd->nlh, RDMA_NLDEV_ATTR_DEV_DIM, dim_setting);
337
338 return rd_sendrecv_msg(rd, seq);
339}
340
341static int dev_set_dim_off(struct rd *rd)
342{
343 return dev_set_dim_sendmsg(rd, 0);
344}
345
346static int dev_set_dim_on(struct rd *rd)
347{
348 return dev_set_dim_sendmsg(rd, 1);
349}
350
351static int dev_set_dim(struct rd *rd)
352{
353 const struct rd_cmd cmds[] = {
354 { NULL, dev_help},
355 { "on", dev_set_dim_on},
356 { "off", dev_set_dim_off},
357 { 0 }
358 };
359
360 return rd_exec_cmd(rd, cmds, "parameter");
361}
362
4443c9c6
LR
363static int dev_one_set(struct rd *rd)
364{
365 const struct rd_cmd cmds[] = {
366 { NULL, dev_help},
367 { "name", dev_set_name},
d17a0248 368 { "netns", dev_set_netns},
8a56ef32 369 { "adaptive-moderation", dev_set_dim},
4443c9c6
LR
370 { 0 }
371 };
372
373 return rd_exec_cmd(rd, cmds, "parameter");
374}
375
40df8263
LR
376static int dev_show(struct rd *rd)
377{
8b92a2c9 378 return rd_exec_dev(rd, dev_one_show);
40df8263
LR
379}
380
4443c9c6
LR
381static int dev_set(struct rd *rd)
382{
383 return rd_exec_require_dev(rd, dev_one_set);
384}
385
40df8263
LR
386int cmd_dev(struct rd *rd)
387{
388 const struct rd_cmd cmds[] = {
389 { NULL, dev_show },
390 { "show", dev_show },
391 { "list", dev_show },
4443c9c6 392 { "set", dev_set },
40df8263
LR
393 { "help", dev_help },
394 { 0 }
395 };
396
397 return rd_exec_cmd(rd, cmds, "dev command");
398}