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